-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtsmom.py
105 lines (95 loc) · 3.7 KB
/
tsmom.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
#package imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
#data imports
#all data has been previously downloaded and saved locally from IEXcloud
df = pd.read_csv('IBM.csv', parse_dates=True, index_col=0)
frame = pd.DataFrame(df)
#build of the strategy function
#set shorts to true or false depending on whether or not you want to add shorts positions
def TSMstrat(returns, period=1, shorts=False):
if shorts:
#map allows us to transforma all items in an iterable without having to use a for loop
position = returns.rolling(period).mean().map(
#lambda can take any number of arguments but only have one expression
lambda x: -1 if x <= 0 else 1)
else:
position = returns.rolling(period).mean().map(
lambda x: 0 if x <= 0 else 1)
performance = position.shift(1) * returns
return performance
#calc of the standard returns
returns = np.log(frame['close'] / frame['close'].shift(1)).dropna()
#used for the plotting and graphing
label='amd'
ticker='amd'
performance = TSMstrat(returns, period=1, shorts=False).dropna()
years = (performance.index.max() - performance.index.min()).days / 365
perf_cum = np.exp(performance.cumsum())
tot = perf_cum[-1] - 1
ann = perf_cum[-1] ** (1 / years) - 1
vol = performance.std() * np.sqrt(252)
rfr = 0.02
sharpe = (ann - rfr) / vol
print(f"1-day tsm strat yields:" +
f"\n\t{tot*100:.2f}% total returns" +
f"\n\t{ann*100:.2f}% annual returns" +
f"\n\t{sharpe:.2f} Sharpe Ratio")
amd_ret = np.exp(returns.cumsum())
b_tot = amd_ret[-1] - 1
b_ann = amd_ret[-1] ** (1 / years) - 1
b_vol = returns.std() * np.sqrt(252)
b_sharpe = (b_ann - rfr) / b_vol
print(f"Baseline Buy-and-Hold Strategy yields:" +
f"\n\t{b_tot*100:.2f}% total returns" +
f"\n\t{b_ann*100:.2f}% annual returns" +
f"\n\t{b_sharpe:.2f} Sharpe Ratio")
periods = [8, 12, 15, 21, 33]
fig = plt.figure(figsize=(12, 10))
gs = fig.add_gridspec(4, 4)
ax0 = fig.add_subplot(gs[:2, :4])
ax1 = fig.add_subplot(gs[2:, :2])
ax2 = fig.add_subplot(gs[2:, 2:])
ax0.plot((np.exp(returns.cumsum()) - 1) * 100, label=ticker, linestyle='-')
perf_dict = {'tot_ret': {'buy_and_hold': (np.exp(returns.sum()) - 1)}}
perf_dict['ann_ret'] = {'buy_and_hold': b_ann}
perf_dict['sharpe'] = {'buy_and_hold': b_sharpe}
#for loop to iterate thru the periods list
for p in periods:
log_perf = TSMstrat(returns, period=p, shorts=True)
perf = np.exp(log_perf.cumsum())
perf_dict['tot_ret'][p] = (perf[-1] - 1)
ann = (perf[-1] ** (1/years) - 1)
perf_dict['ann_ret'][p] = ann
vol = log_perf.std() * np.sqrt(252)
perf_dict['sharpe'][p] = (ann - rfr) / vol
ax0.plot((perf - 1) * 100, label=f'{p}-Day Mean')
ax0.set_ylabel('Returns (%)')
ax0.set_xlabel('Date')
ax0.set_title('Cumulative Returns')
ax0.grid()
ax0.legend()
_ = [ax1.bar(i, v * 100) for i, v in enumerate(perf_dict['ann_ret'].values())]
ax1.set_xticks([i for i, k in enumerate(perf_dict['ann_ret'])])
ax1.set_xticklabels([f'{k}-Day Mean'
if type(k) is int else ticker for
k in perf_dict['ann_ret'].keys()],
rotation=45)
ax1.grid()
ax1.set_ylabel('Returns (%)')
ax1.set_xlabel('Strategy')
ax1.set_title('Annual Returns')
_ = [ax2.bar(i, v) for i, v in enumerate(perf_dict['sharpe'].values())]
ax2.set_xticks([i for i, k in enumerate(perf_dict['sharpe'])])
ax2.set_xticklabels([f'{k}-Day Mean'
if type(k) is int else ticker for
k in perf_dict['sharpe'].keys()],
rotation=45)
ax2.grid()
ax2.set_ylabel('Sharpe Ratio')
ax2.set_xlabel('Strategy')
ax2.set_title('Sharpe Ratio')
plt.tight_layout()
plt.show()