예제 #1
0
 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)
예제 #2
0
 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)
예제 #3
0
 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)
예제 #4
0
 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)
예제 #5
0
 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)
예제 #6
0
 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)
예제 #7
0
 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())
예제 #8
0
 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())
예제 #9
0
#       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])
예제 #10
0
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())
예제 #11
0
 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())
예제 #12
0
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())
예제 #13
0
 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())