Ejemplo n.º 1
0
        public static MarketDatum ParseMarketDatum(Date asof, string datumName, double value)
        {
            List <string> tokens = datumName.Split('/').ToList();

            Utils.QL_REQUIRE(tokens.Count > 2, () => "more than 2 tokens expected in " + datumName);

            MarketDatum.InstrumentType instrumentType = ParseInstrumentType(tokens[0]);
            MarketDatum.QuoteType      quoteType      = ParseQuoteType(tokens[1]);

            switch (instrumentType)
            {
            case MarketDatum.InstrumentType.ZERO:
            {
                //ZERO / RATE / EUR / EUR1D / A365 / 1Y
                Utils.QL_REQUIRE(quoteType == MarketDatum.QuoteType.RATE || quoteType == MarketDatum.QuoteType.YIELD_SPREAD, () => "Invalid quote type for " + datumName);
                Utils.QL_REQUIRE(tokens.Count == 6, () => "6 tokens expected in " + datumName);
                string     ccy = tokens[2];
                DayCounter dc  = Parsers.ParseDayCounter(tokens[4]);
                // token 5 can be a date, or tenor
                Date   date   = new Date();
                Period tenor  = new Period();
                bool   isDate = false;
                Parsers.ParseDateOrPeriod(tokens[5], date, tenor, out isDate);
                return(new ZeroQuote(value, asof, datumName, quoteType, ccy, date, dc, tenor));
            }

            case MarketDatum.InstrumentType.DISCOUNT:
            {
                // DISCOUNT/RATE/EUR/EUR1D/1Y
                // DISCOUNT/RATE/EUR/EUR1D/2016-12-15
                Utils.QL_REQUIRE(tokens.Count == 5, () => "5 tokens expected in " + datumName);
                string ccy = tokens[2];
                // token 4 can be a date, or tenor
                Date   date   = new Date();
                Period tenor  = new Period();
                bool   isDate = false;
                Parsers.ParseDateOrPeriod(tokens[4], date, tenor, out isDate);
                if (!isDate)
                {
                    // we can't assume any calendar here, so we do the minimal adjustment with a weekend only calendar
                    Utils.QL_REQUIRE(tenor != null, () => "neither date nor tenor recognised");
                    date = new WeekendsOnly().adjust(asof + tenor);
                }
                return(new DiscountQuote(value, asof, datumName, quoteType, ccy, date));
            }

            //case MarketDatum.InstrumentType.MM:
            //    {
            //        QL_REQUIRE(tokens.size() == 5, "5 tokens expected in " << datumName);
            //        const string&ccy = tokens[2];
            //        Period fwdStart = parsePeriod(tokens[3]);
            //        Period term = parsePeriod(tokens[4]);
            //        return boost::make_shared<MoneyMarketQuote>(value, asof, datumName, quoteType, ccy, fwdStart, term);
            //    }

            //case MarketDatum.InstrumentType.MM_FUTURE:
            //    {
            //        QL_REQUIRE(tokens.size() == 6, "6 tokens expected in " << datumName);
            //        const string&ccy = tokens[2];
            //        const string&expiry = tokens[3];
            //        const string&contract = tokens[4];
            //        Period term = parsePeriod(tokens[5]);
            //        return boost::make_shared<MMFutureQuote>(value, asof, datumName, quoteType, ccy, expiry, contract, term);
            //    }

            case MarketDatum.InstrumentType.FRA:
            {
                Utils.QL_REQUIRE(tokens.Count == 5, () => "5 tokens expected in " + datumName);
                string ccy      = tokens[2];
                Period fwdStart = Parsers.ParsePeriod(tokens[3]);
                Period term     = Parsers.ParsePeriod(tokens[4]);
                return(new FRAQuote(value, asof, datumName, quoteType, ccy, fwdStart, term));
            }

            //case MarketDatum.InstrumentType.IMM_FRA:
            //    {
            //        QL_REQUIRE(tokens.size() == 5, "5 tokens expected in " << datumName);
            //        const string&ccy = tokens[2];
            //        string imm1 = tokens[3];
            //        string imm2 = tokens[4];
            //        unsigned int m1 = parseInteger(imm1);
            //        unsigned int m2 = parseInteger(imm2);
            //        QL_REQUIRE(m2 > m1, "Second IMM date must be after the first in " << datumName);
            //        return boost::make_shared<ImmFraQuote>(value, asof, datumName, quoteType, ccy, m1, m2);
            //    }

            case MarketDatum.InstrumentType.IR_SWAP:
            {
                Utils.QL_REQUIRE(tokens.Count == 6, () => "6 tokens expected in " + datumName);
                string ccy      = tokens[2];
                Period fwdStart = Parsers.ParsePeriod(tokens[3]);
                Period tenor    = Parsers.ParsePeriod(tokens[4]);
                Period term     = Parsers.ParsePeriod(tokens[5]);
                return(new SwapQuote(value, asof, datumName, quoteType, ccy, fwdStart, term, tenor));
            }

            //case MarketDatum.InstrumentType.BASIS_SWAP:
            //    {
            //        QL_REQUIRE(tokens.size() == 6, "6 tokens expected in " << datumName);
            //        Period flatTerm = parsePeriod(tokens[2]);
            //        Period term = parsePeriod(tokens[3]);
            //        const string&ccy = tokens[4];
            //        Period maturity = parsePeriod(tokens[5]);
            //        return boost::make_shared<BasisSwapQuote>(value, asof, datumName, quoteType, flatTerm, term, ccy, maturity);
            //    }

            case MarketDatum.InstrumentType.CC_BASIS_SWAP:
            {
                Utils.QL_REQUIRE(tokens.Count == 7, () => "7 tokens expected in " + datumName);
                string flatCcy  = tokens[2];
                Period flatTerm = Parsers.ParsePeriod(tokens[3]);
                string ccy      = tokens[4];
                Period term     = Parsers.ParsePeriod(tokens[5]);
                Period maturity = Parsers.ParsePeriod(tokens[6]);
                return(new CrossCcyBasisSwapQuote(value, asof, datumName, quoteType, flatCcy, flatTerm, ccy, term, maturity));
            }

            //case MarketDatum.InstrumentType.CDS:
            //    {
            //        QL_REQUIRE(tokens.size() == 6, "6 tokens expected in " << datumName);
            //        const string&underlyingName = tokens[2];
            //        const string&seniority = tokens[3];
            //        const string&ccy = tokens[4];
            //        Period term = parsePeriod(tokens[5]);
            //        return boost::make_shared<CdsSpreadQuote>(value, asof, datumName, underlyingName, seniority, ccy, term);
            //    }

            //case MarketDatum.InstrumentType.HAZARD_RATE:
            //    {
            //        QL_REQUIRE(tokens.size() == 6, "6 tokens expected in " << datumName);
            //        const string&underlyingName = tokens[2];
            //        const string&seniority = tokens[3];
            //        const string&ccy = tokens[4];
            //        Period term = parsePeriod(tokens[5]);
            //        return boost::make_shared<HazardRateQuote>(value, asof, datumName, underlyingName, seniority, ccy, term);
            //    }

            //case MarketDatum.InstrumentType.RECOVERY_RATE:
            //    {
            //        QL_REQUIRE(tokens.size() == 3 || tokens.size() == 5, "3 or 5 tokens expected in " << datumName);
            //        const string&underlyingName = tokens[2]; // issuer name for CDS, security ID for bond specific RRs
            //        string seniority = "";
            //        string ccy = "";
            //        if (tokens.size() == 5)
            //        {
            //            // CDS
            //            seniority = tokens[3];
            //            ccy = tokens[4];
            //        }
            //        return boost::make_shared<RecoveryRateQuote>(value, asof, datumName, underlyingName, seniority, ccy);
            //    }

            //case MarketDatum.InstrumentType.CAPFLOOR:
            //    {
            //        QL_REQUIRE(tokens.size() == 8 || tokens.size() == 4, "Either 4 or 8 tokens expected in " << datumName);
            //        const string&ccy = tokens[2];
            //        if (tokens.size() == 8)
            //        {
            //            Period term = parsePeriod(tokens[3]);
            //            Period tenor = parsePeriod(tokens[4]);
            //            bool atm = parseBool(tokens[5].c_str());
            //            bool relative = parseBool(tokens[6].c_str());
            //            Real strike = parseReal(tokens[7]);
            //            return boost::make_shared<CapFloorQuote>(value, asof, datumName, quoteType, ccy, term, tenor, atm, relative,
            //                                                     strike);
            //        }
            //        else
            //        {
            //            Period indexTenor = parsePeriod(tokens[3]);
            //            return boost::make_shared<CapFloorShiftQuote>(value, asof, datumName, quoteType, ccy, indexTenor);
            //        }
            //    }

            case MarketDatum.InstrumentType.SWAPTION:
            {
                Utils.QL_REQUIRE(tokens.Count == 4 || tokens.Count == 6 || tokens.Count == 7, () => "4, 6 or 7 tokens expected in " + datumName);

                string ccy    = tokens[2];
                Period expiry = tokens.Count >= 6 ? Parsers.ParsePeriod(tokens[3]) : new Period(0, TimeUnit.Days);
                Period term   = tokens.Count >= 6 ? Parsers.ParsePeriod(tokens[4]) : Parsers.ParsePeriod(tokens[3]);
                if (tokens.Count >= 6)
                {         // volatility
                    string dimension = tokens[5];
                    double strike    = 0.0;
                    if (dimension == "ATM")
                    {
                        Utils.QL_REQUIRE(tokens.Count == 6, () => "6 tokens expected in ATM quote " + datumName);
                    }
                    else if (dimension == "Smile")
                    {
                        Utils.QL_REQUIRE(tokens.Count == 7, () => "7 tokens expected in Smile quote " + datumName);
                        strike = Parsers.ParseDouble(tokens[6]);
                    }
                    else
                    {
                        Utils.QL_FAIL("Swaption vol quote dimension " + dimension + " not recognised");
                    }
                    return(new SwaptionQuote(value, asof, datumName, quoteType, ccy, expiry, term, dimension, strike));
                }
                else
                {         // SLN volatility shift
                    return(null);
                    //return new SwaptionShiftQuote(value, asof, datumName, quoteType, ccy, term);
                }
            }

            case MarketDatum.InstrumentType.FX_SPOT:
            {
                Utils.QL_REQUIRE(tokens.Count == 4, () => "4 tokens expected in " + datumName);
                string unitCcy = tokens[2];
                string ccy     = tokens[3];
                return(new FXSpotQuote(value, asof, datumName, quoteType, unitCcy, ccy));
            }

            case MarketDatum.InstrumentType.FX_FWD:
            {
                Utils.QL_REQUIRE(tokens.Count == 5, () => "5 tokens expected in " + datumName);
                string unitCcy = tokens[2];
                string ccy     = tokens[3];
                Period term    = Parsers.ParsePeriod(tokens[4]);
                return(new FXForwardQuote(value, asof, datumName, quoteType, unitCcy, ccy, term));
            }

            case MarketDatum.InstrumentType.FX_OPTION:
            {
                Utils.QL_REQUIRE(tokens.Count == 6, () => "6 tokens expected in " + datumName);
                string unitCcy = tokens[2];
                string ccy     = tokens[3];
                Period expiry  = Parsers.ParsePeriod(tokens[4]);
                string strike  = tokens[5];
                return(new FXOptionQuote(value, asof, datumName, quoteType, unitCcy, ccy, expiry, strike));
            }

            //case MarketDatum.InstrumentType.ZC_INFLATIONSWAP:
            //    {
            //        QL_REQUIRE(tokens.size() == 4, "4 tokens expected in " << datumName);
            //        const string&index = tokens[2];
            //        Period term = parsePeriod(tokens[3]);
            //        return boost::make_shared<ZcInflationSwapQuote>(value, asof, datumName, index, term);
            //    }

            //case MarketDatum.InstrumentType.YY_INFLATIONSWAP:
            //    {
            //        QL_REQUIRE(tokens.size() == 4, "4 tokens expected in " << datumName);
            //        const string&index = tokens[2];
            //        Period term = parsePeriod(tokens[3]);
            //        return boost::make_shared<YoYInflationSwapQuote>(value, asof, datumName, index, term);
            //    }

            //case MarketDatum.InstrumentType.ZC_INFLATIONCAPFLOOR:
            //    {
            //        QL_REQUIRE(tokens.size() == 6, "6 tokens expected in " << datumName);
            //        const string&index = tokens[2];
            //        Period term = parsePeriod(tokens[3]);
            //        QL_REQUIRE(tokens[4] == "C" || tokens[4] == "F",
            //                   "excepted C or F for Cap or Floor at position 5 in " << datumName);
            //        bool isCap = tokens[4] == "C";
            //        string strike = tokens[5];
            //        return boost::make_shared<ZcInflationCapFloorQuote>(value, asof, datumName, quoteType, index, term, isCap,
            //                                                            strike);
            //    }

            //case MarketDatum.InstrumentType.SEASONALITY:
            //    {
            //        QL_REQUIRE(tokens.size() == 5, "5 tokens expected in " << datumName);
            //        const string&index = tokens[3];
            //        const string&type = tokens[2];
            //        const string&month = tokens[4];
            //        return boost::make_shared<SeasonalityQuote>(value, asof, datumName, index, type, month);
            //    }
            //case MarketDatum.InstrumentType.EQUITY_SPOT:
            //    {
            //        QL_REQUIRE(tokens.size() == 4, "4 tokens expected in " << datumName);
            //        QL_REQUIRE(quoteType == MarketDatum.QuoteType.PRICE, "Invalid quote type for " << datumName);
            //        const string&equityName = tokens[2];
            //        const string&ccy = tokens[3];
            //        return boost::make_shared<EquitySpotQuote>(value, asof, datumName, quoteType, equityName, ccy);
            //    }

            //case MarketDatum.InstrumentType.EQUITY_FWD:
            //    {
            //        QL_REQUIRE(tokens.size() == 5, "5 tokens expected in " << datumName);
            //        QL_REQUIRE(quoteType == MarketDatum.QuoteType.PRICE, "Invalid quote type for " << datumName);
            //        const string&equityName = tokens[2];
            //        const string&ccy = tokens[3];
            //        Date expiryDate = getDateFromDateOrPeriod(tokens[4], asof);
            //        return boost::make_shared<EquityForwardQuote>(value, asof, datumName, quoteType, equityName, ccy, expiryDate);
            //    }

            //case MarketDatum.InstrumentType.EQUITY_DIVIDEND:
            //    {
            //        QL_REQUIRE(tokens.size() == 5, "5 tokens expected in " << datumName);
            //        QL_REQUIRE(quoteType == MarketDatum.QuoteType.RATE, "Invalid quote type for " << datumName);
            //        const string&equityName = tokens[2];
            //        const string&ccy = tokens[3];
            //        Date tenorDate = getDateFromDateOrPeriod(tokens[4], asof);
            //        return boost::make_shared<EquityDividendYieldQuote>(value, asof, datumName, quoteType, equityName, ccy,
            //                                                            tenorDate);
            //    }

            //case MarketDatum.InstrumentType.EQUITY_OPTION:
            //    {
            //        QL_REQUIRE(tokens.size() == 6, "6 tokens expected in " << datumName);
            //        QL_REQUIRE(quoteType == MarketDatum.QuoteType.RATE_LNVOL, "Invalid quote type for " << datumName);
            //        const string&equityName = tokens[2];
            //        const string&ccy = tokens[3];
            //        string expiryString = tokens[4];
            //        const string&strike = tokens[5];
            //        // note how we only store the expiry string - to ensure we can support both Periods and Dates being specified in
            //        // the vol curve-config.
            //        return boost::make_shared<EquityOptionQuote>(value, asof, datumName, quoteType, equityName, ccy, expiryString,
            //                                                     strike);
            //    }

            //case MarketDatum.InstrumentType.BOND:
            //    {
            //        QL_REQUIRE(tokens.size() == 3, "3 tokens expected in " << datumName);
            //        const string&securityID = tokens[2];
            //        return boost::make_shared<SecuritySpreadQuote>(value, asof, datumName, securityID);
            //    }

            //case MarketDatum.InstrumentType.CDS_INDEX:
            //    {
            //        QL_REQUIRE(tokens.size() == 5, "5 tokens expected in " << datumName);
            //        QL_REQUIRE(quoteType == MarketDatum.QuoteType.BASE_CORRELATION, "Invalid quote type for " << datumName);
            //        const string&cdsIndexName = tokens[2];
            //        Period term = parsePeriod(tokens[3]);
            //        Real detachmentPoint = parseReal(tokens[4]);
            //        return boost::make_shared<BaseCorrelationQuote>(value, asof, datumName, quoteType, cdsIndexName, term,
            //                                                        detachmentPoint);
            //    }

            //case MarketDatum.InstrumentType.INDEX_CDS_OPTION:
            //    {
            //        QL_REQUIRE(tokens.size() == 4, "4 tokens expected in " << datumName);
            //        QL_REQUIRE(quoteType == MarketDatum.QuoteType.RATE_LNVOL, "Invalid quote type for " << datumName);
            //        const string&indexName = tokens[2];
            //        const string&expiry = tokens[3];
            //        return boost::make_shared<IndexCDSOptionQuote>(value, asof, datumName, indexName, expiry);
            //    }

            default:
                //Utils.QL_FAIL("Cannot convert \"" + datumName + "\" to MarketDatum");
                return(null);
            }
        }