def setUp(self): T = 9 B = Annuity(T, [8], 4, 100, 0.5) P = Time(PutV(T, 105), [2, 4, 5, 6]) C = Time(CallVR(T, 110), [3, 4, 6, 7]) S = Time(CallA(T, 0), [1, 2, 3, 4, 9]) self.payoff = Stack([B, P, C, S]) Ssect = [ np.linspace(0, 0.25, 10), np.linspace(0.25, -.25, 10), np.linspace(-.25, 0.75, 10), np.linspace(0.75, 1, 9, endpoint=False) ] Vsect = [ np.linspace(0, -.25, 10), np.linspace(-.25, 0.25, 10), np.linspace(0.25, 0.50, 10), np.linspace(0.50, 1, 9, endpoint=False) ] Ssect = np.array(sum((list(i) for i in Ssect), [])) Vsect = np.array(sum((list(i) for i in Vsect), [])) critical = [10, 50, 100, 105, 110, 200] S = [] V = [] for i in range(len(critical) - 1): l, u = critical[i:i + 2] lu = u - l S.extend(Ssect * lu + l) V.extend(Vsect * lu + l) self.S = np.array(S) self.V = np.array(V)
def test_default(self): """Test default value of stacked Forward and American call.""" S = np.linspace(S0 - 10, S0 + 10, 21) Vd = np.maximum(S - K, 0) payoff = Stack([Forward(T, K), CallA(T, K)]) for t in np.linspace(0, 1, N, endpoint=False): self.assertTrue((payoff.default(t, S) == Vd).all()) self.assertRaises(AssertionError, payoff.default, T, S)
def test_transcient(self): """Test value of transient for stacked normal and reversed American call.""" S = np.linspace(S0 - 10, S0 + 10, 21) V = np.linspace(S0 + 10, S0 - 10, 21) Vm = np.minimum(np.maximum(V, np.maximum(S - K, 0)), K + 5) payoff = Stack([CallA(T, K), CallVR(T, K + 5)]) for t in np.linspace(0, 1, N, endpoint=False): self.assertTrue((payoff.transient(t, V, S) == Vm).all()) self.assertRaises(AssertionError, payoff.transient, T, V, S)
def setUp(self): T = 9 B = Annuity(T, [8], 4, 100, 0.5) P = Time(PutV(T, 105), [2, 4, 5, 6]) C = Time(CallVR(T, 110), [3, 4, 6, 7]) S = Time(CallA(T, 0), [1, 2, 3, 4, 9]) self.payoff = Stack([B, P, C, S]) Ssect = [ np.linspace(0, 0.25, 10), np.linspace(0.25, -0.25, 10), np.linspace(-0.25, 0.75, 10), np.linspace(0.75, 1, 9, endpoint=False), ] Vsect = [ np.linspace(0, -0.25, 10), np.linspace(-0.25, 0.25, 10), np.linspace(0.25, 0.50, 10), np.linspace(0.50, 1, 9, endpoint=False), ] Ssect = np.array(sum((list(i) for i in Ssect), [])) Vsect = np.array(sum((list(i) for i in Vsect), [])) critical = [10, 50, 100, 105, 110, 200] S = [] V = [] for i in range(len(critical) - 1): l, u = critical[i : i + 2] lu = u - l S.extend(Ssect * lu + l) V.extend(Vsect * lu + l) self.S = np.array(S) self.V = np.array(V)
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 test_value(self): """Test the value object for the binomial model.""" dS = WienerJumpProcess(0.1, 0.1, 0.02, 0) N = 16 T = 1 ct = np.linspace(0, T, N // 2 + 1) c = 1 S = 100 model = BinomialModel(N, dS, Stack([CallA(T, S), Annuity(T, ct, c)])) P = model.price(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 price sequence self.assertEqual(P.S[0][0], S) self.assertEqual(len(P.S), N + 1) for i in range(1, N + 1): self.assertGreaterEqual(P.S[i][0], P.S[i - 1][0]) self.assertLessEqual(P.S[i][-1], P.S[i - 1][-1]) self.assertTrue((P.S[i][:-1] > P.S[i][1:]).all()) # Test default sequence self.assertEqual(len(P.V), N + 1) for i in range(1, N + 1): self.assertGreaterEqual(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] >= 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())
# Nominal value = 100 # Semi-annual coupon = 4 # Recovery factor = 0 A = Annuity(T, np.arange(0.5, T + 0.5, 0.5), C=4, N=100, R=0) # American put option on portfolio # Strike = 105 # Time = 3 P = Time(Put(T, 105, A), times=[3]) # Reversed American call option on portfolio # Strike = 110 # Time = [2, 5] C = Time(Call(T, 110, A), times=[(2, 5)]) # Stock option (conversion option into stock for portfolio) S = Time(CallA(T, 0), times=[(0, 5)]) # Bond component of convertible bond B = Stack([A, P, C]) # Equity component of convertible bond E = S # Convertible bond: # Bond # American put option on portfolio # Reversed American call option on portfolio # Stock payoff = Stack([A, P, C, S])
class TestConvertibleBond(unittest.TestCase): """Test Payoff of unit tests, based on AKW08 Table 1""" def setUp(self): T = 9 B = Annuity(T, [8], 4, 100, 0.5) P = Time(PutV(T, 105), [2, 4, 5, 6]) C = Time(CallVR(T, 110), [3, 4, 6, 7]) S = Time(CallA(T, 0), [1, 2, 3, 4, 9]) self.payoff = Stack([B, P, C, S]) Ssect = [ np.linspace(0, 0.25, 10), np.linspace(0.25, -.25, 10), np.linspace(-.25, 0.75, 10), np.linspace(0.75, 1, 9, endpoint=False) ] Vsect = [ np.linspace(0, -.25, 10), np.linspace(-.25, 0.25, 10), np.linspace(0.25, 0.50, 10), np.linspace(0.50, 1, 9, endpoint=False) ] Ssect = np.array(sum((list(i) for i in Ssect), [])) Vsect = np.array(sum((list(i) for i in Vsect), [])) critical = [10, 50, 100, 105, 110, 200] S = [] V = [] for i in range(len(critical) - 1): l, u = critical[i:i + 2] lu = u - l S.extend(Ssect * lu + l) V.extend(Vsect * lu + l) self.S = np.array(S) self.V = np.array(V) def test_SV(self): """Test sample stock and portfolio values.""" S = self.S V = self.V for i in [50, 100, 105, 110]: self.assertTrue((S > i).any()) self.assertTrue((S == i).any()) self.assertTrue((S < i).any()) self.assertTrue((V > i).any()) self.assertTrue((V == i).any()) self.assertTrue((V < i).any()) self.assertTrue(((S > i) & (V < i)).any()) self.assertTrue(((S < i) & (V > i)).any()) def test_conv(self): """Test conversion option, without call or put option.""" t = 1 S = self.S V = self.V Vm = np.maximum(V, S) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_conv_put(self): """Test conversion and put option without call option.""" t = 2 S = self.S V = self.V Vm = np.maximum(V, S) # Normal conversion # Put option put = (V < 105) & (S < 105) self.assertTrue(put.any()) Vm[put] = 105 self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_conv_call(self): """Test conversion and call option, without put option.""" t = 3 S = self.S V = self.V Vm = np.maximum(V, S) # Normal conversion # Call option call = (V > 110) & (S <= 110) Vm[call] = 110 self.assertTrue(call.any()) # Conversion option (forced conversion) conv = (V > 110) & (S > 110) & (V > S) self.assertTrue(conv.any()) Vm[conv] = S[conv] self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_conv_call_put(self): """Test conversion, call and put option,""" t = 4 S = self.S V = self.V Vm = np.maximum(V, S) # Normal conversion # Put option put = (V < 105) & (S < 105) self.assertTrue(put.any()) Vm[put] = 105 # Call option call = (V > 110) & (S <= 110) Vm[call] = 110 self.assertTrue(call.any()) # Conversion option (forced conversion) conv = (V > 110) & (S > 110) & (V > S) self.assertTrue(conv.any()) Vm[conv] = S[conv] self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) # Default Vd = np.maximum(S, 50) self.assertTrue((self.payoff.default(t, S) == Vd).all()) def test_put(self): """Test put option, without conversion or call option.""" t = 5 S = self.S V = self.V Vm = np.maximum(V, 105) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_put_call(self): """Test put and call option, without conversion option.""" t = 6 S = self.S V = self.V Vm = V.copy() # Put option put = (V < 105) Vm[put] = 105 # Call option call = (V > 110) Vm[call] = 110 self.assertTrue(call.any()) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_call(self): """Test call option, without conversion or put option.""" t = 7 S = self.S V = self.V Vm = np.minimum(V, 110) self.assertTrue((V > 110).any()) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_coupon(self): t = 8 self.assertTrue((self.payoff.coupon(t) == 4).all()) def test_redemption(self): """Test redemption of convertible bond.""" S = self.S V = np.maximum(100, S) self.assertTrue((self.payoff.terminal(S) == V).all())
def test_terminal(self): """Test value of terminal for stacked Forward and American call.""" S = np.linspace(S0 - 10, S0 + 10, 21) V = np.maximum(S - K + 5, 0) payoff = Stack([Forward(T, K - 5), CallE(T, K)]) self.assertTrue((payoff.terminal(S) == V).all())
class TestConvertibleBond(unittest.TestCase): """Test Payoff of unit tests, based on AKW08 Table 1""" def setUp(self): T = 9 B = Annuity(T, [8], 4, 100, 0.5) P = Time(PutV(T, 105), [2, 4, 5, 6]) C = Time(CallVR(T, 110), [3, 4, 6, 7]) S = Time(CallA(T, 0), [1, 2, 3, 4, 9]) self.payoff = Stack([B, P, C, S]) Ssect = [ np.linspace(0, 0.25, 10), np.linspace(0.25, -0.25, 10), np.linspace(-0.25, 0.75, 10), np.linspace(0.75, 1, 9, endpoint=False), ] Vsect = [ np.linspace(0, -0.25, 10), np.linspace(-0.25, 0.25, 10), np.linspace(0.25, 0.50, 10), np.linspace(0.50, 1, 9, endpoint=False), ] Ssect = np.array(sum((list(i) for i in Ssect), [])) Vsect = np.array(sum((list(i) for i in Vsect), [])) critical = [10, 50, 100, 105, 110, 200] S = [] V = [] for i in range(len(critical) - 1): l, u = critical[i : i + 2] lu = u - l S.extend(Ssect * lu + l) V.extend(Vsect * lu + l) self.S = np.array(S) self.V = np.array(V) def test_SV(self): """Test sample stock and portfolio values.""" S = self.S V = self.V for i in [50, 100, 105, 110]: self.assertTrue((S > i).any()) self.assertTrue((S == i).any()) self.assertTrue((S < i).any()) self.assertTrue((V > i).any()) self.assertTrue((V == i).any()) self.assertTrue((V < i).any()) self.assertTrue(((S > i) & (V < i)).any()) self.assertTrue(((S < i) & (V > i)).any()) def test_conv(self): """Test conversion option, without call or put option.""" t = 1 S = self.S V = self.V Vm = np.maximum(V, S) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_conv_put(self): """Test conversion and put option without call option.""" t = 2 S = self.S V = self.V Vm = np.maximum(V, S) # Normal conversion # Put option put = (V < 105) & (S < 105) self.assertTrue(put.any()) Vm[put] = 105 self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_conv_call(self): """Test conversion and call option, without put option.""" t = 3 S = self.S V = self.V Vm = np.maximum(V, S) # Normal conversion # Call option call = (V > 110) & (S <= 110) Vm[call] = 110 self.assertTrue(call.any()) # Conversion option (forced conversion) conv = (V > 110) & (S > 110) & (V > S) self.assertTrue(conv.any()) Vm[conv] = S[conv] self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_conv_call_put(self): """Test conversion, call and put option,""" t = 4 S = self.S V = self.V Vm = np.maximum(V, S) # Normal conversion # Put option put = (V < 105) & (S < 105) self.assertTrue(put.any()) Vm[put] = 105 # Call option call = (V > 110) & (S <= 110) Vm[call] = 110 self.assertTrue(call.any()) # Conversion option (forced conversion) conv = (V > 110) & (S > 110) & (V > S) self.assertTrue(conv.any()) Vm[conv] = S[conv] self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) # Default Vd = np.maximum(S, 50) self.assertTrue((self.payoff.default(t, S) == Vd).all()) def test_put(self): """Test put option, without conversion or call option.""" t = 5 S = self.S V = self.V Vm = np.maximum(V, 105) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_put_call(self): """Test put and call option, without conversion option.""" t = 6 S = self.S V = self.V Vm = V.copy() # Put option put = V < 105 Vm[put] = 105 # Call option call = V > 110 Vm[call] = 110 self.assertTrue(call.any()) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_call(self): """Test call option, without conversion or put option.""" t = 7 S = self.S V = self.V Vm = np.minimum(V, 110) self.assertTrue((V > 110).any()) self.assertTrue((self.payoff.transient(t, V, S) == Vm).all()) def test_coupon(self): t = 8 self.assertTrue((self.payoff.coupon(t) == 4).all()) def test_redemption(self): """Test redemption of convertible bond.""" S = self.S V = np.maximum(100, S) self.assertTrue((self.payoff.terminal(S) == V).all())