private void Initialize() { var pillarsAsDoubles = _pillarDates.Select(x => x.ToOADate()).ToArray(); switch (_curveType) { case PriceCurveType.Linear: _interp = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, _prices, Interpolator1DType.Linear); break; case PriceCurveType.Next: _interp = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, _prices, Interpolator1DType.NextValue); break; case PriceCurveType.NextButOnExpiry: pillarsAsDoubles = pillarsAsDoubles.Select(x => x - 1).ToArray(); _interp = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, _prices, Interpolator1DType.NextValue); break; case PriceCurveType.Constant: _interp = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, _prices, Interpolator1DType.DummyPoint); break; default: throw new Exception($"Unkown price curve type {_curveType}"); } }
public HazzardCurve Solve(List <CDS> instruments, double recoveryRate, IIrCurve discountCurve, DateTime buildDate, DayCountBasis basis = DayCountBasis.ACT365F) { _curveInstruments = instruments; _pillars = instruments.OrderBy(x => x.FinalSensitivityDate).Select(c => c.FinalSensitivityDate).ToArray(); _pillarsT = _pillars.Select(p => buildDate.CalculateYearFraction(p, basis)).ToArray(); _numberOfInstruments = _curveInstruments.Count; _numberOfPillars = _pillars.Length; _discountCurve = discountCurve; _buildDate = buildDate; _basis = basis; _recoveryRate = recoveryRate; _currentGuess = instruments.OrderBy(x => x.FinalSensitivityDate).Select((x, ix) => x.Spread / (1.0 - recoveryRate)).ToArray(); _currentCurve = new LinearHazzardInterpolator(_pillarsT, _currentGuess); _currentPVs = ComputePVs(); ComputeJacobian(); for (var i = 0; i < MaxItterations; i++) { ComputeNextGuess(); _currentCurve = new LinearHazzardInterpolator(_pillarsT, _currentGuess); _currentPVs = ComputePVs(); if (_currentPVs.Max(x => System.Math.Abs(x)) < Tollerance) { UsedItterations = i + 1; break; } ComputeJacobian(); } return(new HazzardCurve(_buildDate, _basis, _currentCurve)); }
public static IInterpolator1D RegressNotContinuous(double[] Xs, double[] Ys, int nSegments) { var nSamples = Xs.Length; //var x = new double[nSegments + 1]; //var y = new double[nSegments + 1]; var samplesPerSegment = nSamples / nSegments; var interps = new IInterpolator1D[nSegments]; var uBounds = new double[nSegments]; for (var i = 0; i < nSegments; i++) { var sampleXs = Xs.Skip(i * samplesPerSegment).Take(samplesPerSegment).ToArray(); var sampleYs = Ys.Skip(i * samplesPerSegment).Take(samplesPerSegment).ToArray(); var lr = LinearRegression.LinearRegressionVector(sampleXs, sampleYs); var xLo = sampleXs.First(); var xHi = sampleXs.Last(); var yLo = lr.Alpha + lr.Beta * xLo; var yHi = lr.Alpha + lr.Beta * xHi; interps[i] = InterpolatorFactory.GetInterpolator(new[] { xLo, xHi }, new[] { yLo, yHi }, Interpolator1DType.Linear); uBounds[i] = xHi; } uBounds[uBounds.Length - 1] = double.MaxValue; return(new NonContinuousInterpolator(uBounds, interps)); }
private void DumpDataToDisk(KeyValuePair <double, double>[] data, IInterpolator1D fitted, string fileName) { var header = new[] { "X,Y,YFited" }; var linesToWrite = header.Concat(data.Select(x => string.Join(",", x.Key, x.Value, fitted.Interpolate(x.Key)))).ToArray(); System.IO.File.WriteAllLines(fileName, linesToWrite); }
public void Build(DateTime originDate, double[][] strikes, DateTime[] expiries, double[][] vols, Func <double, double> forwardCurve) { OriginDate = originDate; Expiries = expiries; ExpiriesDouble = Expiries.Select(t => TimeBasis.CalculateYearFraction(originDate, t)).ToArray(); if (Expiries.Length != strikes.Length) { throw new InvalidOperationException("Expiries and first dimension of Strikes must of same length"); } if (Expiries.Length != vols.Length) { throw new InvalidOperationException("Expiries and first dimension of Vols must of same length"); } Alphas = new double[Expiries.Length]; Betas = new double[Expiries.Length]; Nus = new double[Expiries.Length]; Rhos = new double[Expiries.Length]; for (var i = 0; i < expiries.Length; i++) { var vs = vols[i]; var ks = strikes[i]; var t = ExpiriesDouble[i]; var fwd = forwardCurve(t); Betas[i] = 1.0; Func <double[], double[]> errorFunc = (x => { var err = ks.Select((k, ix) => vs[ix] - SABR.CalcImpVol_Beta1(fwd, k, t, x[0], x[1], x[2])); return(err.ToArray()); }); var n2Sol = new Math.Solvers.GaussNewton { ObjectiveFunction = errorFunc, InitialGuess = new double[] { vs.Average(), 0.1, 0.1 }, Tollerance = 1e-8, JacobianBump = 0.0000001 }; var paramArr = n2Sol.Solve(); Alphas[i] = paramArr[0]; Rhos[i] = paramArr[1]; Nus[i] = paramArr[2]; } var fwds = ExpiriesDouble.Select(x => forwardCurve(x)).ToArray(); _alphaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Alphas, TimeInterpolatorType); _betaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Betas, TimeInterpolatorType); _rhoInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Rhos, TimeInterpolatorType); _nuInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Nus, TimeInterpolatorType); _fwdsInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, TimeInterpolatorType); }
public IInterpolator1D[] Regress(IAssetFxModel model) { if (_regressors != null) { return(_regressors); } var o = new IInterpolator1D[_dateIndexes.Length]; var nPaths = _pathwiseValues.First().Length; var finalSchedules = _portfolio.Select(x => x.ExpectedFlowsByPath(model)).ToArray(); ParallelUtils.Instance.For(0, _dateIndexes.Length, 1, d => { var exposureDate = _regressionDates[d]; var sortedFinalValues = new KeyValuePair <double, double> [nPaths]; for (var p = 0; p < nPaths; p++) { var finalValue = 0.0; foreach (var schedule in finalSchedules) { foreach (var flow in schedule[p].Flows) { if (flow.SettleDate > exposureDate) { finalValue += flow.Pv; } } } sortedFinalValues[p] = new KeyValuePair <double, double>(_pathwiseValues[d][p], finalValue); } sortedFinalValues = sortedFinalValues.OrderBy(q => q.Key).ToArray(); if (_requireContinuity) { o[d] = SegmentedLinearRegression.Regress(sortedFinalValues.Select(x => x.Key).ToArray(), sortedFinalValues.Select(y => y.Value).ToArray(), 5); } else { o[d] = SegmentedLinearRegression.RegressNotContinuous(sortedFinalValues.Select(x => x.Key).ToArray(), sortedFinalValues.Select(y => y.Value).ToArray(), 5); } if (DebugMode) { DumpDataToDisk(sortedFinalValues, o[d], $@"C:\temp\regData{d}.csv"); } }).Wait(); _regressors = o; return(o); }
private double GetVolForAbsoluteStrike(double strike, IInterpolator1D interp) { var cp = strike < 0 ? OptionType.Put : OptionType.Call; Func <double, double> testFunc = (deltaK => { var vol = interp.Interpolate(-deltaK); var absK = AbsoluteStrikefromDeltaKAnalytic(_fwd, deltaK, 0, _tExp, vol); return(absK - strike); }); var solvedStrike = -Brent.BrentsMethodSolve(testFunc, -0.999999999, -0.000000001, 1e-8); return(interp.Interpolate(solvedStrike)); }
public static IInterpolator1D GeneratePDF(this IInterpolator1D smile, int numSamples, double t, double fwd) { var deltaK = fwd * 0.0001; var atmVol = smile.Interpolate(fwd); var lowStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.0001, 0, t, atmVol); var hiStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.9999, 0, t, atmVol); var x = new double[numSamples + 2]; var y = new double[numSamples + 2]; var k = lowStrike; var kStep = (hiStrike - lowStrike) / numSamples; for (var i = 0; i < x.Length; i++) { if (i == 0) { x[0] = lowStrike / 2.0; y[0] = 0; continue; } if (i == x.Length - 1) { x[i] = k * 2; y[i] = 0; continue; } var volLow = smile.Interpolate(k - deltaK); var callLow = BlackFunctions.BlackPV(fwd, k - deltaK, 0, t, volLow, OptionType.C); var volMid = smile.Interpolate(k); var callMid = BlackFunctions.BlackPV(fwd, k, 0, t, volMid, OptionType.C); var volHi = smile.Interpolate(k + deltaK); var callHi = BlackFunctions.BlackPV(fwd, k + deltaK, 0, t, volHi, OptionType.C); var digitalLo = (callLow - callMid) / deltaK; var digitalHi = (callMid - callHi) / deltaK; y[i] = (digitalLo - digitalHi) / deltaK; x[i] = k; k += kStep; } var firstPass = InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap); var totalY = ((IIntegrableInterpolator)firstPass).DefiniteIntegral(x.First(), x.Last()); y = y.Select(v => v / totalY).ToArray(); return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.LinearFlatExtrap)); }
private void Initialize() { var pillarsAsDoubles = _pillarDates.Select(x => x.ToOADate()).ToArray(); switch (_curveType) { case SparsePriceCurveType.Coal: _interpA = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, _prices, Interpolator1DType.LinearFlatExtrap); var allDates = _pillarDates.First().CalendarDaysInPeriod(_pillarDates.Last()); var monthlyDates = allDates.Select(x => x.NthLastSpecificWeekDay(DayOfWeek.Friday, 1)).Distinct(); var monthlyPillars = monthlyDates.Select(x => x.ToOADate()).ToArray(); var monthlyPrices = _interpA.Many(monthlyPillars).ToArray(); _interpB = InterpolatorFactory.GetInterpolator(monthlyPillars, monthlyPrices, Interpolator1DType.NextValue); break; } }
private void ComputeJacobian() { _jacobian = Math.Matrix.DoubleArrayFunctions.MatrixCreate(_numberOfPillars, _numberOfPillars); for (var i = 0; i < _numberOfPillars; i++) { _currentCurve = new LinearHazzardInterpolator(_pillarsT, _currentGuess.Select((g, ix) => ix == i ? g + JacobianBump : g).ToArray()); var bumpedPVs = ComputePVs(); for (var j = 0; j < bumpedPVs.Length; j++) { _jacobian[i][j] = (bumpedPVs[j] - _currentPVs[j]) / JacobianBump; } } _currentCurve = new LinearHazzardInterpolator(_pillarsT, _currentGuess); }
public IrCurve(DateTime[] pillars, double[] rates, DateTime buildDate, string name, Interpolator1DType interpKind) { _interpKind = interpKind; _pillars = new DateTime[pillars.Length]; pillars.CopyTo(_pillars, 0); _rates = new double[_pillars.Length]; var pillarsD = new double[_pillars.Length]; _buildDate = buildDate; for (var i = 0; i < pillars.Length; i++) { pillarsD[i] = buildDate.CalculateYearFraction(pillars[i], _basis); _rates[i] = rates[i]; } _interpolator = InterpolatorFactory.GetInterpolator(pillarsD.ToArray(), _rates.ToArray(), interpKind, isSorted: true, noCopy: true); _name = name; }
public static double InverseCDF(IInterpolator1D putPremiumInterp, double t, double fwd, double p) { var deltaK = fwd * 1e-8; var targetFunc = new Func <double, double>(k => { var digi = putPremiumInterp.FirstDerivative(k); return(p - digi); }); var targetFunc2 = new Func <double, double>(k => - putPremiumInterp.SecondDerivative(k)); //var b = Math.Solvers.Brent.BrentsMethodSolve(targetFunc, lowGuess, highGuess, 1e-6); var b = Math.Solvers.Newton1D.MethodSolve(targetFunc, targetFunc2, fwd, 1e-6, 1000); if (double.IsInfinity(b) || double.IsNaN(b)) { throw new Exception("Invalid strike found"); } return(b); }
public static IInterpolator1D GenerateCDF(this IInterpolator1D smile, int numSamples, double t, double fwd) { var deltaK = fwd * 0.0001; var atmVol = smile.Interpolate(fwd); var lowStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.0001, 0, t, atmVol); var hiStrike = BlackFunctions.AbsoluteStrikefromDeltaKAnalytic(fwd, -0.9999, 0, t, atmVol); var x = new double[numSamples + 2]; var y = new double[numSamples + 2]; var k = lowStrike; var kStep = (hiStrike - lowStrike) / numSamples; for (var i = 0; i < x.Length; i++) { if (i == 0) { x[0] = k / 2.0; y[0] = 0; continue; } if (i == x.Length - 1) { x[i] = k * 2; y[i] = 1; continue; } var volLow = smile.Interpolate(k - deltaK / 2.0); var putLow = BlackFunctions.BlackPV(fwd, k - deltaK / 2.0, 0, t, volLow, OptionType.P); var volHi = smile.Interpolate(k + deltaK / 2.0); var putHi = BlackFunctions.BlackPV(fwd, k + deltaK / 2.0, 0, t, volHi, OptionType.P); var digital = (putHi - putLow) / deltaK; y[i] = digital; x[i] = k; k += kStep; } return(InterpolatorFactory.GetInterpolator(x, y, Interpolator1DType.Linear)); }
public IrCurve(DateTime[] pillars, double[] rates, DateTime buildDate, string name, Interpolator1DType interpKind, Currency ccy, string collateralSpec = null, RateType rateStorageType = RateType.Exponential) { _interpKind = interpKind; _rateStorageType = rateStorageType; _pillars = new DateTime[pillars.Length]; pillars.CopyTo(_pillars, 0); _rates = new double[_pillars.Length]; var pillarsD = new double[_pillars.Length]; _buildDate = buildDate; for (var i = 0; i < pillars.Length; i++) { pillarsD[i] = buildDate.CalculateYearFraction(pillars[i], _basis); _rates[i] = rates[i]; } _interpolator = InterpolatorFactory.GetInterpolator(pillarsD.ToArray(), _rates.ToArray(), interpKind, isSorted: true, noCopy: true); _name = name; Currency = ccy; CollateralSpec = collateralSpec ?? (string.IsNullOrWhiteSpace(_name) ? null : (_name.Contains("[")) ? _name.Split('[').Last().Trim("[]".ToCharArray()) : _name.Split('.').Last()); }
public SVIVolSurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas, double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType, Interpolator1DType timeInterpType, SviType sviType = SviType.Raw, string[] pillarLabels = null) : base() { if (pillarLabels == null) { PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray(); } else { PillarLabels = pillarLabels; } if (ATMVols.Length != expiries.Length || expiries.Length != riskies.Length || riskies.Length != flies.Length) { throw new Exception("Inputs do not have consistent time dimensions"); } if (wingDeltas.Length != riskies[0].Length || riskies[0].Length != flies[0].Length) { throw new Exception("Inputs do not have consistent strike dimensions"); } var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint { ATMVolType = atmVolType, MarketVol = a }).ToArray(); var needsFlip = wingDeltas.First() > wingDeltas.Last(); var strikes = new double[2 * wingDeltas.Length + 1]; if (needsFlip) { for (var s = 0; s < wingDeltas.Length; s++) { strikes[s] = wingDeltas[wingDeltas.Length - 1 - s]; strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s]; } } else { for (var s = 0; s < wingDeltas.Length; s++) { strikes[s] = wingDeltas[s]; strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[s]; } } strikes[wingDeltas.Length] = 0.5; var wingConstraints = new RRBFConstraint[expiries.Length][]; RawParams = new SviRawParameters[expiries.Length]; var f = new AssetSmileSolver(); if (needsFlip) { for (var i = 0; i < wingConstraints.Length; i++) { var offset = wingDeltas.Length - 1; wingConstraints[i] = new RRBFConstraint[wingDeltas.Length]; for (var j = 0; j < wingConstraints[i].Length; j++) { wingConstraints[i][j] = new RRBFConstraint { Delta = wingDeltas[offset - j], FlyVol = flies[i][offset - j], RisykVol = riskies[i][offset - j], WingQuoteType = wingQuoteType, }; } RawParams[i] = f.SolveSviRaw(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], true); } } else { for (var i = 0; i < wingConstraints.Length; i++) { wingConstraints[i] = new RRBFConstraint[wingDeltas.Length]; for (var j = 0; j < wingConstraints[i].Length; j++) { wingConstraints[i][j] = new RRBFConstraint { Delta = wingDeltas[j], FlyVol = flies[i][j], RisykVol = riskies[i][j], WingQuoteType = wingQuoteType, }; } RawParams[i] = f.SolveSviRaw(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], true); } } OriginDate = originDate; TimeInterpolatorType = timeInterpType; Expiries = expiries; ExpiriesDouble = expiries.Select(x => originDate.CalculateYearFraction(x, TimeBasis)).ToArray(); _interps = new IInterpolator1D[5]; _interps[0] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.A).ToArray(), TimeInterpolatorType); _interps[1] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.B).ToArray(), TimeInterpolatorType); _interps[2] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.M).ToArray(), TimeInterpolatorType); _interps[3] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.Rho).ToArray(), TimeInterpolatorType); _interps[4] = InterpolatorFactory.GetInterpolator(ExpiriesDouble, RawParams.Select(x => x.Sigma).ToArray(), TimeInterpolatorType); _fwdsInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, Interpolator1DType.Linear); }
private void Initialize() { var pillarsAsDoubles = PillarDates.Select(x => x.ToOADate()).ToArray(); _interp = InterpolatorFactory.GetInterpolator(pillarsAsDoubles, Contangos, Interpolator1DType.Linear); }
public SabrVolSurface(DateTime originDate, double[] ATMVols, DateTime[] expiries, double[] wingDeltas, double[][] riskies, double[][] flies, double[] fwds, WingQuoteType wingQuoteType, AtmVolType atmVolType, Interpolator1DType timeInterpType, string[] pillarLabels = null) { if (pillarLabels == null) { PillarLabels = expiries.Select(x => x.ToString("yyyy-MM-dd")).ToArray(); } else { PillarLabels = pillarLabels; } if (ATMVols.Length != expiries.Length || expiries.Length != riskies.Length || riskies.Length != flies.Length) { throw new Exception("Inputs do not have consistent time dimensions"); } if (wingDeltas.Length != riskies[0].Length || riskies[0].Length != flies[0].Length) { throw new Exception("Inputs do not have consistent strike dimensions"); } var atmConstraints = ATMVols.Select(a => new ATMStraddleConstraint { ATMVolType = atmVolType, MarketVol = a }).ToArray(); var needsFlip = wingDeltas.First() > wingDeltas.Last(); var strikes = new double[2 * wingDeltas.Length + 1]; if (needsFlip) { for (var s = 0; s < wingDeltas.Length; s++) { strikes[s] = wingDeltas[wingDeltas.Length - 1 - s]; strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[wingDeltas.Length - 1 - s]; } } else { for (var s = 0; s < wingDeltas.Length; s++) { strikes[s] = wingDeltas[s]; strikes[strikes.Length - 1 - s] = 1.0 - wingDeltas[s]; } } strikes[wingDeltas.Length] = 0.5; var wingConstraints = new RRBFConstraint[expiries.Length][]; var parameters = new SABRParameters[expiries.Length]; var f = new AssetSmileSolver(); if (needsFlip) { for (var i = 0; i < wingConstraints.Length; i++) { var offset = wingDeltas.Length - 1; wingConstraints[i] = new RRBFConstraint[wingDeltas.Length]; for (var j = 0; j < wingConstraints[i].Length; j++) { wingConstraints[i][j] = new RRBFConstraint { Delta = wingDeltas[offset - j], FlyVol = flies[i][offset - j], RisykVol = riskies[i][offset - j], WingQuoteType = wingQuoteType, }; } parameters[i] = f.SolveSABR(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], 1.0); } } else { for (var i = 0; i < wingConstraints.Length; i++) { wingConstraints[i] = new RRBFConstraint[wingDeltas.Length]; for (var j = 0; j < wingConstraints[i].Length; j++) { wingConstraints[i][j] = new RRBFConstraint { Delta = wingDeltas[j], FlyVol = flies[i][j], RisykVol = riskies[i][j], WingQuoteType = wingQuoteType, }; } parameters[i] = f.SolveSABR(atmConstraints[i], wingConstraints[i], originDate, expiries[i], fwds[i], 1.0); } } OriginDate = originDate; TimeInterpolatorType = timeInterpType; Expiries = expiries; ExpiriesDouble = expiries.Select(x => originDate.CalculateYearFraction(x, TimeBasis)).ToArray(); Alphas = parameters.Select(x => x.Alpha).ToArray(); Betas = parameters.Select(x => x.Beta).ToArray(); Nus = parameters.Select(x => x.Nu).ToArray(); Rhos = parameters.Select(x => x.Rho).ToArray(); _alphaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Alphas, TimeInterpolatorType); _betaInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Betas, TimeInterpolatorType); _rhoInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Rhos, TimeInterpolatorType); _nuInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, Nus, TimeInterpolatorType); _fwdsInterp = InterpolatorFactory.GetInterpolator(ExpiriesDouble, fwds, TimeInterpolatorType); }
public static double Average(this IInterpolator1D interp, IEnumerable <double> Xs) => Xs.Average(x => interp.Interpolate(x));
public HazzardCurve(DateTime originDate, DayCountBasis basis, IInterpolator1D hazzardRateInterpolator) { OriginDate = originDate; Basis = basis; _hazzardCurve = hazzardRateInterpolator; }
public static double MinY(this IInterpolator1D interp, IEnumerable <double> Xs) => Xs.Min(x => interp.Interpolate(x));
public static double Sum(this IInterpolator1D interp, IEnumerable <double> Xs) => Xs.Sum(x => interp.Interpolate(x));
private void UpdateInterpolator() => _interp = InterpolatorFactory.GetInterpolator(_strikes, _currentGuess, _interpType);
public static double VanillaPV(double T, double S, double K, IInterpolator1D r_interp, double sigma, OptionType CP, IInterpolator1D fwd_interp, int n, bool isAmerican) { var deltaT = T / (double)n; var u = System.Math.Exp(sigma * System.Math.Sqrt(2.0 * deltaT)); var d = System.Math.Exp(-sigma * System.Math.Sqrt(2.0 * deltaT)); var Z = sigma * System.Math.Sqrt(deltaT / 2.0); var p = new double[n * 2 + 1]; double exercise, spot; double cp = CP == OptionType.Call ? 1 : -1; //initial values at time T for (var i = 0; i <= 2 * n; i++) { spot = S * System.Math.Pow(d, n - i); p[i] = System.Math.Max(0, cp * (S * System.Math.Pow(u, System.Math.Max(i - n, 0)) * System.Math.Pow(d, System.Math.Max(n - i, 0)) - K)); } //move back to earlier times for (var j = n - 1; j >= 0; j--) { var t_step = T * (double)j / (double)n; var t_stepPrev = T * (double)(j + 1) / (double)n; var r = System.Math.Log(System.Math.Exp(r_interp.Interpolate(t_stepPrev) * t_stepPrev) / System.Math.Exp(r_interp.Interpolate(t_step) * t_step)) / deltaT; var q = r - System.Math.Log(fwd_interp.Interpolate(t_stepPrev) / fwd_interp.Interpolate(t_step)) / deltaT; var df1p = System.Math.Exp(-r * deltaT); var pu = (System.Math.Exp((r - q) * deltaT / 2.0) - System.Math.Exp(-Z)) / (System.Math.Exp(Z) - System.Math.Exp(-Z)); var pd = (System.Math.Exp(Z) - System.Math.Exp((r - q) * deltaT / 2.0)) / (System.Math.Exp(Z) - System.Math.Exp(-Z)); pu *= pu; pd *= pd; var pm = 1 - (pu + pd); for (var i = 0; i <= j * 2; i++) { spot = S * System.Math.Pow(u, i - j); p[i] = df1p * (pd * p[i] + pm * p[i + 1] + pu * p[i + 2]); if (isAmerican) { if (CP == OptionType.Put) { exercise = K - spot; //exercise value } else { exercise = spot - K; //exercise value } if (p[i] < exercise) { p[i] = exercise; } } } } return(p[0]); }
public static double[] Many(this IInterpolator1D interp, IEnumerable <double> Xs) => Xs.Select(x => interp.Interpolate(x)).ToArray();
public LinearHazzardInterpolator(double[] xs, double[] hs) { _xs = xs; _hs = hs; _linearInterp = InterpolatorFactory.GetInterpolator(xs, hs, Interpolator1DType.LinearFlatExtrap); }
public static TO_Interpolator1d ToTransportObject(this IInterpolator1D interp) { switch (interp) { case LinearInterpolatorFlatExtrap i1: return(new TO_Interpolator1d { Xs = i1.Xs, Ys = i1.Ys, Type = Interpolator1DType.LinearFlatExtrap }); case LinearInterpolator i2: return(new TO_Interpolator1d { Xs = i2.Xs, Ys = i2.Ys, Type = Interpolator1DType.Linear }); case LinearInVarianceInterpolator i3: return(new TO_Interpolator1d { Xs = i3.Xs, Ys = i3.Ys, Type = Interpolator1DType.LinearInVariance }); case GaussianKernelInterpolator i4: return(new TO_Interpolator1d { Xs = i4.Xs, Ys = i4.Ys, Type = Interpolator1DType.GaussianKernel }); case NextInterpolator i5: return(new TO_Interpolator1d { Xs = i5.Xs, Ys = i5.Ys, Type = Interpolator1DType.NextValue }); case PreviousInterpolator i6: return(new TO_Interpolator1d { Xs = i6.Xs, Ys = i6.Ys, Type = Interpolator1DType.PreviousValue }); case CubicHermiteSplineInterpolator i7: return(new TO_Interpolator1d { Xs = i7.Xs, Ys = i7.Ys, Type = Interpolator1DType.CubicSpline }); case DummyPointInterpolator i8: return(new TO_Interpolator1d { Xs = new[] { i8.Point }, Ys = new[] { i8.Point }, Type = Interpolator1DType.DummyPoint }); case ConstantHazzardInterpolator i9: return(new TO_Interpolator1d { Xs = new[] { i9.H }, Ys = new[] { i9.H }, Type = Interpolator1DType.ConstantHazzard }); default: throw new InvalidOperationException($"We don't have a way of serializing a {interp.GetType().Name} interpolator"); } }