-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbacktesting.py
More file actions
155 lines (110 loc) · 3.93 KB
/
Copy pathbacktesting.py
File metadata and controls
155 lines (110 loc) · 3.93 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# %%
from datetime import datetime
import talib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# %%
def get_stock(symbol: str, start: str = None, end: str = None) -> pd.DataFrame:
"""Get Stock data frame
Args:
symbol: stock symbol
start: start date trading, ex 2019-02-28
end: end date trading, ex 2019-02-28
Returns:
DataFrame Stock
"""
# download stock from github
# raw data from repository
df = pd.read_csv(f'https://raw.githubusercontent.com/faisalburhanudin/idx/master/stocks/{symbol}.csv')
# convert string Date to DateTime
df['DateTime'] = pd.DatetimeIndex(df['Date'])
df['Month'] = pd.DatetimeIndex(df['Date']).month
df['Year'] = pd.DatetimeIndex(df['Date']).year
df['Day'] = pd.DatetimeIndex(df['Date']).day
# limit dataframe start until start date
if start:
df = df[df['DateTime'] >= datetime.fromisoformat(start)]
# limit dataframe until end date
if end:
df = df[df['DateTime'] <= datetime.fromisoformat(end)]
return df
stock = get_stock('BBRI', '2000-01-01')
# %%
def buy_and_hold(stock_df: pd.DataFrame):
money = 0
record = []
df_month = stock_df.groupby(['Year', 'Month'], as_index=False).first()
for value in df_month.itertuples():
# deposit money
money += 1_000_000
# price per lot
per_lot = value.Close * 100
# total share buy
buy_share = money // per_lot * 100
# total cost buy
buy_cost = buy_share * value.Close
# deduct from money
money -= buy_cost
record.append((value.DateTime, money, value.Close, buy_share))
record = pd.DataFrame(record, columns=['DateTime', 'Money', 'Close', 'Share'])
record['SumShare'] = record['Share'].expanding().sum()
record['Value'] = record['SumShare'] * record['Close'] + record['Money']
return record
record_df = buy_and_hold(stock)
# %%
def golden(stock_df: pd.DataFrame):
stock_df['MA50'] = talib.SMA(stock_df['Close'], timeperiod=50)
stock_df['MA200'] = talib.SMA(stock_df['Close'], timeperiod=200)
money = 0
record = []
df_month = stock_df.groupby(['Year', 'Month'], as_index=False).first()
for value in df_month.itertuples():
# deposit money
money += 1_000_000
buy_share = 0
if not np.isnan(value.MA50) and not np.isnan(value.MA200):
# price per lot
per_lot = value.Close * 100
# buy stock
if value.MA50 >= value.MA200:
# total share buy
buy_share = money // per_lot * 100
# total cost buy
buy_cost = buy_share * value.Close
# deduct from money
money -= buy_cost
# sell stock
else:
# calculated total owned share
own_share = get_owned_share([i[3] for i in record])
if own_share:
buy_share = -own_share
money += own_share * value.Close
record.append((value.DateTime, money, value.Close, buy_share, value.MA50, value.MA200))
record = pd.DataFrame(record, columns=['DateTime', 'Money', 'Close', 'Share', 'MA50', 'MA200'])
record['SumShare'] = record['Share'].expanding().sum()
record['Value'] = record['SumShare'] * record['Close'] + record['Money']
return record
def get_owned_share(buy_share):
owned = 0
for i in reversed(buy_share):
if i < 0:
break
else:
owned += i
return owned
golden_df = golden(stock)
# %%
final = pd.DataFrame({
'DateTime': record_df['DateTime'],
'Close': record_df['Close'],
'hold': record_df['SumShare'],
'gold': golden_df['SumShare'],
'reality': record_df['Value'],
'idea': golden_df['Value'],
})
final.plot.line(x='DateTime', y=['reality', 'idea'])
ax = plt.gca()
ax.ticklabel_format(style='plain', axis='y')
plt.show()