ロスカットとトレイリングストップの有効性を検証|日経225 FX 4時間足

Posted on July 27th, 2018Updated on October 30th, 2020
ロスカットとトレイリングストップの有効性を検証|日経225 FX 4時間足

※ この記事は最終更新日から4年以上が経過しています。

どんな記事

この記事を読むと、次のことがわかるようになります。

  • ロスカット(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_UMSO_Close_3_UM
SO_Entry_3_20SO_Close_3_20
SO_Entry_2_UMSO_Close_2_UM
SO_Entry_2_20SO_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」で算出する。

言葉で書くとややこしいので、次のグラフをご覧いただくのが良いと思います。

ATR Upper Middle ATR

上がATR20、下がUM-ATRです。UM-ATRは、「ATR20 > 過去1800本最高値と最安値の中間」のときはATR20を、「ATR20 < 中間の値」のときは中間の値を使います。「なぜ、こんなことをするのか」については、次回の記事で解説したいと思います。

テストするパターン

ここまで解説してきたENTRYやFILTER、EXIT1、EXIT2を組み合わせた以下のパターンの検証を行いました。

EntryFilterExit1Exit2
1Cycle63noneCycle36none
2Cycle63noneCycle36SO_Entry_3_UM
3Cycle63noneCycle36SO_Entry_3_20
4Cycle63noneCycle36SO_Entry_2_UM
5Cycle63noneCycle36SO_Entry_2_20
6Cycle63noneCycle36SO_Close_3_UM
7Cycle63noneCycle36SO_Close_3_20
8Cycle63noneCycle36SO_Close_2_UM
9Cycle63noneCycle36SO_Close_2_20
10Cycle63UpperCycle63Cycle36none
11Cycle63UpperCycle63Cycle36SO_Entry_3_UM
12Cycle63UpperCycle63Cycle36SO_Entry_3_20
13Cycle63UpperCycle63Cycle36SO_Entry_2_UM
14Cycle63UpperCycle63Cycle36SO_Entry_2_20
15Cycle63UpperCycle63Cycle36SO_Close_3_UM
16Cycle63UpperCycle63Cycle36SO_Close_3_20
17Cycle63UpperCycle63Cycle36SO_Close_2_UM
18Cycle63UpperCycle63Cycle36SO_Close_2_20

バックテストの実施と考察

バックテストの関数を作成

ここが一番重要だったりするのですが、ものすごく長くなってしまうので割愛します。こちらのサイトのコードを参考に作成しました((´・ω・`;)ヒィィッ すいません「バックテストを試してみました」

参考として、ストラテジー部分のみ掲載します。

GoogleColab
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)

バックテストを実行

諸々の準備が整ったら、バックテストを実行します。

EntryFilterExit1Exit2
1Cycle63noneCycle36none
2Cycle63noneCycle36SO_Entry_3_UM
3Cycle63noneCycle36SO_Entry_3_20
4Cycle63noneCycle36SO_Entry_2_UM
5Cycle63noneCycle36SO_Entry_2_20
6Cycle63noneCycle36SO_Close_3_UM
7Cycle63noneCycle36SO_Close_3_20
8Cycle63noneCycle36SO_Close_2_UM
9Cycle63noneCycle36SO_Close_2_20
10Cycle63UpperCycle63Cycle36none
11Cycle63UpperCycle63Cycle36SO_Entry_3_UM
12Cycle63UpperCycle63Cycle36SO_Entry_3_20
13Cycle63UpperCycle63Cycle36SO_Entry_2_UM
14Cycle63UpperCycle63Cycle36SO_Entry_2_20
15Cycle63UpperCycle63Cycle36SO_Close_3_UM
16Cycle63UpperCycle63Cycle36SO_Close_3_20
17Cycle63UpperCycle63Cycle36SO_Close_2_UM
18Cycle63UpperCycle63Cycle36SO_Close_2_20
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
1593229.99%2.908-1.14444.3132.550.074
2595230.07%2.902-1.117554.162.60.092
3596230.24%3.859-1.452932.7112.660.154
4605930.07%2.878-1.078686.3052.670.111
5625629.56%3.803-1.351106.6642.820.173
6632330.97%2.775-1.111593.4782.50.092
7685031.55%3.411-1.387887.3642.460.127
8794733.32%2.323-1.025758.2732.270.091
91004835.10%2.474-1.1881090.3012.080.098
10357333.81%3.069-1.398406.1672.20.113
11363033.25%3.072-1.359436.7122.260.115
12368432.82%4.099-1.746682.2542.350.172
13379231.88%3.08-1.26520.9732.440.124
14404430.07%4.092-1.501837.3182.730.18
15398533.75%2.937-1.322477.5442.220.115
16446333.72%3.564-1.593697.8422.240.146
17528635.36%2.415-1.142674.7622.110.116
18695435.71%2.566-1.261880.7752.040.106

金額にかかる項目はすべてそのときのATRで割った数値を使っています。そうすることで、すべての銘柄の検証結果を同じように扱うことができます。

ロスカットは設定した方が良いか?

まず、ロスカットを設定しないパターンの結果をみてみましょう。

EntryFilterExit1Exit2
1Cycle63noneCycle36none
10Cycle63UpperCycle63Cycle36none
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
1593229.99%2.908-1.14444.3132.550.074
10357333.81%3.069-1.398406.1672.20.113

次に、基本的な「固定ロスカット」を設定したパターンです。

EntryFilterExit1Exit2
3Cycle63noneCycle36SO_Entry_3_20
5Cycle63noneCycle36SO_Entry_2_20
12Cycle63UpperCycle63Cycle36SO_Entry_3_20
14Cycle63UpperCycle63Cycle36SO_Entry_2_20
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
3596230.24%3.859-1.452932.7112.660.154
5625629.56%3.803-1.351106.6642.820.173
12368432.82%4.099-1.746682.2542.350.172
14404430.07%4.092-1.501837.3182.730.18

「累計損益」「期待値」ともに、すべてのパターンで上回っていますね。「3-ATR」よりも「2-ATR」の方が、成績が良くなる傾向がありそうです。

ロスカットは設置したほうが良い」と言えそうです。

固定ロスカットとトレイリングストップ

さらに、基本的な「トレイリングストップ」を設定したパターンもみてみましょう。

EntryFilterExit1Exit2
7Cycle63noneCycle36SO_Close_3_20
9Cycle63noneCycle36SO_Close_2_20
16Cycle63UpperCycle63Cycle36SO_Close_3_20
18Cycle63UpperCycle63Cycle36SO_Close_2_20
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
7685031.55%3.411-1.387887.3642.460.127
91004835.10%2.474-1.1881090.3012.080.098
16446333.72%3.564-1.593697.8422.240.146
18695435.71%2.566-1.261880.7752.040.106

「ロスカットを設定しないパターン」より良い結果ですが、「固定ロスカット」と比較すると少し見劣りする結果になりました。

「固定ロスカット」と「トレイリングストップ」を比較すると、勝率は「トレイリングストップ」の方が良く、リスクリワード比率は「固定ロスカット」の方が良い傾向があります。この点から、「トレイリングストップ」は 早くに〝利確されてしまう〟 ことに問題がありそうです。

単純なトレイリングストップよりも固定ロスカットのほうが良い」と結論づけることができそうです。

固定ロスカット幅は2-ATRか3-ATRか

次は、「固定ロスカット」の幅の比較をします。

EntryFilterExit1Exit2
3Cycle63noneCycle36SO_Entry_3_20
5Cycle63noneCycle36SO_Entry_2_20
12Cycle63UpperCycle63Cycle36SO_Entry_3_20
14Cycle63UpperCycle63Cycle36SO_Entry_2_20
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
3596230.24%3.859-1.452932.7112.660.154
5625629.56%3.803-1.351106.6642.820.173
12368432.82%4.099-1.746682.2542.350.172
14404430.07%4.092-1.501837.3182.730.18

「3-ATR」よりも「2-ATR」の方が良い結果 になっています。マイナス方向に「2-ATR」進んだエントリーは失敗と判断して良さそうです。

トレイリングストップの幅は2-ATRか3-ATRか

「トレイリングストップ」の幅も確認してみます。

EntryFilterExit1Exit2
7Cycle63noneCycle36SO_Close_3_20
9Cycle63noneCycle36SO_Close_2_20
16Cycle63UpperCycle63Cycle36SO_Close_3_20
18Cycle63UpperCycle63Cycle36SO_Close_2_20
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
7685031.55%3.411-1.387887.3642.460.127
91004835.10%2.474-1.1881090.3012.080.098
16446333.72%3.564-1.593697.8422.240.146
18695435.71%2.566-1.261880.7752.040.106

「固定ロスカット」と違い、「2-ATR」よりも「3-ATR」の方が良い結果 になりました。「固定ロスカット」の結果を踏まえると、「3 -ATR」の方がトレンドのノイズにかかりづらいと考えることができそうです。

これらの結果から、「エントリー後は2-ATRの固定ロスカット、トレンドは3-ATRのトレイリングストップとすると、さらに良い成績になる」という仮説が立ちそうです。

ATRの数値には素直に従うべきか

最後に「Upper Middle ATR」について確認します。
まずは「固定ロスカット」の「ATR20」「UM-ATR」についてみてみます。

EntryFilterExit1Exit2
3Cycle63noneCycle36SO_Entry_3_20
5Cycle63noneCycle36SO_Entry_2_20
12Cycle63UpperCycle63Cycle36SO_Entry_3_20
14Cycle63UpperCycle63Cycle36SO_Entry_2_20
2Cycle63noneCycle36SO_Entry_3_UM
4Cycle63noneCycle36SO_Entry_2_UM
11Cycle63UpperCycle63Cycle36SO_Entry_3_UM
13Cycle63UpperCycle63Cycle36SO_Entry_2_UM
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
3596230.24%3.859-1.452932.7112.660.154
5625629.56%3.803-1.351106.6642.820.173
12368432.82%4.099-1.746682.2542.350.172
14404430.07%4.092-1.501837.3182.730.18
2595230.07%2.902-1.117554.162.60.092
4605930.07%2.878-1.078686.3052.670.111
11363033.25%3.072-1.359436.7122.260.115
13379231.88%3.08-1.26520.9732.440.124

思ったより大きな違いがでました。通常の「ATR20」の方(素直に従った方)が良い結果になりました。

念のため「トレイリングストップ」も確認してみます。

EntryFilterExit1Exit2
7Cycle63noneCycle36SO_Close_3_20
9Cycle63noneCycle36SO_Close_2_20
16Cycle63UpperCycle63Cycle36SO_Close_3_20
18Cycle63UpperCycle63Cycle36SO_Close_2_20
6Cycle63noneCycle36SO_Close_3_UM
8Cycle63noneCycle36SO_Close_2_UM
15Cycle63UpperCycle63Cycle36SO_Close_3_UM
17Cycle63UpperCycle63Cycle36SO_Close_2_UM
取引回数勝率平均利益/atr平均損失/atr累計損益/atrRR比率期待値/atr
7685031.55%3.411-1.387887.3642.460.127
91004835.10%2.474-1.1881090.3012.080.098
16446333.72%3.564-1.593697.8422.240.146
18695435.71%2.566-1.261880.7752.040.106
6632330.97%2.775-1.111593.4782.50.092
8794733.32%2.323-1.025758.2732.270.091
15398533.75%2.937-1.322477.5442.220.115
17528635.36%2.415-1.142674.7622.110.116

これも同様ですね。通常の「ATR20」の方が良い成績です。

ということは、通常の「ATR20」の方が良いという結論になりそうです――と言いたいところですが、実は、これについては新たな仮説がでてきました。

ボクのトレードでは、ポジションサイジングの計算にATRを使っています。つまり、ATRの大小で取引量が変わり、取引量が変わるということは損益にも影響がでます。ということは、単純な「勝率」「RR比率」「期待値」だけでは、不十分で判断することができない のです。

これは、このまま次回の記事のテーマとしたいと思います。

銘柄ごとの損益曲線

このグラフを見ると、トレードが「大数の法則」で成り立っているということや「正規分布をコントロールすることで成績を良くしていくことができる」ということを強く感じます。

バックテスト 結果 日経225(Nikkei225) バックテスト 結果 米ドル/円(USDJPY) バックテスト 結果 ユーロ/円(EURJPY) バックテスト 結果 ポンド/円(GBPJPY) バックテスト 結果 豪ドル/円(AUDJPY) バックテスト 結果 ユーロ/米ドル(EURUSD) バックテスト 結果 ポンド/米ドル(GBPUSD) バックテスト 結果 豪ドル/米ドル(AUDUSD)

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

バックテスト 結果 1 バックテスト 結果 2 バックテスト 結果 3 バックテスト 結果 4 バックテスト 結果 5 バックテスト 結果 6 バックテスト 結果 7 バックテスト 結果 8 バックテスト 結果 9 バックテスト 結果 10 バックテスト 結果 11 バックテスト 結果 12 バックテスト 結果 13 バックテスト 結果 14 バックテスト 結果 15 バックテスト 結果 16 バックテスト 結果 17 バックテスト 結果 18

まとめ

若干の次回への宿題が残りましたが、おおむね今回のバックテストの目的はクリアできたと思います。

ロスカットは設定した方が良く、固定ロスカットなら2-ATR、トレイリングストップなら3-ATRの方が良いですね。今回のバックテストでは、トレイリングストップよりも固定ロスカットの方が良い結果になりました。ただ、固定ロスカットとトレイリングストップの良し悪しは工夫次第の面もあると思います。

注意点

ちなみに、これらの結果は4時間足のものです。トレードする時間足を変えると、これらの結果もガラッと変わることがありますので十分ご注意ください。

取引回数としてのサンプルは十分、リーマンショックの期間も含まれているので、そこそこ参考になる数字だとは思います。しかし、銘柄数や年数のサンプルとしては、正直ちょっと不十分です。銘柄や年の変化は想像以上にトレード結果に影響を及ぼしますので。

また、バックテストには万全を期していますが、結果の完全性や手法を用いた際の利益を保証するものではありません。予めご了承ください。

yuya takahashi

タカハシ / 11年目の兼業投資家

投資やプログラミング、動画コンテンツの撮影・制作・編集などが得意。更新のお知らせは、LINE、メールで行っています。

このブログと筆者についてご質問はこちら

  • 記事をシェア
© Investment Tech Hack 2023.