English Русский 中文 Español Deutsch Português
MQL5の料理本 - 移動チャネルのプログラミング

MQL5の料理本 - 移動チャネルのプログラミング

MetaTrader 5 | 25 7月 2016, 13:39
864 0
Denis Kirichenko
Denis Kirichenko

はじめに

チャートには市場価格の動向が表されているというのは常識で、トレンドを示したり、トレンドがなければチャートが水平になっているということになります。オシレータ類に当てはまるテクニカルインディケーターは、値動きが水平に近い場合に機能するものです。しかし、トレンドが出現する際にも価格の振幅を伴うある一定のレンジは存在します。

本稿では、等間隔チャネル、一般には移動チャネルと呼ばれるチャネル構築の動的方法について記述しようと思います。移動チャネルにおけるもっとも有名な戦略の一つは、ビクター・バリシュポルツの戦略です。移動チャネル生成の規則に用いるため、バリシュポルツ氏の考え方を説明していきます。また、これら規則の拡張を試みます。著者の意見ですが、チャネルシステムの機能性を拡大できるのはないかと考えています。


1. 等間隔チャネルの基本

まず初めに、等間隔チャネルプログラミングのフレームワークとして用いられている模式図から見ていきます。ヘルプから"等間隔チャネル"テクニカル分析ツールを読んでおきましょう。 

チャネルは3点で構築でき、各点は価格と時間の座標を持っています。まず、時間の座標に注目します。これらシークエンスがチャネルタイプに関係します。例として、2つの極小値からなるメインラインをチャネルに使用します。3点目は極大値になります。これら3点の位置をチャネル分類の基準として使用することができます。

チャネルを描画する際、左方向の延長線も、右方向の延長線も、特に明記しない限り使用しません。

一番目のチャネルタイプは、最小値が最初に現れ、次に最大値、最後に再び最小値が現れるタイプです。この場合の模式図を図1に示します。

図1 第1タイプ 模式図

図1 第1タイプ 模式図

以下の図は価格チャートに現れた第1タイプです。

図2 第1タイプ 価格チャート

図2 第1タイプ 価格チャート

第2タイプは、最初に最大値、次に最小値、最後に2つ目の最小値がチャート上に現れるケースです(図3)。

図3 第2タイプ 模式図

図3 第2タイプ 模式図

最初に現れた極大値は、結果として3点目になります。メインラインを形成する2最小値が続きます。

第3タイプは"最小ー最小ー最大"の方式に基づいています。このケースでは、メインラインは極小値が形成されてからできます(図4)。

図4 第3タイプ 模式図

図4 第3タイプ 模式図

残り2つのタイプは比較的特殊なケースのものです。 

3点目と1点目の形成時刻が一致する場合が第4タイプです(図5)。

図5 第4タイプ 模式図

図5 第4タイプ 模式図

そして最後に、2点目と3点目の形成時刻が一致する場合が第5タイプになります。

図6 第5タイプ 模式図

図6 第5タイプ 模式図


取り扱っていく等間隔チャネルの5タイプについて見ていきました。次のセクションでは、チャネルライン作成に使用する各点のプログラミングを行っていきます。


2. データの補助形式

チャネルのトレンドライン描画に使う各点は、フラクタルを示しています。つまり、点はフラクタルであると同時に直線を引く基点となるのです。

フラクタル点をOOPを使って簡易化してコード化してみましょう。

2.1フラクタル点のクラス

フラクタル点クラスの特徴として、等間隔チャネルを形成する各点間に存在する点であることが挙げられます。

このクラスを、CFractalPointと名付けます。そして、MQL5言語の機能を利用し、これをCObjectインターフェースクラスへ継承します。

//+------------------------------------------------------------------+
//| フラクタル点のクラス                                      |
//+------------------------------------------------------------------+
class CFractalPoint : public CObject
  {
   //--- === データメンバ === --- 
private:
   datetime          m_date;           //日時
   double            m_value;          // 値
   ENUM_EXTREMUM_TYPE m_extreme_type;  // 極値型
   int               m_idx;            // インデックス(0~2)
   //--- === メソッド === --- 
public:
   //--- コンストラクタ/デストラクタ
   void              CFractalPoint(void);
   void              CFractalPoint(datetime _date,double _value,
                                   ENUM_EXTREMUM_TYPE _extreme_type,int _idx);
   void             ~CFractalPoint(void){};
   //--- メソッドの取得
   datetime          Date(void) const {return m_date;};
   double            Value(void) const {return m_value;};
   ENUM_EXTREMUM_TYPE FractalType(void) const {return m_extreme_type;};
   int               Index(void) const {return m_idx;};
   //--- メソッドの設定
   void              Date(const datetime _date) {m_date=_date;};
   void              Value(const double _value) {m_value=_value;};
   void              FractalType(const ENUM_EXTREMUM_TYPE extreme_type) {m_extreme_type=extreme_type;};
   void              Index(const int _bar_idx){m_idx=_bar_idx;};
   //--- サービス
   void              Copy(const CFractalPoint &_source_frac);
   void              Print(void);
  };
//+------------------------------------------------------------------+

クラスにはデータ転送に使用する4つのメンバがあります。

  1. m_date — チャート上にある点の時刻座標
  2. m_value — チャート上にある点の価格座標
  3. m_extreme_type –  極値型
  4. m_idx – インデックス

ENUM_EXTREMUM_TYPEの列挙は極値型になります。

//+------------------------------------------------------------------+
//| 極値型                                                    |
//+------------------------------------------------------------------+
enum ENUM_EXTREMUM_TYPE
  {
   EXTREMUM_TYPE_MIN=0, // 最小値
   EXTREMUM_TYPE_MAX=1, // 最大値
  };

CFractalPoint方法の主目的は、上記のプライベートメンバの値を受け取りリフレッシュさせることです。

例として、図7のEURUSD、H4チャートに、2016年1月26日8:00時点のローソク足のフラクタル点をプログラミングしてみましょう。フラクタルはローソク足の最大値である価格1,08742に形成されました。

図7 フラクタル事例

図7 フラクタル事例

以下がこのフラクタル作成のコードになります。

//--- フラクタル点データ
   datetime pnt_date=D'26.01.2016 08:00';
   double pnt_val=1.08742;
   ENUM_EXTREMUM_TYPE pnt_type=EXTREMUM_TYPE_MAX;
   int pnt_idx=0;
//--- フラクタル点を生成
   CFractalPoint myFracPoint(pnt_date,pnt_val,pnt_type,pnt_idx);
   myFracPoint.Print();

ログには次の内容が表示されます。

---=== フラクタル点データ ===---
Date: 2016.01.26 08:00
Price: 1.08742
Type: EXTREMUM_TYPE_MAX
Index: 0

上記はフラクタル点が2016年1月26日付、価格1,08742のバーに位置されたことを示しています。このフラクタル点は極大値になります。インデックスがゼロなのは、それが同様の点の集まりの中で最初の点であることを示しています。


2.2フラクタル点セットのクラス

ここから、等間隔チャネルの構築に使用するフラクタル点セットの作成を進めていきます。作成するには、複数のフラクタル点を特定しセットにするCFractalSetクラスを使用します。

このクラスはインディケータではなく、エキスパートアドバイザに含まれています。そのため、チャネルはインディケータバッファではなく、CChartObjectChannelタイプの描画オブジェクトを参照します。

CFractalSetはスタンダードライブラリのCArrayObjクラスの子クラスです筆者は高度に特化したクラスのインターフェースを作成するため継承のセキュアモードを選択します。

//+------------------------------------------------------------------+
//| フラクタル点セットのクラス                                 |
//+------------------------------------------------------------------+
class CFractalSet : protected CArrayObj
  {
   //--- === データメンバ === --- 
private:
   ENUM_SET_TYPE     m_set_type;           // type of the points' set
   int               m_fractal_num;        // フラクタル点の定数
   int               m_fractals_ha;        // フラクタルインディケータのハンドル 
   CisNewBar         m_new_bar;            // 新たなバーのオブジェクト
   CArrayObj         m_channels_arr;       // インディケータアレイのオブジェクト
   color             m_channel_colors[4];  // チャネルカラー
   bool              m_is_init;            // 初期化フラグ
   //--- チャネル設定
   int               m_prev_frac_num;      // 以前のフラクタル
   int               m_bars_beside;        // フラクタル左側/右側のバー
   int               m_bars_between;       // 中間バー数 
   bool              m_to_delete_prev;     // 以前のチャネルを削除しますか?
   bool              m_is_alt;             // 代替フラクタルインディケータを使用しますか?
   ENUM_RELEVANT_EXTREMUM m_rel_frac;      // relevant point
   bool              m_is_array;           // 矢印を描きますか?
   int               m_line_wid;           // 線幅
   bool              m_to_log;             // ログを保存しますか?
   //--- === メソッド === --- 
public:
   //--- コンストラクタ/デストラクタ
   void              CFractalSet(void);
   void              CFractalSet(const CFractalSet &_src_frac_set);
   void             ~CFractalSet(void){};
   //---
   void              operator=(const CFractalSet &_src_frac_set);
   //--- ハンドラ
   bool              Init(
                          int _prev_frac_num,
                          int _bars_beside,
                          int _bars_between=0,
                          bool _to_delete_prev=true,
                          bool _is_alt=false,
                          ENUM_RELEVANT_EXTREMUM _rel_frac=RELEVANT_EXTREMUM_PREV,
                          bool _is_arr=false,
                          int _line_wid=3,
                          bool _to_log=true
                          );
   void              Deinit(void);
   void              Process(void);
   //--- サービス
   CChartObjectChannel *GetChannelByIdx(const int _ch_idx);
   int               ChannelsTotal(void) const {return m_channels_arr.Total();};
private:
   int               AddFrac(const int _buff_len);
   int               CheckSet(const SFracData &_fractals[]);
   ENUM_SET_TYPE     GetTypeOfSet(void) const {return m_set_type;};
   void              SetTypeOfSet(const ENUM_SET_TYPE _set_type) {m_set_type=_set_type;};
   bool              PlotChannel(void);
   bool              Crop(const uint _num_to_crop);
   void              BubbleSort(void);
  };
//+------------------------------------------------------------------+

このクラスのメンバリストは次のとおりです。 

  1. m_set_type – フラクタル点セットのタイプ。以下はセット分類を担当するものが並びます。
  2. m_fractal_num – セットに含まれるフラクタル点の定数。
  3. m_fractals_ha – フラクタルインディケータのハンドル。
  4. m_new_bar – 新たなバーのオブジェクト。
  5. m_channels_arr – インディケータアレイのオブジェクト。
  6. m_channel_colors[4] — チャネル表示色のアレイ。
  7. m_is_init — 初期化フラグ。
    チャネル設定をおこなうメンバブロックが並びます。
  8. m_prev_frac_num — 初期チャネル構築に使用した以前のフラクタル点の数。3点の場合、チャネルは初期化の直後に作成されます。  
  9. m_bars_beside — フラクタル左側/右側のバー数。例えば5本にした場合、計11本のバーがフラクタルを探すのに使用されます。
  10. m_bars_between — 中間バー数。これが付近のフラクタル点間に存在すべき最小バー数になります。
  11. m_to_delete_prev — 以前のチャネルの削除許可。
  12. m_is_alt — 代替フラクタルインディケータを使用するフラグ。
  13. m_rel_frac — 関連フラクタル点の選択。中間バー数が不足していれば、このフラクタル点タイプはどのバーをスキップすべきか示すでしょう。
  14. m_is_array — 矢印を描くフラグ。
  15. m_line_wid — 線幅。
  16. m_to_log — フラグの記録。

フラクタル点セットのタイプを処理するものを以下に示します。

//+------------------------------------------------------------------+
//| 極値点セットタイプ                                |
//+------------------------------------------------------------------+
enum ENUM_SET_TYPE
  {
   SET_TYPE_NONE=0,     // セットなし
   SET_TYPE_MINMAX=1,   // 最小-最大ー最小
   SET_TYPE_MAXMIN=2,   // 最大ー最小-最大                       
  };

この例では、SET_TYPE_MAXMIN値は、順に最大、最小、最大のフラクタル点に対応します(図8)。

図8「最大ー最小ー最大」タイプセット

図8「最大ー最小ー最大」タイプセット

常にフラクタル点が順番通りに並ぶというわけではありません。時折、最初に最小値が現れた後にまた最小値が続く場合もあります。第一セクション(図4)で説明したフラクタル点セットの第3タイプのことです。いずれにせよ、最小値2個と最大値1個か、最大値2個と最小値1個か、完全なセットであるかどうかを検討します。

これら関連フラクタル点タイプの処理列挙は次の形式になります。

//+------------------------------------------------------------------+
//| 関連フラクタル点タイプ                                      |
//+------------------------------------------------------------------+
enum ENUM_RELEVANT_EXTREMUM
  {
   RELEVANT_EXTREMUM_PREV=0, // 以前の極値
   RELEVANT_EXTREMUM_LAST=1, // 最新の極値
  };

メソッドに進みましょう。最初にハンドラをリストアップします。

  1. Init() – セットを初期化します。メソッドは、フラクタル点セットを表示するオブジェクト処理の正確な開始が必要です。
  2. Deinit() - セットを非初期化します。
  3. Process() – 価格ストリームのコントロール。このメソッドはフラクタル点を特定しチャネルを表示します。

サービスメソッド

  1. AddFrac() — セットにフラクタル点を追加します。
  2. CheckSet() 現在のセット状況をチェックします。
  3. PlotChannel() – 等間隔チャネルを描画します。
  4. Crop() – セットをトリミングします。
  5. BubbleSort() — セットのフラクタル点を出現時間順に並び替えます。

2.3別のチャネル構築機会

チャネル構築のそのプロパティに対処するには標準ライブラリのCChartObjectChannelクラスを使用しました。どのアルゴリズム実行が自動チャネル構築機能を向上させることができのか、考えていきます。


2.3.1 ライン同期化

両方のチャネルラインが、同じバーからスタートする時点でチャートを視覚的に見てみるのが最も有効です。正式には、第4チャネルタイプがこの方法になります(図5)。明らかに、チャネルは別タイプに分類することができます。このため、フラクタル点の価格・時刻座標は、第4チャネルタイプに適合するようにCFractalSet::PlotChannel()メソッドにおいて修正されます。また、チャネルの傾きと幅を記憶することも必要です。

次の価格チャート(図9)において、等間隔チャネルについて見ていきましょう。

図9 初期フラクタル点に基づく等間隔チャネル

図9 初期フラクタル点に基づく等間隔チャネル

手動で構築できるように最初から整理したいと思います。以下のフラクタル点があります。

  1. 2015年12月3日 1.05189ドル(最小値)
  2. 2016年1月5日 1.07106ドル(最小値)
  3. 2016年1月5日 1.10594ドル(最大値)

CFractalSetクラスで同様なチャネルを表示すると、次のようになります(図10)。


図10 計算されたフラクタル点における等間隔チャネル

図10 計算されたフラクタル点における等間隔チャネル

図10のチャネル構築における決定的な相異は、計算されたフラクタル点に基づいていることです。2番目と3番目のフラクタル点の価格と時刻の値が計算されています。最後のフラクタル点は1番目の点と時刻座標が一致しなければなりません。

計算されたフラクタル点を2つに分けてチャネルを描画するタスクを見ていきましょう。

1つ目は時刻座標に注目します。チャネルの開始と終了を定義します。以下のコードブロックがこのメソッドに含まれるものです。

//--- 1) 時刻座標
//--- チャネル開始
int first_date_idx=ArrayMinimum(times);
if(first_date_idx<0)
  {
   Print("軸座標の取得に失敗しました!");
   m_channels_arr.Delete(m_channels_arr.Total()-1);
   return false;
  }
datetime first_point_date=times[first_date_idx];
//--- チャネル終了
datetime dates[];
if(CopyTime(_Symbol,_Period,0,1,dates)!=1)
  {
   Print("最新バー時刻の取得に失敗しました!");
   m_channels_arr.Delete(m_channels_arr.Total()-1);
   return false;
  }
datetime last_point_date=dates[0];

この方法では、全てのフラクタル点は時刻座標を持つことになります。

//--- 最終時刻座標 
times[0]=times[2]=first_point_date;
times[1]=last_point_date;

2つ目のタスクは価格座標についてです。新しい価格は3番目か1番目のフラクタル点において決定されます。

最初にどれだけ早くチャネルラインの価格がバーが移動するごとに変化するのか、チャネルは上下どちらの方向へ向かうのか特定します。

//--- 2) 価格座標
//--- 2.1 ラインの傾き
//--- 第1・第2フラクタル点間のバー
datetime bars_dates[];
int bars_between=CopyTime(_Symbol,_Period,
                          times[0],times[1],bars_dates
                          );
if(bars_between<2)
  {
   Print("フラクタル点間のバー数の取得に失敗しました!");
   m_channels_arr.Delete(m_channels_arr.Total()-1);
   return false;
  }
bars_between-=1;
//--- 一般差動
double price_differential=MathAbs(prices[0]-prices[1]);
//--- 価格速度(最初のバーにおける価格変動)
double price_speed=price_differential/bars_between;
//--- チャネル方向
bool is_up=(prices[0]<prices[1]);

フラクタル点の価格座標はリフレッシュすることがでます。どのフラクタル点が先にできたのか、知る必要があります。さらに、チャネルが向かっている方向、上か下かを知る必要があります。

//--- 2.2 第1または第3フラクタル点の最新価格  
if(times[0]!=times[2])
  {
   datetime start,end;
   start=times[0];
   end=times[2];
//--- 3点目が1点目よりも前の場合
   bool is_3_point_earlier=false;
   if(times[2]<times[0])
     {
      start=times[2];
      end=times[0];
      is_3_point_earlier=true;
     }
//--- 第1・第3フラクタル点間のバー
   int bars_between_1_3=CopyTime(_Symbol,_Period,
                                 start,end,bars_dates
                                 );
   if(bars_between_1_3<2)
     {
      Print("フラクタル点間のバー数の取得に失敗しました!");
      m_channels_arr.Delete(m_channels_arr.Total()-1);
      return false;
     }
   bars_between_1_3-=1;
//--- チャネルが上方向の場合
   if(is_up)
     {
      //--- 第3点が先に現れる場合
      if(is_3_point_earlier)
         prices[0]-=(bars_between_1_3*price_speed);
      else
         prices[2]-=(bars_between_1_3*price_speed);
     }
//--- またはチャネルが下方向の場合
   else
     {
      //--- 第3点が先に現れる場合
      if(is_3_point_earlier)
         prices[0]+=(bars_between_1_3*price_speed);
      else
         prices[2]+=(bars_between_1_3*price_speed);
     }
  }
以前の例として、第1フラクタル点が先にできるものがありました。これは第3フラクタル点をリフレッシュしなければならないことを意味します。

最後に、第2フラクタル点座標をリフレッシュしましょう。

//--- 2.3 第2フラクタル点の最新価格 
if(times[1]<last_point_date)
  {
   datetime dates_for_last_bar[];
//---第2フラクタル点と最新バー間のバー数
   bars_between=CopyTime(_Symbol,_Period,times[1],last_point_date,dates_for_last_bar);
   if(bars_between<2)
     {
      Print("フラクタル点間のバー数の取得に失敗しました!");
      m_channels_arr.Delete(m_channels_arr.Total()-1);
      return false;
     }
   bars_between-=1;
//--- チャネルが上方向の場合
   if(is_up)
      prices[1]+=(bars_between*price_speed);
//--- またはチャネルが下方向の場合
   else
      prices[1]-=(bars_between*price_speed);
  }

What we obtain:

  1. 2015年12月3日 1.05189ドル(最小値)
  2. 2016年2月26日 1.10575ドル(計算値)
  3. 2015年12月3日 1.09864ドル(計算値)

チャネルは右矢印を使用してもしなくても描画できます。しかし、このオプションは現在のチャネルだけに言えることです。チャート上にあるこれまでの全チャネルオブジェクトからは右矢印がなくなります。

2.3.2 以前のフラクタル点の考察

入力パラメータに基づくフラクタル点を検索するヒストリを宣言するオプションはCFractalSetクラスです。これを使用するのはクラスサンプルの初期化中の間だけです。m_prev_frac_numメンバが”過去から出発する点”に依存していることに注意してください。

例を分析してみましょう(図11)。TestChannelEAエキスパートアドバイザの初期化後すぐに、チャート上に複数のフラクタル点を見つけなければいけません。それらの点は数字を付したフラクタル点にすることができます。

図11 初期化中のフラクタル点

図11 初期化中のフラクタル点

全3点を取得すると、チャネルを構築することができます(図12)。

図12 初期化中に構築された最初のチャネル

図12 初期化中に構築された最初のチャネル


ログにメッセージがあります。

2016.02.25 15:49:23.248 TestChannelEA (EURUSD.e,H4)     以前のフラクタルが追加されました。 3

フラクタル点が右から左へセットに追加されることを知らせるのは難しいことではありません。そして、チャネルは左から右へ収集された点に基づいて構築されます。ソートのプライベートメソッドCFractalSet::BubbleSort()は、実際のチャネルを描く前にフラクタル点を整理することができます。

CFractalSet::Init() メソッドにおける初期化中のフラクタル点セットをおこなうコードブロックは次の通りです。

//--- 以前のフラクタル点が追加される場合
if(m_prev_frac_num>0)
  {
//--- 1) 読込履歴 [開始]
   bool synchronized=false;
//--- ループカウンタ
   int attempts=0;
//--- 同期化を10回試行
   while(attempts<10)
     {
      if(SeriesInfoInteger(_Symbol,0,SERIES_SYNCHRONIZED))
        {
         synchronized=true;
         //--- 同期化が確立したならばイグジット
         break;
        }
      //--- カウンタ拡大
      attempts++;
      //--- 次の反復処理まで50ミリ秒待機
      Sleep(50);
     }
//---
   if(!synchronized)
     {
      Print("バー数の取得に失敗しました。",_Symbol);
      return false;
     }
   int curr_bars_num=Bars(_Symbol,_Period);
   if(curr_bars_num>0)
     {
      PrintFormat("現時点のシンボル/期間に基づくターミナルヒストリ上のバー数: %d",
                  curr_bars_num);
     }
//--- 1) 読込履歴 [終了]
//--- 2) 要求したインディケータに必要な計算データ [開始]
   double Ups[];
   int i,copied=CopyBuffer(m_fractals_ha,0,0,curr_bars_num,Ups);
   if(copied<=0)
     {
      Sleep(50);
      for(i=0;i<100;i++)
        {
         if(BarsCalculated(m_fractals_ha)>0)
            break;
         Sleep(50);
        }
      copied=CopyBuffer(m_fractals_ha,0,0,curr_bars_num,Ups);
      if(copied<=0)
        {
         Print("上部フラクタル点のコピーに失敗しました。Error = ",GetLastError(),
               "i=",i,"    copied= ",copied);
         return false;
        }
      else
        {
         if(m_to_log)
            Print("上部フラクタルのコピーに成功しました。",
                  " i = ",i,"    copied = ",copied);
        }
     }
   else
     {
      if(m_to_log)
         Print("上部フラクタルのコピーに成功しました。ArraySize = ",ArraySize(Ups));
     }
//--- 2) 要求したインディケータに必要な計算データ [終了]
//--- 3) フラクタル点を追加 [開始]
   int prev_fracs_num=AddFrac(curr_bars_num-1);
   if(m_to_log)
      if(prev_fracs_num>0)
         PrintFormat("これまでのフラクタル点を追加しました。: %d",prev_fracs_num);
//--- チャネルを表示可能な場合
   if(prev_fracs_num==3)
      if(!this.PlotChannel())
         Print("チャネル表示に失敗しました!");
//--- 3)フラクタル点を追加 [終了]
  }

これは3つのサブブロックに分けることができます。

  1. クウォート履歴の読込。
  2. フラクタルインディケーターデータの計算。
  3. セットへフラクタル点の追加。

 このように、チャネルを初期化時点で描画することができます。これは、特にチャートデータがサーバーデータと同期されていない場合に必要な操作です。

2.3.3 隣接フラクタル点間バーの考察

使用したフラクタル点(第1と第2、そして第3と第4)は以前のチャート上に隣同士に配置されています。最も近いフラクタル点を抹消するために、ある種のフィルターを追加することができます。この機能はm_bars_betweenメンバによって実行されます。隣接フラクタル点間のバー数です。ナンバーを1にセットすると、第2フラクタル点はセットに落ちません。そして現在の第3フラクタル点に置き換えられます。

図13 中間バーを考慮した最初のチャネル

 図13 中間バーを考慮した最初のチャネル

隣接フラクタル点間に少なくとも1本のバーがあればチャネルを構築できます(図13)。第1・第2フラクタル点が続く点はスキップする必要があることが分かります。黄色で強調した点です。

例えば、最初の欠落している点は以下のログに対応します。

2016.02.25 16:11:48.037 TestChannelEA (EURUSD.e,H4)     以前のフラクタル点はスキップされました。: 2016.02.24 12:00
2016.02.25 16:11:48.037 TestChannelEA (EURUSD.e,H4)     中間バー数が不足しています。フラクタル点はスキップされます。

探し出したチャネルはそのために狭く、おそらくトレーダーの使用には耐えられるものではないでしょう。

コードに関して、認められた中間バー数のチェックは CFractalSet::CheckSet() プライベートメソッドにおいて実行されます。

//--- 過去から現在までのフラクタル点間バー数をチェック
if(m_bars_between>0)
  {
   curr_fractal_num=this.Total();
   if(curr_fractal_num>0)
     {
      CFractalPoint *ptr_prev_frac=this.At(curr_fractal_num-1);
      if(CheckPointer(ptr_prev_frac)!=POINTER_DYNAMIC)
        {
         Print("セットからフラクタル点オブジェクト取得に失敗しました!");
         return -1;
        }
      datetime time1,time2;
      time1=ptr_prev_frac.Date();
      time2=ptr_temp_frac.Date();
      //--- フラクタル点間バー
      datetime bars_dates[];
      int bars_between=CopyTime(_Symbol,_Period,
                                time1,time2,bars_dates
                                );
      if(bars_between<0)
        {
         Print("バー発生時刻データの取得に失敗しmした!");
         return -1;
        }
      bars_between-=2;
      //--- 複数バーの場合
      if(bars_between>=0)
         //--- 中間バー数が不足している場合 
         if(bars_between<m_bars_between)
           {
            bool to_delete_frac=false;
            if(m_to_log)
               Print("中間バー数が十分ではありません。フラクタル点はスキップされます。");
            // ...
           }
     }
  }

bars_between変数は2つの隣接フラクタル点間のバー数を取得します。この値が許可されると、フラクタル点はスキップされます。次のセクションから、フラクタル点が現在のものか以前のものかどうか明らかにしていきます。

2.3.4 関連フラクタル点の選別

中間バー数が不足しており、フラクタル点の1つは無視しなければいけない場合、スキップするフラクタル点を指示することができます。上記の例では、出現時間が古いフラクタル点はスキップされました。なぜなら最後の点が関連フラクタル点とみなされるからです。以前のフラクタル点を関連付けるとどのようになるか見てみましょう。

図14 中間バーと以前の関連フラクタル点を考慮した最初のチャネル

図14 中間バーと以前の関連フラクタル点を考慮した最初のチャネル

例として、次のような最初のスキップしたフラクタル点のログを取得します。

2016.02.25 16:46:06.212 TestChannelEA (EURUSD.e,H4)    現在のフラクタル点はスキップされました。: 2016.02.24 16:00
2016.02.25 16:46:06.212 TestChannelEA (EURUSD.e,H4)    中間バー数が十分ではありません。フラクタル点はスキップされます。

おそらく、このチャネルは全ての隣接バーを制限するのでより有効に見えます。以前か最後の関連フラクタル点のどちらががチャネル描画の際に使用できるのか、あらかじめ知るのは困難です。

コード(CFractalSet::CheckSet()プライベートメソッド内にあるものと同一のコード)がある場合、2つの事柄がメソッドの動作に影響することが分かるでしょう。実際のフラクタル点の選択タイプと初期化フラグとが影響します。

//--- 中間バー数が不足している場合 
if(bars_between<m_bars_between)
  {
   bool to_delete_frac=false;
   if(m_to_log)
      Print("中間バー数が十分ではありません。フラクタル点はスキップされます。");
//--- 以前のフラクタル点が関連している場合
   if(m_rel_frac==RELEVANT_EXTREMUM_PREV)
     {
      datetime curr_frac_date=time2;
      //--- 初期化があった場合
      if(m_is_init)
        {
         continue;
        }
      //--- 初期化がなかった場合
      else
        {
         //--- 現在のフラクタル点を削除
         to_delete_frac=true;
         curr_frac_date=time1;
        }
      if(m_to_log)
        {
         PrintFormat("現在のフラクタル点は除外されました。: %s",
                     TimeToString(curr_frac_date));
        }
     }
//--- 最後のフラクタル点が関連している場合
   else
     {
      datetime curr_frac_date=time1;
      //--- 初期化があった場合
      if(m_is_init)
        {
         //--- 以前のフラクタル点を削除
         to_delete_frac=true;
        }
      //--- 初期化がなかった場合
      else
        {
         curr_frac_date=time2;
        }
      if(m_to_log)
         PrintFormat("以前のフラクタル点がスキップされました。: %s",
                     TimeToString(curr_frac_date));
      if(curr_frac_date==time2)
         continue;
     }
//--- フラクタル点が削除された場合
   if(to_delete_frac)
     {
      if(!this.Delete(curr_fractal_num-1))
        {
         Print("セットにおける最後のフラクタル点削除に失敗しました!");
         return -1;
        }
     }
  }

次のセクションでは、等間隔チャネルセットを扱って、それらのパラメータを変更することで価格スライド画像を取得してみましょう。

3. 自動的に移動チャネルを生成するには

ChannelsPlotterと名付けられたエキスパートアドバイザーのバージョンはチャネル描画をテストするために作成されました。エキスパートアドバイザーの稼働結果を図15に示しました。御覧の通り、チャネルは標準的なフラクタル点に基づき、明確な市場トレンドがない中で”ちらつき”始めています。したがって、代替フラクタルインディケータを使用したオプションを、極値付近の任意のバー数をセットして追加しました。 X-バーフラタルインディケータを ソースコードベースから借用しました。

図15 標準フラクタルに基づくチャネルスライド

標準フラクタルにおける移動チャネル

代替フラクタルインディケータを選択してエキスパートアドバイザを稼働させれば、極値検索に十分なバー数増加の結果を得ることができます。したがって、23本のバーからなるグループ上でフラクタルを探すと、結果は図16のとおりになるでしょう。

図16 代替フラクタルに基づくチャネルスライド
図16 代替フラクタルに基づく移動チャネル


このように、フラクタル決定に必要な隣接バー数が少ないほど、よりたくさんの”チャネル”ノイズが価格チャートに現れるのです。

おわりに

本稿では、等間隔チャネルシステムのプログラミン法について記述しました。チャネル構築の細部についていくつか説明しました。ビクター・バリシュポルツのアイデアをフレームワークに使用しました。筆者の次稿では、移動チャネルによって生成されるトレーディングシグナルについて分析します。

ファイル場所:

私見ですが、ファイルをプロジェクトフォルダに作成、保存するのが一番便利です。例えば保存場所は次のようなります。: <data folder>\MQL5\Projects\ChannelsPlotter. 忘れずに代替フラクタルインディケータ、X-bars_Fractalsをコンパイルして下さい。インディケータのソースコードはインディケータフォルダに保存してください。— <data folder>\MQL5\Indicators.

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1862

添付されたファイル |
cfractalpoint.mqh (83.04 KB)
cisnewbar.mqh (15.18 KB)
x-bars_fractals.mq5 (11.58 KB)
ユニバーサルEA:グループでの取引とストラテジーのポートフォリオを管理する(その4) ユニバーサルEA:グループでの取引とストラテジーのポートフォリオを管理する(その4)
CStrategyの取引エンジンについての一連の記事の最後のパートでは、XMLファイルからストラテジーをロードする方法を行います。複数の取引アルゴリズムの同時動作を考慮し、単一の実行可能モジュールからのEAを選択する簡単なパネルを提示し、その取引モードを管理します。
ユニバーサルEA:カスタムストラテジーと補助トレードクラス(その3) ユニバーサルEA:カスタムストラテジーと補助トレードクラス(その3)
この記事では、ストラテジーの取引エンジンのアルゴリズムを分析していきます。シリーズの3番目の部分は、このアプローチを使用して、特定の取引ストラテジーを開発する方法の詳細な分析があります。特別な注意が補助アルゴリズムに必要です - EAは、従来のインデクサーを使用して、システムとデータへのアクセスをログに記録します(Close[1]、Open[0]など)
マーケットでの公開前にトレードロボットに行うべき検査 マーケットでの公開前にトレードロボットに行うべき検査
マーケットの全ての製品は、均一な品質基準を確保する為に、公開前に事前の必須検査を受けます。この記事では、開発者が自分のテクニカルインディケータやトレードロボットで犯しがちなミスについてお話しします。また、マーケットへ提出する前の、製品の自己テストの方法もご紹介します。
ユニバーサルEA:イベントモデルと取引ストラテジープロトタイプ(パート2) ユニバーサルEA:イベントモデルと取引ストラテジープロトタイプ(パート2)
この記事は、ユニバーサルEAのシリーズです。このパートでは、データ処理に基づいて、オリジナルのイベント・モデルについて解説し、エンジンのストラテジーの基本クラスの構造を扱います。