17 using MathNet.Numerics.Distributions;
32 public static decimal BlackTheoreticalPrice(decimal volatility, decimal spotPrice, decimal strikePrice, decimal timeToExpiration, decimal riskFreeRate, decimal dividendYield,
OptionRight optionType)
34 var d1 = CalculateD1(spotPrice, strikePrice, timeToExpiration, riskFreeRate, dividendYield, volatility);
35 var d2 = CalculateD2(d1, volatility, timeToExpiration);
36 var norm =
new Normal();
38 var optionPrice = 0.0m;
42 optionPrice = spotPrice * DecimalMath(Math.Exp, -dividendYield * timeToExpiration) * DecimalMath(norm.CumulativeDistribution, d1)
43 - strikePrice * DecimalMath(Math.Exp, -riskFreeRate * timeToExpiration) * DecimalMath(norm.CumulativeDistribution, d2);
47 optionPrice = strikePrice * DecimalMath(Math.Exp, -riskFreeRate * timeToExpiration) * DecimalMath(norm.CumulativeDistribution, -d2)
48 - spotPrice * DecimalMath(Math.Exp, -dividendYield * timeToExpiration) * DecimalMath(norm.CumulativeDistribution, -d1);
52 throw new ArgumentException(
"Invalid option right.");
58 internal static decimal CalculateD1(decimal spotPrice, decimal strikePrice, decimal timeToExpiration, decimal riskFreeRate, decimal dividendYield, decimal volatility)
60 var numerator = DecimalMath(Math.Log, spotPrice / strikePrice) + (riskFreeRate - dividendYield + 0.5m * volatility * volatility) * timeToExpiration;
61 var denominator = volatility * DecimalMath(Math.Sqrt, Math.Max(0m, timeToExpiration));
62 if (denominator == 0m)
67 return numerator / denominator;
70 internal static decimal CalculateD2(decimal d1, decimal volatility, decimal timeToExpiration)
72 return d1 - volatility * DecimalMath(Math.Sqrt, Math.Max(0m, timeToExpiration));
76 public static decimal CRRTheoreticalPrice(decimal volatility, decimal spotPrice, decimal strikePrice,
77 decimal timeToExpiration, decimal riskFreeRate, decimal dividendYield,
OptionRight optionType,
int steps =
Steps)
79 var deltaTime = timeToExpiration / steps;
80 var upFactor = DecimalMath(Math.Exp, volatility * DecimalMath(Math.Sqrt, deltaTime));
86 var downFactor = 1m / upFactor;
87 var probUp = (DecimalMath(Math.Exp, (riskFreeRate - dividendYield) * deltaTime) - downFactor) / (upFactor - downFactor);
89 return BinomialTheoreticalPrice(deltaTime, probUp, upFactor, riskFreeRate, spotPrice, strikePrice, optionType, steps);
92 public static decimal ForwardTreeTheoreticalPrice(decimal volatility, decimal spotPrice, decimal strikePrice,
93 decimal timeToExpiration, decimal riskFreeRate, decimal dividendYield,
OptionRight optionType,
int steps =
Steps)
95 var deltaTime = timeToExpiration / steps;
96 var discount = DecimalMath(Math.Exp, (riskFreeRate - dividendYield) * deltaTime);
97 var upFactor = DecimalMath(Math.Exp, volatility * DecimalMath(Math.Sqrt, deltaTime)) * discount;
98 var downFactor = DecimalMath(Math.Exp, -volatility * DecimalMath(Math.Sqrt, deltaTime)) * discount;
99 if (upFactor - downFactor == 0m)
104 downFactor = 0.9999m;
106 var probUp = (discount - downFactor) / (upFactor - downFactor);
108 return BinomialTheoreticalPrice(deltaTime, probUp, upFactor, riskFreeRate, spotPrice, strikePrice, optionType, steps);
111 private static decimal BinomialTheoreticalPrice(decimal deltaTime, decimal probUp, decimal upFactor, decimal riskFreeRate,
112 decimal spotPrice, decimal strikePrice,
OptionRight optionType,
int steps =
Steps)
114 var probDown = 1m - probUp;
115 var values =
new decimal[steps + 1];
117 for (
int i = 0; i <= steps; i++)
119 var nextPrice = spotPrice * Convert.ToDecimal(Math.Pow((
double)upFactor, 2 * i - steps));
123 for (
int period = steps - 1; period >= 0; period--)
125 for (
int i = 0; i <= period; i++)
127 var binomialValue = DecimalMath(Math.Exp, -riskFreeRate * deltaTime) * (values[i] * probDown + values[i + 1] * probUp);
131 values[i] = binomialValue;
134 var nextPrice = spotPrice * Convert.ToDecimal(Math.Pow((
double)upFactor, 2 * i - period));
136 values[i] = Math.Max(binomialValue, exerciseValue);
143 internal static decimal DecimalMath(Func<double, double>
function, decimal input)
145 return Convert.ToDecimal(
function((
double)input));