Ejemplo n.º 1
0
        //! Detailed constructor
        public FXVolCurve(Date asof, FXVolatilityCurveSpec spec, Loader loader, CurveConfigurations curveConfigs,
                          Dictionary <string, FXSpot> fxSpots,
                          Dictionary <string, YieldCurve> yieldCurves)
        {
            try
            {
                FXVolatilityCurveConfig config = curveConfigs.FxVolCurveConfig(spec.CurveConfigID());

                Utils.QL_REQUIRE(config.GetDimension() == FXVolatilityCurveConfig.Dimension.ATM ||
                                 config.GetDimension() == FXVolatilityCurveConfig.Dimension.Smile,
                                 () => "Unkown FX curve building dimension");

                bool isATM = config.GetDimension() == FXVolatilityCurveConfig.Dimension.ATM;

                // We loop over all market data, looking for quotes that match the configuration
                // every time we find a matching expiry we remove it from the list
                // we replicate this for all 3 types of quotes were applicable.
                int n = isATM ? 1 : 3; // [0] = ATM, [1] = RR, [2] = BF
                List <List <FXOptionQuote> > quotes   = new List <List <FXOptionQuote> >(n);
                List <List <Period> >        expiries = new InitializedList <List <Period> >(n, config.Expiries());
                foreach (var md in loader.LoadQuotes(asof))
                {
                    // skip irrelevant data
                    if (md.AsofDate() == asof && md.GetInstrumentType() == MarketDatum.InstrumentType.FX_OPTION)
                    {
                        FXOptionQuote q = md as FXOptionQuote;

                        if (q.UnitCcy() == spec.UnitCcy() && q.Ccy() == spec.Ccy())
                        {
                            int idx = 999999;
                            if (q.Strike() == "ATM")
                            {
                                idx = 0;
                            }
                            else if (q.Strike() == "25RR")
                            {
                                idx = 1;
                            }
                            else if (q.Strike() == "25BF")
                            {
                                idx = 2;
                            }

                            // silently skip unknown strike strings
                            if ((isATM && idx == 0) || (!isATM && idx <= 2))
                            {
                                if (expiries[idx].Contains(q.Expiry()))
                                //var it = std::find(expiries[idx].begin(), expiries[idx].end(), q->expiry());
                                //if (it != expiries[idx].end())
                                {
                                    // we have a hit
                                    quotes[idx].Add(q);
                                    // remove it from the list
                                    expiries[idx].Remove(q.Expiry());
                                }

                                // check if we are done
                                // for ATM we just check expiries[0], otherwise we check all 3
                                if (expiries[0].empty() && (isATM || (expiries[1].empty() && expiries[2].empty())))
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                // Check ATM first
                // Check that we have all the expiries we need
                //LOG("FXVolCurve: read " + quotes[0].Count + " ATM vols");
                Utils.QL_REQUIRE(expiries[0].Count == 0, () => "No ATM quote found for spec " + spec + " with expiry " + expiries[0].First());
                Utils.QL_REQUIRE(quotes[0].Count > 0, () => "No ATM quotes found for spec " + spec);
                // No check the rest
                if (!isATM)
                {
                    //LOG("FXVolCurve: read " + quotes[1].Count + " RR and " + quotes[2].Count + " BF quotes");
                    Utils.QL_REQUIRE(expiries[1].Count == 0, () => "No RR quote found for spec " + spec + " with expiry " + expiries[1].First());
                    Utils.QL_REQUIRE(expiries[2].Count == 0, () => "No BF quote found for spec " + spec + " with expiry " + expiries[2].First());
                }

                // daycounter used for interpolation in time.
                // TODO: push into conventions or config
                DayCounter dc  = config.DayCounter();
                Calendar   cal = config.Calendar();

                // sort all quotes
                for (int i = 0; i < n; i++)
                {
                    // TODO!!
                    //IComparer<FXOptionQuote> compare =
                    //quotes[i] = quotes[i].Sort((a,b) => a.Expiry().CompareTo(b.Expiry()))
                }

                // build vol curve
                if (isATM && quotes[0].Count == 1)
                {
                    _vol = new BlackConstantVol(asof, new Calendar(), quotes[0].First().Quote().link.value(), dc);
                }
                else
                {
                    int                   numExpiries = quotes[0].Count;
                    List <Date>           dates       = new List <Date>(numExpiries);
                    List <List <double> > vols        = new InitializedList <List <double> >(n, new List <double>(numExpiries)); // same as above: [0] = ATM, etc.

                    for (int i = 0; i < numExpiries; i++)
                    {
                        dates[i] = asof + quotes[0][i].Expiry();
                        for (int idx = 0; idx < n; idx++)
                        {
                            vols[idx][i] = quotes[idx][i].Quote().link.value();
                        }
                    }

                    if (isATM)
                    {
                        // ATM
                        _vol = new BlackVarianceCurve(asof, dates, vols[0], dc, false);
                    }
                    else
                    {
                        // Smile
                        if (fxSpots.ContainsKey(config.FxSpotID()) && yieldCurves.ContainsKey(config.FxDomesticYieldCurveID()) && yieldCurves.ContainsKey(config.FxForeignYieldCurveID()))
                        {
                            var fxSpot = fxSpots[config.FxSpotID()]; // new Handle<Quote>(config.FxSpotID(), fxSpots);
                            var domYTS = yieldCurves[config.FxDomesticYieldCurveID()];
                            var forYTS = yieldCurves[config.FxForeignYieldCurveID()];

                            // TODO!!
                            //_vol = new QuantExt.FxBlackVannaVolgaVolatilitySurface(asof, dates, vols[0], vols[1], vols[2], dc, cal, fxSpot, domYTS, forYTS));
                        }
                        else
                        {
                            Utils.QL_FAIL("FXVolCurve: Can't find spec " + spec);
                        }
                    }
                }
                _vol.enableExtrapolation();
            }
            catch (Exception e)
            {
                Utils.QL_FAIL("fx vol curve building failed :" + e.Message);
            }
        }
Ejemplo n.º 2
0
        public TodaysMarket(Date asof, TodaysMarketParameters todaysParams, Loader loader, CurveConfigurations curveConfigs, Conventions conventions) : base(conventions)
        {
            // Fixings
            // Apply them now in case a curve builder needs them
            //LOG("Todays Market Loading Fixings");
            //applyFixings(loader.loadFixings(), conventions);
            //LOG("Todays Market Loading Fixing done.");

            // store all curves built, since they might appear in several configurations
            // and might therefore be reused
            Dictionary <string, YieldCurve> requiredYieldCurves = new Dictionary <string, YieldCurve>();
            Dictionary <string, SwapIndex>  requiredSwapIndices = new Dictionary <string, SwapIndex>();
            Dictionary <string, FXSpot>     requiredFxSpots     = new Dictionary <string, FXSpot>();
            Dictionary <string, FXVolCurve> requiredFxVolCurves = new Dictionary <string, FXVolCurve>();

            //Dictionary<string, SwaptionVolCurve> requiredSwaptionVolCurves = new Dictionary<string, SwaptionVolCurve>();

            foreach (var configuration in todaysParams.Configurations())
            {
                //LOG("Build objects in TodaysMarket configuration " << configuration.first);

                _asof = asof;

                // Build the curve specs
                List <CurveSpec> specs = new List <CurveSpec>();
                foreach (var it in todaysParams.CurveSpecs(configuration.Key))
                {
                    specs.Add(CurveSpecParser.ParseCurveSpec(it));
                    //DLOG("CurveSpec: " << specs.back()->name());
                }

                // order them
                //Order(specs, curveConfigs);
                bool swapIndicesBuilt = false;

                // Loop over each spec, build the curve and add it to the MarketImpl container.
                for (int count = 0; count < specs.Count; ++count)
                {
                    var spec = specs[count];
                    //LOG("Loading spec " << *spec);

                    switch (spec.BaseType())
                    {
                    case CurveSpec.CurveType.Yield:
                        //YieldCurveSpec ycspec = new YieldCurveSpec(spec);
                        //Utils.QL_REQUIRE(ycspec != null, () => "Failed to convert spec " + spec + " to yield curve spec");
                        //// have we built the curve already ?
                        //auto itr = requiredYieldCurves.find(ycspec->name());
                        //if (itr == requiredYieldCurves.end())
                        //{
                        //    // build
                        //    //LOG("Building YieldCurve for asof " << asof);
                        //    YieldCurve yieldCurve = new YieldCurve(asof, *ycspec, curveConfigs, loader, conventions, requiredYieldCurves);

                        //    itr = requiredYieldCurves.insert(make_pair(ycspec->name(), yieldCurve)).first;
                        //}

                        ////DLOG("Added YieldCurve \"" << ycspec->name() << "\" to requiredYieldCurves map");

                        //if (itr->second->currency().code() != ycspec->ccy())
                        //{
                        //    //WLOG("Warning: YieldCurve has ccy " << itr->second->currency() << " but spec has ccy " << ycspec->ccy());

                        //}

                        //// We may have to add this spec multiple times (for discounting, yield and forwarding curves)
                        //List<YieldCurveType> yieldCurveTypes = new List<YieldCurveType>{ YieldCurveType.Discount, YieldCurveType.Yield };
                        //foreach (var y in yieldCurveTypes)
                        //{
                        //    MarketObject o = y as MarketObject;
                        //    foreach (auto & it : params.mapping(o, configuration.first))
                        //    {
                        //        if (it.second == spec->name())
                        //        {
                        //            LOG("Adding YieldCurve(" << it.first << ") with spec " << *ycspec << " to configuration " << configuration.first);

                        //        yieldCurves_[make_tuple(configuration.first, y, it.first)] = itr->second->handle();
                        //        }
                        //    }
                        //}

                        //for (const auto&it : params.mapping(MarketObject::IndexCurve, configuration.first))
                        //{
                        //    if (it.second == spec->name())
                        //    {
                        //        LOG("Adding Index(" << it.first << ") with spec " << *ycspec << " to configuration "
                        //                            << configuration.first);
                        //        iborIndices_[make_pair(configuration.first, it.first)] =
                        //            Handle<IborIndex>(parseIborIndex(it.first, itr->second->handle()));
                        //    }
                        //}
                        break;

                    case CurveSpec.CurveType.FX:
                        FXSpotSpec fxspec = spec as FXSpotSpec;
                        QLNet.Utils.QL_REQUIRE(fxspec != null, () => "Failed to convert spec " + spec + " to fx spot spec");

                        //// have we built the curve already ?
                        //var itr = requiredFxSpots.find(fxspec->name());
                        //if (itr == requiredFxSpots.end())
                        //{
                        //    // build the curve
                        //    LOG("Building FXSpot for asof " << asof);
                        //    boost::shared_ptr<FXSpot> fxSpot = boost::make_shared<FXSpot>(asof, *fxspec, loader);
                        //    itr = requiredFxSpots.insert(make_pair(fxspec->name(), fxSpot)).first;
                        //}

                        //// add the handle to the Market Map (possible lots of times for proxies)
                        //for (const auto&it : params.mapping(MarketObject::FXSpot, configuration.first))
                        //{
                        //    if (it.second == spec->name())
                        //    {
                        //        LOG("Adding FXSpot (" << it.first << ") with spec " << *fxspec << " to configuration "
                        //                              << configuration.first);
                        //        fxSpots_[configuration.first].addQuote(it.first, itr->second->handle());
                        //    }
                        //}
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                }
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="asof">Valuation date</param>
 /// <param name="curveSpec">Yield curve specification</param>
 /// <param name="curveConfigs">Repository of yield curve configurations</param>
 /// <param name="loader">Market data loader</param>
 /// <param name="conventions">Repository of market conventions for building bootstrap helper</param>
 /// <param name="requiredYieldCurves">Map of underlying yield curves if required</param>
 public YieldCurve(Date asof, YieldCurveSpec curveSpec, CurveConfigurations curveConfigs, Loader loader, Conventions conventions, Dictionary <string, YieldCurve> requiredYieldCurves = null)
 {
 }