예제 #1
0
        public void GetPPDTest()
        {
            string[] rows = new string[] { "1 MONTH", "2 MONTH", "3 MONTH", "6 MONTH", "1 YEAR", "2 YEAR", "3 YEAR", "5 YEAR", "7 YEAR", "10 YEAR" };
            string[] cols = new string[] { "1YEAR", "2 YEAR", "3 YEAR", "4 YEAR", "5 YEAR", "6 YEAR", "7 YEAR", "8 YEAR", "9 YEAR", "10 YEAR" };

            object[][] data = new object[][]
            {
                new object[] { 6.4M, 6.4M, 6.6M, 7M, 7M, 7M, 6.9M, 6.9M, 6.9M, 6.8M },
                new object[] { 6.4M, 6.4M, 6.6M, 7M, 7M, 7M, 6.9M, 6.9M, 6.9M, 6.8M },
                new object[] { 6.5M, 6.6M, 6.7M, 6.8M, 6.8M, 6.8M, 6.7M, 6.7M, 6.7M, 6.6M },
                new object[] { 6.5M, 6.6M, 6.7M, 6.8M, 6.8M, 6.8M, 6.7M, 6.7M, 6.7M, 6.5M },
                new object[] { 6.5M, 6.5M, 6.4M, 6.35M, 6.4M, 6.4M, 6.3M, 6.3M, 6.3M, 6.2M },
                new object[] { 6.4M, 6.4M, 6.2M, 6.15M, 6.1M, 6.1M, 6M, 6M, 6M, 5.9M },
                new object[] { 6.1M, 6.25M, 5.8M, 5.55M, 5.3M, 5.3M, 5.2M, 5.2M, 5.2M, 5.1M },
                new object[] { 5.7M, 5.4M, 5.2M, 5M, 4.9M, 4.9M, 4.85M, 4.85M, 4.85M, 4.75M },
                new object[] { 5.7M, 5.4M, 5.2M, 5M, 4.9M, 4.9M, 4.85M, 4.85M, 4.85M, 4.75M },
                new object[] { 5.7M, 5.4M, 5.2M, 5M, 4.9M, 4.9M, 4.85M, 4.85M, 4.85M, 4.75M }
            };

            SwaptionPPDGrid target = new SwaptionPPDGrid(rows, cols, data);

            string  expiry   = "3M";
            string  tenor    = "3Y";
            decimal expected = 6.7m;
            decimal actual   = target.GetPPD(expiry, tenor);

            Assert.AreEqual(expected, actual);

            expiry   = "2Y";
            tenor    = "5Y";
            expected = 6.1m;
            actual   = target.GetPPD(expiry, tenor);
            Assert.AreEqual(expected, actual);
        }
        public string PublishLpmSwaptionVolMatrix(object[][] structurePropertiesRange, object[][] publishPropertiesRange, object[][] valuesRange, object[][] rateCurveFiltersRange)
        {
            NamedValueSet structureProperties = structurePropertiesRange.ToNamedValueSet();

            object[,] values = valuesRange.ConvertArrayToMatrix();
            string[]   tenors      = Array.ConvertAll(values.GetRow(0).Skip(1).ToArray(), Convert.ToString);
            string[]   expiries    = Array.ConvertAll(values.GetColumn(0).Skip(1).ToArray(), Convert.ToString);
            object[][] dataObjects = values.GetRows(1, values.RowCount(), 1, values.ColumnCount());
            object[][] data        = dataObjects.Select(a => a.Select(b => b).ToArray()).ToArray();
            // Setup base values needed to build
            var baseDate = structureProperties.GetValue <DateTime>(CurveProp.BaseDate, false);

            if (baseDate == DateTime.MinValue)
            {
                baseDate = structureProperties.GetValue <DateTime>(CurveProp.BuildDateTime, false).Date;
                if (baseDate == DateTime.MinValue)
                {
                    baseDate = DateTime.Today;
                }
            }
            string sourceName = structureProperties.GetString("Source", true);
            string currency   = structureProperties.GetString(CurveProp.Currency1, true);
            string marketName = structureProperties.GetString(CurveProp.MarketAndDate, true);
            string indexName  = structureProperties.GetString(CurveProp.IndexName, true);
            int    year       = baseDate.Year;
            int    weekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(baseDate, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
            string id         = $"LPMSwaptionCurve.{currency}.{baseDate:yyyy-MM-dd}";
            var    ppdGrid    = new SwaptionPPDGrid(expiries, tenors, data);
            // Load underlying curve
            Market market = GetCurve(Logger.Target, Cache, NameSpace, rateCurveFiltersRange);
            Market matrix = LPMSwaptionCurve.ProcessSwaption(Logger.Target, Cache, market, ppdGrid, id, NameSpace);
            string newId  = $"{marketName}.{indexName}.Swaption.{currency}.{sourceName}.{year}.Week{weekOfYear}";
            string name   = $"Swaption-{currency}-{sourceName}-{baseDate:dd/MM/yyyy}";

            structureProperties.Set("Identifier", newId);
            structureProperties.Set("Name", name);
            // Save
            Publish(matrix, "Market." + newId, structureProperties, publishPropertiesRange);
            return(newId);
        }
예제 #3
0
        /// <summary>
        /// Process a PPD Grid. The result is a Market structure that can be published.
        /// </summary>
        /// <param name="logger">The logger</param>
        /// <param name="cache">The cache.</param>
        /// <param name="swapCurve">The latest rate curve</param>
        /// <param name="ppdGrid">The raw Points Per Day matrix supplied from the subscriber</param>
        /// <param name="id">The id to use in publishing the curve</param>
        /// <param name="nameSpace">The client namespace</param>
        /// <returns></returns>
        public static Market ProcessSwaption(ILogger logger, ICoreCache cache, Market swapCurve, SwaptionPPDGrid ppdGrid, string id, string nameSpace)
        {
            var mkt   = swapCurve;
            var curve = new SimpleRateCurve(mkt);

            // List the values so we can build our ATM vols
            var atmVols = new Dictionary <SimpleKey, decimal>();

            // Create a calendar to use to modify the date
            // default to be Sydney...
            IBusinessCalendar bc = BusinessCenterHelper.ToBusinessCalendar(cache, new[] { "AUSY" }, nameSpace); //BusinessCalendarHelper("AUSY");

            // Use some logic to get the spot date to use
            // LPM Spot lag is 2 days (mod following)
            DateTime spotDate = curve.GetSpotDate();

            // Extract each surface and build an ATM engine therefrom
            // Build a list of all possible engines
            foreach (string e in ExpiryKeys)
            {
                // Assume frequency = 4 months until 3 years tenor is reached
                Period expiration         = PeriodHelper.Parse(e);
                double expiryYearFraction = expiration.ToYearFraction();

                foreach (string t in TenorKeys)
                {
                    // Create a Swap rate for each expiry/tenor pair
                    // Assume frequency = 4 months until 3 years tenor is reached
                    double tenorYearFraction = PeriodHelper.Parse(t).ToYearFraction();
                    int    frequency         = tenorYearFraction < 4 ? 4 : 2;

                    // Calculation date
                    // Discount factors
                    // Offsets (elapsed days)
                    var rates = new SwapRate(logger, cache, nameSpace, "AUSY", curve.BaseDate, "ACT/365.FIXED", curve.GetDiscountFactors(), curve.GetDiscountFactorOffsets(), frequency, BusinessDayConventionEnum.MODFOLLOWING);

                    // Calculate the volatility given PPD and swap curve
                    DateTime expiry = bc.Roll(expiration.Add(spotDate), BusinessDayConventionEnum.FOLLOWING);
                    decimal  vol    = CalculateAtmVolatility(rates, expiry, ppdGrid, expiryYearFraction, tenorYearFraction);
                    atmVols.Add(new SimpleKey(e, t), vol);
                }
            }

            var vols = new object[atmVols.Count + 1, 3];
            var i    = 1;

            vols[0, 0] = "Expiry";
            vols[0, 1] = "Tenor";
            vols[0, 2] = "0";

            foreach (var key in atmVols.Keys)
            {
                vols[i, 0] = key.Expiry;
                vols[i, 1] = key.Tenor;
                vols[i, 2] = atmVols[key];
                i++;
            }

            DateTime buildDateTime = swapCurve.Items1[0].buildDateTime;
            var      volSurface    = new VolatilitySurface(vols, new VolatilitySurfaceIdentifier(id), curve.BaseDate, buildDateTime);

            return(CreateMarketDocument(volSurface.GetFpMLData()));
        }
예제 #4
0
        /// <summary>
        /// Calculate an ATM volatility given a Price Per Day (PPD) value and a swap curve
        /// The curve provides forward rates for the calculation
        /// </summary>
        private static decimal CalculateAtmVolatility(SwapRate rate, DateTime baseDate, SwaptionPPDGrid grid, double expiryYearFraction, double tenorYearFraction)
        {
            // Extract the forward rate
            var swapRate = rate.ComputeSwapRate(baseDate, tenorYearFraction);

            swapRate = swapRate * 100;

            // Extract the correct ppd from the grid (compensate for the swap rate being * 100)
            var ppd = grid.GetPPD(expiryYearFraction, tenorYearFraction) * 0.01m;

            // Calculate the volatility from the parameters
            var atmVolatility = (ppd * (decimal)System.Math.Sqrt(250.0)) / swapRate;

            return(atmVolatility);
        }