• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revision0627e54111783317fc221b1997836a81e6466750 (tree)
Time2023-02-11 11:48:53
Authorkazuhiro_kondow <simauma.circus@gmai...>
Commiterkazuhiro_kondow

Log Message

macdについてcrossoverの角度要素を検討

Change Summary

Incremental Difference

--- /dev/null
+++ b/Docs/datetime_tips.py
@@ -0,0 +1,64 @@
1+import MetaTrader5 as mt5
2+import datetime as dt
3+import pytz
4+
5+
6+cp = 'USDJPY'
7+mt5.initialize()
8+mt5.copy_rates_from_pos(cp, mt5.TIMEFRAME_M1, 0, 1)
9+
10+# 日本時間の8:58に取得
11+# array([(1675994280, 131.517, 131.518, 131.516, 131.516, 6, 3, 0)],
12+# dtype=[('time', '<i8'), ('open', '<f8'), ('high', '<f8'), ('low', '<f8'), ('close', '<f8'), ('tick_volume', '<u8'), ('spread', '<i4'), ('real_volume', '<u8')])
13+
14+# ローカルタイムスタンプとして扱うと2時間ずれる
15+dt.datetime.fromtimestamp(1675994280)
16+# datetime.datetime(2023, 2, 10, 10, 58)
17+
18+# UTCとして扱うとこのようになる
19+dt.datetime.utcfromtimestamp(1675994280)
20+# datetime.datetime(2023, 2, 10, 1, 58)
21+
22+# なので以下のようにして日本時間に変換する
23+# 日本のtimezone
24+tz_local = pytz.timezone('Etc/GMT-9')
25+# OANDAサーバのtimezone
26+tz_oanda = pytz.timezone('Etc/GMT-2')
27+
28+tz_oanda.localize(dt.datetime.utcfromtimestamp(1675994280))
29+# datetime.datetime(2023, 2, 10, 1, 58, tzinfo=<StaticTzInfo 'Etc/GMT-2'>)
30+
31+tz_oanda.localize(dt.datetime.utcfromtimestamp(1675994280)).astimezone(tz_local)
32+# datetime.datetime(2023, 2, 10, 8, 58, tzinfo=<StaticTzInfo 'Etc/GMT-9'>)
33+
34+# dataframeの場合は次の通り
35+
36+local_to = dt.datetime(
37+ now.year,
38+ now.month,
39+ now.day,
40+ 0,
41+ 0,
42+ 0,
43+ tzinfo=tz_local
44+)
45+local_from = local_to - dt.timedelta(days=30)
46+
47+rate_to = local_to.astimezone(tz_oanda)
48+rate_from = local_from.astimezone(tz_oanda)
49+
50+# レートを取得
51+cp = 'USDJPY'
52+mt5.initialize()
53+rates = mt5.copy_rates_range(cp, mt5.TIMEFRAME_M1, rate_from, rate_to)
54+
55+df = pd.DataFrame(rates)
56+
57+# timeカラムをdatetime型に変換
58+df.time = pd.to_datetime(df['time'], unit='s')
59+# timeカラムをindexに時系列インデックスとして割り当て
60+df.index = pd.DatetimeIndex(df.time, name='Date')
61+# インデックスのTimeZoneをUTCに設定
62+df.index = df.index.tz_localize(dt.timezone.utc)
63+# インデックスのTimeZoneをLovalに変換
64+df.index = df.index.tz_convert(tz_local)
--- /dev/null
+++ b/investigation_study/backtesting_fx_M1_4.py
@@ -0,0 +1,247 @@
1+# 元ネタ
2+# https://qiita.com/Fujinoinvestor/items/780b138e441531860e60
3+
4+# crossoverにangle要素を追加してどのように結果が変わるか検証する
5+# 比較対象はbacktesting_fx_M1_2.pyの結果
6+# UserWarning: Searching for best of 7200 configurations.
7+# Processing time: 11776.894
8+# Start 2022-10-04 03:57:00
9+# End 2022-12-30 23:54:00
10+# Duration 87 days 19:57:00
11+# Exposure Time [%] 85.284329
12+# Equity Final [$] 10644.792312
13+# Equity Peak [$] 10896.238091
14+# Return [%] 6.447923
15+# Buy & Hold Return [%] -9.405472
16+# Return (Ann.) [%] 26.162524
17+# Volatility (Ann.) [%] 10.079171
18+# Sharpe Ratio 2.595702
19+# Sortino Ratio 5.504483
20+# Calmar Ratio 7.157977
21+# Max. Drawdown [%] -3.655017
22+# Avg. Drawdown [%] -0.110736
23+# Max. Drawdown Duration 22 days 13:17:00
24+# Avg. Drawdown Duration 0 days 06:13:00
25+# # Trades 871
26+# Win Rate [%] 22.962113
27+# Best Trade [%] 0.540564
28+# Worst Trade [%] -0.085376
29+# Avg. Trade [%] 0.010165
30+# Max. Trade Duration 3 days 01:51:00
31+# Avg. Trade Duration 0 days 02:23:00
32+# Profit Factor 1.167371
33+# Expectancy [%] 0.01031
34+# SQN 1.276678
35+# _strategy MACDCross4(n1=28...
36+# _equity_curve ...
37+# _trades Size Entry...
38+# MACDCross4(n1=28,n2=53,ns=15)
39+
40+import os
41+import talib as ta
42+from backtesting.lib import crossover
43+from backtesting import Backtest
44+from backtesting import Strategy
45+import pandas as pd
46+import time
47+
48+# 現在ディレクトリ取得
49+cwd = os.getcwd()
50+
51+# get data
52+data_path = os.path.join(
53+ cwd,
54+ 'csv',
55+ 'USDJPY_M1_202210040357_202212302354.csv'
56+)
57+
58+# csvがtab区切りなのでreat_tableを使う
59+df = pd.read_table(
60+ data_path
61+)
62+
63+# DataFrameのカラム名をbacktesting向けに修正
64+df = df.rename(
65+ columns={
66+ "<DATE>": "Date",
67+ "<TIME>": "Time",
68+ "<OPEN>": "Open",
69+ "<HIGH>": "High",
70+ "<LOW>": "Low",
71+ "<CLOSE>": "Close",
72+ "<TICKVOL>": "Volume",
73+ "<VOL>": "not_use",
74+ "<SPREAD>": "Spread",
75+ }
76+)
77+
78+# 日付に時間文字列を結合
79+df.Date = df['Date'] + ' ' + df['Time']
80+
81+# Dateカラムをdatetime型に変換
82+df.Date = pd.to_datetime(df['Date'], format='%Y.%m.%d %H:%M:%S')
83+
84+# indexをDateカラムに設定
85+df = df.set_index('Date')
86+
87+# 必要なカラムのみ取得
88+data = df.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']]
89+
90+
91+def MACD(close, n1, n2, ns):
92+ macd, macdsignal, macdhist = ta.MACD(
93+ close, fastperiod=n1, slowperiod=n2, signalperiod=ns)
94+ return macd, macdsignal
95+
96+
97+# 下記記事を参考にStrategyを修正
98+# https://mmorley.hatenablog.com/entry/fx_backtesting01
99+
100+class MACDCross(Strategy):
101+ # 短期EMAの期間
102+ n1 = 28
103+ # 長期EMAの期間
104+ n2 = 53
105+ # シグナル(MACDのSMA)の期間
106+ ns = 15
107+ # angleの閾値
108+ crossover_angle = 0.5
109+
110+ def init(self):
111+ self.macd, self.macdsignal = self.I(
112+ MACD, self.data.Close, self.n1, self.n2, self.ns)
113+
114+ # チャートデータの行ごとに呼び出される
115+ # tp(take profit)利確する価格
116+ # sl(stop losst)損切りする価格
117+ def next(self):
118+ # macdがsignalを上回った時
119+ if crossover(self.macd, self.macdsignal) and self.macd[-1] < 0.0:
120+ # 買いオーダー
121+ self.buy(
122+ tp=self.data.Close[-1] + 0.5,
123+ sl=self.data.Close[-1] - 0.1
124+ )
125+
126+ # signalがmacdを上回った時
127+ elif crossover(self.macdsignal, self.macd) and self.macd[-1] > 0.0:
128+ # 売りオーダー
129+ self.sell(
130+ tp=self.data.Close[-1] - 0.5,
131+ sl=self.data.Close[-1] + 0.1
132+ )
133+
134+# まずはStrategyが少し異なる(比較元はmacdの0以上、以下を判定してなかった)ので、その検証
135+
136+
137+# バックテストを設定
138+bt = Backtest(
139+ # チャートデータ
140+ data,
141+ # 売買戦略
142+ MACDCross,
143+ # 最初の所持金
144+ cash=10000,
145+ # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円)
146+ # OANDAの場合0.3〜0.9銭=0.003~0.009円
147+ commission=0.00009,
148+ # レバレッジ倍率の逆数(0.5で2倍レバレッジ)
149+ margin=1.0,
150+ # True:現在の終値で取引,False:次の時間の始値で取引
151+ trade_on_close=True
152+)
153+
154+s_time = time.perf_counter()
155+# バックテスト実行
156+output = bt.run()
157+e_time = time.perf_counter()
158+# 経過時間を出力(秒)
159+p_time = round((e_time - s_time), 3)
160+print(f'Processing time: {p_time}')
161+
162+# 実行結果(データ)
163+print(output)
164+
165+# とても駄目
166+# Processing time: 5.412
167+# Start 2022-10-04 03:57:00
168+# End 2022-12-30 23:54:00
169+# Duration 87 days 19:57:00
170+# Exposure Time [%] 80.680482
171+# Equity Final [$] 9033.372661
172+# Equity Peak [$] 10078.256653
173+# Return [%] -9.666273
174+# Buy & Hold Return [%] -9.405472
175+# Return (Ann.) [%] -33.651759
176+# Volatility (Ann.) [%] 5.827159
177+# Sharpe Ratio 0.0
178+# Sortino Ratio 0.0
179+# Calmar Ratio 0.0
180+# Max. Drawdown [%] -11.131486
181+# Avg. Drawdown [%] -0.272737
182+# Max. Drawdown Duration 85 days 20:48:00
183+# Avg. Drawdown Duration 1 days 17:17:00
184+# # Trades 822
185+# Win Rate [%] 22.262774
186+# Best Trade [%] 0.399431
187+# Worst Trade [%] -0.085376
188+# Avg. Trade [%] -0.002357
189+# Max. Trade Duration 3 days 10:04:00
190+# Avg. Trade Duration 0 days 02:35:00
191+# Profit Factor 0.964156
192+# Expectancy [%] -0.002238
193+# SQN -2.511314
194+# _strategy MACDCross
195+# _equity_curve ...
196+# _trades Size Entry...
197+# dtype: object
198+
199+# 最適化
200+s_time = time.perf_counter()
201+output2 = bt.optimize(
202+ n1=range(20, 40, 1),
203+ n2=range(40, 60, 1),
204+ ns=range(2, 20, 1),
205+ maximize='SQN',
206+ method='grid'
207+)
208+e_time = time.perf_counter()
209+# 経過時間を出力(秒)
210+p_time = round((e_time - s_time), 3)
211+print(f'Processing time: {p_time}')
212+print(output2)
213+print(output2._strategy)
214+
215+# Processing time: 36708.622
216+# Start 2022-10-04 03:57:00
217+# End 2022-12-30 23:54:00
218+# Duration 87 days 19:57:00
219+# Exposure Time [%] 78.989816
220+# Equity Final [$] 9818.920317
221+# Equity Peak [$] 10081.403521
222+# Return [%] -1.810797
223+# Buy & Hold Return [%] -9.405472
224+# Return (Ann.) [%] -7.448111
225+# Volatility (Ann.) [%] 7.25267
226+# Sharpe Ratio 0.0
227+# Sortino Ratio 0.0
228+# Calmar Ratio 0.0
229+# Max. Drawdown [%] -4.752928
230+# Avg. Drawdown [%] -0.310453
231+# Max. Drawdown Duration 50 days 07:50:00
232+# Avg. Drawdown Duration 2 days 10:29:00
233+# # Trades 727
234+# Win Rate [%] 20.770289
235+# Best Trade [%] 0.399431
236+# Worst Trade [%] -0.085338
237+# Avg. Trade [%] 0.002205
238+# Max. Trade Duration 3 days 10:02:00
239+# Avg. Trade Duration 0 days 02:33:00
240+# Profit Factor 1.036753
241+# Expectancy [%] 0.002341
242+# SQN -0.429096
243+# _strategy MACDCross(n1=37,...
244+# _equity_curve ...
245+# _trades Size Entry...
246+# dtype: object
247+# MACDCross(n1=37,n2=46,ns=18)
--- /dev/null
+++ b/investigation_study/backtesting_fx_M1_5.py
@@ -0,0 +1,245 @@
1+# 元ネタ
2+# https://qiita.com/Fujinoinvestor/items/780b138e441531860e60
3+
4+# 過去90日のrateを取得してbacktestingを実行する
5+
6+import talib as ta
7+from backtesting.lib import crossover
8+from backtesting import Backtest
9+from backtesting import Strategy
10+import pandas as pd
11+import datetime as dt
12+import pytz
13+import MetaTrader5 as mt5
14+import numpy as np
15+from numpy import linalg as LA
16+
17+# 本日日付
18+now = dt.datetime.now()
19+# 日本のtimezone
20+tz_local = pytz.timezone('Etc/GMT-9')
21+# OANDAサーバのtimezone
22+tz_oanda = pytz.timezone('Etc/GMT-2')
23+
24+local_to = dt.datetime(
25+ now.year,
26+ now.month,
27+ now.day,
28+ 0,
29+ 0,
30+ 0,
31+ tzinfo=tz_local
32+)
33+local_from = local_to - dt.timedelta(days=90)
34+
35+rate_to = local_to.astimezone(tz_oanda)
36+rate_from = local_from.astimezone(tz_oanda)
37+
38+# レートを取得
39+cp = 'USDJPY'
40+mt5.initialize()
41+rates = mt5.copy_rates_range(cp, mt5.TIMEFRAME_M1, rate_from, rate_to)
42+
43+df = pd.DataFrame(rates)
44+
45+# timeカラムをdatetime型に変換
46+df.time = pd.to_datetime(df['time'], unit='s')
47+# timeカラムをindexに時系列インデックスとして割り当て
48+df.index = pd.DatetimeIndex(df.time, name='Date')
49+# インデックスのTimeZoneをUTCに設定
50+df.index = df.index.tz_localize(dt.timezone.utc)
51+# インデックスのTimeZoneをLovalに変換
52+df.index = df.index.tz_convert(tz_local)
53+
54+# DataFrameのカラム名をbacktesting向けに修正
55+df = df.rename(
56+ columns={
57+ "time": "Date",
58+ "open": "Open",
59+ "high": "High",
60+ "low": "Low",
61+ "close": "Close",
62+ "tick_volume": "Volume",
63+ "spread": "Spread",
64+ "real_volume": "not_use",
65+ }
66+)
67+
68+# 必要なカラムのみ取得
69+data = df.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']]
70+
71+
72+def MACD(close, n1, n2, ns):
73+ macd, macdsignal, macdhist = ta.MACD(
74+ close, fastperiod=n1, slowperiod=n2, signalperiod=ns)
75+ return macd, macdsignal
76+
77+
78+# 下記記事を参考にStrategyを修正
79+# https://mmorley.hatenablog.com/entry/fx_backtesting01
80+
81+class MACDCross(Strategy):
82+ # 短期EMAの期間
83+ n1 = 28
84+ # 長期EMAの期間
85+ n2 = 53
86+ # シグナル(MACDのSMA)の期間
87+ ns = 15
88+ # angleの閾値
89+ crossover_angle = 0.0
90+
91+ def init(self):
92+ self.macd, self.macdsignal = self.I(
93+ MACD, self.data.Close, self.n1, self.n2, self.ns)
94+
95+ def vector_angle(self, u: np.ndarray, v: np.ndarray):
96+ i = np.inner(u, v)
97+ n = LA.norm(u) * LA.norm(v)
98+ c = i / n
99+ return np.rad2deg(np.arccos(np.clip(c, -1.0, 1.0)))
100+
101+ # チャートデータの行ごとに呼び出される
102+ # tp(take profit)利確する価格
103+ # sl(stop losst)損切りする価格
104+ def next(self):
105+ # macdがsignalを上回った時
106+ if crossover(self.macd, self.macdsignal) and \
107+ self.macd[-1] < 0.0 and \
108+ self.vector_angle(
109+ self.macd[-2:],
110+ self.macdsignal[-2:]
111+ ) > self.crossover_angle:
112+ # 買いオーダー
113+ self.buy(
114+ tp=self.data.Close[-1] + 0.5,
115+ sl=self.data.Close[-1] - 0.1
116+ )
117+
118+ # signalがmacdを上回った時
119+ elif crossover(self.macdsignal, self.macd) and \
120+ self.macd[-1] > 0.0 and \
121+ self.vector_angle(
122+ self.macd[-2:],
123+ self.macdsignal[-2:]
124+ ) > self.crossover_angle:
125+ # 売りオーダー
126+ self.sell(
127+ tp=self.data.Close[-1] - 0.5,
128+ sl=self.data.Close[-1] + 0.1
129+ )
130+
131+# まずはStrategyが少し異なる(比較元はmacdの0以上、以下を判定してなかった)ので、その検証
132+
133+
134+# バックテストを設定
135+bt = Backtest(
136+ # チャートデータ
137+ data,
138+ # 売買戦略
139+ MACDCross,
140+ # 最初の所持金
141+ cash=10000,
142+ # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円)
143+ # OANDAの場合0.3〜0.9銭=0.003~0.009円
144+ commission=0.00009,
145+ # レバレッジ倍率の逆数(0.5で2倍レバレッジ)
146+ margin=1.0,
147+ # True:現在の終値で取引,False:次の時間の始値で取引
148+ trade_on_close=True
149+)
150+
151+s_time = dt.datetime.timestamp(dt.datetime.utcnow())
152+# バックテスト実行
153+output = bt.run()
154+e_time = dt.datetime.timestamp(dt.datetime.utcnow())
155+# 経過時間を出力(秒)
156+p_time = round((e_time - s_time), 0)
157+print(f'Processing time(sec): {p_time}')
158+
159+# 実行結果(データ)
160+print(output)
161+
162+# Processing time(sec): 16.0
163+# Start 2022-11-14 09:00...
164+# End 2023-02-11 00:00...
165+# Duration 88 days 15:00:00
166+# Exposure Time [%] 79.312882
167+# Equity Final [$] 9613.15298
168+# Equity Peak [$] 10130.710517
169+# Return [%] -3.86847
170+# Buy & Hold Return [%] -5.877446
171+# Return (Ann.) [%] -11.649176
172+# Volatility (Ann.) [%] 7.002821
173+# Sharpe Ratio 0.0
174+# Sortino Ratio 0.0
175+# Calmar Ratio 0.0
176+# Max. Drawdown [%] -8.675607
177+# Avg. Drawdown [%] -0.269104
178+# Max. Drawdown Duration 77 days 02:20:00
179+# Avg. Drawdown Duration 1 days 14:35:00
180+# # Trades 888
181+# Win Rate [%] 20.833333
182+# Best Trade [%] 0.383547
183+# Worst Trade [%] -0.087276
184+# Avg. Trade [%] 0.002029
185+# Max. Trade Duration 3 days 10:04:00
186+# Avg. Trade Duration 0 days 02:09:00
187+# Profit Factor 1.032843
188+# Expectancy [%] 0.002176
189+# SQN -0.824697
190+# _strategy MACDCross
191+# _equity_curve ...
192+# _trades Size Entry...
193+# dtype: object
194+
195+# 最適化して検証
196+# 時間がかかりすぎるのでangleのみ最適化
197+s_time = dt.datetime.timestamp(dt.datetime.utcnow())
198+output2 = bt.optimize(
199+ # n1=range(20, 40, 1),
200+ # n2=range(40, 60, 1),
201+ # ns=range(10, 30, 1),
202+ crossover_angle=[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0],
203+ maximize='SQN',
204+ method='grid'
205+)
206+e_time = dt.datetime.timestamp(dt.datetime.utcnow())
207+# 経過時間を出力(秒)
208+p_time = round((e_time - s_time), 0)
209+print(f'Processing time(sec): {p_time}')
210+print(output2)
211+print(output2._strategy)
212+
213+# Processing time(sec): 132.0
214+# Start 2022-11-14 09:00...
215+# End 2023-02-11 00:00...
216+# Duration 88 days 15:00:00
217+# Exposure Time [%] 29.644473
218+# Equity Final [$] 10306.515571
219+# Equity Peak [$] 10399.114836
220+# Return [%] 3.065156
221+# Buy & Hold Return [%] -5.877446
222+# Return (Ann.) [%] 10.297861
223+# Volatility (Ann.) [%] 5.746197
224+# Sharpe Ratio 1.792118
225+# Sortino Ratio 3.735854
226+# Calmar Ratio 2.387603
227+# Max. Drawdown [%] -4.313055
228+# Avg. Drawdown [%] -0.120288
229+# Max. Drawdown Duration 65 days 17:52:00
230+# Avg. Drawdown Duration 0 days 17:15:00
231+# # Trades 312
232+# Win Rate [%] 20.512821
233+# Best Trade [%] 1.057665
234+# Worst Trade [%] -0.08725
235+# Avg. Trade [%] 0.009701
236+# Max. Trade Duration 2 days 10:13:00
237+# Avg. Trade Duration 0 days 02:36:00
238+# Profit Factor 1.149254
239+# Expectancy [%] 0.009877
240+# SQN 0.925784
241+# _strategy MACDCross(crosso...
242+# _equity_curve ...
243+# _trades Size Entry...
244+# dtype: object
245+# MACDCross(crossover_angle=3.5)
--- /dev/null
+++ b/investigation_study/backtesting_fx_M1_6.py
@@ -0,0 +1,246 @@
1+# 元ネタ
2+# https://qiita.com/Fujinoinvestor/items/780b138e441531860e60
3+
4+# 過去90日のrateを取得してbacktestingを実行する
5+# セオリーからGoldenCross,DeadCross判定に
6+# macdの0.0以上、以下を外した場合の方が
7+# backtesting_fx_M1_5.pyと比較して
8+# Backtestingの結果が良かった
9+
10+import talib as ta
11+from backtesting.lib import crossover
12+from backtesting import Backtest
13+from backtesting import Strategy
14+import pandas as pd
15+import datetime as dt
16+import pytz
17+import MetaTrader5 as mt5
18+import numpy as np
19+from numpy import linalg as LA
20+
21+# 本日日付
22+now = dt.datetime.now()
23+# 日本のtimezone
24+tz_local = pytz.timezone('Etc/GMT-9')
25+# OANDAサーバのtimezone
26+tz_oanda = pytz.timezone('Etc/GMT-2')
27+
28+local_to = dt.datetime(
29+ now.year,
30+ now.month,
31+ now.day,
32+ 0,
33+ 0,
34+ 0,
35+ tzinfo=tz_local
36+)
37+local_from = local_to - dt.timedelta(days=90)
38+
39+rate_to = local_to.astimezone(tz_oanda)
40+rate_from = local_from.astimezone(tz_oanda)
41+
42+# レートを取得
43+cp = 'USDJPY'
44+mt5.initialize()
45+rates = mt5.copy_rates_range(cp, mt5.TIMEFRAME_M1, rate_from, rate_to)
46+
47+df = pd.DataFrame(rates)
48+
49+# timeカラムをdatetime型に変換
50+df.time = pd.to_datetime(df['time'], unit='s')
51+# timeカラムをindexに時系列インデックスとして割り当て
52+df.index = pd.DatetimeIndex(df.time, name='Date')
53+# インデックスのTimeZoneをUTCに設定
54+df.index = df.index.tz_localize(dt.timezone.utc)
55+# インデックスのTimeZoneをLovalに変換
56+df.index = df.index.tz_convert(tz_local)
57+
58+# DataFrameのカラム名をbacktesting向けに修正
59+df = df.rename(
60+ columns={
61+ "time": "Date",
62+ "open": "Open",
63+ "high": "High",
64+ "low": "Low",
65+ "close": "Close",
66+ "tick_volume": "Volume",
67+ "spread": "Spread",
68+ "real_volume": "not_use",
69+ }
70+)
71+
72+# 必要なカラムのみ取得
73+data = df.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']]
74+
75+
76+def MACD(close, n1, n2, ns):
77+ macd, macdsignal, macdhist = ta.MACD(
78+ close, fastperiod=n1, slowperiod=n2, signalperiod=ns)
79+ return macd, macdsignal
80+
81+
82+# 下記記事を参考にStrategyを修正
83+# https://mmorley.hatenablog.com/entry/fx_backtesting01
84+
85+class MACDCross(Strategy):
86+ # 短期EMAの期間
87+ n1 = 28
88+ # 長期EMAの期間
89+ n2 = 53
90+ # シグナル(MACDのSMA)の期間
91+ ns = 15
92+ # angleの閾値
93+ crossover_angle = 0.0
94+
95+ def init(self):
96+ self.macd, self.macdsignal = self.I(
97+ MACD, self.data.Close, self.n1, self.n2, self.ns)
98+
99+ def vector_angle(self, u: np.ndarray, v: np.ndarray):
100+ i = np.inner(u, v)
101+ n = LA.norm(u) * LA.norm(v)
102+ c = i / n
103+ return np.rad2deg(np.arccos(np.clip(c, -1.0, 1.0)))
104+
105+ # チャートデータの行ごとに呼び出される
106+ # tp(take profit)利確する価格
107+ # sl(stop losst)損切りする価格
108+ def next(self):
109+ # macdがsignalを上回った時
110+ if crossover(self.macd, self.macdsignal) and \
111+ self.vector_angle(
112+ self.macd[-2:],
113+ self.macdsignal[-2:]
114+ ) > self.crossover_angle:
115+ # 買いオーダー
116+ self.buy(
117+ tp=self.data.Close[-1] + 0.5,
118+ sl=self.data.Close[-1] - 0.1
119+ )
120+
121+ # signalがmacdを上回った時
122+ elif crossover(self.macdsignal, self.macd) and \
123+ self.vector_angle(
124+ self.macd[-2:],
125+ self.macdsignal[-2:]
126+ ) > self.crossover_angle:
127+ # 売りオーダー
128+ self.sell(
129+ tp=self.data.Close[-1] - 0.5,
130+ sl=self.data.Close[-1] + 0.1
131+ )
132+
133+
134+# バックテストを設定
135+bt = Backtest(
136+ # チャートデータ
137+ data,
138+ # 売買戦略
139+ MACDCross,
140+ # 最初の所持金
141+ cash=10000,
142+ # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円)
143+ # OANDAの場合0.3〜0.9銭=0.003~0.009円
144+ commission=0.00009,
145+ # レバレッジ倍率の逆数(0.5で2倍レバレッジ)
146+ margin=1.0,
147+ # True:現在の終値で取引,False:次の時間の始値で取引
148+ trade_on_close=True
149+)
150+
151+s_time = dt.datetime.timestamp(dt.datetime.utcnow())
152+# バックテスト実行
153+output = bt.run()
154+e_time = dt.datetime.timestamp(dt.datetime.utcnow())
155+# 経過時間を出力(秒)
156+p_time = round((e_time - s_time), 0)
157+print(f'Processing time(sec): {p_time}')
158+
159+# 実行結果(データ)
160+print(output)
161+
162+# Processing time(sec): 20.0
163+# Start 2022-11-14 09:00...
164+# End 2023-02-11 00:00...
165+# Duration 88 days 15:00:00
166+# Exposure Time [%] 84.418508
167+# Equity Final [$] 10681.733506
168+# Equity Peak [$] 10725.062947
169+# Return [%] 6.817335
170+# Buy & Hold Return [%] -5.877446
171+# Return (Ann.) [%] 23.66191
172+# Volatility (Ann.) [%] 9.973056
173+# Sharpe Ratio 2.372584
174+# Sortino Ratio 4.343607
175+# Calmar Ratio 6.480834
176+# Max. Drawdown [%] -3.65106
177+# Avg. Drawdown [%] -0.124067
178+# Max. Drawdown Duration 42 days 14:15:00
179+# Avg. Drawdown Duration 0 days 07:42:00
180+# # Trades 1041
181+# Win Rate [%] 24.207493
182+# Best Trade [%] 1.057665
183+# Worst Trade [%] -0.087407
184+# Avg. Trade [%] 0.012589
185+# Max. Trade Duration 2 days 08:09:00
186+# Avg. Trade Duration 0 days 02:07:00
187+# Profit Factor 1.202623
188+# Expectancy [%] 0.012749
189+# SQN 1.205884
190+# _strategy MACDCross
191+# _equity_curve ...
192+# _trades Size Entr...
193+# dtype: object
194+
195+
196+# 最適化して検証
197+# 時間がかかりすぎるのでangleのみ最適化
198+s_time = dt.datetime.timestamp(dt.datetime.utcnow())
199+output2 = bt.optimize(
200+ # n1=range(20, 40, 1),
201+ # n2=range(40, 60, 1),
202+ # ns=range(10, 30, 1),
203+ crossover_angle=[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0],
204+ maximize='SQN',
205+ method='grid'
206+)
207+e_time = dt.datetime.timestamp(dt.datetime.utcnow())
208+# 経過時間を出力(秒)
209+p_time = round((e_time - s_time), 0)
210+print(f'Processing time(sec): {p_time}')
211+print(output2)
212+print(output2._strategy)
213+
214+# Processing time(sec): 163.0
215+# Start 2022-11-14 09:00...
216+# End 2023-02-11 00:00...
217+# Duration 88 days 15:00:00
218+# Exposure Time [%] 48.076332
219+# Equity Final [$] 10675.172967
220+# Equity Peak [$] 10707.548153
221+# Return [%] 6.75173
222+# Buy & Hold Return [%] -5.877446
223+# Return (Ann.) [%] 22.986772
224+# Volatility (Ann.) [%] 7.923884
225+# Sharpe Ratio 2.900947
226+# Sortino Ratio 7.140729
227+# Calmar Ratio 6.643383
228+# Max. Drawdown [%] -3.4601
229+# Avg. Drawdown [%] -0.112675
230+# Max. Drawdown Duration 44 days 09:11:00
231+# Avg. Drawdown Duration 0 days 09:08:00
232+# # Trades 495
233+# Win Rate [%] 21.212121
234+# Best Trade [%] 1.057665
235+# Worst Trade [%] -0.087566
236+# Avg. Trade [%] 0.012992
237+# Max. Trade Duration 2 days 06:53:00
238+# Avg. Trade Duration 0 days 02:11:00
239+# Profit Factor 1.200226
240+# Expectancy [%] 0.01317
241+# SQN 1.600122
242+# _strategy MACDCross(crosso...
243+# _equity_curve ...
244+# _trades Size Entry...
245+# dtype: object
246+# MACDCross(crossover_angle=3.5)
--- /dev/null
+++ b/investigation_study/numpy_vector_angle_1.py
@@ -0,0 +1,47 @@
1+# vector angle
2+# ベクトルのなす角を用いてMACDのCrossOver判定について改良を試みる
3+# 参考文献
4+# https://hiraocafe.com/note/2lineanglevec.html
5+# https://www.mathpython.com/numpy-vector-angle
6+import numpy as np
7+from numpy import linalg as LA
8+
9+
10+def vector_angle(u: np.array, v: np.array):
11+ i = np.inner(u, v)
12+ n = LA.norm(u) * LA.norm(v)
13+ c = i / n
14+ return np.rad2deg(np.arccos(np.clip(c, -1.0, 1.0)))
15+
16+
17+u = np.array([3, 4])
18+v = np.array([-4, 3])
19+print(vector_angle(u, v)) # 90.0
20+
21+# テストケース
22+# 2023-02-03 13:24:02,027
23+# num[-2]: MACD: 0.002432, MACDSignal: 0.003394
24+# num[-1]: MACD: 0.00243, MACDSignal: 0.003274
25+# Technical Indicator: Consider it a DeadCross.
26+u1 = np.array([0.00243, 0.002432])
27+v1 = np.array([0.003274, 0.003394])
28+print(vector_angle(u1, v1))
29+# 1.0074377034490547
30+
31+# 2023-02-03 13:25:02,727
32+# num[-2]: MACD: 0.002782, MACDSignal: 0.003317
33+# num[-1]: MACD: 0.003056, MACDSignal: 0.003285
34+# Technical Indicator: Consider it a DeadCross.
35+u2 = np.array([0.003056, 0.002782])
36+v2 = np.array([0.003285, 0.003317])
37+print(vector_angle(u2, v2))
38+# 2.964852801558037
39+
40+# 2023-02-03 13:42:02,638
41+# num[-2]: MACD: 0.007748, MACDSignal: 0.007773
42+# num[-1]: MACD: 0.006698, MACDSignal: 0.007639
43+# Technical Indicator: Consider it a DeadCross.
44+u3 = np.array([0.007748, 0.007773])
45+v3 = np.array([0.006698, 0.007639])
46+print(vector_angle(u3, v3))
47+# 3.6628990024599957
--- /dev/null
+++ b/investigation_study/numpy_vector_angle_2.py
@@ -0,0 +1,120 @@
1+# vector angle
2+# ベクトルのなす角を用いてMACDのCrossOver判定について改良を試みる
3+# 参考文献
4+# https://hiraocafe.com/note/2lineanglevec.html
5+# https://www.mathpython.com/numpy-vector-angle
6+# 過去データ検証
7+import MetaTrader5 as mt5
8+import talib as ta
9+import numpy as np
10+from datetime import datetime
11+from datetime import timedelta
12+import pytz
13+from numpy import linalg as LA
14+
15+
16+def vector_angle(u: np.ndarray, v: np.ndarray):
17+ i = np.inner(u, v)
18+ n = LA.norm(u) * LA.norm(v)
19+ c = i / n
20+ return np.rad2deg(np.arccos(np.clip(c, -1.0, 1.0)))
21+
22+
23+def crossover(series1: np.ndarray, series2: np.ndarray) -> bool:
24+ """指標値列の交差判定
25+ """
26+ return series1[-2] < series2[-2] and series1[-1] > series2[-1]
27+
28+
29+mt5.initialize()
30+cp = 'USDJPY'
31+# 短期EMAの期間
32+n1 = 28
33+# 長期EMAの期間
34+n2 = 53
35+# シグナル(MACDのSMA)の期間
36+ns = 15
37+
38+
39+# OANDAサーバのtimezone
40+tz_oanda = pytz.timezone('Etc/GMT-2')
41+oanda_from = datetime(2023, 2, 8, 0, 0, 0, tzinfo=tz_oanda)
42+oanda_to = oanda_from + timedelta(hours=24)
43+
44+# レートを取得
45+rates = mt5.copy_rates_range(cp, mt5.TIMEFRAME_M1, oanda_from, oanda_to)
46+
47+closes = rates['close']
48+
49+macd, macdsignal, _ = ta.MACD(
50+ closes,
51+ fastperiod=n1,
52+ slowperiod=n2,
53+ signalperiod=ns
54+)
55+
56+macd = np.around(macd, 6)
57+macdsignal = np.around(macdsignal, 6)
58+
59+for i in range(0, (len(rates) - 1)):
60+ if np.isnan(macd[i]) or np.isnan(macd[i + 1]):
61+ # データがnanは何もしない
62+ continue
63+ if np.isnan(macdsignal[i]) or np.isnan(macdsignal[i + 1]):
64+ # データがnanは何もしない
65+ continue
66+ macd_s = macd[i: i + 2]
67+ macdsignal_s = macdsignal[i: i + 2]
68+ if crossover(macd_s, macdsignal_s) and macd_s[-1] < 0.0:
69+ # GoldenCross 上昇転換サイン
70+ msg = 'Technical Indicator: GoldenCross.'
71+ rate_time = tz_oanda.localize(
72+ datetime.utcfromtimestamp(rates[i]['time'])
73+ )
74+ angle = round(vector_angle(macd_s, macdsignal_s), 6)
75+ print(f'{rate_time}: {angle}: {msg}')
76+ elif crossover(macdsignal_s, macd_s) and macd_s[-1] > 0.0:
77+ # DeadCross 降下転換サイン
78+ msg = 'Technical Indicator: DeadCross.'
79+ rate_time = tz_oanda.localize(
80+ datetime.utcfromtimestamp(rates[i]['time'])
81+ )
82+ angle = round(vector_angle(macdsignal_s, macd_s), 6)
83+ print(f'{rate_time}: {angle}: {msg}')
84+
85+# angleが0.5以上を採用すれば誤判定を少しへらせるかも
86+# backtestで検証する
87+
88+# 2023-02-07 23:46:00+02:00: 0.48448: Technical Indicator: GoldenCross.
89+# 2023-02-07 23:50:00+02:00: 1.119538: Technical Indicator: GoldenCross.
90+# 2023-02-08 00:18:00+02:00: 3.135568: Technical Indicator: GoldenCross.
91+# 2023-02-08 01:00:00+02:00: 22.266663: Technical Indicator: GoldenCross.
92+# 2023-02-08 01:28:00+02:00: 0.558075: Technical Indicator: DeadCross.
93+# 2023-02-08 02:50:00+02:00: 1.175004: Technical Indicator: GoldenCross.
94+# 2023-02-08 04:15:00+02:00: 0.211562: Technical Indicator: DeadCross.
95+# 2023-02-08 04:28:00+02:00: 0.247605: Technical Indicator: DeadCross.
96+# 2023-02-08 05:36:00+02:00: 1.632956: Technical Indicator: GoldenCross.
97+# 2023-02-08 05:59:00+02:00: 3.524362: Technical Indicator: GoldenCross.
98+# 2023-02-08 06:15:00+02:00: 0.855166: Technical Indicator: GoldenCross.
99+# 2023-02-08 06:59:00+02:00: 0.940879: Technical Indicator: DeadCross.
100+# 2023-02-08 07:16:00+02:00: 2.399271: Technical Indicator: DeadCross.
101+# 2023-02-08 08:11:00+02:00: 1.337743: Technical Indicator: GoldenCross.
102+# 2023-02-08 08:43:00+02:00: 3.563947: Technical Indicator: DeadCross.
103+# 2023-02-08 09:22:00+02:00: 2.031104: Technical Indicator: DeadCross.
104+# 2023-02-08 10:08:00+02:00: 0.784882: Technical Indicator: GoldenCross.
105+# 2023-02-08 10:28:00+02:00: 0.961372: Technical Indicator: GoldenCross.
106+# 2023-02-08 11:25:00+02:00: 0.760229: Technical Indicator: GoldenCross.
107+# 2023-02-08 12:00:00+02:00: 1.235069: Technical Indicator: GoldenCross.
108+# 2023-02-08 12:41:00+02:00: 1.106239: Technical Indicator: DeadCross.
109+# 2023-02-08 13:49:00+02:00: 2.006404: Technical Indicator: GoldenCross.
110+# 2023-02-08 14:25:00+02:00: 10.711557: Technical Indicator: DeadCross.
111+# 2023-02-08 15:34:00+02:00: 0.568802: Technical Indicator: DeadCross.
112+# 2023-02-08 17:03:00+02:00: 1.336369: Technical Indicator: DeadCross.
113+# 2023-02-08 17:15:00+02:00: 0.909583: Technical Indicator: DeadCross.
114+# 2023-02-08 17:59:00+02:00: 0.832841: Technical Indicator: DeadCross.
115+# 2023-02-08 18:27:00+02:00: 4.131851: Technical Indicator: GoldenCross.
116+# 2023-02-08 19:06:00+02:00: 1.267079: Technical Indicator: GoldenCross.
117+# 2023-02-08 19:32:00+02:00: 1.267604: Technical Indicator: GoldenCross.
118+# 2023-02-08 20:17:00+02:00: 2.140756: Technical Indicator: GoldenCross.
119+# 2023-02-08 20:55:00+02:00: 2.290568: Technical Indicator: DeadCross.
120+# 2023-02-08 21:59:00+02:00: 0.812178: Technical Indicator: DeadCross.
--- a/mt5-operator.log.2022-12-15
+++ /dev/null
@@ -1,71 +0,0 @@
1-2022-12-15 04:59:45,523 8028 MainThread __main__:75 main [DEBUG]: set schedule.
2-2022-12-15 04:59:45,528 8028 MainThread __main__:81 main [DEBUG]: start loop.
3-2022-12-15 05:00:00,636 8028 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:00:00 Open: 135.303 High: 135.385 Low: 135.303 Close: 135.358 Volume: 313 Spread: 3
4-2022-12-15 05:00:16,666 8028 MainThread __main__:59 check_ticks [DEBUG]: time bid ask last volume time_msc flags volume_real
5-0 2022-12-14 11:00:15 135.355 135.363 0.0 0 1671015615341 4 0.0
6-1 2022-12-14 11:00:15 135.361 135.368 0.0 0 1671015615492 134 0.0
7-2 2022-12-14 11:00:15 135.360 135.368 0.0 0 1671015615559 130 0.0
8-3 2022-12-14 11:00:15 135.358 135.366 0.0 0 1671015615618 134 0.0
9-4 2022-12-14 11:00:16 135.361 135.367 0.0 0 1671015616267 134 0.0
10-.. ... ... ... ... ... ... ... ...
11-995 2022-12-14 11:03:50 135.327 135.332 0.0 0 1671015830632 134 0.0
12-996 2022-12-14 11:03:50 135.326 135.332 0.0 0 1671015830731 130 0.0
13-997 2022-12-14 11:03:52 135.326 135.331 0.0 0 1671015832092 4 0.0
14-998 2022-12-14 11:03:52 135.325 135.331 0.0 0 1671015832200 130 0.0
15-999 2022-12-14 11:03:52 135.324 135.331 0.0 0 1671015832526 130 0.0
16-
17-[1000 rows x 8 columns]
18-2022-12-15 05:00:30,883 8028 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:00:00 Open: 135.303 High: 135.385 Low: 135.303 Close: 135.358 Volume: 313 Spread: 3
19-2022-12-15 05:00:45,974 8028 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:00:00 Open: 135.303 High: 135.385 Low: 135.303 Close: 135.358 Volume: 313 Spread: 3
20-2022-12-15 05:01:00,046 8028 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:01:00 Open: 135.357 High: 135.358 Low: 135.326 Close: 135.347 Volume: 211 Spread: 3
21-2022-12-15 05:01:15,161 8028 MainThread __main__:59 check_ticks [DEBUG]: time bid ask last volume time_msc flags volume_real
22-0 2022-12-14 11:01:15 135.332 135.341 0.0 0 1671015675064 4 0.0
23-1 2022-12-14 11:01:15 135.333 135.341 0.0 0 1671015675132 130 0.0
24-2 2022-12-14 11:01:15 135.332 135.340 0.0 0 1671015675191 134 0.0
25-3 2022-12-14 11:01:15 135.333 135.340 0.0 0 1671015675353 130 0.0
26-4 2022-12-14 11:01:15 135.335 135.341 0.0 0 1671015675838 134 0.0
27-.. ... ... ... ... ... ... ... ...
28-995 2022-12-14 11:05:57 135.318 135.325 0.0 0 1671015957797 134 0.0
29-996 2022-12-14 11:05:57 135.318 135.324 0.0 0 1671015957870 4 0.0
30-997 2022-12-14 11:05:58 135.319 135.326 0.0 0 1671015958179 134 0.0
31-998 2022-12-14 11:05:58 135.319 135.325 0.0 0 1671015958290 4 0.0
32-999 2022-12-14 11:05:58 135.322 135.329 0.0 0 1671015958480 134 0.0
33-
34-[1000 rows x 8 columns]
35-2022-12-15 05:05:49,913 7540 MainThread __main__:75 main [DEBUG]: set schedule.
36-2022-12-15 05:05:49,915 7540 MainThread __main__:81 main [DEBUG]: start loop.
37-2022-12-15 05:06:00,946 7540 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:06:00 Open: 135.317 High: 135.322 Low: 135.277 Close: 135.277 Volume: 124 Spread: 3
38-2022-12-15 05:06:15,978 7540 MainThread __main__:59 check_ticks [DEBUG]: time bid ask last volume time_msc flags volume_real
39-0 2022-12-14 11:06:15 135.302 135.309 0.0 0 1671015975199 134 0.0
40-1 2022-12-14 11:06:15 135.302 135.306 0.0 0 1671015975250 4 0.0
41-2 2022-12-14 11:06:15 135.302 135.309 0.0 0 1671015975309 4 0.0
42-3 2022-12-14 11:06:15 135.301 135.308 0.0 0 1671015975364 134 0.0
43-4 2022-12-14 11:06:15 135.300 135.306 0.0 0 1671015975459 134 0.0
44-.. ... ... ... ... ... ... ... ...
45-995 2022-12-14 11:12:31 135.226 135.230 0.0 0 1671016351385 134 0.0
46-996 2022-12-14 11:12:31 135.223 135.230 0.0 0 1671016351436 130 0.0
47-997 2022-12-14 11:12:31 135.224 135.229 0.0 0 1671016351490 134 0.0
48-998 2022-12-14 11:12:31 135.220 135.227 0.0 0 1671016351541 134 0.0
49-999 2022-12-14 11:12:31 135.220 135.225 0.0 0 1671016351759 4 0.0
50-
51-[1000 rows x 8 columns]
52-2022-12-15 05:06:30,201 7540 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:06:00 Open: 135.317 High: 135.322 Low: 135.277 Close: 135.277 Volume: 124 Spread: 3
53-2022-12-15 05:06:45,296 7540 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:06:00 Open: 135.317 High: 135.322 Low: 135.277 Close: 135.277 Volume: 124 Spread: 3
54-2022-12-15 05:08:40,838 972 MainThread __main__:76 main [DEBUG]: set schedule.
55-2022-12-15 05:08:40,843 972 MainThread __main__:82 main [DEBUG]: start loop.
56-2022-12-15 05:08:45,867 972 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:08:00 Open: 135.275 High: 135.296 Low: 135.259 Close: 135.284 Volume: 157 Spread: 3
57-2022-12-15 05:09:00,923 972 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:09:00 Open: 135.283 High: 135.285 Low: 135.256 Close: 135.271 Volume: 140 Spread: 3
58-2022-12-15 05:09:15,972 972 MainThread __main__:60 check_ticks [DEBUG]: time
59-2022-12-15 05:09:15,972 972 MainThread __main__:60 check_ticks [DEBUG]: bid
60-2022-12-15 05:09:15,972 972 MainThread __main__:60 check_ticks [DEBUG]: ask
61-2022-12-15 05:09:15,981 972 MainThread __main__:60 check_ticks [DEBUG]: last
62-2022-12-15 05:09:15,981 972 MainThread __main__:60 check_ticks [DEBUG]: volume
63-2022-12-15 05:09:15,982 972 MainThread __main__:60 check_ticks [DEBUG]: time_msc
64-2022-12-15 05:09:15,982 972 MainThread __main__:60 check_ticks [DEBUG]: flags
65-2022-12-15 05:09:15,983 972 MainThread __main__:60 check_ticks [DEBUG]: volume_real
66-2022-12-15 05:09:48,869 2512 MainThread __main__:75 main [DEBUG]: set schedule.
67-2022-12-15 05:09:48,875 2512 MainThread __main__:81 main [DEBUG]: start loop.
68-2022-12-15 05:10:00,907 2512 MainThread __main__:33 job [DEBUG]: rate_M1 time: 2022-12-14 11:10:00 Open: 135.271 High: 135.275 Low: 135.225 Close: 135.231 Volume: 131 Spread: 3
69-2022-12-15 05:10:15,947 2512 MainThread __main__:59 check_ticks [DEBUG]: Empty DataFrame
70-Columns: [time, bid, ask, last, volume, time_msc, flags, volume_real]
71-Index: []
--- a/src/config/logging.conf
+++ b/src/config/logging.conf
@@ -18,7 +18,7 @@ args=(sys.stdout,)
1818 class=logging.handlers.TimedRotatingFileHandler
1919 level=DEBUG
2020 formatter=simple
21-args=('./mt5-operator.log', 'D', 1, 10, 'utf-8')
21+args=('./mt5-operator.log', 'D', 10, 10, 'utf-8')
2222
2323 [formatters]
2424 keys=simple
--- a/src/config/setting.ini
+++ b/src/config/setting.ini
@@ -36,9 +36,9 @@ Allowablespread = 0.01
3636 # 1銭は0.01円
3737 OpenMergin = 0.007
3838 # 利益確定(円)
39-ProfitTaking = 1.0
39+ProfitTaking = 1.5
4040 # 損切(円)
41-LossCut = 0.5
41+LossCut = 0.2
4242
4343 # テクニカル分析
4444 [Technical]
--- a/src/definition.py
+++ b/src/definition.py
@@ -2,6 +2,7 @@
22 # テクニカル分析
33 TECHNICAL_UNCHANGED = 0
44 TECHNICAL_GOLDEN_CROSS = 1
5-TECHNICAL_UPTREND = 2
6-TECHNICAL_DEAD_CROSS = 3
5+TECHNICAL_DEAD_CROSS = 2
6+TECHNICAL_UPTREND = 3
77 TECHNICAL_DOWNTREND = 4
8+
--- a/src/exchange_rate_info.py
+++ b/src/exchange_rate_info.py
@@ -163,7 +163,6 @@ class ExchangeRateInfo():
163163 count
164164 )
165165
166- # for debug
167166 # MACDを算出
168167 macd, macdsignal, _ = ta.MACD(
169168 closes,
@@ -172,9 +171,9 @@ class ExchangeRateInfo():
172171 signalperiod=self.__ns
173172 )
174173
175- # MACDの結果を端数処理(少数点以下5)
176- macd = np.around(macd, 5)
177- macdsignal = np.around(macdsignal, 5)
174+ # MACDの結果を端数処理(少数点以下6)
175+ macd = np.around(macd, 6)
176+ macdsignal = np.around(macdsignal, 6)
178177
179178 # for debug
180179 for i in range(-4, 0, 1):
@@ -183,28 +182,6 @@ class ExchangeRateInfo():
183182 )
184183 logger.debug(msg)
185184
186- # 最新bidを暫定終わり値としてclosesに追加
187- # closes = np.append(closes, self.__get_latest_bid())
188-
189- # MACDを算出
190- # macd, macdsignal, _ = ta.MACD(
191- # closes,
192- # fastperiod=self.__n1,
193- # slowperiod=self.__n2,
194- # signalperiod=self.__ns
195- # )
196-
197- # MACDの結果を端数処理(少数点以下4)
198- # macd = np.around(macd, 4)
199- # macdsignal = np.around(macdsignal, 4)
200-
201- # asum_macd = macd[-1]
202- # asum_macdsig = macdsignal[-1]
203- # msg = (
204- # f'Assumption MACD: {asum_macd}, Signal: {asum_macdsig} .'
205- # )
206- # logger.debug(msg)
207-
208185 # 指標判定
209186 if self.__crossover(macd, macdsignal) and macd[-1] < 0.0:
210187 # GoldenCross 上昇転換サイン
@@ -214,22 +191,24 @@ class ExchangeRateInfo():
214191 # DeadCross 降下転換サイン
215192 s.technical_indicator = DEF.TECHNICAL_DEAD_CROSS
216193 msg = 'Technical Indicator: DeadCross.'
217- elif macd[-1] > macdsignal[-1] and macd[-1] < 0.0:
218- # 弱い上昇トレンド
219- s.technical_indicator = DEF.TECHNICAL_UPTREND
220- msg = 'Technical Indicator: Weak Uptrend.'
221- elif macd[-1] > macdsignal[-1] and macd[-1] > 0.0:
222- # 強い上昇トレンド
223- s.technical_indicator = DEF.TECHNICAL_UPTREND
224- msg = 'Technical Indicator: Strong Uptrend.'
225- elif macd[-1] < macdsignal[-1] and macd[-1] > 0.0:
226- # 弱い降下トレンド
227- s.technical_indicator = DEF.TECHNICAL_DOWNTREND
228- msg = 'Technical Indicator: Weak Downtrand.'
229- elif macd[-1] < macdsignal[-1] and macd[-1] < 0.0:
230- # 強い降下トレンド
231- s.technical_indicator = DEF.TECHNICAL_DOWNTREND
232- msg = 'Technical Indicator: Strong Downtrand.'
194+ elif macd[-1] > macdsignal[-1]:
195+ if macd[-1] < 0.0:
196+ # 弱い上昇トレンド
197+ s.technical_indicator = DEF.TECHNICAL_UPTREND
198+ msg = 'Technical Indicator: Weak Uptrend.'
199+ else:
200+ # 強い上昇トレンド
201+ s.technical_indicator = DEF.TECHNICAL_UPTREND
202+ msg = 'Technical Indicator: Strong Uptrend.'
203+ elif macd[-1] < macdsignal[-1]:
204+ if macd[-1] > 0.0:
205+ # 弱い降下トレンド
206+ s.technical_indicator = DEF.TECHNICAL_DOWNTREND
207+ msg = 'Technical Indicator: Weak Downtrand.'
208+ else:
209+ # 強い降下トレンド
210+ s.technical_indicator = DEF.TECHNICAL_DOWNTREND
211+ msg = 'Technical Indicator: Strong Downtrand.'
233212 else:
234213 # いずれにも該当しない
235214 s.technical_indicator = DEF.TECHNICAL_UNCHANGED