Example #1
0
        public static ICube Calculate(IAssetFxModel model, Portfolio portfolio, double confidenceInterval, Currency reportingCcy, ICurrencyProvider currencyProvider,
                                      ICalendarProvider calendarProvider, DateTime[] exposureDates = null, DatePeriodType sampleFreq = DatePeriodType.Month, bool correlationCorrection = true)
        {
            var types = portfolio.Instruments.Select(x => x.GetType()).Distinct();

            if (!types.All(t => AllowedTypes.Contains(t)))
            {
                throw new Exception("Unsupported instrument types detected");
            }

            var pf       = portfolio.UnStripStrips();
            var assetIns = pf.Instruments.Select(x => ((IAssetInstrument)x));
            //check everything facting in same direction
            var pos = assetIns.Select(x => x.IsLongDeltaPosition()).Distinct();

            if (pos.Count() > 1)
            {
                throw new Exception("All trades must have same delta direction");
            }

            //check everything same asset/currency
            var keys = assetIns.Select(x => $"{x.Currency}~{string.Join("-",x.AssetIds)}").Distinct();

            if (keys.Count() > 1)
            {
                throw new Exception("All trades must have same underlying and currency");
            }

            //flip tail of distribution if we are short
            var ci = pos.Single() ? confidenceInterval : 1.0 - confidenceInterval;

            if (exposureDates == null)
            {
                exposureDates = pf.ComputeSimDates(model.BuildDate, sampleFreq);
            }

            var m = model.TrimModel(portfolio);

            var day0Pv = 0.0;

            if (exposureDates.Contains(model.BuildDate))
            {
                day0Pv = Max(0, pf.PV(m, reportingCcy, true).SumOfAllRows);
            }
            //adjust fx surface for correlation if needed
            var pairs = assetIns.Select(x => x.FxPair(model)).Where(x => !string.IsNullOrEmpty(x));

            if (correlationCorrection && pairs.Any())
            {
                var pd = pairs.Distinct();
                if (pd.Count() != 1)
                {
                    throw new Exception("Expecting a single Fx pair, if any");
                }
                var pair    = pd.Single();
                var assetId = assetIns.SelectMany(x => x.AssetIds).Distinct().Single();
                var(fxSurface, assetSurface)     = model.ImplySurfaceToCorrelation(assetId, pair, assetIns.First().Currency, currencyProvider);
                m.FundingModel.VolSurfaces[pair] = fxSurface;
                m.AddVolSurface(assetId, assetSurface);
            }

            var fxPairsToRoll = assetIns.SelectMany(x => x.AssetIds).Where(x => x.Length == 7 && x.Substring(3, 1) == "/")
                                .Concat(assetIns.Select(x => x.FxPair(model)))
                                .Where(x => !string.IsNullOrWhiteSpace(x))
                                .Distinct().ToList();

            var o = new double[exposureDates.Length];

            for (var i = 0; i < exposureDates.Length; i++)
            {
                var mm = m.RollModelPfe(exposureDates[i], ci, currencyProvider, calendarProvider, fxPairsToRoll);
                o[i] = exposureDates[i] == model.BuildDate ? day0Pv : Max(0, pf.PV(mm, reportingCcy, true).SumOfAllRows);
            }

            return(PackToCube(exposureDates, o, "PFE"));
        }