-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b400ab7
commit 6f2e54a
Showing
5 changed files
with
214 additions
and
319 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.Extensions.Logging; | ||
using Qwack.Core.Basic; | ||
using Qwack.Core.Cubes; | ||
using Qwack.Core.Instruments; | ||
using Qwack.Core.Models; | ||
using Qwack.Dates; | ||
using Qwack.Futures; | ||
using Qwack.Models.MCModels; | ||
using Qwack.Models.Risk.Mutators; | ||
using Qwack.Options.VolSurfaces; | ||
using Qwack.Transport.Results; | ||
|
||
namespace Qwack.Models.Risk.VaR | ||
{ | ||
public class McVaRCalculator | ||
{ | ||
private readonly IAssetFxModel _model; | ||
private readonly Portfolio _portfolio; | ||
private ICube _basePvCube; | ||
private readonly ILogger _logger; | ||
private readonly ICurrencyProvider _currencyProvider; | ||
private readonly ICalendarProvider _calendarProvider; | ||
private readonly IFutureSettingsProvider _futureSettingsProvider; | ||
private readonly McModelType _modelType; | ||
private readonly List<IAssetFxModel> _bumpedModels = new(); | ||
private readonly Dictionary<string, double> _spotFactors = new(); | ||
private readonly Dictionary<string, double[]> _returns = new(); | ||
private int _ciIx = 0; | ||
private VaREngine _varEngine; | ||
|
||
public int CIIX => _ciIx; | ||
|
||
public McVaRCalculator(IAssetFxModel model, Portfolio portfolio, ILogger logger, ICurrencyProvider currencyProvider, | ||
ICalendarProvider calendarProvider, IFutureSettingsProvider futureSettingsProvider, McModelType modelType) | ||
{ | ||
_model = model.Clone(); | ||
_portfolio = portfolio; | ||
_logger = logger; | ||
_currencyProvider = currencyProvider; | ||
_calendarProvider = calendarProvider; | ||
_futureSettingsProvider = futureSettingsProvider; | ||
_modelType = modelType; | ||
} | ||
|
||
public void AddSpotFactor(string assetId, double vol) | ||
{ | ||
_spotFactors[assetId] = vol; | ||
} | ||
|
||
public void AddReturns(string assetId, double[] returns) | ||
{ | ||
_returns[assetId] = returns; | ||
} | ||
|
||
public string[] GetSpotFactors() => _spotFactors.Keys.OrderBy(x => x).ToArray(); | ||
|
||
public void SetCorrelationMatrix(ICorrelationMatrix matrix) => _model.CorrelationMatrix = matrix; | ||
|
||
public void CalculateModels() | ||
{ | ||
//var allAssetIds = _portfolio.AssetIds().Concat(_portfolio.Instruments.Select(x => x.Currency.Ccy).Where(x => x != "USD").Select(x =>$"USD/{x}")).ToArray(); | ||
var allAssetIds = _model.CurveNames.Concat(_portfolio.Instruments.Select(x => x.Currency.Ccy).Where(x => x != "USD").Select(x => $"USD/{x}")).ToArray(); | ||
var simulatedIds = allAssetIds.Intersect(_spotFactors.Keys).ToArray(); | ||
|
||
foreach (var simulatedId in simulatedIds) | ||
{ | ||
var surf = new ConstantVolSurface(_model.BuildDate, _spotFactors[simulatedId]) { AssetId = simulatedId }; | ||
if (_returns.TryGetValue(simulatedId, out var returns)) | ||
surf.Returns = returns; | ||
_model.AddVolSurface(simulatedId, surf); | ||
if (simulatedId.Length == 6 && simulatedId[3] == '/') | ||
{ | ||
_model.FundingModel.VolSurfaces.Add(simulatedId, surf); | ||
} | ||
} | ||
|
||
_logger.LogInformation("Simulating {nFac} spot factors", simulatedIds.Length); | ||
|
||
var mcSettings = new McSettings | ||
{ | ||
McModelType = _modelType, | ||
Generator = RandomGeneratorType.MersenneTwister, | ||
NumberOfPaths = 2048, | ||
NumberOfTimesteps = 2, | ||
ReportingCurrency = _currencyProvider.GetCurrencySafe("USD") | ||
}; | ||
|
||
var vd = _model.BuildDate.AddDays(1); | ||
var fp = new FactorReturnPayoff(simulatedIds, new DateTime[] { _model.BuildDate, vd }); | ||
|
||
var mcModel = new AssetFxMCModel(_model.BuildDate, fp, _model, mcSettings, _currencyProvider, _futureSettingsProvider, _calendarProvider); | ||
mcModel.Engine.RunProcess(); | ||
|
||
var dix = fp.DateIndices[vd]; | ||
for (var p = 0; p < mcSettings.NumberOfPaths; p++) | ||
{ | ||
var pModel = _model.Clone(); | ||
for (var a = 0; a < simulatedIds.Length; a++) | ||
{ | ||
var price0 = fp.ResultsByPath[a][p][0]; | ||
var price1 = fp.ResultsByPath[a][p][dix]; | ||
var bump = price1 / price0 - 1.0; | ||
|
||
if (IsFx(simulatedIds[a])) | ||
pModel = RelativeShiftMutator.FxSpotShift(_currencyProvider.GetCurrencySafe(simulatedIds[a].Split('/').Last()), bump, pModel); | ||
else | ||
pModel = RelativeShiftMutator.AssetCurveShift(simulatedIds[a], bump, pModel); | ||
} | ||
|
||
_bumpedModels.Add(pModel); | ||
} | ||
|
||
_varEngine = new VaREngine(_logger, _model, _portfolio, _bumpedModels.Select((x, ix) => (ix, x)).ToDictionary(kv => kv.ix.ToString(), kv => kv.x)); | ||
} | ||
|
||
private static bool IsFx(string assetId) => assetId.Length == 7 && assetId[3] == '/'; | ||
|
||
public (double VaR, string ScenarioId, double cVaR) CalculateVaR(double ci, Currency ccy, string[] excludeTradeIds) | ||
=> _varEngine.CalculateVaR(ci, ccy, excludeTradeIds); | ||
|
||
public (double VaR, string ScenarioId, double cVaR) CalculateVaRInc(double ci, Currency ccy, string[] includeTradeIds) | ||
=> _varEngine.CalculateVaRInc(ci, ccy, includeTradeIds); | ||
|
||
public double[] CalculateVaRRange(double[] cis) => _varEngine.CalculateVaRRange(cis); | ||
|
||
public Dictionary<string, double> GetBaseValuations() => _varEngine.GetBaseValuations(); | ||
|
||
public Dictionary<string, double> GetContributions(int ix) => _varEngine.GetContributions(ix.ToString()); | ||
|
||
public decimal ComputeStress(string insId, decimal shockSize, int? nNearestSamples = null) | ||
=> _varEngine.ComputeStress(insId, shockSize, nNearestSamples); | ||
|
||
public StressTestResult ComputeStressObject(string insId, decimal shockSize, int? nNearestSamples = null) | ||
=> _varEngine.ComputeStressObject(insId, shockSize, nNearestSamples); | ||
|
||
public (double VaR, string ScenarioId, double cVaR) CalculateVaR(double ci, Currency ccy) => CalculateVaR(ci, ccy, _portfolio); | ||
|
||
public (double VaR, string ScenarioId, double cVaR) CalculateVaR(double ci, Currency ccy, Portfolio pf, bool parallelize = true) | ||
=> _varEngine.CalculateVaR(ci, ccy, pf, parallelize); | ||
} | ||
} |
Oops, something went wrong.