資金管理(サイジング)が成績に及ぼす影響のバックテスト|日経225 FX 4時間足

資金管理(サイジング)が成績に及ぼす影響のバックテスト|日経225 FX 4時間足

このバックテストでは、次のことがわかります。

サイジングの有効性とデータによる裏付け
基準にするATRは加工したほうが良いのか
単利の資金管理を含めるとどうなるのか

今回のバックテストを行うにあたって、これまでのバックテストに単利の資金管理を含める開発を行いました。サイジングの検証は、資金管理を含めないと意味をなさないからです。

手前味噌ですが、この辺りから「チャートを眺めて行うバックテストではできない領域」に入ってくると思います。以前まで行っていた検証に比べるとまだまだ機能が劣りますが(鋭意開発中)、何より計算が速い。機能をフルに盛り込んでも以前の100倍くらいの速さで行うことができそうです。楽しみ。

2018年8月19日 修正
3-3.値幅による損益の統計の記述を一部修正しました。

資金管理(サイジング)が成績に及ぼす影響のバックテスト

  1. バックテストに使用したツールと価格データ
  2. テストする手法
    1. 今回のバックテストの目的
    2. 開発にともなう変更点
    3. 資金管理(サイジング)
    4. エントリー
    5. 決済1
    6. 決済2
    7. テストするパターン
  3. バックテストの実施と考察
    1. バックテストの関数
    2. バックテストの実行と結果
    3. 値幅による損益の統計
    4. ATRによる資金管理(サイジング)は、バックテストを再現する要
    5. ATRの数値には素直に従うべきか(前回の宿題)
    6. 銘柄ごとの損益曲線
    7. ストラテジーごとの損益曲線
  4. まとめ
  5. プレゼント

1.バックテストに使用したツールと価格データ

google colaboratory

ここは過去に書いた記事とまったく一緒なので引用します。

使用したツール

バックテストには以下のツールを使用しました。

Python(Google Colaboratory

  • Pandas(価格データの整形・抽出)
  • Numpy(データの計算処理)
  • Ta-Lib(テクニカル分析)
  • Plotly(グラフ描画)
  • Matplotlib(グラフ描画)
  • datetime(日付の操作)
  • openpyxl(excelファイル関連)
  • tpdm

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-2.開発にともなう変更点」だけお読みください。

2-1.今回のバックテストの目的

今回のバックテストは以下を目的として行った

  • 資金管理を含めたバックテストの開発
  • ATRの数値には素直に従うべきか(前回の宿題)
  • 資金管理(サイジング)が成績に及ぼす影響の確認

目次

2-2.開発にともなう変更点

今回の開発にともなって生じたバックテストの変更点

  • 資金管理を含めたバックテストの導入
  • 検証の期間の変更
    これまでの検証期間は、元データが同一であるため「短期の手法の検証期間 > 長期の手法の検証期間」であったが、「長期の手法の検証期間」にあわせることとした
  • ティックごとのオペレーションの調整
    先々の開発を見据えて1ティックごとのオペレーションを調整。それにともない売買回数や成績に若干の差異が生じたが、結果の本質には影響がないと考える(改めて入念な確認をしたため、今回のほうが正しい)

目次

2-3.資金管理(サイジング)

今回のバックテストから導入する資金管理(サイジング)です。単利で、すべてのパターンで同一としています。

  • 元金:1000万円
  • 1エントリーのサイズ:1日のリスクが元金の1%(10万円)となるように

「UnitValue / ( ATR * Lot * Currency)」で1ティックごとに算出しています。

UnitValue:資金の1%(10万円)
ATR:そのティックのATR(ATR20かUM-ATR)
Currency:クロス円の場合は1、ドルストレートの場合はそのティックのUSDJPY

これだけじゃわからない方は以前の記事「どんな市場でも使える資金管理とリスク管理」をお読みください。

目次

2-4.エントリー

今回は、次の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の関係でステージを判断する

※ EMAは指数平滑移動平均線のこと、EMA5はローソク足5本のEMAを指す

「ステージ」の詳細については、権利の関係がありそうなので本家の記事を御覧ください。また、本家では、単純にステージだけでエントリーやイグジットを判断するのではなく、ローソク足の形やもみ合い放れ等も考慮して判断するようです(つまり、本家はこの検証結果よりも良い成績になると思われる)

上昇トレンド
ステージ6:早仕掛け、ステージ1:本仕掛け
下降トレンド
ステージ3:早仕掛け、ステージ4:本仕掛け
引用元上位足を考慮した移動平均線のバックテスト|日経225 FX 4時間足

目次

2-5.決済1

決済1も以前と同じものですね。

決済1は、同じく小次郎講師による移動平均線大循環分析の「ステージ」の考えに基づくものです。主に、「利益確定」や、「トレンドがなくなったことを確認した損切り」の決済です。

今回のバックテストでは、ステージによる決済は以下で統一しています。

EXIT1_CycleStage36
通常のパターン(エントリーが遅くなりがち)
買いエントリー(ステージ6か1)はステージ3で決済
売りエントリー(ステージ3か4)はステージ6で決済

「ステージ」の詳細については、権利の関係がありそうなので本家の記事を御覧ください。また、本家では、単純にステージだけでイグジットを判断するのではなく、形成されたトレンドの強弱等も考慮して判断するようです(つまり、本家はこの検証結果よりも良い成績になると思われる)

バックテスト 決済
引用元上位足を考慮した移動平均線のバックテスト|日経225 FX 4時間足

目次

2-6.決済2

決済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」で算出する。

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

ATR Upper Middle ATR

上がATR20、下がUM-ATRです。UM-ATRは、「ATR20 > 過去1800本最高値と最安値の中間」のときはATR20を、「ATR20 < 中間の値」のときは中間の値を使います。

目次

2-7.テストするパターン

ここも前回と一緒ですね。

ここまで解説してきた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.バックテストの関数

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

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

Strategy_CycleEMA_Base(Google Colab)

class Strategy_CycleEMA_Base(StrategyBase) :
  
  def __init__(self ,symbol ,np_arr_dic ,df) :
    
    StrategyBase.__init__(self ,symbol ,np_arr_dic ,df)
    
    self.principal = 10000000
    self.unit_pct  = 0.01
    
    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)

    def calc_stage(s ,m ,l) : 
      return 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 ,s ,m ,l)))
                                      
    self.stage       = calc_stage(self.ema5 ,self.ema20  ,self.ema40)
    self.upper_stage = calc_stage(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)))
    
    self.is_nan = np.isnan(self.ema240)

    
  def management(self ,i ,Case=None) :
      
    first    = self.first_time
    not_nan  = not Case == 'is_nan'
    
    Lot      = Dict_Symbol[self.symbol]['lot']
    Currency = 1 if Dict_Symbol[self.symbol]['currency']=="" else self.np_arr_dic[self.symbol]['Close'][i-1]
    LS       = self.l_s
    b4asset  = np.nan if first else self.asset[i-1]
    b4mgmt   = np.nan if first else self.mgmt[i-1]
    ATR      = np.nan if first else self.atr[i-1]
    ATR_N    = self.atrN 
    Entry    = self.entry_price
    Close    = self.c[i-1]
    
    def mgmt_calc_unit() :
      if first            : self.mgmt[i]['Unit'] = np.nan
      elif Case=='is_nan' : self.mgmt[i]['Unit'] = b4mgmt['Unit']
      else :
        UnitValue      = b4asset['UnitValue'] if Case=='1st' else self.asset[i]['UnitValue']
        Unit           = round( UnitValue / ( ATR * Lot * Currency) )
        self.mgmt[i]['Unit'] = Unit if not_nan else b4mgmt['Unit']
    
    def mgmt_append() :
      if not_nan and not first :
        Amount          = b4mgmt["Amount"]
        self.count_nums = np.nan if Amount==0 else self.count_nums + 1
        b4_SO_Close     = np.nan if Amount==0 else b4mgmt["SO_Close"]
        b4_SO_Entry     = np.nan if Amount==0 else b4mgmt["SO_Entry"]
        pre_SO_Close    = np.nan if Amount==0 else Close - ATR * ATR_N * LS
        pre_SO_Entry    = np.nan if Amount==0 else Entry - ATR * ATR_N * LS
        SO_Close        = np.nan if Amount==0 else pre_SO_Close if (LS==1 and pre_SO_Close > b4_SO_Close) or (LS==-1 and pre_SO_Close < b4_SO_Close) else b4_SO_Close
        SO_Entry        = np.nan if Amount==0 else pre_SO_Entry if (LS==1 and pre_SO_Entry > b4_SO_Entry) or (LS==-1 and pre_SO_Entry < b4_SO_Entry) else b4_SO_Entry
      self.mgmt[i]['Time']         = self.df.index[i]
      self.mgmt[i]['Symol']        = self.symbol
      self.mgmt[i]['b4Open']       = np.nan if first else self.o[i-1]           if not_nan else b4mgmt['b4Close']
      self.mgmt[i]['b4High']       = np.nan if first else self.h[i-1]           if not_nan else b4mgmt['b4Close']
      self.mgmt[i]['b4Low']        = np.nan if first else self.l[i-1]           if not_nan else b4mgmt['b4Close']
      self.mgmt[i]['b4Close']      = np.nan if first else self.c[i-1]           if not_nan else b4mgmt['b4Close']
      self.mgmt[i]['b4ATR']        = np.nan if first else self.atr[i-1]         if not_nan else b4mgmt['b4ATR']
      self.mgmt[i]['b4EMA5']       = np.nan if first else self.ema5[i-1]        if not_nan else b4mgmt['b4EMA5']
      self.mgmt[i]['b4EMA20']      = np.nan if first else self.ema20[i-1]       if not_nan else b4mgmt['b4EMA20']
      self.mgmt[i]['b4EMA40']      = np.nan if first else self.ema40[i-1]       if not_nan else b4mgmt['b4EMA40']
      self.mgmt[i]['b4EMA120']     = np.nan if first else self.ema120[i-1]      if not_nan else b4mgmt['b4EMA120']
      self.mgmt[i]['b4EMA240']     = np.nan if first else self.ema240[i-1]      if not_nan else b4mgmt['b4EMA240']
      self.mgmt[i]['b4Stage']      = np.nan if first else self.stage[i-1]       if not_nan else b4mgmt['b4Stage']
      self.mgmt[i]['b4UpperStage'] = np.nan if first else self.upper_stage[i-1] if not_nan else b4mgmt['b4UpperStage']
      self.mgmt[i]['Amount']       = 0      if first else Amount                if not_nan else b4mgmt['Amount']
      self.mgmt[i]['CountNums']    = self.count_nums
      self.mgmt[i]['EntrySig']     = 0
      self.mgmt[i]['ExitSig']      = 0
      self.mgmt[i]['L/S']          = LS
      self.mgmt[i]['Lot']          = Lot
      self.mgmt[i]['EntryPrice']   = Entry
      self.mgmt[i]['ExitPrice']    = np.nan
      self.mgmt[i]['b4Currency']   = Currency
      self.mgmt[i]['SO']           = self.sosig
      self.mgmt[i]['SO_Close']     = np.nan if first else SO_Close if not_nan else b4mgmt['SO_Close']
      self.mgmt[i]['SO_Entry']     = np.nan if first else SO_Entry if not_nan else b4mgmt['SO_Entry']
      self.mgmt[i]['MTM_']         = 0
      self.mgmt[i]['MTM']          = 0
      self.mgmt[i]['PL_']          = 0
      self.mgmt[i]['PL']           = 0
    
    # TotalN LongN ShortN
    def asset_count_n() :
      pass
    
    def asset_append() :
      if not_nan and not first : 
        Total_PL    = self.mgmt[i]['PL']
        Total_MTM   = self.mgmt[i]['MTM']
        Cash        = b4asset['Cash'] + Total_PL
        Net         = Cash + Total_MTM
        MAX_Cash    = Cash if Cash > b4asset['MAX_Cash'] else b4asset['MAX_Cash']
        MAX_Net     = Net  if Net  > b4asset['MAX_Net']  else b4asset['MAX_Net']
        DD_Cash     = Cash - MAX_Cash
        DD_Net      = Net - MAX_Net
        DD_pct_Cash = DD_Cash / MAX_Cash
        DD_pct_Net  = DD_Net / MAX_Net
        UnitValue   = self.principal * self.unit_pct
      self.asset[i]['Time']        = self.df.index[i]
      self.asset[i]['Total_PL']    = 0              if first else Total_PL    if not_nan else b4asset['Total_PL']
      self.asset[i]['Total_MTM']   = 0              if first else Total_MTM   if not_nan else b4asset['Total_MTM']
      self.asset[i]['Cash']        = self.principal if first else Cash        if not_nan else b4asset['Cash']
      self.asset[i]['Net']         = self.principal if first else Net         if not_nan else b4asset['Net']
      self.asset[i]['MAX_Cash']    = self.principal if first else MAX_Cash    if not_nan else b4asset['MAX_Cash']
      self.asset[i]['MAX_Net']     = self.principal if first else MAX_Net     if not_nan else b4asset['MAX_Net']
      self.asset[i]['DD_Cash']     = 0              if first else DD_Cash     if not_nan else b4asset['DD_Cash']
      self.asset[i]['DD_Net']      = 0              if first else DD_Net      if not_nan else b4asset['DD_Net']
      self.asset[i]['DD_pct_Cash'] = 0              if first else DD_pct_Cash if not_nan else b4asset['DD_pct_Cash']
      self.asset[i]['DD_pct_Net']  = 0              if first else DD_pct_Net  if not_nan else b4asset['DD_pct_Net']
      self.asset[i]['UnitValue']   = self.principal * self.unit_pct if first else UnitValue if not_nan else b4asset['UnitValue']
    
    if Case=='is_nan' or first:
      mgmt_append()
      mgmt_calc_unit()
      asset_append()
      asset_count_n()
      # エントリーに2つ前のデータを使用する
      if first and not self.is_nan[i+1] : self.first_time = False
    
    elif Case=='1st' :
      mgmt_append()
      asset_count_n()
    
    elif Case=='2nd' :
      self.mark_to_market(i)
      asset_append()
      mgmt_calc_unit()
      asset_count_n()
      self.count_correl_risk(i)
    
      
  def entry_sig(self ,i) :
    if self.FILTER=='none' : 
      buy_filter = sell_filter = True
    elif self.FILTER=='UpperCycle63' :
      buy_filter  = self.mgmt[i]['b4UpperStage'] == 6 or self.mgmt[i]['b4UpperStage'] == 1
      sell_filter = self.mgmt[i]['b4UpperStage'] == 3 or self.mgmt[i]['b4UpperStage'] == 4
      
    buy_sig  = self.mgmt[i]['b4Stage'] == 6 or self.mgmt[i]['b4Stage'] == 1
    sell_sig = self.mgmt[i]['b4Stage'] == 3 or self.mgmt[i]['b4Stage'] == 4
    
    if   all([buy_filter  ,buy_sig  ,self.count_buy()==0])  : self.opsig = self.mgmt[i]['EntrySig'] = 1
    elif all([sell_filter ,sell_sig ,self.count_sell()==0]) : self.opsig = self.mgmt[i]['EntrySig'] = -1
  
  
  def exit_sig(self ,i) :
    self.sosig = np.nan

    if self.count_buy() > 0 :
      clbuy = self.mgmt[i-1]['b4Stage'] < 3 and ( self.mgmt[i]['b4Stage'] == 3 or self.mgmt[i]['b4Stage'] == 4 )
      if not self.EXIT2=='none' and self.mgmt[i]['b4Low'] < self.mgmt[i-1][self.EXIT2] : self.sosig = 1
      if any([clbuy ,self.sosig==1 ,self.opsig==-1]) : self.clsig = self.mgmt[i]['ExitSig'] = 1

    elif self.count_sell() > 0 :
      clsell = ( self.mgmt[i-1]['b4Stage'] < 6 and self.mgmt[i-1]['b4Stage'] >= 4 ) and ( self.mgmt[i]['b4Stage'] == 6 or self.mgmt[i]['b4Stage'] == 1 ) 
      if not self.EXIT2=='none' and self.mgmt[i]['b4High'] > self.mgmt[i-1][self.EXIT2] : self.sosig = 1
      if any([clsell ,self.sosig==1 ,self.opsig==1]) : self.clsig = self.mgmt[i]['ExitSig'] = 1
    

  def onTick_Base(self ,i) :
    self.append_dict(i)
    
    if self.is_nan[i] or self.first_time :
      self.management(i ,Case='is_nan')
      return
      
    self.management(i ,Case='1st')
    self.entry_sig(i)
    self.exit_sig(i)
    self.exit(i)
    # LO を導入したら使用する
    # self.entry(i ,Case='LO')
    self.management(i ,Case='2nd')
    self.entry(i)
    
  

Strategy(Google Colab)

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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 3
    self.EXIT2  = 'none'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 3
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 3
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 2
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 2
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 3
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 3
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 2
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 2
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'none'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 3
    self.EXIT2  = 'none'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 3
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 3
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 2
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 2
    self.EXIT2  = 'SO_Entry'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 3
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 3
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atrUM
    self.atrN   = 2
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(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.first_time = True
    # Setting
    self.opcl   = 'close'     #前日終値か当日始値か
    self.atr    = self.atr20
    self.atrN   = 2
    self.EXIT2  = 'SO_Close'
    self.FILTER = 'UpperCycle63'
  def onTick(self ,i) : self.onTick_Base(i)

    

目次

3-2.バックテストの実行と結果

諸々の準備が整ったら、バックテストを実行します。4分程度で計算できてしまいます。すごい。

run backtesting バックテストを実行

バックテストの結果

FILTER EXIT2 取引回数 勝率 平均利益
/atr
平均損失
/atr
累計損益
/atr
RR比率 期待値
/atr
1 none none 5387 30.02% 2.964 -1.153 453 2.57 0.083
2 none SO_Entry_3_UM 5411 29.88% 2.965 -1.137 490 2.61 0.089
3 none SO_Entry_3_20 5427 29.78% 4.013 -1.513 732 2.65 0.133
4 none SO_Entry_2_UM 5528 29.40% 2.958 -1.097 534 2.7 0.095
5 none SO_Entry_2_20 5749 28.21% 4.006 -1.394 755 2.87 0.129
6 none SO_Close_3_UM 5838 30.95% 2.815 -1.137 511 2.48 0.087
7 none SO_Close_3_20 6498 31.75% 3.435 -1.439 709 2.39 0.108
8 none SO_Close_2_UM 7589 33.31% 2.333 -1.046 607 2.23 0.080
9 none SO_Close_2_20 9925 34.79% 2.495 -1.211 778 2.06 0.078
10 UpperCycle63 none 3401 33.28% 3.107 -1.373 408 2.26 0.118
11 UpperCycle63 SO_Entry_3_UM 3459 32.70% 3.106 -1.347 382 2.31 0.109
12 UpperCycle63 SO_Entry_3_20 3521 32.15% 4.208 -1.757 572 2.39 0.161
13 UpperCycle63 SO_Entry_2_UM 3614 31.43% 3.105 -1.254 424 2.48 0.116
14 UpperCycle63 SO_Entry_2_20 3872 29.55% 4.183 -1.510 673 2.77 0.172
15 UpperCycle63 SO_Close_3_UM 3816 33.60% 2.940 -1.323 418 2.22 0.109
16 UpperCycle63 SO_Close_3_20 4384 33.85% 3.532 -1.611 570 2.19 0.130
17 UpperCycle63 SO_Close_2_UM 5184 35.03% 2.417 -1.143 539 2.11 0.104
18 UpperCycle63 SO_Close_2_20 7002 35.62% 2.548 -1.263 660 2.02 0.094

※ 各番号のストラテジーは以下の通り
1:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_none
2:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_3_UM
3:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_3_20
4:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_2_UM
5:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Entry_2_20
6:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_3_UM
7:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_3_20
8:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_2_UM
9:ENTRY_Cycle63__FILTER_none__EXIT1_Cycle36__EXIT2_SO_Close_2_20
10:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_none
11:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_3_UM
12:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_3_20
13:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_2_UM
14:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Entry_2_20
15:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_3_UM
16:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_3_20
17:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_2_UM
18:ENTRY_Cycle63__FILTER_UpperCycle63__EXIT1_Cycle36__EXIT2_SO_Close_2_20

結果を踏まえて、順番に解説していきます。

目次

3-3.値幅による損益の統計

まずは、値幅による損益の統計です。取引量やATRなどは一切関係なく、純粋な値幅です。日経225なら「100円獲った」とか、USDJPYなら「1.252円獲った」とか、そういうやつです。

値幅で考える場合は、銘柄に寄って呼び値がまったく違うので注意が必要です(日経:10円刻み、USDJPY:0.001円刻み、EURUSD:0.00001USD刻み)。つまり、同じように集計することができないのです。

ここではモデルケースとして、Nikkei225とEURJPYあたりで比較してみようと思います。まずはNikkei225です。

FILTER EXIT2 銘柄 取引回数
/共通
勝率
/共通
RR比率
/price
RR比率
/atr
1 none none Nikkei225 236 30.93% 2.19 2.55
2 none SO_Entry_3_UM Nikkei225 239 30.54% 2.14 2.48
3 none SO_Entry_3_20 Nikkei225 239 30.54% 2.17 2.49
4 none SO_Entry_2_UM Nikkei225 241 30.29% 2.25 2.62
5 none SO_Entry_2_20 Nikkei225 248 29.44% 2.31 2.61
6 none SO_Close_3_UM Nikkei225 252 29.76% 2.03 2.32
7 none SO_Close_3_20 Nikkei225 254 30.31% 2.01 2.36
8 none SO_Close_2_UM Nikkei225 274 31.39% 2.09 2.48
9 none SO_Close_2_20 Nikkei225 296 33.78% 1.91 2.25
10 UpperCycle63 none Nikkei225 163 31.29% 1.81 2.04
11 UpperCycle63 SO_Entry_3_UM Nikkei225 164 31.10% 1.81 2.05
12 UpperCycle63 SO_Entry_3_20 Nikkei225 164 31.10% 1.87 2.11
13 UpperCycle63 SO_Entry_2_UM Nikkei225 169 30.18% 2.02 2.29
14 UpperCycle63 SO_Entry_2_20 Nikkei225 175 29.71% 2.07 2.3
15 UpperCycle63 SO_Close_3_UM Nikkei225 175 30.86% 1.65 1.85
16 UpperCycle63 SO_Close_3_20 Nikkei225 177 32.77% 1.55 1.78
17 UpperCycle63 SO_Close_2_UM Nikkei225 193 31.61% 1.83 2.1
18 UpperCycle63 SO_Close_2_20 Nikkei225 211 34.60% 1.63 1.85

同じ銘柄とバックテストのパターンなので、当然、取引回数と勝率は同じ結果です。それに対してRR比率を比較すると、単なる値幅の「RR比率/price」に対して、すべてにおいて「RR比率/atr」の方が良い結果になっています。

次に、EURJPYも見てみましょう。

FILTER EXIT2 銘柄 取引回数
/共通
勝率
/共通
RR比率
/price
RR比率
/atr
1 none none EURJPY 721 31.35% 2.42 2.55
2 none SO_Entry_3_UM EURJPY 725 31.17% 2.44 2.58
3 none SO_Entry_3_20 EURJPY 726 31.13% 2.46 2.64
4 none SO_Entry_2_UM EURJPY 737 30.66% 2.53 2.68
5 none SO_Entry_2_20 EURJPY 767 29.07% 2.68 2.87
6 none SO_Close_3_UM EURJPY 787 32.27% 2.3 2.46
7 none SO_Close_3_20 EURJPY 887 33.15% 2.23 2.38
8 none SO_Close_2_UM EURJPY 1009 34.69% 2.13 2.25
9 none SO_Close_2_20 EURJPY 1381 36.13% 1.89 2
10 UpperCycle63 none EURJPY 456 33.55% 2.21 2.32
11 UpperCycle63 SO_Entry_3_UM EURJPY 460 33.26% 2.23 2.36
12 UpperCycle63 SO_Entry_3_20 EURJPY 473 32.35% 2.28 2.36
13 UpperCycle63 SO_Entry_2_UM EURJPY 483 31.68% 2.34 2.5
14 UpperCycle63 SO_Entry_2_20 EURJPY 520 29.81% 2.58 2.77
15 UpperCycle63 SO_Close_3_UM EURJPY 511 34.83% 2.08 2.23
16 UpperCycle63 SO_Close_3_20 EURJPY 590 35.59% 2.05 2.11
17 UpperCycle63 SO_Close_2_UM EURJPY 687 35.81% 2.04 2.17
18 UpperCycle63 SO_Close_2_20 EURJPY 970 36.80% 1.88 1.98

EURJPYも同様に、総じて「RR比率/atr」の方が良い結果になりました。

これは「もみ合い放れ」の利益が大きくなることが要因であると考えています(もみ合い → ATRが小さくなる → 取引量が多くなる → そのもみ合いから放れたときの利益が大きくなる)。

目次

3-4.ATRによる資金管理(サイジング)は、バックテストを再現する要

さて、次に資金管理を含めた統計を見ていきます。

FILTER EXIT2 取引回数 勝率 平均利益 平均損失 累計損益 RR比率 RR比率
/atr
期待値
1 none none 5387 30.02% 297,357 -115,931 44,577,933 2.56 2.57 8,124
2 none SO_Entry_3_UM 5411 29.88% 297,519 -114,416 47,909,574 2.6 2.61 8,685
3 none SO_Entry_3_20 5427 29.78% 407,273 -154,323 71,261,888 2.64 2.65 12,904
4 none SO_Entry_2_UM 5528 29.40% 296,688 -110,266 52,520,816 2.69 2.7 9,361
5 none SO_Entry_2_20 5749 28.21% 406,311 -141,872 74,666,019 2.86 2.87 12,790
6 none SO_Close_3_UM 5838 30.95% 282,781 -114,354 50,594,961 2.47 2.48 8,569
7 none SO_Close_3_20 6498 31.75% 349,242 -146,481 71,283,806 2.38 2.39 10,902
8 none SO_Close_2_UM 7589 33.31% 234,089 -105,087 60,141,557 2.23 2.23 7,897
9 none SO_Close_2_20 9925 34.79% 252,189 -122,581 77,705,989 2.06 2.06 7,805
10 UpperCycle63 none 3401 33.28% 311,440 -137,887 40,237,406 2.26 2.26 11,669
11 UpperCycle63 SO_Entry_3_UM 3459 32.70% 311,251 -135,446 37,248,808 2.3 2.31 10,612
12 UpperCycle63 SO_Entry_3_20 3521 32.15% 426,048 -178,382 56,844,312 2.39 2.39 15,942
13 UpperCycle63 SO_Entry_2_UM 3614 31.43% 310,941 -126,015 41,466,831 2.47 2.48 11,334
14 UpperCycle63 SO_Entry_2_20 3872 29.55% 423,224 -152,900 67,669,208 2.77 2.77 17,319
15 UpperCycle63 SO_Close_3_UM 3816 33.60% 295,031 -133,011 41,445,470 2.22 2.22 10,791
16 UpperCycle63 SO_Close_3_20 4384 33.85% 358,275 -163,235 58,299,384 2.19 2.19 13,298
17 UpperCycle63 SO_Close_2_UM 5184 35.03% 242,292 -114,750 53,523,075 2.11 2.11 10,325
18 UpperCycle63 SO_Close_2_20 7002 35.62% 257,266 -127,496 66,868,116 2.02 2.02 9,550

「まあ、こんな感じか」といったところですね。十数年かけて、1000万円の資金が5~8倍程度になったことがわかります。

ここで1点特筆すべきなのは「RR比率」です。「RR比率/atr」を並べて掲載しましたが、すべて「誤差0.01」で収まっているのがわかると思います(取引回数や勝率は一緒です)。つまり、資金管理を含めても「ATRで平準化した統計を再現することができた」ということです。

以前の記事で解説した内容を、再現できたということですね。

この手法の想定される利益は

もっとも成績がよかった⑤の想定される利益は、以下のように算出することができます。100万円の運用資金だとすると、477万円の利益で、577万円まで資金が増えるであろうことがわかります。

引用元上位足を考慮した移動平均線のバックテスト|日経225 FX 4時間足

つまり、どんなにチャートを見ながら検証して良い手法を見つけたとしても、資金管理(サイジング)を怠ると再現することができず、劣悪な結果になってしまうということです。ATRによる資金管理(サイジング)は「バックテストを再現する要」と言えそうです。

また、資金量が少ないトレーダーは、サイジングを適切に行うことができないという点で不利だと言えそうです。

目次

3-5.ATRの数値には素直に従うべきか(前回の宿題)

最後に、前回の宿題について考えてみたいと思います。

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

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

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

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

実はこれは、「3-4.資金管理は、バックテストを再現する要」の結果をもって解決しています。

以前の仮説は「取引量が変わることが損益に影響を及ぼす」でしたが、今回の検証で、「資金管理を含めた統計の結果」と「ATRで平準化した統計の結果」が同一である(RR比の誤差0.01のみ)ことがわかりました。これをもって、「通常の『ATR20』の方が良いという結論」になります。

目次

3-6.銘柄ごとの損益曲線

前回の記事では同じパターンのATR比のグラフを掲載したので、今回は取引量に応じた損益の推移を掲載します。

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

目次

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

ここも同様に、取引量に応じた損益の推移を掲載しています。

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

目次

4.まとめ

今回のバックテストでは、開発に思いのほか手間取りました。結果的には思い通りのものができましたし、今回の開発は、以降の分散投資を含めたバックテストに不可欠なものだったので、おおむね満足しています。

「ATRによる資金管理(サイジング)が最終的な成績に良い影響を及ぼす」という点は、新たな気付きでした。おそらく「もみ合い期」の損失を軽減するためでしょう。

たとえ4時間足であっても、単一銘柄だと損失で終わる年がけっこうあります。これが、複数銘柄で分散投資をするとどうなるのか、早く開発をすすめて試してみたいものです。

注意点

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

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

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

Back to Top

Investment Tech Hack

Sorry... doesn't support your browser

To get the best possible experience using our site we recommend that you upgrade to a modern web browser. Investment Tech Hackではご利用中のブラウザサポートはしていません。
Internet Explorerのアップグレード行う、もしくはその他のブラウザを使用しての閲覧をお願いします。