internal static EPutCall SPutCall(PutCall x) { switch (x) { case PutCall.Put: return EPutCall.Put; case PutCall.Call: return EPutCall.Call; default: throw new NotSupportedException(); } }
public static double Parity(double P, double S, double X, double t, double r, PutCall PutCall) { return SmartQuant.Quant.FinMath.Parity(P, S, X, t, r, FinMath.SPutCall(PutCall)); }
public static double Rho(double S, double X, double t, double s, double r, PutCall PutCall) { return SmartQuant.Quant.FinMath.Rho(S, X, t, s, r, FinMath.SPutCall(PutCall)); }
//------------------------------------------------------------------------- /// <summary> /// Obtains an instance. /// </summary> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="putCall"> put or call </param> /// <param name="numberOfSteps"> the number of time steps </param> /// <returns> the instance </returns> public static EuropeanVanillaOptionFunction of(double strike, double timeToExpiry, PutCall putCall, int numberOfSteps) { double sign = putCall.Call ? 1d : -1d; ArgChecker.isTrue(numberOfSteps > 0, "the number of steps should be positive"); return(new EuropeanVanillaOptionFunction(strike, timeToExpiry, sign, numberOfSteps)); }
public Instrument(Instrument instrument) : this() { this.id = instrument.id; this.type = instrument.type; this.symbol = instrument.symbol; this.description = instrument.description; this.exchange = instrument.exchange; this.currencyId = instrument.currencyId; this.tickSize = instrument.tickSize; this.putcall = instrument.putcall; this.factor = instrument.factor; this.strike = instrument.strike; this.maturity = instrument.maturity; this.margin = instrument.margin; foreach (Leg current in instrument.Legs) { this.Legs.Add(new Leg(current.Instrument, current.Weight)); } this.trade = instrument.Trade; this.bid = instrument.Bid; this.ask = instrument.Ask; }
//------------------------------------------------------------------------- /// <summary> /// Computes the vega. /// <para> /// Note that the 'numeraire' is a simple multiplier and is the responsibility of the caller. /// /// </para> /// </summary> /// <param name="forward"> the forward value of the underlying </param> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="normalVol"> the normal volatility </param> /// <param name="putCall"> whether it is put or call </param> /// <returns> the vega </returns> public static double vega(double forward, double strike, double timeToExpiry, double normalVol, PutCall putCall) { int sign = putCall.Call ? 1 : -1; double rootT = Math.Sqrt(timeToExpiry); double sigmaRootT = normalVol * rootT; if (sigmaRootT < NEAR_ZERO) { double x = sign * (forward - strike); // ambiguous if x and sigmaRootT are tiny, then reference number is returned return(Math.Abs(x) > NEAR_ZERO ? 0d : rootT / Math.Sqrt(2d * Math.PI)); } double arg = (forward - strike) / sigmaRootT; double pdf = DISTRIBUTION.getPDF(arg); return(pdf * rootT); }
/// <summary> /// Creates an identifier for an ETD option instrument. /// <para> /// This takes into account the expiry of the underlying instrument. If the underlying expiry /// is the same as the expiry of the option, the identifier is the same as the normal one. /// Otherwise, the underlying expiry is added after the option expiry. For example: /// {@code 'OG-ETD~O-ECAG-OGBS-201706-P1.50-U201709'}. /// /// </para> /// </summary> /// <param name="exchangeId"> the MIC code of the exchange where the instruments are traded </param> /// <param name="contractCode"> the code supplied by the exchange for use in clearing and margining, such as in SPAN </param> /// <param name="expiryMonth"> the month of expiry </param> /// <param name="variant"> the variant of the ETD, such as 'Monthly', 'Weekly, 'Daily' or 'Flex' </param> /// <param name="version"> the non-negative version, zero by default </param> /// <param name="putCall"> the Put/Call flag </param> /// <param name="strikePrice"> the strike price </param> /// <param name="underlyingExpiryMonth"> the expiry of the underlying instrument, such as a future, may be null </param> /// <returns> the identifier </returns> public static SecurityId optionId(ExchangeId exchangeId, EtdContractCode contractCode, YearMonth expiryMonth, EtdVariant variant, int version, PutCall putCall, double strikePrice, YearMonth underlyingExpiryMonth) { ArgChecker.notNull(exchangeId, "exchangeId"); ArgChecker.notNull(contractCode, "contractCode"); ArgChecker.notNull(expiryMonth, "expiryMonth"); ArgChecker.notNull(variant, "variant"); ArgChecker.notNull(putCall, "putCall"); string putCallStr = putCall == PutCall.PUT ? "P" : "C"; string versionCode = version > 0 ? "V" + version + SEPARATOR : ""; NumberFormat f = NumberFormat.getIntegerInstance(Locale.ENGLISH); f.GroupingUsed = false; f.MaximumFractionDigits = 8; string strikeStr = f.format(strikePrice).replace('-', 'M'); string underlying = ""; if (underlyingExpiryMonth != null && !underlyingExpiryMonth.Equals(expiryMonth)) { underlying = SEPARATOR + "U" + underlyingExpiryMonth.format(YM_FORMAT); } string id = (new StringBuilder(40)).Append(OPT_PREFIX).Append(exchangeId).Append(SEPARATOR).Append(contractCode).Append(SEPARATOR).Append(expiryMonth.format(YM_FORMAT)).Append(variant.Code).Append(SEPARATOR).Append(versionCode).Append(putCallStr).Append(strikeStr).Append(underlying).ToString(); return(SecurityId.of(ETD_SCHEME, id)); }
private EtdOptionSecurity(SecurityInfo info, EtdContractSpecId contractSpecId, YearMonth expiry, EtdVariant variant, int version, PutCall putCall, double strikePrice, YearMonth underlyingExpiryMonth) { JodaBeanUtils.notNull(info, "info"); JodaBeanUtils.notNull(contractSpecId, "contractSpecId"); JodaBeanUtils.notNull(expiry, "expiry"); JodaBeanUtils.notNull(variant, "variant"); ArgChecker.notNegative(version, "version"); JodaBeanUtils.notNull(putCall, "putCall"); this.info = info; this.contractSpecId = contractSpecId; this.expiry = expiry; this.variant = variant; this.version = version; this.putCall = putCall; this.strikePrice = strikePrice; this.underlyingExpiryMonth = underlyingExpiryMonth; }
/// <summary> /// Sets whether the option is a put or call. </summary> /// <param name="putCall"> the new value, not null </param> /// <returns> this, for chaining, not null </returns> public Builder putCall(PutCall putCall) { JodaBeanUtils.notNull(putCall, "putCall"); this.putCall_Renamed = putCall; return(this); }
//------------------------------------------------------------------------- /// <summary> /// Obtains an instance from a contract specification, expiry year-month, variant, version, put/call and strike price. /// <para> /// The security identifier will be automatically created using <seealso cref="EtdIdUtils"/>. /// The specification must be for an option. /// /// </para> /// </summary> /// <param name="spec"> the option contract specification </param> /// <param name="expiry"> the expiry year-month of the option </param> /// <param name="variant"> the variant of the ETD, such as 'Monthly', 'Weekly, 'Daily' or 'Flex' </param> /// <param name="version"> the non-negative version, zero if versioning does not apply </param> /// <param name="putCall"> whether the option is a put or call </param> /// <param name="strikePrice"> the strike price of the option </param> /// <returns> an option security based on this contract specification </returns> /// <exception cref="IllegalStateException"> if the product type of the contract specification is not {@code OPTION} </exception> public static EtdOptionSecurity of(EtdContractSpec spec, YearMonth expiry, EtdVariant variant, int version, PutCall putCall, double strikePrice) { return(of(spec, expiry, variant, version, putCall, strikePrice, null)); }
/// <summary> /// Obtains an instance from a contract specification, expiry year-month, variant, /// version, put/call, strike price and underlying expiry. /// <para> /// The security identifier will be automatically created using <seealso cref="EtdIdUtils"/>. /// The specification must be for an option. /// /// </para> /// </summary> /// <param name="spec"> the option contract specification </param> /// <param name="expiry"> the expiry year-month of the option </param> /// <param name="variant"> the variant of the ETD, such as 'Monthly', 'Weekly, 'Daily' or 'Flex' </param> /// <param name="version"> the non-negative version, zero if versioning does not apply </param> /// <param name="putCall"> whether the option is a put or call </param> /// <param name="strikePrice"> the strike price of the option </param> /// <param name="underlyingExpiryMonth"> the expiry of the underlying instrument, such as a future, may be null </param> /// <returns> an option security based on this contract specification </returns> /// <exception cref="IllegalStateException"> if the product type of the contract specification is not {@code OPTION} </exception> public static EtdOptionSecurity of(EtdContractSpec spec, YearMonth expiry, EtdVariant variant, int version, PutCall putCall, double strikePrice, YearMonth underlyingExpiryMonth) { if (spec.Type != EtdType.OPTION) { throw new System.InvalidOperationException(Messages.format("Cannot create an EtdOptionSecurity from a contract specification of type '{}'", spec.Type)); } SecurityId securityId = EtdIdUtils.optionId(spec.ExchangeId, spec.ContractCode, expiry, variant, version, putCall, strikePrice, underlyingExpiryMonth); return(EtdOptionSecurity.builder().info(SecurityInfo.of(securityId, spec.PriceInfo)).contractSpecId(spec.Id).expiry(expiry).variant(variant).version(version).putCall(putCall).strikePrice(strikePrice).underlyingExpiryMonth(underlyingExpiryMonth).build()); }
/// <summary> /// Creates an option security based on this contract specification. /// <para> /// The security identifier will be automatically created using <seealso cref="EtdIdUtils"/>. /// The <seealso cref="#getType() type"/> must be <seealso cref="EtdType#OPTION"/> otherwise an exception will be thrown. /// /// </para> /// </summary> /// <param name="expiryMonth"> the expiry month of the option </param> /// <param name="variant"> the variant of the ETD, such as 'Monthly', 'Weekly, 'Daily' or 'Flex' </param> /// <param name="version"> the non-negative version, zero by default </param> /// <param name="putCall"> whether the option is a put or call </param> /// <param name="strikePrice"> the strike price of the option </param> /// <param name="underlyingExpiryMonth"> the expiry of the underlying instrument, such as a future </param> /// <returns> an option security based on this contract specification </returns> /// <exception cref="IllegalStateException"> if the product type of the contract specification is not {@code OPTION} </exception> public EtdOptionSecurity createOption(YearMonth expiryMonth, EtdVariant variant, int version, PutCall putCall, double strikePrice, YearMonth underlyingExpiryMonth) { return(EtdOptionSecurity.of(this, expiryMonth, variant, version, putCall, strikePrice, underlyingExpiryMonth)); }
/// <summary> /// Test consistency between price methods, and Greek via finite difference. /// </summary> public virtual void test_trinomialTree() { int nSteps = 135; double dt = TIME / nSteps; LatticeSpecification lattice = new CoxRossRubinsteinLatticeSpecification(); double fdEps = 1.0e-4; foreach (bool isCall in new bool[] { true, false }) { foreach (double strike in STRIKES) { foreach (double interest in INTERESTS) { foreach (double vol in VOLS) { foreach (double dividend in DIVIDENDS) { OptionFunction function = EuropeanVanillaOptionFunction.of(strike, TIME, PutCall.ofPut(!isCall), nSteps); double[] @params = lattice.getParametersTrinomial(vol, interest - dividend, dt).toArray(); DoubleArray time = DoubleArray.of(nSteps + 1, i => dt * i); DoubleArray df = DoubleArray.of(nSteps, i => Math.Exp(-interest * dt)); double[][] stateValue = new double[nSteps + 1][]; stateValue[0] = new double[] { SPOT }; IList <DoubleMatrix> prob = new List <DoubleMatrix>(); double[] probs = new double[] { @params[5], @params[4], @params[3] }; for (int i = 0; i < nSteps; ++i) { int index = i; stateValue[i + 1] = DoubleArray.of(2 * i + 3, j => SPOT * Math.Pow(@params[2], index + 1 - j) * Math.Pow(@params[1], j)).toArray(); double[][] probMatrix = new double[2 * i + 1][]; Arrays.fill(probMatrix, probs); prob.Add(DoubleMatrix.ofUnsafe(probMatrix)); } RecombiningTrinomialTreeData treeData = RecombiningTrinomialTreeData.of(DoubleMatrix.ofUnsafe(stateValue), prob, df, time); double priceData = TRINOMIAL_TREE.optionPrice(function, treeData); double priceParams = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend); assertEquals(priceData, priceParams); ValueDerivatives priceDeriv = TRINOMIAL_TREE.optionPriceAdjoint(function, treeData); assertEquals(priceDeriv.Value, priceData); double priceUp = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT + fdEps, vol, interest, dividend); double priceDw = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT - fdEps, vol, interest, dividend); double fdDelta = 0.5 * (priceUp - priceDw) / fdEps; assertEquals(priceDeriv.getDerivative(0), fdDelta, 3.0e-2); } } } } } }
public virtual void test_trinomialTree() { int nSteps = 135; LatticeSpecification[] lattices = new LatticeSpecification[] { new CoxRossRubinsteinLatticeSpecification(), new TrigeorgisLatticeSpecification() }; double tol = 5.0e-3; foreach (bool isCall in new bool[] { true, false }) { foreach (double strike in STRIKES) { foreach (double interest in INTERESTS) { foreach (double vol in VOLS) { foreach (double dividend in DIVIDENDS) { OptionFunction function = EuropeanVanillaOptionFunction.of(strike, TIME, PutCall.ofPut(!isCall), nSteps); double exact = BlackScholesFormulaRepository.price(SPOT, strike, TIME, vol, interest, interest - dividend, isCall); foreach (LatticeSpecification lattice in lattices) { double computed = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend); assertEquals(computed, exact, Math.Max(exact, 1d) * tol); } } } } } } }
internal static PutOrCall Convert(PutCall value) { switch (value) { case PutCall.Put: return PutOrCall.Put; case PutCall.Call: return PutOrCall.Call; default: throw new ArgumentException(string.Format("Unsupported PutOrCall - {0}", value)); } }
public static double BM(double S, double X, double t, double s, double r, PutCall PutCall, int n) { return(SmartQuant.Quant.FinMath.BM(S, X, t, s, r, FinMath.SPutCall(PutCall))); }
//------------------------------------------------------------------------- /// <summary> /// Computes the price and first order derivatives. /// <para> /// The derivatives are stored in an array with: /// <ul> /// <li>[0] derivative with respect to the forward /// <li>[1] derivative with respect to the volatility /// <li>[2] derivative with respect to the strike /// </ul> /// /// </para> /// </summary> /// <param name="forward"> the forward value of the underlying </param> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="normalVol"> the normal volatility </param> /// <param name="numeraire"> the numeraire </param> /// <param name="putCall"> whether it is put or call </param> /// <returns> the price and associated derivatives </returns> public static ValueDerivatives priceAdjoint(double forward, double strike, double timeToExpiry, double normalVol, double numeraire, PutCall putCall) { int sign = putCall.Call ? 1 : -1; double price; double cdf = 0d; double pdf = 0d; double arg = 0d; double x = 0d; // Implementation Note: Forward sweep. double sigmaRootT = normalVol * Math.Sqrt(timeToExpiry); if (sigmaRootT < NormalFormulaRepository.NEAR_ZERO) { x = sign * (forward - strike); price = (x > 0 ? numeraire * x : 0d); } else { arg = sign * (forward - strike) / sigmaRootT; cdf = NormalFormulaRepository.DISTRIBUTION.getCDF(arg); pdf = NormalFormulaRepository.DISTRIBUTION.getPDF(arg); price = numeraire * (sign * (forward - strike) * cdf + sigmaRootT * pdf); } // Implementation Note: Backward sweep. double forwardDerivative; double volatilityDerivative; double strikeDerivative; double priceBar = 1d; if (sigmaRootT < NormalFormulaRepository.NEAR_ZERO) { double xBar = (x > 0 ? numeraire : 0d); forwardDerivative = sign * xBar; strikeDerivative = -forwardDerivative; volatilityDerivative = 0d; } else { double cdfBar = numeraire * (sign * (forward - strike)) * priceBar; double pdfBar = numeraire * sigmaRootT * priceBar; double argBar = pdf * cdfBar - pdf * arg * pdfBar; forwardDerivative = numeraire * sign * cdf * priceBar + sign / sigmaRootT * argBar; strikeDerivative = -forwardDerivative; double sigmaRootTBar = -arg / sigmaRootT * argBar + numeraire * pdf * priceBar; volatilityDerivative = Math.Sqrt(timeToExpiry) * sigmaRootTBar; } return(ValueDerivatives.of(price, DoubleArray.of(forwardDerivative, volatilityDerivative, strikeDerivative))); }
public static double Theta(double S, double X, double t, double s, double r, PutCall PutCall) { return(SmartQuant.Quant.FinMath.Theta(S, X, t, s, r, FinMath.SPutCall(PutCall))); }
//------------------------------------------------------------------------- /// <summary> /// Computes the forward price. /// <para> /// Note that the 'numeraire' is a simple multiplier and is the responsibility of the caller. /// /// </para> /// </summary> /// <param name="forward"> the forward value of the underlying </param> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="normalVol"> the normal volatility </param> /// <param name="putCall"> whether it is put or call </param> /// <returns> the forward price </returns> public static double price(double forward, double strike, double timeToExpiry, double normalVol, PutCall putCall) { double sigmaRootT = normalVol * Math.Sqrt(timeToExpiry); int sign = putCall.Call ? 1 : -1; if (sigmaRootT < NEAR_ZERO) { double x = sign * (forward - strike); return(x > 0 ? x : 0d); } double arg = sign * (forward - strike) / sigmaRootT; double cdf = DISTRIBUTION.getCDF(arg); double pdf = DISTRIBUTION.getPDF(arg); return(sign * (forward - strike) * cdf + sigmaRootT * pdf); }
public double priceVega(double expiry, PutCall putCall, double strike, double forward, double volatility) { double shift = shiftCurve.yValue(expiry); return(BlackFormulaRepository.vega(forward + shift, strike + shift, expiry, volatility)); }
public static double Theta(double S, double X, double t, double s, double r, PutCall PutCall) { return FreeQuant.Quant.FinMath.Theta(S, X, t, s, r, FinMath.SPutCall(PutCall)); }
public static double Payoff(double S, double X, PutCall PutCall) { return(FreeQuant.Quant.FinMath.Payoff(S, X, FinMath.SPutCall(PutCall))); }
//------------------------------------------------------------------------- /// <summary> /// Obtains an instance. /// </summary> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="putCall"> put or call </param> /// <param name="numberOfSteps"> number of steps </param> /// <param name="barrierType"> the barrier type </param> /// <param name="barrierLevel"> the barrier level </param> /// <param name="rebate"> the rebate </param> /// <returns> the instance </returns> public static ConstantContinuousSingleBarrierKnockoutFunction of(double strike, double timeToExpiry, PutCall putCall, int numberOfSteps, BarrierType barrierType, double barrierLevel, DoubleArray rebate) { ArgChecker.isTrue(numberOfSteps > 0, "the number of steps should be positive"); ArgChecker.isTrue(numberOfSteps + 1 == rebate.size(), "the size of rebate should be numberOfSteps + 1"); double sign = putCall.Call ? 1d : -1d; return(new ConstantContinuousSingleBarrierKnockoutFunction(strike, timeToExpiry, sign, numberOfSteps, barrierType, barrierLevel, rebate)); }
public static double Parity(double P, double S, double X, double t, double r, PutCall PutCall) { return(FreeQuant.Quant.FinMath.Parity(P, S, X, t, r, FinMath.SPutCall(PutCall))); }
public static double Payoff(double S, double X, PutCall PutCall) { return SmartQuant.Quant.FinMath.Payoff(S, X, FinMath.SPutCall(PutCall)); }
public static double MC(double S, double X, double t, double s, double r, PutCall PutCall, int n) { return(FreeQuant.Quant.FinMath.MC(S, X, t, s, r, FinMath.SPutCall(PutCall))); }
public static double MC(double S, double X, double t, double s, double r, PutCall PutCall, int n) { return SmartQuant.Quant.FinMath.MC(S, X, t, s, r, FinMath.SPutCall(PutCall)); }
public static double Rho(double S, double X, double t, double s, double r, PutCall PutCall) { return(FreeQuant.Quant.FinMath.Rho(S, X, t, s, r, FinMath.SPutCall(PutCall))); }
public static double ImpliedVolatility(double S, double X, double t, double r, double P, OptionType OptionType, PutCall PutCall, OptionPrice Method) { return SmartQuant.Quant.FinMath.ImpliedVolatility(S, X, t, r, P, FinMath.SOptionType(OptionType), FinMath.SPutCall(PutCall), FinMath.SOptionPrice(Method)); }
public static double ImpliedVolatility(double S, double X, double t, double r, double P, OptionType OptionType, PutCall PutCall, OptionPrice Method) { return(FreeQuant.Quant.FinMath.ImpliedVolatility(S, X, t, r, P, FinMath.SOptionType(OptionType), FinMath.SPutCall(PutCall), FinMath.SOptionPrice(Method))); }
/// <summary> /// Sets whether the option is put or call. /// <para> /// A call gives the owner the right, but not obligation, to buy the underlying at /// an agreed price in the future. A put gives a similar option to sell. /// </para> /// </summary> /// <param name="putCall"> the new value </param> /// <returns> this, for chaining, not null </returns> public Builder putCall(PutCall putCall) { this.putCall_Renamed = putCall; return(this); }
public virtual void test_trinomialTree_down() { int nSteps = 133; LatticeSpecification lattice = new CoxRossRubinsteinLatticeSpecification(); DoubleArray rebate = DoubleArray.of(nSteps + 1, i => REBATE_AMOUNT); double barrierLevel = 76d; double tol = 1.0e-2; foreach (bool isCall in new bool[] { true, false }) { foreach (double strike in STRIKES) { foreach (double interest in INTERESTS) { foreach (double vol in VOLS) { foreach (double dividend in DIVIDENDS) { OptionFunction function = ConstantContinuousSingleBarrierKnockoutFunction.of(strike, TIME, PutCall.ofPut(!isCall), nSteps, BarrierType.DOWN, barrierLevel, rebate); SimpleConstantContinuousBarrier barrier = SimpleConstantContinuousBarrier.of(BarrierType.DOWN, KnockType.KNOCK_OUT, barrierLevel); double exact = REBATE_AMOUNT * REBATE_PRICER.price(SPOT, TIME, interest - dividend, interest, vol, barrier.inverseKnockType()) + BARRIER_PRICER.price(SPOT, strike, TIME, interest - dividend, interest, vol, isCall, barrier); double computed = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend); assertEquals(computed, exact, Math.Max(exact, 1d) * tol); } } } } } }
public double priceTheta(double expiry, PutCall putCall, double strike, double forward, double volatility) { return(NormalFormulaRepository.theta(forward, strike, expiry, volatility, putCall)); }
public double priceDelta(double expiry, double tenor, PutCall putCall, double strike, double forward, double volatility) { return(BlackFormulaRepository.delta(forward, strike, expiry, volatility, putCall.Call)); }
//------------------------------------------------------------------------- /// <summary> /// Computes the delta. /// <para> /// Note that the 'numeraire' is a simple multiplier and is the responsibility of the caller. /// /// </para> /// </summary> /// <param name="forward"> the forward value of the underlying </param> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="normalVol"> the normal volatility </param> /// <param name="putCall"> whether it is put or call </param> /// <returns> the delta </returns> public static double delta(double forward, double strike, double timeToExpiry, double normalVol, PutCall putCall) { int sign = putCall.Call ? 1 : -1; double sigmaRootT = normalVol * Math.Sqrt(timeToExpiry); if (sigmaRootT < NEAR_ZERO) { double x = sign * (forward - strike); if (Math.Abs(x) <= NEAR_ZERO) { // ambiguous if x and sigmaRootT are tiny, then reference number is returned return(sign * 0.5); } return(x > 0 ? sign : 0d); } double arg = sign * (forward - strike) / sigmaRootT; double cdf = DISTRIBUTION.getCDF(arg); return(sign * cdf); }
public double priceTheta(double expiry, double tenor, PutCall putCall, double strike, double forward, double volatility) { return(BlackFormulaRepository.driftlessTheta(forward, strike, expiry, volatility)); }
//------------------------------------------------------------------------- /// <summary> /// Computes the implied volatility. /// <para> /// If the volatility data is not zero, it is used as a starting point for the volatility search. /// </para> /// <para> /// Note that the 'numeraire' is a simple multiplier and is the responsibility of the caller. /// /// </para> /// </summary> /// <param name="optionPrice"> the price of the option </param> /// <param name="forward"> the forward value of the underlying </param> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="initialNormalVol"> the normal volatility used to start the search </param> /// <param name="numeraire"> the numeraire </param> /// <param name="putCall"> whether it is put or call </param> /// <returns> the implied volatility </returns> public static double impliedVolatility(double optionPrice, double forward, double strike, double timeToExpiry, double initialNormalVol, double numeraire, PutCall putCall) { double intrinsicPrice = numeraire * Math.Max(0, (putCall.Call ? 1 : -1) * (forward - strike)); ArgChecker.isTrue(optionPrice > intrinsicPrice || DoubleMath.fuzzyEquals(optionPrice, intrinsicPrice, 1e-6), "Option price (" + optionPrice + ") less than intrinsic value (" + intrinsicPrice + ")"); if (System.BitConverter.DoubleToInt64Bits(optionPrice) == Double.doubleToLongBits(intrinsicPrice)) { return(0d); } double sigma = (Math.Abs(initialNormalVol) < 1e-10 ? 0.3 * forward : initialNormalVol); double maxChange = 0.5 * forward; ValueDerivatives price = priceAdjoint(forward, strike, timeToExpiry, sigma, numeraire, putCall); double vega = price.getDerivative(1); double change = (price.Value - optionPrice) / vega; double sign = Math.Sign(change); change = sign * Math.Min(maxChange, Math.Abs(change)); if (change > 0 && change > sigma) { change = sigma; } int count = 0; while (Math.Abs(change) > EPS) { sigma -= change; price = priceAdjoint(forward, strike, timeToExpiry, sigma, numeraire, putCall); vega = price.getDerivative(1); change = (price.Value - optionPrice) / vega; sign = Math.Sign(change); change = sign * Math.Min(maxChange, Math.Abs(change)); if (change > 0 && change > sigma) { change = sigma; } if (count++ > MAX_ITERATIONS) { BracketRoot bracketer = new BracketRoot(); BisectionSingleRootFinder rootFinder = new BisectionSingleRootFinder(EPS); System.Func <double, double> func = (double?volatility) => { return(numeraire * NormalFormulaRepository.price(forward, strike, timeToExpiry, volatility.Value, putCall) - optionPrice); }; double[] range = bracketer.getBracketedPoints(func, 0d, 10d); return(rootFinder.getRoot(func, range[0], range[1]).Value); } } return(sigma); }
public static double BM(double S, double X, double t, double s, double r, PutCall PutCall, int n) { return FreeQuant.Quant.FinMath.BM(S, X, t, s, r, FinMath.SPutCall(PutCall)); }
public double priceVega(double expiry, PutCall putCall, double strike, double forward, double volatility) { return(BlackFormulaRepository.vega(forward, strike, expiry, volatility)); }
/// <summary> /// Creates an identifier for an ETD option instrument. /// <para> /// A typical monthly ETD with version zero will have the format: /// {@code 'OG-ETD~O-ECAG-OGBS-201706-P1.50'}. /// </para> /// <para> /// A more complex flex ETD (12th of the month, Cash settlement, European) with version two will have the format: /// {@code 'OG-ETD~O-ECAG-OGBS-20170612CE-V2-P1.50'}. /// /// </para> /// </summary> /// <param name="exchangeId"> the MIC code of the exchange where the instruments are traded </param> /// <param name="contractCode"> the code supplied by the exchange for use in clearing and margining, such as in SPAN </param> /// <param name="expiryMonth"> the month of expiry </param> /// <param name="variant"> the variant of the ETD, such as 'Monthly', 'Weekly, 'Daily' or 'Flex' </param> /// <param name="version"> the non-negative version, zero by default </param> /// <param name="putCall"> the Put/Call flag </param> /// <param name="strikePrice"> the strike price </param> /// <returns> the identifier </returns> public static SecurityId optionId(ExchangeId exchangeId, EtdContractCode contractCode, YearMonth expiryMonth, EtdVariant variant, int version, PutCall putCall, double strikePrice) { return(optionId(exchangeId, contractCode, expiryMonth, variant, version, putCall, strikePrice, null)); }