def payoffProfile(self, sArr, spotMVAsZero=True, dayFromNow=0): if spotMVAsZero: mvNow = 0.0 for tr in self.tradeRecord: if tr: opt = EuropeanOption(tr["CallOrPut"] == "Call", tr["Strike"], tr["DayToExpiry"], tr["DvdYield"] / 100.0) opt.setLevel(self.spot, tr["ImplVol"] / 100.0, tr["RiskFree"] / 100.0) mvNow += opt.fairValue() * tr["Notional"] payoff = [0.0] * len(sArr) for tr in self.tradeRecord: if tr: opt = EuropeanOption(tr["CallOrPut"] == "Call", tr["Strike"], max(0.0, tr["DayToExpiry"] - dayFromNow), tr["DvdYield"] / 100.0) for i, s in enumerate(sArr): opt.setLevel(s, tr["ImplVol"] / 100.0, tr["RiskFree"] / 100.0) payoff[i] += opt.fairValue() * tr["Notional"] for i in range(len(sArr)): payoff[i] -= mvNow return payoff
def perTradeCalc(self): tradeCalc = [{} for i in range(self.NTradeInput)] for i, tr in enumerate(self.tradeRecord): if tr: opt = EuropeanOption(tr["CallOrPut"] == "Call", tr["Strike"], tr["DayToExpiry"], tr["DvdYield"] / 100.0) opt.setLevel(self.spot, tr["ImplVol"] / 100.0, tr["RiskFree"] / 100.0) tradeCalc[i]["FairValue"] = opt.fairValue() tradeCalc[i]["Delta"] = opt.delta() tradeCalc[i]["Gamma"] = opt.gamma() tradeCalc[i]["Vega"] = opt.vega() tradeCalc[i]["Rho"] = opt.rho() tradeCalc[i]["Theta"] = opt.theta() / self.DaysPerYear return tradeCalc
def perScenCalc(self, scen): calc = {} calc["FairValue"], calc["Delta"], calc["Gamma"], calc["Vega"], calc[ "Rho"], calc["Theta"] = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 for tr in self.tradeRecord: if tr: vol = scen[f"k={tr['Strike']:.2f}"] / 100.0 opt = EuropeanOption( tr["CallOrPut"] == "Call", tr["Strike"], tr["DayToExpiry"] - abs(scen["DayToExpiry"]), tr["DvdYield"] / 100.0) opt.setLevel(self.spot + scen["Spot"], vol, (tr["RiskFree"] + scen["RiskFree"]) / 100.0) calc["FairValue"] += opt.fairValue() * tr["Notional"] calc["Delta"] += opt.delta() * tr["Notional"] calc["Gamma"] += opt.gamma() * tr["Notional"] calc["Vega"] += opt.vega() * tr["Notional"] calc["Rho"] += opt.rho() * tr["Notional"] calc["Theta"] += opt.theta( ) * tr["Notional"] / self.DaysPerYear return calc
def greekProfile(self, sArr, greekName): greekArr = [0.0] * len(sArr) for tr in self.tradeRecord: if tr: opt = EuropeanOption(tr["CallOrPut"] == "Call", tr["Strike"], tr["DayToExpiry"], tr["DvdYield"] / 100.0) for i, s in enumerate(sArr): opt.setLevel(s, tr["ImplVol"] / 100.0, tr["RiskFree"] / 100.0) if greekName.lower() == "delta": greekArr[i] += opt.delta() * tr["Notional"] elif greekName.lower() == "gamma": greekArr[i] += opt.gamma() * tr["Notional"] elif greekName.lower() == "vega": greekArr[i] += opt.vega() * tr["Notional"] elif greekName.lower() == "rho": greekArr[i] += opt.rho() * tr["Notional"] elif greekName.lower() == "theta": greekArr[i] += opt.theta( ) * tr["Notional"] / self.DaysPerYear return greekArr
def _init_option_a(self): opt = EuropeanOption(True, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt.setLevel(200.0, 0.3, 0.03) #spot, ivol, riskFree return opt
def test_expired_put_2(self): opt = EuropeanOption(False, 51.0, 0.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt.setLevel(50.0, 0.3, 0.03) #spot, ivol, riskFree assert self._isFloatNear(opt.fairValue(), 1.0, 1e-16)
def test_f_volga(self): #Delta Decay/ Charm: - d2X/dt dv = -dDelta/dt = -dTheta/dS dvol = 0.001 opt1 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt1.setLevel(200.0, 0.300, 0.03) #spot, ivol, riskFree #note for the option class, theta convention = -dV/dt v1 = opt1.vega() opt2 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt2.setLevel(200.0, 0.300+dvol, 0.03) #spot, ivol, riskFree v2 = opt2.vega() approx = (v2-v1)/dvol optMid = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield optMid.setLevel(200.0, 0.300+dvol*0.5, 0.03) #spot, ivol, riskFree assert self._isFloatNear( approx/ optMid.volga(), 1.0, 1e-3)
def test_f_charm(self): #Delta Decay/ Charm: - d2X/dt dS = -dDelta/dt = -dTheta/dS dt = 0.1 opt1 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt1.setLevel(200.0, 0.300, 0.03) #spot, ivol, riskFree #note for the option class, theta convention = -dV/dt d1 = opt1.delta() opt2 = EuropeanOption(False, 204.0, 91.0+dt, 0.02) #isCall, strike, dayToExpiry, dvdYield opt2.setLevel(200.0, 0.300, 0.03) #spot, ivol, riskFree d2 = opt2.delta() approx = -(d2-d1)/(dt/365.0) optMid = EuropeanOption(False, 204.0, 91.0+dt*0.5, 0.02) #isCall, strike, dayToExpiry, dvdYield optMid.setLevel(200.0, 0.300, 0.03) #spot, ivol, riskFree assert self._isFloatNear( approx/ optMid.charm(), 1.0, 1e-3)
def test_f_veta(self): #veta = d2V/ dt dv = dTheta/dv dvol = 0.001 opt1 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt1.setLevel(200.0, 0.300, 0.03) #spot, ivol, riskFree #note for the option class, theta convention = -dV/dt t1 = -opt1.theta() opt2 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt2.setLevel(200.0, 0.300+dvol, 0.03) #spot, ivol, riskFree t2 = -opt2.theta() approx = (t2-t1)/dvol optMid = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield optMid.setLevel(200.0, 0.300+dvol*0.5, 0.03) #spot, ivol, riskFree assert self._isFloatNear( approx/ optMid.veta(), 1.0, 1e-3)
def test_f_vanna(self): #vanna = d2V/ dS dv = dDelta/dv dvol = 0.001 opt1 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt1.setLevel(200.0, 0.300, 0.03) #spot, ivol, riskFree d1 = opt1.delta() opt2 = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt2.setLevel(200.0, 0.300+dvol, 0.03) #spot, ivol, riskFree d2 = opt2.delta() approx = (d2-d1)/dvol optMid = EuropeanOption(False, 204.0, 91.0, 0.02) #isCall, strike, dayToExpiry, dvdYield optMid.setLevel(200.0, 0.300+dvol*0.5, 0.03) #spot, ivol, riskFree print(approx) print(optMid.vanna()) assert self._isFloatNear( approx/ optMid.vanna(), 1.0, 1e-3)
def _init_option_d(self): opt = EuropeanOption(False, 49.0, 30.0, 0.02) #isCall, strike, dayToExpiry, dvdYield opt.setLevel(50.0, 0.3, 0.03) #spot, ivol, riskFree return opt
def prtfCalc(self): calc = {} calc["FairValue"], calc["Delta"], calc["Gamma"], calc["Vega"], calc[ "Rho"], calc["Theta"] = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 calc["Vanna"], calc["Volga"], calc["Veta"], calc[ "Charm"] = 0.0, 0.0, 0.0, 0.0 for tr in self.tradeRecord: if tr: opt = EuropeanOption(tr["CallOrPut"] == "Call", tr["Strike"], tr["DayToExpiry"], tr["DvdYield"] / 100.0) opt.setLevel(self.spot, tr["ImplVol"] / 100.0, tr["RiskFree"] / 100.0) calc["FairValue"] += opt.fairValue() * tr["Notional"] calc["Delta"] += opt.delta() * tr["Notional"] calc["Gamma"] += opt.gamma() * tr["Notional"] calc["Vega"] += opt.vega() * tr["Notional"] calc["Rho"] += opt.rho() * tr["Notional"] calc["Theta"] += opt.theta( ) * tr["Notional"] / self.DaysPerYear calc["Vanna"] += opt.vanna() * tr["Notional"] calc["Volga"] += opt.volga() * tr["Notional"] calc["Veta"] += opt.veta() * tr["Notional"] calc["Charm"] += opt.charm() * tr["Notional"] return calc