public double GetTheta(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); var d1 = GetD1(timePeriod, pricingData); var d2 = GetD2(timePeriod, pricingData); if (IsCall) { var term1 = -Math.Exp(-pricingData.DivYield * timePeriod) * pricingData.CurrentPrice * Normal.PDF(0, 1, d1) * pricingData.Vol / (2 * Math.Sqrt(timePeriod)); var term2 = pricingData.InterestRate * Strike * Math.Exp(-pricingData.InterestRate * timePeriod) * Normal.CDF(0, 1, d2); var term3 = pricingData.DivYield * pricingData.CurrentPrice * Math.Exp(-pricingData.DivYield * timePeriod) * Normal.CDF(0, 1, d1); var theta = term1 - term2 + term3; return(theta / TimePeriods.BusinessDaysInYear); } else { var term1 = -Math.Exp(-pricingData.DivYield * timePeriod) * pricingData.CurrentPrice * Normal.PDF(0, 1, -d1) * pricingData.Vol / (2 * Math.Sqrt(timePeriod)); var term2 = pricingData.InterestRate * Strike * Math.Exp(-pricingData.InterestRate * timePeriod) * (Normal.CDF(0, 1, d2) - 1); var term3 = pricingData.DivYield * pricingData.CurrentPrice * Math.Exp(-pricingData.DivYield * timePeriod) * (Normal.CDF(0, 1, d1) - 1); var theta = term1 - term2 + term3; return(theta / TimePeriods.BusinessDaysInYear); } }
protected double GetD2(double timePeriod, OptionPricingData pricingData) { var d1 = GetD1(timePeriod, pricingData); var d2 = d1 - pricingData.Vol * Math.Sqrt(timePeriod); return(d2); }
public void SetMarketData(OptionPricingData pricingData, bool fixedData) { StartPriceDoubleBox.Value = pricingData.CurrentPrice; VolDoubleBox.Value = pricingData.Vol; InterestDoubleBox.Value = pricingData.InterestRate; DivYieldDoubleBox.Value = pricingData.DivYield; FixedDataCheckBox.IsChecked = fixedData; }
protected double GetD1(double timePeriod, OptionPricingData pricingData) { var d1 = (Math.Log(pricingData.CurrentPrice / Strike) + (pricingData.InterestRate - pricingData.DivYield + 0.5 * Math.Pow(pricingData.Vol, 2)) * timePeriod) / (pricingData.Vol * Math.Pow(timePeriod, 0.5)); return(d1); }
public double GetGamma(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); var d1 = GetD1(timePeriod, pricingData); var gamma = Math.Exp(-pricingData.DivYield * timePeriod) * Normal.PDF(0, 1, d1) / (pricingData.CurrentPrice * pricingData.Vol * Math.Sqrt(timePeriod)); return(gamma); }
public double GetVega(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); var d1 = GetD1(timePeriod, pricingData); var vega = Math.Exp(-pricingData.DivYield * timePeriod) * pricingData.CurrentPrice * Math.Sqrt(timePeriod) * Normal.PDF(0, 1, d1) / 100; return(vega); }
public ValueTuple <OptionPricingData, bool> GetMarketData() { var startPrice = (double)StartPriceDoubleBox.Value; var vol = (double)VolDoubleBox.Value; var interestRate = (double)InterestDoubleBox.Value; var divYield = (double)DivYieldDoubleBox.Value; var fixedData = (bool)FixedDataCheckBox.IsChecked; var pricingData = new OptionPricingData(startPrice, vol, interestRate, divYield); return(pricingData, fixedData); }
public void TestGetPutTheta() { // arrange var option = GetOption(false); var currentDate = new DateTime(2020, 1, 1); var pricingData = new OptionPricingData(47.5, 0.22, 0.05, 0.03); // act var result = option.GetTheta(currentDate, pricingData); // asset Assert.AreEqual(-0.006292, result, 1e-6); }
public void TestGetCallRho() { // arrange var option = GetOption(true); var currentDate = new DateTime(2020, 1, 1); var pricingData = new OptionPricingData(47.5, 0.22, 0.05, 0.03); // act var result = option.GetRho(currentDate, pricingData); // asset Assert.AreEqual(0.146061, result, 1e-6); }
public void TestDigitalOptionPutCashSettled() { // arrange var option = GetOption(false, false); var pricingData = new OptionPricingData(107, 0.24, 0.03, 0.04); var currentDate = new DateTime(2017, 8, 31); // act var result = option.GetPriceBSModel(currentDate, pricingData); // assert Assert.AreEqual(0.509378, result, 1e-6); }
public void TestDigitalOptionPutAssetSettled() { // arrange var option = GetOption(false, true); var pricingData = new OptionPricingData(100, 0.15, 0.04, 0.0); var currentDate = new DateTime(2016, 4, 30); // act var result = option.GetPriceBSModel(currentDate, pricingData); // assert Assert.AreEqual(38.865210, result, 1e-6); }
public void TestDigitalOptionCallAssetSettled() { // arrange var option = GetOption(true, true); var pricingData = new OptionPricingData(100, 0.15, 0.04, 0); var currentDate = new DateTime(2016, 3, 30); // act var result = option.GetPriceBSModel(currentDate, pricingData); // assert Assert.AreEqual(61.711724, result, 1e-6); }
public void TestGetPriceBSModelPut() { // arrange var EqOption = GetOption(false); var currentDate = new DateTime(2019, 03, 31); var pricingData = new OptionPricingData(53, 0.15, 0.04, 0.06); // act var result = EqOption.GetPriceBSModel(currentDate, pricingData); // assert Assert.AreEqual(2.957613, result, 1e-6); }
public void TestGetPriceBSModelCall() { // arrange var EqOption = GetOption(true); var currentDate = new DateTime(2019, 6, 30); var pricingData = new OptionPricingData(48, 0.2, 0.05, 0.02); // act var result = EqOption.GetPriceBSModel(currentDate, pricingData); // assert Assert.AreEqual(4.224185, result, 1e-6); }
public double GetDelta(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); var d1 = GetD1(timePeriod, pricingData); if (IsCall) { return(Math.Exp(-pricingData.DivYield * timePeriod) * Normal.CDF(0, 1, d1)); } else { return(Math.Exp(-pricingData.DivYield * timePeriod) * (Normal.CDF(0, 1, d1) - 1)); } }
public double GetRho(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); var d2 = GetD2(timePeriod, pricingData); if (IsCall) { return(Math.Exp(-pricingData.InterestRate * timePeriod) * timePeriod * Strike * Normal.CDF(0, 1, d2) / 100); } else { return(Math.Exp(-pricingData.InterestRate * timePeriod) * timePeriod * Strike * (Normal.CDF(0, 1, d2) - 1) / 100); } }
public void TestDigitalOptionPutCallParityAssetSettled() { // arrange var callOption = GetOption(true, true); var putOption = GetOption(false, true); var pricingData = new OptionPricingData(101, 0.29, 0.04, 0.04); var currentDate = new DateTime(2017, 3, 31); // act var callPrice = callOption.GetPriceBSModel(currentDate, pricingData); var putPrice = putOption.GetPriceBSModel(currentDate, pricingData); var sum = callPrice + putPrice; // assert var paritySum = 96.204922; // should be discounted forward rate Assert.AreEqual(paritySum, sum, 1e-6); }
public void TestGetPriceBSModelPutCallParity() { // arrange var callOption = GetOption(true); var putOption = GetOption(false); var currentDate = new DateTime(2020, 8, 31); var pricingData = new OptionPricingData(45, 0.18, 0.02, 0.01); // assert var callPrice = callOption.GetPriceBSModel(currentDate, pricingData); var putPrice = putOption.GetPriceBSModel(currentDate, pricingData); var difference = callPrice - putPrice; // act var parityImpliedDifference = -4.951660; Assert.AreEqual(parityImpliedDifference, difference, 1e-6); }
public void TestDigitalOptionPutCallParityCashSettled() { // arrange var callOption = GetOption(true, false); var putOption = GetOption(false, false); var pricingDate = new OptionPricingData(106, 0.12, 0.07, 0.01); var currentDate = new DateTime(2017, 5, 31); // act var callPrice = callOption.GetPriceBSModel(currentDate, pricingDate); var putPrice = putOption.GetPriceBSModel(currentDate, pricingDate); var sum = callPrice + putPrice; // assert var paritySum = 0.929526; // should just be the discount factor Assert.AreEqual(paritySum, sum, 1e-6); }
public double GetPriceBSModel(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); var d1 = GetD1(timePeriod, pricingData); var d2 = GetD2(timePeriod, pricingData); var discountedStrike = Math.Exp(-pricingData.InterestRate * timePeriod) * Strike; var divAdjustedCurrentPrice = Math.Exp(-pricingData.DivYield * timePeriod) * pricingData.CurrentPrice; if (IsCall) { var price = divAdjustedCurrentPrice * Normal.CDF(0, 1, d1) - discountedStrike * Normal.CDF(0, 1, d2); return(price); } else { var price = discountedStrike * Normal.CDF(0, 1, -d2) - divAdjustedCurrentPrice * Normal.CDF(0, 1, -d1); return(price); } }
public double GetPriceBSModel(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); double optionPrice; var currentPrice = pricingData.CurrentPrice; var interestRate = pricingData.InterestRate; var divYield = pricingData.DivYield; var vol = pricingData.Vol; if (_isAssetSettled) { var divFactor = Math.Exp(-divYield * timePeriod); var d1 = GetD1(timePeriod, pricingData); if (IsCall) { optionPrice = currentPrice * Normal.CDF(0, 1, d1) * divFactor; } else { optionPrice = currentPrice * Normal.CDF(0, 1, -d1) * divFactor; } } else { var discountFactor = Math.Exp(-interestRate * timePeriod); var d2 = GetD2(timePeriod, pricingData); if (IsCall) { optionPrice = Normal.CDF(0, 1, d2) * discountFactor; } else { optionPrice = Normal.CDF(0, 1, -d2) * discountFactor; } } return(optionPrice); }
protected double GetDelta(DateTime currentDate, OptionPricingData pricingData) { var timePeriod = GetTimePeriodToExpiry(currentDate); if (_isAssetSettled) { var d1 = GetD1(timePeriod, pricingData); var adjustment = Math.Exp(-pricingData.DivYield * timePeriod); var scaling = pricingData.Vol * Math.Sqrt(timePeriod); if (IsCall) { var delta = adjustment * (Normal.CDF(0, 1, d1) + Normal.PDF(0, 1, d1) / scaling); return(delta); } else { var delta = adjustment * (Normal.CDF(0, 1, -d1) - Normal.PDF(0, 1, d1) / scaling); return(delta); } } else { var d2 = GetD2(timePeriod, pricingData); var discountFactor = Math.Exp(-pricingData.InterestRate * timePeriod); var scaling = pricingData.CurrentPrice * pricingData.Vol * Math.Sqrt(timePeriod); var delta = discountFactor * Normal.PDF(0, 1, d2) / scaling; if (IsCall) { return(delta); } else { return(-delta); } } }
private SortedList <DateTime, OptionPricingData> GenerateOptionPricingData(DateTime startDate, DateTime expiryDate, GbmParameters gbmParams, OptionPricingData basicPricingData, int?seed) { int days = startDate.GetWorkingDaysTo(expiryDate); var stockPrices = StochasticEngine.GetGeometricBrownianSeries(gbmParams, 1.0 / TimePeriods.BusinessDaysInYear, days, seed); var pricingData = new SortedList <DateTime, OptionPricingData>(); var date = startDate; if (!date.IsWorkingDay()) { date = date.AddWorkingDay(); } foreach (double price in stockPrices) { pricingData.Add(date, new OptionPricingData(price, basicPricingData.Vol, basicPricingData.InterestRate, basicPricingData.DivYield)); date = date.AddWorkingDay(); } return(pricingData); }
public GbmParameters(OptionPricingData pricingData) { Mean = pricingData.InterestRate - pricingData.DivYield; Vol = pricingData.Vol; InitialVal = pricingData.CurrentPrice; }
public void PlotDailyPnL(DateTime startDate, OptionPricingData basicPricingData, List <HedgingStrategy> hedgingStrategies, int?seed = null) { ClearCharts(); var gbmParameters = new GbmParameters(basicPricingData); var pricingData = GenerateOptionPricingData(startDate, hedgingStrategies[0].ExpiryDate, gbmParameters, basicPricingData, seed); var minPrice = double.PositiveInfinity; var maxPrice = double.NegativeInfinity; var stockSeries = new LineSeries() { Title = @"Stock Price" }; for (int i = 0; i < pricingData.Count; i++) { var stockPrice = pricingData.Values[i].CurrentPrice; stockSeries.Points.Add(new DataPoint(i, stockPrice)); minPrice = Math.Min(minPrice, stockPrice); maxPrice = Math.Max(maxPrice, stockPrice); } PlotStockPrice.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Minimum = 0, TextColor = OxyColors.Transparent }); PlotStockPrice.Axes.Add(new OxyPlot.Axes.LinearAxis { Position = OxyPlot.Axes.AxisPosition.Left, Minimum = (Math.Floor(minPrice / 5) - 1) * 5, Maximum = (Math.Floor(maxPrice / 5) + 1) * 5 }); PlotStockPrice.Series.Add(stockSeries); var strike = hedgingStrategies[0].Portfolio.Option.Strike; var strikeAnnotation = new LineAnnotation() { Y = strike, MinimumX = 0, MaximumX = stockSeries.Points.Count, Color = OxyColors.Red, LineStyle = LineStyle.Solid, Type = LineAnnotationType.Horizontal }; PlotStockPrice.Annotations.Add(strikeAnnotation); foreach (HedgingStrategy strategy in hedgingStrategies) { var pnl = strategy.GetDailyPnl(pricingData); var dailyPnlSeries = new ColumnSeries() { Title = $"{strategy.Name} - Daily PnL" }; var cumulativeSeries = new ColumnSeries() { Title = $"{strategy.Name} - Cumulative PnL" }; var cumulativePnl = new List <double>(); foreach (KeyValuePair <DateTime, (double, double, double)> dailyPnl in pnl) { // TODO: plot different PnL elements seperately (double optionPnl, double hedgePnl, double cashPnl) = dailyPnl.Value; var totalPnl = optionPnl + hedgePnl + cashPnl; dailyPnlSeries.Items.Add(new ColumnItem(totalPnl)); if (cumulativePnl.Count == 0) { cumulativePnl.Add(totalPnl); } else { cumulativePnl.Add(cumulativePnl[cumulativePnl.Count - 1] + totalPnl); } } foreach (double dailyVal in cumulativePnl) { cumulativeSeries.Items.Add(new ColumnItem(dailyVal)); } PlotModelDaily.Series.Add(dailyPnlSeries); PlotModelCumulative.Series.Add(cumulativeSeries); PlotModelDaily.Axes.Add(new CategoryAxis() { Position = AxisPosition.Bottom, IsAxisVisible = false }); PlotModelCumulative.Axes.Add(new CategoryAxis() { Position = AxisPosition.Bottom, IsAxisVisible = false }); RefreshCharts(); } }