/// <summary> /// Price of a zcb at t > 0 with maturity TT > t /// as a function of the rate R, of the factor u at t /// and of the current zr curve (ZR) /// using the Hull & White two-factor model /// <para> /// dr = (theta(t) + u - a * r) * dt + sigma1 * dz1 /// du = -b * du * dt + sigma2 * dz2 /// with dz1 * dz2 = rho * dt /// </para> /// (see Hull-White (1994) Journal of Derivatives). /// </summary> /// <param name="context">The underlying project context.</param> /// <param name="cache">Data structure where pre-calculated values are stored.</param> /// <param name="hw2">An HW2Context object to use for the evaluation.</param> /// <param name="R">Rate of return from time t to t+dt.</param> /// <param name="u">Factor u at t.</param> /// <param name="PT">Current price of a zcb maturing at TT.</param> /// <param name="P_t">Current price of a zcb maturing at t.</param> /// <param name="Pdt">Current price of a zcb maturing at t + dt.</param> /// <param name="TT">The bond maturity.</param> /// <param name="t">The initial date of the zcb.</param> /// <param name="dt">The length of time steps.</param> /// <returns>The value of the bond using the HW2 model.</returns> private static double BondHW2(Project context, SPCache cache, HW2Context hw2, double R, double u, double PT, double P_t, double Pdt, double TT, double t, double dt) { double a_a_b = +hw2.alpha1 * (hw2.alpha1 - hw2.alpha2); double b_a_b = +hw2.alpha2 * (hw2.alpha1 - hw2.alpha2); double ab = hw2.alpha1 * hw2.alpha2; double TT_t = TT - t; int t_idx = context.DiscreteTime(t); int TT_idx = context.DiscreteTime(TT); double aHat = 0; double bHat = 0; double cHat = 0; #if _USE_CACHE_ #if !_SWAPTIONW_ lock (cache) #endif { if (!cache.IsCached_Eta[t_idx]) { cache.Cached_Eta[t_idx] = Eta(t, t + dt, a, b, sigma1, sigma2, rho); cache.IsCached_Eta[t_idx] = true; } } int TT_idx_rel = TT_idx - t_idx; if (cache.cache.J > TT_idx_rel) { HWCache2 cached_element = null; #if !_SWAPTIONW_ lock (cache.cache) #endif { if (!cache.cache.IsCached(t_idx, TT_idx_rel)) { cached_element = cache.cache.InsertToCache(t_idx, TT_idx_rel); cached_element.Eta2 = Eta(t, TT, a, b, sigma1, sigma2, rho); cached_element.Bhat = BHat(t, TT, dt, a); cached_element.Chat = CHat(t, TT, dt, a, b, cached_element.Bhat); double BtT = (1 - Math.Exp(-a * (TT_t))) / a; double Btdt = (1 - Math.Exp(-a * (dt))) / a; cached_element.Ahat = PT / P_t * Math.Exp(-BtT / Btdt * Math.Log(Pdt / P_t) - cached_element.Eta2 + BtT / Btdt * cache.Cached_Eta[t_idx]); } } cached_element = cache.cache.Get(t_idx, TT_idx_rel); bHat = cached_element.Bhat; cHat = cached_element.Chat; aHat = cached_element.Ahat; } else { double BtT = (1 - Math.Exp(-a * (TT_t))) / a; double Btdt = (1 - Math.Exp(-a * (dt))) / a; aHat = PT / P_t * Math.Exp(-BtT / Btdt * Math.Log(Pdt / P_t) - Eta(t, TT, a, b, sigma1, sigma2, rho) + BtT / Btdt * cache.Cached_Eta[t_idx]); bHat = BHat(t, TT, dt, a); cHat = CHat(t, TT, dt, a, b, bHat); } #else double BtT = (1 - Math.Exp(-hw2.alpha1 * (TT_t))) / hw2.alpha1; double Btdt = (1 - Math.Exp(-hw2.alpha1 * (dt))) / hw2.alpha1; double l_Pdt_Pt = Math.Log(Pdt / P_t); double eta_TT = hw2.Eta(t, TT); double eta_dt = hw2.Eta(t, t + dt); double arg = -BtT / Btdt * (l_Pdt_Pt - eta_dt) - eta_TT; if (Engine.Log) { if (SolverContext.SimulationRealization == 0) { Log.Write(string.Format("arg {0} eta_TT {1} eta_dt {2}", arg, eta_TT, eta_dt)); } } aHat = (PT / P_t) * Math.Exp(arg); bHat = hw2.BHat(t, TT, dt); cHat = hw2.CHat(t, TT, dt, bHat); #endif double bond = aHat * Math.Exp(-bHat * R - cHat * u); #if _CHECK_OWERFLOWS_ if (Double.IsInfinity(bond)) { bond = Double.MaxValue / 1000000; } #endif return(bond); }
/// <summary> /// Price of a zcb at t > 0 with maturity TT > t /// as a function of the rate R, of the factor u at t /// and of the current zr curve (ZR) /// using the Hull & White two-factor model /// <para> /// dr = (theta(t) + u - a * r) * dt + sigma1 * dz1 /// du = -b * du * dt + sigma2 * dz2 /// with dz1 * dz2 = rho * dt /// </para> /// (see Hull-White (1994) Journal of Derivatives). /// </summary> /// <param name="context">The underlying project context.</param> /// <param name="cache">Data structure where pre-calculated values are stored.</param> /// <param name="hw2">An HW2Context object to use for the evaluation.</param> /// <param name="R">Rate of return from time t to t+dt.</param> /// <param name="u">Factor u at t.</param> /// <param name="PT">Current price of a zcb maturing at TT.</param> /// <param name="P_t">Current price of a zcb maturing at t.</param> /// <param name="Pdt">Current price of a zcb maturing at t + dt.</param> /// <param name="TT">The bond maturity.</param> /// <param name="t">The initial date of the zcb.</param> /// <param name="dt">The length of time steps.</param> /// <returns>The value of the bond using the HW2 model.</returns> private static double BondHW2(Project context, SPCache cache, HW2Context hw2, double R, double u, double PT, double P_t, double Pdt, double TT, double t, double dt) { double a_a_b = +hw2.alpha1 * (hw2.alpha1 - hw2.alpha2); double b_a_b = +hw2.alpha2 * (hw2.alpha1 - hw2.alpha2); double ab = hw2.alpha1 * hw2.alpha2; double TT_t = TT - t; int t_idx = context.DiscreteTime(t); int TT_idx = context.DiscreteTime(TT); double aHat = 0; double bHat = 0; double cHat = 0; #if _USE_CACHE_ #if !_SWAPTIONW_ lock (cache) #endif { if (!cache.IsCached_Eta[t_idx]) { cache.Cached_Eta[t_idx] = Eta(t, t + dt, a, b, sigma1, sigma2, rho); cache.IsCached_Eta[t_idx] = true; } } int TT_idx_rel= TT_idx-t_idx; if(cache.cache.J>TT_idx_rel) { HWCache2 cached_element = null; #if !_SWAPTIONW_ lock (cache.cache) #endif { if (!cache.cache.IsCached(t_idx, TT_idx_rel)) { cached_element = cache.cache.InsertToCache(t_idx, TT_idx_rel); cached_element.Eta2 = Eta(t, TT, a, b, sigma1, sigma2, rho); cached_element.Bhat = BHat(t, TT, dt, a); cached_element.Chat = CHat(t, TT, dt, a, b, cached_element.Bhat); double BtT = (1 - Math.Exp(-a * (TT_t))) / a; double Btdt = (1 - Math.Exp(-a * (dt))) / a; cached_element.Ahat = PT / P_t * Math.Exp(-BtT / Btdt * Math.Log(Pdt / P_t) - cached_element.Eta2 + BtT / Btdt * cache.Cached_Eta[t_idx]); } } cached_element=cache.cache.Get(t_idx,TT_idx_rel); bHat=cached_element.Bhat; cHat=cached_element.Chat; aHat=cached_element.Ahat; } else { double BtT = (1 - Math.Exp(-a*(TT_t)))/a; double Btdt = (1 - Math.Exp(-a*(dt)))/a; aHat = PT/P_t *Math.Exp( -BtT/Btdt * Math.Log( Pdt/P_t ) - Eta(t,TT,a,b,sigma1,sigma2,rho) + BtT/Btdt * cache.Cached_Eta[t_idx]); bHat=BHat(t,TT,dt,a); cHat=CHat(t,TT,dt,a,b,bHat); } #else double BtT = (1 - Math.Exp(-hw2.alpha1 * (TT_t))) / hw2.alpha1; double Btdt = (1 - Math.Exp(-hw2.alpha1 * (dt))) / hw2.alpha1; double l_Pdt_Pt = Math.Log(Pdt / P_t); double eta_TT = hw2.Eta(t, TT); double eta_dt = hw2.Eta(t, t + dt); double arg = -BtT / Btdt * (l_Pdt_Pt - eta_dt) - eta_TT; if (Engine.Log) if (SolverContext.SimulationRealization == 0) Log.Write(string.Format("arg {0} eta_TT {1} eta_dt {2}", arg, eta_TT, eta_dt)); aHat = (PT / P_t) * Math.Exp(arg); bHat = hw2.BHat(t, TT, dt); cHat = hw2.CHat(t, TT, dt, bHat); #endif double bond = aHat * Math.Exp(-bHat * R - cHat * u); #if _CHECK_OWERFLOWS_ if(Double.IsInfinity(bond)) bond= Double.MaxValue/1000000; #endif return bond; }