public MersenneTwisterUniformRng(List <ulong> seeds) { mt = new InitializedList <ulong>(N); seedInitialization(19650218UL); int i = 1, j = 0, k = (N > seeds.Count ? N : seeds.Count); for (; k != 0; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) + seeds[j] + (ulong)j; /* non linear */ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; j++; if (i >= N) { mt[0] = mt[N - 1]; i = 1; } if (j >= seeds.Count) { j = 0; } } for (k = N - 1; k != 0; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL)) - (ulong)i; /* non linear */ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; if (i >= N) { mt[0] = mt[N - 1]; i = 1; } } mt[0] = 0x80000000UL; /*MSB is 1; assuring non-zero initial array*/ }
public InterpolatedSmileSection(Date d, List <double> strikes, List <Handle <Quote> > stdDevHandles, Handle <Quote> atmLevel, DayCounter dc = null, //Actual365Fixed(), Interpolator interpolator = default(Interpolator), Date referenceDate = null, double shift = 0.0) : base(d, dc, referenceDate, VolatilityType.ShiftedLognormal, shift) { exerciseTimeSquareRoot_ = Math.Sqrt(exerciseTime()); strikes_ = strikes; stdDevHandles_ = stdDevHandles; atmLevel_ = atmLevel; vols_ = new InitializedList <double>(stdDevHandles.Count); for (int i = 0; i < stdDevHandles_.Count; ++i) { stdDevHandles_[i].registerWith(update); } atmLevel_.registerWith(update); // check strikes!!!!!!!!!!!!!!!!!!!! interpolation_ = interpolator.interpolate(strikes_, strikes_.Count, vols_); }
//! fixed reference date, fixed market data public CapFloorTermVolCurve(Date settlementDate, Calendar calendar, BusinessDayConvention bdc, List <Period> optionTenors, List <double> vols, DayCounter dc = null) // Actual365Fixed() : base(settlementDate, calendar, bdc, dc ?? new Actual365Fixed()) { nOptionTenors_ = optionTenors.Count; optionTenors_ = optionTenors; optionDates_ = new InitializedList <Date>(nOptionTenors_); optionTimes_ = new InitializedList <double>(nOptionTenors_); volHandles_ = new InitializedList <Handle <Quote> >(vols.Count); vols_ = vols; // do not initialize with nOptionTenors_ checkInputs(); initializeOptionDatesAndTimes(); // fill dummy handles to allow generic handle-based computations later for (int i = 0; i < nOptionTenors_; ++i) { volHandles_[i] = new Handle <Quote>(new SimpleQuote(vols_[i])); } interpolate(); }
public InterpolatedSmileSection(Date d, List <double> strikes, List <double> stdDevs, double atmLevel, DayCounter dc = null, // Actual365Fixed(), Interpolator interpolator = default(Interpolator), Date referenceDate = null, double shift = 0.0) : base(d, dc ?? new Actual365Fixed(), referenceDate, VolatilityType.ShiftedLognormal, shift) { strikes_ = strikes; stdDevHandles_ = new InitializedList <Handle <Quote> >(stdDevs.Count); vols_ = new InitializedList <double>(stdDevs.Count); //fill dummy handles to allow generic handle-based // computations later on for (int i = 0; i < stdDevs.Count; ++i) { stdDevHandles_[i] = new Handle <Quote>(new SimpleQuote(stdDevs[i])); } atmLevel_ = new Handle <Quote>(new SimpleQuote(atmLevel)); // check strikes!!!!!!!!!!!!!!!!!!!! interpolation_ = interpolator.interpolate(strikes_, strikes_.Count, vols_); }
public InterpolatedSmileSection(double timeToExpiry, List <double> strikes, List <double> stdDevs, double atmLevel, Interpolator interpolator = default(Interpolator), DayCounter dc = null, //Actual365Fixed(), double shift = 0.0) : base(timeToExpiry, dc, VolatilityType.ShiftedLognormal, shift) { exerciseTimeSquareRoot_ = Math.Sqrt(exerciseTime()); strikes_ = strikes; stdDevHandles_ = new InitializedList <Handle <Quote> >(stdDevs.Count); vols_ = new InitializedList <double>(stdDevs.Count); // fill dummy handles to allow generic handle-based // computations later on for (int i = 0; i < stdDevs.Count; ++i) { stdDevHandles_[i] = new Handle <Quote>(new SimpleQuote(stdDevs[i])); } atmLevel_ = new Handle <Quote>(new SimpleQuote(atmLevel)); // check strikes!!!!!!!!!!!!!!!!!!!! interpolation_ = interpolator.interpolate(strikes_, strikes_.Count, vols_); }
// Multi leg constructor. public Swap(List <List <CashFlow> > legs, List <bool> payer) { legs_ = (InitializedList <List <CashFlow> >)legs; payer_ = new InitializedList <double>(legs.Count, 1.0); legNPV_ = new InitializedList <double?>(legs.Count, 0.0); legBPS_ = new InitializedList <double?>(legs.Count, 0.0); startDiscounts_ = new InitializedList <double?>(legs.Count, 0.0); endDiscounts_ = new InitializedList <double?>(legs.Count, 0.0); npvDateDiscount_ = 0.0; Utils.QL_REQUIRE(payer.Count == legs_.Count, () => "size mismatch between payer (" + payer.Count + ") and legs (" + legs_.Count + ")"); for (int i = 0; i < legs_.Count; ++i) { if (payer[i]) { payer_[i] = -1; } for (int j = 0; j < legs_[i].Count; j++) { legs_[i][j].registerWith(update); } } }
public Fj_Helper(Handle <PiecewiseTimeDependentHestonModel> model, double term, double strike, int j) { j_ = j; term_ = term; v0_ = model.link.v0(); x_ = Math.Log(model.link.s0()); sx_ = Math.Log(strike); r_ = new InitializedList <double>(model.link.timeGrid().size() - 1); q_ = new InitializedList <double>(model.link.timeGrid().size() - 1); model_ = model; timeGrid_ = model.link.timeGrid(); for (int i = 0; i < timeGrid_.size() - 1; ++i) { double begin = Math.Min(term_, timeGrid_[i]); double end = Math.Min(term_, timeGrid_[i + 1]); r_[i] = model.link.riskFreeRate().link.forwardRate(begin, end, Compounding.Continuous, Frequency.NoFrequency).rate(); q_[i] = model.link.dividendYield().link.forwardRate(begin, end, Compounding.Continuous, Frequency.NoFrequency).rate(); } Utils.QL_REQUIRE(term_ < model_.link.timeGrid().Last(), () => "maturity is too large"); }
public override void fetchResults(IPricingEngineResults r) { base.fetchResults(r); Swap.Results results = r as Swap.Results; if (results == null) { throw new ArgumentException("wrong result type"); } if (results.legNPV.Count != 0) { if (results.legNPV.Count != legNPV_.Count) { throw new ArgumentException("wrong number of leg NPV returned"); } legNPV_ = results.legNPV; } else { legNPV_ = new InitializedList <double?>(legNPV_.Count); } if (results.legBPS.Count != 0) { if (results.legBPS.Count != legBPS_.Count) { throw new ArgumentException("wrong number of leg BPS returned"); } legBPS_ = results.legBPS; } else { legBPS_ = new InitializedList <double?>(legBPS_.Count); } }
public override void calculate() { double value = 0.0; double vega = 0.0; int optionlets = arguments_.startDates.Count; List <double> values = new InitializedList <double>(optionlets); List <double> vegas = new InitializedList <double>(optionlets); List <double> stdDevs = new InitializedList <double>(optionlets); CapFloorType type = arguments_.type; Date today = vol_.link.referenceDate(); Date settlement = discountCurve_.link.referenceDate(); for (int i = 0; i < optionlets; ++i) { Date paymentDate = arguments_.endDates[i]; if (paymentDate > settlement) { // discard expired caplets double d = arguments_.nominals[i] * arguments_.gearings[i] * discountCurve_.link.discount(paymentDate) * arguments_.accrualTimes[i]; double?forward = arguments_.forwards[i]; Date fixingDate = arguments_.fixingDates[i]; double sqrtTime = 0.0; if (fixingDate > today) { sqrtTime = Math.Sqrt(vol_.link.timeFromReference(fixingDate)); } if (type == CapFloorType.Cap || type == CapFloorType.Collar) { double?strike = arguments_.capRates[i]; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike.Value)); vegas[i] = Utils.blackFormulaStdDevDerivative(strike.Value, forward.Value, stdDevs[i], d, displacement_) * sqrtTime; } // include caplets with past fixing date values[i] = Utils.blackFormula(Option.Type.Call, strike.Value, forward.Value, stdDevs[i], d, displacement_); } if (type == CapFloorType.Floor || type == CapFloorType.Collar) { double?strike = arguments_.floorRates[i]; double floorletVega = 0.0; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(vol_.link.blackVariance(fixingDate, strike.Value)); floorletVega = Utils.blackFormulaStdDevDerivative(strike.Value, forward.Value, stdDevs[i], d, displacement_) * sqrtTime; } double floorlet = Utils.blackFormula(Option.Type.Put, strike.Value, forward.Value, stdDevs[i], d, displacement_); if (type == CapFloorType.Floor) { values[i] = floorlet; vegas[i] = floorletVega; } else { // a collar is long a cap and short a floor values[i] -= floorlet; vegas[i] -= floorletVega; } } value += values[i]; vega += vegas[i]; } } results_.value = value; results_.additionalResults["vega"] = vega; results_.additionalResults["optionletsPrice"] = values; results_.additionalResults["optionletsVega"] = vegas; results_.additionalResults["optionletsAtmForward"] = arguments_.forwards; if (type != CapFloorType.Collar) { results_.additionalResults["optionletsStdDev"] = stdDevs; } }
public SobolRsg(int dimensionality, ulong seed, DirectionIntegers directionIntegers) { dimensionality_ = dimensionality; sequenceCounter_ = 0; firstDraw_ = true; sequence_ = new Sample <List <double> >(new InitializedList <double>(dimensionality), 1.0); integerSequence_ = new InitializedList <ulong>(dimensionality); directionIntegers_ = new InitializedList <List <ulong> >(dimensionality); for (int i = 0; i < dimensionality; i++) { directionIntegers_[i] = new InitializedList <ulong>(bits_); } if (!(dimensionality > 0)) { throw new Exception("dimensionality must be greater than 0"); } if (!(dimensionality <= PPMT_MAX_DIM)) { throw new Exception("dimensionality " + dimensionality + " exceeds the number of available " + "primitive polynomials modulo two (" + PPMT_MAX_DIM + ")"); } // initializes coefficient array of the k-th primitive polynomial // and degree of the k-th primitive polynomial List <uint> degree = new InitializedList <uint>(dimensionality_); List <long> ppmt = new InitializedList <long>(dimensionality_); bool useAltPolynomials = false; if (directionIntegers == DirectionIntegers.Kuo || directionIntegers == DirectionIntegers.Kuo2 || directionIntegers == DirectionIntegers.Kuo3 || directionIntegers == DirectionIntegers.SobolLevitan || directionIntegers == DirectionIntegers.SobolLevitanLemieux) { useAltPolynomials = true; } // degree 0 is not used ppmt[0] = 0; degree[0] = 0; int k, index; uint currentDegree = 1; k = 1; index = 0; uint altDegree = useAltPolynomials ? maxAltDegree : 0; for ( ; k < Math.Min(dimensionality_, altDegree); k++, index++) { ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index]; if (ppmt[k] == -1) { ++currentDegree; index = 0; ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index]; } degree[k] = currentDegree; } for ( ; k < dimensionality_; k++, index++) { ppmt[k] = PrimitivePolynomials[currentDegree - 1][index]; if (ppmt[k] == -1) { ++currentDegree; index = 0; ppmt[k] = PrimitivePolynomials[currentDegree - 1][index]; } degree[k] = currentDegree; } // initializes bits_ direction integers for each dimension // and store them into directionIntegers_[dimensionality_][bits_] // // In each dimension k with its associated primitive polynomial, // the first degree_[k] direction integers can be chosen freely // provided that only the l leftmost bits can be non-zero, and // that the l-th leftmost bit must be set // degenerate (no free direction integers) first dimension int j; for (j = 0; j < bits_; j++) { directionIntegers_[0][j] = (1UL << (bits_ - j - 1)); } int maxTabulated = 0; // dimensions from 2 (k=1) to maxTabulated (k=maxTabulated-1) included // are initialized from tabulated coefficients switch (directionIntegers) { case DirectionIntegers.Unit: maxTabulated = dimensionality_; for (k = 1; k < maxTabulated; k++) { for (int l = 1; l <= degree[k]; l++) { directionIntegers_[k][l - 1] = 1UL; directionIntegers_[k][l - 1] <<= (bits_ - l); } } break; case DirectionIntegers.Jaeckel: // maxTabulated=32 maxTabulated = initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.SobolLevitan: // maxTabulated=40 maxTabulated = SLinitializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (SLinitializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = SLinitializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.SobolLevitanLemieux: // maxTabulated=360 maxTabulated = Linitializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Linitializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Linitializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.JoeKuoD5: // maxTabulated=1898 maxTabulated = JoeKuoD5initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD5initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD5initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.JoeKuoD6: // maxTabulated=1799 maxTabulated = JoeKuoD6initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD6initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD6initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.JoeKuoD7: // maxTabulated=1898 maxTabulated = JoeKuoD7initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (JoeKuoD7initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = JoeKuoD7initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.Kuo: // maxTabulated=4925 maxTabulated = Kuoinitializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuoinitializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Kuoinitializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.Kuo2: // maxTabulated=3946 maxTabulated = Kuo2initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuo2initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Kuo2initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; case DirectionIntegers.Kuo3: // maxTabulated=4585 maxTabulated = Kuo3initializers.Length + 1; for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++) { j = 0; // 0UL marks coefficients' end for a given dimension while (Kuo3initializers[k - 1][j] != 0UL) { directionIntegers_[k][j] = Kuo3initializers[k - 1][j]; directionIntegers_[k][j] <<= (bits_ - j - 1); j++; } } break; default: break; } // random initialization for higher dimensions if (dimensionality_ > maxTabulated) { MersenneTwisterUniformRng uniformRng = new MersenneTwisterUniformRng(seed); for (k = maxTabulated; k < dimensionality_; k++) { for (int l = 1; l <= degree[k]; l++) { do { // u is in (0,1) double u = uniformRng.next().value; // the direction integer has at most the // rightmost l bits non-zero directionIntegers_[k][l - 1] = (ulong)(u * (1UL << l)); } while (!((directionIntegers_[k][l - 1] & 1UL) != 0)); // iterate until the direction integer is odd // that is it has the rightmost bit set // shifting bits_-l bits to the left // we are guaranteed that the l-th leftmost bit // is set, and only the first l leftmost bit // can be non-zero directionIntegers_[k][l - 1] <<= (bits_ - l); } } } // computation of directionIntegers_[k][l] for l>=degree_[k] // by recurrence relation for (k = 1; k < dimensionality_; k++) { uint gk = degree[k]; for (int l = (int)gk; l < bits_; l++) { // eq. 8.19 "Monte Carlo Methods in Finance" by P. Jдckel ulong n = (directionIntegers_[k][(int)(l - gk)] >> (int)gk); // a[k][j] are the coefficients of the monomials in ppmt[k] // The highest order coefficient a[k][0] is not actually // used in the recurrence relation, and the lowest order // coefficient a[k][gk] is always set: this is the reason // why the highest and lowest coefficient of // the polynomial ppmt[k] are not included in its encoding, // provided that its degree is known. // That is: a[k][j] = ppmt[k] >> (gk-j-1) for (uint z = 1; z < gk; z++) { // XORed with a selection of (unshifted) direction // integers controlled by which of the a[k][j] are set if ((((ulong)ppmt[k] >> (int)(gk - z - 1)) & 1UL) != 0) { n ^= directionIntegers_[k][(int)(l - z)]; } } // a[k][gk] is always set, so directionIntegers_[k][l-gk] // will always enter n ^= directionIntegers_[k][(int)(l - gk)]; directionIntegers_[k][l] = n; } } // in case one needs to check the directionIntegers used /* bool printDirectionIntegers = false; * if (printDirectionIntegers) { * std::ofstream outStream("directionIntegers.txt"); * for (k=0; k<std::min(32UL,dimensionality_); k++) { * outStream << std::endl << k+1 << "\t" * << degree[k] << "\t" * << ppmt[k] << "\t"; * for (j=0; j<10; j++) { * outStream << io::power_of_two( * directionIntegers_[k][j]) << "\t"; * } * } * outStream.close(); * } */ // initialize the Sobol integer/double vectors // first draw for (k = 0; k < dimensionality_; k++) { integerSequence_[k] = directionIntegers_[k][0]; } }
public MersenneTwisterUniformRng(ulong seed) { mt = new InitializedList <ulong>(N); seedInitialization(seed); }
public Concentrating1dMesher(double start, double end, int size, List <Tuple <double?, double?, bool> > cPoints, double tol = 1e-8) : base(size) { Utils.QL_REQUIRE(end > start, () => "end must be larger than start"); List <double?> points = new List <double?>(), betas = new List <double?>(); foreach (Tuple <double?, double?, bool> iter in cPoints) { points.Add(iter.Item1); betas.Add((iter.Item2 * (end - start)) * (iter.Item2 * (end - start))); } // get scaling factor a so that y(1) = end double aInit = 0.0; for (int i = 0; i < points.Count; ++i) { double c1 = Utils.Asinh((start - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault()); double c2 = Utils.Asinh((end - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault()); aInit += (c2 - c1) / points.Count; } OdeIntegrationFct fct = new OdeIntegrationFct(points, betas, tol); double a = new Brent().solve( new OdeSolver(fct, start, 0.0, 1.0, end), tol, aInit, 0.1 * aInit); // solve ODE for all grid points Vector x = new Vector(size), y = new Vector(size); x[0] = 0.0; y[0] = start; double dx = 1.0 / (size - 1); for (int i = 1; i < size; ++i) { x[i] = i * dx; y[i] = fct.solve(a, y[i - 1], x[i - 1], x[i]); } // eliminate numerical noise and ensure y(1) = end double dy = y[y.Count - 1] - end; for (int i = 1; i < size; ++i) { y[i] -= i * dx * dy; } LinearInterpolation odeSolution = new LinearInterpolation(x, x.Count, y); // ensure required points are part of the grid List <Pair <double?, double?> > w = new InitializedList <Pair <double?, double?> >(1, new Pair <double?, double?>(0.0, 0.0)); for (int i = 0; i < points.Count; ++i) { if (cPoints[i].Item3 && points[i] > start && points[i] < end) { int j = y.distance(y[0], y.BinarySearch(points[i].Value)); double e = new Brent().solve( new OdeSolver2(odeSolution.value, points[i].Value), Const.QL_EPSILON, x[j], 0.5 / size); w.Add(new Pair <double?, double?>(Math.Min(x[size - 2], x[j]), e)); } } w.Add(new Pair <double?, double?>(1.0, 1.0)); w = w.OrderBy(xx => xx.first).Distinct(new equal_on_first()).ToList(); List <double> u = new List <double>(w.Count), z = new List <double>(w.Count); for (int i = 0; i < w.Count; ++i) { u[i] = w[i].first.GetValueOrDefault(); z[i] = w[i].second.GetValueOrDefault(); } LinearInterpolation transform = new LinearInterpolation(u, u.Count, z); for (int i = 0; i < size; ++i) { locations_[i] = odeSolution.value(transform.value(i * dx)); } for (int i = 0; i < size - 1; ++i) { dplus_[i] = dminus_[i + 1] = locations_[i + 1] - locations_[i]; } dplus_[dplus_.Count] = null; dminus_[0] = null; }
public override void calculate() { Utils.QL_REQUIRE(arguments_.settlementType == Settlement.Type.Physical, () => "cash-settled swaptions not priced by Jamshidian engine"); Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () => "cannot use the Jamshidian decomposition on exotic swaptions"); Utils.QL_REQUIRE(arguments_.swap.spread.IsEqual(0.0), () => "non zero spread (" + arguments_.swap.spread + ") not allowed"); Date referenceDate; DayCounter dayCounter; ITermStructureConsistentModel tsmodel = (ITermStructureConsistentModel)base.model_.link; try { if (tsmodel != null) { referenceDate = tsmodel.termStructure().link.referenceDate(); dayCounter = tsmodel.termStructure().link.dayCounter(); } else { referenceDate = termStructure_.link.referenceDate(); dayCounter = termStructure_.link.dayCounter(); } } catch { referenceDate = termStructure_.link.referenceDate(); dayCounter = termStructure_.link.dayCounter(); } List <double> amounts = new InitializedList <double>(arguments_.fixedCoupons.Count); for (int i = 0; i < amounts.Count; i++) { amounts[i] = arguments_.fixedCoupons[i]; } amounts[amounts.Count - 1] = amounts.Last() + arguments_.nominal; double maturity = dayCounter.yearFraction(referenceDate, arguments_.exercise.date(0)); List <double> fixedPayTimes = new InitializedList <double>(arguments_.fixedPayDates.Count); for (int i = 0; i < fixedPayTimes.Count; i++) { fixedPayTimes[i] = dayCounter.yearFraction(referenceDate, arguments_.fixedPayDates[i]); } rStarFinder finder = new rStarFinder(model_, arguments_.nominal, maturity, fixedPayTimes, amounts); Brent s1d = new Brent(); double minStrike = -10.0; double maxStrike = 10.0; s1d.setMaxEvaluations(10000); s1d.setLowerBound(minStrike); s1d.setUpperBound(maxStrike); double rStar = s1d.solve(finder, 1e-8, 0.05, minStrike, maxStrike); Option.Type w = arguments_.type == VanillaSwap.Type.Payer ? Option.Type.Put : Option.Type.Call; int size = arguments_.fixedCoupons.Count; double value = 0.0; for (int i = 0; i < size; i++) { double fixedPayTime = dayCounter.yearFraction(referenceDate, arguments_.fixedPayDates[i]); double strike = model_.link.discountBond(maturity, fixedPayTime, rStar); double dboValue = model_.link.discountBondOption( w, strike, maturity, fixedPayTime); value += amounts[i] * dboValue; } results_.value = value; }
public void recalibration(double beta, Period swapTenor) { List <double> betaVector = new InitializedList <double>(nOptionTenors_, beta); recalibration(betaVector, swapTenor); }
public override void update() { sectionHelpers_.Clear(); if (size_ == 2) //single period { ISectionHelper singleHelper = new EverywhereConstantHelper(yBegin_[1], 0.0, xBegin_[0]); sectionHelpers_.Add(xBegin_[1], singleHelper); extrapolationHelper_ = singleHelper; return; } List <double> f = new InitializedList <double>(size_); sectionHelpers_ = new Dictionary <double, ISectionHelper>(preSectionHelpers_); int startPoint = sectionHelpers_.Count + 1; //first derive the boundary forwards. for (int i = startPoint; i < size_ - 1; ++i) { double dxPrev = xBegin_[i] - xBegin_[i - 1]; double dx = xBegin_[i + 1] - xBegin_[i]; f[i] = dxPrev / (dx + dxPrev) * yBegin_[i] + dx / (dx + dxPrev) * yBegin_[i + 1]; } if (startPoint > 1) { f[startPoint - 1] = preSectionHelpers_.Last().Value.fNext(); } if (startPoint == 1) { f[0] = 1.5 * yBegin_[1] - 0.5 * f[1]; } f[size_ - 1] = 1.5 * yBegin_[size_ - 1] - 0.5 * f[size_ - 2]; if (forcePositive_) { if (f[0] < 0) { f[0] = 0.0; } if (f[size_ - 1] < 0.0) { f[size_ - 1] = 0.0; } } double primitive = 0.0; for (int i = 0; i < startPoint - 1; ++i) { primitive += yBegin_[i + 1] * (xBegin_[i + 1] - xBegin_[i]); } int endPoint = size_; //constantLastPeriod_ = false; if (constantLastPeriod_) { endPoint = endPoint - 1; } for (int i = startPoint; i < endPoint; ++i) { double gPrev = f[i - 1] - yBegin_[i]; double gNext = f[i] - yBegin_[i]; //first deal with the zero gradient case if (Math.Abs(gPrev) < 1.0E-14 && Math.Abs(gNext) < 1.0E-14) { ISectionHelper singleHelper = new ConstantGradHelper(f[i - 1], primitive, xBegin_[i - 1], xBegin_[i], f[i]); sectionHelpers_.Add(xBegin_[i], singleHelper); } else { double quadraticity = quadraticity_; ISectionHelper quadraticHelper = null; ISectionHelper convMonotoneHelper = null; if (quadraticity_ > 0.0) { if (gPrev >= -2.0 * gNext && gPrev > -0.5 * gNext && forcePositive_) { quadraticHelper = new QuadraticMinHelper(xBegin_[i - 1], xBegin_[i], f[i - 1], f[i], yBegin_[i], primitive); } else { quadraticHelper = new QuadraticHelper(xBegin_[i - 1], xBegin_[i], f[i - 1], f[i], yBegin_[i], primitive); } } if (quadraticity_ < 1.0) { if ((gPrev > 0.0 && -0.5 * gPrev >= gNext && gNext >= -2.0 * gPrev) || (gPrev < 0.0 && -0.5 * gPrev <= gNext && gNext <= -2.0 * gPrev)) { quadraticity = 1.0; if (quadraticity_ == 0) { if (forcePositive_) { quadraticHelper = new QuadraticMinHelper( xBegin_[i - 1], xBegin_[i], f[i - 1], f[i], yBegin_[i], primitive); } else { quadraticHelper = new QuadraticHelper( xBegin_[i - 1], xBegin_[i], f[i - 1], f[i], yBegin_[i], primitive); } } } else if ((gPrev < 0.0 && gNext > -2.0 * gPrev) || (gPrev > 0.0 && gNext < -2.0 * gPrev)) { double eta = (gNext + 2.0 * gPrev) / (gNext - gPrev); double b2 = (1.0 + monotonicity_) / 2.0; if (eta < b2) { convMonotoneHelper = new ConvexMonotone2Helper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], eta, primitive); } else { if (forcePositive_) { convMonotoneHelper = new ConvexMonotone4MinHelper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], b2, primitive); } else { convMonotoneHelper = new ConvexMonotone4Helper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], b2, primitive); } } } else if ((gPrev > 0.0 && gNext < 0.0 && gNext > -0.5 * gPrev) || (gPrev < 0.0 && gNext > 0.0 && gNext < -0.5 * gPrev)) { double eta = gNext / (gNext - gPrev) * 3.0; double b3 = (1.0 - monotonicity_) / 2.0; if (eta > b3) { convMonotoneHelper = new ConvexMonotone3Helper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], eta, primitive); } else { if (forcePositive_) { convMonotoneHelper = new ConvexMonotone4MinHelper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], b3, primitive); } else { convMonotoneHelper = new ConvexMonotone4Helper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], b3, primitive); } } } else { double eta = gNext / (gPrev + gNext); double b2 = (1.0 + monotonicity_) / 2.0; double b3 = (1.0 - monotonicity_) / 2.0; if (eta > b2) { eta = b2; } if (eta < b3) { eta = b3; } if (forcePositive_) { convMonotoneHelper = new ConvexMonotone4MinHelper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], eta, primitive); } else { convMonotoneHelper = new ConvexMonotone4Helper( xBegin_[i - 1], xBegin_[i], gPrev, gNext, yBegin_[i], eta, primitive); } } } if (quadraticity == 1.0) { sectionHelpers_.Add(xBegin_[i], quadraticHelper); } else if (quadraticity == 0.0) { sectionHelpers_.Add(xBegin_[i], convMonotoneHelper); } else { sectionHelpers_.Add(xBegin_[i], new ComboHelper(quadraticHelper, convMonotoneHelper, quadraticity)); } } primitive += yBegin_[i] * (xBegin_[i] - xBegin_[i - 1]); } if (constantLastPeriod_) { sectionHelpers_.Add(xBegin_[size_ - 1], new EverywhereConstantHelper(yBegin_[size_ - 1], primitive, xBegin_[size_ - 2])); extrapolationHelper_ = sectionHelpers_[xBegin_[size_ - 1]]; } else { extrapolationHelper_ = new EverywhereConstantHelper((sectionHelpers_.Last()).Value.value(xBegin_.Last()), primitive, xBegin_.Last()); } }
public FdmLinearOpIterator(List <int> dim) { index_ = 0; dim_ = dim; coordinates_ = new InitializedList <int>(dim.Count, 0); }
public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) { // set up of the problem //double ftol = endCriteria.functionEpsilon(); // end criteria on f(x) (see Numerical Recipes in C++, p.410) double xtol = endCriteria.rootEpsilon(); // end criteria on x (see GSL v. 1.9, http://www.gnu.org/software/gsl/) int maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations(); EndCriteria.Type ecType = EndCriteria.Type.None; P.reset(); Vector x_ = P.currentValue(); int iterationNumber_ = 0; // Initialize vertices of the simplex bool end = false; int n = x_.Count; vertices_ = new InitializedList <Vector>(n + 1, x_); for (int i = 0; i < n; i++) { Vector direction = new Vector(n, 0.0); Vector vertice = vertices_[i + 1]; direction[i] = 1.0; P.constraint().update(ref vertice, direction, lambda_); vertices_[i + 1] = vertice; } // Initialize function values at the vertices of the simplex values_ = new Vector(n + 1, 0.0); for (int i = 0; i <= n; i++) { values_[i] = P.value(vertices_[i]); } // Loop looking for minimum do { sum_ = new Vector(n, 0.0); for (int i = 0; i <= n; i++) { sum_ += vertices_[i]; } // Determine the best (iLowest), worst (iHighest) // and 2nd worst (iNextHighest) vertices int iLowest = 0; int iHighest; int iNextHighest; if (values_[0] < values_[1]) { iHighest = 1; iNextHighest = 0; } else { iHighest = 0; iNextHighest = 1; } for (int i = 1; i <= n; i++) { if (values_[i] > values_[iHighest]) { iNextHighest = iHighest; iHighest = i; } else { if ((values_[i] > values_[iNextHighest]) && i != iHighest) { iNextHighest = i; } } if (values_[i] < values_[iLowest]) { iLowest = i; } } // Now compute accuracy, update iteration number and check end criteria //// Numerical Recipes exit strategy on fx (see NR in C++, p.410) //double low = values_[iLowest]; //double high = values_[iHighest]; //double rtol = 2.0*std::fabs(high - low)/ // (std::fabs(high) + std::fabs(low) + QL_EPSILON); //++iterationNumber_; //if (rtol < ftol || // endCriteria.checkMaxIterations(iterationNumber_, ecType)) { // GSL exit strategy on x (see GSL v. 1.9, http://www.gnu.org/software/gsl double simplexSize = Utils.computeSimplexSize(vertices_); ++iterationNumber_; if (simplexSize < xtol || endCriteria.checkMaxIterations(iterationNumber_, ref ecType)) { endCriteria.checkStationaryPoint(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType); endCriteria.checkMaxIterations(iterationNumber_, ref ecType); x_ = vertices_[iLowest]; double low = values_[iLowest]; P.setFunctionValue(low); P.setCurrentValue(x_); return(ecType); } // If end criteria is not met, continue double factor = -1.0; double vTry = extrapolate(ref P, iHighest, ref factor); if ((vTry <= values_[iLowest]) && (factor == -1.0)) { factor = 2.0; extrapolate(ref P, iHighest, ref factor); } else if (Math.Abs(factor) > Const.QL_EPSILON) { if (vTry >= values_[iNextHighest]) { double vSave = values_[iHighest]; factor = 0.5; vTry = extrapolate(ref P, iHighest, ref factor); if (vTry >= vSave && Math.Abs(factor) > Const.QL_EPSILON) { for (int i = 0; i <= n; i++) { if (i != iLowest) { #if QL_ARRAY_EXPRESSIONS vertices_[i] = 0.5 * (vertices_[i] + vertices_[iLowest]); #else vertices_[i] += vertices_[iLowest]; vertices_[i] *= 0.5; #endif values_[i] = P.value(vertices_[i]); } } } } } // If can't extrapolate given the constraints, exit if (Math.Abs(factor) <= Const.QL_EPSILON) { x_ = vertices_[iLowest]; double low = values_[iLowest]; P.setFunctionValue(low); P.setCurrentValue(x_); return(EndCriteria.Type.StationaryFunctionValue); } } while (end == false); throw new Exception("optimization failed: unexpected behaviour"); }
public override void calculate() { // copy black version then adapt to others double value = 0.0; int optionlets = arguments_.startDates.Count; List <double> values = new InitializedList <double>(optionlets, 0.0); List <double> stdDevs = new InitializedList <double>(optionlets, 0.0); List <double> forwards = new InitializedList <double> (optionlets, 0.0); CapFloorType type = arguments_.type; Handle <YoYInflationTermStructure> yoyTS = index().yoyInflationTermStructure(); Handle <YieldTermStructure> nominalTS = yoyTS.link.nominalTermStructure(); Date settlement = nominalTS.link.referenceDate(); for (int i = 0; i < optionlets; ++i) { Date paymentDate = arguments_.payDates[i]; if (paymentDate > settlement) { // discard expired caplets double d = arguments_.nominals[i] * arguments_.gearings[i] * nominalTS.link.discount(paymentDate) * arguments_.accrualTimes[i]; // We explicitly have the index and assume that // the fixing is natural, i.e. no convexity adjustment. // If that was required then we would also need // nominal vols in the pricing engine, i.e. a different engine. // This also means that we do not need the coupon to have // a pricing engine to return the swaplet rate and then // the adjusted fixing in the instrument. forwards[i] = yoyTS.link.yoyRate(arguments_.fixingDates[i], new Period(0, TimeUnit.Days)); double forward = forwards[i]; Date fixingDate = arguments_.fixingDates[i]; double sqrtTime = 0.0; if (fixingDate > volatility_.link.baseDate()) { sqrtTime = Math.Sqrt(volatility_.link.timeFromBase(fixingDate)); } if (type == CapFloorType.Cap || type == CapFloorType.Collar) { double strike = arguments_.capRates[i].Value; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(volatility_.link.totalVariance(fixingDate, strike, new Period(0, TimeUnit.Days))); } // sttDev=0 for already-fixed dates so everything on forward values[i] = optionletImpl(Option.Type.Call, strike, forward, stdDevs[i], d); } if (type == CapFloorType.Floor || type == CapFloorType.Collar) { double strike = arguments_.floorRates[i].Value; if (sqrtTime > 0.0) { stdDevs[i] = Math.Sqrt(volatility_.link.totalVariance(fixingDate, strike, new Period(0, TimeUnit.Days))); } double floorlet = optionletImpl(Option.Type.Put, strike, forward, stdDevs[i], d); if (type == CapFloorType.Floor) { values[i] = floorlet; } else { // a collar is long a cap and short a floor values[i] -= floorlet; } } value += values[i]; } } results_.value = value; results_.additionalResults["optionletsPrice"] = values; results_.additionalResults["optionletsAtmForward"] = forwards; if (type != CapFloorType.Collar) { results_.additionalResults["optionletsStdDev"] = stdDevs; } }
protected List <double> spreadVolInterpolation(Date atmOptionDate, Period atmSwapTenor) { double atmOptionTime = timeFromReference(atmOptionDate); double atmTimeLength = swapLength(atmSwapTenor); List <double> result = new List <double>(); List <double> optionTimes = sparseParameters_.optionTimes(); List <double> swapLengths = sparseParameters_.swapLengths(); List <Date> optionDates = sparseParameters_.optionDates(); List <Period> swapTenors = sparseParameters_.swapTenors(); double optionTimesPreviousNode, swapLengthsPreviousNode; optionTimesPreviousNode = optionTimes_.First(x => x >= atmOptionTime); int optionTimesPreviousIndex = optionTimes_.IndexOf(optionTimesPreviousNode); swapLengthsPreviousNode = swapLengths_.First(x => x >= atmTimeLength); int swapLengthsPreviousIndex = swapLengths_.IndexOf(swapLengthsPreviousNode); if (optionTimesPreviousIndex > 0) { optionTimesPreviousIndex--; } if (swapLengthsPreviousIndex > 0) { swapLengthsPreviousIndex--; } List <List <SmileSection> > smiles = new List <List <SmileSection> >(); List <SmileSection> smilesOnPreviousExpiry = new List <SmileSection>(); List <SmileSection> smilesOnNextExpiry = new List <SmileSection>(); Utils.QL_REQUIRE(optionTimesPreviousIndex + 1 < sparseSmiles_.Count, () => "optionTimesPreviousIndex+1 >= sparseSmiles_.size()"); Utils.QL_REQUIRE(swapLengthsPreviousIndex + 1 < sparseSmiles_[0].Count, () => "swapLengthsPreviousIndex+1 >= sparseSmiles_[0].size()"); smilesOnPreviousExpiry.Add(sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex]); smilesOnPreviousExpiry.Add(sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex + 1]); smilesOnNextExpiry.Add(sparseSmiles_[optionTimesPreviousIndex + 1][swapLengthsPreviousIndex]); smilesOnNextExpiry.Add(sparseSmiles_[optionTimesPreviousIndex + 1][swapLengthsPreviousIndex + 1]); smiles.Add(smilesOnPreviousExpiry); smiles.Add(smilesOnNextExpiry); List <double> optionsNodes = new InitializedList <double>(2); optionsNodes[0] = optionTimes[optionTimesPreviousIndex]; optionsNodes[1] = optionTimes[optionTimesPreviousIndex + 1]; List <Date> optionsDateNodes = new InitializedList <Date>(2); optionsDateNodes[0] = optionDates[optionTimesPreviousIndex]; optionsDateNodes[1] = optionDates[optionTimesPreviousIndex + 1]; List <double> swapLengthsNodes = new InitializedList <double>(2); swapLengthsNodes[0] = swapLengths[swapLengthsPreviousIndex]; swapLengthsNodes[1] = swapLengths[swapLengthsPreviousIndex + 1]; List <Period> swapTenorNodes = new InitializedList <Period>(2); swapTenorNodes[0] = swapTenors[swapLengthsPreviousIndex]; swapTenorNodes[1] = swapTenors[swapLengthsPreviousIndex + 1]; double atmForward = atmStrike(atmOptionDate, atmSwapTenor); double shift = atmVol_.link.shift(atmOptionTime, atmTimeLength); Matrix atmForwards = new Matrix(2, 2, 0.0); Matrix atmShifts = new Matrix(2, 2, 0.0); Matrix atmVols = new Matrix(2, 2, 0.0); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { atmForwards[i, j] = atmStrike(optionsDateNodes[i], swapTenorNodes[j]); atmShifts[i, j] = atmVol_.link.shift(optionsNodes[i], swapLengthsNodes[j]); atmVols[i, j] = atmVol_.link.volatility(optionsDateNodes[i], swapTenorNodes[j], atmForwards[i, j]); /* With the old implementation the interpolated spreads on ATM * volatilities were null even if the spreads on ATM volatilities to be * interpolated were non-zero. The new implementation removes * this behaviour, but introduces a small ERROR in the cube: * even if no spreads are applied on any cube ATM volatility corresponding * to quoted smile sections (that is ATM volatilities in sparse cube), the * cube ATM volatilities corresponding to not quoted smile sections (that * is ATM volatilities in dense cube) are no more exactly the quoted values, * but that ones PLUS the linear interpolation of the fit errors on the ATM * volatilities in sparse cube whose spreads are used in the calculation. * A similar imprecision is introduced to the volatilities in dense cube * whith moneyness near to 1. * (See below how spreadVols are calculated). * The extent of this error depends on the quality of the fit: in case of * good fits it is negligibile. */ } } for (int k = 0; k < nStrikes_; k++) { double strike = Math.Max(atmForward + strikeSpreads_[k], cutoffStrike_ - shift); double moneyness = (atmForward + shift) / (strike + shift); Matrix strikes = new Matrix(2, 2, 0.0); Matrix spreadVols = new Matrix(2, 2, 0.0); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { strikes[i, j] = (atmForwards[i, j] + atmShifts[i, j]) / moneyness - atmShifts[i, j]; spreadVols[i, j] = smiles[i][j].volatility(strikes[i, j]) - atmVols[i, j]; } } Cube localInterpolator = new Cube(optionsDateNodes, swapTenorNodes, optionsNodes, swapLengthsNodes, 1); localInterpolator.setLayer(0, spreadVols); localInterpolator.updateInterpolators(); result.Add(localInterpolator.value(atmOptionTime, atmTimeLength)[0]); } return(result); }
protected Cube sabrCalibration(Cube marketVolCube) { List <double> optionTimes = marketVolCube.optionTimes(); List <double> swapLengths = marketVolCube.swapLengths(); List <Date> optionDates = marketVolCube.optionDates(); List <Period> swapTenors = marketVolCube.swapTenors(); Matrix alphas = new Matrix(optionTimes.Count, swapLengths.Count, 0.0); Matrix betas = new Matrix(alphas); Matrix nus = new Matrix(alphas); Matrix rhos = new Matrix(alphas); Matrix forwards = new Matrix(alphas); Matrix errors = new Matrix(alphas); Matrix maxErrors = new Matrix(alphas); Matrix endCriteria = new Matrix(alphas); List <Matrix> tmpMarketVolCube = marketVolCube.points(); List <double> strikes = new InitializedList <double>(strikeSpreads_.Count); List <double> volatilities = new InitializedList <double>(strikeSpreads_.Count); for (int j = 0; j < optionTimes.Count; j++) { for (int k = 0; k < swapLengths.Count; k++) { double atmForward = atmStrike(optionDates[j], swapTenors[k]); double shiftTmp = atmVol_.link.shift(optionTimes[j], swapLengths[k]); strikes.Clear(); volatilities.Clear(); for (int i = 0; i < nStrikes_; i++) { double strike = atmForward + strikeSpreads_[i]; if (strike + shiftTmp >= cutoffStrike_) { strikes.Add(strike); Matrix matrix = tmpMarketVolCube[i]; volatilities.Add(matrix[j, k]); } } List <double> guess = parametersGuess_.value(optionTimes[j], swapLengths[k]); SABRInterpolation sabrInterpolation = new SABRInterpolation(strikes, strikes.Count, volatilities, optionTimes[j], atmForward, guess[0], guess[1], guess[2], guess[3], isParameterFixed_[0], isParameterFixed_[1], isParameterFixed_[2], isParameterFixed_[3], vegaWeightedSmileFit_, endCriteria_, optMethod_, errorAccept_, useMaxError_, maxGuesses_ );// shiftTmp sabrInterpolation.update(); double rmsError = sabrInterpolation.rmsError(); double maxError = sabrInterpolation.maxError(); alphas [j, k] = sabrInterpolation.alpha(); betas [j, k] = sabrInterpolation.beta(); nus [j, k] = sabrInterpolation.nu(); rhos [j, k] = sabrInterpolation.rho(); forwards [j, k] = atmForward; errors [j, k] = rmsError; maxErrors [j, k] = maxError; endCriteria[j, k] = (double)sabrInterpolation.endCriteria(); Utils.QL_REQUIRE(endCriteria[j, k].IsNotEqual((double)EndCriteria.Type.MaxIterations), () => "global swaptions calibration failed: " + "MaxIterations reached: " + "\n" + "option maturity = " + optionDates[j] + ", \n" + "swap tenor = " + swapTenors[k] + ", \n" + "error = " + (errors[j, k]) + ", \n" + "max error = " + (maxErrors[j, k]) + ", \n" + " alpha = " + alphas[j, k] + "n" + " beta = " + betas[j, k] + "\n" + " nu = " + nus[j, k] + "\n" + " rho = " + rhos[j, k] + "\n" ); Utils.QL_REQUIRE(useMaxError_ ? maxError > 0 : rmsError < maxErrorTolerance_, () => "global swaptions calibration failed: " + "option tenor " + optionDates[j] + ", swap tenor " + swapTenors[k] + (useMaxError_ ? ": max error " : ": error") + (useMaxError_ ? maxError : rmsError) + " alpha = " + alphas[j, k] + "\n" + " beta = " + betas[j, k] + "\n" + " nu = " + nus[j, k] + "\n" + " rho = " + rhos[j, k] + "\n" + (useMaxError_ ? ": error" : ": max error ") + (useMaxError_ ? rmsError :maxError) ); } } Cube sabrParametersCube = new Cube(optionDates, swapTenors, optionTimes, swapLengths, 8, true, backwardFlat_); sabrParametersCube.setLayer(0, alphas); sabrParametersCube.setLayer(1, betas); sabrParametersCube.setLayer(2, nus); sabrParametersCube.setLayer(3, rhos); sabrParametersCube.setLayer(4, forwards); sabrParametersCube.setLayer(5, errors); sabrParametersCube.setLayer(6, maxErrors); sabrParametersCube.setLayer(7, endCriteria); return(sabrParametersCube); }
public EuropeanExercise(Date date) : base(Type.European) { dates_ = new InitializedList <Date>(1, date); }
public static List <Func <Vector, double> > multiPathBasisSystem(int dim, int order, PolynomType polynomType) { List <Func <double, double> > b = pathBasisSystem(order, polynomType); List <Func <Vector, double> > ret = new List <Func <Vector, double> >(); ret.Add((xx) => 1.0); for (int i = 1; i <= order; ++i) { List <Func <Vector, double> > a = w(dim, i, polynomType, b); foreach (var iter in a) { ret.Add(iter); } } // remove-o-zap: now remove redundant functions. // usually we do have a lot of them due to the construction schema. // We use a more "hands on" method here. List <bool> rm = new InitializedList <bool>(ret.Count, true); Vector x = new Vector(dim), v = new Vector(ret.Count); MersenneTwisterUniformRng rng = new MersenneTwisterUniformRng(1234UL); for (int i = 0; i < 10; ++i) { int k; // calculate random x vector for (k = 0; k < dim; ++k) { x[k] = rng.next().value; } // get return values for all basis functions for (k = 0; k < ret.Count; ++k) { v[k] = ret[k](x); } // find duplicates for (k = 0; k < ret.Count; ++k) { if (v.First(xx => (Math.Abs(v[k] - xx) <= 10 * v[k] * Const.QL_EPSILON)) == v.First() + k) { // don't remove this item, it's unique! rm[k] = false; } } } int iter2 = 0; for (int i = 0; i < rm.Count; ++i) { if (rm[i]) { ret.RemoveAt(iter2); } else { ++iter2; } } return(ret); }
public AmericanExercise(Date latest, bool payoffAtExpiry = false) : base(Type.American, payoffAtExpiry) { dates_ = new InitializedList <Date>(2); dates_[0] = Date.minDate(); dates_[1] = latest; }
//@} public override void calculate() { if (!(base.arguments_.settlementType == Settlement.Type.Physical)) { throw new ArgumentException("cash-settled swaptions not priced with tree engine"); } if (base.model_ == null) { throw new ArgumentException("no model specified"); } Date referenceDate; DayCounter dayCounter; ITermStructureConsistentModel tsmodel = (ITermStructureConsistentModel)base.model_.link; try { if (tsmodel != null) { referenceDate = tsmodel.termStructure().link.referenceDate(); dayCounter = tsmodel.termStructure().link.dayCounter(); } else { referenceDate = termStructure_.link.referenceDate(); dayCounter = termStructure_.link.dayCounter(); } } catch { referenceDate = termStructure_.link.referenceDate(); dayCounter = termStructure_.link.dayCounter(); } DiscretizedSwaption swaption = new DiscretizedSwaption(arguments_, referenceDate, dayCounter); Lattice lattice; if (lattice_ != null) { lattice = lattice_; } else { List <double> times = swaption.mandatoryTimes(); TimeGrid timeGrid = new TimeGrid(times, times.Count, timeSteps_); lattice = model_.link.tree(timeGrid); } List <double> stoppingTimes = new InitializedList <double>(arguments_.exercise.dates().Count); for (int i = 0; i < stoppingTimes.Count; ++i) { stoppingTimes[i] = dayCounter.yearFraction(referenceDate, arguments_.exercise.date(i)); } swaption.initialize(lattice, stoppingTimes.Last()); double nextExercise; /*std::find_if(stoppingTimes.begin(), * stoppingTimes.end(), * std::bind2nd(std::greater_equal<Time>(), 0.0));*/ List <double> listExercise = new List <double>(); listExercise.AddRange(stoppingTimes.FindAll(x => x >= 0)); nextExercise = listExercise[0]; swaption.rollback(nextExercise); results_.value = swaption.presentValue(); }
// calculating swaption volatility matrix using // Rebonatos approx. formula. Be aware that this // matrix is valid only for regular fixings and // assumes that the fix and floating leg have the // same frequency public SwaptionVolatilityMatrix getSwaptionVolatilityMatrix() { if (swaptionVola != null) { return(swaptionVola); } IborIndex index = process_.index(); Date today = process_.fixingDates()[0]; int size = process_.size() / 2; Matrix volatilities = new Matrix(size, size); List <Date> exercises = new InitializedList <Date>(size); for (int i = 0; i < size; ++i) { exercises[i] = process_.fixingDates()[i + 1]; } List <Period> lengths = new InitializedList <Period>(size); for (int i = 0; i < size; ++i) { lengths[i] = (i + 1) * index.tenor(); } Vector f = process_.initialValues(); for (int k = 0; k < size; ++k) { int alpha = k; double t_alpha = process_.fixingTimes()[alpha + 1]; Matrix var = new Matrix(size, size); for (int i = alpha + 1; i <= k + size; ++i) { for (int j = i; j <= k + size; ++j) { var[i - alpha - 1, j - alpha - 1] = var[j - alpha - 1, i - alpha - 1] = covarProxy_.integratedCovariance(i, j, t_alpha, null); } } for (int l = 1; l <= size; ++l) { int beta = l + k; Vector w = w_0(alpha, beta); double sum = 0.0; for (int i = alpha + 1; i <= beta; ++i) { for (int j = alpha + 1; j <= beta; ++j) { sum += w[i] * w[j] * f[i] * f[j] * var[i - alpha - 1, j - alpha - 1]; } } volatilities[k, l - 1] = Math.Sqrt(sum / t_alpha) / S_0(alpha, beta); } } return(swaptionVola = new SwaptionVolatilityMatrix(today, exercises, lengths, volatilities, index.dayCounter())); }
public void sabrCalibrationSection(Cube marketVolCube, Cube parametersCube, Period swapTenor) { List <double> optionTimes = marketVolCube.optionTimes(); List <double> swapLengths = marketVolCube.swapLengths(); List <Date> optionDates = marketVolCube.optionDates(); List <Period> swapTenors = marketVolCube.swapTenors(); int k = swapTenors.IndexOf(swapTenors.First(x => x == swapTenor)); Utils.QL_REQUIRE(k != swapTenors.Count, () => "swap tenor not found"); List <double> calibrationResult = new InitializedList <double>(8, 0.0); List <Matrix> tmpMarketVolCube = marketVolCube.points(); List <double> strikes = new List <double>(strikeSpreads_.Count); List <double> volatilities = new List <double>(strikeSpreads_.Count); for (int j = 0; j < optionTimes.Count; j++) { double atmForward = atmStrike(optionDates[j], swapTenors[k]); double shiftTmp = atmVol_.link.shift(optionTimes[j], swapLengths[k]); strikes.Clear(); volatilities.Clear(); for (int i = 0; i < nStrikes_; i++) { double strike = atmForward + strikeSpreads_[i]; if (strike + shiftTmp >= cutoffStrike_) { strikes.Add(strike); volatilities.Add(tmpMarketVolCube[i][j, k]); } } List <double> guess = parametersGuess_.value(optionTimes[j], swapLengths[k]); var sabrInterpolation = new SABRInterpolation(strikes, strikes.Count, volatilities, optionTimes[j], atmForward, guess[0], guess[1], guess[2], guess[3], isParameterFixed_[0], isParameterFixed_[1], isParameterFixed_[2], isParameterFixed_[3], vegaWeightedSmileFit_, endCriteria_, optMethod_, errorAccept_, useMaxError_, maxGuesses_ );//shiftTmp sabrInterpolation.update(); double interpolationError = sabrInterpolation.rmsError(); calibrationResult[0] = sabrInterpolation.alpha(); calibrationResult[1] = sabrInterpolation.beta(); calibrationResult[2] = sabrInterpolation.nu(); calibrationResult[3] = sabrInterpolation.rho(); calibrationResult[4] = atmForward; calibrationResult[5] = interpolationError; calibrationResult[6] = sabrInterpolation.maxError(); calibrationResult[7] = (double)sabrInterpolation.endCriteria(); Utils.QL_REQUIRE(calibrationResult[7].IsNotEqual((double)EndCriteria.Type.MaxIterations), () => "section calibration failed: " + "option tenor " + optionDates[j] + ", swap tenor " + swapTenors[k] + ": max iteration (" + endCriteria_.maxIterations() + ")" + ", alpha " + calibrationResult[0] + ", beta " + calibrationResult[1] + ", nu " + calibrationResult[2] + ", rho " + calibrationResult[3] + ", max error " + calibrationResult[6] + ", error " + calibrationResult[5] ); Utils.QL_REQUIRE(useMaxError_ ? calibrationResult[6] > 0 : calibrationResult[5] < maxErrorTolerance_, () => "section calibration failed: " + "option tenor " + optionDates[j] + ", swap tenor " + swapTenors[k] + (useMaxError_ ? ": max error " : ": error ") + (useMaxError_ ? calibrationResult[6] : calibrationResult[5]) + ", alpha " + calibrationResult[0] + ", beta " + calibrationResult[1] + ", nu " + calibrationResult[2] + ", rho " + calibrationResult[3] + (useMaxError_ ? ": error" : ": max error ") + (useMaxError_ ? calibrationResult[5] : calibrationResult[6]) ); parametersCube.setPoint(optionDates[j], swapTenors[k], optionTimes[j], swapLengths[k], calibrationResult); parametersCube.updateInterpolators(); } }
protected override void setupExpired() { base.setupExpired(); legNPV_ = new InitializedList <double?>(legNPV_.Count); }
public override List <SparseMatrix> toMatrixDecomp() { List <SparseMatrix> retVal = new InitializedList <SparseMatrix>(1, mapT_.toMatrix()); return(retVal); }
public LinearInterpolationImpl(List <double> xBegin, int size, List <double> yBegin) : base(xBegin, size, yBegin) { primitiveConst_ = new InitializedList <double>(size_); s_ = new InitializedList <double>(size_); }
public override void calculate() { /* this engine cannot really check for the averageType==Geometric * since it can be used as control variate for the Arithmetic version * QL_REQUIRE(arguments_.averageType == Average::Geometric, * "not a geometric average option"); */ if (!(arguments_.exercise.type() == Exercise.Type.European)) { throw new ApplicationException("not an European Option"); } double runningLog; int pastFixings; if (arguments_.averageType == Average.Type.Geometric) { if (!(arguments_.runningAccumulator > 0.0)) { throw new ApplicationException("positive running product required: " + arguments_.runningAccumulator + " not allowed"); } runningLog = Math.Log(arguments_.runningAccumulator.GetValueOrDefault()); pastFixings = arguments_.pastFixings.GetValueOrDefault(); } else // it is being used as control variate { runningLog = 1.0; pastFixings = 0; } PlainVanillaPayoff payoff = (PlainVanillaPayoff)(arguments_.payoff); if (payoff == null) { throw new ApplicationException("non-plain payoff given"); } Date referenceDate = process_.riskFreeRate().link.referenceDate(); DayCounter rfdc = process_.riskFreeRate().link.dayCounter(); DayCounter divdc = process_.dividendYield().link.dayCounter(); DayCounter voldc = process_.blackVolatility().link.dayCounter(); List <double> fixingTimes = new InitializedList <double>(arguments_.fixingDates.Count()); int i; for (i = 0; i < arguments_.fixingDates.Count(); i++) { if (arguments_.fixingDates[i] >= referenceDate) { double t = voldc.yearFraction(referenceDate, arguments_.fixingDates[i]); fixingTimes.Add(t); } } int remainingFixings = fixingTimes.Count(); int numberOfFixings = pastFixings + remainingFixings; double N = numberOfFixings; double pastWeight = pastFixings / N; double futureWeight = 1.0 - pastWeight; /*double timeSum = std::accumulate(fixingTimes.begin(), * fixingTimes.end(), 0.0);*/ double timeSum = 0; fixingTimes.ForEach((ii, vv) => timeSum += fixingTimes[ii]); double vola = process_.blackVolatility().link.blackVol( arguments_.exercise.lastDate(), payoff.strike()); double temp = 0.0; for (i = pastFixings + 1; i < numberOfFixings; i++) { temp += fixingTimes[i - pastFixings - 1] * (N - i); } double variance = vola * vola / N / N * (timeSum + 2.0 * temp); double dsigG_dsig = Math.Sqrt((timeSum + 2.0 * temp)) / N; double sigG = vola * dsigG_dsig; double dmuG_dsig = -(vola * timeSum) / N; Date exDate = arguments_.exercise.lastDate(); double dividendRate = process_.dividendYield().link. zeroRate(exDate, divdc, Compounding.Continuous, Frequency.NoFrequency).rate(); double riskFreeRate = process_.riskFreeRate().link. zeroRate(exDate, rfdc, Compounding.Continuous, Frequency.NoFrequency).rate(); double nu = riskFreeRate - dividendRate - 0.5 * vola * vola; double s = process_.stateVariable().link.value(); if (!(s > 0.0)) { throw new ApplicationException("positive underlying value required"); } int M = (pastFixings == 0 ? 1 : pastFixings); double muG = pastWeight * runningLog / M + futureWeight * Math.Log(s) + nu * timeSum / N; double forwardPrice = Math.Exp(muG + variance / 2.0); double riskFreeDiscount = process_.riskFreeRate().link.discount( arguments_.exercise.lastDate()); BlackCalculator black = new BlackCalculator(payoff, forwardPrice, Math.Sqrt(variance), riskFreeDiscount); results_.value = black.value(); results_.delta = futureWeight * black.delta(forwardPrice) * forwardPrice / s; results_.gamma = forwardPrice * futureWeight / (s * s) * (black.gamma(forwardPrice) * futureWeight * forwardPrice - pastWeight * black.delta(forwardPrice)); double Nx_1, nx_1; CumulativeNormalDistribution CND = new CumulativeNormalDistribution(); NormalDistribution ND = new NormalDistribution(); if (sigG > Const.QL_Epsilon) { double x_1 = (muG - Math.Log(payoff.strike()) + variance) / sigG; Nx_1 = CND.value(x_1); nx_1 = ND.value(x_1); } else { Nx_1 = (muG > Math.Log(payoff.strike()) ? 1.0 : 0.0); nx_1 = 0.0; } results_.vega = forwardPrice * riskFreeDiscount * ((dmuG_dsig + sigG * dsigG_dsig) * Nx_1 + nx_1 * dsigG_dsig); if (payoff.optionType() == Option.Type.Put) { results_.vega -= riskFreeDiscount * forwardPrice * (dmuG_dsig + sigG * dsigG_dsig); } double tRho = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(), arguments_.exercise.lastDate()); results_.rho = black.rho(tRho) * timeSum / (N * tRho) - (tRho - timeSum / N) * results_.value; double tDiv = divdc.yearFraction( process_.dividendYield().link.referenceDate(), arguments_.exercise.lastDate()); results_.dividendRho = black.dividendRho(tDiv) * timeSum / (N * tDiv); results_.strikeSensitivity = black.strikeSensitivity(); results_.theta = Utils.blackScholesTheta(process_, results_.value.GetValueOrDefault(), results_.delta.GetValueOrDefault(), results_.gamma.GetValueOrDefault()); }