/// <summary>
        /// Gets the closest non-zero volatility strike to money.
        /// </summary>
        /// <param name="expiry">The expiry.</param>
        /// <returns></returns>
        ///
        public static Strike GetClosestStrikeToMoney(ForwardExpiry expiry)
        {
            decimal fwdPrice   = expiry.FwdPrice;
            var     expiryCopy = BinarySerializerHelper.Clone(expiry);

            /* Bin search bitwise complement returns first element larger than search key
             * Returns Array Length + 1 if search key greater than all elements */
            expiryCopy.RawStrikePrices.Sort();
            double[] strikes = expiryCopy.RawStrikePrices.ToArray();
            int      index   = Array.BinarySearch(strikes, Convert.ToDouble(fwdPrice));

            if (index < 0)
            {
                index = ~index;
            }
            if (expiryCopy.Strikes.Length == 0)
            {
                return(null);
            }
            if (index < expiryCopy.Strikes.Length)
            {
                double dist1 = Math.Abs(strikes[index] - Convert.ToDouble(fwdPrice));
                double dist2 = 0.0;
                if (index >= 1)
                {
                    dist2 = Math.Abs(strikes[index - 1] - Convert.ToDouble(fwdPrice));
                }
                if (dist1 <= dist2 || index == 0)
                {
                    return(expiryCopy.Strikes[index]);
                }
                return(expiryCopy.Strikes[index - 1]);
            }
            return(expiryCopy.Strikes[expiryCopy.RawStrikePrices.Count - 1]);
        }
Example #2
0
        public void TestVolSurface()
        {
            IVolatilitySurface volSurface = new VolatilitySurface("BHP", 4500M, DateTime.Today);
            ForwardExpiry      expiry1    = new ForwardExpiry(DateTime.Parse("01-Jan-2010"), 4200);
            ForwardExpiry      expiry2    = new ForwardExpiry(DateTime.Parse("01-Jan-2011"), 4400);
            OptionPosition     call1      = new OptionPosition("1245", 104, PositionType.Call);
            OptionPosition     put1       = new OptionPosition("1246", 1200, PositionType.Put);
            OptionPosition     call2      = new OptionPosition("1645", 180, PositionType.Call);
            OptionPosition     put2       = new OptionPosition("1646", 1300, PositionType.Put);
            Strike             strike1    = new Strike(4200, call1, put1);
            Strike             strike2    = new Strike(4000, call2, put2);
            IVolatilityPoint   point1     = new VolatilityPoint();

            point1.SetVolatility(0.30M, VolatilityState.Default());
            put1.SetVolatility(point1);
            call1.SetVolatility(point1);
            IVolatilityPoint point2 = new VolatilityPoint();

            point2.SetVolatility(0.40M, VolatilityState.Default());
            call2.SetVolatility(point2);
            put2.SetVolatility(point2);
            expiry1.AddStrike(strike1, true);
            expiry2.AddStrike(strike2, false);
            volSurface.AddExpiry(expiry1);
            volSurface.AddExpiry(expiry2);
            List <ForwardExpiry> forwardExpiries = volSurface.NodalExpiries.ToList();
            int n1 = forwardExpiries[0].Strikes.Count(item => item.NodalPoint);
            // int n2 = forwardExpiries[1].Strikes.Count(delegate(Strike item) { return item.NodalPoint == true; });
            int n2 = 0;

            Assert.AreEqual(1, n1 + n2);
        }
Example #3
0
        internal static Pair <Strike, Strike> GetBoundingStrikes(ForwardExpiry expiry, double strike)
        {
            if (expiry.Strikes.Length < 2)
            {
                return(new Pair <Strike, Strike>(expiry.Strikes[0], expiry.Strikes[0]));
            }
            Strike strike1;
            Strike strike2;

            if (strike <= expiry.RawStrikePrices[0])
            {
                strike1 = expiry.Strikes[0];
                strike2 = strike1;
                return(new Pair <Strike, Strike>(strike1, strike2));
            }

            for (int idx = 0; idx < expiry.Strikes.Length - 1; idx++)
            {
                if (strike > expiry.RawStrikePrices[idx] & strike <= expiry.RawStrikePrices[idx + 1])
                {
                    strike1 = expiry.Strikes[idx];
                    strike2 = expiry.Strikes[idx + 1];
                    return(new Pair <Strike, Strike>(strike1, strike2));
                }
            }
            strike1 = expiry.Strikes[expiry.Strikes.Length - 1];
            strike2 = strike1;
            return(new Pair <Strike, Strike>(strike1, strike2));
        }
        /// <summary>
        /// Does the grouping.
        /// </summary>
        public static void DoGrouping(ForwardExpiry expiry)
        {
            var inTheMoney  = new List <Strike>();
            var atTheMoney  = new List <Strike>();
            var outTheMoney = new List <Strike>();

            GroupStrikesByMoneyness(expiry.FwdPrice, new List <Strike>(expiry.Strikes), expiry.RawStrikePrices, ref inTheMoney, ref atTheMoney, ref outTheMoney);
        }
        /// <summary>
        /// Gets the longest expiry.
        /// </summary>
        /// <param name="fwdExpiries">The FWD expiries.</param>
        /// <returns></returns>
        public static ForwardExpiry GetLongestExpiry(ForwardExpiry[] fwdExpiries)
        {
            DateTime      lastExpiryDate = DateTime.MinValue;
            ForwardExpiry lastExpiry     = null;

            foreach (ForwardExpiry fwdExpiry in fwdExpiries)
            {
                if (fwdExpiry.ExpiryDate <= lastExpiryDate)
                {
                    continue;
                }
                lastExpiryDate = fwdExpiry.ExpiryDate;
                lastExpiry     = fwdExpiry;
            }
            return(lastExpiry);
        }
        /// <summary>
        /// Returns a reference to the minimum proximity contract to lead expiry
        /// (contract expiries are not perfectly aligned) provided the date difference
        /// is within some specified number of days.
        /// </summary>
        /// <param name="fwdExpiry">The FWD expiry.</param>
        /// <param name="volSurface">The vol surface.</param>
        /// <param name="proximityDays">The proximity days.</param>
        /// <returns></returns>
        public static ForwardExpiry FindExpiryClosestTo(ForwardExpiry fwdExpiry, VolatilitySurface volSurface, int proximityDays)
        {
            int           lastProx           = proximityDays;
            ForwardExpiry closestChildExpiry = null;

            foreach (ForwardExpiry childExpiry in volSurface.Expiries)
            {
                int prox = Math.Abs(childExpiry.ExpiryDate.Subtract(fwdExpiry.ExpiryDate).Days);

                if (prox <= proximityDays)
                {
                    lastProx           = prox;
                    closestChildExpiry = childExpiry;
                }
            }
            return(lastProx <= proximityDays ? closestChildExpiry : null);
        }
        ///// <summary>
        ///// Creates the surface from expiry node list.
        ///// </summary>
        ///// <param name="assetId">The asset id.</param>
        ///// <param name="expiryNodes">The expiry nodes.</param>
        ///// <returns></returns>
        //public static IVolatilitySurface CreateSurfaceFromNodalExpiryNodeList(string assetId, XmlNodeList expiryNodes)
        //{
        //    IVolatilitySurface surface = new VolatilitySurface(assetId);
        //    List<ForwardExpiry> expiries = ForwardExpiryHelper.CreateExpiriesFromExpiryNodeList(expiryNodes);

        //    if (expiries != null)
        //    {
        //        foreach (ForwardExpiry expiry in expiries)
        //        {
        //            surface.AddExpiry(expiry);
        //        }
        //    }
        //    else
        //    {
        //        throw new IncompleteInputDataException("Surface has no expiries");
        //    }
        //    return surface;

        //}



        /// <summary>
        /// Gets the closest non-zero volatility strike to money.
        /// </summary>
        /// <param name="expiry">The expiry.</param>
        /// <returns></returns>
        ///
        public static double GetClosestNonZeroVolStrikeToMoney(ForwardExpiry expiry)
        {
            decimal fwdPrice   = expiry.FwdPrice;
            var     expiryCopy = BinarySerializerHelper.Clone(expiry);

            //Remove strikes with zero vol in the search object
            //Want to return the location of the nearest *non-zero* strike
            foreach (Strike strike in expiryCopy.Strikes)
            {
                if (strike.Volatility.Value == 0)
                {
                    expiryCopy.RemoveStrike(strike.StrikePrice);
                }
            }

            /* Bin search bitwise complement returns first element larger than search key
             * Returns Array Length + 1 if search key greater than all elements */

            expiryCopy.RawStrikePrices.Sort();
            double[] strikes = expiryCopy.RawStrikePrices.ToArray();
            int      index   = Array.BinarySearch(strikes, Convert.ToDouble(fwdPrice));

            if (index < 0)
            {
                index = ~index;
            }
            if (expiryCopy.RawStrikePrices.Count == 0)
            {
                return(0.0);
            }
            if (index < expiryCopy.RawStrikePrices.Count)
            {
                double dist1 = Math.Abs(strikes[index] - Convert.ToDouble(fwdPrice));
                double dist2 = 0.0;
                if (index >= 1)
                {
                    dist2 = Math.Abs(strikes[index - 1] - Convert.ToDouble(fwdPrice));
                }
                if (dist1 <= dist2 || index == 0)
                {
                    return(expiryCopy.RawStrikePrices[index]);
                }
                return(expiryCopy.RawStrikePrices[index - 1]);
            }
            return(expiryCopy.RawStrikePrices[expiryCopy.RawStrikePrices.Count - 1]);
        }
Example #8
0
        public static Stock CreateStock(EquityVolCalcTestData.Stock stock)
        {
            DateTime today    = XmlGetDate(stock.Date);
            decimal  spot     = Convert.ToDecimal(stock.Spot);
            DateTime baseDate = XmlGetDate(stock.RateCurve.BaseDate);

            DateTime[] rateDates = XmlGetDateArray(stock.RateCurve.DateArray);
            //Load rate curve
            String tp = stock.RateCurve.RateType;
            var    rc = new RateCurve(stock.RateCurve.Ccy, tp, baseDate, rateDates, stock.RateCurve.RateArray);
            // Load dividends
            var divs = (from div in stock.Dividends let exDate = XmlGetDate(div.ExDate) select new Dividend(exDate, Convert.ToDecimal(div.Amount))).ToList();
            //Load stock object
            var stock0 = new Stock(today, spot, stock.AssetId, stock.Name, rc, divs);
            var vol0   = new VolatilitySurface(stock.AssetId, spot, today);

            //Load vols
            stock0.VolatilitySurface = vol0;
            foreach (StockVolatilitySurfaceForwardExpiry exp in stock.VolatilitySurface.Expiries)
            {
                DateTime expDate = XmlGetDate(exp.ExpiryDate);
                Decimal  fwd     = Convert.ToDecimal(exp.FwdPrice);
                var      exp0    = new ForwardExpiry(expDate, fwd);
                // exp0.NodalPoint = System.Convert.ToBoolean(exp.NodalPoint);
                vol0.AddExpiry(exp0);

                foreach (StockVolatilitySurfaceForwardExpiryStrike str in exp.Strikes)
                {
                    var    call         = new OptionPosition();
                    var    put          = new OptionPosition();
                    double strikeprice0 = Convert.ToDouble(str.StrikePrice);
                    var    str0         = new Strike(strikeprice0, call, put, Units.Cents)
                    {
                        Moneyness = Convert.ToDouble(str.Moneyness)
                    };
                    exp0.AddStrike(str0, true);
                    var     vp  = new VolatilityPoint();
                    decimal vol = Convert.ToDecimal(str.Volatility.Value);
                    vp.SetVolatility(vol, VolatilityState.Default());
                    str0.SetVolatility(vp);
                }
            }
            return(stock0);
        }
        /// <summary>
        /// Determines whether the specified strike is match.
        /// </summary>
        /// <param name="strike">The strike.</param>
        /// <param name="expiry">The expiry.</param>
        /// <param name="expiries">The expiries.</param>
        /// <returns>
        ///     <c>true</c> if the specified strike is match; otherwise, <c>false</c>.
        /// </returns>
        public static Strike GetStrike(double strike, DateTime expiry, ForwardExpiry[] expiries)
        {
            ForwardExpiry exp = ForwardExpiryHelper.FindExpiry(expiry, new List <ForwardExpiry>(expiries));

            if (exp == null)
            {
                return(null);
            }
            foreach (Strike str in exp.Strikes)
            {
                int i;
                StrikeHelper.FindStrikeWithPrice(strike, new List <Strike>(exp.Strikes), out i);
                if (i >= 0)
                {
                    return(exp.Strikes[i]);
                }
            }
            return(null);
        }
Example #10
0
        private static VolatilitySurface CreateSurface(Stock stock)
        {
            VolatilitySurface surface = new VolatilitySurface(stock.AssetId, stock.Spot, stock.Date);
            List <DateTime>   dates   = new List <DateTime>
            {
                new DateTime(2009, 9, 16),
                new DateTime(2009, 10, 05),
                new DateTime(2009, 10, 10),
                new DateTime(2009, 11, 9),
                new DateTime(2009, 11, 26),
                new DateTime(2009, 12, 9),
                new DateTime(2010, 3, 10),
                new DateTime(2010, 6, 9),
                new DateTime(2010, 9, 8),
                new DateTime(2011, 3, 12),
                new DateTime(2011, 9, 7),
                new DateTime(2012, 9, 9),
                new DateTime(2013, 9, 9),
                new DateTime(2014, 9, 9),
            };
            IList <double> moneynesses = new List <double> {
                0.5, 0.9, 1, 1.1, 1.5
            };

            foreach (DateTime date in dates)
            {
                var expiry = new ForwardExpiry
                {
                    FwdPrice   = (decimal)stock.GetForward(stock.Date, date),
                    ExpiryDate = date
                };
                foreach (double moneyness in moneynesses)
                {
                    Strike           str = new Strike(Math.Round(Convert.ToDouble(expiry.FwdPrice) * moneyness, 2), null, null, Units.Cents);
                    IVolatilityPoint vp  = new VolatilityPoint();
                    vp.SetVolatility(Convert.ToDecimal(Math.Exp(moneyness) / 3 * 0.32), VolatilityState.Default());
                    str.SetVolatility(vp);
                    expiry.AddStrike(str, true);
                }
                surface.AddExpiry(expiry);
            }
            return(surface);
        }
        /// <summary>
        /// Gets the  i-th closest non-zero volatility strike to money.
        /// </summary>
        /// <param name="expiry">The expiry.</param>
        /// <param name="i"></param>
        /// <returns></returns>
        public static double GetClosestNonZeroVolStrikeToMoney(ForwardExpiry expiry, int i)
        {
            decimal fwdPrice   = expiry.FwdPrice;
            var     expiryCopy = BinarySerializerHelper.Clone(expiry);

            //Remove strikes with zero vol in the search object
            //Want to return the location of the nearest *non-zero* strike
            foreach (Strike strike in expiryCopy.Strikes)
            {
                if (strike.Volatility.Value == 0)
                {
                    expiryCopy.RemoveStrike(strike.StrikePrice);
                }
            }
            var newStrikes = new double[expiryCopy.RawStrikePrices.Count];

            expiryCopy.RawStrikePrices.Sort();
            double[] strikes = expiryCopy.RawStrikePrices.ToArray();

            if (strikes.Length < i)
            {
                return(0);
            }
            var keys = new int[strikes.Length];

            for (int idx = 0; idx < strikes.Length; idx++)
            {
                newStrikes[idx] = strikes[idx] - (double)fwdPrice;
                keys[idx]       = idx;
            }
            //Get min distance to forward
            Array.Sort(newStrikes, keys, new DistanceComparer());
            if (i > 0)
            {
                return(expiryCopy.Strikes[keys[i - 1]].StrikePrice);
            }
            return(0);

            /* Bin search bitwise complement returns first element larger than search key
             * Returns Array Length + 1 if search key greater than all elements */
        }
        //const int CExpiryDays = 5;

        /// <summary>
        /// Adds the expiry.
        /// </summary>
        /// <param name="expiry">The expiry.</param>
        /// <param name="expiries">The expiries.</param>
        internal static void AddExpiry(ForwardExpiry expiry, List <ForwardExpiry> expiries)
        {
            ForwardExpiry match = FindExpiry(expiry.ExpiryDate, expiry.FwdPrice, expiry.InterestRate, expiries);

            if (match == null)
            {
                if (expiries.Count == 0)
                {
                    expiries.Add(expiry);
                }
                else
                {
                    List <ForwardExpiry> expiriesFound = expiries.FindAll(
                        expiryItem => (expiryItem.ExpiryDate < expiry.ExpiryDate)
                        );
                    expiries.Insert(expiriesFound.Count == 0 ? 0 : expiriesFound.Count, expiry);
                }
            }
            else
            {
                throw new DuplicateNotAllowedException(
                          $"An expiry date {expiry.ExpiryDate} with price {expiry.FwdPrice} already exists on this surface");
            }
        }
        private static VolatilitySurface CreateSurface(Stock stock)
        {
            VolatilitySurface surface = new VolatilitySurface(stock.AssetId, stock.Spot, stock.Date);
            List <DateTime>   dates   = new List <DateTime>
            {
                new DateTime(2014, 9, 9),
                new DateTime(2016, 9, 9)
            };
            IList <double> strikes = new List <double> {
                2261,
                2638,
                2827,
                3015,
                3204,
                3298,
                3392,
                3467,
                3543,
                3581,
                3618,
                3694,
                3769,
                3844,
                3920,
                3957,
                3995,
                4071,
                4146,
                4240,
                4334,
                4523,
                4711,
                4900,
                5277,
                5465,
                5654,
                5842,
                6030,
                6219,
                6407,
                6596,
                6784,
                6973,
                7161,
                7350,
                7538
            };

            IList <double> vols1 = new List <double> {
                0.4162,
                0.4094,
                0.4062,
                0.4031,
                0.4,
                0.3985,
                0.3972,
                0.3961,
                0.3949,
                0.3944,
                0.3938,
                0.3925,
                0.3912,
                0.3899,
                0.3886,
                0.388,
                0.3874,
                0.3862,
                0.385,
                0.3835,
                0.382,
                0.3792,
                0.3764,
                0.3738,
                0.3688,
                0.3665,
                0.3643,
                0.3622,
                0.3602,
                0.3584,
                0.3566,
                0.3549,
                0.3533,
                0.3518,
                0.3503,
                0.3489,
                0.3476
            };

            IList <double> vols2 = new List <double> {
                0.4085,
                0.4021,
                0.399,
                0.3961,
                0.3932,
                0.3918,
                0.3906,
                0.3897,
                0.3888,
                0.3883,
                0.3878,
                0.3866,
                0.3853,
                0.384,
                0.3828,
                0.3822,
                0.3816,
                0.3803,
                0.3792,
                0.3777,
                0.3763,
                0.3734,
                0.3707,
                0.3681,
                0.3631,
                0.3608,
                0.3585,
                0.3564,
                0.3544,
                0.3525,
                0.3506,
                0.3489,
                0.3472,
                0.3456,
                0.344,
                0.3425,
                0.3411
            };


            var expiry1 = new ForwardExpiry
            {
                FwdPrice   = (decimal)stock.GetForward(stock.Date, dates[0]),
                ExpiryDate = dates[0]
            };
            var expiry2 = new ForwardExpiry
            {
                FwdPrice   = (decimal)stock.GetForward(stock.Date, dates[1]),
                ExpiryDate = dates[1]
            };

            for (int idx = 0; idx < strikes.Count; idx++)
            {
                Strike           str = new Strike(strikes[idx], null, null, Units.Cents);
                IVolatilityPoint vp  = new VolatilityPoint();
                vp.SetVolatility(Convert.ToDecimal(vols1[idx]), VolatilityState.Default());
                str.SetVolatility(vp);
                expiry1.AddStrike(str, true);
            }
            surface.AddExpiry(expiry1);
            for (int idx = 0; idx < strikes.Count; idx++)
            {
                Strike           str = new Strike(strikes[idx], null, null, Units.Cents);
                IVolatilityPoint vp  = new VolatilityPoint();
                vp.SetVolatility(Convert.ToDecimal(vols2[idx]), VolatilityState.Default());
                str.SetVolatility(vp);
                expiry2.AddStrike(str, true);
            }
            surface.AddExpiry(expiry2);
            return(surface);
        }