public static object AmericanFutureOptionImpliedVol( [ExcelArgument(Description = "Time-to-expiry")] double T, [ExcelArgument(Description = "Strike")] double K, [ExcelArgument(Description = "Forward")] double F, [ExcelArgument(Description = "Discounting rate")] double R, [ExcelArgument(Description = "Option Premium")] double PV, [ExcelArgument(Description = "Call or Put")] string CP, [ExcelArgument(Description = "Pricing method (Defult Trinomial)")] string Method) { return(ExcelHelper.Execute(_logger, () => { if (!Enum.TryParse(CP, out OptionType optType)) { return $"Could not parse call or put flag - {CP}"; } if (!Enum.TryParse(Method, out AmericanPricingType method)) { return $"Could not parse pricing type - {Method}"; } if (method == AmericanPricingType.Binomial) { return BinomialTree.AmericanFuturesOptionImpliedVol(F, K, R, T, PV, optType); } else { return TrinomialTree.AmericanFuturesOptionImpliedVol(F, K, R, T, PV, optType); } })); }
public override Lattice tree( TimeGrid grid) { TermStructureFittingParameter phi= new TermStructureFittingParameter(termStructure()); ShortRateDynamics numericDynamics= new Dynamics(phi, a(), sigma()); TrinomialTree trinomial= new TrinomialTree(numericDynamics.process(), grid); ShortRateTree numericTree = new ShortRateTree(trinomial, numericDynamics, grid); TermStructureFittingParameter.NumericalImpl impl = (TermStructureFittingParameter.NumericalImpl)phi.implementation(); impl.reset(); double value = 1.0; double vMin = -50.0; double vMax = 50.0; for (int i=0; i<(grid.size() - 1); i++) { double discountBond = termStructure().link.discount(grid[i+1]); double xMin = trinomial.underlying(i, 0); double dx = trinomial.dx(i); Helper finder = new Helper(i, xMin, dx, discountBond, numericTree); Brent s1d = new Brent(); s1d.setMaxEvaluations(1000); value = s1d.solve(finder, 1e-7, value, vMin, vMax); impl.setvalue(grid[i], value); // vMin = value - 10.0; // vMax = value + 10.0; } return numericTree; }
public override Lattice tree(TimeGrid grid) { TermStructureFittingParameter phi = new TermStructureFittingParameter(termStructure()); ShortRateDynamics numericDynamics = new Dynamics(phi, a(), sigma()); TrinomialTree trinomial = new TrinomialTree(numericDynamics.process(), grid); ShortRateTree numericTree = new ShortRateTree(trinomial, numericDynamics, grid); TermStructureFittingParameter.NumericalImpl impl = (TermStructureFittingParameter.NumericalImpl)phi.implementation(); impl.reset(); for (int i=0; i<(grid.size() - 1); i++) { double discountBond = termStructure().link.discount(grid[i+1]); Vector statePrices = numericTree.statePrices(i); int size = numericTree.size(i); double dt = numericTree.timeGrid().dt(i); double dx = trinomial.dx(i); double x = trinomial.underlying(i,0); double value = 0.0; for (int j=0; j<size; j++) { value += statePrices[j]*Math.Exp(-x*dt); x += dx; } value = Math.Log(value/discountBond)/dt; impl.setvalue(grid[i], value); } return numericTree; }
public static void Main() { // Declare and initialise the parameters TrinomialParameters myData; // Clewlow p. 55 C = 8.42534 for N = 3 myData.sigma = 0.2; myData.T = 1.0; // One year myData.r = 0.06; myData.K = 100; myData.div = 0.03; myData.type = 'C'; myData.exercise = false; myData.NumberOfSteps = 3; Console.WriteLine("How many timesteps: "); myData.NumberOfSteps = Convert.ToInt32(Console.ReadLine()); // Now define option-related calculations and price TrinomialTree myTree = new TrinomialTree(myData); Console.WriteLine("Price {0}", myTree.Price(100)); // Clewlow p. 14 check against binomial method C = 10.1457 myData.sigma = 0.2; myData.T = 1.0; // One year myData.r = 0.06; myData.K = 100; myData.div = 0.0; myData.type = 'C'; myData.exercise = false; //myData.NumberOfSteps = 3; TrinomialTree myTree2 = new TrinomialTree(myData); Console.WriteLine("Price {0}", myTree2.Price(100)); // Clewlow p. 63 American Put myData.sigma = 0.2; myData.T = 1.0; // One year myData.r = 0.06; myData.K = 100; myData.div = 0.0; myData.type = 'P'; // Put myData.exercise = true; //myData.NumberOfSteps = 3; TrinomialTree myTree3 = new TrinomialTree(myData); Console.WriteLine("Price {0}", myTree3.Price(100)); }
public void PVFacts() { var t = 1.0; var k = 0; var f = 100; var vol = 0.32; var rf = 0.05; var cp = OptionType.P; var df = System.Math.Exp(-rf * t); //zero strike put is worthless var PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.Equal(0, PV, 10); PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.Equal(0, PV, 10); //zero strike call is worth fwd with no discounting cp = OptionType.C; PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.Equal(f, PV, 10); PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.Equal(f, PV, 10); //and has delta = 1.0 var greeks = TrinomialTree.AmericanFutureOption(f, k, rf, t, vol, cp); Assert.Equal(1.0, (double)greeks[1, 0], 10); greeks = BinomialTree.AmericanFutureOption(f, k, rf, t, vol, cp); Assert.Equal(1.0, (double)greeks[1, 0], 10); //OTM option with zero vol is worthless vol = 0.0; k = f + 1; PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.Equal(0, PV, 10); PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.Equal(0, PV, 10); //option worth >= black in all cases for same inputs vol = 0.32; k = f + 20; var PVBlack = BlackFunctions.BlackPV(f, k, rf, t, vol, cp); PV = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.True(PV >= PVBlack); PV = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); Assert.True(PV >= PVBlack); }
public void PVFacts() { var t = 1.0; var k = 0.0; var f = 100.0; var vol = 0.32; var rf = 0.05; var cp = OptionType.P; //zero strike put is worthless var PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp); Assert.Equal(0, PV, 10); PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100); Assert.Equal(0, PV, 10); var flatInterp = new DummyPointInterpolator(new[] { 1.0 }, new[] { rf }); var flatFwdInterp = new DummyPointInterpolator(new[] { 1.0 }, new[] { f }); PV = TrinomialTree.VanillaPV(t, f, k, flatInterp, vol, cp, flatFwdInterp, 100, true); Assert.Equal(0, PV, 10); //zero strike call is worth fwd with no discounting cp = OptionType.C; PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp); Assert.Equal(f, PV, 10); PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100); Assert.Equal(f, PV, 10); //OTM option with zero vol is worthless vol = 0.0; k = f + 1.0; PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100); Assert.Equal(0, PV, 10); PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp); Assert.Equal(0, PV, 10); //option worth >= black in all cases for same inputs vol = 0.32; k = f + 20; var PVBlack = BlackFunctions.BlackPV(f, k, rf, t, vol, cp); PV = BinomialTree.AmericanPV(t, f, k, rf, vol, cp, rf, 100); Assert.True(PV >= PVBlack); PV = TrinomialTree.AmericanAssetOptionPV(f, k, rf, f, t, vol, cp); Assert.True(PV >= PVBlack); }
public void ImpliedVolFacts() { var t = 1.0; var k = 120; var f = 100; var vol = 0.32; var rf = 0.05; var cp = OptionType.P; var PVbi = BinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); var PVtri = TrinomialTree.AmericanFutureOptionPV(f, k, rf, t, vol, cp); var impliedVolBi = BinomialTree.AmericanFuturesOptionImpliedVol(f, k, rf, t, PVbi, cp); var impliedVolTri = TrinomialTree.AmericanFuturesOptionImpliedVol(f, k, rf, t, PVtri, cp); Assert.Equal(vol, impliedVolBi, 10); Assert.Equal(vol, impliedVolTri, 10); }
public void EuropeanOnGridFacts() { var t = 1.0; var k = 120; var f = 100; var vol = 0.32; var rf = 0.05; var cp = OptionType.P; var PVBlack = BlackFunctions.BlackPV(f, k, rf, t, vol, cp); var PVbi = BinomialTree.EuropeanPV(t, f, k, rf, vol, cp, rf, 100); var PVtri = TrinomialTree.EuropeanPV(t, f, k, rf, vol, cp, rf, 100); Assert.Equal(PVBlack, PVbi, 1); Assert.Equal(PVBlack, PVtri, 1); PVbi = BinomialTree.EuropeanFuturePV(t, f, k, rf, vol, cp, 100); PVtri = TrinomialTree.EuropeanFuturePV(t, f, k, rf, vol, cp, 100); Assert.Equal(PVBlack, PVbi, 1); Assert.Equal(PVBlack, PVtri, 1); }
/// <summary> /// Build a trinomial tree for given yield curve and time grids. /// For better pricing, one tree shall be rebuilt for each trade because of different coupon time and call/put dates. /// </summary> /// <param name="times">The times.</param> /// <param name="r0">The r0.</param> /// <param name="yieldCurve">The yield curve.</param> /// <returns></returns> public override NumericTree Tree(double[] times, double r0, IYieldCurve yieldCurve = null) { var tree = new TrinomialTree(new OrnsteinUhlenbeckProcess(_a, _sigma), times, 0); return(new NumericTree(this, tree, yieldCurve)); }
private TrinomialTree(TrinomialTree tritree) {// Copy-constructor // No body }
public override Lattice tree(TimeGrid grid){ TrinomialTree trinomial = new TrinomialTree(dynamics().process(), grid, true); return new ShortRateTree(trinomial, dynamics(), grid); }