-
Notifications
You must be signed in to change notification settings - Fork 1
/
bt_example.py
102 lines (77 loc) · 3.18 KB
/
bt_example.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
import bt
import pandas as pd
from bt.algos import WeighTarget
# data = pd.read_csv('histdata/stocks_psi_geral/son-pl_daily_01-03-2000_11-02-2018.csv', names = ["open","high","low","close","date"], parse_dates=['date'], index_col=4, date_parser=parse, skiprows=1)
def long_only_ew(tickers, start='2010-01-01', name='long_only_ew'):
s = bt.Strategy(name, [bt.algos.RunOnce(),
bt.algos.SelectAll(),
bt.algos.WeighEqually(),
bt.algos.Rebalance()])
data = bt.get(tickers, start=start)
bt.data.csv()
return bt.Backtest(s, data)
class SelectWhere(bt.Algo):
"""
Selects securities based on an indicator DataFrame.
Selects securities where the value is True on the current date (target.now).
Args:
* signal (DataFrame): DataFrame containing the signal (boolean DataFrame)
Sets:
* selected
"""
def __init__(self, signal):
self.signal = signal
def __call__(self, target):
# get signal on target.now
if target.now in self.signal.index:
sig = self.signal.ix[target.now]
# get indices where true as list
selected = list(sig.index[sig])
# save in temp - this will be used by the weighing algo
target.temp['selected'] = selected
# return True because we want to keep on moving down the stack
return True
def above_sma(tickers, sma_per=50, start='2010-01-01', name='above_sma'):
"""
Long securities that are above their n period
Simple Moving Averages with equal weights.
"""
# download data
data = bt.get(tickers, start=start)
print(type(data))
print(data.head())
# calc sma
sma = data.rolling(sma_per).mean()
# create strategy
s = bt.Strategy(name, [SelectWhere(data > sma),
bt.algos.WeighEqually(),
bt.algos.Rebalance()])
# now we create the backtest
return bt.Backtest(s, data)
def ma_cross(tickers, start='2010-01-01',
short_ma=50, long_ma=200, name='ma_cross'):
# these are all the same steps as above
data = bt.get(tickers, start=start)
short_sma = data.rolling(short_ma).mean()
long_sma = data.rolling(long_ma).mean()
# target weights
tw = long_sma.copy()
tw[short_sma > long_sma] = 1.0
tw[short_sma <= long_sma] = -1.0
tw[long_sma.isnull()] = 0.0
# here we specify the children (3rd) arguemnt to make sure the strategy
# has the proper universe. This is necessary in strategies of strategies
s = bt.Strategy(name, [WeighTarget(tw), bt.algos.Rebalance()], [tickers])
return bt.Backtest(s, data)
# create the backtests
tickers = 'aapl,msft,c,gs,ge'
sma10 = above_sma(tickers, sma_per=10, name='sma10')
sma20 = above_sma(tickers, sma_per=20, name='sma20')
sma40 = above_sma(tickers, sma_per=40, name='sma40')
benchmark = long_only_ew('spy', name='spy')
# run all the backtests!
res = bt.run(sma10, sma20, sma40, benchmark)
print(res.plot(freq='m'))
res.display()
print(res.plot_correlation())
print(res.get_transactions())