public BlackFuturesCurve(IATMVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <DateTime, double> forwardCurve, string name, IFutureSettingsProvider futureSettingsProvider, Dictionary <DateTime, double> pastFixings = null) { _surface = volSurface; _startDate = startDate; _expiryDate = expiryDate; _numberOfSteps = nTimeSteps; _name = name; _forwardCurve = forwardCurve; _pastFixings = pastFixings ?? (new Dictionary <DateTime, double>()); _futureSettingsProvider = futureSettingsProvider; if (startDate > expiryDate) { throw new Exception("Start date must be before expiry date"); } _codes = new List <string>(); _futuresExpiries = new List <DateTime>(); var fCode = new FutureCode(name, _futureSettingsProvider); var currentCode = fCode.GetFrontMonth(startDate); _codes.Add(currentCode); fCode = new FutureCode(currentCode, DateTime.Today.Year - 2, _futureSettingsProvider); _futuresExpiries.Add(fCode.GetRollDate()); fCode = new FutureCode(currentCode, DateTime.Today.Year - 2, _futureSettingsProvider); var targetCode = fCode.GetFrontMonth(expiryDate); while (currentCode != targetCode) { currentCode = fCode.GetNextCode(false); _futuresExpiries.Add(fCode.GetRollDate()); _codes.Add(currentCode); } }
public BlackSingleAsset(IATMVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <double, double> forwardCurve, string name) { _surface = volSurface; _startDate = startDate; _expiryDate = expiryDate; _numberOfSteps = nTimeSteps; _name = name; _forwardCurve = forwardCurve; }
public SimpleAveragePathCorrector(SimpleAveragePathCalculator pathCalc, IATMVolSurface volSurface, Func <double, double> forwardCurve, string name, Dictionary <DateTime, double> pastFixings = null, IATMVolSurface fxAdjustSurface = null, double fxAssetCorrelation = 0.0) { PathCalc = pathCalc; _surface = volSurface; _name = name; _forwardCurve = forwardCurve; _pastFixings = pastFixings ?? (new Dictionary <DateTime, double>()); _adjSurface = fxAdjustSurface; _correlation = fxAssetCorrelation; }
public LVSingleAsset(IVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <double, double> forwardCurve, string name, Dictionary <DateTime, double> pastFixings = null, IATMVolSurface fxAdjustSurface = null, double fxAssetCorrelation = 0.0) { _surface = volSurface; _startDate = startDate; _expiryDate = expiryDate; _numberOfSteps = nTimeSteps; _name = name; _pastFixings = pastFixings ?? (new Dictionary <DateTime, double>()); _forwardCurve = forwardCurve; _adjSurface = fxAdjustSurface; _correlation = fxAssetCorrelation; }
public BlackSingleAsset(IATMVolSurface volSurface, DateTime startDate, DateTime expiryDate, int nTimeSteps, Func <double, double> forwardCurve, string name, Dictionary <DateTime, double> pastFixings = null, IATMVolSurface fxAdjustSurface = null, double fxAssetCorrelation = 0.0) { _surface = volSurface; _startDate = startDate; _expiryDate = expiryDate; _numberOfSteps = nTimeSteps; _name = name; _forwardCurve = forwardCurve; _pastFixings = pastFixings ?? (new Dictionary <DateTime, double>()); _adjSurface = fxAdjustSurface; _correlation = fxAssetCorrelation; if (volSurface is InverseFxSurface || (_adjSurface != null && _adjSurface?.AssetId == volSurface.AssetId)) { _siegelInvert = true; } if (_adjSurface != null && _adjSurface?.AssetId == volSurface.AssetId) { _adjSurface = null; } }
public AssetFxMCModel(DateTime originDate, Portfolio portfolio, IAssetFxModel model, McSettings settings, ICurrencyProvider currencyProvider, IFutureSettingsProvider futureSettingsProvider, ICalendarProvider calendarProvider) { if (settings.CompactMemoryMode && settings.AveragePathCorrection) { throw new Exception("Can't use both CompactMemoryMode and PathCorrection"); } _currencyProvider = currencyProvider; _futureSettingsProvider = futureSettingsProvider; _calendarProvider = calendarProvider; Engine = new PathEngine(settings.NumberOfPaths) { Parallelize = settings.Parallelize, CompactMemoryMode = settings.CompactMemoryMode }; OriginDate = originDate; Portfolio = portfolio; Model = model; Settings = settings; switch (settings.Generator) { case RandomGeneratorType.MersenneTwister: Engine.AddPathProcess(new Random.MersenneTwister.MersenneTwister64() { UseNormalInverse = true, UseAnthithetic = false }); break; case RandomGeneratorType.Sobol: var directionNumers = new Random.Sobol.SobolDirectionNumbers(GetSobolFilename()); Engine.AddPathProcess(new Random.Sobol.SobolPathGenerator(directionNumers, 1000) { UseNormalInverse = true }); break; case RandomGeneratorType.Constant: Engine.AddPathProcess(new Random.Constant.Constant() { UseNormalInverse = true, }); break; case RandomGeneratorType.FlipFlop: Engine.AddPathProcess(new Random.Constant.FlipFlop(settings.CreditSettings.ConfidenceInterval, true)); break; } Engine.IncrementDepth(); if (model.CorrelationMatrix != null) { if (settings.LocalCorrelation) { Engine.AddPathProcess(new CholeskyWithTime(model.CorrelationMatrix, model)); } else { Engine.AddPathProcess(new Cholesky(model.CorrelationMatrix)); } Engine.IncrementDepth(); } var lastDate = portfolio.LastSensitivityDate; var assetIds = portfolio.AssetIds(); var assetInstruments = portfolio.Instruments .Where(x => x is IAssetInstrument) .Select(x => x as IAssetInstrument); var fixingsNeeded = new Dictionary <string, List <DateTime> >(); foreach (var ins in assetInstruments) { var fixingsForIns = ins.PastFixingDates(originDate); if (fixingsForIns.Any()) { foreach (var kv in fixingsForIns) { if (!fixingsNeeded.ContainsKey(kv.Key)) { fixingsNeeded.Add(kv.Key, new List <DateTime>()); } fixingsNeeded[kv.Key] = fixingsNeeded[kv.Key].Concat(kv.Value).Distinct().ToList(); } } } //asset processes var fxAssetsToAdd = new List <string>(); var corrections = new Dictionary <string, SimpleAveragePathCorrector>(); foreach (var assetId in assetIds) { if (assetId.Length == 7 && assetId[3] == '/') { fxAssetsToAdd.Add(assetId); continue; } if (!(model.GetVolSurface(assetId) is IATMVolSurface surface)) { throw new Exception($"Vol surface for asset {assetId} could not be cast to IATMVolSurface"); } var fixingDict = fixingsNeeded.ContainsKey(assetId) ? model.GetFixingDictionary(assetId) : null; var fixings = fixingDict != null ? fixingsNeeded[assetId].ToDictionary(x => x, x => fixingDict.GetFixing(x)) : new Dictionary <DateTime, double>(); var futuresSim = settings.ExpensiveFuturesSimulation && (model.GetPriceCurve(assetId).CurveType == PriceCurveType.ICE || model.GetPriceCurve(assetId).CurveType == PriceCurveType.NYMEX); if (futuresSim) { var fwdCurve = new Func <DateTime, double>(t => { return(model.GetPriceCurve(assetId).GetPriceForDate(t)); }); var asset = new BlackFuturesCurve ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: Settings.FuturesMappingTable[assetId], pastFixings: fixings, futureSettingsProvider: _futureSettingsProvider ); Engine.AddPathProcess(asset); } else { var fwdCurve = new Func <double, double>(t => { var c = model.GetPriceCurve(assetId); var d = originDate.AddYearFraction(t, DayCountBasis.ACT365F); if (c is PriceCurve pc) { d = d.AddPeriod(RollType.F, pc.SpotCalendar, pc.SpotLag); } else if (c is ContangoPriceCurve cc) { d = d.AddPeriod(RollType.F, cc.SpotCalendar, cc.SpotLag); } return(c.GetPriceForDate(d)); }); IATMVolSurface adjSurface = null; var correlation = 0.0; if (settings.ReportingCurrency != model.GetPriceCurve(assetId).Currency) { var fxAdjPair = settings.ReportingCurrency + "/" + model.GetPriceCurve(assetId).Currency; var fxAdjPairInv = model.GetPriceCurve(assetId).Currency + "/" + settings.ReportingCurrency; if (!(model.FundingModel.GetVolSurface(fxAdjPair) is IATMVolSurface adjSurface2)) { throw new Exception($"Vol surface for fx pair {fxAdjPair} could not be cast to IATMVolSurface"); } adjSurface = adjSurface2; if (model.CorrelationMatrix != null) { if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPair, assetId, out var correl)) { correlation = correl; } else if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPairInv, assetId, out var correl2)) { correlation = -correl2; } } } if (settings.McModelType == McModelType.LocalVol) { var asset = new LVSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: assetId, pastFixings: fixings, fxAdjustSurface: adjSurface, fxAssetCorrelation: correlation ); Engine.AddPathProcess(asset); } else if (settings.McModelType == McModelType.TurboSkew) { var asset = new TurboSkewSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: assetId, pastFixings: fixings, fxAdjustSurface: adjSurface, fxAssetCorrelation: correlation ); Engine.AddPathProcess(asset); } else { var asset = new BlackSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: assetId, pastFixings: fixings, fxAdjustSurface: adjSurface, fxAssetCorrelation: correlation ); Engine.AddPathProcess(asset); } if (settings.AveragePathCorrection) { corrections.Add(assetId, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(assetId) { CompactMode = settings.CompactMemoryMode }, surface, fwdCurve, assetId, fixings, adjSurface, correlation)); } } } //fx pairs var pairsAdded = new List <string>(); var fxPairs = portfolio.FxPairs(model).Concat(fxAssetsToAdd); var payoutCcys = portfolio.Instruments.Select(i => i.Currency); if (payoutCcys.Any(p => p != settings.ReportingCurrency)) { var ccysToAdd = payoutCcys.Where(p => p != settings.ReportingCurrency).Distinct(); var pairsToAdd = ccysToAdd.Select(c => $"{c.Ccy}/{settings.ReportingCurrency}"); fxPairs = fxPairs.Concat(pairsToAdd).Distinct(); } foreach (var fxPair in fxPairs) { var fxPairName = fxPair; var pair = fxPairName.FxPairFromString(_currencyProvider, _calendarProvider); if (pairsAdded.Contains(pair.ToString())) { continue; } if (!(model.FundingModel.VolSurfaces[fxPairName] is IATMVolSurface surface)) { throw new Exception($"Vol surface for fx pair {fxPairName} could not be cast to IATMVolSurface"); } var fwdCurve = new Func <double, double>(t => { var date = originDate.AddYearFraction(t, DayCountBasis.ACT365F); var spotDate = pair.SpotDate(date); return(model.FundingModel.GetFxRate(spotDate, fxPairName)); }); pairsAdded.Add(pair.ToString()); if (settings.McModelType == McModelType.LocalVol) { var asset = new LVSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: fxPairName ); Engine.AddPathProcess(asset); if (settings.AveragePathCorrection) { corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName) { CompactMode = settings.CompactMemoryMode }, surface, fwdCurve, fxPairName)); } } else if (settings.McModelType == McModelType.TurboSkew) { if (fxPairName.Substring(fxPairName.Length - 3, 3) != settings.ReportingCurrency) {//needs to be drift-adjusted var fxAdjPair = settings.ReportingCurrency + "/" + fxPairName.Substring(fxPairName.Length - 3, 3); if (!(model.FundingModel.VolSurfaces[fxAdjPair] is IATMVolSurface adjSurface)) { throw new Exception($"Vol surface for fx pair {fxAdjPair} could not be cast to IATMVolSurface"); } var correlation = fxPair == fxAdjPair ? -1.0 : 0.0; if (correlation != -1.0 && model.CorrelationMatrix != null) { if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPair, fxPair, out var correl)) { correlation = correl; } } var asset = new TurboSkewSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: fxPairName, fxAdjustSurface: adjSurface, fxAssetCorrelation: correlation ); Engine.AddPathProcess(asset); if (settings.AveragePathCorrection) { corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName) { CompactMode = settings.CompactMemoryMode }, surface, fwdCurve, fxPairName, null, adjSurface, correlation)); } } else { var asset = new TurboSkewSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: fxPairName ); Engine.AddPathProcess(asset); if (settings.AveragePathCorrection) { corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName) { CompactMode = settings.CompactMemoryMode }, surface, fwdCurve, fxPairName)); } } } else { if (fxPairName.Substring(fxPairName.Length - 3, 3) != settings.ReportingCurrency) {//needs to be drift-adjusted var fxAdjPair = settings.ReportingCurrency + "/" + fxPairName.Substring(fxPairName.Length - 3, 3); if (!(model.FundingModel.VolSurfaces[fxAdjPair] is IATMVolSurface adjSurface)) { throw new Exception($"Vol surface for fx pair {fxAdjPair} could not be cast to IATMVolSurface"); } var correlation = fxPair == fxAdjPair ? -1.0 : 0.0; if (correlation != -1.0 && model.CorrelationMatrix != null) { if (model.CorrelationMatrix.TryGetCorrelation(fxAdjPair, fxPair, out var correl)) { correlation = correl; } } var asset = new BlackSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: fxPairName, fxAdjustSurface: adjSurface, fxAssetCorrelation: correlation ); Engine.AddPathProcess(asset); if (settings.AveragePathCorrection) { corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName) { CompactMode = settings.CompactMemoryMode }, surface, fwdCurve, fxPairName, null, adjSurface, correlation)); } } else { var asset = new BlackSingleAsset ( startDate: originDate, expiryDate: lastDate, volSurface: surface, forwardCurve: fwdCurve, nTimeSteps: settings.NumberOfTimesteps, name: fxPairName ); Engine.AddPathProcess(asset); if (settings.AveragePathCorrection) { corrections.Add(fxPairName, new SimpleAveragePathCorrector(new SimpleAveragePathCalculator(fxPairName) { CompactMode = settings.CompactMemoryMode }, surface, fwdCurve, fxPairName)); } } } } //apply path correctin if (settings.AveragePathCorrection && corrections.Any()) { Engine.IncrementDepth(); foreach (var pc in corrections) { Engine.AddPathProcess(pc.Value.PathCalc); } Engine.IncrementDepth(); foreach (var pc in corrections) { Engine.AddPathProcess(pc.Value); } } //payoffs Engine.IncrementDepth(); _payoffs = assetInstruments.ToDictionary(x => x.TradeId, y => new AssetPathPayoff(y, _currencyProvider, _calendarProvider, settings.ReportingCurrency)); if (!settings.AvoidRegressionForBackPricing && _payoffs.Any(x => x.Value.Regressors != null)) { var regressorsToAdd = _payoffs.Where(x => x.Value.Regressors != null) .SelectMany(x => x.Value.Regressors) .Distinct(); foreach (var regressor in regressorsToAdd) { Engine.AddPathProcess(regressor); foreach (var payoff in _payoffs.Where(x => x.Value.Regressors != null)) { if (payoff.Value.Regressors.Any(x => x == regressor)) { payoff.Value.SetRegressor(regressor); } } } Engine.IncrementDepth(); } foreach (var product in _payoffs) { if (settings.AvoidRegressionForBackPricing && (product.Value.AssetInstrument is BackPricingOption || product.Value.AssetInstrument is MultiPeriodBackpricingOption)) { product.Value.VanillaModel = VanillaModel; } Engine.AddPathProcess(product.Value); } var metricsNeedRegression = new[] { BaseMetric.PFE, BaseMetric.KVA, BaseMetric.CVA, BaseMetric.FVA, BaseMetric.EPE }; //Need to calculate PFE if (settings.CreditSettings != null && settings.CreditSettings.ExposureDates != null && settings.ReportingCurrency != null && metricsNeedRegression.Contains(settings.CreditSettings.Metric))//setup for PFE, etc { Engine.IncrementDepth(); switch (settings.CreditSettings.PfeRegressorType) { case PFERegressorType.MultiLinear: _regressor = new LinearPortfolioValueRegressor(settings.CreditSettings.ExposureDates, _payoffs.Values.ToArray(), settings); break; case PFERegressorType.MonoLinear: _regressor = new MonoIndexRegressor(settings.CreditSettings.ExposureDates, _payoffs.Values.ToArray(), settings, true); break; } Engine.AddPathProcess(_regressor); } //Need to calculate expected capital if (settings.CreditSettings != null && settings.CreditSettings.ExposureDates != null && settings.ReportingCurrency != null && settings.CreditSettings.Metric == BaseMetric.ExpectedCapital) { Engine.IncrementDepth(); _capitalCalc = new ExpectedCapitalCalculator(Portfolio, settings.CreditSettings.CounterpartyRiskWeighting, settings.CreditSettings.AssetIdToHedgeGroupMap, settings.ReportingCurrency, VanillaModel, settings.CreditSettings.ExposureDates); Engine.AddPathProcess(_capitalCalc); } Engine.SetupFeatures(); }
public InverseFxSurface(string Name, IATMVolSurface fxSurface, ICurrencyProvider currencyProvider) { FxSurface = fxSurface; _currencyProvider = currencyProvider; this.Name = Name; }