// A parsimonious constructor is chosen, which for example // doesn't need a strike. The reason for this is, that we'd // like this class to calculate deltas for different strikes // many times, e.g. in a numerical routine, which will be the // case in the smile setup procedure. public BlackDeltaCalculator(Option.Type ot, DeltaVolQuote.DeltaType dt, double spot, double dDiscount, // domestic discount double fDiscount, // foreign discount double stdDev) { dt_ = dt; ot_ = ot; dDiscount_ = dDiscount; fDiscount_ = fDiscount; stdDev_ = stdDev; spot_ = spot; forward_ = spot * fDiscount / dDiscount; phi_ = (int)ot; Utils.QL_REQUIRE(spot_ > 0.0, () => "positive spot value required: " + spot_ + " not allowed"); Utils.QL_REQUIRE(dDiscount_ > 0.0, () => "positive domestic discount factor required: " + dDiscount_ + " not allowed"); Utils.QL_REQUIRE(fDiscount_ > 0.0, () => "positive foreign discount factor required: " + fDiscount_ + " not allowed"); Utils.QL_REQUIRE(stdDev_ >= 0.0, () => "non-negative standard deviation required: " + stdDev_ + " not allowed"); fExpPos_ = forward_ * Math.Exp(0.5 * stdDev_ * stdDev_); fExpNeg_ = forward_ * Math.Exp(-0.5 * stdDev_ * stdDev_); }
public BlackDeltaCalculator(Option.Type ot, DeltaVolQuote.DeltaType dt, double spot, double dDiscount, double fDiscount, double stDev) : this(NQuantLibcPINVOKE.new_BlackDeltaCalculator((int)ot, (int)dt, spot, dDiscount, fDiscount, stDev), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public DeltaVolQuote(QuoteHandle vol, DeltaVolQuote.DeltaType deltaType, double maturity, DeltaVolQuote.AtmType atmType) : this(NQuantLibcPINVOKE.new_DeltaVolQuote__SWIG_1(QuoteHandle.getCPtr(vol), (int)deltaType, maturity, (int)atmType), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public BlackDeltaPremiumAdjustedMaxStrikeClass(Option.Type ot, DeltaVolQuote.DeltaType dt, double spot, double dDiscount, // domestic discount double fDiscount, // foreign discount double stdDev) { bdc_ = new BlackDeltaCalculator(ot, dt, spot, dDiscount, fDiscount, stdDev); stdDev_ = stdDev; }
public BlackDeltaPremiumAdjustedSolverClass(Option.Type ot, DeltaVolQuote.DeltaType dt, double spot, double dDiscount, // domestic discount double fDiscount, // foreign discount double stdDev, double delta) { bdc_ = new BlackDeltaCalculator(ot, dt, spot, dDiscount, fDiscount, stdDev); delta_ = delta; }
public DeltaData(Option.Type ot, DeltaVolQuote.DeltaType dt, double spot, double dDf, double fDf, double stdDev, double strike, double value) : this() { this.ot = ot; this.dt = dt; this.spot = spot; this.dDf = dDf; this.fDf = fDf; this.stdDev = stdDev; this.strike = strike; this.value = value; }
// alternative delta type private double strikeFromDelta(double delta, DeltaVolQuote.DeltaType dt) { double res = 0.0; double arg = 0.0; InverseCumulativeNormal f = new InverseCumulativeNormal(); Utils.QL_REQUIRE(delta * phi_ >= 0.0, () => "Option type and delta are incoherent."); switch (dt) { case DeltaVolQuote.DeltaType.Spot: Utils.QL_REQUIRE(Math.Abs(delta) <= fDiscount_, () => "Spot delta out of range."); arg = -phi_ *f.value(phi_ *delta / fDiscount_) * stdDev_ + 0.5 * stdDev_ * stdDev_; res = forward_ * Math.Exp(arg); break; case DeltaVolQuote.DeltaType.Fwd: Utils.QL_REQUIRE(Math.Abs(delta) <= 1.0, () => "Forward delta out of range."); arg = -phi_ *f.value(phi_ *delta) * stdDev_ + 0.5 * stdDev_ * stdDev_; res = forward_ * Math.Exp(arg); break; case DeltaVolQuote.DeltaType.PaSpot: case DeltaVolQuote.DeltaType.PaFwd: // This has to be solved numerically. One of the // problems is that the premium adjusted call delta is // not monotonic in strike, such that two solutions // might occur. The one right to the max of the delta is // considered to be the correct strike. Some proper // interval bounds for the strike need to be chosen, the // numerics can otherwise be very unreliable and // unstable. I've chosen Brent over Newton, since the // interval can be specified explicitly and we can not // run into the area on the left of the maximum. The // put delta doesn't have this property and can be // solved without any problems, but also numerically. BlackDeltaPremiumAdjustedSolverClass f1 = new BlackDeltaPremiumAdjustedSolverClass( ot_, dt, spot_, dDiscount_, fDiscount_, stdDev_, delta); Brent solver = new Brent(); solver.setMaxEvaluations(1000); double accuracy = 1.0e-10; double rightLimit = 0.0; double leftLimit = 0.0; // Strike of not premium adjusted is always to the right of premium adjusted if (dt == DeltaVolQuote.DeltaType.PaSpot) { rightLimit = strikeFromDelta(delta, DeltaVolQuote.DeltaType.Spot); } else { rightLimit = strikeFromDelta(delta, DeltaVolQuote.DeltaType.Fwd); } if (phi_ < 0) { // if put res = solver.solve(f1, accuracy, rightLimit, 0.0, spot_ * 100.0); break; } else { // find out the left limit which is the strike // corresponding to the value where premium adjusted // deltas have their maximum. BlackDeltaPremiumAdjustedMaxStrikeClass g = new BlackDeltaPremiumAdjustedMaxStrikeClass( ot_, dt, spot_, dDiscount_, fDiscount_, stdDev_); leftLimit = solver.solve(g, accuracy, rightLimit * 0.5, 0.0, rightLimit); double guess = leftLimit + (rightLimit - leftLimit) * 0.5; res = solver.solve(f1, accuracy, guess, leftLimit, rightLimit); } // end if phi<0 else break; default: Utils.QL_FAIL("invalid delta type"); break; } return(res); }
public void setDeltaType(DeltaVolQuote.DeltaType dt) { dt_ = dt; }