Пример #1
0
        //------------------------------------------------------------------------------------------------
        public SpreadSeriesBuilder(string metric, FuturesSeriesBuilder rawfuturesBuilder, SwapCurveSeriesBuilder swapBuilder,
            Dictionary<string, TimeSeriesBondStatic> bondStatics, SpreadConventions conventions, List<DateTime> holidays=null)
        //------------------------------------------------------------------------------------------------
        {

            if (holidays == null)
            {
                holidays = new List<DateTime>();
            }

            // Setup Everything
            var futuresBuilder = new FuturesSeriesBuilder(rawfuturesBuilder); //use copy constructor
            FuturesPrices = futuresBuilder.RawFuturesPrices;
            FuturesStatic = futuresBuilder.FuturesStatic;

            BondStatic = bondStatics;
            CombinedStatic = SpreadSeriesBuilder.combineFuturesAndBondStatic(BondStatic, FuturesStatic);

            if (conventions.bForecastCurve)
            {
                ForecastCurves = swapBuilder.ForecastCurves;
                DiscountCurves = swapBuilder.DiscountCurves;
            }
            else
            {
                ForecastCurves = swapBuilder.DiscountCurves;
                DiscountCurves = swapBuilder.DiscountCurves;
            }

            SpreadMetric_   = metric;
            Conv_           = conventions;

            Holidays_       = holidays;

            var rawSpreads = computeFuturesSpreads();

            // Now use this to get rolling futures too
            futuresBuilder.RawFuturesPrices = rawSpreads;
            futuresBuilder.interpolateRawPriceFrame();
            SpreadValues = futuresBuilder.getCombinedResults();

            FuturesBuilder_ = futuresBuilder;

        }
Пример #2
0
        //------------------------------------------------------------------------------------------------
        public static double calcFwdBondMeasure(string measure,
            AnalyticsBondStaticData bondstatic,
            double fwdPrice,
            DateTime asofDate, DateTime settle,
            SpreadConventions convs,
            SortedDictionary<DateTime, Tuple<DateTime,double>[]> ForecastCurves,
            SortedDictionary<DateTime, Tuple<DateTime, double>[]> DiscountCurves,
            List<DateTime> hols,
            Tuple<DateTime, double> previous = null)
            //------------------------------------------------------------------------------------------------
        {

            // Cast forecast and discount curves
            var newForecastCurves = new SortedDictionary<DateTime, DiscountFactors>(
                ForecastCurves.ToDictionary(kvp => kvp.Key, kvp => new DiscountFactors(kvp.Value)));
            var newDiscountCurves = new SortedDictionary<DateTime, DiscountFactors>(
                DiscountCurves.ToDictionary(kvp => kvp.Key, kvp => new DiscountFactors(kvp.Value)));

            // Run them through original code
            return calcFwdBondMeasure(measure,bondstatic,fwdPrice,asofDate,settle,convs,newForecastCurves,newDiscountCurves,hols,previous);

        }
Пример #3
0
        //------------------------------------------------------------------------------------------------
        public static double calcFwdBondMeasure(string measure, 
                                        AnalyticsBondStaticData bondstatic, 
                                        double fwdPrice, 
                                        DateTime asofDate, DateTime settle, 
                                        SpreadConventions convs,
                                        SortedDictionary<DateTime,DiscountFactors> ForecastCurves,
                                        SortedDictionary<DateTime, DiscountFactors> DiscountCurves,
                                        List<DateTime> hols,
                                        Tuple<DateTime,double> previous = null)
        //------------------------------------------------------------------------------------------------
        {

            //string identifier = bondstatic.Id;

            // Setup Params
            DateTime FwdDate = settle;
            DateTime effectiveDate = bondstatic.EffectiveDate;
            DateTime firstCpnDate = bondstatic.FirstCouponDate;
            DateTime maturity = bondstatic.MaturityDate; 

            double coupon = bondstatic.Coupon;

            long bondCpnFreq = bondstatic.CpnFreq;
            long fixedFreq = convs.SwapFixedFrequency;
            long floatFreq = convs.SwapFloatFrequency;
            BondAnalytics.Country eCountry = bondstatic.Country;
            BondAnalytics.DayCountType dct = convs.DayCount;
            bool bOIS = !convs.bForecastCurve;

            int blendIdx = convs.BlendIndex;

            double output = double.NaN;
            switch (measure)
            {
                case "Yield":
                    {

                        output = 10000.0 * BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[0];

                        break;
                    }
                case "TrueSpread":
                    {

                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        DiscountFactors curve = ForecastCurves[asofDate];
                        DateTime[] dfDates = curve.CurveDates;
                        double[] dfs = curve.Dfs;

                        //  Check. Sometimes (holidays) the first date on the curve can be repeated, which will cause an exception in the pricer.
                        if (dfDates[0] == dfDates[1])
                        {
                            dfDates = dfDates.GetSubArray(1, dfDates.GetLength(0)).ToArray();
                            dfs = dfs.GetSubArray(1, dfs.GetLength(0)).ToArray();
                        }
                        output = -10000.0 * BondAnalytics.SolveZSpread(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq, dfDates, dfs, hols);
                        break;

                    }
                case "MMS":
                    {
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[asofDate];
                        var forecastCurve = ForecastCurves[asofDate];

                        DateTime[] discDfDates = discountCurve.CurveDates;
                        DateTime[] fcstDfDates = forecastCurve.CurveDates;
                        double[] discDfs = discountCurve.Dfs;
                        double[] fcstDfs = forecastCurve.Dfs;

                        //double mms = BondAnalytics.CalcMMS(FwdDate, maturity, dct, fixedFreq, floatFreq, discDfDates, discDfs, fcstDfDates, fcstDfs, hols, null, null, null, null, null, firstCpnDate, blendIdx);
                        var mms = SwapAnalytics.CalcSwapRate(FwdDate, maturity, 0.0, dct, fixedFreq, dct, floatFreq, discDfDates,
                            discDfs, fcstDfDates, fcstDfs, hols, 0.0, blendIdx, bOIS ? blendIdx : 0);
                        output = 10000.0 * mms;
                        break;

                    }
                case "Spread":
                    {
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[asofDate];
                        var forecastCurve = ForecastCurves[asofDate];

                        DateTime[] discDfDates = discountCurve.CurveDates;
                        DateTime[] fcstDfDates = forecastCurve.CurveDates;
                        double[] discDfs = discountCurve.Dfs;
                        double[] fcstDfs = forecastCurve.Dfs;

                        var mms = SwapAnalytics.CalcSwapRate(FwdDate, maturity, 0.0, dct, fixedFreq, dct, floatFreq, discDfDates,
                            discDfs, fcstDfDates, fcstDfs, hols, 0.0, blendIdx, bOIS ? blendIdx : 0);
                        double yield = 0.0;

                        yield = BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[0];

                        output = 10000.0 * (mms - yield);
                        break;

                    }

                case "FuturesDV01":
                    {

                        double previous_price = double.NaN;
                        if (previous != null)
                        {
                            previous_price = previous.Item2;
                        }


                        // Get the CTD Bond DV01 here
                        double dv01 = BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[1] / 1000000 * 100;

                        // Get next price
                        output = dv01;
                        break;
                    }

                case "MMSDV01":
                    {
                        // Setup current swap curve
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[asofDate];
                        var forecastCurve = ForecastCurves[asofDate];

                        double rate = BondAnalytics.CalcMMS(FwdDate, maturity, dct, fixedFreq, floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates, forecastCurve.Dfs, hols, null, null, null, null, null, firstCpnDate, blendIdx);

                        // Get Current DV01
                        double dv01 = SwapAnalytics.CalcSwapDv01(FwdDate, maturity, 1, rate, dct, dct, fixedFreq,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);

                        // DV01 adjusted PnL
                        output = dv01 * 100; // 100 Notional Terms here

                        break;
                    }


                case "FuturesPnlDV01Adj":
                    {

                        double previous_fwdprice = double.NaN;
                        if (previous != null)
                        {
                            previous_fwdprice = previous.Item2;
                        }


                        // Get the CTD Bond DV01 here
                        double dv01 = BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[1] / 1000000 * 100;

                        // Get next price
                        output = (fwdPrice - previous_fwdprice)  / Math.Abs(dv01); //Normalise into 100 par terms

                        break;
                    }
                case "FuturesPnl":
                    {

                        double previous_fwdprice = double.NaN;
                        if (previous != null)
                        {
                            previous_fwdprice = previous.Item2;
                        }

                        // PnL in notional terms
                        output = fwdPrice - previous_fwdprice; // Actual pnl is given by price change of the CTD bond

                        break;
                    }
                case "SwapPnl":
                    {
                        // Previous date, curve to get original MMS rate
                        DateTime previousDate = DateTime.MinValue;
                        if (previous != null)
                        {
                            previousDate = previous.Item1;
                        }

                        if (!ForecastCurves.ContainsKey(previousDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[previousDate];
                        var forecastCurve = ForecastCurves[previousDate];

                        double previouRate = BondAnalytics.CalcMMS(FwdDate, maturity, dct, fixedFreq, floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates, forecastCurve.Dfs, hols, null, null, null, null, null, firstCpnDate, blendIdx);
                        previouRate *= 100; // For cents
                        // Setup current swap curve
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        discountCurve = DiscountCurves[asofDate];
                        forecastCurve = ForecastCurves[asofDate];

                        // Get PnL of rate
                        //priceSwap(DateTime startDate, DateTime endDate, int payRec, double fixedRate, BondAnalytics.DayCountType fixedDctType, long fixedFreq, double floatSpread, BondAnalytics.DayCountType floatDctType, long floatFreq, DateTime[] discCurveDates, double[] discDfs, DateTime[] fcstCurveDates, double[] fcstDfs, List<DateTime> holidays, double lastFixing = 0.0, int blendIndexD = 0, int blendIndexF = 0, bool incPrin = false)
                        double pnl = SwapAnalytics.PriceSwap(FwdDate, maturity, 1, previouRate, dct, fixedFreq, 0.0, dct,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);

                        // Raw PnL innotional terms
                        output = pnl * 100;  // pnl in cents

                        break;
                    }

                case "SwapPnlDV01Adj":
                    {

                        // Previous date, curve to get original MMS rate
                        DateTime previousDate = DateTime.MinValue;
                        if (previous != null)
                        {
                            previousDate = previous.Item1;
                        }

                        if (!ForecastCurves.ContainsKey(previousDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[previousDate];
                        var forecastCurve = ForecastCurves[previousDate];

                        double previousRate = BondAnalytics.CalcMMS(FwdDate, maturity, dct, fixedFreq, floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates, forecastCurve.Dfs, hols, null, null, null, null, null, firstCpnDate, blendIdx);

                        previousRate *= 100; // To put this into cents

                        // Setup current swap curve
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        discountCurve = DiscountCurves[asofDate];
                        forecastCurve = ForecastCurves[asofDate];

                        // Get PnL of rate
                        double pnl = SwapAnalytics.PriceSwap(FwdDate, maturity, 1, previousRate, dct, fixedFreq, 0.0, dct,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);

                        // Get Current DV01
                        double dv01 = SwapAnalytics.CalcSwapDv01(FwdDate, maturity, 1, previousRate, dct, dct, fixedFreq,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);

                        // DV01 adjusted PnL
                        output = pnl / Math.Abs(dv01); // 100 Notional Terms here

                        break;
                    }
                case "SpreadPnlDV01Adj":
                    {
                        // FUTURES.
                        double previous_fwdprice = double.NaN;
                        if (previous != null)
                        {
                            previous_fwdprice = previous.Item2;
                        }


                        // Get the CTD Bond DV01 here
                        double dv01 = BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[1] / 1000000 * 100;

                        // Get next price
                        double futures01AdjPnl = (fwdPrice - previous_fwdprice) / Math.Abs(dv01);

                        // SWAP.
                        // Previous date, curve to get original MMS rate
                        DateTime previousDate = DateTime.MinValue;
                        if (previous != null)
                        {
                            previousDate = previous.Item1;
                        }

                        if (!ForecastCurves.ContainsKey(previousDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[previousDate];
                        var forecastCurve = ForecastCurves[previousDate];

                        double previousRate = BondAnalytics.CalcMMS(FwdDate, maturity, dct, fixedFreq, floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates, forecastCurve.Dfs, hols, null, null, null, null, null, firstCpnDate, blendIdx);
                        previousRate *= 100; // To put in cents

                        // Setup current swap curve
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        discountCurve = DiscountCurves[asofDate];
                        forecastCurve = ForecastCurves[asofDate];

                        // Get PnL of rate
                        double pnl = SwapAnalytics.PriceSwap(FwdDate, maturity, 1, previousRate, dct, fixedFreq, 0.0, dct,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);

                        // Get Current DV01
                        dv01 = SwapAnalytics.CalcSwapDv01(FwdDate, maturity, 1, previousRate, dct, dct, fixedFreq,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);

                        // DV01 adjusted PnL
                        double swap01AdjPnl = pnl / Math.Abs(dv01); // Notional Terms here

                        output = swap01AdjPnl - futures01AdjPnl;

                        break;
                    }
                case "SpreadHedgeRatio":
                    {

                        // Get Bond DV01
                        double previous_price = double.NaN;
                        if (previous != null)
                        {
                            previous_price = previous.Item2;
                        }


                        // Get the CTD Bond DV01 here
                        double futuresDv01 = BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[1] / 1000000;// Match futures notional (1mil notional. prices in cents)
                        // Setup current swap curve
                        if (!ForecastCurves.ContainsKey(asofDate))
                        {
                            output = double.NaN;
                            break;
                        }

                        var discountCurve = DiscountCurves[asofDate];
                        var forecastCurve = ForecastCurves[asofDate];

                        double mms = BondAnalytics.CalcMMS(FwdDate, maturity, dct, fixedFreq, floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates, forecastCurve.Dfs, hols, null, null, null, null, null, firstCpnDate, blendIdx);
                        mms *= 100;

                        // Get Swap DV01
                        double swapDv01 = SwapAnalytics.CalcSwapDv01(FwdDate, maturity, 1, mms, dct, dct, fixedFreq,
                            floatFreq, discountCurve.CurveDates, discountCurve.Dfs, forecastCurve.CurveDates,
                            forecastCurve.Dfs, hols);


                        output = Math.Abs(futuresDv01) / Math.Abs(swapDv01);

                        break;
                    }
            }

            return output;

        }
Пример #4
0
        //----------------------------------------------------------------------------------------
        public static Frame<DateTime, String> GenerateInvoiceSpreadTRS(
                    List<string> tickers, 
                    DateTime start,  
                    DateTime end,         
                    string countryCode, 
                    string pnlType = "InvoiceSpread",
                    bool bCumulative = true,
                    bool bOIS = true,
                    string samplingFreq= "1b",   
                    string rollMethod = "FirstNoticeDate", 
                    string holcal = "",
                    double notional = double.NaN,
                    ICarbonClient client = null)
        //----------------------------------------------------------------------------------------
        {
            var eRollMethod         = TimeSeriesUtilities.GetRollMethods(rollMethod);
            var eInterpolationTypes = TimeSeriesUtilities.GetInterpolationType("None");
            var eSmoothingTypes     = TimeSeriesUtilities.GetSmoothingTypes("None"); // Don't smooth, doesn't make sense for PnL
            bool bForecastCurve     = !bOIS;

            /* CARBON REQUIRES UTC TIME - MODIFY DATES TO ACCOMODATE */
            start = new DateTime(start.Year, start.Month, start.Day, 0, 0, 0, DateTimeKind.Utc);
            end = new DateTime(end.Year, end.Month, end.Day, 0, 0, 0, DateTimeKind.Utc);

            #region cache
            string all_tickers = ";";
            foreach (var s in tickers) all_tickers += s;

            string cacheKey = "GenerateInvoiceSpread" + tickers.ToString() + start.ToString() + end.ToString() +
                              countryCode + pnlType + bCumulative.ToString() + bOIS.ToString() + samplingFreq +
                              rollMethod + holcal + notional.ToString();

            if (TimeSeriesCache.ContainsKey(cacheKey))
            {
                return TimeSeriesCache[cacheKey];
            }
            #endregion
            if (client == null)
            {
                throw new ArgumentException("No Carbon Client!");
            }
            
            #region MeasureSetup

            string swapMeasure = "";
            string futMeasure = "";
            string ratio = "";
            bool bDefaultNoCumulative = false;
            switch (pnlType)
            {

                case "InvoiceSpread":
                    if (double.IsNaN(notional)) // work in DV01 terms
                    {
                        swapMeasure = "SwapPnlDV01Adj";
                        futMeasure = "FuturesPnlDV01Adj";
                    }
                    else
                    {
                        swapMeasure = "SwapPnl";
                        futMeasure = "FuturesPnl";
                        //ratio = "SpreadHedgeRatio"; // required to construct the correct pnl
                    }
                    
                    break;
                case "Futures":
                    if (double.IsNaN(notional)) // work in DV01 terms
                    {
                        swapMeasure = "";
                        futMeasure = "FuturesPnlDV01Adj";
                    }
                    else
                    {
                        swapMeasure = "";
                        futMeasure = "FuturesPnl";
                    }
                    break;
                case "MMS":
                    if (double.IsNaN(notional)) // work in DV01 terms
                    {
                        swapMeasure = "SwapPnlDV01Adj";
                        futMeasure = "";
                    }
                    else
                    {
                        swapMeasure = "SwapPnl";
                        futMeasure = "";
                    }
                    break;

                case "MMSDV01":
                    swapMeasure = "MMSDV01";
                    futMeasure = "";
                    bDefaultNoCumulative = true;
                    break;

                case "FuturesDV01":
                    swapMeasure = "FuturesDV01";
                    futMeasure = "";
                    bDefaultNoCumulative = true;
                    break;

                case "HedgeRatio":
                    swapMeasure = "SpreadHedgeRatio";
                    futMeasure = "";
                    bDefaultNoCumulative = true;
                    break;

                default:
                    throw new ArgumentException("");
            }
            #endregion

            #region Configs
            
            SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs(countryCode, !bOIS);

            string ccy = config.ccy;
            string calendarcode = (holcal != "") ? holcal : config.calendarcode;
            string futuresStaticMoniker = config.futuresStaticMoniker;
            string carbonEnv = config.carbonEnv;
            BondAnalytics.Country country = config.country;
            BondAnalytics.DayCountType dct = config.dct;
            long swpfixfreq = config.swpfixfreq;
            long swpfloatfreq = config.swpfloatfreq;
            long bndCouponFreq = config.bndCouponFreq;
            int BlendIndex = config.BlendIndex;
            string symForecastCurveName = config.SymForecastCurveName;
            string symDiscountCurveName = config.SymDiscountCurveName;
            List<string> contractSortOrder = config.contractSortOrder;

            List<DateTime> holidays = TimeSeriesUtilities.GetHolidays(calendarcode, client);

            #endregion

            var dateRange = TimeSeriesUtilities.GetAllDatesInDateime(start, end, calendarcode, client, samplingFreq);

            // Spread Static.
            SpreadConventions
                spreadconventions = new SpreadConventions(country, dct, swpfixfreq, swpfloatfreq, bndCouponFreq, bForecastCurve, BlendIndex);

            // Futures.
            FuturesSeriesBuilder
                   seriesBuilder = new FuturesSeriesBuilder(tickers, dateRange, holidays, futuresStaticMoniker, client, carbonEnv, rollMthd: eRollMethod, interpType: eInterpolationTypes, contractSortOrder: contractSortOrder, smoothingType: eSmoothingTypes);
            
            // Bond Static
            var bndStatics = TimeSeriesUtilities.GetBondStaticsFromFuturesBuilder(seriesBuilder, config, client);

            // Swap Curves
            var curves = TimeSeriesUtilities.GetCurvesFromCarbon(dateRange, ccy, client);

            if (curves == null || bndStatics == null) return null;

            var forecastCurves = curves.Item1;
            var discountCurves = curves.Item2;

            SwapCurveSeriesBuilder
                    swapBuilder = new SwapCurveSeriesBuilder(dateRange, symForecastCurveName, symDiscountCurveName, ccy, holidays, forecastCurves, discountCurves, client);

            // Generate Pnls
            Frame<DateTime,string> swapPnl = null;
            Frame<DateTime, string> futPnl = null;
            
            if (swapMeasure != "")
            {
                SpreadSeriesBuilder swapPnlBuilder = new SpreadSeriesBuilder(swapMeasure, seriesBuilder, swapBuilder,
                    bndStatics, spreadconventions, holidays);
                    
                swapPnl = swapPnlBuilder.SpreadValues;
            }
            if (futMeasure != "")
            {
                SpreadSeriesBuilder futPnlBuilder = new SpreadSeriesBuilder(futMeasure, seriesBuilder, swapBuilder,
                    bndStatics, spreadconventions, holidays);

                futPnl = futPnlBuilder.SpreadValues;
            }

            // Setup pnl correctly
            Frame<DateTime, string> pnl;
            if ( (swapPnl != null) && (futPnl != null))
            {
                // This allows it to match movements on the invoice spread chart.
                // Long TRS = pay fixed, long bond
                // Spread increases, mms increases, yield decreases -> swap/bond +ve pnl

                pnl = futPnl - swapPnl; 
            }
            else if (swapPnl != null)
            {
                pnl = swapPnl;
            }
            else
            {
                pnl = futPnl;
            }

           
           
            // Make it cumulative if flagged, but not for hedge ratios etc
            if (bCumulative && !bDefaultNoCumulative)
            {
                pnl = pnl.SortRowsByKey(); // in case
                pnl = TimeSeriesUtilities.DeedleFrameCumsum(pnl);
            }

            //Notional Adjust this thing
            if (!double.IsNaN(notional) && pnlType!="HedgeRatio")
            {
                pnl *= notional/100; // Default 100
            }
            

            TimeSeriesCache[cacheKey] = pnl;

            return pnl;

        }
Пример #5
0
        //----------------------------------------------------------------------------------------
        public static Frame<DateTime, String> GenerateRollingBondForwardSeries(
            List<string> tickers,
            DateTime start,
            DateTime end,
            string tenor,
            string countryCode,
            string measure,
            string holidayCode,
            bool bOIS = true,
            int optExDivDays = 0,
            bool bSpreadOrRepo = true,
            List<double> reposOrSpreads = null, 
            ICarbonClient client = null)
        //----------------------------------------------------------------------------------------
        {

            // Checks
            if (client == null) 
            {
                throw new ArgumentException("No Carbon Client!");
            }
            
            
            #region cache
            string all_tickers = ";";
            foreach (var s in tickers) all_tickers += s;
            string allRepoOis = "";
            if (reposOrSpreads != null)
                foreach (var s in reposOrSpreads) allRepoOis+= s;

            string cacheKey = "GenerateRollingBondForwardSeries" + tickers.ToString() + start.ToString() + end.ToString() +
                              tenor + countryCode + measure + holidayCode + bOIS.ToString() 
                              + optExDivDays.ToString() + bSpreadOrRepo.ToString() + allRepoOis;

            if (TimeSeriesCache.ContainsKey(cacheKey))
            {
                return TimeSeriesCache[cacheKey];
            }
            #endregion
            
            #region Checks
            if (start >end) throw new ArgumentException("#Error: start date cannot be after end date");
            #endregion

            var settings = new List<Tuple<string/*moniker*/, string/*tickercol*/, string/*pricecol*/>>();

            // Get Configs
            foreach (var ticker in tickers)
            {
                if (ticker.Contains('.')) // it's a CTD series!
                {
                    settings.Add(MonikerConfigs.getCTDMoniker(countryCode,ticker,client));
                }
                else if (ticker.ToLower().Contains("ct"))
                {
                    settings.Add(MonikerConfigs.getCTMoniker(countryCode, ticker, client));
                }
                else
                {
                    throw new ArgumentException("#Error: Invalid ticker found - " + ticker);
                }
            }

            #region DATA
            bool bHaveEverything    = true;
            var configs             = new SpreadTimeSeriesConfigs(countryCode, !bOIS);
            var spreadConventions   = new SpreadConventions(configs);
            var dateRange           = TimeSeriesUtilities.GetAllDatesInDateime(start, end, configs.calendarcode, client, "1b"); // Force daily sampling
            var fwdDates            = dateRange.Select(dte => dte.AddTenor(Tenor.FromString(tenor))).ToList();
            var holidays            = TimeSeriesUtilities.GetHolidays(holidayCode,client);


            // Parcel input repo rates or spreads
            Series<DateTime, double> inputSrs = null;
            if (reposOrSpreads != null )
                if (reposOrSpreads.Count != dateRange.Count && reposOrSpreads.Count != 1)
                {
                    throw new ArgumentException("#Error: number of spreads or rates do not much the days in range");
                }
                else
                {
                    var sb = new SeriesBuilder<DateTime, double>();
                    double scale_factor = bSpreadOrRepo ? 10000 : 1;
                    for (int i = 0; i < dateRange.Count; ++i)
                    {
                        if (reposOrSpreads.Count == 1)
                        {
                            sb.Add(dateRange[i], reposOrSpreads[0]/scale_factor);
                        }
                        else
                        {
                            sb.Add(dateRange[i], reposOrSpreads[i]/scale_factor);
                        }
                    }
                    inputSrs = sb.Series;
                }


            // Swap Curves
            var curves = TimeSeriesUtilities.GetCurvesFromCarbon(dateRange, configs.ccy, client);
            if (curves == null) bHaveEverything = false;


            // Prices and tickers from ad-hoc persistence
            var frames = new Dictionary<string, Frame<DateTime, string>>();
            
            for (int i = 0; i < tickers.Count; ++i)
            {
                var setting = settings[i];
                var ticker  = tickers[i];
                var moniker = setting.Item1;
                var tickercol = setting.Item2;
                var pricecol = setting.Item3;

                var tmp_df = client.GetFrameAsync<DateTime>(moniker, "AdHocData").Result;
                if (tmp_df == null)
                {
                    bHaveEverything = false;
                }
                else
                {
                    // Extract price and ticker cols only
                    var colsOfInterest = new Dictionary<string, Series<DateTime,object>>();

                    // Filter data to contain date range
                    tmp_df = tmp_df.Where(kvp => (kvp.Key >= start) && (kvp.Key <= end));

                    colsOfInterest["price"] = tmp_df.GetColumn<object>(pricecol);
                    colsOfInterest["isin"] = tmp_df.GetColumn<object>(tickercol);

                    frames[ticker] = Frame.FromColumns(colsOfInterest);
                }
            }

            //Bond static
            var bondIsinSet = new HashSet<string>();
            foreach(var kvp in frames)
            {
                var ticker  = kvp.Key;
                var data    = kvp.Value;

                var isins = data.GetColumn<string>("isin").Values;

                //isins.Select(isin => bondIsinSet.Add(isin));
                foreach (string isin in isins)
                {
                    bondIsinSet.Add(isin);
                }
            }
   
            var bondStatics = client.BulkGetBondStaticData( bondIsinSet.ToList());
            if (curves == null || bondStatics == null ) return null;
            #endregion

            #region RepoRegion
            Series<DateTime, double> repoSrs = null;
            if (reposOrSpreads == null)
            {
                // Load default repo-OIS Spread
                double[,] repoRates =
                    client.GetRepoRateFromSavedRepoOisSpread(BondAnalytics.CountryMappings[countryCode], dateRange,
                        fwdDates, holidays);

                // Break out if no data
                if (repoRates == null) return null;

                var repoSrsBlder = new SeriesBuilder<DateTime, double>();
                for (int i = 0; i < dateRange.Count; ++i)
                {
                    repoSrsBlder.Add(dateRange[i], repoRates[i, 1]);
                }
                repoSrs = repoSrsBlder.Series;
            }

            else
            {
                // User-defined repo-OIS Spread or repo rates
                if (bSpreadOrRepo)
                {
                    //Inputs are spreads
                    double[,] repoRates =
                    client.CalcRepoRatesFromOisSpread(inputSrs, BondAnalytics.CountryMappings[countryCode], dateRange, fwdDates, holidays);

                    // Break out if no data
                    if (repoRates == null) return null;

                    var repoSrsBlder = new SeriesBuilder<DateTime, double>();
                    for (int i = 0; i < dateRange.Count; ++i)
                    {
                        repoSrsBlder.Add(dateRange[i], repoRates[i, 1]);
                    }
                    repoSrs = repoSrsBlder.Series;
                }
                else
                {
                    //Inputs are repo rates
                    repoSrs = inputSrs;
                }
            }

            #endregion

            // Calculation loop
            var forecastCurves = curves.Item1;
            var discountCurves = curves.Item2;

            // Overwrite forecast curve if we want OIS
            if (bOIS)
            {
                forecastCurves = discountCurves;
            }

            var outputs = new Dictionary<string, Series<DateTime, double>> ();

            foreach (string ticker in tickers)
            {
                var sb = new SeriesBuilder<DateTime, double>();
                var df = frames[ticker];

                var idx = df.RowKeys;

                var isins   = df.GetColumn<string>("isin");
                var prices  = df.GetColumn<double>("price");
                
                foreach (var dte in idx)
                {
                    var tryisin = isins.TryGet(dte);
                    var tryprice = prices.TryGet(dte);
                    var tryrepo = repoSrs.TryGet(dte);

                    if (!tryprice.HasValue || !tryisin.HasValue || !tryrepo.HasValue)
                        continue;

                    var isin    = tryisin.Value;
                    var price   = tryprice.Value;
                    var repo    = tryrepo.Value;
                    var fwddate = dte.AddTenor(Tenor.FromString(tenor));
                    var bondstatic  = bondStatics[isin];
                    double value = double.NaN;

                    if (measure == "Repo")
                    {
                        value = repo;
                    }
                    
                    else
                    {
                        var fwdprice = BondAnalytics.CalcBondFwd(configs.country, dte, price, bondstatic.EffectiveDate,
                            bondstatic.FirstCouponDate, bondstatic.MaturityDate, bondstatic.Coupon, bondstatic.CpnFreq,
                            fwddate, repo, optExDivDays)[0];

                        if (measure == "Price")
                        {
                            value = fwdprice;
                        }
                        else
                        {
                            value = MeasureCalculator.calcFwdBondMeasure(measure, bondstatic, fwdprice, dte, fwddate,
                                spreadConventions, forecastCurves, discountCurves, holidays);
                        }
                    }

                    sb.Add(dte,value);
                }

                outputs[ticker] = sb.Series;
            }

            var consolidatedMeasures = Frame.FromColumns(outputs);

            // Cache results
            TimeSeriesCache[cacheKey] = consolidatedMeasures;

            return consolidatedMeasures;
        }
         //---------------------------------------------------------------------------------------------------------
         //[Test]
         public void SpreadSeriesToArrayTests()
        //---------------------------------------------------------------------------------------------------------
         {
             // Params.
             DateTime start = new DateTime(2016, 2, 28);
             DateTime end = new DateTime(2016, 3, 18);
             List<String> tickers = new List<string>() { "TUH6", "TUM6", "TUU6" };
             string samplingFreq = "1b";

             // Default Configs
             SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs("US");
             string forecastCurveName = config.forecastCurveName;
             string discountCurveName = config.discountCurveName;
             string ccy = config.ccy;
             string calendarcode = config.calendarcode;
             string futuresStaticMoniker = config.futuresStaticMoniker;
             string carbonEnv = config.carbonEnv;
             BondAnalytics.Country country = config.country;
             BondAnalytics.DayCountType dct = config.dct;
             long swpfixfreq = config.swpfixfreq;
             long swpfloatfreq = config.swpfloatfreq;
             long bndCouponFreq = config.bndCouponFreq;
             int BlendIndex = config.BlendIndex;
             bool bForecastCurve = true;

             // Bond Static
             Dictionary<string, TimeSeriesBondStatic> bondstatic = new Dictionary<string, TimeSeriesBondStatic>()
             {
                 {"US912828G799", new TimeSeriesBondStatic("US912828G799", new DateTime(2017,12,15), new DateTime(2015,12,15),DateTime.MinValue,1.0)},
                 {"US912828J686", new TimeSeriesBondStatic("US912828J686", new DateTime(2018,03,15), new DateTime(2015,03,16),DateTime.MinValue,1.0)},
                 {"US912828VK31", new TimeSeriesBondStatic("US912828VK31", new DateTime(2018,06,30), new DateTime(2015,07,01),DateTime.MinValue,1.0)}
             };


             //Spread Static
             SpreadConventions spreadconventions = new SpreadConventions(country, dct, swpfixfreq, swpfloatfreq, bndCouponFreq, bForecastCurve, BlendIndex);


             // Dates
             var holidays = new List<DateTime>();
             var dateRange = new List<DateTime>();

             using (var client = new CarbonClient(carbonEnv))
             {

                 // Holidays
                 if (calendarcode != "")
                 {
                     var nodaHols = client.GetCalendarAsync(calendarcode).Result.Dates;

                     foreach (LocalDate hol in nodaHols)
                     {
                         holidays.Add(hol.ToDateTime());
                     }
                 }

                 // DateRange
                 DateTime startDate = start.AddTenor(Tenor.FromString("1b"), "").AddTenor(Tenor.FromString("-1b"), "");
                 DateTime nextDate = end.AddTenor(Tenor.FromString("1b"), "").AddTenor(Tenor.FromString("-1b"), "");
                 //TimeSpan EOD = new TimeSpan(23, 59, 59);
                 /*if (startDate > nextDate)
                 {
                     return "Error! Bad Inputs!";
                 }*/
                 var tenor = Tenor.FromString("-" + samplingFreq);
                 while (nextDate >= startDate)
                 {
                     dateRange.Add(nextDate);
                     nextDate = BondAnalytics.PrevBusDay(nextDate.AddTenor(tenor, ""), holidays);
                 }

             }

             //Swap.
             var swapBuilder = new SwapCurveSeriesBuilder(dateRange, forecastCurveName, discountCurveName, ccy, holidays, mCarbonClient);
             swapBuilder.buildAllCurves();

             // Futures.
             var seriesBuilder = new FuturesSeriesBuilder(tickers, dateRange, holidays, futuresStaticMoniker, mCarbonClient, carbonEnv);

             // Spread Series.
             Dictionary<string, double> testVals = new Dictionary<string, double>()
             {
                 {"Price", 109.1015625},
                 {"Yield", 0.009007303 * 10000},
                 {"TrueSpread",6.7788999},
                 {"MMS", 0.009689381* 10000},
                 {"Spread", 6.820787365}
             };


             Dictionary<string /*metric*/, SpreadSeriesBuilder /*builder*/> spreadbuildermap = new Dictionary<string, SpreadSeriesBuilder>();

             SpreadSeriesBuilder output = null;
             foreach (var metric in testVals.Keys.ToList())
             {
                 output = new SpreadSeriesBuilder(metric, seriesBuilder, swapBuilder, bondstatic, spreadconventions);
                 Console.WriteLine(metric + " :");
                 output.SpreadValues.Print();

                 var row = output.SpreadValues.GetRow<double>(new DateTime(2016, 03, 18));

                 double TUM6 = row.Get("TUM6");
                 double error = Math.Abs(TUM6 - testVals[metric]);
                 Assert.LessOrEqual(error, Math.Pow(10, -3) * 5, "Error found in " + metric + ", test: " + testVals[metric].ToString() + ", actual: " + TUM6.ToString());  // 0.005bps

                 Console.WriteLine("Error :{0}", error);
             }

             // Now let's look at converting this to an array
             if (output != null)
             {
                 var objArr = output.getSpreadAsObjArr();
             }


         }
         //---------------------------------------------------------------------------------------------------------
         //[Test]
         public void SpreadSeries()
         //---------------------------------------------------------------------------------------------------------
         {
             
             // Params.
             DateTime start = new DateTime(2016, 2, 28);
             DateTime end = new DateTime(2016, 3, 18);
             List<String> tickers = new List<string>() { "TUH6", "TUM6", "TUU6","TU.Front" };

             // Default Configs
             SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs("US");
             string forecastCurveName       = config.forecastCurveName;
             string discountCurveName       = config.discountCurveName;
             string ccy                     = config.ccy;
             string calendarcode            = config.calendarcode;
             string futuresStaticMoniker    = config.futuresStaticMoniker;
             string carbonEnv               = config.carbonEnv;
             BondAnalytics.Country country  = config.country;
             BondAnalytics.DayCountType dct = config.dct;
             long swpfixfreq                = config.swpfixfreq;
             long swpfloatfreq              = config.swpfloatfreq;
             long bndCouponFreq             = config.bndCouponFreq;
             int BlendIndex                 = config.BlendIndex;
             bool bForecastCurve = true;

             // Bond Static
             Dictionary<string, TimeSeriesBondStatic> bondstatic = new Dictionary<string, TimeSeriesBondStatic>()
             {
                 {"US912828G799", new TimeSeriesBondStatic("US912828G799", new DateTime(2017,12,15), new DateTime(2015,12,15),DateTime.MinValue,1.0)},
                 {"US912828J686", new TimeSeriesBondStatic("US912828J686", new DateTime(2018,03,15), new DateTime(2015,03,16),DateTime.MinValue,1.0)},
                 {"US912828VK31", new TimeSeriesBondStatic("US912828VK31", new DateTime(2018,06,30), new DateTime(2015,07,01),DateTime.MinValue,1.0)}
             };

             //Spread Static
             SpreadConventions spreadconventions = new SpreadConventions(country,dct,swpfixfreq,swpfloatfreq,bndCouponFreq,bForecastCurve,BlendIndex);

             //Swap.
             var swapBuilder = new SwapCurveSeriesBuilder(start, end, forecastCurveName, discountCurveName, ccy, mCarbonClient, calendarcode);
             swapBuilder.buildAllCurves();
             //swapBuilder.DiscountCurves[new DateTime(2016, 03, 18)].PrintDump();
             swapBuilder.ForecastCurves[new DateTime(2016, 03, 18)].PrintDump();
             // Futures.
             var seriesBuilder                  = new FuturesSeriesBuilder(tickers, start, end, calendarcode, futuresStaticMoniker, mCarbonClient,carbonEnv);
             
             // Spread Series.
             Dictionary<string, double> testVals = new Dictionary<string, double>()
             {
                 {"Price", 109.1015625},
                 {"Yield", 0.009007303 * 10000},
                 {"TrueSpread",6.7788999},
                 {"MMS", 0.009689381* 10000},
                 {"Spread", 6.820787365}
             };


             Dictionary<string /*metric*/, SpreadSeriesBuilder /*builder*/> spreadbuildermap = new Dictionary<string, SpreadSeriesBuilder>();
             SpreadSeriesBuilder output = null;
             foreach (var metric in testVals.Keys.ToList())
             {
                 output = new SpreadSeriesBuilder(metric, seriesBuilder, swapBuilder, bondstatic, spreadconventions);
                 Console.WriteLine(metric + " :");
                 output.SpreadValues.Print();

                 var row = output.SpreadValues.GetRow<double>(new DateTime(2016, 03, 18));

                 double TUM6 = row.Get("TUM6");
                 double error = Math.Abs(TUM6 - testVals[metric]);
                 Assert.LessOrEqual(error, Math.Pow(10, -3) * 5, "Error found in " + metric + ", test: " + testVals[metric].ToString() + ", actual: " + TUM6.ToString());  // 0.005bps

                 Console.WriteLine("Error :{0}", error);
             }            


             // Now let's try to index 1 Mar
             if (output != null)
             {
                 var spreadVals = output.SpreadValues;
                 var myList = spreadVals.RowKeys.ToList();
                 Console.WriteLine("Key List: {0}", myList);

                 // Try on individual series
                 Dictionary<string/*colname*/, Series<DateTime,object>/*actualsrs*/> tmp = new Dictionary<string, Series<DateTime, object>>();

                 foreach (string colname in spreadVals.ColumnKeys)
                 {
                     tmp[colname] = spreadVals.Columns[colname].FillMissing("#N/A");
                 }

                 spreadVals = Frame.FromColumns(tmp);

                 //spreadVals.FillMissing("#N/A").Print();
                 var row = spreadVals.GetRow<string>(new DateTime(2016, 03, 01));
                 Console.WriteLine("Row values");
                 row.Print();

             }
         }