Example #1
0
        //-------------------------------------------------------------------------
        public virtual void test_currencyExposure()
        {
            double eps = 1.0e-14;
            ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build();
            DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer();
            // USD
            MultiCurrencyAmount computedUSD = test.currencyExposure(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov);
            PointSensitivities  pointUSD    = test.presentValueSensitivity(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov).build();
            MultiCurrencyAmount expectedUSD = prov.currencyExposure(pointUSD.convertedTo(USD, prov)).plus(CurrencyAmount.of(FX_RESET_NOTIONAL_EXCHANGE_REC_USD.Currency, test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov)));

            assertFalse(computedUSD.contains(GBP));     // 0 GBP
            assertEquals(computedUSD.getAmount(USD).Amount, expectedUSD.getAmount(USD).Amount, eps * NOTIONAL);
            // GBP
            MultiCurrencyAmount computedGBP = test.currencyExposure(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov);
            PointSensitivities  pointGBP    = test.presentValueSensitivity(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov).build();
            MultiCurrencyAmount expectedGBP = prov.currencyExposure(pointGBP.convertedTo(GBP, prov)).plus(CurrencyAmount.of(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP.Currency, test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov)));

            assertFalse(computedGBP.contains(USD));     // 0 USD
            assertEquals(computedGBP.getAmount(GBP).Amount, expectedGBP.getAmount(GBP).Amount, eps * NOTIONAL);
            // FD approximation
            FxMatrix fxMatrixUp           = FxMatrix.of(GBP, USD, FX_RATE + EPS_FD);
            ImmutableRatesProvider provUp = ImmutableRatesProvider.builder(VAL_DATE).fxRateProvider(fxMatrixUp).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build();
            double expectedFdUSD          = -(test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, provUp) - test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov)) * FX_RATE * FX_RATE / EPS_FD;

            assertEquals(computedUSD.getAmount(USD).Amount, expectedFdUSD, EPS_FD * NOTIONAL);
            double expectedFdGBP = (test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, provUp) - test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov)) / EPS_FD;

            assertEquals(computedGBP.getAmount(GBP).Amount, expectedFdGBP, EPS_FD * NOTIONAL);
        }
Example #2
0
        public double GetFxRate(DateTime settlementDate, Currency domesticCcy, Currency foreignCcy)
        { //domestic-per-foreign
            if (foreignCcy == domesticCcy)
            {
                return(1.0);
            }

            double spot;

            if (domesticCcy == FxMatrix.BaseCurrency)
            {
                spot = FxMatrix.GetSpotRate(foreignCcy);
            }
            else if (foreignCcy == FxMatrix.BaseCurrency)
            {
                spot = 1.0 / FxMatrix.GetSpotRate(domesticCcy);
            }
            else
            {
                var forToBase = GetFxRate(settlementDate, FxMatrix.BaseCurrency, foreignCcy);
                var domToBase = GetFxRate(settlementDate, FxMatrix.BaseCurrency, domesticCcy);
                return(forToBase / domToBase);
            }
            var fxPair   = FxMatrix.GetFxPair(domesticCcy, foreignCcy);
            var spotDate = BuildDate.AddPeriod(RollType.F, fxPair.PrimaryCalendar, fxPair.SpotLag);
            var dfDom    = GetDf(domesticCcy, spotDate, settlementDate);
            var dfFor    = GetDf(foreignCcy, spotDate, settlementDate);

            return(spot * dfDom / dfFor);
        }
Example #3
0
        public virtual void test_currencyExposureOnFixing_noTimeSeries()
        {
            double    eps           = 1.0e-14;
            LocalDate valuationDate = date(2014, 6, 27);
            LocalDate paymentDate   = date(2014, 7, 1);
            LocalDate fixingDate    = date(2014, 6, 27);
            FxResetNotionalExchange resetNotionalUSD      = FxResetNotionalExchange.of(CurrencyAmount.of(USD, NOTIONAL), paymentDate, FxIndexObservation.of(GBP_USD_WM, fixingDate, REF_DATA));
            FxResetNotionalExchange resetNotionalGBP      = FxResetNotionalExchange.of(CurrencyAmount.of(GBP, -NOTIONAL), paymentDate, FxIndexObservation.of(GBP_USD_WM, fixingDate, REF_DATA));
            ImmutableRatesProvider  prov                  = ImmutableRatesProvider.builder(valuationDate).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build();
            DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer();
            // USD
            MultiCurrencyAmount computedUSD = test.currencyExposure(resetNotionalUSD, prov);
            PointSensitivities  pointUSD    = test.presentValueSensitivity(resetNotionalUSD, prov).build();
            MultiCurrencyAmount expectedUSD = prov.currencyExposure(pointUSD.convertedTo(USD, prov)).plus(CurrencyAmount.of(resetNotionalUSD.Currency, test.presentValue(resetNotionalUSD, prov)));

            assertFalse(computedUSD.contains(GBP));     // 0 GBP
            assertEquals(computedUSD.getAmount(USD).Amount, expectedUSD.getAmount(USD).Amount, eps * NOTIONAL);
            // GBP
            MultiCurrencyAmount computedGBP = test.currencyExposure(resetNotionalGBP, prov);
            PointSensitivities  pointGBP    = test.presentValueSensitivity(resetNotionalGBP, prov).build();
            MultiCurrencyAmount expectedGBP = prov.currencyExposure(pointGBP.convertedTo(GBP, prov)).plus(CurrencyAmount.of(resetNotionalGBP.Currency, test.presentValue(resetNotionalGBP, prov)));

            assertFalse(computedGBP.contains(USD));     // 0 USD
            assertEquals(computedGBP.getAmount(GBP).Amount, expectedGBP.getAmount(GBP).Amount, eps * NOTIONAL);
            // FD approximation
            FxMatrix fxMatrixUp           = FxMatrix.of(GBP, USD, FX_RATE + EPS_FD);
            ImmutableRatesProvider provUp = ImmutableRatesProvider.builder(valuationDate).fxRateProvider(fxMatrixUp).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build();
            double expectedFdUSD          = -(test.presentValue(resetNotionalUSD, provUp) - test.presentValue(resetNotionalUSD, prov)) * FX_RATE * FX_RATE / EPS_FD;

            assertEquals(computedUSD.getAmount(USD).Amount, expectedFdUSD, EPS_FD * NOTIONAL);
            double expectedFdGBP = (test.presentValue(resetNotionalGBP, provUp) - test.presentValue(resetNotionalGBP, prov)) / EPS_FD;

            assertEquals(computedGBP.getAmount(GBP).Amount, expectedFdGBP, EPS_FD * NOTIONAL);
        }
        //-------------------------------------------------------------------------
        public virtual void test_convertedTo_singleCurrency()
        {
            CurveSensitivities @base = sut();
            CurveSensitivities test  = @base.convertedTo(USD, FxMatrix.empty());

            assertEquals(test.TypedSensitivities.get(ZERO_RATE_DELTA).Sensitivities, ImmutableList.of(ENTRY_USD));
        }
Example #5
0
        public static IFundingModel RemapBaseCurrency(IFundingModel input, Currency newBaseCurrency, ICurrencyProvider currencyProvider)
        {
            if (newBaseCurrency == input.FxMatrix.BaseCurrency)
            {
                return(input.Clone());
            }

            var mf         = input.DeepClone(null);
            var homeToBase = mf.FxMatrix.SpotRates[newBaseCurrency];
            var ccys       = mf.FxMatrix.SpotRates.Keys.ToList()
                             .Concat(new[] { mf.FxMatrix.BaseCurrency })
                             .Where(x => x != newBaseCurrency);
            var newRateDict = new Dictionary <Currency, double>();

            foreach (var ccy in ccys)
            {
                var spotDate = mf.FxMatrix.GetFxPair(newBaseCurrency, ccy).SpotDate(mf.BuildDate);
                var newRate  = mf.GetFxRate(spotDate, newBaseCurrency, ccy);
                newRateDict.Add(ccy, newRate);
            }

            var newFx = new FxMatrix(currencyProvider);

            newFx.Init(newBaseCurrency, mf.FxMatrix.BuildDate, newRateDict, mf.FxMatrix.FxPairDefinitions, mf.FxMatrix.DiscountCurveMap);
            mf.SetupFx(newFx);

            return(mf);
        }
        public static object CreateFxMatrix(
            [ExcelArgument(Description = "Fx matrix name")] string ObjectName,
            [ExcelArgument(Description = "Base currency")] string BaseCurrency,
            [ExcelArgument(Description = "Build date")] DateTime BuildDate,
            [ExcelArgument(Description = "Spot rates")] object[,] SpotRateMap,
            [ExcelArgument(Description = "Fx pair definitions")] object[] FxPairDefinitions,
            [ExcelArgument(Description = "DiscountCurves")] object[,] DiscountCurves)
        {
            return(ExcelHelper.Execute(_logger, () =>
            {
                var fxPairsCache = ContainerStores.GetObjectCache <FxPair>();
                var fxPairs = FxPairDefinitions
                              .Where(s => fxPairsCache.Exists(s as string))
                              .Select(s => fxPairsCache.GetObject(s as string).Value)
                              .ToList();
                var currencies = ContainerStores.GlobalContainer.GetRequiredService <ICurrencyProvider>();

                var spotRatesRaw = SpotRateMap.RangeToDictionary <string, double>();

                var spotRates = spotRatesRaw.ToDictionary(y => currencies[y.Key], y => y.Value);

                var discountCurvesRaw = DiscountCurves.RangeToDictionary <string, string>();
                var discountCurves = discountCurvesRaw.ToDictionary(y => currencies[y.Key], y => y.Value);


                var matrix = new FxMatrix(currencies);
                matrix.Init(currencies[BaseCurrency], BuildDate, spotRates, fxPairs, discountCurves);

                return ExcelHelper.PushToCache(matrix, ObjectName);
            }));
        }
Example #7
0
        private AssetFxMCModel GetSut()
        {
            var buildDate = DateTime.Parse("2018-10-04");
            var usd       = TestProviderHelper.CurrencyProvider["USD"];

            TestProviderHelper.CalendarProvider.Collection.TryGetCalendar("NYC", out var usdCal);
            var dfCurve = new IrCurve(new[] { buildDate, buildDate.AddDays(1000) }, new[] { 0.0, 0.0 }, buildDate, "disco", Interpolator1DType.Linear, usd, "DISCO");

            var comCurve = new BasicPriceCurve(buildDate, new[] { buildDate, buildDate.AddDays(15), buildDate.AddDays(100) }, new[] { 100.0, 100.0, 100.0 }, PriceCurveType.NYMEX, TestProviderHelper.CurrencyProvider)
            {
                Name    = "CL",
                AssetId = "CL"
            };
            var comSurface = new ConstantVolSurface(buildDate, 0.32)
            {
                AssetId = "CL"
            };
            var fModel = new FundingModel(buildDate, new Dictionary <string, IrCurve> {
                { "DISCO", dfCurve }
            }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);
            var fxM = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxM.Init(usd, buildDate, new Dictionary <Currency, double>(), new List <FxPair>(), new Dictionary <Currency, string> {
                { usd, "DISCO" }
            });
            fModel.SetupFx(fxM);

            var aModel = new AssetFxModel(buildDate, fModel);

            aModel.AddVolSurface("CL", comSurface);
            aModel.AddPriceCurve("CL", comCurve);

            var product = AssetProductFactory.CreateAsianOption(buildDate.AddDays(10), buildDate.AddDays(20), 101, "CL", OptionType.Call, usdCal, buildDate.AddDays(21), usd);

            product.TradeId       = "waaah";
            product.DiscountCurve = "DISCO";


            var pfolio = new Portfolio {
                Instruments = new List <IInstrument> {
                    product
                }
            };
            var settings = new McSettings
            {
                Generator         = RandomGeneratorType.MersenneTwister,
                NumberOfPaths     = (int)System.Math.Pow(2, 13),
                NumberOfTimesteps = 1,
                ReportingCurrency = usd,
                Parallelize       = false,
                CreditSettings    = new CreditSettings
                {
                    ExposureDates = new DateTime[] { buildDate.AddDays(5), buildDate.AddDays(20), buildDate.AddDays(22) }
                },
            };
            var sut = new AssetFxMCModel(buildDate, pfolio, aModel, settings, TestProviderHelper.CurrencyProvider, TestProviderHelper.FutureSettingsProvider, TestProviderHelper.CalendarProvider);

            return(sut);
        }
Example #8
0
        private IPvModel GenerateTestData()
        {
            Utils.Parallel.ParallelUtils.Instance.MultiThreaded = false;

            var usd = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var zar = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR");
            var nyc = TestProviderHelper.CalendarProvider.Collection["NYC"];

            var ins = new Forward
            {
                TradeId         = "TestA",
                AssetId         = "FakeAsset",
                ExpiryDate      = _originDate.AddDays(180),
                PaymentCurrency = zar,
                Notional        = 1e6,
                Strike          = 1400,
                DiscountCurve   = "DISCO-ZAR"
            };
            var pf = new Portfolio {
                Instruments = new List <IInstrument> {
                    ins
                }
            };
            var pillars = new[] { _originDate.AddDays(90), _originDate.AddDays(180) };

            var discoUsd = new IrCurve(pillars, pillars.Select(p => 0.02).ToArray(), _originDate, "DISCO-USD", Interpolator1DType.Linear, usd);
            var discoZar = new IrCurve(pillars, pillars.Select(p => 0.02).ToArray(), _originDate, "DISCO-ZAR", Interpolator1DType.Linear, zar);

            var fxpairs = new List <FxPair>
            {
                new FxPair {
                    Domestic = usd, Foreign = zar, PrimaryCalendar = nyc, SpotLag = 2.Bd()
                },
                new FxPair {
                    Domestic = zar, Foreign = usd, PrimaryCalendar = nyc, SpotLag = 2.Bd()
                },
            };
            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxMatrix.Init(usd, _originDate, new Dictionary <Currency, double> {
                { zar, 14.0 }
            }, fxpairs, new Dictionary <Currency, string> {
                { usd, "DISCO-USD" }, { zar, "DISCO-ZAR" }
            });

            var fModel = new FundingModel(_originDate, new[] { discoUsd, discoZar }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);

            var model = new AssetFxModel(_originDate, fModel);

            var curve = new ConstantPriceCurve(100, _originDate, TestProviderHelper.CurrencyProvider);

            model.AddPriceCurve("FakeAsset", curve);
            model.AddFixingDictionary("FakeAsset", new FixingDictionary());
            model.AttachPortfolio(pf);
            return(model);
        }
Example #9
0
        public void CompositePriceCurveFact()
        {
            var originDate = new DateTime(2019, 05, 28);
            var zar        = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR");
            var usd        = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var zarCurve   = new ConstantRateIrCurve(0.07, originDate, "ZARCurve", zar);
            var usdCurve   = new ConstantRateIrCurve(0.02, originDate, "USDCurve", usd);
            var fModel     = new FundingModel(originDate, new[] { zarCurve, usdCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);
            var fxMatrix   = new FxMatrix(TestProviderHelper.CurrencyProvider);
            var fxPair     = new FxPair {
                Domestic = zar, Foreign = usd, SpotLag = new Dates.Frequency("0d")
            };

            fxMatrix.Init(zar, originDate, new Dictionary <Currency, double> {
                { usd, 10.0 }
            }, new List <FxPair>()
            {
                fxPair
            }, new Dictionary <Currency, string> {
                { usd, "USDCurve" }, { zar, "ZARCurve" }
            });
            fModel.SetupFx(fxMatrix);
            var baseCurve = new ConstantPriceCurve(100.0, originDate, TestProviderHelper.CurrencyProvider)
            {
                Currency = usd,
                Name     = "gooo",
                AssetId  = "rooo"
            };

            var sut  = new CompositePriceCurve(originDate, baseCurve, fModel, zar);
            var sut2 = new CompositePriceCurve(originDate, () => baseCurve, () => fModel, zar);

            var fxOrigin = fModel.GetFxRate(originDate, usd, zar);

            Assert.Equal(baseCurve.GetPriceForDate(originDate) * fxOrigin, sut.GetPriceForDate(originDate));
            Assert.Equal(baseCurve.GetPriceForDate(originDate) * fxOrigin, sut2.GetPriceForDate(originDate));
            Assert.Equal(baseCurve.GetPriceForDate(originDate) * fxOrigin, sut.GetPriceForFixingDate(originDate));
            Assert.Equal(baseCurve.GetPriceForDate(originDate) * fxOrigin, sut.GetAveragePriceForDates(new[] { originDate }));

            Assert.Equal("gooo", sut.Name);
            Assert.Throws <Exception>(() => sut.Name = null);
            Assert.Single(sut.GetDeltaScenarios(0.0, null));
            Assert.Equal(PriceCurveType.Linear, sut.CurveType);
            Assert.False(sut.UnderlyingsAreForwards);
            Assert.Equal(1, sut.NumberOfPillars);
            Assert.Equal("rooo", sut.AssetId);
            Assert.Equal(zar, sut.CompoCurrency);
            Assert.Equal(zar, sut.Currency);
            Assert.Throws <Exception>(() => sut.Currency = null);
            Assert.Equal(usd, sut.CurveCurrency);
            Assert.Single(sut.PillarDates);

            Assert.Equal(DateTime.Today.AddDays(1), sut.RebaseDate(DateTime.Today.AddDays(1)).BuildDate);
            Assert.Equal(originDate, sut.PillarDatesForLabel(originDate.ToString("yyyy-MM-dd")));
            Assert.Throws <Exception>(() => sut.PillarDatesForLabel(""));
        }
Example #10
0
 public FundingModel(DateTime buildDate, Dictionary <string, IrCurve> curves, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider)
 {
     _currencyProvider = currencyProvider;
     _calendarProvider = calendarProvider;
     BuildDate         = buildDate;
     Curves            = new Dictionary <string, IrCurve>(curves);
     FxMatrix          = new FxMatrix(_currencyProvider);
     VolSurfaces       = new Dictionary <string, IVolSurface>();
     SetupMappings();
 }
Example #11
0
        public static (IrCurve curve, double spotPrice) GetMetalCurveForCode(string cmxSettleFwdFilename, string cmxSymbol, FxPair metalPair, string curveName, DateTime valDate, IrCurve baseCurve, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider)
        {
            var blob = CMEFileParser.Instance.GetBlob(cmxSettleFwdFilename);
            var fwds = blob.Batch.Where(b => b.Instrmt.Sym == cmxSymbol).ToDictionary(x => x.Instrmt.MatDt, x => Convert.ToDouble(x.Full.Where(x => x.Typ == "6").First().Px));

            var curveCcy = metalPair.Domestic;
            var bc       = baseCurve.Clone();

            bc.SolveStage = -1;
            var spotDate = metalPair.SpotDate(valDate);
            var spotRate = Convert.ToDouble(fwds[spotDate]);

            fwds = Downsample(fwds, spotDate, metalPair.PrimaryCalendar);

            var fwdObjects = fwds.Select(x => new FxForward
            {
                DomesticCCY          = metalPair.Foreign,
                DeliveryDate         = x.Key,
                DomesticQuantity     = 1e6,
                ForeignCCY           = metalPair.Domestic,
                PillarDate           = x.Key,
                SolveCurve           = curveName,
                Strike               = Convert.ToDouble(x.Value),
                ForeignDiscountCurve = baseCurve.Name,
            });

            var fic = new FundingInstrumentCollection(currencyProvider);

            fic.AddRange(fwdObjects);
            var pillars  = fwds.Keys.OrderBy(x => x).ToArray();
            var curve    = new IrCurve(pillars, pillars.Select(p => 0.01).ToArray(), valDate, curveName, Interpolator1DType.Linear, curveCcy);
            var fm       = new FundingModel(valDate, new[] { curve, bc }, currencyProvider, calendarProvider);
            var matrix   = new FxMatrix(currencyProvider);
            var discoMap = new Dictionary <Currency, string> {
                { curveCcy, curveName }, { baseCurve.Currency, baseCurve.Name }
            };

            matrix.Init(metalPair.Foreign, valDate, new Dictionary <Currency, double> {
                { metalPair.Domestic, spotRate }
            }, new List <FxPair> {
                metalPair
            }, discoMap);
            fm.SetupFx(matrix);
            var solver = new NewtonRaphsonMultiCurveSolverStaged()
            {
                InLineCurveGuessing = true
            };

            solver.Solve(fm, fic);

            return(curve, spotRate);
        }
Example #12
0
        public static IrCurve StripFxBasisCurve(string cmeFwdFileName, FxPair ccyPair, string cmePair, Currency curveCcy, string curveName, DateTime valDate, IrCurve baseCurve, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider)
        {
            var fwdsDict = GetFwdFxRatesFromFwdFile(cmeFwdFileName, new Dictionary <string, string> {
                { ccyPair.ToString(), cmePair }
            });
            var bc = baseCurve.Clone();

            bc.SolveStage = -1;
            var fwds     = fwdsDict[ccyPair.ToString()];
            var spotDate = ccyPair.SpotDate(valDate);
            var spotRate = fwds[spotDate];

            fwds = Downsample(fwds, spotDate, ccyPair.PrimaryCalendar);

            var fwdObjects = fwds.Select(x => new FxForward
            {
                DomesticCCY          = ccyPair.Domestic,
                DeliveryDate         = x.Key,
                DomesticQuantity     = 1e6,
                ForeignCCY           = ccyPair.Foreign,
                PillarDate           = x.Key,
                SolveCurve           = curveName,
                Strike               = x.Value,
                ForeignDiscountCurve = ccyPair.Foreign == curveCcy ? curveName : baseCurve.Name,
            });

            var fic = new FundingInstrumentCollection(currencyProvider);

            fic.AddRange(fwdObjects);
            var pillars  = fwds.Keys.OrderBy(x => x).ToArray();
            var curve    = new IrCurve(pillars, pillars.Select(p => 0.01).ToArray(), valDate, curveName, Interpolator1DType.Linear, curveCcy);
            var fm       = new FundingModel(valDate, new[] { curve, bc }, currencyProvider, calendarProvider);
            var matrix   = new FxMatrix(currencyProvider);
            var discoMap = new Dictionary <Currency, string> {
                { curveCcy, curveName }, { baseCurve.Currency, baseCurve.Name }
            };

            matrix.Init(ccyPair.Domestic, valDate, new Dictionary <Currency, double> {
                { ccyPair.Foreign, spotRate }
            }, new List <FxPair> {
                ccyPair
            }, discoMap);
            fm.SetupFx(matrix);
            var solver = new NewtonRaphsonMultiCurveSolverStaged()
            {
                InLineCurveGuessing = true
            };

            solver.Solve(fm, fic);

            return(curve);
        }
Example #13
0
        public IFundingModel DeepClone(DateTime?newBuildDate = null)
        {
            var returnValue = new FundingModel(newBuildDate ?? BuildDate, Curves.Values.Select(c => c.Clone()).ToArray(), _currencyProvider, _calendarProvider)
            {
                VolSurfaces = VolSurfaces == null ? new Dictionary <string, IVolSurface>() : new Dictionary <string, IVolSurface>(VolSurfaces)
            };

            if (FxMatrix != null)
            {
                returnValue.SetupFx(FxMatrix.Clone());
            }
            return(returnValue);
        }
Example #14
0
        public void CashBalanceFact()
        {
            var bd         = new DateTime(2019, 06, 14);
            var pillars    = new[] { bd, bd.AddDays(1000) };
            var flatRate   = 0.05;
            var rates      = pillars.Select(p => flatRate).ToArray();
            var usd        = TestProviderHelper.CurrencyProvider["USD"];
            var zar        = TestProviderHelper.CurrencyProvider["ZAR"];
            var discoCurve = new IrCurve(pillars, rates, bd, "USD.BLAH", Interpolator1DType.Linear, usd);
            var fxMatrix   = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxMatrix.Init(usd, bd, new Dictionary <Currency, double>(), new List <FxPair>(), new Dictionary <Currency, string> {
                { usd, "X" }, { zar, "Y" }
            });
            var fModel = new FundingModel(bd, new[] { discoCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);
            var aModel = new AssetFxModel(bd, fModel);

            var notional = 100e6;
            var maturity = bd.AddDays(365);
            var b        = new CashBalance(usd, notional, null);

            var t = bd.CalculateYearFraction(maturity, DayCountBasis.Act365F);

            var pv = b.Pv(fModel, false);

            Assert.Equal(notional, pv);

            Assert.Empty(b.Dependencies(null));
            Assert.Empty(b.AssetIds);
            Assert.Empty(b.PastFixingDates(bd));
            Assert.Equal(0.0, b.CalculateParRate(null));
            Assert.Equal(0.0, b.FlowsT0(null));
            Assert.Equal(string.Empty, b.FxPair(null));
            Assert.Equal(FxConversionType.None, b.FxType(null));
            Assert.Equal(usd, b.Currency);
            Assert.Equal(DateTime.MinValue, b.LastSensitivityDate);

            var y = (CashBalance)b.Clone();

            Assert.True(b.Equals(y));
            y.TradeId = "xxx";
            Assert.False(b.Equals(y));

            Assert.Throws <NotImplementedException>(() => b.Sensitivities(fModel));
            Assert.Throws <NotImplementedException>(() => b.SetStrike(0.0));
            Assert.Equal(b, b.SetParRate(0.0));

            Assert.Single(b.IrCurves(aModel));
        }
Example #15
0
 public double[] GetFxRates(DateTime[] fixingDates, Currency domesticCcy, Currency foreignCcy)
 {
     if (foreignCcy == domesticCcy)
     {
         return(Enumerable.Repeat(1.0, fixingDates.Length).ToArray());
     }
     else
     {
         var pair        = FxMatrix.GetFxPair(domesticCcy, foreignCcy);
         var settleDates = fixingDates.Select(x => x.AddPeriod(RollType.F, pair.PrimaryCalendar, pair.SpotLag));
         var rates       = settleDates.Select(d => GetFxRate(d, domesticCcy, foreignCcy)).ToArray();
         return(rates);
     }
 }
Example #16
0
        private AssetFxModel GetModel()
        {
            var irCurveZar = new ConstantRateIrCurve(0.07, ValDate, "ZAR-IR", zar);
            var irCurveUsd = new ConstantRateIrCurve(0.02, ValDate, "USD-IR", zar);
            var fxMatrix   = new FxMatrix(TestProviderHelper.CurrencyProvider);
            var fxPair     = new FxPair()
            {
                Domestic          = usd,
                Foreign           = zar,
                PrimaryCalendar   = TestProviderHelper.CalendarProvider.GetCalendar("ZAR"),
                SecondaryCalendar = TestProviderHelper.CalendarProvider.GetCalendar("USD"),
                SpotLag           = new Frequency("2b")
            };

            fxMatrix.Init(usd, ValDate, new Dictionary <Currency, double> {
                { zar, 20.0 }
            }, new List <FxPair> {
                fxPair
            }, new Dictionary <Currency, string> {
                { zar, "ZAR-IR" }, { usd, "USD-IR" }
            });
            var fModel = new FundingModel(ValDate, new[] { irCurveUsd, irCurveZar }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);
            var fxSurface = new ConstantVolSurface(ValDate, 0.16);

            fModel.VolSurfaces.Add("USD/ZAR", fxSurface);
            var crudeCurve = new ConstantPriceCurve(100, ValDate, TestProviderHelper.CurrencyProvider)
            {
                Name     = "OIL",
                AssetId  = "OIL",
                Currency = usd
            };
            var crudeSurface = new ConstantVolSurface(ValDate, 0.32)
            {
                Name     = "OIL",
                AssetId  = "OIL",
                Currency = usd
            };
            var aModel = new AssetFxModel(ValDate, fModel);

            aModel.AddPriceCurve("OIL", crudeCurve);
            aModel.AddVolSurface("OIL", crudeSurface);
            aModel.CorrelationMatrix = new CorrelationMatrix(new[] { "OIL" }, new[] { "USD/ZAR" }, new double[][] { new [] { 0.5 } });
            return(aModel);
        }
Example #17
0
        public void FxForwardCurveFact()
        {
            var originDate = new DateTime(2019, 05, 28);
            var zar        = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR");
            var usd        = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var zarCurve   = new ConstantRateIrCurve(0.07, originDate, "ZARCurve", zar);
            var usdCurve   = new ConstantRateIrCurve(0.02, originDate, "USDCurve", usd);
            var fModel     = new FundingModel(originDate, new[] { zarCurve, usdCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);
            var fxMatrix   = new FxMatrix(TestProviderHelper.CurrencyProvider);
            var fxPair     = new FxPair {
                Domestic = zar, Foreign = usd, SpotLag = new Dates.Frequency("0d")
            };

            fxMatrix.Init(zar, originDate, new Dictionary <Currency, double> {
                { usd, 10.0 }
            }, new List <FxPair>()
            {
                fxPair
            }, new Dictionary <Currency, string> {
                { usd, "USDCurve" }, { zar, "ZARCurve" }
            });
            fModel.SetupFx(fxMatrix);
            var sut = new FxForwardCurve(originDate, fModel, zar, usd)
            {
                Name = "gooo",
            };
            var sut2 = new FxForwardCurve(originDate, new Func <Models.IFundingModel>(() => fModel), zar, usd);

            Assert.Equal(10, sut.GetPriceForDate(originDate));
            Assert.Equal(10, sut2.GetPriceForDate(originDate));
            Assert.Equal(10, sut.GetPriceForFixingDate(originDate));
            Assert.Equal(10, sut.GetAveragePriceForDates(new[] { originDate }));

            Assert.Equal("gooo", sut.Name);
            Assert.Equal(new Dictionary <string, IPriceCurve>(), sut.GetDeltaScenarios(0.0, null));
            Assert.Equal(PriceCurveType.Linear, sut.CurveType);
            Assert.True(sut.UnderlyingsAreForwards);
            Assert.Equal(0, sut.NumberOfPillars);
            Assert.Equal(usd.Ccy, sut.AssetId);
            Assert.Null(sut.PillarDates);

            Assert.Throws <NotImplementedException>(() => sut.RebaseDate(DateTime.Today));
            Assert.Throws <NotImplementedException>(() => sut.PillarDatesForLabel(""));
            Assert.Throws <Exception>(() => sut.Currency = null);
        }
Example #18
0
        public void AsianCompoSwap()
        {
            ParallelUtils.Instance.MultiThreaded = false;

            var startDate = new DateTime(2018, 07, 28);
            var cal       = TestProviderHelper.CalendarProvider.Collection["LON"];
            var xaf       = TestProviderHelper.CurrencyProvider["XAF"];
            var usd       = TestProviderHelper.CurrencyProvider["USD"];

            var curvePillars     = new[] { "1W", "1M", "3M", "6M", "1Y" };
            var curvePillarDates = curvePillars.Select(l => startDate.AddPeriod(RollType.F, cal, new Frequency(l))).ToArray();
            var curvePoints      = new[] { 100.0, 100, 100, 100, 100 };
            var curve            = new BasicPriceCurve(startDate, curvePillarDates, curvePoints, PriceCurveType.LME, TestProviderHelper.CurrencyProvider, curvePillars)
            {
                Currency       = usd,
                CollateralSpec = "CURVE",
                Name           = "Coconuts",
                AssetId        = "Coconuts"
            };

            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);
            var fxSpot   = 7;
            var rates    = new Dictionary <Currency, double> {
                { xaf, fxSpot }
            };
            var discoMap = new Dictionary <Currency, string> {
                { xaf, "XAF.CURVE" }, { usd, "USD.CURVE" }
            };
            var fxPair = new FxPair()
            {
                Domestic        = usd,
                Foreign         = xaf,
                PrimaryCalendar = cal,
                SpotLag         = new Frequency("2b")
            };

            fxMatrix.Init(usd, startDate, rates, new List <FxPair> {
                fxPair
            }, discoMap);

            var irPillars = new[] { startDate, startDate.AddYears(10) };
            var xafRates  = new[] { 0.1, 0.1 };
            var usdRates  = new[] { 0.01, 0.01 };
            var xafCurve  = new IrCurve(irPillars, xafRates, startDate, "XAF.CURVE", Interpolator1DType.Linear, xaf, "CURVE");
            var usdCurve  = new IrCurve(irPillars, usdRates, startDate, "USD.CURVE", Interpolator1DType.Linear, usd, "CURVE");

            var fModel = new FundingModel(startDate, new[] { xafCurve, usdCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);

            var aModel = new AssetFxModel(startDate, fModel);

            aModel.AddPriceCurve("Coconuts", curve);

            var periodCode = "SEP-18";

            var(Start, End) = periodCode.ParsePeriod();
            var fixingDates = Start.BusinessDaysInPeriod(End, cal).ToArray();
            var settleDate  = fixingDates.Last().AddPeriod(RollType.F, cal, new Frequency("5b"));
            var fxFwd       = aModel.FundingModel.GetFxAverage(fixingDates, usd, xaf);
            var assetFwd    = curve.GetAveragePriceForDates(fixingDates);
            var fairStrike  = fxFwd * assetFwd;

            var asianSwap = AssetProductFactory.CreateMonthlyAsianSwap(periodCode, fairStrike, "Coconuts", cal, cal, new Frequency("5b"), xaf, TradeDirection.Long, new Frequency("0b"), 1000, DateGenerationType.BusinessDays);

            asianSwap.TradeId = "aLovelyBunch";
            foreach (var sw in asianSwap.Swaplets)
            {
                sw.DiscountCurve    = "XAF.CURVE";
                sw.FxConversionType = FxConversionType.AverageThenConvert;
            }
            var pv = asianSwap.PV(aModel, false);

            Assert.Equal(0, pv, 8);

            var portfolio = new Portfolio()
            {
                Instruments = new List <IInstrument> {
                    asianSwap
                }
            };
            var pfPvCube = portfolio.PV(aModel);
            var pfPv     = (double)pfPvCube.GetAllRows().First().Value;

            Assert.Equal(0.0, pfPv, 8);

            var deltaCube = portfolio.AssetDelta(aModel);
            var dAgg      = deltaCube.Pivot("TradeId", AggregationAction.Sum);
            var delta     = (double)dAgg.GetAllRows().First().Value;
            var t0Spot    = aModel.FundingModel.GetFxRate(startDate, usd, xaf);
            var df        = xafCurve.GetDf(startDate, settleDate);

            Assert.Equal(995.361065482776, delta, 7);

            var fxDeltaCube = portfolio.FxDelta(aModel, usd, TestProviderHelper.CurrencyProvider);
            var dfxAgg      = fxDeltaCube.Pivot("TradeId", AggregationAction.Sum);
            var fxDelta     = (double)dfxAgg.GetAllRows().First().Value;

            Assert.Equal(-1000 * df * fxFwd * 100 / (t0Spot / fxSpot) / usdCurve.GetDf(startDate, fxPair.SpotDate(startDate)), fxDelta, 4);
        }
Example #19
0
        public void ForwardFact()
        {
            var orgin    = new DateTime(2019, 06, 12);
            var usd      = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var zar      = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR");
            var fixDates = new[] { orgin };
            var x        = new Forward()
            {
                AssetId          = "QS",
                DiscountCurve    = "X",
                ExpiryDate       = orgin,
                FxConversionType = FxConversionType.None,
                Notional         = 1,
                PaymentCurrency  = usd,
                PaymentDate      = orgin,
                SpotLag          = 0.Bd(),
                Strike           = 1000,
            };
            var xFx = new Forward()
            {
                AssetId          = "USD/ZAR",
                DiscountCurve    = "Y",
                ExpiryDate       = orgin,
                FxConversionType = FxConversionType.None,
                Notional         = 1,
                PaymentCurrency  = usd,
                PaymentDate      = orgin,
                SpotLag          = 0.Bd(),
                Strike           = 1000,
            };
            var x2 = new Forward()
            {
                AssetId          = "QS",
                DiscountCurve    = "X",
                ExpiryDate       = orgin,
                FxConversionType = FxConversionType.AverageThenConvert,
                Notional         = 1,
                PaymentCurrency  = zar,
                PaymentDate      = orgin,
                SpotLag          = 0.Bd(),
                Strike           = 1000,
            };

            var fakeModel = new Mock <IAssetFxModel>();
            var c         = new ConstantPriceCurve(100, DateTime.Today, TestProviderHelper.CurrencyProvider)
            {
                Currency = usd
            };

            fakeModel.Setup(xx => xx.GetPriceCurve(It.IsAny <string>(), null)).Returns(c);
            fakeModel.Setup(xx => xx.BuildDate).Returns(DateTime.Today);
            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxMatrix.Init(usd, orgin, new Dictionary <Currency, double>(), new List <FxPair>(), new Dictionary <Currency, string> {
                { usd, "X" }, { zar, "Y" }
            });
            var fModel = new Mock <IFundingModel>();

            fModel.Setup(xx => xx.FxMatrix).Returns(fxMatrix);
            fakeModel.Setup(xx => xx.FundingModel).Returns(fModel.Object);

            Assert.Equal(usd, x.Currency);
            Assert.Equal(usd, x.PaymentCurrency);
            var a = x.AssetIds;

            Assert.Contains("QS", a);

            Assert.Single(x.IrCurves(fakeModel.Object));
            var ir2 = xFx.IrCurves(fakeModel.Object);

            Assert.Contains("X", ir2);
            Assert.Contains("Y", ir2);
            ir2 = x2.IrCurves(fakeModel.Object);
            Assert.Contains("X", ir2);
            Assert.Contains("Y", ir2);

            Assert.Equal(string.Empty, x.FxPair(fakeModel.Object));
            Assert.Equal("USD/ZAR", x2.FxPair(fakeModel.Object));

            Assert.Equal(FxConversionType.None, x.FxType(fakeModel.Object));
            Assert.Equal(orgin, x.LastSensitivityDate);

            var pf = x.PastFixingDates(orgin.AddDays(1));

            Assert.Contains("QS", pf.Keys);

            var y = (Forward)x.Clone();

            Assert.True(x.Equals(y));
            y.TradeId = "xxx";
            Assert.False(x.Equals(y));

            var z = (Forward)x.SetStrike(0);

            Assert.Equal(0, z.Strike);

            Assert.Equal(1.0, z.SupervisoryDelta(fakeModel.Object));
        }
Example #20
0
        //-------------------------------------------------------------------------
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @ImmutableDefaults private static void applyDefaults(Builder builder)
        private static void applyDefaults(Builder builder)
        {
            builder.fxRateProvider = FxMatrix.empty();
        }
Example #21
0
        public void MultiPeriodBackpricingOptionFact()
        {
            var orgin    = new DateTime(2019, 06, 12);
            var usd      = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var zar      = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR");
            var fixDates = new[] { orgin };
            var x        = new MultiPeriodBackpricingOption()
            {
                AssetId       = "QS",
                CallPut       = OptionType.C,
                DiscountCurve = "X",
                FixingDates   = new List <DateTime[]>()
                {
                    fixDates
                },
                FxConversionType = FxConversionType.None,
                Notional         = 1,
                PaymentCurrency  = usd,
                SpotLag          = 0.Bd(),
                SpotLagRollType  = RollType.F,
                PeriodDates      = new [] { new Tuple <DateTime, DateTime> (orgin, orgin) }
            };
            var x2 = new MultiPeriodBackpricingOption()
            {
                AssetId       = "QS",
                CallPut       = OptionType.C,
                DiscountCurve = "X",
                FixingDates   = new List <DateTime[]>()
                {
                    fixDates
                },
                FxConversionType = FxConversionType.AverageThenConvert,
                Notional         = 1,
                PaymentCurrency  = zar,
                SpotLag          = 0.Bd(),
                SpotLagRollType  = RollType.F,
                PeriodDates      = new[] { new Tuple <DateTime, DateTime>(orgin, orgin) }
            };

            var fakeModel = new Mock <IAssetFxModel>();
            var c         = new ConstantPriceCurve(100, DateTime.Today, TestProviderHelper.CurrencyProvider)
            {
                Currency = usd
            };

            fakeModel.Setup(xx => xx.GetPriceCurve(It.IsAny <string>(), null)).Returns(c);
            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxMatrix.Init(usd, orgin, new Dictionary <Currency, double>(), new List <FxPair>(), new Dictionary <Currency, string> {
                { usd, "X" }, { zar, "Y" }
            });
            var fModel = new Mock <IFundingModel>();

            fModel.Setup(xx => xx.FxMatrix).Returns(fxMatrix);
            fakeModel.Setup(xx => xx.FundingModel).Returns(fModel.Object);

            Assert.Equal(usd, x.Currency);
            Assert.Equal(usd, x.PaymentCurrency);
            var a = x.AssetIds;

            Assert.Contains("QS", a);

            Assert.Single(x.IrCurves(fakeModel.Object));
            var ir2 = x2.IrCurves(fakeModel.Object);

            Assert.Contains("X", ir2);
            Assert.Contains("Y", ir2);

            Assert.Equal(FxConversionType.None, x.FxType(fakeModel.Object));
            Assert.Equal(orgin, x.LastSensitivityDate);

            var pf = x.PastFixingDates(orgin.AddDays(1));

            Assert.Contains("QS", pf.Keys);

            Assert.Equal(string.Empty, x.FxPair(fakeModel.Object));

            Assert.Throws <InvalidOperationException>(() => x.SetStrike(0));
        }
Example #22
0
        public void ContangoSwap()
        {
            var bd          = new DateTime(2019, 06, 14);
            var pillars     = new[] { bd, bd.AddDays(1000) };
            var flatRateUsd = 0.05;
            var flatRateXau = 0.01;
            var spotRate    = 1200;
            var ratesUsd    = pillars.Select(p => flatRateUsd).ToArray();
            var ratesXau    = pillars.Select(p => flatRateXau).ToArray();

            var usd = TestProviderHelper.CurrencyProvider["USD"];
            var xau = TestProviderHelper.CurrencyProvider["XAU"];

            CalendarProvider.Collection.TryGetCalendar("LON", out var cal);
            var pair = new FxPair()
            {
                Domestic = xau, Foreign = usd, SettlementCalendar = cal, SpotLag = 2.Bd()
            };

            var discoCurveUsd = new IrCurve(pillars, ratesUsd, bd, "USD.BLAH", Interpolator1DType.Linear, usd);
            var discoCurveXau = new IrCurve(pillars, ratesXau, bd, "XAU.BLAH", Interpolator1DType.Linear, xau);

            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxMatrix.Init(usd, bd, new Dictionary <Currency, double> {
                { xau, 1.0 / spotRate }
            }, new List <FxPair> {
                pair
            }, new Dictionary <Currency, string> {
                { usd, "USD.BLAH" }, { xau, "XAU.BLAH" }
            });
            var fModel = new FundingModel(bd, new[] { discoCurveUsd, discoCurveXau }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);


            var maturity = bd.AddDays(365);
            var spot     = bd.SpotDate(2.Bd(), cal, cal);
            var c        = 0.022;
            var b        = new ContangoSwap
            {
                CashCCY           = usd,
                MetalCCY          = xau,
                CashDiscountCurve = "USD.BLAH",
                DeliveryDate      = maturity,
                ContangoRate      = c,
                MetalQuantity     = 1,
                SpotDate          = spot
            };

            var t = spot.CalculateYearFraction(maturity, DayCountBasis.Act360);

            var pv = b.Pv(fModel, false);

            var fwdA       = (1.0 + c * t) * spotRate;
            var fwdB       = fModel.GetFxRate(maturity, xau, usd);
            var df         = discoCurveUsd.GetDf(bd, maturity);
            var expectedPv = (fwdB - fwdA) * b.MetalQuantity;

            expectedPv *= df;
            Assert.Equal(expectedPv, pv, 10);
            Assert.Equal(maturity, b.LastSensitivityDate);
            Assert.Equal(usd, b.Currency);

            var s = b.Sensitivities(fModel);

            Assert.True(s.Count == 2 && s.Keys.Contains("USD.BLAH") && s.Keys.Contains("XAU.BLAH"));

            var s2 = b.Dependencies(fModel.FxMatrix);

            Assert.True(s2.Count == 2 && s2.Contains("USD.BLAH") && s2.Contains("XAU.BLAH"));

            Assert.Equal(0.0402428426839156, b.CalculateParRate(fModel), 8);

            var b2 = (ContangoSwap)b.SetParRate(0.05);

            Assert.Equal(0.05, b2.ContangoRate);
        }
Example #23
0
        private AssetFxMCModel GetSut()
        {
            var buildDate = DateTime.Parse("2018-10-04");
            var usd       = TestProviderHelper.CurrencyProvider["USD"];
            var zar       = TestProviderHelper.CurrencyProvider["ZAR"];

            TestProviderHelper.CalendarProvider.Collection.TryGetCalendar("NYC", out var usdCal);
            var pair = new FxPair()
            {
                Domestic = zar, Foreign = usd, PrimaryCalendar = usdCal, SpotLag = 2.Bd()
            };

            var dfCurve = new IrCurve(new[] { buildDate, buildDate.AddDays(1000) }, new[] { 0.0, 0.0 }, buildDate, "disco", Interpolator1DType.Linear, usd, "DISCO");

            var dates    = new[] { buildDate, buildDate.AddDays(32), buildDate.AddDays(60), buildDate.AddDays(90) };
            var times    = dates.Select(d => buildDate.CalculateYearFraction(d, DayCountBasis.Act365F)).ToArray();
            var vols     = new[] { 0.32, 0.30, 0.29, 0.28 };
            var comCurve = new PriceCurve(buildDate, dates, new[] { 100.0, 100.0, 100.0, 100.0 }, PriceCurveType.NYMEX, TestProviderHelper.CurrencyProvider)
            {
                Name    = "CL",
                AssetId = "CL"
            };
            var comSurface = new GridVolSurface(buildDate, new[] { 0.5 }, dates, vols.Select(x => new double[] { x }).ToArray(), StrikeType.ForwardDelta, Interpolator1DType.Linear, Interpolator1DType.LinearInVariance, DayCountBasis.Act365F)
            {
                AssetId = "CL"
            };
            var fxSurface = new ConstantVolSurface(buildDate, 0.16)
            {
                AssetId = "USD/ZAR"
            };
            var correlVector = new CorrelationTimeVector("CL", "USD/ZAR", _correls, times);
            var fModel       = new FundingModel(buildDate, new Dictionary <string, IrCurve> {
                { "DISCO", dfCurve }
            }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);
            var fxM = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxM.Init(usd, buildDate, new Dictionary <Currency, double>()
            {
                { zar, 14.0 }
            }, new List <FxPair>()
            {
                pair
            }, new Dictionary <Currency, string> {
                { usd, "DISCO" }, { zar, "DISCO" }
            });
            fModel.SetupFx(fxM);
            fModel.VolSurfaces.Add("ZAR/USD", fxSurface);
            fModel.VolSurfaces.Add("USD/ZAR", fxSurface);

            var aModel = new AssetFxModel(buildDate, fModel);

            aModel.AddVolSurface("CL", comSurface);
            aModel.AddPriceCurve("CL", comCurve);
            aModel.CorrelationMatrix = correlVector;

            var product1 = AssetProductFactory.CreateAsianOption(dates[1], dates[1], 1400, "CL", OptionType.Call, usdCal, dates[1], zar);

            product1.TradeId          = "P1";
            product1.DiscountCurve    = "DISCO";
            product1.FxConversionType = FxConversionType.AverageThenConvert;
            var product2 = AssetProductFactory.CreateAsianOption(dates[2], dates[2], 1400, "CL", OptionType.Call, usdCal, dates[2], zar);

            product2.TradeId          = "P2";
            product2.DiscountCurve    = "DISCO";
            product2.FxConversionType = FxConversionType.AverageThenConvert;
            var product3 = AssetProductFactory.CreateAsianOption(dates[3], dates[3], 1400, "CL", OptionType.Call, usdCal, dates[3], zar);

            product3.TradeId          = "P3";
            product3.DiscountCurve    = "DISCO";
            product3.FxConversionType = FxConversionType.AverageThenConvert;

            var pfolio = new Portfolio {
                Instruments = new List <IInstrument> {
                    product1, product2, product3
                }
            };
            var settings = new McSettings
            {
                Generator         = RandomGeneratorType.MersenneTwister,
                NumberOfPaths     = (int)2.0.IntPow(15),
                NumberOfTimesteps = 1,
                ReportingCurrency = zar,
                Parallelize       = false,
                LocalCorrelation  = true,
            };
            var sut = new AssetFxMCModel(buildDate, pfolio, aModel, settings, TestProviderHelper.CurrencyProvider, TestProviderHelper.FutureSettingsProvider, TestProviderHelper.CalendarProvider);

            return(sut);
        }
Example #24
0
        public void FxDeltaOnUSDTrade()
        {
            ParallelUtils.Instance.MultiThreaded = false;

            var startDate = new DateTime(2018, 07, 28);
            var cal       = TestProviderHelper.CalendarProvider.Collection["LON"];
            var zar       = TestProviderHelper.CurrencyProvider["ZAR"];
            var usd       = TestProviderHelper.CurrencyProvider["USD"];

            var curvePillars     = new[] { "1W", "1M", "3M", "6M", "1Y" };
            var curvePillarDates = curvePillars.Select(l => startDate.AddPeriod(RollType.F, cal, new Frequency(l))).ToArray();
            var curvePoints      = new[] { 100.0, 100, 100, 100, 100 };
            var curve            = new PriceCurve(startDate, curvePillarDates, curvePoints, PriceCurveType.LME, TestProviderHelper.CurrencyProvider, curvePillars)
            {
                Currency       = usd,
                CollateralSpec = "CURVE",
                Name           = "Coconuts"
            };

            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);
            var fxSpot   = 15;
            var rates    = new Dictionary <Currency, double> {
                { zar, fxSpot }
            };
            var discoMap = new Dictionary <Currency, string> {
                { zar, "ZAR.CURVE" }, { usd, "USD.CURVE" }
            };
            var fxPair = new FxPair()
            {
                Domestic           = usd,
                Foreign            = zar,
                SettlementCalendar = cal,
                SpotLag            = new Frequency("0b")
            };

            fxMatrix.Init(usd, startDate, rates, new List <FxPair> {
                fxPair
            }, discoMap);

            var irPillars = new[] { startDate, startDate.AddYears(10) };
            var zarRates  = new[] { 0.0, 0.0 };
            var usdRates  = new[] { 0.0, 0.0 };
            var zarCurve  = new IrCurve(irPillars, zarRates, startDate, "ZAR.CURVE", Interpolator1DType.Linear, zar, "CURVE");
            var usdCurve  = new IrCurve(irPillars, usdRates, startDate, "USD.CURVE", Interpolator1DType.Linear, usd, "CURVE");

            var fModel = new FundingModel(startDate, new[] { zarCurve, usdCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);

            var aModel = new AssetFxModel(startDate, fModel);

            aModel.AddPriceCurve("Coconuts", curve);

            var periodCode = "SEP-18";

            var(Start, End) = periodCode.ParsePeriod();
            var fixingDates = Start.BusinessDaysInPeriod(End, cal).ToArray();
            var settleDate  = fixingDates.Last().AddPeriod(RollType.F, cal, new Frequency("5b"));
            var fxFwd       = aModel.FundingModel.GetFxAverage(fixingDates, usd, zar);
            var assetFwd    = curve.GetAveragePriceForDates(fixingDates);
            var fairStrike  = assetFwd;
            var strike      = fairStrike - 10;
            var nominal     = 1000;

            var asianSwap = AssetProductFactory.CreateMonthlyAsianSwap(periodCode, strike, "Coconuts", cal, cal, new Frequency("5b"), usd, TradeDirection.Long, new Frequency("0b"), nominal, DateGenerationType.BusinessDays);

            asianSwap.TradeId = "aLovelyBunch";
            foreach (var sw in asianSwap.Swaplets)
            {
                sw.DiscountCurve    = "USD.CURVE";
                sw.FxConversionType = FxConversionType.None;
            }
            var pv         = asianSwap.PV(aModel, false);
            var expectedPV = (fairStrike - strike) * nominal;

            Assert.Equal(expectedPV, pv, 8);

            var portfolio = new Portfolio()
            {
                Instruments = new List <IInstrument> {
                    asianSwap
                }
            };
            var pfPvCube = portfolio.PV(aModel, usd);
            var pfPv     = (double)pfPvCube.GetAllRows().First().Value;

            Assert.Equal(expectedPV, pfPv, 8);

            //expected fx delta is just PV in USD
            var deltaCube = portfolio.FxDelta(aModel, zar, TestProviderHelper.CurrencyProvider);
            var dAgg      = deltaCube.Pivot("TradeId", AggregationAction.Sum);
            var delta     = (double)dAgg.GetAllRows().First().Value;

            Assert.Equal(expectedPV, delta, 4);
        }
Example #25
0
        public static object MergeFundingModels(
            [ExcelArgument(Description = "Output funding model")] string ObjectName,
            [ExcelArgument(Description = "Funding model A")] string FundingModelA,
            [ExcelArgument(Description = "Funding model B")] string FundingModelB)
        {
            return(ExcelHelper.Execute(_logger, () =>
            {
                var modelCache = ContainerStores.GetObjectCache <IFundingModel>();
                if (!modelCache.TryGetObject(FundingModelA, out var modelA))
                {
                    return $"Could not find funding model {FundingModelA}";
                }
                if (!modelCache.TryGetObject(FundingModelB, out var modelB))
                {
                    return $"Could not find funding model {FundingModelB}";
                }

                var combinedCurves = modelA.Value.Curves.Values.Concat(modelB.Value.Curves.Values).ToArray();

                if (combinedCurves.Length != combinedCurves.Select(x => x.Name).Distinct().Count())
                {
                    return $"Not all curves have unique names";
                }

                var outModel = new FundingModel(modelA.Value.BuildDate, combinedCurves, ContainerStores.CurrencyProvider, ContainerStores.CalendarProvider);

                foreach (var vs in modelA.Value.VolSurfaces)
                {
                    outModel.VolSurfaces.Add(vs.Key, vs.Value);
                }
                foreach (var vs in modelB.Value.VolSurfaces)
                {
                    outModel.VolSurfaces.Add(vs.Key, vs.Value);
                }

                var fxA = modelA.Value.FxMatrix;
                var fxB = modelB.Value.FxMatrix;

                var spotRates = new Dictionary <Currency, double>();
                foreach (var s in fxA.SpotRates)
                {
                    spotRates.Add(s.Key, s.Value);
                }
                foreach (var s in fxB.SpotRates)
                {
                    spotRates.Add(s.Key, s.Value);
                }

                var discoMap = new Dictionary <Currency, string>();
                foreach (var s in fxA.DiscountCurveMap)
                {
                    discoMap.Add(s.Key, s.Value);
                }
                foreach (var s in fxB.DiscountCurveMap)
                {
                    discoMap.Add(s.Key, s.Value);
                }

                var pairs = fxA.FxPairDefinitions.Concat(fxB.FxPairDefinitions).Distinct().ToList();

                var fxMatrix = new FxMatrix(ContainerStores.CurrencyProvider);
                fxMatrix.Init(fxA.BaseCurrency, modelA.Value.BuildDate, spotRates, pairs, discoMap);

                outModel.SetupFx(fxMatrix);

                return ExcelHelper.PushToCache <IFundingModel>(outModel, ObjectName);
            }));
        }
Example #26
0
        private (IAssetFxModel startModel, IAssetFxModel endModel, Portfolio portfolio) GenerateTestData()
        {
            Utils.Parallel.ParallelUtils.Instance.MultiThreaded = false;

            var usd = TestProviderHelper.CurrencyProvider.GetCurrency("USD");
            var zar = TestProviderHelper.CurrencyProvider.GetCurrency("ZAR");
            var nyc = TestProviderHelper.CalendarProvider.Collection["NYC"];

            var originDate = DateTime.Parse("2019-04-25");
            var ins        = new FxForward
            {
                TradeId              = "TestA",
                DeliveryDate         = originDate.AddDays(30),
                DomesticCCY          = zar,
                ForeignCCY           = usd,
                DomesticQuantity     = 1e6,
                Strike               = 14,
                ForeignDiscountCurve = "DISCO-USD"
            };
            var pf = new Portfolio {
                Instruments = new List <IInstrument> {
                    ins
                }
            };

            var discoUsd = new FlatIrCurve(0.02, usd, "DISCO-USD");
            var discoZar = new FlatIrCurve(0.05, zar, "DISCO-ZAR");
            var fxpairs  = new List <FxPair>
            {
                new FxPair {
                    Domestic = usd, Foreign = zar, PrimaryCalendar = nyc, SpotLag = 2.Bd()
                },
                new FxPair {
                    Domestic = zar, Foreign = usd, PrimaryCalendar = nyc, SpotLag = 2.Bd()
                },
            };
            var fxMatrix = new FxMatrix(TestProviderHelper.CurrencyProvider);

            fxMatrix.Init(zar, originDate, new Dictionary <Currency, double> {
                { usd, 14.0 }
            }, fxpairs, new Dictionary <Currency, string> {
                { usd, "DISCO-USD" }, { zar, "DISCO-ZAR" }
            });

            var fModel = new FundingModel(originDate, new[] { discoUsd, discoZar }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            fModel.SetupFx(fxMatrix);
            var startModel = new AssetFxModel(originDate, fModel);

            startModel.AddFixingDictionary("FakeAsset", new FixingDictionary());
            startModel.AddPriceCurve("FakeAsset", new ConstantPriceCurve(100, originDate, TestProviderHelper.CurrencyProvider));
            startModel.AddVolSurface("FakeAsset", new ConstantVolSurface(originDate, 1.00)
            {
                AssetId = "FakeAsset", Currency = usd
            });

            var endFModel = fModel.DeepClone();

            endFModel.FxMatrix.SpotRates[usd] = 15;
            var endModel = startModel.Clone(endFModel);

            endModel.AddFixingDictionary("FakeAsset", new FixingDictionary());
            endModel.AddPriceCurve("FakeAsset", new ConstantPriceCurve(100, originDate, TestProviderHelper.CurrencyProvider));
            endModel.AddVolSurface("FakeAsset", new ConstantVolSurface(originDate, 1.00)
            {
                AssetId = "FakeAsset", Currency = usd
            });
            return(startModel, endModel, pf);
        }
Example #27
0
        //-------------------------------------------------------------------------
        public virtual void test_convertedTo_singleCurrency()
        {
            CurrencyParameterSensitivities test = SENSI_1.convertedTo(USD, FxMatrix.empty());

            assertEquals(test.Sensitivities, ImmutableList.of(ENTRY_USD));
        }
Example #28
0
 //-------------------------------------------------------------------------
 public virtual void test_total_singleCurrency()
 {
     assertEquals(SENSI_1.total(USD, FxMatrix.empty()).Amount, VECTOR_USD1.sum(), 1e-8);
 }
Example #29
0
        public AssetFxModel BuildModel(DateTime valDate, ModelBuilderSpec spec, IFutureSettingsProvider futureSettingsProvider, ICurrencyProvider currencyProvider, ICalendarProvider calendarProvider)
        {
            var indices     = spec.RateIndices.ToDictionary(x => x.Key, x => new FloatRateIndex(x.Value, calendarProvider, currencyProvider));
            var fxPairs     = spec.FxPairs.Select(x => new FxPair(x, currencyProvider, calendarProvider)).ToList();
            var priceCurves = new List <IPriceCurve>();
            var surfaces    = new List <IVolSurface>();
            var fxSurfaces  = new List <IVolSurface>();

            foreach (var c in spec.NymexSpecs)
            {
                var curve = NYMEXModelBuilder.GetCurveForCode(c.NymexCodeFuture, Path.Combine(_filepath, FilenameNymexFuture), c.QwackCode, futureSettingsProvider, currencyProvider);
                priceCurves.Add(curve);
                if (!string.IsNullOrWhiteSpace(c.NymexCodeOption))
                {
                    var surface = NYMEXModelBuilder.GetSurfaceForCode(c.NymexCodeOption, Path.Combine(_filepath, FilenameNymexOption), c.QwackCode, curve, calendarProvider, currencyProvider, futureSettingsProvider);
                    surface.AssetId = c.QwackCode;
                    surfaces.Add(surface);
                }
            }
            var irCurves = new Dictionary <string, IrCurve>();

            foreach (var c in spec.CmeBaseCurveSpecs)
            {
                var ixForThis = new Dictionary <string, FloatRateIndex> {
                    { c.QwackCode, indices[c.FloatRateIndex] }
                };
                var curve = CMEModelBuilder.GetCurveForCode(c.CmeCode, Path.Combine(_filepath, c.IsCbot? FilenameCbot:FilenameCme), c.QwackCode, c.CurveName, ixForThis,
                                                            new Dictionary <string, string>()
                {
                    { c.QwackCode, c.CurveName }
                }, futureSettingsProvider, currencyProvider, calendarProvider);
                irCurves.Add(c.CurveName, curve);
            }
            foreach (var c in spec.CmeBasisCurveSpecs)
            {
                var fxPair = fxPairs.Single(x => $"{x.Domestic}{x.Foreign}" == c.FxPair);
                var curve  = CMEModelBuilder.StripFxBasisCurve(Path.Combine(_filepath, FilenameCmeFwdsXml), fxPair, c.CmeFxPair, currencyProvider.GetCurrency(c.Currency), c.CurveName, valDate, irCurves[c.BaseCurveName], currencyProvider, calendarProvider);
                irCurves.Add(c.CurveName, curve);
            }
            foreach (var c in spec.CmeFxFutureSpecs)
            {
                var curve   = CMEModelBuilder.GetFuturesCurveForCode(c.CmeCodeFut, Path.Combine(_filepath, FilenameCme), currencyProvider);
                var surface = CMEModelBuilder.GetFxSurfaceForCode(c.CmeCodeOpt, Path.Combine(_filepath, FilenameCme), curve, currencyProvider);
                surface.AssetId = c.FxPair;
                fxSurfaces.Add(surface);
            }

            var pairMap     = spec.CmeBasisCurveSpecs.ToDictionary(x => x.FxPair, x => x.CmeFxPair);
            var pairCcyMap  = spec.CmeBasisCurveSpecs.ToDictionary(x => x.FxPair, x => currencyProvider.GetCurrency(x.Currency));
            var spotRates   = CMEModelBuilder.GetSpotFxRatesFromFwdFile(Path.Combine(_filepath, FilenameCmeFwdsXml), valDate, pairMap, currencyProvider, calendarProvider);
            var discountMap = spec.CmeBasisCurveSpecs.ToDictionary(x => pairCcyMap[x.FxPair], x => x.CurveName);

            foreach (var c in spec.CmxMetalCurves)
            {
                var fxPair = fxPairs.Single(x => $"{x.Domestic}{x.Foreign}" == c.MetalPair);
                var(curve, spotPrice) = COMEXModelBuilder.GetMetalCurveForCode(Path.Combine(_filepath, FilenameCmxFwdsXml), c.CmxSymbol, fxPair, c.CurveName, valDate, irCurves[c.BaseCurveName], currencyProvider, calendarProvider);
                irCurves.Add(c.CurveName, curve);
                spotRates.Add(c.MetalPair, spotPrice);
                discountMap.Add(currencyProvider.GetCurrency(c.Currency), c.CurveName);
                pairCcyMap.Add(c.MetalPair, currencyProvider.GetCurrency(c.Currency));
                if (!string.IsNullOrWhiteSpace(c.CmxOptCode))
                {
                    var surface = COMEXModelBuilder.GetMetalSurfaceForCode(c.CmxOptCode, Path.Combine(_filepath, FilenameCmxXml), currencyProvider);
                    surface.AssetId = c.MetalPair;
                    fxSurfaces.Add(surface);
                }
            }

            var fm = new FundingModel(valDate, irCurves, currencyProvider, calendarProvider);

            var spotRatesByCcy = spotRates.ToDictionary(x => pairCcyMap[x.Key], x => x.Key.StartsWith("USD") ? x.Value : 1.0 / x.Value);

            var fxMatrix = new FxMatrix(currencyProvider);

            fxMatrix.Init(
                baseCurrency: currencyProvider.GetCurrency("USD"),
                buildDate: valDate,
                spotRates: spotRatesByCcy,
                fXPairDefinitions: fxPairs,
                discountCurveMap: discountMap);
            fm.SetupFx(fxMatrix);
            foreach (var fxs in fxSurfaces)
            {
                fm.VolSurfaces.Add(fxs.AssetId, fxs);
            }
            var o = new AssetFxModel(valDate, fm);

            o.AddVolSurfaces(surfaces.ToDictionary(s => s.AssetId, s => s));
            o.AddPriceCurves(priceCurves.ToDictionary(c => c.AssetId, c => c));
            return(o);
        }
Example #30
0
        public void ComplexerCurve()
        {
            var startDate = new DateTime(2016, 05, 20);

            Frequency[] depoTenors       = { 3.Months() };
            Frequency[] OISdepoTenors    = { 1.Bd() };
            double[]    depoPricesZAR    = { 0.06 };
            double[]    depoPricesUSD    = { 0.01 };
            double[]    OISdepoPricesZAR = { 0.055 };
            double[]    OISdepoPricesUSD = { 0.009 };

            string[] FRATenors    = { "3x6", "6x9", "9x12", "12x15", "15x18", "18x21", "21x24" };
            double[] FRAPricesZAR = { 0.065, 0.07, 0.075, 0.077, 0.08, 0.081, 0.082 };
            double[] FRAPricesUSD = { 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018 };

            Frequency[] swapTenors    = { 3.Years(), 4.Years(), 5.Years(), 6.Years(), 7.Years(), 8.Years(), 9.Years(), 10.Years(), 12.Years(), 15.Years(), 20.Years(), 25.Years(), 30.Years() };
            double[]    swapPricesZAR = { 0.08, 0.083, 0.085, 0.087, 0.089, 0.091, 0.092, 0.093, 0.094, 0.097, 0.099, 0.099, 0.099 };
            double[]    swapPricesUSD = { 0.017, 0.018, 0.019, 0.020, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.03 };
            Frequency[] oisTenors     = { 3.Months(), 6.Months(), 1.Years(), 18.Months(), 2.Years(), 3.Years(), 4.Years(), 5.Years(), 6.Years(), 7.Years(), 8.Years(), 9.Years(), 10.Years(), 12.Years(), 15.Years(), 20.Years(), 25.Years(), 30.Years() };
            double[]    oisPricesZAR  = { 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004 };
            double[]    oisPricesUSD  = { 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002, 0.002 };

            var fxSpot = 14.0;

            Frequency[] fxForwardTenors = { 3.Months(), 6.Months(), 1.Years(), 18.Months(), 2.Years(), 3.Years() };
            double[]    fxForwardPrices = { 14.10, 14.20, 14.40, 14.60, 14.80, 15.20 };
            Frequency[] xcySwapTenors   = { 4.Years(), 5.Years(), 6.Years(), 7.Years(), 8.Years(), 9.Years(), 10.Years(), 12.Years(), 15.Years(), 20.Years(), 25.Years(), 30.Years() };
            double[]    xcySwapPrices   = { 0.0055, 0.0050, 0.0045, 0.0040, 0.0035, 0.0030, 0.0025, 0.0020, 0.0015, 0.0010, 0.0005, 0.0000 };

            var ZARpillarDatesDepo    = depoTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray();
            var ZARpillarDatesFRA     = FRATenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, new Frequency(x.Split('x')[1] + "M"))).ToArray();
            var ZARpillarDatesSwap    = swapTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray();
            var ZARpillarDates3m      = ZARpillarDatesDepo.Union(ZARpillarDatesSwap).Union(ZARpillarDatesFRA).Distinct().OrderBy(x => x).ToArray();
            var ZARpillarDatesDepoOIS = OISdepoTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray();
            var ZARpillarDatesOISSwap = oisTenors.Select(x => startDate.AddPeriod(RollType.MF, JHB, x)).ToArray();
            var ZARpillarDatesOIS     = ZARpillarDatesDepoOIS.Union(ZARpillarDatesOISSwap).Distinct().OrderBy(x => x).ToArray();


            var USDpillarDatesDepo    = depoTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray();
            var USDpillarDatesFRA     = FRATenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, new Frequency(x.Split('x')[1] + "M"))).ToArray();
            var USDpillarDatesSwap    = swapTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray();
            var USDpillarDates3m      = USDpillarDatesDepo.Union(USDpillarDatesSwap).Union(USDpillarDatesFRA).Distinct().OrderBy(x => x).ToArray();
            var USDpillarDatesDepoOIS = OISdepoTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray();
            var USDpillarDatesOISSwap = oisTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray();
            var USDpillarDatesOIS     = USDpillarDatesDepoOIS.Union(USDpillarDatesOISSwap).Distinct().OrderBy(x => x).ToArray();

            var fxForwardPillarDates = fxForwardTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray();
            var xcySwapDates         = xcySwapTenors.Select(x => startDate.AddPeriod(RollType.MF, _usd, x)).ToArray();
            var fxPillarDates        = fxForwardPillarDates.Union(xcySwapDates).Distinct().OrderBy(x => x).ToArray();


            var ZARswaps    = new IrSwap[swapTenors.Length];
            var ZARdepos    = new IrSwap[depoTenors.Length];
            var ZARdeposOIS = new IrSwap[OISdepoTenors.Length];
            var ZARoisSwaps = new IrBasisSwap[oisTenors.Length];
            var ZARFRAs     = new ForwardRateAgreement[FRATenors.Length];

            var USDswaps    = new IrSwap[swapTenors.Length];
            var USDdepos    = new IrSwap[depoTenors.Length];
            var USDdeposOIS = new IrSwap[OISdepoTenors.Length];
            var USDoisSwaps = new IrBasisSwap[oisTenors.Length];
            var USDFRAs     = new ForwardRateAgreement[FRATenors.Length];

            var fxForwards = new FxForward[fxForwardTenors.Length];
            var xcySwaps   = new XccyBasisSwap[xcySwapTenors.Length];

            var FIC = new FundingInstrumentCollection(TestProviderHelper.CurrencyProvider);

            for (var i = 0; i < FRATenors.Length; i++)
            {
                ZARFRAs[i] = new ForwardRateAgreement(startDate, FRATenors[i], FRAPricesZAR[i], _zar3m, SwapPayReceiveType.Payer, FraDiscountingType.Isda, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR")
                {
                    SolveCurve = "ZAR.JIBAR.3M"
                };
                FIC.Add(ZARFRAs[i]);
                USDFRAs[i] = new ForwardRateAgreement(startDate, FRATenors[i], FRAPricesUSD[i], usd3m, SwapPayReceiveType.Payer, FraDiscountingType.Isda, "USD.LIBOR.3M", "USD.DISC.CSA_USD")
                {
                    SolveCurve = "USD.LIBOR.3M"
                };
                FIC.Add(USDFRAs[i]);
            }

            for (var i = 0; i < oisTenors.Length; i++)
            {
                ZARoisSwaps[i] = new IrBasisSwap(startDate, oisTenors[i], oisPricesZAR[i], true, zaron, _zar3m, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR", "ZAR.DISC.CSA_ZAR")
                {
                    SolveCurve = "ZAR.DISC.CSA_ZAR"
                };
                FIC.Add(ZARoisSwaps[i]);
                USDoisSwaps[i] = new IrBasisSwap(startDate, oisTenors[i], oisPricesUSD[i], true, usdon, usd3m, "USD.LIBOR.3M", "USD.DISC.CSA_USD", "USD.DISC.CSA_USD")
                {
                    SolveCurve = "USD.DISC.CSA_USD"
                };
                FIC.Add(USDoisSwaps[i]);
            }

            for (var i = 0; i < swapTenors.Length; i++)
            {
                ZARswaps[i] = new IrSwap(startDate, swapTenors[i], _zar3m, swapPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR")
                {
                    SolveCurve = "ZAR.JIBAR.3M"
                };
                FIC.Add(ZARswaps[i]);
                USDswaps[i] = new IrSwap(startDate, swapTenors[i], usd3m, swapPricesUSD[i], SwapPayReceiveType.Payer, "USD.LIBOR.3M", "USD.DISC.CSA_USD")
                {
                    SolveCurve = "USD.LIBOR.3M"
                };
                FIC.Add(USDswaps[i]);
            }

            for (var i = 0; i < depoTenors.Length; i++)
            {
                ZARdepos[i] = new IrSwap(startDate, depoTenors[i], _zar3m, depoPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.JIBAR.3M", "ZAR.DISC.CSA_ZAR")
                {
                    SolveCurve = "ZAR.JIBAR.3M"
                };
                FIC.Add(ZARdepos[i]);
                USDdepos[i] = new IrSwap(startDate, depoTenors[i], usd3m, depoPricesUSD[i], SwapPayReceiveType.Payer, "USD.LIBOR.3M", "USD.DISC.CSA_USD")
                {
                    SolveCurve = "USD.LIBOR.3M"
                };
                FIC.Add(USDdepos[i]);
            }

            for (var i = 0; i < OISdepoTenors.Length; i++)
            {
                ZARdeposOIS[i] = new IrSwap(startDate, OISdepoTenors[i], zaron, OISdepoPricesZAR[i], SwapPayReceiveType.Payer, "ZAR.DISC.CSA_ZAR", "ZAR.DISC.CSA_ZAR")
                {
                    SolveCurve = "ZAR.DISC.CSA_ZAR"
                };
                FIC.Add(ZARdeposOIS[i]);
                USDdeposOIS[i] = new IrSwap(startDate, OISdepoTenors[i], usdon, OISdepoPricesUSD[i], SwapPayReceiveType.Payer, "USD.DISC.CSA_USD", "USD.DISC.CSA_USD")
                {
                    SolveCurve = "USD.DISC.CSA_USD"
                };
                FIC.Add(USDdeposOIS[i]);
            }

            for (var i = 0; i < fxForwards.Length; i++)
            {
                fxForwards[i] = new FxForward
                {
                    SolveCurve           = "ZAR.DISC.CSA_USD",
                    DeliveryDate         = fxForwardPillarDates[i],
                    DomesticCCY          = ccyUsd,
                    ForeignCCY           = ccyZar,
                    DomesticQuantity     = 1e6 / fxForwardPrices[i],
                    Strike               = fxForwardPrices[i],
                    ForeignDiscountCurve = "ZAR.DISC.CSA_USD",
                };
                FIC.Add(fxForwards[i]);
            }

            for (var i = 0; i < xcySwapTenors.Length; i++)
            {
                xcySwaps[i] = new XccyBasisSwap(startDate, xcySwapTenors[i], xcySwapPrices[i], true, usd3m, _zar3m, ExchangeType.Both, MTMSwapType.ReceiveNotionalFixed, "USD.LIBOR.3M", "ZAR.JIBAR.3M", "USD.DISC.CSA_USD", "ZAR.DISC.CSA_USD")
                {
                    SolveCurve = "ZAR.DISC.CSA_USD"
                };
                FIC.Add(xcySwaps[i]);
            }

            var ZARcurve3m = new IrCurve(ZARpillarDates3m, new double[ZARpillarDates3m.Length], startDate, "ZAR.JIBAR.3M", Interpolator1DType.LinearFlatExtrap, ccyZar)
            {
                SolveStage = 0
            };
            var ZARcurveOIS = new IrCurve(ZARpillarDatesOIS, new double[ZARpillarDatesOIS.Length], startDate, "ZAR.DISC.CSA_ZAR", Interpolator1DType.LinearFlatExtrap, ccyZar)
            {
                SolveStage = 0
            };
            var USDcurve3m = new IrCurve(USDpillarDates3m, new double[USDpillarDates3m.Length], startDate, "USD.LIBOR.3M", Interpolator1DType.LinearFlatExtrap, ccyUsd)
            {
                SolveStage = 1
            };
            var USDcurveOIS = new IrCurve(USDpillarDatesOIS, new double[USDpillarDatesOIS.Length], startDate, "USD.DISC.CSA_USD", Interpolator1DType.LinearFlatExtrap, ccyUsd)
            {
                SolveStage = 1
            };
            var fxCurve = new IrCurve(fxPillarDates, new double[fxPillarDates.Length], startDate, "ZAR.DISC.CSA_USD", Interpolator1DType.LinearFlatExtrap, ccyZar)
            {
                SolveStage = 2
            };


            var engine = new FundingModel(startDate, new IrCurve[] { ZARcurve3m, ZARcurveOIS, USDcurve3m, USDcurveOIS, fxCurve }, TestProviderHelper.CurrencyProvider, TestProviderHelper.CalendarProvider);

            var fxMatrix  = new FxMatrix(TestProviderHelper.CurrencyProvider);
            var spotRates = new Dictionary <Currency, double>
            {
                { ccyZar, fxSpot }
            };
            var fxPairs = new List <FxPair>
            {
                new FxPair {
                    Domestic = ccyUsd, Foreign = ccyZar, SettlementCalendar = _usd, SpotLag = new Frequency("2b")
                }
            };
            var discountMap = new Dictionary <Currency, string>
            {
                { ccyUsd, "USD.DISC.CSA_USD" },
                { ccyZar, "ZAR.DISC.CSA_USD" },
            };

            fxMatrix.Init(ccyUsd, startDate, spotRates, fxPairs, discountMap);
            engine.SetupFx(fxMatrix);

            var S = new NewtonRaphsonMultiCurveSolverStaged()
            {
                Tollerance     = IsCoverageOnly ? 1 : 0.00000001,
                MaxItterations = IsCoverageOnly ? 1 : 100,
            };

            S.Solve(engine, FIC);

            if (!IsCoverageOnly)
            {
                foreach (var ins in FIC)
                {
                    var pv = ins.Pv(engine, false);
                    Assert.Equal(0.0, pv, 7);
                }
            }
        }