예제 #1
0
        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);
            }
        }
예제 #2
0
        protected double GetD2(double timePeriod,
                               OptionPricingData pricingData)
        {
            var d1 = GetD1(timePeriod, pricingData);
            var d2 = d1 - pricingData.Vol * Math.Sqrt(timePeriod);

            return(d2);
        }
예제 #3
0
 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;
 }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        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);
        }
예제 #15
0
        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));
            }
        }
예제 #16
0
        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);
            }
        }
예제 #17
0
        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);
        }
예제 #19
0
        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);
        }
예제 #20
0
        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);
            }
        }
예제 #21
0
        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);
        }
예제 #22
0
        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);
        }
예제 #24
0
 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();
            }
        }