def main(): S = np.linspace(0, 200, 200 * 8 + 1) Sl = 0 Su = 250 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) legend = [] label = "$\\Omega^v = [%i, 5]$" model = FDEModel(N, dS, payoff) fig = plt.figure() fig.set_figwidth(1.8 * fig.get_figwidth()) ax = fig.add_subplot(1, 2, 1) for i in range(1, 5): Conv.times = [(i, 5)] ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) legend.append(label % i) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(legend) ax = fig.add_subplot(1, 2, 2, projection="3d") plot_model(ax, dS, payoff)
def test_table20_5(self): """Test Example 20.1 using explicit finite difference method.""" model = FDEModel(10, self.dS, self.V) P = model.price(0, 100, 20, scheme=ExplicitScheme, boundary="ignore") for i in reversed(range(len(P.V))): self.assertTrue( (np.abs(self.table20_5[::-1, i] - P.V[i]) < 0.01).all())
def plot_model(ax, dS, payoff): N = 40 model = FDEModel(N, dS, payoff) P = model.price(0, 250, 125, scheme=CrankNicolsonScheme) colours = choices(P) plot_strips(ax, P.t, P.S[:100], np.array(P.V)[:, :100].T, facecolors=colours[:100]) ax.set_xlabel("Time") ax.set_ylabel("Stock Price") ax.set_zlabel("Portfolio Value") legend(ax)
def main(): S = np.arange(24, 121) Sl = 0 Su = 200 N = 128 * T K = 8 * (Su - Sl) Sk = K * (S - Sl) / (Su - Sl) dS1 = copy.copy(dS) dS1.lambd_ = lambda S: 0.02 * (S / 100)**-1.2 dS1.cap_lambda = True dS2 = copy.copy(dS) dS2.lambd_ = lambda S: 0.02 * (S / 100)**-2.0 dS2.cap_lambda = True model1 = FDEModel(N, dS, payoff) model2 = FDEModel(N, dS1, payoff) model3 = FDEModel(N, dS2, payoff) plt.plot(S, model1.price(Sl, Su, K).V[0][Sk]) plt.plot(S, model2.price(Sl + 1, Su, K - 8).V[0][Sk - 8]) plt.plot(S, model3.price(Sl + 1, Su, K - 8).V[0][Sk - 8]) plt.xlim(S[0], S[-1]) plt.ylim(50, 150) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend( ["Constant hazard rate", "$\\alpha = -1.2$", "$\\alpha = -2.0$"], loc=2)
def main(): N = 128 * T S = np.arange(24, 121) model1 = FDEModel(N, dS, payoff) model2 = FDEModel(N, dS_var12, payoff) model3 = FDEModel(N, dS_var20, payoff) plt.plot(S, delta(S, model3)) plt.plot(S, delta(S, model2)) plt.plot(S, delta(S, model1)) plt.xlim(S[0], S[-1]) plt.ylim(-1, 1) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["$\\alpha = -2.0$", "$\\alpha = -1.2$", "Constant hazard rate"], loc=4)
def main(): S = np.linspace(0, 120, 120 * 8 + 1) Sl = 0 Su = 200 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) model1 = FDEModel(N, dS, payoff) model2 = FDEModel(N, dS_var, payoff) plt.plot(S, model1.price(Sl, Su, K).V[0][Sk]) plt.plot(S, np.append(A.R * A.N, model2.price(Sl + 1, Su, K - 8).V[0][Sk[:-1]])) plt.ylim([40, 160]) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["Constant $\\lambda$", "Synthesis $\\lambda$"], loc=2)
def main(): S = np.arange(80, 121) Sl = 0 Su = 200 N = 128 * T K = 8 * (Su - Sl) Sk = K * (S - Sl) / (Su - Sl) model1 = FDEModel(N, dS, payoff) model2 = FDEModel(N, dS_partial, payoff) model3 = FDEModel(N, dS_total, payoff) plt.plot(S, model1.price(Sl, Su, K).V[0][Sk]) plt.plot(S, model2.price(Sl, Su, K).V[0][Sk]) plt.plot(S, model3.price(Sl, Su, K).V[0][Sk]) plt.ylim(100, 150) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["No default", "Partial default", "Total Default"], loc=2)
def main(): S = np.linspace(0, 100, 100 * 8 + 1) Sl = 0 Su = 150 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) legend = [] label = "$\\Omega^p = \\{%i\\}$" model = FDEModel(N, dS, payoff) fig = plt.figure() ax = fig.add_subplot(111) for i in range(1, 5): P.times = [i] ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) legend.append(label % i) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(legend)
def main(): S = np.linspace(0, 200, 200 * 8 + 1) Sl = 0 Su = 250 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) legend = [] label = "$\\Omega^c = \\{%i\\}$" model = FDEModel(N, dS, payoff) fig = plt.figure() ax = fig.add_subplot(111) for i in range(1, 5): C.times = [i] ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) legend.append(label % i) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(legend)
def test_call(self): """Test that the finite difference model correctly prices a call option.""" K = 100 def price(r, S): d1 = (np.log(S / K) + r + 0.0005) / 0.1 d2 = d1 - 0.1 price = stats.norm.cdf(d1) * S price -= stats.norm.cdf(d2) * K * np.exp(-r) return price dS = WienerJumpProcess(0.1, 0.1) dSdq = WienerJumpProcess(0.1, 0.1, 0.1) S = np.linspace(0, 200, 41) V = CallE(1, K) model = FDEModel(64, dS, V) model2 = FDEModel(64, dSdq, V) accuracy = np.array((15, 15, 15, 14, 12, 11, 9, 8, 6, 5, 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)) accuracy2 = np.array((15, 15, 11, 10, 9, 8, 7, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)) for scheme in SCHEMES: P = model.price(0, 200, 40, scheme=scheme) self.assertTrue((abs(P.V[0] - price(0.1, S)) < 10.0**-accuracy).all()) P = model2.price(0, 200, 40, scheme=scheme) self.assertTrue((abs(P.V[0] - price(0.2, S)) < 10.0**-accuracy2).all()) return
def main(): Sl = 0 Su = 200 N = 128 * T K = 8 * (Su - Sl) S = 100 Sk = K * (S - Sl) / (Su - Sl) ETA = np.linspace(0, 1, 65) name = ["No default"] fde = FDEModel(N, dS, payoff) plt.plot(ETA, [fde.price(Sl, Su, K).V[0][Sk]] * len(ETA)) for lambd_ in (0.01, 0.02, 0.03): dS.lambd_ = lambd_ V = [] for eta in ETA: dS.eta = eta V.append(fde.price(Sl, Su, K).V[0][Sk]) plt.plot(ETA, V) name.append("$\\lambda = %i\\%%$" % (lambd_ * 100)) plt.xlabel("$\\eta$") plt.ylabel("Price at $S=100$") plt.legend(name, loc=3)
def test_value(self): """Test the value object for the finite difference model.""" dS = WienerJumpProcess(0.1, 0.1, 0.02, 0) N = 16 T = 1 ct = np.linspace(0, T, N // 2 + 1) c = 1 Sl = 0 Su = 200 K = 40 model = FDEModel(N, dS, Stack([CallA(T, 100), Annuity(T, ct, c)])) P = model.price(Sl, Su, K) S = P.S # Test N self.assertEqual(P.N, N) # Test time series self.assertEqual(P.t[0], 0) self.assertEqual(P.t[-1], T) self.assertEqual(len(P.t), N + 1) # Test Coupon sequence self.assertTrue((P.C[::2] == c).all()) self.assertTrue((P.C[1::2] == 0).all()) # Test K self.assertEqual(P.K, K) # Test Stock series self.assertEqual(P.S[0], Sl) self.assertEqual(P.S[-1], Su) self.assertEqual(len(P.S), K + 1) # Test default sequence self.assertEqual(len(P.V), N + 1) for i in range(1, N + 1): self.assertLessEqual(P.V[i][0] - P.C[i], P.V[i - 1][0]) self.assertLessEqual(P.V[i][-1] - P.C[i], P.V[i - 1][-1]) self.assertTrue((P.V[i][:-1] - 1e14 <= P.V[i][1:]).all()) self.assertEqual(len(P.X), N) for i in range(1, N): self.assertGreaterEqual(P.X[i][0], P.X[i - 1][0]) self.assertLessEqual(P.X[i][-1], P.X[i - 1][-1]) self.assertTrue((P.X[i][:-1] <= P.X[i][1:]).all())
def main(): S = np.linspace(0, 200, 200 * 8 + 1) Sl = 0 Su = 250 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) model = FDEModel(N, dS, payoff) fig = plt.figure() fig.set_figwidth(1.8 * fig.get_figwidth()) ax = fig.add_subplot(1, 2, 1) ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) C.times = [2] ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["$\\Omega^c = [2, 5)$", "$\\Omega^c = \\{2\\}$"]) ax = fig.add_subplot(1, 2, 2, projection="3d") plot_model(ax, dS, payoff)
def main(): S = np.linspace(0, 200, 200 * 8 + 1) Sl = 0 Su = 250 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) model = FDEModel(N, dS, payoff) fig = plt.figure() fig.set_figwidth(1.8 * fig.get_figwidth()) ax = fig.add_subplot(1, 2, 1) ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) A.N = -A.C ax.plot(S, model.price(Sl, Su, K).V[0][Sk]) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["$R = 104$", "$R = 0$"]) ax = fig.add_subplot(1, 2, 2, projection="3d") plot_model(ax, dS, payoff)
def main(): S0 = 100 Sl = 0 Su = 200 X = range(11) N = lambda x: 2**(x + 1) * T K = lambda x: 2**((x + 1) // 2) * (Su - Sl) fig = plt.figure() fig.set_figwidth(1.8 * fig.get_figwidth()) plt_x = fig.add_subplot(1, 2, 1) plt_t = fig.add_subplot(1, 2, 2) p = [] t = [] for x in X: start = time.time() p.append(float(BinomialModel(N(x), dS, payoff).price(S0))) t.append(time.time() - start) plt_x.plot(X, p) plt_t.plot(t, p) print p[-1] for scheme in (ImplicitScheme, CrankNicolsonScheme, PenaltyScheme): p = [] t = [] for x in X: k = K(x) Sk = k * (S0 - Sl) / (Su - Sl) start = time.time() p.append(FDEModel(N(x), dS, payoff).price(Sl, Su, k, scheme=scheme).V[0][Sk]) t.append(time.time() - start) plt_x.plot(X, p[:len(X)]) plt_t.plot(t, p) print p[-1] label(plt_x, "$\\delta_t = 2^{-(x + 1)}$; $\\delta_S = 2^{-\\frac{x + 1}{2}}$") label(plt_t, "Computational Time (seconds)") #plt_t.set_xlim(0, 2.5) plt_t.set_xscale('log')
def main(): S = np.linspace(0, 120, 120 * 8 + 1) Sl = 0 Su = 200 N = 128 * T K = 8 * (Su - Sl) Sk = (K * (S - Sl) / (Su - Sl)).astype(int) model1 = FDEModel(N, dS, payoff) model2 = FDEModel(N, dS_var, payoff) plt.plot(S, model1.price(Sl, Su, K).V[0][Sk]) plt.plot( S, np.append(A.R * A.N, model2.price(Sl + 1, Su, K - 8).V[0][Sk[:-1]])) plt.ylim([40, 160]) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["Constant $\\lambda$", "Synthesis $\\lambda$"], loc=2)
def test_forward(self): """Test that the finite difference model correctly prices a forward contract.""" dS = WienerJumpProcess(0.1, 0.1) dSdq = WienerJumpProcess(0.1, 0.1, 0.02) S = np.linspace(0, 200, 41) V = Forward(1, 100) model = FDEModel(64, dS, V) model2 = FDEModel(64, dSdq, V) for scheme in SCHEMES: if isinstance(scheme, CrankNicolsonScheme): accuracy = 5 else: accuracy = 2 P = model.price(0, 200, 40, scheme=scheme) self.assertTrue((abs(P.V[0] - (S - 100 * np.exp(-0.1))) < 10.0**-accuracy).all()) P = model2.price(0, 200, 40, scheme=scheme) self.assertTrue((abs(P.V[0] - (S - 100 * np.exp(-0.12))) < 10.0**-accuracy).all())
def test_annuity(self): """Test the pricing of a series of payments.""" def price(r): erdt = np.exp(-r) i = 1 / erdt - 1 return (1 - erdt**(T * 2)) / i + 10 * erdt**(T * 2) dS = WienerJumpProcess(0.1, 0.1) dSdq = WienerJumpProcess(0.1, 0.1, 0.02) # Semi-annual payments of 1 T = 10 V = Annuity(T, np.arange(0.5, T + 0.5, 0.5), 1, 10) model = FDEModel(T * 8, dS, V) model2 = FDEModel(T * 8, dSdq, V) for scheme in SCHEMES: P = model.price(0, 200, 25, scheme=scheme) self.assertTrue((np.abs(P.V[0] - price(0.05)) < 1e-1).all()) P = model2.price(0, 200, 25, scheme=scheme) self.assertTrue((np.abs(P.V[0] - price(0.06)) < 1e-1).all())
def main(): S = np.arange(24, 121) Sl = 0 Su = 200 N = 128 * T K = 8 * (Su - Sl) Sk = K * (S - Sl) / (Su - Sl) dS1 = copy.copy(dS) dS1.lambd_ = lambda S: 0.02 * (S / 100)**-1.2 dS1.cap_lambda = True dS2 = copy.copy(dS) dS2.lambd_ = lambda S: 0.02 * (S / 100)**-2.0 dS2.cap_lambda = True model1 = FDEModel(N, dS, payoff) model2 = FDEModel(N, dS1, payoff) model3 = FDEModel(N, dS2, payoff) plt.plot(S, model1.price(Sl, Su, K).V[0][Sk]) plt.plot(S, model2.price(Sl + 1, Su, K - 8).V[0][Sk - 8]) plt.plot(S, model3.price(Sl + 1, Su, K - 8).V[0][Sk - 8]) plt.xlim(S[0], S[-1]) plt.ylim(50, 150) plt.xlabel("Stock Price") plt.ylabel("Convertible Bond Price") plt.legend(["Constant hazard rate", "$\\alpha = -1.2$", "$\\alpha = -2.0$"], loc=2)
def test_table20_5(self): """Test Example 20.1 using explicit finite difference method.""" model = FDEModel(10, self.dS, self.V) P = model.price(0, 100, 20, scheme=ExplicitScheme, boundary="ignore") for i in reversed(range(len(P.V))): self.assertTrue((np.abs(self.table20_5[::-1, i] - P.V[i]) < 0.01).all())