Beispiel #1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="asof"></param>
 /// <param name="spec"></param>
 public FXSpot(Date asof, FXSpotSpec spec, Loader loader)
 {
     foreach (var md in loader.LoadQuotes(asof))
     {
         if (md.AsofDate() == asof && md.GetInstrumentType() == MarketDatum.InstrumentType.FX_SPOT)
         {
             FXSpotQuote q = md as FXSpotQuote;
             Utils.QL_REQUIRE(q != null, () => "Failed to cast " + md.Name() + " to FXSpotQuote");
             if (q.UnitCcy() == spec.UnitCcy() && q.Ccy() == spec.Ccy())
             {
                 _spot = q.Quote();
                 return;
             }
         }
     }
     Utils.QL_FAIL("Failed to find a quote for " + spec);
 }
Beispiel #2
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);
            }
        }