public static BinomialLattice GetShortRateLattice(double interestRate, double upRatio, double downRatio, double upPossibility, int periods) { var lattice = new BinomialLattice(periods); lattice.Root.UnderlyingValue = interestRate; lattice.InterestRates[0] = lattice.Root.UnderlyingValue; // we are operating on the interest rates. for (int i = 0; i < periods; i++) { } return(lattice); }
public static void ComputeOption(Option option, double interestRate, int periods) { var n = periods; var maturity = option.TimeToMaturity; var dt = maturity / n; var style = option.Style; var strike = option.Strike; var q = option.Underlying.YieldRate; var r = interestRate; var sig = option.Underlying.Volatility; var lattice = new BinomialLattice(n); var node = new BinomialLatticeNode { Stage = 0, Index = 0, UnderlyingValue = option.Underlying.MarketPrice }; lattice.Root = node; lattice.InterestRates[0] = r; // from node to leaves; excludes root node for (int stage = 0; stage <= n; stage++) { var tempIndex = stage == n ? stage - 1 : stage; var u = Math.Exp(sig * Math.Sqrt(dt)); var d = 1 / u; var p = (Math.Exp((r - q) * dt) - d) / (u - d); var lowerNodeFactor = d / u; // compute current stage for (int i = 0; i <= stage; i++) { lattice[stage][i].Stage = stage; lattice[stage][i].Index = i; lattice[stage][i].UpRatio = u; lattice[stage][i].DownRatio = d; lattice[stage][i].UpRiskNeutralProbability = p; lattice[stage][i].DownRiskNeutralProbability = 1 - p; lattice.InterestRates[stage] = r; } if (stage == n) { continue; } // compute next stage lattice[stage + 1][0] = new BinomialLatticeNode { UnderlyingValue = lattice[stage][0].UnderlyingValue * lattice[stage][0].UpRatio }; for (int i = 1; i <= stage + 1; i++) { lattice[stage + 1][i] = new BinomialLatticeNode { UnderlyingValue = lattice[stage + 1][i - 1].UnderlyingValue * lowerNodeFactor }; } } // process the leaves for (int i = 0; i <= lattice.Dimension; i++) { node = lattice.Get(lattice.Dimension, i); var exerciseValue = option.Type == OptionType.Call ? node.UnderlyingValue - strike : strike - node.UnderlyingValue; node.DerivedValue = Math.Max(exerciseValue, 0); } // from last 2nd level leaves to nodes; includes root node for (int stage = n - 1; stage >= 0; stage--) { var disc = Math.Exp(-lattice.InterestRates[stage] * dt); var pUp = node.UpRiskNeutralProbability; var pDown = node.DownRiskNeutralProbability; for (int i = 0; i < lattice[stage].Length; i++) { node = lattice[stage][i]; var childUp = lattice[stage + 1][i]; // up child var childDown = lattice[stage + 1][i + 1]; // down child node.DerivedValue = disc * (pUp * childUp.DerivedValue + pDown * childDown.DerivedValue); if (style == OptionStyleType.American) { var exerciseValue = option.Type == OptionType.Call ? node.UnderlyingValue - strike : strike - node.UnderlyingValue; node.DerivedValue = Math.Max(exerciseValue, node.DerivedValue); } } } option.FairPrice = lattice.Root.DerivedValue; }