-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVerticalSpread.py
119 lines (96 loc) · 3.78 KB
/
VerticalSpread.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from config import *
class VerticalSpread:
def __init__ (self, underlying_price, K1, K2, premium1, premium2, spread_type):
self.underlying_price = underlying_price;
#
# Define Upper/Lower Strikes
# • K1 = lower strike
# • K2 = upper strike
#
self.K1 = min(K1, K2);
self.K2 = max(K1, K2);
self.premium1 = np.round(premium1, 4);
self.premium2 = np.round(premium2, 4);
self.premium = np.round(abs(self.premium1-self.premium2), 4);
self.spread_type = spread_type;
self.price_range = np.linspace(.8*self.underlying_price, 1.2*self.underlying_price, 200);
vertical_spreads = ['bear_call', 'bear_put', 'bull_call', 'bull_put'];
if spread_type not in vertical_spreads:
raise ValueError('Invalid Spread type');
self.is_credit_spread = spread_type in ['bear_call', 'bull_put'];
self.is_debit_spread = not self.is_credit_spread;
print(f'Lower Strike: {self.K1}');
print(f'Upper Strike: {self.K2}');
print(f'Lower Strike Premium: {self.premium1}');
print(f'Upper Strike Premium: {self.premium2}');
print(f'Net Premium: {self.premium}');
print(f'Credit Spread: {self.is_credit_spread}');
print(f'Debit Spread: {self.is_debit_spread}');
def get_payoff (self, S_T):
if self.spread_type == 'bull_call':
return np.maximum(S_T-self.K1,0) - np.maximum(S_T-self.K2,0) - self.premium;
elif self.spread_type == 'bull_put':
return np.maximum(self.K1-S_T,0) - np.maximum(self.K2-S_T,0) + self.premium;
elif self.spread_type == 'bear_call':
return np.maximum(S_T-self.K2,0) - np.maximum(S_T-self.K1,0) + self.premium;
elif self.spread_type == 'bear_put':
return np.maximum(self.K2-S_T,0) - np.maximum(self.K1-S_T,0) - self.premium;
else:
return np.array();
def breakeven_price (self):
def objective_function (S_T):
if self.spread_type == 'bull_call':
return np.maximum(S_T-self.K1,0) - np.maximum(S_T-self.K2,0) - self.premium;
elif self.spread_type == 'bull_put':
return np.maximum(self.K1-S_T,0) - np.maximum(self.K2-S_T,0) + self.premium;
elif self.spread_type == 'bear_call':
return np.maximum(S_T-self.K2,0) - np.maximum(S_T-self.K1,0) + self.premium;
elif self.spread_type == 'bear_put':
return np.maximum(self.K2-S_T,0) - np.maximum(self.K1-S_T,0) - self.premium;
lower_bound = self.K1;
upper_bound = self.K2;
if self.is_credit_spread:
upper_bound += self.premium;
else:
lower_bound -= self.premium;
print(f'Search Bounds for Breakeven: ({lower_bound, upper_bound})');
try:
return brentq(objective_function, lower_bound, upper_bound);
except ValueError:
print('wtf breakeven');
return None;
def max_loss (self):
if self.is_credit_spread:
return (self.K2 - self.K1) - self.premium;
else:
return self.premium;
def max_profit (self):
if self.is_credit_spread:
return self.premium;
else:
return (self.K2 - self.K1) - self.premium;
def risk_reward_ratio (self):
return self.max_loss() / self.max_profit();
def return_on_risk (self):
return self.max_profit() / self.max_loss();
def metrics(self):
spread_metrics = {
'breakeven_price': self.breakeven_price(),
'max_loss': np.round(self.max_loss(), 4),
'max_profit': np.round(self.max_profit(), 4),
'risk_reward_ratio': np.round(self.risk_reward_ratio(), 4),
'return_on_risk': np.round(self.return_on_risk(), 4)
};
return spread_metrics;
def payoff_diagram (self):
payoff_values = self.get_payoff(self.price_range);
plt.figure(figsize=(10,6));
plt.plot(self.price_range, payoff_values);
plt.axhline(y=0, color='r', linestyle='--');
plt.axvline(x=self.underlying_price, color='g', linestyle='--', label='Current Price');
plt.title(f"{self.spread_type.replace('_', ' ').title()} Spread Payoff");
plt.xlabel('Underlying Price at Expiry');
plt.ylabel('Payoff');
plt.grid(True);
plt.legend();
plt.show();