この記事を読むと、次のことがわかるようになります。
・ロスカット(Stop Order)の有効性とデータによる裏付け
・固定のロスカットとトレイリングストップはどちらが良いのか
・ATRを基準にする場合、「2-ATR」「3-ATR」のどちらが良いのか
「ロスカットは必ず設定しなくてはならない――」
これは、投資を長く続けていくのなら絶対に必要なことです。
なぜなら、”絶対はなく、いつ何が起こるかわからない”のが「相場」だからです。
そんな「相場」の中、ロスカットの設定は”登山家の命綱”のようにトレーダーを守ってくれます。
そして、ロスカットと言っても様々なノウハウがあって、実際に運用するとなると何を採用して良いのか迷ってしまいます。そんなときは、確かなデータの裏付けがあると大変心強いものです。
最近、ボク自身のトレードルールを再考するにあたって行った「ロスカットに関する検証(バックテスト)」を、備忘録も兼ねてまとめました。
ロスカットとトレイリングストップの有効性を検証(バックテスト)
1.バックテストに使用したツールと価格データ
ここは過去に書いた記事と一緒なので、引用します。
使用したツール
バックテストには以下のツールを使用しました。
Python(Google Colaboratory)
Pythonを手軽に試したいなら、Google Colaboratoryがめちゃくちゃオススメです。Google Driveでドキュメントやスプレッドシートを作る感覚でPythonを試すことができます。今回のような、ちゃちゃっと検証したいときに非常に便利です。
使用した価格データ
価格データは以下を使用しました。
- 1分毎の価格データを含むcsvファイル
- 日経225
- MT4のhstファイル
- USDJPY、EURJPY、GBPJPY、AUDJPY、EURUSD、GBPUSD、AUDUSD
日経225は独自に保有しているもので、hstファイルはFXDDさんのものを使用しています。
引用元上位足を考慮した移動平均線のバックテスト|日経225 FX 4時間足
2.テストする手法
今回はロスカットの検証なので、エントリーやエグジットは以前のスキームを流用しています。前の記事を読んだことをある方は「2-1.今回のバックテストの目的」「2-4.決済2」「2-5.テストするパターン」をお読みください。
2-1.今回のバックテストの目的
ロスカットに関する以下の項目の有効性を検証する
- ロスカットは必要か
- 固定ロスカットとトレイリングストップ
- 固定ロスカットの有効な幅
- トレイリングストップの有効な幅
- ATRの数値には素直に従うべきか
2-2.エントリー
今回は、次の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日
また、移動平均のもみ合い時の「だまし」を軽減するために、小次郎講師による移動平均線大循環分析の「ステージ」の考えを用います。
引用元上位足を考慮した移動平均線のバックテスト|日経225 FX 4時間足
- 4時間足のトレンド
- EMA5とEMA20、EMA40の関係でステージを判断する
- 日足のトレンド
- 4時間足のEMA5とEMA120、EMA240の関係でステージを判断する
※ EMAは指数平滑移動平均線のこと、EMA5はローソク足5本のEMAを指す
※「ステージ」の詳細については、権利の関係がありそうなので本家の記事を御覧ください。また、本家では、単純にステージだけでエントリーやイグジットを判断するのではなく、ローソク足の形やもみ合い放れ等も考慮して判断するようです(つまり、本家はこの検証結果よりも良い成績になると思われる)
- 上昇トレンド
- ステージ6:早仕掛け、ステージ1:本仕掛け
- 下降トレンド
- ステージ3:早仕掛け、ステージ4:本仕掛け
2-3.決済1
決済1も以前と同じものですね。
決済1は、同じく小次郎講師による移動平均線大循環分析の「ステージ」の考えに基づくものです。主に、「利益確定」や、「トレンドがなくなったことを確認した損切り」の決済です。
今回のバックテストでは、ステージによる決済は以下で統一しています。
- EXIT1_CycleStage36
- 通常のパターン(エントリーが遅くなりがち)
買いエントリー(ステージ6か1)はステージ3で決済
売りエントリー(ステージ3か4)はステージ6で決済※「ステージ」の詳細については、権利の関係がありそうなので本家の記事を御覧ください。また、本家では、単純にステージだけでイグジットを判断するのではなく、形成されたトレンドの強弱等も考慮して判断するようです(つまり、本家はこの検証結果よりも良い成績になると思われる)
引用元上位足を考慮した移動平均線のバックテスト|日経225 FX 4時間足
2-4.決済2
今回の検証の最重要項目です。
まずは検証するパターンをご紹介し、その下でスキームの詳細を解説します。
決済2のパターン
EXIT2_none EXIT2_SO_Entry_3_UM EXIT2_SO_Entry_3_20 EXIT2_SO_Entry_2_UM EXIT2_SO_Entry_2_20 | EXIT2_SO_Close_3_UM EXIT2_SO_Close_2_20 EXIT2_SO_Close_3_UM EXIT2_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の数値には素直に従うべきか」を確認します。
※ 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 < 中間の値」のときは中間の値を使います。「なぜ、こんなことをするのか」については、次回の記事で解説したいと思います。
2-5.テストするパターン
ここまで解説してきたENTRYやFILTER、EXIT1、EXIT2を組み合わせた以下のパターンの検証を行いました。
ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_none ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_3_UM ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_3_20 ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_2_UM ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_2_20 ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_3_UM ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_3_20 ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_2_UM ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_2_20 ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_none ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_3_UM ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_3_20 ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_2_UM ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_2_20 ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_3_UM ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_3_20 ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_2_UM ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_2_20 |
3.バックテストの実施と考察
3-1.バックテストの関数を作成
ここが一番重要だったりするのですが、ものすごく長くなってしまうので割愛します。こちらのサイトのコードを参考に作成しました((´・ω・`;)ヒィィッ すいません「バックテストを試してみました」)
参考として、ストラテジー部分のみ掲載します。
Google Colab
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
# upper middle
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)
3-2.バックテストを実行
諸々の準備が整ったら、バックテストを実行します。
※ 各番号のストラテジーは以下の通り |
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
1 | none | none | 5932 | 29.99% | 2.908 | -1.14 | 444.313 | 2.55 | 0.074 |
2 | none | SO_Entry_3_UM | 5952 | 30.07% | 2.902 | -1.117 | 554.16 | 2.6 | 0.092 |
3 | none | SO_Entry_3_20 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
4 | none | SO_Entry_2_UM | 6059 | 30.07% | 2.878 | -1.078 | 686.305 | 2.67 | 0.111 |
5 | none | SO_Entry_2_20 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
6 | none | SO_Close_3_UM | 6323 | 30.97% | 2.775 | -1.111 | 593.478 | 2.5 | 0.092 |
7 | none | SO_Close_3_20 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
8 | none | SO_Close_2_UM | 7947 | 33.32% | 2.323 | -1.025 | 758.273 | 2.27 | 0.091 |
9 | none | SO_Close_2_20 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
10 | UpperCycle63 | none | 3573 | 33.81% | 3.069 | -1.398 | 406.167 | 2.2 | 0.113 |
11 | UpperCycle63 | SO_Entry_3_UM | 3630 | 33.25% | 3.072 | -1.359 | 436.712 | 2.26 | 0.115 |
12 | UpperCycle63 | SO_Entry_3_20 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
13 | UpperCycle63 | SO_Entry_2_UM | 3792 | 31.88% | 3.08 | -1.26 | 520.973 | 2.44 | 0.124 |
14 | UpperCycle63 | SO_Entry_2_20 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
15 | UpperCycle63 | SO_Close_3_UM | 3985 | 33.75% | 2.937 | -1.322 | 477.544 | 2.22 | 0.115 |
16 | UpperCycle63 | SO_Close_3_20 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
17 | UpperCycle63 | SO_Close_2_UM | 5286 | 35.36% | 2.415 | -1.142 | 674.762 | 2.11 | 0.116 |
18 | UpperCycle63 | SO_Close_2_20 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
金額にかかる項目はすべてそのときのATRで割った数値を使っています。そうすることで、すべての銘柄の検証結果を同じように扱うことができます。
3-3.ロスカットは設定した方が良いか?
まず、ロスカットを設定しないパターンの結果をみてみましょう。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
1 | none | none | 5932 | 29.99% | 2.908 | -1.14 | 444.313 | 2.55 | 0.074 |
10 | UpperCycle63 | none | 3573 | 33.81% | 3.069 | -1.398 | 406.167 | 2.2 | 0.113 |
次に、基本的な「固定ロスカット」を設定したパターンです。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
3 | none | SO_Entry_3_20 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
5 | none | SO_Entry_2_20 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
12 | UpperCycle63 | SO_Entry_3_20 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
14 | UpperCycle63 | SO_Entry_2_20 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
「累計損益」「期待値」ともに、すべてのパターンで上回っていますね。「3-ATR」よりも「2-ATR」の方が、成績が良くなる傾向がありそうです。
「ロスカットは設置したほうが良い」と言えそうです。
3-4.固定ロスカットとトレイリングストップ
さらに、基本的な「トレイリングストップ」を設定したパターンもみてみましょう。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
7 | none | SO_Close_3_20 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
9 | none | SO_Close_2_20 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
16 | UpperCycle63 | SO_Close_3_20 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
18 | UpperCycle63 | SO_Close_2_20 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
「ロスカットを設定しないパターン」より良い結果ですが、「固定ロスカット」と比較すると少し見劣りする結果になりました。
「固定ロスカット」と「トレイリングストップ」を比較すると、勝率は「トレイリングストップ」の方が良く、リスクリワード比率は「固定ロスカット」の方が良い傾向があります。この点から、「トレイリングストップ」は早くに”利確されてしまう”ことに問題がありそうです。
「単純なトレイリングストップよりも固定ロスカットのほうが良い」
と結論づけることができそうです。3-5.固定ロスカット幅は2-ATRか3-ATRか
次は、「固定ロスカット」の幅の比較をします。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
3 | none | SO_Entry_3_20 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
5 | none | SO_Entry_2_20 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
12 | UpperCycle63 | SO_Entry_3_20 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
14 | UpperCycle63 | SO_Entry_2_20 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
「3-ATR」よりも「2-ATR」の方が良い結果になっています。マイナス方向に「2-ATR」進んだエントリーは失敗と判断して良さそうです。
3-6.トレイリングストップの幅は2-ATRか3-ATRか
「トレイリングストップ」の幅も確認してみます。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
7 | none | SO_Close_3_20 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
9 | none | SO_Close_2_20 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
16 | UpperCycle63 | SO_Close_3_20 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
18 | UpperCycle63 | SO_Close_2_20 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
「固定ロスカット」と違い、「2-ATR」よりも「3-ATR」の方が良い結果になりました。「固定ロスカット」の結果を踏まえると、「3 -ATR」の方がトレンドのノイズにかかりづらいと考えることができそうです。
これらの結果から、「エントリー後は2-ATRの固定ロスカット、トレンドは3-ATRのトレイリングストップとすると、さらに良い成績になる」という仮説が立ちそうです。
3-7.ATRの数値には素直に従うべきか
最後に「Upper Middle ATR」について確認します。
まずは「固定ロスカット」の「ATR20」「UM-ATR」についてみてみます。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
3 | none | SO_Entry_3_20 | 5962 | 30.24% | 3.859 | -1.452 | 932.711 | 2.66 | 0.154 |
5 | none | SO_Entry_2_20 | 6256 | 29.56% | 3.803 | -1.35 | 1106.664 | 2.82 | 0.173 |
12 | UpperCycle63 | SO_Entry_3_20 | 3684 | 32.82% | 4.099 | -1.746 | 682.254 | 2.35 | 0.172 |
14 | UpperCycle63 | SO_Entry_2_20 | 4044 | 30.07% | 4.092 | -1.501 | 837.318 | 2.73 | 0.18 |
2 | none | SO_Entry_3_UM | 5952 | 30.07% | 2.902 | -1.117 | 554.16 | 2.6 | 0.092 |
4 | none | SO_Entry_2_UM | 6059 | 30.07% | 2.878 | -1.078 | 686.305 | 2.67 | 0.111 |
11 | UpperCycle63 | SO_Entry_3_UM | 3630 | 33.25% | 3.072 | -1.359 | 436.712 | 2.26 | 0.115 |
13 | UpperCycle63 | SO_Entry_2_UM | 3792 | 31.88% | 3.08 | -1.26 | 520.973 | 2.44 | 0.124 |
思ったより大きな違いがでました。通常の「ATR20」の方(素直に従った方)が良い結果になりました。
念のため「トレイリングストップ」も確認してみます。
FILTER | EXIT2 | 取引回数 | 勝率 | 平均利益 /atr | 平均損失 /atr | 累計損益 /atr | RR比率 | 期待値 /atr | |
7 | none | SO_Close_3_20 | 6850 | 31.55% | 3.411 | -1.387 | 887.364 | 2.46 | 0.127 |
9 | none | SO_Close_2_20 | 10048 | 35.10% | 2.474 | -1.188 | 1090.301 | 2.08 | 0.098 |
16 | UpperCycle63 | SO_Close_3_20 | 4463 | 33.72% | 3.564 | -1.593 | 697.842 | 2.24 | 0.146 |
18 | UpperCycle63 | SO_Close_2_20 | 6954 | 35.71% | 2.566 | -1.261 | 880.775 | 2.04 | 0.106 |
6 | none | SO_Close_3_UM | 6323 | 30.97% | 2.775 | -1.111 | 593.478 | 2.5 | 0.092 |
8 | none | SO_Close_2_UM | 7947 | 33.32% | 2.323 | -1.025 | 758.273 | 2.27 | 0.091 |
15 | UpperCycle63 | SO_Close_3_UM | 3985 | 33.75% | 2.937 | -1.322 | 477.544 | 2.22 | 0.115 |
17 | UpperCycle63 | SO_Close_2_UM | 5286 | 35.36% | 2.415 | -1.142 | 674.762 | 2.11 | 0.116 |
これも同様ですね。通常の「ATR20」の方が良い成績です。
ということは、通常の「ATR20」の方が良いという結論になりそうです――と言いたいところですが、実は、これについては新たな仮説がでてきました。
ボクのトレードでは、ポジションサイジングの計算にATRを使っています。つまり、ATRの大小で取引量が変わり、取引量が変わるということは損益にも影響がでます。ということは、単純な「勝率」「RR比率」「期待値」だけでは、不十分で判断することができないのです。
これは、このまま次回の記事のテーマとしたいと思います。
3-8.銘柄ごとの損益曲線
このグラフを見ると、トレードが「大数の法則」で成り立っているということや「正規分布をコントロールすることで成績を良くしていくことができる」ということを強く感じます。








3-9.ストラテジーごとの損益曲線


















4.まとめ
若干の次回への宿題が残りましたが、おおむね今回のバックテストの目的はクリアできたと思います。
ロスカットは設定した方が良く、固定ロスカットなら2-ATR、トレイリングストップなら3-ATRの方が良いですね。今回のバックテストでは、トレイリングストップよりも固定ロスカットの方が良い結果になりました。ただ、固定ロスカットとトレイリングストップの良し悪しは工夫次第の面もあると思います。
注意点
ちなみに、これらの結果は4時間足のものです。トレードする時間足を変えると、これらの結果もガラッと変わることがありますので十分ご注意ください。
取引回数としてのサンプルは十分、リーマンショックの期間も含まれているので、そこそこ参考になる数字だとは思います。しかし、銘柄数や年数のサンプルとしては、正直ちょっと不十分です。銘柄や年の変化は想像以上にトレード結果に影響を及ぼしますので。
また、バックテストには万全を期していますが、結果の完全性や手法を用いた際の利益を保証するものではありません。予めご了承ください。
5.「わずか数分で検証できる!バックテストのテンプレート」をプレゼント

このバックテストの記事を読む方は、きっと自分でもバックテストをしてみたいはず!
ということで、この記事を一番下(ここ)まで読んでくださった”あなた”に、数分で導入することができるバックテストのテンプレートをプレゼントいたします。
このテンプレートには、こんな特徴があります。
- 数分で導入できる(Googleのアカウントが必要)
- 簡単操作(セルを上から実行していくだけ)
- 価格データを準備する必要なし(含まれています)
- 「資金管理(サイジング)が成績に及ぼす影響のバックテスト」のバックテストを完全再現
- 長期フィルターの有無による効果の検証
- リスク管理の有無による効果の検証
- 資金管理を含めたバックテスト
- テスト結果をExcelファイルで書き出すことができる
- テスト結果をグラフ化して確認することができる
ざっとこんなところでしょうか。必要なのはメールアドレスのご登録だけです!
※ メルマガで行うのは、ほとんどがブログ更新のお知らせです。面白い、もしくは役に立つツールができたらお知らせすることもありますが、本業が忙しいのでせいぜい年に数回です。
※ 使用方法がわからない方はこの記事の最後にあるコメント欄からお問い合わせください。できる限りお答えします。コードの細かい部分も、ご質問いただければ出し惜しみせずお答えするつもりです!
数分で検証できる!バックテストのテンプレート(Google Colaboratory)
誰でも、もっとも簡単にバックテストができる Google Colaboratory テンプレート