どんな記事
この記事を読むと、次のことがわかるようになります。
- ロスカット(Stop Order)の有効性とデータによる裏付け
- 固定のロスカットとトレイリングストップはどちらが良いのか
- ATRを基準にする場合、「2-ATR」「3-ATR」のどちらが良いのか
「ロスカットは必ず設定しなくてはならない――」
これは、投資を長く続けていくのなら絶対に必要なことです。なぜなら、〝絶対はなく、いつ何が起こるかわからない〟のが「相場」 だからです。
そんな「相場」の中、ロスカットの設定は〝登山家の命綱〟のようにトレーダーを守ってくれます。
そして、ロスカットと言っても様々なノウハウがあって、実際に運用するとなると何を採用して良いのか迷ってしまいます。そんなときは、確かなデータの裏付けがあると大変心強いです。
最近、ボク自身のトレードルールを再考するにあたって行った「ロスカットに関する検証(バックテスト)」を、備忘録も兼ねてまとめました。
バックテストに使用したツールと価格データ
ここは過去に書いた記事と一緒なので、引用します。
使用したツール
前回同様、バックテストには以下のツールを使用しました。
Python(Google Colaboratory)
Pythonを手軽に試したいなら、Google Colaboratoryがめちゃくちゃオススメです。Google Driveでドキュメントやスプレッドシートを作る感覚でPythonを試すことができます。今回のような、ちゃちゃっと検証したいときに非常に便利です。
使用した価格データ
こちらも前回と同様です。
1分毎の価格データを含むcsvファイル
日経225
MT4のhstファイル
USDJPY、EURJPY、GBPJPY、AUDJPY、EURUSD、GBPUSD、AUDUSD
日経225は独自に保有しているもので、hstファイルはFXDDさんのものを使用しています。
テストする手法
今回はロスカットの検証なので、エントリーやエグジットも以前のロジックを一部流用しています。
今回のバックテストの目的
ロスカットに関する以下の項目の有効性を検証する
- ロスカットは必要か
- 固定ロスカットとトレイリングストップ
- 固定ロスカットの有効な幅
- トレイリングストップの有効な幅
- ATRの数値には素直に従うべきか
エントリー
今回は、次の2パターンのエントリーでバックテストを行いました。
ENTRY_Cycle63_FILTER_none
通常のパターン
ENTRY_Cycle63_FILTER_UpperCycle63
上位足のフィルター有りのパターン
「ENTRY」は4時間足のステージで、「FILTER」は日足相当のステージです。
日足のトレンドを、4時間足のエントリーのフィルターとする
日足のトレンドを確認すると言っても毎回チャートを切り替えるのは手間なので、次の考え方を用います。以下は4時間足であっても、120本の移動平均線は20日相当、240本は40日相当になるということです。
- 4時間 ✕ 6 = 1日(24時間)
- 4時間 ✕ 120 = 20日
- 4時間 ✕ 240 = 40日
また、移動平均のもみ合い時の「だまし」を軽減するために、小次郎講師による移動平均線大循環分析の「ステージ」の考えを用います。
4時間足のトレンド
EMA5とEMA20、EMA40の関係でステージを判断する日足のトレンド
4時間足のEMA5とEMA120、EMA240の関係でステージを判断する上昇トレンド
ステージ6:早仕掛け、ステージ1:本仕掛け下降トレンド
ステージ3:早仕掛け、ステージ4:本仕掛け
決済1
決済1も以前と同じものです。
決済1は、同じく小次郎講師による移動平均線大循環分析の「ステージ」の考えに基づくものです。主に、「利益確定」や、「トレンドがなくなったことを確認した損切り」の決済です。
今回のバックテストでは、ステージによる決済は以下で統一しています。
EXIT1_CycleStage36
通常のパターン(エントリーが遅くなりがち)
買いエントリー(ステージ6か1)はステージ3で決済
売りエントリー(ステージ3か4)はステージ6で決済
決済2
今回の検証の最重要項目です。
まずは検証するパターンをご紹介し、その下でスキームの詳細を解説します。
決済2(EXIT2)のパターン
none | |
SO_Entry_3_UM | SO_Close_3_UM |
SO_Entry_3_20 | SO_Close_3_20 |
SO_Entry_2_UM | SO_Close_2_UM |
SO_Entry_2_20 | SO_Close_2_20 |
「none」とは
「none」は、ロスカットもトレイリングストップも設定しないパターンです。「ロスカットは必要か」を確認します。
「SO_Entry_N_」「SO_Close_N_」の意味
- 「固定ロスカットとトレイリングストップ」どちらが良いのか
- 「固定ロスカットの有効な幅」
- 「トレイリングストップの有効な幅」
を、確認します。
SO_Entry_N_
エントリーの価格から「N ✕ ATR」マイナス方向にロスカットを設置(固定)
例)SO_Entry_2_:エントリーから2-ATRマイナス方向
SO_Close_N_
「N ✕ ATR」マイナス方向にロスカットを設置し、終値がプラス方向に推移するごとに追随させる
例)SO_Close_3_:3-ATRマイナス方向に設置し、プラス方向に追随
※「SO_Entry_」「SO_Close_」の後ろに記載している数値を「N」とする
「_20」「_UM」とは
この2つのパターンで「ATRの数値には素直に従うべきか」を確認します。
_20(ATR20)
ロスカットやトレイリングストップを「N ✕ 20日ATR」で算出する。
_UM(Upper Middle of ATR20)
ロスカットやトレイリングストップの算出に使用するATRを、過去1800本さかのぼった20日ATRの最高値と最安値の中間以上の値とし(UM-ATR)、「N ✕ UM-ATR」で算出する。
言葉で書くとややこしいので、次のグラフをご覧いただくのが良いと思います。
上がATR20、下がUM-ATRです。UM-ATRは、「ATR20 > 過去1800本最高値と最安値の中間」のときはATR20を、「ATR20 < 中間の値」のときは中間の値を使います。「なぜ、こんなことをするのか」については、次回の記事で解説したいと思います。
テストするパターン
ここまで解説してきたENTRYやFILTER、EXIT1、EXIT2を組み合わせた以下のパターンの検証を行いました。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
1 | Cycle63 | none | Cycle36 | none |
2 | Cycle63 | none | Cycle36 | SO_Entry_3_UM |
3 | Cycle63 | none | Cycle36 | SO_Entry_3_20 |
4 | Cycle63 | none | Cycle36 | SO_Entry_2_UM |
5 | Cycle63 | none | Cycle36 | SO_Entry_2_20 |
6 | Cycle63 | none | Cycle36 | SO_Close_3_UM |
7 | Cycle63 | none | Cycle36 | SO_Close_3_20 |
8 | Cycle63 | none | Cycle36 | SO_Close_2_UM |
9 | Cycle63 | none | Cycle36 | SO_Close_2_20 |
10 | Cycle63 | UpperCycle63 | Cycle36 | none |
11 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_UM |
12 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_20 |
13 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_UM |
14 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_20 |
15 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_UM |
16 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_20 |
17 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_UM |
18 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_20 |
バックテストの実施と考察
バックテストの関数を作成
ここが一番重要だったりするのですが、ものすごく長くなってしまうので割愛します。こちらのサイトのコードを参考に作成しました((´・ω・`;)ヒィィッ すいません「バックテストを試してみました」)
参考として、ストラテジー部分のみ掲載します。
class Strategy_CycleEMA_Base(StrategyBase) :
def __init__(self ,symbol ,np_arr_dic ,df) :
StrategyBase.__init__(self ,symbol ,np_arr_dic ,df)
self.ema5 = ta.EMA(self.c ,5)
self.ema20 = ta.EMA(self.c ,20)
self.ema40 = ta.EMA(self.c ,40)
self.ema120 = ta.EMA(self.c ,120)
self.ema240 = ta.EMA(self.c ,240)
self.stage = np.array(list(map(lambda s ,m ,l :
1 if s > m and m > l else \
2 if m > s and s > l else \
3 if m > l and l > s else \
4 if l > m and m > s else \
5 if l > s and s > m else \
6 if s > l and l > m else \
np.nan
,self.ema5 ,self.ema20 ,self.ema40)))
self.upper_stage = np.array(list(map(lambda s ,m ,l :
1 if s > m and m > l else \
2 if m > s and s > l else \
3 if m > l and l > s else \
4 if l > m and m > s else \
5 if l > s and s > m else \
6 if s > l and l > m else \
np.nan
,self.ema5 ,self.ema120 ,self.ema240)))
self.atrL ,self.atrH = ta.MINMAX(self.atr20 ,1800)
self.atrM = (self.atrH + self.atrL) / 2
self.atrUM = np.array(list(map(lambda a ,b :
a if a > b else \
b if a < b else \
a if np.isnan(b)==True and np.isnan(a)==False else \
b if np.isnan(a)==True and np.isnan(b)==False else \
np.nan
,self.atr20 ,self.atrM)))
def Base_record_mgmt(self ,i) :
Pos = self.count_pos()
self.count_days = np.nan if Pos==0 else self.count_days + 1
b4_EntrySig = False if Pos==0 else abs(self.mgmt[-1]["EntrySig"])==1
MTM = 0 if Pos==0 else ((self.o[i] - self.entry_price) * self.l_s)
b4_SO_Close = np.nan if Pos==0 else self.mgmt[-1]["SO_Close"]
b4_SO_Entry = np.nan if Pos==0 else self.mgmt[-1]["SO_Entry"]
pre_SO_Close = np.nan if Pos==0 and not b4_EntrySig else self.c[i-1] - self.atr[i-1] * self.ATR_N * self.l_s
pre_SO_Entry = np.nan if Pos==0 and not b4_EntrySig else self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s
SO_Close = np.nan if Pos==0 and not b4_EntrySig else pre_SO_Close if b4_EntrySig or (self.l_s==1 and pre_SO_Close > b4_SO_Close) or (self.l_s==-1 and pre_SO_Close < b4_SO_Close) else b4_SO_Close
SO_Entry = np.nan if Pos==0 and not b4_EntrySig else pre_SO_Entry if b4_EntrySig or (self.l_s==1 and pre_SO_Entry > b4_SO_Entry) or (self.l_s==-1 and pre_SO_Entry < b4_SO_Entry) else b4_SO_Entry
PL = 0 if len(self.hst)==0 else self.hst[-1]['profit'] if self.mgmt[-1]['ExitSig']==1 else 0
self.mgmt.append({
'Time' : self.df.index[i]
,'Open' : self.o[i]
,'High' : self.h[i]
,'Low' : self.l[i]
,'Close' : self.c[i]
,'ATR' : self.atr[i]
,'EMA5' : self.ema5[i]
,'EMA20' : self.ema20[i]
,'EMA40' : self.ema40[i]
,'EMA120' : self.ema120[i]
,'EMA240' : self.ema240[i]
,'Pos' : Pos
,'CountDays' : self.count_days
,'EntrySig' : 1 if self.opbuy else -1 if self.opsell else 0
,'ExitSig' : 1 if self.clbuy or self.clsell else 0
,'L/S' : self.l_s
,'EntryPrice' : self.entry_price
,'MTM' : MTM
,'PL' : PL
,'Stage' : self.stage[i]
,'UpperStage' : self.upper_stage[i]
,'SO' : self.SO
,'SO_Close' : SO_Close
,'SO_Entry' : SO_Entry
})
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_none(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
self.clbuy = any([clbuy_1 ,self.opsell])
if self.count_sell() > 0 :
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
self.clsell = any([clsell_1 ,self.opbuy])
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_3_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_3_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_2_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_2_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_3_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_3_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_2_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_2_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = True
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = True
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_none(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
self.clbuy = any([clbuy_1 ,self.opsell])
if self.count_sell() > 0 :
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
self.clsell = any([clsell_1 ,self.opbuy])
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_3_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_3_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_2_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_2_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Entry'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Entry
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Entry = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Entry']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Entry
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_3_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_3_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 3
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_2_UM(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atrUM
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
class ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_2_20(Strategy_CycleEMA_Base) :
def __init__(self ,symbol ,np_arr_dic ,df) :
Strategy_CycleEMA_Base.__init__(self ,symbol ,np_arr_dic ,df)
self.atr = self.atr20
self.ATR_N = 2
def onTick(self ,i) :
if self.is_nan[i] : return
if any([self.opbuy ,self.opsell ,self.clbuy ,self.clsell]) :
if self.SO :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.mgmt[-2]['SO_Close'] ,ATR=self.atr[i-1])
self.SO = False
else :
self.order_proccesing(i ,Entry_Price=self.c[i-1] ,Exit_Price=self.c[i-1] ,ATR=self.atr[i-1])
opbuy = opsell = clbuy_1 = clbuy_2 = clsell_1 = clsell_2 = False
buy_filter = self.upper_stage[i] == 6 or self.upper_stage[i] == 1
buy_sig = self.stage[i] == 6 or self.stage[i] == 1
sell_filter = self.upper_stage[i] == 3 or self.upper_stage[i] == 4
sell_sig = self.stage[i] == 3 or self.stage[i] == 4
self.opbuy = buy_filter and buy_sig and self.count_buy()==0
self.opsell = sell_filter and sell_sig and self.count_sell()==0
if self.count_buy() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clbuy_1 = self.stage[i-1] < 3 and (self.stage[i] == 3 or self.stage[i] == 4)
clbuy_2 = self.l[i] < SO_Close
self.clbuy = any([clbuy_1 ,clbuy_2 ,self.opsell])
self.SO = clbuy_2
if self.count_sell() > 0 :
SO_Close = self.entry_price - self.atr[i-1] * self.ATR_N * self.l_s if self.count_days==0 else self.mgmt[-1]['SO_Close']
clsell_1 = (self.stage[i-1] < 6 and self.stage[i-1] >= 4) and (self.stage[i] == 6 or self.stage[i] == 1)
clsell_2 = self.h[i] > SO_Close
self.clsell = any([clsell_1 ,clsell_2 ,self.opbuy])
self.SO = clsell_2
self.Base_record_mgmt(i)
バックテストを実行
諸々の準備が整ったら、バックテストを実行します。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
1 | Cycle63 | none | Cycle36 | none |
2 | Cycle63 | none | Cycle36 | SO_Entry_3_UM |
3 | Cycle63 | none | Cycle36 | SO_Entry_3_20 |
4 | Cycle63 | none | Cycle36 | SO_Entry_2_UM |
5 | Cycle63 | none | Cycle36 | SO_Entry_2_20 |
6 | Cycle63 | none | Cycle36 | SO_Close_3_UM |
7 | Cycle63 | none | Cycle36 | SO_Close_3_20 |
8 | Cycle63 | none | Cycle36 | SO_Close_2_UM |
9 | Cycle63 | none | Cycle36 | SO_Close_2_20 |
10 | Cycle63 | UpperCycle63 | Cycle36 | none |
11 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_UM |
12 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_20 |
13 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_UM |
14 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_20 |
15 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_UM |
16 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_20 |
17 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_UM |
18 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_20 |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
1 | 5932 | 29.99% | 2.908 | -1.14 | 444.313 | 2.55 | 0.074 |
2 | 5952 | 30.07% | 2.902 | -1.117 | 554.16 | 2.6 | 0.092 |
3 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
4 | 6059 | 30.07% | 2.878 | -1.078 | 686.305 | 2.67 | 0.111 |
5 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
6 | 6323 | 30.97% | 2.775 | -1.111 | 593.478 | 2.5 | 0.092 |
7 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
8 | 7947 | 33.32% | 2.323 | -1.025 | 758.273 | 2.27 | 0.091 |
9 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
10 | 3573 | 33.81% | 3.069 | -1.398 | 406.167 | 2.2 | 0.113 |
11 | 3630 | 33.25% | 3.072 | -1.359 | 436.712 | 2.26 | 0.115 |
12 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
13 | 3792 | 31.88% | 3.08 | -1.26 | 520.973 | 2.44 | 0.124 |
14 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
15 | 3985 | 33.75% | 2.937 | -1.322 | 477.544 | 2.22 | 0.115 |
16 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
17 | 5286 | 35.36% | 2.415 | -1.142 | 674.762 | 2.11 | 0.116 |
18 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
金額にかかる項目はすべてそのときのATRで割った数値を使っています。そうすることで、すべての銘柄の検証結果を同じように扱うことができます。
ロスカットは設定した方が良いか?
まず、ロスカットを設定しないパターンの結果をみてみましょう。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
1 | Cycle63 | none | Cycle36 | none |
10 | Cycle63 | UpperCycle63 | Cycle36 | none |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
1 | 5932 | 29.99% | 2.908 | -1.14 | 444.313 | 2.55 | 0.074 |
10 | 3573 | 33.81% | 3.069 | -1.398 | 406.167 | 2.2 | 0.113 |
次に、基本的な「固定ロスカット」を設定したパターンです。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
3 | Cycle63 | none | Cycle36 | SO_Entry_3_20 |
5 | Cycle63 | none | Cycle36 | SO_Entry_2_20 |
12 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_20 |
14 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_20 |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
3 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
5 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
12 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
14 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
「累計損益」「期待値」ともに、すべてのパターンで上回っていますね。「3-ATR」よりも「2-ATR」の方が、成績が良くなる傾向がありそうです。
「ロスカットは設置したほうが良い」と言えそうです。
固定ロスカットとトレイリングストップ
さらに、基本的な「トレイリングストップ」を設定したパターンもみてみましょう。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
7 | Cycle63 | none | Cycle36 | SO_Close_3_20 |
9 | Cycle63 | none | Cycle36 | SO_Close_2_20 |
16 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_20 |
18 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_20 |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
7 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
9 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
16 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
18 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
「ロスカットを設定しないパターン」より良い結果ですが、「固定ロスカット」と比較すると少し見劣りする結果になりました。
「固定ロスカット」と「トレイリングストップ」を比較すると、勝率は「トレイリングストップ」の方が良く、リスクリワード比率は「固定ロスカット」の方が良い傾向があります。この点から、「トレイリングストップ」は 早くに〝利確されてしまう〟 ことに問題がありそうです。
「単純なトレイリングストップよりも固定ロスカットのほうが良い」と結論づけることができそうです。
固定ロスカット幅は2-ATRか3-ATRか
次は、「固定ロスカット」の幅の比較をします。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
3 | Cycle63 | none | Cycle36 | SO_Entry_3_20 |
5 | Cycle63 | none | Cycle36 | SO_Entry_2_20 |
12 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_20 |
14 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_20 |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
3 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
5 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
12 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
14 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
「3-ATR」よりも「2-ATR」の方が良い結果 になっています。マイナス方向に「2-ATR」進んだエントリーは失敗と判断して良さそうです。
トレイリングストップの幅は2-ATRか3-ATRか
「トレイリングストップ」の幅も確認してみます。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
7 | Cycle63 | none | Cycle36 | SO_Close_3_20 |
9 | Cycle63 | none | Cycle36 | SO_Close_2_20 |
16 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_20 |
18 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_20 |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
7 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
9 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
16 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
18 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
「固定ロスカット」と違い、「2-ATR」よりも「3-ATR」の方が良い結果 になりました。「固定ロスカット」の結果を踏まえると、「3 -ATR」の方がトレンドのノイズにかかりづらいと考えることができそうです。
これらの結果から、「エントリー後は2-ATRの固定ロスカット、トレンドは3-ATRのトレイリングストップとすると、さらに良い成績になる」という仮説が立ちそうです。
ATRの数値には素直に従うべきか
最後に「Upper Middle ATR」について確認します。
まずは「固定ロスカット」の「ATR20」「UM-ATR」についてみてみます。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
3 | Cycle63 | none | Cycle36 | SO_Entry_3_20 |
5 | Cycle63 | none | Cycle36 | SO_Entry_2_20 |
12 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_20 |
14 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_20 |
2 | Cycle63 | none | Cycle36 | SO_Entry_3_UM |
4 | Cycle63 | none | Cycle36 | SO_Entry_2_UM |
11 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_3_UM |
13 | Cycle63 | UpperCycle63 | Cycle36 | SO_Entry_2_UM |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
3 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
5 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
12 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
14 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
2 | 5952 | 30.07% | 2.902 | -1.117 | 554.16 | 2.6 | 0.092 |
4 | 6059 | 30.07% | 2.878 | -1.078 | 686.305 | 2.67 | 0.111 |
11 | 3630 | 33.25% | 3.072 | -1.359 | 436.712 | 2.26 | 0.115 |
13 | 3792 | 31.88% | 3.08 | -1.26 | 520.973 | 2.44 | 0.124 |
思ったより大きな違いがでました。通常の「ATR20」の方(素直に従った方)が良い結果になりました。
念のため「トレイリングストップ」も確認してみます。
Entry | Filter | Exit1 | Exit2 | |
---|---|---|---|---|
7 | Cycle63 | none | Cycle36 | SO_Close_3_20 |
9 | Cycle63 | none | Cycle36 | SO_Close_2_20 |
16 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_20 |
18 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_20 |
6 | Cycle63 | none | Cycle36 | SO_Close_3_UM |
8 | Cycle63 | none | Cycle36 | SO_Close_2_UM |
15 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_3_UM |
17 | Cycle63 | UpperCycle63 | Cycle36 | SO_Close_2_UM |
取引回数 | 勝率 | 平均利益/atr | 平均損失/atr | 累計損益/atr | RR比率 | 期待値/atr | |
---|---|---|---|---|---|---|---|
7 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
9 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
16 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
18 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
6 | 6323 | 30.97% | 2.775 | -1.111 | 593.478 | 2.5 | 0.092 |
8 | 7947 | 33.32% | 2.323 | -1.025 | 758.273 | 2.27 | 0.091 |
15 | 3985 | 33.75% | 2.937 | -1.322 | 477.544 | 2.22 | 0.115 |
17 | 5286 | 35.36% | 2.415 | -1.142 | 674.762 | 2.11 | 0.116 |
これも同様ですね。通常の「ATR20」の方が良い成績です。
ということは、通常の「ATR20」の方が良いという結論になりそうです――と言いたいところですが、実は、これについては新たな仮説がでてきました。
ボクのトレードでは、ポジションサイジングの計算にATRを使っています。つまり、ATRの大小で取引量が変わり、取引量が変わるということは損益にも影響がでます。ということは、単純な「勝率」「RR比率」「期待値」だけでは、不十分で判断することができない のです。
これは、このまま次回の記事のテーマとしたいと思います。
銘柄ごとの損益曲線
このグラフを見ると、トレードが「大数の法則」で成り立っているということや「正規分布をコントロールすることで成績を良くしていくことができる」ということを強く感じます。
3-9.ストラテジーごとの損益曲線