public void Compute(OptionPosition option) { var t = option.TimeToExpiry.TotalDays / 365.0; if (Math.Abs(t) < Double.Epsilon) { return; } var d1 = Math.Log(option.UnderlyingPrice / option.Strike) + (option.InterestRate - option.DividendRate + Math.Pow(option.Volatility, 2)) / t; var d2 = d1 - option.Volatility * Math.Sqrt(t); // when calculating option greeks keep in mind that we calculate greek for position, // and that's why BS formulas for greeks must be multiplied by -1 in case we're selling options // so formulas for greeks are [sign * BSFormula] if (option.Type == OptionType.Call) { option.OptionPrice = option.UnderlyingPrice * NormalDistribution.Phi(d1) - option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(d2); option.Delta = Math.Exp(-option.DividendRate * t) * NormalDistribution.Phi(d1); option.Theta = -Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Density(d1) * option.Volatility / (2 * Math.Sqrt(t)) + option.DividendRate * Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Phi(d1) - option.InterestRate * option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(d2); option.Rho = t * option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(d2); } else { option.OptionPrice = -option.UnderlyingPrice * NormalDistribution.Phi(-d1) + option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(-d2); option.Delta = Math.Exp(-option.DividendRate * t) * (NormalDistribution.Phi(d1) - 1); option.Theta = -Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Density(d1) * option.Volatility / (2 * Math.Sqrt(t)) - option.DividendRate * Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Phi(-d1) + option.InterestRate * option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(-d2); option.Rho = -t *option.Strike *Math.Exp(-option.InterestRate *t) * NormalDistribution.Phi(-d2); } option.Gamma = Math.Exp(-option.DividendRate * t) * NormalDistribution.Density(d1) / (option.UnderlyingPrice * option.Volatility * Math.Sqrt(t)); option.Vega = Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Density(d1) * Math.Sqrt(t); SideHelper.FixGreeksAccordingToSide(option); }
public void Compute(OptionPosition option) { int steps = option.TreeSteps; double s = option.UnderlyingPrice; var t = option.TimeToExpiry.TotalDays / 365.0; if (Math.Abs(t) < Double.Epsilon) { return; } if (option.TreeSteps == 0) { return; } var deltaT = t / (double)steps; if (deltaT >= Math.Pow(option.Volatility, 2) / Math.Pow(option.InterestRate - option.DividendRate, 2)) { return; } double u = Math.Exp(option.Volatility * Math.Sqrt(t)); double d = 1 / u; var prices = GetPrices(option.Type == OptionType.Call, option.UnderlyingPrice, t, steps, option.Volatility, option.Strike, option.InterestRate, option.DividendRate); // x x x // x x // x option.OptionPrice = prices[0, 0]; option.Delta = (prices[1, 1] - prices[1, 0]) / (s * u - s * d); option.Gamma = ((prices[2, 2] - prices[2, 1]) / (s * u * u - s * u * d) - (prices[2, 1] - prices[2, 0]) / (s * u * d - s * d * d)) / (0.5 * (s * u * u - s * d * d)); option.Theta = (prices[2, 1] - prices[0, 0]) / (2 * deltaT); option.Vega = (GetPrices(option.Type == OptionType.Call, option.UnderlyingPrice, t, steps, option.Volatility * 1.01, option.Strike, option.InterestRate, option.DividendRate)[0, 0] - option.OptionPrice) / (option.Volatility * 0.01); option.Rho = (GetPrices(option.Type == OptionType.Call, option.UnderlyingPrice, t, steps, option.Volatility, option.Strike, option.InterestRate * 1.01, option.DividendRate)[0, 0] - option.OptionPrice) / (option.InterestRate * 0.01); SideHelper.FixGreeksAccordingToSide(option); }
public void Compute(OptionPosition option) { var t = option.TimeToExpiry.TotalDays / 365.0; if (Math.Abs(t) < Double.Epsilon) { return; } if (option.TreeSteps == 0) { return; } Func <double, double> getWithTime = x => GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike, option.Volatility, option.InterestRate, option.DividendRate, x, option.TreeSteps)[0, 0]; Func <double, double> getWithVol = x => GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike, x, option.InterestRate, option.DividendRate, t, option.TreeSteps)[0, 0]; Func <double, double> getWithR = x => GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike, option.Volatility, x, option.DividendRate, t, option.TreeSteps)[0, 0]; var deltaT = t / (double)option.TreeSteps; double u = Math.Exp(option.Volatility * Math.Sqrt(2 * deltaT)); double d = Math.Exp(-option.Volatility * Math.Sqrt(2 * deltaT)); var prices = GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike, option.Volatility, option.InterestRate, option.DividendRate, t, option.TreeSteps); option.OptionPrice = prices[0, 0]; option.Delta = (prices[1, 2] - 2 * prices[1, 1] + prices[1, 0]) / (option.UnderlyingPrice * (u - d)); option.Gamma = ((prices[2, 4] - 2 * prices[2, 3] + prices[2, 2]) / (Math.Pow(option.UnderlyingPrice * (u * u - u), 2)) - (prices[2, 2] - 2 * prices[2, 1] + prices[2, 0]) / (Math.Pow(option.UnderlyingPrice * (d - d * d), 2))) / (0.5 * (option.UnderlyingPrice * (u * u - d * d))); option.Theta = (getWithTime(t + deltaT) - getWithTime(t - deltaT)) / (2 * deltaT); double volDelta = option.Volatility * 0.01; option.Vega = (getWithVol(option.Volatility + volDelta) - getWithVol(option.Volatility - volDelta)) / (2 * volDelta); double rDelta = option.InterestRate * 0.01; option.Rho = (getWithR(option.InterestRate + rDelta) - getWithR(option.InterestRate - rDelta)) / (2 * rDelta); SideHelper.FixGreeksAccordingToSide(option); }