リビジョン | c0a503d1f466d4f8ca74c6fd760a70e0b247df93 (tree) |
---|---|
日時 | 2023-01-23 18:20:41 |
作者 | kazuhiro_kondow <simauma.circus@gmai...> |
コミッター | kazuhiro_kondow |
検討資料を追加
M1で比較的使えそうなMACDのパラメータが出来たと思う
@@ -0,0 +1,381 @@ | ||
1 | +# 元ネタ | |
2 | +# https://qiita.com/Fujinoinvestor/items/780b138e441531860e60 | |
3 | + | |
4 | +# データcsvはmt5から取得している | |
5 | + | |
6 | +import os | |
7 | +import talib as ta | |
8 | +from backtesting.lib import crossover | |
9 | +from backtesting import Backtest | |
10 | +from backtesting import Strategy | |
11 | +import pandas as pd | |
12 | +import time | |
13 | + | |
14 | +# 現在ディレクトリ取得 | |
15 | +cwd = os.getcwd() | |
16 | + | |
17 | +# get data | |
18 | +data_path = os.path.join( | |
19 | + cwd, | |
20 | + 'csv', | |
21 | + 'USDJPY_M1_202210040357_202212302354.csv' | |
22 | +) | |
23 | + | |
24 | +# csvがtab区切りなのでreat_tableを使う | |
25 | +df = pd.read_table( | |
26 | + data_path | |
27 | +) | |
28 | + | |
29 | +# DataFrameのカラム名をbacktesting向けに修正 | |
30 | +df = df.rename( | |
31 | + columns={ | |
32 | + "<DATE>": "Date", | |
33 | + "<TIME>": "Time", | |
34 | + "<OPEN>": "Open", | |
35 | + "<HIGH>": "High", | |
36 | + "<LOW>": "Low", | |
37 | + "<CLOSE>": "Close", | |
38 | + "<TICKVOL>": "Volume", | |
39 | + "<VOL>": "not_use", | |
40 | + "<SPREAD>": "Spread", | |
41 | + } | |
42 | +) | |
43 | + | |
44 | +# 日付に時間文字列を結合 | |
45 | +df.Date = df['Date'] + ' ' + df['Time'] | |
46 | + | |
47 | +# Dateカラムをdatetime型に変換 | |
48 | +df.Date = pd.to_datetime(df['Date'], format='%Y.%m.%d %H:%M:%S') | |
49 | + | |
50 | +# indexをDateカラムに設定 | |
51 | +df = df.set_index('Date') | |
52 | + | |
53 | +# 必要なカラムのみ取得 | |
54 | +data = df.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']] | |
55 | + | |
56 | + | |
57 | +def MACD(close, n1, n2, ns): | |
58 | + macd, macdsignal, macdhist = ta.MACD( | |
59 | + close, fastperiod=n1, slowperiod=n2, signalperiod=ns) | |
60 | + return macd, macdsignal | |
61 | + | |
62 | + | |
63 | +# 下記記事を参考にStrategyを修正 | |
64 | +# https://mmorley.hatenablog.com/entry/fx_backtesting01 | |
65 | + | |
66 | +class MACDCross(Strategy): | |
67 | + n1 = 12 # 短期EMAの期間 | |
68 | + n2 = 26 # 長期EMAの期間 | |
69 | + ns = 9 # シグナル(MACDのSMA)の期間 | |
70 | + | |
71 | + def init(self): | |
72 | + self.macd, self.macdsignal = self.I( | |
73 | + MACD, self.data.Close, self.n1, self.n2, self.ns) | |
74 | + | |
75 | + # チャートデータの行ごとに呼び出される | |
76 | + def next(self): | |
77 | + # macdがsignalを上回った時 | |
78 | + if crossover(self.macd, self.macdsignal): | |
79 | + # positionがあるなら決済する | |
80 | + if self.position: | |
81 | + self.position.close() | |
82 | + # 買いオーダー | |
83 | + self.buy() | |
84 | + | |
85 | + # signalがmacdを上回った時 | |
86 | + elif crossover(self.macdsignal, self.macd): | |
87 | + # positionがあるなら決済する | |
88 | + if self.position: | |
89 | + self.position.close() | |
90 | + # 売りオーダー | |
91 | + self.sell() | |
92 | + | |
93 | + | |
94 | +# バックテストを設定 | |
95 | +bt = Backtest( | |
96 | + data, # チャートデータ | |
97 | + MACDCross, # 売買戦略 | |
98 | + # 最初の所持金 | |
99 | + cash=10000, | |
100 | + # 取引手数料 | |
101 | + commission=0.00495, | |
102 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
103 | + margin=1.0, | |
104 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
105 | + trade_on_close=True, | |
106 | + # 自動でポジションをクローズ(オープン) | |
107 | + exclusive_orders=True | |
108 | +) | |
109 | + | |
110 | + | |
111 | +s_time = time.perf_counter() | |
112 | +# バックテスト実行 | |
113 | +output = bt.run() | |
114 | +e_time = time.perf_counter() | |
115 | +# 経過時間を出力(秒) | |
116 | +p_time = round((e_time - s_time), 3) | |
117 | +print(f'Processing time: {p_time}') | |
118 | + | |
119 | +# 実行結果(データ) | |
120 | +print(output) | |
121 | + | |
122 | +# 悲惨な結果 | |
123 | +# >>> print(output) | |
124 | +# Start 2022-10-04 03:57:00 | |
125 | +# End 2022-12-30 23:54:00 | |
126 | +# Duration 87 days 19:57:00 | |
127 | +# Exposure Time [%] 1.984646 | |
128 | +# Equity Final [$] 12.377452 | |
129 | +# Equity Peak [$] 10000.0 | |
130 | +# Return [%] -99.876225 | |
131 | +# Buy & Hold Return [%] -9.405472 | |
132 | +# Return (Ann.) [%] -99.91742 | |
133 | +# Volatility (Ann.) [%] 0.326292 | |
134 | +# Sharpe Ratio 0.0 | |
135 | +# Sortino Ratio 0.0 | |
136 | +# Calmar Ratio 0.0 | |
137 | +# Max. Drawdown [%] -99.876225 | |
138 | +# Avg. Drawdown [%] -99.876225 | |
139 | +# Max. Drawdown Duration 87 days 19:17:00 | |
140 | +# Avg. Drawdown Duration 87 days 19:17:00 | |
141 | +# # Trades 145 | |
142 | +# Win Rate [%] 0.0 | |
143 | +# Best Trade [%] -0.214864 | |
144 | +# Worst Trade [%] -0.689839 | |
145 | +# Avg. Trade [%] -0.490869 | |
146 | +# Max. Trade Duration 0 days 00:48:00 | |
147 | +# Avg. Trade Duration 0 days 00:13:00 | |
148 | +# Profit Factor 0.0 | |
149 | +# Expectancy [%] -0.490853 | |
150 | +# SQN -7.314609 | |
151 | +# _strategy MACDCross | |
152 | +# _equity_curve ... | |
153 | +# _trades Size Entry... | |
154 | +# dtype: object | |
155 | + | |
156 | +# 実行結果(グラフ) | |
157 | +bt.plot() | |
158 | + | |
159 | +# 最適化 | |
160 | +# output2 = bt.optimize( | |
161 | +# n1=range(2, 100, 1), | |
162 | +# n2=range(2, 300, 1), | |
163 | +# ns=range(2, 50, 1), | |
164 | +# maximize='Equity Final [$]', | |
165 | +# method='grid' | |
166 | +# ) | |
167 | +s_time = time.perf_counter() | |
168 | +output2 = bt.optimize( | |
169 | + n1=range(10, 100, 10), | |
170 | + n2=range(10, 300, 10), | |
171 | + ns=range(10, 50, 5), | |
172 | + maximize='Equity Final [$]', | |
173 | + method='grid' | |
174 | +) | |
175 | +e_time = time.perf_counter() | |
176 | + | |
177 | +# 経過時間を出力(秒) | |
178 | +p_time = round((e_time - s_time), 3) | |
179 | +print(f'Processing time: {p_time}') | |
180 | + | |
181 | +print(output2) | |
182 | + | |
183 | +# Processing time: 2554.244 | |
184 | +# >>> output2 | |
185 | +# Start 2022-10-04 03:57:00 | |
186 | +# End 2022-12-30 23:54:00 | |
187 | +# Duration 87 days 19:57:00 | |
188 | +# Exposure Time [%] 7.207517 | |
189 | +# Equity Final [$] 13.095701 | |
190 | +# Equity Peak [$] 10000.0 | |
191 | +# Return [%] -99.869043 | |
192 | +# Buy & Hold Return [%] -9.405472 | |
193 | +# Return (Ann.) [%] -100.0 | |
194 | +# Volatility (Ann.) [%] 0.000001 | |
195 | +# Sharpe Ratio 0.0 | |
196 | +# Sortino Ratio 0.0 | |
197 | +# Calmar Ratio 0.0 | |
198 | +# Max. Drawdown [%] -99.869573 | |
199 | +# Avg. Drawdown [%] -99.869573 | |
200 | +# Max. Drawdown Duration 87 days 14:24:00 | |
201 | +# Avg. Drawdown Duration 87 days 14:24:00 | |
202 | +# # Trades 140 | |
203 | +# Win Rate [%] 0.0 | |
204 | +# Best Trade [%] -0.253867 | |
205 | +# Worst Trade [%] -0.659086 | |
206 | +# Avg. Trade [%] -0.502208 | |
207 | +# Max. Trade Duration 2 days 02:16:00 | |
208 | +# Avg. Trade Duration 0 days 01:08:00 | |
209 | +# Profit Factor 0.0 | |
210 | +# Expectancy [%] -0.502191 | |
211 | +# SQN -7.369103 | |
212 | +# _strategy MACDCross(n1=30,... | |
213 | +# _equity_curve ... | |
214 | +# _trades Size Entry... | |
215 | +# dtype: object | |
216 | + | |
217 | +# 一週間分の1分足件数 | |
218 | +w1 = 7 * 24 * 60 | |
219 | +one_week = data[-w1:] | |
220 | + | |
221 | +# バックテストを設定 | |
222 | +bt = Backtest( | |
223 | + one_week, # チャートデータ | |
224 | + MACDCross, # 売買戦略 | |
225 | + # 最初の所持金 | |
226 | + cash=10000, | |
227 | + # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円) | |
228 | + # OANDAの場合0.3〜0.9銭=0.003~0.009円 | |
229 | + commission=0.00009, | |
230 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
231 | + margin=1.0, | |
232 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
233 | + trade_on_close=True, | |
234 | + # 自動でポジションをクローズ(オープン) | |
235 | + exclusive_orders=True | |
236 | +) | |
237 | + | |
238 | +s_time = time.perf_counter() | |
239 | +# バックテスト実行 | |
240 | +output3 = bt.run() | |
241 | +e_time = time.perf_counter() | |
242 | +# 経過時間を出力(秒) | |
243 | +p_time = round((e_time - s_time), 3) | |
244 | +print(f'Processing time: {p_time}') | |
245 | +print(output3) | |
246 | + | |
247 | +# 手数料(spread)を見直して再テスト、決して悪くない | |
248 | +# Processing time: 0.249 | |
249 | +# Start 2022-12-20 23:24:00 | |
250 | +# End 2022-12-30 23:54:00 | |
251 | +# Duration 10 days 00:30:00 | |
252 | +# Exposure Time [%] 99.563492 | |
253 | +# Equity Final [$] 9208.140463 | |
254 | +# Equity Peak [$] 10025.718238 | |
255 | +# Return [%] -7.918595 | |
256 | +# Buy & Hold Return [%] -0.418553 | |
257 | +# Return (Ann.) [%] -92.562689 | |
258 | +# Volatility (Ann.) [%] 0.743469 | |
259 | +# Sharpe Ratio 0.0 | |
260 | +# Sortino Ratio 0.0 | |
261 | +# Calmar Ratio 0.0 | |
262 | +# Max. Drawdown [%] -8.183151 | |
263 | +# Avg. Drawdown [%] -1.233574 | |
264 | +# Max. Drawdown Duration 9 days 21:31:00 | |
265 | +# Avg. Drawdown Duration 1 days 10:14:00 | |
266 | +# Trades 802 | |
267 | +# Win Rate [%] 28.179551 | |
268 | +# Best Trade [%] 0.440687 | |
269 | +# Worst Trade [%] -0.153847 | |
270 | +# Avg. Trade [%] -0.010355 | |
271 | +# Max. Trade Duration 3 days 00:13:00 | |
272 | +# Avg. Trade Duration 0 days 00:18:00 | |
273 | +# Profit Factor 0.613766 | |
274 | +# Expectancy [%] -0.010338 | |
275 | +# SQN -5.064877 | |
276 | +# _strategy MACDCross | |
277 | +# _equity_curve ... | |
278 | +# _trades Size Entry... | |
279 | +# dtype: object | |
280 | + | |
281 | +s_time = time.perf_counter() | |
282 | +output4 = bt.optimize( | |
283 | + n1=range(10, 100, 10), | |
284 | + n2=range(10, 300, 10), | |
285 | + ns=range(10, 50, 5), | |
286 | + maximize='Equity Final [$]', | |
287 | + method='grid' | |
288 | +) | |
289 | +e_time = time.perf_counter() | |
290 | + | |
291 | +# 経過時間を出力(秒) | |
292 | +p_time = round((e_time - s_time), 3) | |
293 | +print(f'Processing time: {p_time}') | |
294 | + | |
295 | +print(output4) | |
296 | +# 最適化した所、収支+に変わった | |
297 | +# Processing time: 398.75 | |
298 | +# Start 2022-12-20 23:24:00 | |
299 | +# End 2022-12-30 23:54:00 | |
300 | +# Duration 10 days 00:30:00 | |
301 | +# Exposure Time [%] 96.795635 | |
302 | +# Equity Final [$] 10154.142206 | |
303 | +# Equity Peak [$] 10166.385206 | |
304 | +# Return [%] 1.541422 | |
305 | +# Buy & Hold Return [%] -0.418553 | |
306 | +# Return (Ann.) [%] 61.905686 | |
307 | +# Volatility (Ann.) [%] 23.791446 | |
308 | +# Sharpe Ratio 2.602014 | |
309 | +# Sortino Ratio 9.281665 | |
310 | +# Calmar Ratio 26.552283 | |
311 | +# Max. Drawdown [%] -2.331464 | |
312 | +# Avg. Drawdown [%] -0.146011 | |
313 | +# Max. Drawdown Duration 8 days 11:53:00 | |
314 | +# Avg. Drawdown Duration 0 days 05:44:00 | |
315 | +# Trades 212 | |
316 | +# Win Rate [%] 32.54717 | |
317 | +# Best Trade [%] 0.802108 | |
318 | +# Worst Trade [%] -0.206393 | |
319 | +# Avg. Trade [%] 0.007255 | |
320 | +# Max. Trade Duration 3 days 00:22:00 | |
321 | +# Avg. Trade Duration 0 days 01:07:00 | |
322 | +# Profit Factor 1.233927 | |
323 | +# Expectancy [%] 0.007317 | |
324 | +# SQN 0.961529 | |
325 | +# _strategy MACDCross(n1=70,... | |
326 | +# _equity_curve ... | |
327 | +# _trades Size Entry... | |
328 | +# dtype: object | |
329 | +# >>> output4._strategy | |
330 | +# <Strategy MACDCross(n1=70,n2=270,ns=10)> | |
331 | + | |
332 | +# もう少し細やかに最適化とSQN追及するとどーなる? | |
333 | +s_time = time.perf_counter() | |
334 | +output5 = bt.optimize( | |
335 | + n1=range(2, 100, 4), | |
336 | + n2=range(2, 300, 4), | |
337 | + ns=range(2, 50, 2), | |
338 | + maximize='SQN', | |
339 | + method='grid' | |
340 | +) | |
341 | +e_time = time.perf_counter() | |
342 | +# 経過時間を出力(秒) | |
343 | +p_time = round((e_time - s_time), 3) | |
344 | +print(f'Processing time: {p_time}') | |
345 | + | |
346 | +print(output5) | |
347 | +# UserWarning: Searching for best of 45000 configurations. | |
348 | +# Processing time: 9053.424 | |
349 | +# Start 2022-12-20 23:24:00 | |
350 | +# End 2022-12-30 23:54:00 | |
351 | +# Duration 10 days 00:30:00 | |
352 | +# Exposure Time [%] 97.668651 | |
353 | +# Equity Final [$] 10185.183082 | |
354 | +# Equity Peak [$] 10197.426082 | |
355 | +# Return [%] 1.851831 | |
356 | +# Buy & Hold Return [%] -0.418553 | |
357 | +# Return (Ann.) [%] 78.245453 | |
358 | +# Volatility (Ann.) [%] 23.784343 | |
359 | +# Sharpe Ratio 3.289788 | |
360 | +# Sortino Ratio 14.517367 | |
361 | +# Calmar Ratio 37.341789 | |
362 | +# Max. Drawdown [%] -2.095386 | |
363 | +# Avg. Drawdown [%] -0.156905 | |
364 | +# Max. Drawdown Duration 8 days 07:09:00 | |
365 | +# Avg. Drawdown Duration 0 days 06:23:00 | |
366 | +# Trades 214 | |
367 | +# Win Rate [%] 31.308411 | |
368 | +# Best Trade [%] 0.810285 | |
369 | +# Worst Trade [%] -0.182724 | |
370 | +# Avg. Trade [%] 0.00861 | |
371 | +# Max. Trade Duration 3 days 00:24:00 | |
372 | +# Avg. Trade Duration 0 days 01:07:00 | |
373 | +# Profit Factor 1.287511 | |
374 | +# Expectancy [%] 0.008672 | |
375 | +# SQN 1.145089 | |
376 | +# _strategy MACDCross(n1=98,... | |
377 | +# _equity_curve ... | |
378 | +# _trades Size Entry... | |
379 | +# dtype: object | |
380 | +# >>> output5._strategy | |
381 | +# <Strategy MACDCross(n1=98,n2=218,ns=8)> |
@@ -0,0 +1,851 @@ | ||
1 | +# 元ネタ | |
2 | +# https://qiita.com/Fujinoinvestor/items/780b138e441531860e60 | |
3 | + | |
4 | +# データcsvはmt5から取得している | |
5 | +# M1_1の続き | |
6 | +# Strategyを変更してst,tpを付けてみる | |
7 | +# tp(take profit)利確する価格 | |
8 | +# sl(stop losst)損切りする価格 | |
9 | + | |
10 | +import os | |
11 | +import talib as ta | |
12 | +from backtesting.lib import crossover | |
13 | +from backtesting import Backtest | |
14 | +from backtesting import Strategy | |
15 | +import pandas as pd | |
16 | +import time | |
17 | + | |
18 | +# 現在ディレクトリ取得 | |
19 | +cwd = os.getcwd() | |
20 | + | |
21 | +# get data | |
22 | +data_path = os.path.join( | |
23 | + cwd, | |
24 | + 'csv', | |
25 | + 'USDJPY_M1_202210040357_202212302354.csv' | |
26 | +) | |
27 | + | |
28 | +# csvがtab区切りなのでreat_tableを使う | |
29 | +df = pd.read_table( | |
30 | + data_path | |
31 | +) | |
32 | + | |
33 | +# DataFrameのカラム名をbacktesting向けに修正 | |
34 | +df = df.rename( | |
35 | + columns={ | |
36 | + "<DATE>": "Date", | |
37 | + "<TIME>": "Time", | |
38 | + "<OPEN>": "Open", | |
39 | + "<HIGH>": "High", | |
40 | + "<LOW>": "Low", | |
41 | + "<CLOSE>": "Close", | |
42 | + "<TICKVOL>": "Volume", | |
43 | + "<VOL>": "not_use", | |
44 | + "<SPREAD>": "Spread", | |
45 | + } | |
46 | +) | |
47 | + | |
48 | +# 日付に時間文字列を結合 | |
49 | +df.Date = df['Date'] + ' ' + df['Time'] | |
50 | + | |
51 | +# Dateカラムをdatetime型に変換 | |
52 | +df.Date = pd.to_datetime(df['Date'], format='%Y.%m.%d %H:%M:%S') | |
53 | + | |
54 | +# indexをDateカラムに設定 | |
55 | +df = df.set_index('Date') | |
56 | + | |
57 | +# 必要なカラムのみ取得 | |
58 | +data = df.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']] | |
59 | + | |
60 | +# 一週間分の1分足件数 | |
61 | +w1 = 7 * 24 * 60 | |
62 | +one_week = data[-w1:] | |
63 | + | |
64 | + | |
65 | +def MACD(close, n1, n2, ns): | |
66 | + macd, macdsignal, macdhist = ta.MACD( | |
67 | + close, fastperiod=n1, slowperiod=n2, signalperiod=ns) | |
68 | + return macd, macdsignal | |
69 | + | |
70 | + | |
71 | +# 下記記事を参考にStrategyを修正 | |
72 | +# https://mmorley.hatenablog.com/entry/fx_backtesting01 | |
73 | + | |
74 | +class MACDCross(Strategy): | |
75 | + n1 = 12 # 短期EMAの期間 | |
76 | + n2 = 26 # 長期EMAの期間 | |
77 | + ns = 9 # シグナル(MACDのSMA)の期間 | |
78 | + | |
79 | + def init(self): | |
80 | + self.macd, self.macdsignal = self.I( | |
81 | + MACD, self.data.Close, self.n1, self.n2, self.ns) | |
82 | + | |
83 | + # チャートデータの行ごとに呼び出される | |
84 | + # tp(take profit)利確する価格 | |
85 | + # sl(stop losst)損切りする価格 | |
86 | + def next(self): | |
87 | + # macdがsignalを上回った時 | |
88 | + if crossover(self.macd, self.macdsignal): | |
89 | + # 買いオーダー | |
90 | + self.buy( | |
91 | + tp=self.data.Close[-1] + 0.5, | |
92 | + sl=self.data.Close[-1] - 0.1 | |
93 | + ) | |
94 | + | |
95 | + # signalがmacdを上回った時 | |
96 | + elif crossover(self.macdsignal, self.macd): | |
97 | + # 売りオーダー | |
98 | + self.sell( | |
99 | + tp=self.data.Close[-1] - 0.5, | |
100 | + sl=self.data.Close[-1] + 0.1 | |
101 | + ) | |
102 | + | |
103 | + | |
104 | +# バックテストを設定 | |
105 | +bt = Backtest( | |
106 | + one_week, # チャートデータ | |
107 | + MACDCross, # 売買戦略 | |
108 | + # 最初の所持金 | |
109 | + cash=10000, | |
110 | + # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円) | |
111 | + # OANDAの場合0.3〜0.9銭=0.003~0.009円 | |
112 | + commission=0.00009, | |
113 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
114 | + margin=1.0, | |
115 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
116 | + trade_on_close=True, | |
117 | + # 自動でポジションをクローズ(オープン) | |
118 | + exclusive_orders=True | |
119 | +) | |
120 | + | |
121 | +s_time = time.perf_counter() | |
122 | +# バックテスト実行 | |
123 | +output = bt.run() | |
124 | +e_time = time.perf_counter() | |
125 | +# 経過時間を出力(秒) | |
126 | +p_time = round((e_time - s_time), 3) | |
127 | +print(f'Processing time: {p_time}') | |
128 | + | |
129 | +# 実行結果(データ) | |
130 | +print(output) | |
131 | + | |
132 | +# Processing time: 0.289 | |
133 | +# Start 2022-12-20 23:24:00 | |
134 | +# End 2022-12-30 23:54:00 | |
135 | +# Duration 10 days 00:30:00 | |
136 | +# Exposure Time [%] 97.35119 | |
137 | +# Equity Final [$] 9174.553578 | |
138 | +# Equity Peak [$] 10021.818238 | |
139 | +# Return [%] -8.254464 | |
140 | +# Buy & Hold Return [%] -0.418553 | |
141 | +# Return (Ann.) [%] -93.371341 | |
142 | +# Volatility (Ann.) [%] 0.808312 | |
143 | +# Sharpe Ratio 0.0 | |
144 | +# Sortino Ratio 0.0 | |
145 | +# Calmar Ratio 0.0 | |
146 | +# Max. Drawdown [%] -8.600758 | |
147 | +# Avg. Drawdown [%] -1.495578 | |
148 | +# Max. Drawdown Duration 9 days 21:31:00 | |
149 | +# Avg. Drawdown Duration 1 days 15:56:00 | |
150 | +# Trades 802 | |
151 | +# Win Rate [%] 27.680798 | |
152 | +# Best Trade [%] 0.37054 | |
153 | +# Worst Trade [%] -0.085361 | |
154 | +# Avg. Trade [%] -0.010813 | |
155 | +# Max. Trade Duration 3 days 00:13:00 | |
156 | +# Avg. Trade Duration 0 days 00:18:00 | |
157 | +# Profit Factor 0.599995 | |
158 | +# Expectancy [%] -0.010797 | |
159 | +# SQN -5.341178 | |
160 | +# _strategy MACDCross | |
161 | +# _equity_curve ... | |
162 | +# _trades Size Entry... | |
163 | +# dtype: object | |
164 | + | |
165 | +# 最適解を求める | |
166 | +s_time = time.perf_counter() | |
167 | +output2 = bt.optimize( | |
168 | + n1=range(10, 100, 10), | |
169 | + n2=range(10, 250, 10), | |
170 | + ns=range(10, 50, 5), | |
171 | + maximize='Equity Final [$]', | |
172 | + method='grid' | |
173 | +) | |
174 | +e_time = time.perf_counter() | |
175 | +# 経過時間を出力(秒) | |
176 | +p_time = round((e_time - s_time), 3) | |
177 | +print(f'Processing time: {p_time}') | |
178 | +print(output2) | |
179 | + | |
180 | +# 悪くない数字 | |
181 | +# UserWarning: Searching for best of 1728 configurations. | |
182 | +# Processing time: 368.784 | |
183 | +# Start 2022-12-20 23:24:00 | |
184 | +# End 2022-12-30 23:54:00 | |
185 | +# Duration 10 days 00:30:00 | |
186 | +# Exposure Time [%] 81.795635 | |
187 | +# Equity Final [$] 10174.973572 | |
188 | +# Equity Peak [$] 10187.216572 | |
189 | +# Return [%] 1.749736 | |
190 | +# Buy & Hold Return [%] -0.418553 | |
191 | +# Return (Ann.) [%] 72.702503 | |
192 | +# Volatility (Ann.) [%] 19.228445 | |
193 | +# Sharpe Ratio 3.780987 | |
194 | +# Sortino Ratio 13.703438 | |
195 | +# Calmar Ratio 38.644871 | |
196 | +# Max. Drawdown [%] -1.881298 | |
197 | +# Avg. Drawdown [%] -0.104378 | |
198 | +# Max. Drawdown Duration 7 days 17:11:00 | |
199 | +# Avg. Drawdown Duration 0 days 04:33:00 | |
200 | +# # Trades 131 | |
201 | +# Win Rate [%] 38.167939 | |
202 | +# Best Trade [%] 0.370318 | |
203 | +# Worst Trade [%] -0.08493 | |
204 | +# Avg. Trade [%] 0.013319 | |
205 | +# Max. Trade Duration 3 days 02:25:00 | |
206 | +# Avg. Trade Duration 0 days 01:36:00 | |
207 | +# Profit Factor 1.372048 | |
208 | +# Expectancy [%] 0.013395 | |
209 | +# SQN 1.234211 | |
210 | +# _strategy MACDCross(n1=60,... | |
211 | +# _equity_curve ... | |
212 | +# _trades Size Entry... | |
213 | +# dtype: object | |
214 | +# <Strategy MACDCross(n1=60,n2=160,ns=45)> | |
215 | + | |
216 | +# Tradesを最大化してみると | |
217 | +s_time = time.perf_counter() | |
218 | +output3 = bt.optimize( | |
219 | + n1=range(10, 100, 10), | |
220 | + n2=range(10, 250, 10), | |
221 | + ns=range(10, 50, 5), | |
222 | + maximize='# Trades', | |
223 | + method='grid' | |
224 | +) | |
225 | +e_time = time.perf_counter() | |
226 | +# 経過時間を出力(秒) | |
227 | +p_time = round((e_time - s_time), 3) | |
228 | +print(f'Processing time: {p_time}') | |
229 | +print(output3) | |
230 | + | |
231 | +# あまり良くない | |
232 | +# Start 2022-12-20 23:24:00 | |
233 | +# End 2022-12-30 23:54:00 | |
234 | +# Duration 10 days 00:30:00 | |
235 | +# Exposure Time [%] 97.519841 | |
236 | +# Equity Final [$] 9068.847457 | |
237 | +# Equity Peak [$] 10023.33473 | |
238 | +# Return [%] -9.311525 | |
239 | +# Buy & Hold Return [%] -0.418553 | |
240 | +# Return (Ann.) [%] -95.398589 | |
241 | +# Volatility (Ann.) [%] 0.578335 | |
242 | +# Sharpe Ratio 0.0 | |
243 | +# Sortino Ratio 0.0 | |
244 | +# Calmar Ratio 0.0 | |
245 | +# Max. Drawdown [%] -9.574552 | |
246 | +# Avg. Drawdown [%] -1.97134 | |
247 | +# Max. Drawdown Duration 9 days 21:50:00 | |
248 | +# Avg. Drawdown Duration 1 days 23:56:00 | |
249 | +# # Trades 872 | |
250 | +# Win Rate [%] 27.752294 | |
251 | +# Best Trade [%] 0.37054 | |
252 | +# Worst Trade [%] -0.085343 | |
253 | +# Avg. Trade [%] -0.011288 | |
254 | +# Max. Trade Duration 3 days 00:16:00 | |
255 | +# Avg. Trade Duration 0 days 00:17:00 | |
256 | +# Profit Factor 0.573113 | |
257 | +# Expectancy [%] -0.011273 | |
258 | +# SQN -6.07133 | |
259 | +# _strategy MACDCross(n1=10,... | |
260 | +# _equity_curve ... | |
261 | +# _trades Size Entry... | |
262 | +# dtype: object | |
263 | + | |
264 | +# SQNを最大化してみると | |
265 | +s_time = time.perf_counter() | |
266 | +output4 = bt.optimize( | |
267 | + n1=range(10, 100, 10), | |
268 | + n2=range(10, 250, 10), | |
269 | + ns=range(10, 50, 5), | |
270 | + maximize='SQN', | |
271 | + method='grid' | |
272 | +) | |
273 | +e_time = time.perf_counter() | |
274 | +# 経過時間を出力(秒) | |
275 | +p_time = round((e_time - s_time), 3) | |
276 | +print(f'Processing time: {p_time}') | |
277 | +print(output4) | |
278 | + | |
279 | +# Start 2022-12-20 23:24:00 | |
280 | +# End 2022-12-30 23:54:00 | |
281 | +# Duration 10 days 00:30:00 | |
282 | +# Exposure Time [%] 81.795635 | |
283 | +# Equity Final [$] 10174.973572 | |
284 | +# Equity Peak [$] 10187.216572 | |
285 | +# Return [%] 1.749736 | |
286 | +# Buy & Hold Return [%] -0.418553 | |
287 | +# Return (Ann.) [%] 72.702503 | |
288 | +# Volatility (Ann.) [%] 19.228445 | |
289 | +# Sharpe Ratio 3.780987 | |
290 | +# Sortino Ratio 13.703438 | |
291 | +# Calmar Ratio 38.644871 | |
292 | +# Max. Drawdown [%] -1.881298 | |
293 | +# Avg. Drawdown [%] -0.104378 | |
294 | +# Max. Drawdown Duration 7 days 17:11:00 | |
295 | +# Avg. Drawdown Duration 0 days 04:33:00 | |
296 | +# # Trades 131 | |
297 | +# Win Rate [%] 38.167939 | |
298 | +# Best Trade [%] 0.370318 | |
299 | +# Worst Trade [%] -0.08493 | |
300 | +# Avg. Trade [%] 0.013319 | |
301 | +# Max. Trade Duration 3 days 02:25:00 | |
302 | +# Avg. Trade Duration 0 days 01:36:00 | |
303 | +# Profit Factor 1.372048 | |
304 | +# Expectancy [%] 0.013395 | |
305 | +# SQN 1.234211 | |
306 | +# _strategy MACDCross(n1=60,... | |
307 | +# _equity_curve ... | |
308 | +# _trades Size Entry... | |
309 | +# dtype: object | |
310 | +# <Strategy MACDCross(n1=60,n2=160,ns=45)> | |
311 | + | |
312 | +# もっとStepを小さくしてSQNを最大化してみると | |
313 | +s_time = time.perf_counter() | |
314 | +output5 = bt.optimize( | |
315 | + n1=range(50, 75, 1), | |
316 | + n2=range(140, 160, 1), | |
317 | + ns=range(40, 50, 1), | |
318 | + maximize='SQN', | |
319 | + method='grid' | |
320 | +) | |
321 | +e_time = time.perf_counter() | |
322 | +# 経過時間を出力(秒) | |
323 | +p_time = round((e_time - s_time), 3) | |
324 | +print(f'Processing time: {p_time}') | |
325 | +print(output5) | |
326 | + | |
327 | +# だいぶ良い数字になった | |
328 | +# UserWarning: Searching for best of 5000 configurations. | |
329 | +# Processing time: 1009.649 | |
330 | +# Start 2022-12-20 23:24:00 | |
331 | +# End 2022-12-30 23:54:00 | |
332 | +# Duration 10 days 00:30:00 | |
333 | +# Exposure Time [%] 78.958333 | |
334 | +# Equity Final [$] 10214.662583 | |
335 | +# Equity Peak [$] 10226.905583 | |
336 | +# Return [%] 2.146626 | |
337 | +# Buy & Hold Return [%] -0.418553 | |
338 | +# Return (Ann.) [%] 95.234605 | |
339 | +# Volatility (Ann.) [%] 23.585584 | |
340 | +# Sharpe Ratio 4.037831 | |
341 | +# Sortino Ratio 19.202462 | |
342 | +# Calmar Ratio 53.851618 | |
343 | +# Max. Drawdown [%] -1.768463 | |
344 | +# Avg. Drawdown [%] -0.087079 | |
345 | +# Max. Drawdown Duration 6 days 20:34:00 | |
346 | +# Avg. Drawdown Duration 0 days 03:26:00 | |
347 | +# # Trades 125 | |
348 | +# Win Rate [%] 38.4 | |
349 | +# Best Trade [%] 0.370318 | |
350 | +# Worst Trade [%] -0.08493 | |
351 | +# Avg. Trade [%] 0.017169 | |
352 | +# Max. Trade Duration 3 days 02:25:00 | |
353 | +# Avg. Trade Duration 0 days 01:39:00 | |
354 | +# Profit Factor 1.484438 | |
355 | +# Expectancy [%] 0.017252 | |
356 | +# SQN 1.493431 | |
357 | +# _strategy MACDCross(n1=62,... | |
358 | +# _equity_curve ... | |
359 | +# _trades Size Entry... | |
360 | +# dtype: object | |
361 | +# <Strategy MACDCross(n1=62,n2=150,ns=47)> | |
362 | + | |
363 | +# 上記の設定で全件データを検証してみる | |
364 | + | |
365 | + | |
366 | +class MACDCross2(Strategy): | |
367 | + n1 = 62 # 短期EMAの期間 | |
368 | + n2 = 150 # 長期EMAの期間 | |
369 | + ns = 47 # シグナル(MACDのSMA)の期間 | |
370 | + | |
371 | + def init(self): | |
372 | + self.macd, self.macdsignal = self.I( | |
373 | + MACD, self.data.Close, self.n1, self.n2, self.ns) | |
374 | + | |
375 | + # チャートデータの行ごとに呼び出される | |
376 | + # tp(take profit)利確する価格 | |
377 | + # sl(stop losst)損切りする価格 | |
378 | + def next(self): | |
379 | + # macdがsignalを上回った時 | |
380 | + if crossover(self.macd, self.macdsignal): | |
381 | + # 買いオーダー | |
382 | + self.buy( | |
383 | + tp=self.data.Close[-1] + 0.5, | |
384 | + sl=self.data.Close[-1] - 0.1 | |
385 | + ) | |
386 | + | |
387 | + # signalがmacdを上回った時 | |
388 | + elif crossover(self.macdsignal, self.macd): | |
389 | + # 売りオーダー | |
390 | + self.sell( | |
391 | + tp=self.data.Close[-1] - 0.5, | |
392 | + sl=self.data.Close[-1] + 0.1 | |
393 | + ) | |
394 | + | |
395 | + | |
396 | +# バックテストを設定 | |
397 | +bt2 = Backtest( | |
398 | + data, # チャートデータ | |
399 | + MACDCross2, # 売買戦略 | |
400 | + # 最初の所持金 | |
401 | + cash=10000, | |
402 | + # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円) | |
403 | + # OANDAの場合0.3〜0.9銭=0.003~0.009円 | |
404 | + commission=0.00009, | |
405 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
406 | + margin=1.0, | |
407 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
408 | + trade_on_close=True, | |
409 | + # 自動でポジションをクローズ(オープン) | |
410 | + exclusive_orders=True | |
411 | +) | |
412 | + | |
413 | +s_time = time.perf_counter() | |
414 | +# バックテスト実行 | |
415 | +output6 = bt2.run() | |
416 | +e_time = time.perf_counter() | |
417 | +# 経過時間を出力(秒) | |
418 | +p_time = round((e_time - s_time), 3) | |
419 | +print(f'Processing time: {p_time}') | |
420 | + | |
421 | +# 実行結果(データ) | |
422 | +print(output6) | |
423 | + | |
424 | +# 1週間分のデータから設定したMACDで | |
425 | +# 1年分のデータを対象に戦略を立てることは難しい | |
426 | +# DeepLearningと同様にTraning,Testにデータを分けて | |
427 | +# 検証するのが正だと思う | |
428 | + | |
429 | +# Processing time: 1.582 | |
430 | +# Start 2022-10-04 03:57:00 | |
431 | +# End 2022-12-30 23:54:00 | |
432 | +# Duration 87 days 19:57:00 | |
433 | +# Exposure Time [%] 72.96044 | |
434 | +# Equity Final [$] 9778.203995 | |
435 | +# Equity Peak [$] 10053.368246 | |
436 | +# Return [%] -2.21796 | |
437 | +# Buy & Hold Return [%] -9.405472 | |
438 | +# Return (Ann.) [%] -7.465731 | |
439 | +# Volatility (Ann.) [%] 8.548688 | |
440 | +# Sharpe Ratio 0.0 | |
441 | +# Sortino Ratio 0.0 | |
442 | +# Calmar Ratio 0.0 | |
443 | +# Max. Drawdown [%] -6.357778 | |
444 | +# Avg. Drawdown [%] -0.444463 | |
445 | +# Max. Drawdown Duration 86 days 13:05:00 | |
446 | +# Avg. Drawdown Duration 5 days 03:41:00 | |
447 | +# # Trades 1267 | |
448 | +# Win Rate [%] 28.887135 | |
449 | +# Best Trade [%] 0.372445 | |
450 | +# Worst Trade [%] -0.084972 | |
451 | +# Avg. Trade [%] -0.001786 | |
452 | +# Max. Trade Duration 3 days 02:25:00 | |
453 | +# Avg. Trade Duration 0 days 01:14:00 | |
454 | +# Profit Factor 0.95921 | |
455 | +# Expectancy [%] -0.001717 | |
456 | +# SQN -0.550378 | |
457 | +# _strategy MACDCross2 | |
458 | +# _equity_curve ... | |
459 | +# _trades Size Entr... | |
460 | +# dtype: object | |
461 | + | |
462 | +# 最後に | |
463 | +# 自動でポジションをクローズ(オープン) | |
464 | +# exclusive_orders=True | |
465 | +# こちらのオプションを外して検証 | |
466 | + | |
467 | + | |
468 | +class MACDCross3(Strategy): | |
469 | + n1 = 12 # 短期EMAの期間 | |
470 | + n2 = 26 # 長期EMAの期間 | |
471 | + ns = 9 # シグナル(MACDのSMA)の期間 | |
472 | + | |
473 | + def init(self): | |
474 | + self.macd, self.macdsignal = self.I( | |
475 | + MACD, self.data.Close, self.n1, self.n2, self.ns) | |
476 | + | |
477 | + # チャートデータの行ごとに呼び出される | |
478 | + # tp(take profit)利確する価格 | |
479 | + # sl(stop losst)損切りする価格 | |
480 | + def next(self): | |
481 | + # macdがsignalを上回った時 | |
482 | + if crossover(self.macd, self.macdsignal): | |
483 | + # 買いオーダー | |
484 | + self.buy( | |
485 | + tp=self.data.Close[-1] + 0.5, | |
486 | + sl=self.data.Close[-1] - 0.1 | |
487 | + ) | |
488 | + | |
489 | + # signalがmacdを上回った時 | |
490 | + elif crossover(self.macdsignal, self.macd): | |
491 | + # 売りオーダー | |
492 | + self.sell( | |
493 | + tp=self.data.Close[-1] - 0.5, | |
494 | + sl=self.data.Close[-1] + 0.1 | |
495 | + ) | |
496 | + | |
497 | + | |
498 | +# バックテストを設定 | |
499 | +bt3 = Backtest( | |
500 | + one_week, # チャートデータ | |
501 | + MACDCross3, # 売買戦略 | |
502 | + # 最初の所持金 | |
503 | + cash=10000, | |
504 | + # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円) | |
505 | + # OANDAの場合0.3〜0.9銭=0.003~0.009円 | |
506 | + commission=0.00009, | |
507 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
508 | + margin=1.0, | |
509 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
510 | + trade_on_close=True | |
511 | +) | |
512 | + | |
513 | +s_time = time.perf_counter() | |
514 | +# バックテスト実行 | |
515 | +output7 = bt3.run() | |
516 | +e_time = time.perf_counter() | |
517 | +# 経過時間を出力(秒) | |
518 | +p_time = round((e_time - s_time), 3) | |
519 | +print(f'Processing time: {p_time}') | |
520 | + | |
521 | +# 実行結果(データ) | |
522 | +print(output7) | |
523 | + | |
524 | +# 右がオプション有り、左が無し | |
525 | +# 結果がだいぶ良い | |
526 | +# Start 2022-12-20 23:24:00 Start 2022-12-20 23:24:00 | |
527 | +# End 2022-12-30 23:54:00 End 2022-12-30 23:54:00 | |
528 | +# Duration 10 days 00:30:00 Duration 10 days 00:30:00 | |
529 | +# Exposure Time [%] 94.007937 Exposure Time [%] 97.35119 | |
530 | +# Equity Final [$] 9934.66187 Equity Final [$] 9174.553578 | |
531 | +# Equity Peak [$] 10139.030034 Equity Peak [$] 10021.818238 | |
532 | +# Return [%] -0.653381 Return [%] -8.254464 | |
533 | +# Buy & Hold Return [%] -0.418553 Buy & Hold Return [%] -0.418553 | |
534 | +# Return (Ann.) [%] -18.656595 Return (Ann.) [%] -93.371341 | |
535 | +# Volatility (Ann.) [%] 8.928979 Volatility (Ann.) [%] 0.808312 | |
536 | +# Sharpe Ratio 0.0 Sharpe Ratio 0.0 | |
537 | +# Sortino Ratio 0.0 Sortino Ratio 0.0 | |
538 | +# Calmar Ratio 0.0 Calmar Ratio 0.0 | |
539 | +# Max. Drawdown [%] -2.60927 Max. Drawdown [%] -8.600758 | |
540 | +# Avg. Drawdown [%] -0.130574 Avg. Drawdown [%] -1.495578 | |
541 | +# Max. Drawdown Duration 8 days 07:20:00 Max. Drawdown Duration 9 days 21:31:00 | |
542 | +# Avg. Drawdown Duration 0 days 04:41:00 Avg. Drawdown Duration 1 days 15:56:00 | |
543 | +# # Trades 122 Trades 802 | |
544 | +# Win Rate [%] 27.04918 Win Rate [%] 27.680798 | |
545 | +# Best Trade [%] 0.370877 Best Trade [%] 0.37054 | |
546 | +# Worst Trade [%] -0.085433 Worst Trade [%] -0.085361 | |
547 | +# Avg. Trade [%] 0.007262 Avg. Trade [%] -0.010813 | |
548 | +# Max. Trade Duration 3 days 10:21:00 Max. Trade Duration 3 days 00:13:00 | |
549 | +# Avg. Trade Duration 0 days 02:14:00 Avg. Trade Duration 0 days 00:18:00 | |
550 | +# Profit Factor 1.122313 Profit Factor 0.599995 | |
551 | +# Expectancy [%] 0.007399 Expectancy [%] -0.010797 | |
552 | +# SQN -0.41845 SQN -5.341178 | |
553 | +# _strategy MACDCross3 _strategy MACDCross | |
554 | +# _equity_curve ... _equity_curve ... | |
555 | +# _trades Size Entry... _trades Size Entry... | |
556 | + | |
557 | +# では最適化してみると・・・ | |
558 | +s_time = time.perf_counter() | |
559 | +output8 = bt3.optimize( | |
560 | + n1=range(10, 100, 10), | |
561 | + n2=range(10, 250, 10), | |
562 | + ns=range(10, 50, 5), | |
563 | + maximize='SQN', | |
564 | + method='grid' | |
565 | +) | |
566 | +e_time = time.perf_counter() | |
567 | +# 経過時間を出力(秒) | |
568 | +p_time = round((e_time - s_time), 3) | |
569 | +print(f'Processing time: {p_time}') | |
570 | +print(output8) | |
571 | +print(output8._strategy) | |
572 | +# びっくりするほど優秀な数字! | |
573 | +# UserWarning: Searching for best of 1728 configurations. | |
574 | +# Processing time: 368.826 | |
575 | +# Start 2022-12-20 23:24:00 Start 2022-12-20 23:24:00 | |
576 | +# End 2022-12-30 23:54:00 End 2022-12-30 23:54:00 | |
577 | +# Duration 10 days 00:30:00 Duration 10 days 00:30:00 | |
578 | +# Exposure Time [%] 76.041667 Exposure Time [%] 81.795635 | |
579 | +# Equity Final [$] 10304.130005 Equity Final [$] 10174.973572 | |
580 | +# Equity Peak [$] 10316.532005 Equity Peak [$] 10187.216572 | |
581 | +# Return [%] 3.0413 Return [%] 1.749736 | |
582 | +# Buy & Hold Return [%] -0.418553 Buy & Hold Return [%] -0.418553 | |
583 | +# Return (Ann.) [%] 156.954885 Return (Ann.) [%] 72.702503 | |
584 | +# Volatility (Ann.) [%] 22.409417 Volatility (Ann.) [%] 19.228445 | |
585 | +# Sharpe Ratio 7.00397 Sharpe Ratio 3.780987 | |
586 | +# Sortino Ratio 69.09806 Sortino Ratio 13.703438 | |
587 | +# Calmar Ratio 196.606603 Calmar Ratio 38.644871 | |
588 | +# Max. Drawdown [%] -0.798319 Max. Drawdown [%] -1.881298 | |
589 | +# Avg. Drawdown [%] -0.069599 Avg. Drawdown [%] -0.104378 | |
590 | +# Max. Drawdown Duration 6 days 18:15:00 Max. Drawdown Duration 7 days 17:11:00 | |
591 | +# Avg. Drawdown Duration 0 days 02:25:00 Avg. Drawdown Duration 0 days 04:33:00 | |
592 | +# # Trades 42 # Trades 131 | |
593 | +# Win Rate [%] 35.714286 Win Rate [%] 38.167939 | |
594 | +# Best Trade [%] 0.370278 Best Trade [%] 0.370318 | |
595 | +# Worst Trade [%] -0.08493 Worst Trade [%] -0.08493 | |
596 | +# Avg. Trade [%] 0.071801 Avg. Trade [%] 0.013319 | |
597 | +# Max. Trade Duration 3 days 09:35:00 Max. Trade Duration 3 days 02:25:00 | |
598 | +# Avg. Trade Duration 0 days 04:45:00 Avg. Trade Duration 0 days 01:36:00 | |
599 | +# Profit Factor 2.326556 Profit Factor 1.372048 | |
600 | +# Expectancy [%] 0.072026 Expectancy [%] 0.013395 | |
601 | +# SQN 2.180297 SQN 1.234211 | |
602 | +# _strategy MACDCross3(n1=60... _strategy MACDCross(n1=60,... | |
603 | +# _equity_curve ... _equity_curve ... | |
604 | +# _trades Size EntryB... _trades Size Entry... | |
605 | +# MACDCross3(n1=60,n2=170,ns=45) | |
606 | + | |
607 | +# 同様にもう少し細分化して最適化 | |
608 | +s_time = time.perf_counter() | |
609 | +output9 = bt3.optimize( | |
610 | + n1=range(50, 70, 1), | |
611 | + n2=range(160, 180, 1), | |
612 | + ns=range(40, 60, 1), | |
613 | + maximize='SQN', | |
614 | + method='grid' | |
615 | +) | |
616 | +e_time = time.perf_counter() | |
617 | +# 経過時間を出力(秒) | |
618 | +p_time = round((e_time - s_time), 3) | |
619 | +print(f'Processing time: {p_time}') | |
620 | +print(output9) | |
621 | +print(output9._strategy) | |
622 | + | |
623 | +# 成績は良い、全件で検証する | |
624 | +# UserWarning: Searching for best of 8000 configurations. | |
625 | +# Processing time: 1592.988 | |
626 | +# Start 2022-12-20 23:24:00 | |
627 | +# End 2022-12-30 23:54:00 | |
628 | +# Duration 10 days 00:30:00 | |
629 | +# Exposure Time [%] 76.55754 | |
630 | +# Equity Final [$] 10304.55431 | |
631 | +# Equity Peak [$] 10316.95631 | |
632 | +# Return [%] 3.045543 | |
633 | +# Buy & Hold Return [%] -0.418553 | |
634 | +# Return (Ann.) [%] 157.288393 | |
635 | +# Volatility (Ann.) [%] 22.4435 | |
636 | +# Sharpe Ratio 7.008193 | |
637 | +# Sortino Ratio 69.247796 | |
638 | +# Calmar Ratio 196.761091 | |
639 | +# Max. Drawdown [%] -0.799388 | |
640 | +# Avg. Drawdown [%] -0.067546 | |
641 | +# Max. Drawdown Duration 6 days 18:15:00 | |
642 | +# Avg. Drawdown Duration 0 days 02:21:00 | |
643 | +# # Trades 44 | |
644 | +# Win Rate [%] 38.636364 | |
645 | +# Best Trade [%] 0.370278 | |
646 | +# Worst Trade [%] -0.08493 | |
647 | +# Avg. Trade [%] 0.077755 | |
648 | +# Max. Trade Duration 3 days 09:35:00 | |
649 | +# Avg. Trade Duration 0 days 04:37:00 | |
650 | +# Profit Factor 2.504597 | |
651 | +# Expectancy [%] 0.077979 | |
652 | +# SQN 2.181016 | |
653 | +# _strategy MACDCross3(n1=61... | |
654 | +# _equity_curve ... | |
655 | +# _trades Size EntryB... | |
656 | +# dtype: object | |
657 | +# MACDCross3(n1=61,n2=169,ns=44) | |
658 | + | |
659 | + | |
660 | +class MACDCross4(Strategy): | |
661 | + n1 = 61 # 期EMAの期間 | |
662 | + n2 = 169 # 長期EMAの期間 | |
663 | + ns = 44 # シグナル(MACDのSMA)の期間 | |
664 | + | |
665 | + def init(self): | |
666 | + self.macd, self.macdsignal = self.I( | |
667 | + MACD, self.data.Close, self.n1, self.n2, self.ns) | |
668 | + | |
669 | + # チャートデータの行ごとに呼び出される | |
670 | + # tp(take profit)利確する価格 | |
671 | + # sl(stop losst)損切りする価格 | |
672 | + def next(self): | |
673 | + # macdがsignalを上回った時 | |
674 | + if crossover(self.macd, self.macdsignal): | |
675 | + # 買いオーダー | |
676 | + self.buy( | |
677 | + tp=self.data.Close[-1] + 0.5, | |
678 | + sl=self.data.Close[-1] - 0.1 | |
679 | + ) | |
680 | + | |
681 | + # signalがmacdを上回った時 | |
682 | + elif crossover(self.macdsignal, self.macd): | |
683 | + # 売りオーダー | |
684 | + self.sell( | |
685 | + tp=self.data.Close[-1] - 0.5, | |
686 | + sl=self.data.Close[-1] + 0.1 | |
687 | + ) | |
688 | + | |
689 | + | |
690 | +# バックテストを設定 | |
691 | +bt4 = Backtest( | |
692 | + data, # チャートデータ | |
693 | + MACDCross4, # 売買戦略 | |
694 | + # 最初の所持金 | |
695 | + cash=10000, | |
696 | + # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円) | |
697 | + # OANDAの場合0.3〜0.9銭=0.003~0.009円 | |
698 | + commission=0.00009, | |
699 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
700 | + margin=1.0, | |
701 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
702 | + trade_on_close=True | |
703 | +) | |
704 | + | |
705 | +s_time = time.perf_counter() | |
706 | +# バックテスト実行 | |
707 | +output10 = bt4.run() | |
708 | +e_time = time.perf_counter() | |
709 | +# 経過時間を出力(秒) | |
710 | +p_time = round((e_time - s_time), 3) | |
711 | +print(f'Processing time: {p_time}') | |
712 | + | |
713 | +# 実行結果(データ) | |
714 | +print(output10) | |
715 | + | |
716 | +# 結果は良くないのでここから最適化してみる | |
717 | +# Start 2022-10-04 03:57:00 | |
718 | +# End 2022-12-30 23:54:00 | |
719 | +# Duration 87 days 19:57:00 | |
720 | +# Exposure Time [%] 67.017594 | |
721 | +# Equity Final [$] 9809.700304 | |
722 | +# Equity Peak [$] 10074.386059 | |
723 | +# Return [%] -1.902997 | |
724 | +# Buy & Hold Return [%] -9.405472 | |
725 | +# Return (Ann.) [%] -6.919477 | |
726 | +# Volatility (Ann.) [%] 7.711395 | |
727 | +# Sharpe Ratio 0.0 | |
728 | +# Sortino Ratio 0.0 | |
729 | +# Calmar Ratio 0.0 | |
730 | +# Max. Drawdown [%] -5.597639 | |
731 | +# Avg. Drawdown [%] -0.231798 | |
732 | +# Max. Drawdown Duration 77 days 13:05:00 | |
733 | +# Avg. Drawdown Duration 2 days 08:47:00 | |
734 | +# # Trades 579 | |
735 | +# Win Rate [%] 19.170984 | |
736 | +# Best Trade [%] 0.372445 | |
737 | +# Worst Trade [%] -0.084989 | |
738 | +# Avg. Trade [%] -0.001945 | |
739 | +# Max. Trade Duration 3 days 09:35:00 | |
740 | +# Avg. Trade Duration 0 days 02:34:00 | |
741 | +# Profit Factor 0.971765 | |
742 | +# Expectancy [%] -0.001814 | |
743 | +# SQN -0.511846 | |
744 | +# _strategy MACDCross4 | |
745 | +# _equity_curve ... | |
746 | +# _trades Size Entry... | |
747 | + | |
748 | + | |
749 | +# 最適化 | |
750 | +s_time = time.perf_counter() | |
751 | +output11 = bt4.optimize( | |
752 | + n1=range(10, 100, 10), | |
753 | + n2=range(10, 250, 10), | |
754 | + ns=range(10, 50, 5), | |
755 | + maximize='SQN', | |
756 | + method='grid' | |
757 | +) | |
758 | +e_time = time.perf_counter() | |
759 | +# 経過時間を出力(秒) | |
760 | +p_time = round((e_time - s_time), 3) | |
761 | +print(f'Processing time: {p_time}') | |
762 | +print(output11) | |
763 | +print(output11._strategy) | |
764 | + | |
765 | +# 全件データで最適化したら良い数字が出てる! | |
766 | +# UserWarning: Searching for best of 1728 configurations. | |
767 | +# Processing time: 2614.396 | |
768 | +# Start 2022-10-04 03:57:00 | |
769 | +# End 2022-12-30 23:54:00 | |
770 | +# Duration 87 days 19:57:00 | |
771 | +# Exposure Time [%] 84.856116 | |
772 | +# Equity Final [$] 10564.701691 | |
773 | +# Equity Peak [$] 10872.253006 | |
774 | +# Return [%] 5.647017 | |
775 | +# Buy & Hold Return [%] -9.405472 | |
776 | +# Return (Ann.) [%] 22.408217 | |
777 | +# Volatility (Ann.) [%] 9.94039 | |
778 | +# Sharpe Ratio 2.254259 | |
779 | +# Sortino Ratio 4.679768 | |
780 | +# Calmar Ratio 5.36408 | |
781 | +# Max. Drawdown [%] -4.177457 | |
782 | +# Avg. Drawdown [%] -0.109228 | |
783 | +# Max. Drawdown Duration 25 days 18:11:00 | |
784 | +# Avg. Drawdown Duration 0 days 06:24:00 | |
785 | +# # Trades 871 | |
786 | +# Win Rate [%] 22.38806 | |
787 | +# Best Trade [%] 0.540564 | |
788 | +# Worst Trade [%] -0.085376 | |
789 | +# Avg. Trade [%] 0.007813 | |
790 | +# Max. Trade Duration 3 days 01:51:00 | |
791 | +# Avg. Trade Duration 0 days 02:22:00 | |
792 | +# Profit Factor 1.128089 | |
793 | +# Expectancy [%] 0.007955 | |
794 | +# SQN 1.128353 | |
795 | +# _strategy MACDCross4(n1=30... | |
796 | +# _equity_curve ... | |
797 | +# _trades Size Entry... | |
798 | +# MACDCross4(n1=30,n2=50,ns=15) | |
799 | + | |
800 | +# もう少し細分化して最適化 | |
801 | +s_time = time.perf_counter() | |
802 | +output12 = bt4.optimize( | |
803 | + n1=range(20, 40, 1), | |
804 | + n2=range(40, 60, 1), | |
805 | + ns=range(2, 20, 1), | |
806 | + maximize='SQN', | |
807 | + method='grid' | |
808 | +) | |
809 | +e_time = time.perf_counter() | |
810 | +# 経過時間を出力(秒) | |
811 | +p_time = round((e_time - s_time), 3) | |
812 | +print(f'Processing time: {p_time}') | |
813 | +print(output12) | |
814 | +print(output12._strategy) | |
815 | + | |
816 | +# SQNは平均的な値だが今までの流れからすると良い値と考える | |
817 | +# 全体=1年間なので長いスパンで運用するよりもスケールを変えるか検討が必要 | |
818 | +# いったん、今のコードに機能として追加する方が先と考える | |
819 | +# UserWarning: Searching for best of 7200 configurations. | |
820 | +# Processing time: 11776.894 | |
821 | +# Start 2022-10-04 03:57:00 | |
822 | +# End 2022-12-30 23:54:00 | |
823 | +# Duration 87 days 19:57:00 | |
824 | +# Exposure Time [%] 85.284329 | |
825 | +# Equity Final [$] 10644.792312 | |
826 | +# Equity Peak [$] 10896.238091 | |
827 | +# Return [%] 6.447923 | |
828 | +# Buy & Hold Return [%] -9.405472 | |
829 | +# Return (Ann.) [%] 26.162524 | |
830 | +# Volatility (Ann.) [%] 10.079171 | |
831 | +# Sharpe Ratio 2.595702 | |
832 | +# Sortino Ratio 5.504483 | |
833 | +# Calmar Ratio 7.157977 | |
834 | +# Max. Drawdown [%] -3.655017 | |
835 | +# Avg. Drawdown [%] -0.110736 | |
836 | +# Max. Drawdown Duration 22 days 13:17:00 | |
837 | +# Avg. Drawdown Duration 0 days 06:13:00 | |
838 | +# # Trades 871 | |
839 | +# Win Rate [%] 22.962113 | |
840 | +# Best Trade [%] 0.540564 | |
841 | +# Worst Trade [%] -0.085376 | |
842 | +# Avg. Trade [%] 0.010165 | |
843 | +# Max. Trade Duration 3 days 01:51:00 | |
844 | +# Avg. Trade Duration 0 days 02:23:00 | |
845 | +# Profit Factor 1.167371 | |
846 | +# Expectancy [%] 0.01031 | |
847 | +# SQN 1.276678 | |
848 | +# _strategy MACDCross4(n1=28... | |
849 | +# _equity_curve ... | |
850 | +# _trades Size Entry... | |
851 | +# MACDCross4(n1=28,n2=53,ns=15) |
@@ -1,6 +1,8 @@ | ||
1 | 1 | # 元ネタ |
2 | 2 | # https://qiita.com/Fujinoinvestor/items/780b138e441531860e60 |
3 | + | |
3 | 4 | # yahoo financeからデータ取得できないので手動で取得したcsvを使用する |
5 | +# https://finance.yahoo.com/quote/AAPL/history?p=AAPL | |
4 | 6 | |
5 | 7 | import os |
6 | 8 | import talib as ta |
@@ -27,6 +29,7 @@ data_path = os.path.join( | ||
27 | 29 | 'AAPL_Jan_02_2018-Apr_16_2021.csv' |
28 | 30 | ) |
29 | 31 | |
32 | +# csvが','区切りなのでreat_csvを使う | |
30 | 33 | df = pd.read_csv( |
31 | 34 | data_path, |
32 | 35 | index_col=['Date'] |