private Greeks fnGreeks() { double dIv; bool isCall = OptionQuote.Option.OpType == AOption.EOpType.Call; DateTime dtTradeDate = Date.Decode(OptionQuote.TradeDate); DateTime dtExpDate = Date.Decode(OptionQuote.Option.ExpDate); double dT = Convert.ToDouble(OptionQuote.Option.TimeToExp(dtTradeDate, dtExpDate)); double dRfr = fnRiskFreeRate(dtTradeDate, dtExpDate); int implVolNewton = BlackSholes.ImplVol_Newton( Convert.ToDouble(OptionQuote.Mid), Convert.ToDouble(OptionQuote.UnderPx), Convert.ToDouble(OptionQuote.Option.Strike), dT, dRfr, 0, isCall, out dIv); if (implVolNewton != 0) return null; double dTheoPx; var gg = new Greeks(); int nRet = BlackSholes.BlackSholesCals( Convert.ToDouble(OptionQuote.UnderPx), Convert.ToDouble(OptionQuote.Option.Strike), dT, dRfr, 0, isCall, dIv, out dTheoPx, gg); return nRet != 0 ? null : gg; }
public static int BlackSholesCals(double dUnderPx, double dStrike, double dT, double dR, double dQ, bool isCall, double dSigma,out double dPx,Greeks greeks) { const double dEps = 10e-6; dPx = double.NaN; if( (dStrike < dEps) || (dSigma < dEps) || (dT < dEps) ) return 2;/* Check if any of the the input arguments are too small */ var dExpQt = Math.Exp(-dQ * dT); var dExpRt = Math.Exp(-dR * dT); var d1 = Math.Log(dUnderPx / dStrike) + (dR - dQ + (dSigma * dSigma / 2.0)) * dT; d1 = d1/(dSigma*Math.Sqrt(dT)); var d2 = d1-dSigma*Math.Sqrt(dT); if (isCall) dPx = dUnderPx * dExpQt * CumNormDistrib(d1) - dStrike * dExpRt * CumNormDistrib(d2); else dPx = -dUnderPx * dExpQt * CumNormDistrib(-d1) + dStrike * dExpRt * CumNormDistrib(-d2); if (greeks!=null) { double dPnd = Math.Exp(-d1 * d1 / 2.0) / Math.Sqrt(2.0 * Pi); if (isCall) { greeks.Delta = (CumNormDistrib(d1)) * dExpQt; /* delta */ greeks.Theta = -dUnderPx * dExpQt * dPnd * dSigma / (2.0 * Math.Sqrt(dT)) + dQ * dUnderPx * CumNormDistrib(d1) * dExpQt - dR * dStrike * dExpRt * CumNormDistrib(d2); /* theta */ greeks.Rho = dStrike * dT * dExpRt * CumNormDistrib(d2); /* rho */ } else { greeks.Delta = (CumNormDistrib(d1) - 1.0) * dExpQt; /* delta */ greeks.Theta = -dUnderPx * dExpQt * dPnd * dSigma / (2.0 * Math.Sqrt(dT)) - dQ * dUnderPx * CumNormDistrib(-d1) * dExpQt + dR * dStrike * dExpRt * CumNormDistrib(-d2); /* theta */ greeks.Rho = -dStrike * dT * dExpRt * CumNormDistrib(-d2); /* rho */ } greeks.Gamma = dPnd * dExpQt / (dUnderPx * dSigma * Math.Sqrt(dT)); /* gamma */ greeks.Vega = dUnderPx * dExpQt * Math.Sqrt(dT) * dPnd; /* vega */ greeks.IV = dSigma; } return 0; }
public static int ImplVol(double dPx, double dUnderPx, double dStrike, double dT, double dR, double dQ, bool isCall, double dSigMin, out double dImplVol) { const int nMaxIter = 50; const double dEps = 10e-6; dImplVol = double.NaN; double dTmp = isCall ? Math.Max(dUnderPx*Math.Exp(-dQ*dT)-dStrike*Math.Exp(-dR*dT),0) : Math.Max(dStrike*Math.Exp(-dR*dT)-dUnderPx*Math.Exp(-dQ*dT),0); if(Math.Abs(dPx-dTmp)<=Math.Sqrt(dEps)) return 3; double dSig = dSigMin; /* initial estimate */ double dSig1 = double.NaN; bool bDone=false; var greeks = new Greeks(); for(var i =0;i<nMaxIter&&(!bDone);++i) { double dVal; if(BlackSholesCals(dUnderPx, dStrike, dT, dR, dQ, isCall, dSig, out dVal, greeks)!= 0) return 1; dSig1 = dSig - (dVal - dPx)/greeks.Vega; /* compute the new estimate of sigma using Newton’s method */ if (dEps > Math.Abs((dSig1 - dSig)/dSig1)) bDone=true; /* check whether the specified accuracy has been reached */ dSig = dSig1; /* up date sigma */ } dImplVol = dSig1; /* return the estimate for sigma */ return !bDone ? 3 : 0; }
public static int ImplVol_Newton(double dPx, double dUnderPx, double dStrike, double dT, double dR, double dQ, bool isCall,out double dImplVol) { const int nMaxIter = 10000; const double dEps = 10e-6; dImplVol = Math.Sqrt(Math.Abs(Math.Log(dUnderPx / dStrike) + dR * dT) * 2 / dT); var greeks = new Greeks(); double dTryPx; if (BlackSholesCals(dUnderPx, dStrike, dT, dR, dQ, isCall, dImplVol, out dTryPx, greeks) != 0) return 1; double dMinDiff = Math.Abs(dPx - dTryPx); var bDone = false; for (var i = 0; i < nMaxIter; ++i) { if (Math.Abs(dPx - dTryPx) < dEps || Math.Abs(dPx - dTryPx) > dMinDiff) { bDone = true; break; } dImplVol = dImplVol - (dTryPx - dPx) / greeks.Vega; if (BlackSholesCals(dUnderPx, dStrike, dT, dR, dQ, isCall, dImplVol, out dTryPx, greeks) != 0) return 1; dMinDiff = Math.Abs(dPx - dTryPx); } return !bDone ? 3 : 0; }