@@ -78,8 +78,6 @@ class TargetRedemptionForward {
7878 while (t < end_date_years_ && !trigger_reached) {
7979 const double z = absl::Gaussian<double >(bitgen_, 0 , 1 );
8080 const double stoch_term = sigma * std::sqrt (dt) * z;
81- // double r_d = domestic_rates.forwardRate(t, t + dt);
82- // double r_f = foreign_rates.forwardRate(t, t + dt);
8381 const double drift_term = (r_d - r_f - 0.5 * sigma * sigma) * dt;
8482
8583 t += dt;
@@ -152,6 +150,50 @@ class TargetRedemptionForward {
152150 mutable absl::BitGen bitgen_;
153151};
154152
153+ inline double findZeroNPVStrike (double notional,
154+ double target,
155+ double end_date_years,
156+ double settlement_date_frequency,
157+ FxTradeDirection direction,
158+ double spot,
159+ double sigma,
160+ const RatesCurve& foreign_rates,
161+ const RatesCurve& domestic_rates) {
162+ // TODO: compute the forward for a more intelligent starting guess.
163+ // AND ALSO then verify that the value of one is positive and the other is
164+ // negative.
165+ double k_low = spot * 0.5 ;
166+ double k_high = spot * 2 ;
167+ double k_mid = 0.5 * (k_low + k_high);
168+
169+ double tolerance_pct =
170+ 0.0001 ; // 0.01% difference for starters. Do not hard-code!
171+
172+ // TODO is there ever a need to have this be smaller than the period?
173+ double dt = settlement_date_frequency * 0.5 ;
174+
175+ // Initial method: bisection.
176+ while (std::abs (k_high / k_low - 1 ) > tolerance_pct) {
177+ TargetRedemptionForward tarf_mid (notional,
178+ target,
179+ k_mid,
180+ end_date_years,
181+ settlement_date_frequency,
182+ direction);
183+
184+ double npv_mid =
185+ tarf_mid.price (spot, sigma, dt, 4000 , foreign_rates, domestic_rates);
186+
187+ if (npv_mid > 0 ) {
188+ k_low = k_mid;
189+ } else if (npv_mid < 0 ) {
190+ k_high = k_mid;
191+ }
192+ k_mid = 0.5 * (k_low + k_high);
193+ }
194+ return k_mid;
195+ }
196+
155197} // namespace smileexplorer
156198
157199#endif // SMILEEXPLORER_DERIVATIVES_TARGET_REDEMPTION_FORWARD_H_
0 commit comments