Revision | d21bada40c06056e353dca42cdcecc742753d8f6 (tree) |
---|---|
Time | 2023-02-22 21:41:00 |
Author | kazuhiro_kondow <simauma.circus@gmai...> |
Commiter | kazuhiro_kondow |
Backtestingの結果をsetting.iniに反映
main.py
並びを変更
position_mng
指標反転次にフラグをクリアする動作を修正
exchange_rate_info
MACDテクニカル判定を安定させる目的で修正を
加え続けているが正解がまだ見えない
いったん、角度評価についてパラメータが小数の時に
大きい角度を取っている様子がある
@@ -0,0 +1,32 @@ | ||
1 | +Processing time(sec): 4.0 | |
2 | +Start 2022-11-18 00:00... | |
3 | +End 2023-02-16 00:00... | |
4 | +Duration 90 days 00:00:00 | |
5 | +Exposure Time [%] 82.612554 | |
6 | +Equity Final [$] 9405.308164 | |
7 | +Equity Peak [$] 10478.629701 | |
8 | +Return [%] -5.946918 | |
9 | +Buy & Hold Return [%] -4.777882 | |
10 | +Return (Ann.) [%] -19.025605 | |
11 | +Volatility (Ann.) [%] 8.457869 | |
12 | +Sharpe Ratio 0.0 | |
13 | +Sortino Ratio 0.0 | |
14 | +Calmar Ratio 0.0 | |
15 | +Max. Drawdown [%] -11.023872 | |
16 | +Avg. Drawdown [%] -0.230081 | |
17 | +Max. Drawdown Duration 43 days 13:43:00 | |
18 | +Avg. Drawdown Duration 0 days 16:28:00 | |
19 | +# Trades 166 | |
20 | +Win Rate [%] 58.433735 | |
21 | +Best Trade [%] 1.149513 | |
22 | +Worst Trade [%] -1.187417 | |
23 | +Avg. Trade [%] -0.032828 | |
24 | +Max. Trade Duration 6 days 18:23:00 | |
25 | +Avg. Trade Duration 0 days 11:14:00 | |
26 | +Profit Factor 0.821075 | |
27 | +Expectancy [%] -0.031742 | |
28 | +SQN -1.010143 | |
29 | +_strategy MACDCross | |
30 | +_equity_curve ... | |
31 | +_trades Size Entry... | |
32 | +dtype: object |
@@ -0,0 +1,199 @@ | ||
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 | +# backtesting_bayes_optimize_case1.pyから | |
10 | +# 個々のパラメータを最適化してこちらで検証した結果 | |
11 | + | |
12 | +import talib as ta | |
13 | +from backtesting.lib import crossover | |
14 | +from backtesting import Backtest | |
15 | +from backtesting import Strategy | |
16 | +import pandas as pd | |
17 | +import datetime as dt | |
18 | +import pytz | |
19 | +import MetaTrader5 as mt5 | |
20 | +import numpy as np | |
21 | +from numpy import linalg as LA | |
22 | + | |
23 | +# 本日日付 | |
24 | +now = dt.datetime.now() | |
25 | +# 日本のtimezone | |
26 | +tz_local = pytz.timezone('Etc/GMT-9') | |
27 | +# OANDAサーバのtimezone | |
28 | +tz_oanda = pytz.timezone('Etc/GMT-2') | |
29 | + | |
30 | +local_to = dt.datetime( | |
31 | + now.year, | |
32 | + now.month, | |
33 | + now.day, | |
34 | + 0, | |
35 | + 0, | |
36 | + 0, | |
37 | + tzinfo=tz_local | |
38 | +) | |
39 | +local_from = local_to - dt.timedelta(days=90) | |
40 | + | |
41 | +rate_to = local_to.astimezone(tz_oanda) | |
42 | +rate_from = local_from.astimezone(tz_oanda) | |
43 | + | |
44 | +# レートを取得 | |
45 | +cp = 'USDJPY' | |
46 | +mt5.initialize() | |
47 | +rates = mt5.copy_rates_range(cp, mt5.TIMEFRAME_M1, rate_from, rate_to) | |
48 | + | |
49 | +df = pd.DataFrame(rates) | |
50 | + | |
51 | +# timeカラムをdatetime型に変換 | |
52 | +df.time = pd.to_datetime(df['time'], unit='s') | |
53 | +# timeカラムをindexに時系列インデックスとして割り当て | |
54 | +df.index = pd.DatetimeIndex(df.time, name='Date') | |
55 | +# インデックスのTimeZoneをUTCに設定 | |
56 | +df.index = df.index.tz_localize(dt.timezone.utc) | |
57 | +# インデックスのTimeZoneをLovalに変換 | |
58 | +df.index = df.index.tz_convert(tz_local) | |
59 | + | |
60 | +# DataFrameのカラム名をbacktesting向けに修正 | |
61 | +df = df.rename( | |
62 | + columns={ | |
63 | + "time": "Date", | |
64 | + "open": "Open", | |
65 | + "high": "High", | |
66 | + "low": "Low", | |
67 | + "close": "Close", | |
68 | + "tick_volume": "Volume", | |
69 | + "spread": "Spread", | |
70 | + "real_volume": "not_use", | |
71 | + } | |
72 | +) | |
73 | + | |
74 | +# 必要なカラムのみ取得 | |
75 | +data = df.loc[:, ['Open', 'High', 'Low', 'Close', 'Volume']] | |
76 | + | |
77 | + | |
78 | +def MACD(close, n1, n2, ns): | |
79 | + macd, macdsignal, macdhist = ta.MACD( | |
80 | + close, fastperiod=n1, slowperiod=n2, signalperiod=ns) | |
81 | + return macd, macdsignal | |
82 | + | |
83 | + | |
84 | +# 下記記事を参考にStrategyを修正 | |
85 | +# https://mmorley.hatenablog.com/entry/fx_backtesting01 | |
86 | + | |
87 | +class MACDCross(Strategy): | |
88 | + # 短期EMAの期間 | |
89 | + n1 = 18 | |
90 | + # 長期EMAの期間 | |
91 | + n2 = 41 | |
92 | + # シグナル(MACDのSMA)の期間 | |
93 | + ns = 24 | |
94 | + # angleの閾値 | |
95 | + crossover_angle = 3.794 | |
96 | + # 利益確定(円) | |
97 | + ProfitTaking = 1.428 | |
98 | + # 損切(円) | |
99 | + LossCut = 1.8 | |
100 | + | |
101 | + def init(self): | |
102 | + self.macd, self.macdsignal = self.I( | |
103 | + MACD, self.data.Close, self.n1, self.n2, self.ns) | |
104 | + | |
105 | + def vector_angle(self, u: np.ndarray, v: np.ndarray): | |
106 | + i = np.inner(u, v) | |
107 | + n = LA.norm(u) * LA.norm(v) | |
108 | + c = i / n | |
109 | + return np.rad2deg(np.arccos(np.clip(c, -1.0, 1.0))) | |
110 | + | |
111 | + # チャートデータの行ごとに呼び出される | |
112 | + # tp(take profit)利確する価格 | |
113 | + # sl(stop losst)損切りする価格 | |
114 | + def next(self): | |
115 | + # macdがsignalを上回った時 | |
116 | + if crossover(self.macd, self.macdsignal) and \ | |
117 | + self.vector_angle( | |
118 | + self.macd[-2:], | |
119 | + self.macdsignal[-2:] | |
120 | + ) > self.crossover_angle: | |
121 | + # 買いオーダー | |
122 | + self.buy( | |
123 | + tp=self.data.Close[-1] + self.ProfitTaking, | |
124 | + sl=self.data.Close[-1] - self.LossCut | |
125 | + ) | |
126 | + | |
127 | + # signalがmacdを上回った時 | |
128 | + elif crossover(self.macdsignal, self.macd) and \ | |
129 | + self.vector_angle( | |
130 | + self.macd[-2:], | |
131 | + self.macdsignal[-2:] | |
132 | + ) > self.crossover_angle: | |
133 | + # 売りオーダー | |
134 | + self.sell( | |
135 | + tp=self.data.Close[-1] - self.ProfitTaking, | |
136 | + sl=self.data.Close[-1] + self.LossCut | |
137 | + ) | |
138 | + | |
139 | + | |
140 | +# バックテストを設定 | |
141 | +bt = Backtest( | |
142 | + # チャートデータ | |
143 | + data, | |
144 | + # 売買戦略 | |
145 | + MACDCross, | |
146 | + # 最初の所持金 | |
147 | + cash=10000, | |
148 | + # 取引手数料(為替価格に対する倍率で指定、為替価格100円でcommission=0.0005なら0.05円) | |
149 | + # OANDAの場合0.3〜0.9銭=0.003~0.009円 | |
150 | + commission=0.00009, | |
151 | + # レバレッジ倍率の逆数(0.5で2倍レバレッジ) | |
152 | + margin=1.0, | |
153 | + # True:現在の終値で取引,False:次の時間の始値で取引 | |
154 | + trade_on_close=True | |
155 | +) | |
156 | + | |
157 | +s_time = dt.datetime.timestamp(dt.datetime.utcnow()) | |
158 | +# バックテスト実行 | |
159 | +output = bt.run() | |
160 | +e_time = dt.datetime.timestamp(dt.datetime.utcnow()) | |
161 | +# 経過時間を出力(秒) | |
162 | +p_time = round((e_time - s_time), 0) | |
163 | +print(f'Processing time(sec): {p_time}') | |
164 | + | |
165 | +# 実行結果(データ) | |
166 | +print(output) | |
167 | + | |
168 | +# Processing time(sec): 5.0 | |
169 | +# Start 2022-11-18 00:00... | |
170 | +# End 2023-02-16 00:00... | |
171 | +# Duration 90 days 00:00:00 | |
172 | +# Exposure Time [%] 97.433366 | |
173 | +# Equity Final [$] 12025.707282 | |
174 | +# Equity Peak [$] 12357.610885 | |
175 | +# Return [%] 20.257073 | |
176 | +# Buy & Hold Return [%] -4.777882 | |
177 | +# Return (Ann.) [%] 85.150565 | |
178 | +# Volatility (Ann.) [%] 22.785833 | |
179 | +# Sharpe Ratio 3.736996 | |
180 | +# Sortino Ratio 13.20781 | |
181 | +# Calmar Ratio 20.604035 | |
182 | +# Max. Drawdown [%] -4.132713 | |
183 | +# Avg. Drawdown [%] -0.136679 | |
184 | +# Max. Drawdown Duration 12 days 22:28:00 | |
185 | +# Avg. Drawdown Duration 0 days 04:29:00 | |
186 | +# # Trades 66 | |
187 | +# Win Rate [%] 78.787879 | |
188 | +# Best Trade [%] 1.289563 | |
189 | +# Worst Trade [%] -1.422667 | |
190 | +# Avg. Trade [%] 0.492818 | |
191 | +# Max. Trade Duration 12 days 18:25:00 | |
192 | +# Avg. Trade Duration 2 days 15:42:00 | |
193 | +# Profit Factor 2.825621 | |
194 | +# Expectancy [%] 0.497406 | |
195 | +# SQN 2.896036 | |
196 | +# _strategy MACDCross | |
197 | +# _equity_curve ... | |
198 | +# _trades Size EntryB... | |
199 | +# dtype: object |
@@ -45,3 +45,8 @@ u3 = np.array([0.007748, 0.007773]) | ||
45 | 45 | v3 = np.array([0.006698, 0.007639]) |
46 | 46 | print(vector_angle(u3, v3)) |
47 | 47 | # 3.6628990024599957 |
48 | + | |
49 | +u2 = np.array([-0.0295, -0.0293]) | |
50 | +v2 = np.array([-0.0283, -0.0291]) | |
51 | +print(vector_angle(u2, v2)) | |
52 | + |
@@ -1,8 +1,9 @@ | ||
1 | +import os | |
1 | 2 | import oandapyV20 |
2 | 3 | import oandapyV20.endpoints.forexlabs as labs |
3 | 4 | |
4 | - | |
5 | -client = oandapyV20.API(access_token=...) | |
5 | +token = os.getenv('OANDA_TOKEN') | |
6 | +client = oandapyV20.API(access_token=token) | |
6 | 7 | params = { |
7 | 8 | "instrument": "USD_JPY", |
8 | 9 | "period": 604800 |
@@ -26,3 +27,18 @@ params = { | ||
26 | 27 | r = labs.Calendar(params=params) |
27 | 28 | client.request(r) |
28 | 29 | print(r.response) |
30 | + | |
31 | +# oandapyV20.exceptions.V20Error: { | |
32 | +# "code" : 4, | |
33 | +# "message" : "The access token provided does not allow this request to be made", | |
34 | +# "moreInfo" : "http:\/\/developer.oanda.com\/docs\/v1\/authentication\/#overview" | |
35 | +# } | |
36 | +# 現状ではエラーとなってしまう | |
37 | + | |
38 | +# これは動作した | |
39 | +# curl -H "Content-Type: application/json" -H "Authorization: Bearer <token>" "https://api-fxtrade.oanda.com/v3/accounts" | |
40 | +# {"accounts":[{"id":"001-009-5378507-001","tags":[]},{"id":"001-009-5378507-002","tags":[]}]} | |
41 | + | |
42 | +# これはエラーが帰らないけどデータが無い様子 | |
43 | +# curl -H "Content-Type: application/json" -H "Authorization: Bearer <token>" "https://api-fxtrade.oanda.com/labs/v1/calendar?instrument=USD_JPY&period=2592000" | |
44 | +# [] |
@@ -36,17 +36,17 @@ Allowablespread = 0.01 | ||
36 | 36 | # 1銭は0.01円 |
37 | 37 | OpenMergin = 0.007 |
38 | 38 | # 利益確定(円) |
39 | -ProfitTaking = 1.5 | |
39 | +ProfitTaking = 0.15 | |
40 | 40 | # 損切(円) |
41 | -LossCut = 0.25 | |
41 | +LossCut = 0.265 | |
42 | 42 | |
43 | 43 | # テクニカル分析 |
44 | 44 | [Technical] |
45 | 45 | # 短期EMAの期間 |
46 | -FastEMAperiod = 35 | |
46 | +FastEMAperiod = 18 | |
47 | 47 | # 長期EMAの期間 |
48 | -SlowEMAperiod = 53 | |
48 | +SlowEMAperiod = 56 | |
49 | 49 | # シグナルの期間 |
50 | -Signalperiod = 18 | |
50 | +Signalperiod = 10 | |
51 | 51 | # 交差角度閾値 |
52 | -CrossingAngleThreshold = 1.54 | |
52 | +CrossingAngleThreshold = 0.576 |
@@ -68,7 +68,14 @@ class ExchangeRateInfo(): | ||
68 | 68 | 0, |
69 | 69 | count |
70 | 70 | ) |
71 | - return rates['close'] | |
71 | + | |
72 | + ret = rates['close'] | |
73 | + | |
74 | + # 最新bidを暫定closeとして追加 | |
75 | + tick = mt5.symbol_info_tick(self.__cp) | |
76 | + ret = np.append(ret, tick.bid) | |
77 | + | |
78 | + return ret | |
72 | 79 | |
73 | 80 | def __crossover(self, series1: np.ndarray, series2: np.ndarray) -> bool: |
74 | 81 | """指標値列の交差判定 |
@@ -171,9 +178,8 @@ class ExchangeRateInfo(): | ||
171 | 178 | s = Setting() |
172 | 179 | |
173 | 180 | # MACDテクニカル分析に必要なデータ件数 |
174 | - # mt5アプリの表示と数値の乖離があるので件数を増やしてみる | |
175 | - # count = (self.__n2 + self.__n1) * 20 | |
176 | - count = self.__ns * 20 | |
181 | + # 暫定でmacd_value_verification.pyから1000と推定 | |
182 | + count = 1000 | |
177 | 183 | |
178 | 184 | # 終値履歴を取得 |
179 | 185 | closes = self.__get_history_closes( |
@@ -189,50 +195,62 @@ class ExchangeRateInfo(): | ||
189 | 195 | ) |
190 | 196 | |
191 | 197 | # MACDの結果を端数処理(少数点以下6) |
198 | + # 結果は最後の二つを使う | |
192 | 199 | macd = np.around(macd, 4) |
193 | 200 | macdsignal = np.around(macdsignal, 4) |
194 | 201 | |
195 | - # 前回結果が未設定なら判定しない | |
196 | - if self.__previous_macd is None: | |
197 | - self.__previous_macd = macd[-1] | |
198 | - self.__previous_signal = macdsignal[-1] | |
199 | - s.technical_indicator = DEF.TECHNICAL_UNCHANGED | |
200 | - msg = 'Previous MACD result not set.' | |
201 | - logger.info(msg) | |
202 | - return | |
203 | - else: | |
204 | - macd[-2] = self.__previous_macd | |
205 | - macdsignal[-2] = self.__previous_signal | |
206 | - | |
207 | 202 | # for debug |
208 | - for i in range(-3, 0, 1): | |
203 | + logger.debug('MACD実測値') | |
204 | + for i in range(-6, 0, 1): | |
209 | 205 | msg = ( |
210 | 206 | f'num[{i}]: MACD: {macd[i]}, MACDSignal: {macdsignal[i]}' |
211 | 207 | ) |
212 | 208 | logger.debug(msg) |
213 | 209 | |
210 | + # 指標判定は最後の2データで行う | |
211 | + # macd = macd[-2:] | |
212 | + # macdsignal = macdsignal[-2:] | |
213 | + | |
214 | + # # 前回結果が未設定なら判定しない | |
215 | + # if self.__previous_macd is None: | |
216 | + # self.__previous_macd = macd[-1] | |
217 | + # self.__previous_signal = macdsignal[-1] | |
218 | + # s.technical_indicator = DEF.TECHNICAL_UNCHANGED | |
219 | + # msg = 'Previous MACD result not set.' | |
220 | + # logger.info(msg) | |
221 | + # return | |
222 | + # else: | |
223 | + # macd[-2] = self.__previous_macd | |
224 | + # macdsignal[-2] = self.__previous_signal | |
225 | + | |
226 | + # for debug | |
227 | + # logger.debug('MACD判定値') | |
228 | + # for i in range(-2, 0, 1): | |
229 | + # msg = ( | |
230 | + # f'num[{i}]: MACD: {macd[i]}, MACDSignal: {macdsignal[i]}' | |
231 | + # ) | |
232 | + # logger.debug(msg) | |
233 | + | |
214 | 234 | # 指標判定 |
215 | 235 | v_angle = self.__vector_angle(macd[-2:], macdsignal[-2:]) |
216 | 236 | msg = f'vector angle:{v_angle}' |
217 | 237 | logger.debug(msg) |
218 | - msg = f'macd vector angle:{v_angle}' | |
219 | 238 | |
220 | - if self.__crossover(macd, macdsignal) and \ | |
221 | - v_angle > self.__angle and \ | |
222 | - macd[-1] < 0.0: | |
239 | + msg = f'befor turning point:{s.turning_point}' | |
240 | + logger.debug(msg) | |
241 | + | |
242 | + if self.__crossover(macd[-2:], macdsignal[-2:]): | |
223 | 243 | logger.debug('Cross up.') |
224 | - if s.turning_point is not True: | |
244 | + if s.turning_point is not True and v_angle > self.__angle: | |
225 | 245 | # GoldenCross 上昇転換サイン |
226 | 246 | s.technical_indicator = DEF.TECHNICAL_GOLDEN_CROSS |
227 | 247 | s.turning_point = True |
228 | 248 | msg = 'Technical Indicator: GoldenCross.' |
229 | 249 | else: |
230 | 250 | logger.debug('Already judged goldencross.') |
231 | - elif self.__crossover(macdsignal, macd) and \ | |
232 | - v_angle > self.__angle and \ | |
233 | - macd[-1] > 0.0: | |
251 | + elif self.__crossover(macdsignal[-2:], macd[-2:]): | |
234 | 252 | logger.debug('Cross down.') |
235 | - if s.turning_point is not False: | |
253 | + if s.turning_point is not False and v_angle > self.__angle: | |
236 | 254 | # DeadCross 降下転換サイン |
237 | 255 | s.technical_indicator = DEF.TECHNICAL_DEAD_CROSS |
238 | 256 | s.turning_point = False |
@@ -251,11 +269,42 @@ class ExchangeRateInfo(): | ||
251 | 269 | # いずれにも該当しない |
252 | 270 | s.technical_indicator = DEF.TECHNICAL_UNCHANGED |
253 | 271 | msg = 'Technical Indicator: Unchanged.' |
272 | + | |
273 | + # 過去指標の再判定 | |
274 | + # 2023-02-22 02:17:04 num[-3]: MACD: 0.0278, MACDSignal: 0.0248 > | |
275 | + # 2023-02-22 02:17:04 num[-2]: MACD: 0.0287, MACDSignal: 0.0255 > ! | |
276 | + # 2023-02-22 02:17:04 num[-1]: MACD: 0.0293, MACDSignal: 0.0262 > ! | |
277 | + # 2023-02-22 02:18:04 num[-4]: MACD: 0.0278, MACDSignal: 0.0248 > | |
278 | + # 2023-02-22 02:18:04 num[-3]: MACD: 0.0259, MACDSignal: 0.025 > | |
279 | + # 2023-02-22 02:18:04 num[-2]: MACD: 0.0235, MACDSignal: 0.0248 < ! | |
280 | + # 2023-02-22 02:18:04 num[-1]: MACD: 0.0213, MACDSignal: 0.0241 < ! | |
281 | + # このような事象が発生するので転換サインが出てない場合に限り | |
282 | + # 過去指標(num[-2],num[-3])の再評価を行う | |
283 | + if s.technical_indicator == DEF.TECHNICAL_UPTREND or \ | |
284 | + s.technical_indicator == DEF.TECHNICAL_DOWNTREND or \ | |
285 | + s.technical_indicator == DEF.TECHNICAL_UNCHANGED: | |
286 | + if self.__crossover(macd[-3:-1], macdsignal[-3:-1]): | |
287 | + logger.debug('Re-evaluation Cross up.') | |
288 | + if s.turning_point is not True and v_angle > self.__angle: | |
289 | + # GoldenCross 上昇転換サイン | |
290 | + s.technical_indicator = DEF.TECHNICAL_GOLDEN_CROSS | |
291 | + s.turning_point = True | |
292 | + msg = 'Re-evaluation Technical Indicator: GoldenCross.' | |
293 | + elif self.__crossover(macdsignal[-3:-1], macd[-3:-1]): | |
294 | + logger.debug('Re-evaluation Cross down.') | |
295 | + if s.turning_point is not False and v_angle > self.__angle: | |
296 | + # DeadCross 降下転換サイン | |
297 | + s.technical_indicator = DEF.TECHNICAL_DEAD_CROSS | |
298 | + s.turning_point = False | |
299 | + msg = 'Re-evaluation Technical Indicator: DeadCross.' | |
254 | 300 | logger.info(msg) |
255 | 301 | |
302 | + msg = f'after turning point:{s.turning_point}' | |
303 | + logger.debug(msg) | |
304 | + | |
256 | 305 | # 今回MACD結果を退避 |
257 | - self.__previous_macd = macd[-1] | |
258 | - self.__previous_signal = macdsignal[-1] | |
306 | + # self.__previous_macd = macd[-1] | |
307 | + # self.__previous_signal = macdsignal[-1] | |
259 | 308 | |
260 | 309 | except Exception as e: |
261 | 310 | logger.error(e) |
@@ -65,9 +65,9 @@ def main(): | ||
65 | 65 | # PositionMngは長期ポジションに対応する |
66 | 66 | logger.debug("set schedule.") |
67 | 67 | schedule.every().minute.at(":00").do(em.execute) |
68 | - schedule.every().minute.at(":02").do(rt.execute) | |
69 | - schedule.every().minute.at(":04").do(pm.execute) | |
70 | - schedule.every().minute.at(":06").do(ac.execute) | |
68 | + schedule.every().minute.at(":02").do(ac.execute) | |
69 | + schedule.every().minute.at(":04").do(rt.execute) | |
70 | + schedule.every().minute.at(":06").do(pm.execute) | |
71 | 71 | schedule.every().minute.at(":08").do(tm.execute) |
72 | 72 | |
73 | 73 | logger.debug("start loop.") |
@@ -14,6 +14,8 @@ class PositionMng(): | ||
14 | 14 | # check_position |
15 | 15 | # ポジション確認 |
16 | 16 | # テクニカル指標を確認しポジションを解消する |
17 | + # ポジションが全くない状態でテクニカルフラグがOnなら | |
18 | + # フラグを初期化する | |
17 | 19 | |
18 | 20 | def __init__(self): |
19 | 21 | """initializer |
@@ -42,6 +44,10 @@ class PositionMng(): | ||
42 | 44 | if positions is None: |
43 | 45 | # 保有ポジションは無いとする |
44 | 46 | logger.info('No open position.') |
47 | + if s.turning_point is not None and \ | |
48 | + s.technical_indicator != DEF.TECHNICAL_GOLDEN_CROSS and \ | |
49 | + s.technical_indicator != DEF.TECHNICAL_DEAD_CROSS: | |
50 | + s.turning_point = None | |
45 | 51 | return |
46 | 52 | |
47 | 53 | # テクニカル指標を確認する |