
ミクロ、ミドル、メイントレンドのインディケータ
はじめに
James Hyerczyk氏は著書 "Pattern, Price & Time: Using Gann Theory in Trading Systems" の序文でこう書いています。
「将来ビジネスの経験からよく目にしてきたのは、トレーダーはしばしば分析においてパターン、価格、時間のどれかに夢中になりすぎることです。そういう人達は分析にあたり、均等なバランスを欠き、一方向にウェイトを置く傾向にあります。よくある誤りは、開始時刻と終了価格、または開始価格と終了時間を中心に構築されたシステムです。また、パターンを利用するトレーダーはよく不十分な価格や悪いタイミングで開始や終了に臨むものです。こういう所見は、マーケットでの成功には、3つの手法すべての組合せが必要であるという証明となりました。拙著はこの前提に基づいています。」
この文言には賛成されないかもしれません。では、実際にこれら手法をいくつか使う方法を理解してみようではありませんか。本稿が取り上げるのは、トレードの自動化可能性と分析で、インディケータとEAという形式で、この本で述べられているいくつかの考え方を基にしています。資料をよりよく理解するために、本稿を読む前にその本の一読(すくなくとも序章、モデル部分)をお薦めします。
1.1ミクロトレンド
図1にマイナートレンドをグラフとして示しています。マイナートレンドを構築するルールについて簡単に考察していきます。
- 上昇中(次のバーの高値が前回バーの高値より高く、次のバーの安値が前回バーの安値より高い)、次の高値バーを前回バーとつなげ、上昇傾向の線を引きます。
- 下降中(次のバーの安値が前回バーの安値より低く、次のバーの高値が前回バーの高値より低い)、次の安値バーを前回バーとつなげ、下降傾向の線を引きます。
- 上昇中で別のバーの高値が前回バーの高値を越えず、かつ次回バーの安値が前回バーの安値を下回るとき、動きの方向は下降に転じています。
- 下降中で次回バーの安値が前回バーの安値を下回らず、同時に次回バーの高値が前回バーの高値を下回るとき、動きの方向は上昇に転じています。
- いずれの動きについても、次回バーの安値が前回バーの安値より高く、同時に次回バーの高値が前回バーの高値を下回るとき、このバーは インサイド(図1参照)と呼ばれ、グラフ構成に加わりません。
- いずれの動きについても、次回バーの高値が前回バーの高値を上回り、同時に次回バーの安値が前回バーの安値を下回るとき、このバーは アウトサイド(図1参照)と呼ばれます。バーの方向(上昇あるいは下降)により、対応するグラフセグメントを構築します。
図1 マイナートレンド
グラフの運動方向が変わるとき、いわゆるマイナーなピークボトムと呼ばれるものを形成します。図1では、マイナーボトムはバーの左側に価格ラベルを置き赤でマークされており、マイナーピークはグリーンでバーの右側に置いた価格ラベルでマークされています。
上昇傾向中に、方向が下降に転じても前回安値に届かなければ、コレクティブ傾向にあります。それ以外は、方向転換です。これは下降傾向についても同様です。
価格の動きは安値と高値の間を移動します。そのような動きはスイングと呼ばれます。同時にコレクティブ傾向も生成される可能性があります。
ミクロトレンドのインディケータラインを構築する簡単なルールがあります。これに関する詳述は本の序章で確認可能です。このインディケータグラフは有名な「ジグザグ」インディケータグラフに似ています。異なる点は、別のバーのクローズ後再描画されず、線の構築に影響を与える外部調整可能パラメータがないことです。
1.2. GannMicroTrend インディケータ
ミクロトレンドのグラフを表示するインディケータを作成します。見た目は図1と変わりません。時間に関して高値と安値の最新位置を表示するアウトプットも追加します。このインディケータは本稿添付のGannMicroTrend.mq5ファイルにあります。
この情報を表示するためには、『標準ライブラリクラス使用による独自マーケットウォッチ作成』稿に記述のあるライブラリを使います。そのために、われわれのインディケータテキストの冒頭に、 #include 命令を追加します。
#include <TextDisplay.mqh>
上述ファイルは \MQL5\Include フォルダにあると思われます。
インディケータはグローバル変数内に現在トレンド、そして最新の高値および安値のパラメータを格納する必要があります。また、履歴内所定バー数計算の深さを指定する機能も必要です。
このため、外部指定パラメータを追加します。
input int MaxBars = 1000; input bool IsSaveTrendParams = true; //--------------------------------------------------------------------- input bool ShowInfo = true; input int UpDownInfoShift = 1; input int LeftRightInfoShift = 1; input color TitlesColor = LightCyan; input color TopFieldsColor = Green; input color LowFieldsColor = Brown; //--------------------------------------------------------------------- input color UpTrendColor = LightGreen; input color DnTrendColor = LightPink; input int LineWidth = 4; //--------------------------------------------------------------------- input color UpStopLossColor = Green; input color DnStopLossColor = Brown; input int StopLossWidth = 1;
上記パラメータの目的は以下の一覧に示します。
パラメータ名 | 目的 |
---|---|
MaxBars |
インディケータが描かれる対象となる履歴内最大バー数その数値が 0 の場合、履歴内すべてのバーが数えられ、描かれます。 |
IsSaveTrendParams |
trueであれば、 現在トレンドについてのパラメータ、そして最新の高値および安値のパラメータをグローバル変数に格納します。 |
ShowInfo |
trueであれば、 グラフウィンドウは最新の高値および安値の座標を表示します。 |
UpDownInfoShift |
情報アウトプット箇所の高値から安値への縦の動き |
LeftRightInfoShift |
情報アウトプット箇所の左から右への横向きの動き |
TitlesColor |
情報出力中のヘッダの色 |
TopFieldsColor |
最新高値パラメータ出力中のテキストの色 |
LowFieldsColor |
最新安値パラメータ出力中のテキストの色 |
UpTrendColor |
上昇傾向ライン描画の色 |
DnTrendColor |
下降傾向ライン描画の色 |
LineWidth |
トレンドラインの幅 |
UpStopLossColor |
高値を指す右ラベル色 |
DnStopLossColor |
安値を指す左ラベル色 |
StopLossWidth |
高値および安値を指す価格ラベルサイズ |
CChartObjectTrend タイプのグラフィカルオブジェクトを用いてトレンドラインを構築します。標準クラスセットより二番目の高値は CChartObjectArrowLeftPrice タイプオブジェクトにより左価格ラベルで示します。一方、二番目の安値は CChartObjectArrowRightPrice タイプオブジェクトで示します。両オブジェクトともMetaTrader 5 端末に内蔵の標準ライブラリクラスに含まれています。
将来的にトレンドラインおよびピーク/ボトムの操作が必要になるかもしれないので、それらをこれもまた標準クラスセットにあるCListタイプオブジェクトに格納します。それには、インディケータの冒頭にヘッダファイルのインクルード命令を加えます。
#include <Arrays\List.mqh> #include <ChartObjects\ChartObjectsLines.mqh> #include <ChartObjects\ChartObjectsArrows.mqh>
そして、オブジェクトリストを追加します。
CList* trend_list_Ptr = NULL; // list of the trend lines CList* up_list_Ptr = NULL; // list of the peaks CList* dn_list_Ptr = NULL; // list of the bottoms
これで、インディケータ構築に必要な要素がすべてそろいました。
インディケータのOnInit 関数は以下です。
int OnInit() { trend_list_Ptr = new CList(); if(CheckPointer(trend_list_Ptr) != POINTER_DYNAMIC) { Print("Error of creating the object CList #1"); return(-1); } up_list_Ptr = new CList(); if(CheckPointer(up_list_Ptr) != POINTER_DYNAMIC) { Print("Error of creating the obkect CList #2"); return(-1); } dn_list_Ptr = new CList(); if(CheckPointer(dn_list_Ptr) != POINTER_DYNAMIC) { Print("Error of creating the object CList #3"); return(-1); } if(InitGraphObjects() != 0) { Print("Error of creating the object TableDisplay"); return(-1); } return(0); }
ここで、オブジェクトリストへのポインターが作成され、問題なく作成されたか確認されます。ポインターが有効でなければ、エラーメッセージが受け取られ、これでインディケータ作業は完了です。エラー発生個所は文字# を伴う数字により特定することができます。次に、最新の高値および安値についてのパラメータ表示テーブルを初期化します。関数コードInitGraphObjectsで行われます。
ここでのインディケータの基本部分は、計算に必要なイベントハンドラです。これが OnCalculate関数です。では、ひとつずつ見ていきます。最初の部分は、インディケータの表示部分全体を計算する必要性の確認です。そのような必要が生じると、たとえばインディケータが最初にグラフ上で開始する場合、グラフの更新をダウンロードする場合、時間枠の変更が生じた場合です。こういった場合にはすべて、変数prev_calculated の値がゼロとなっています。
これは以下のようにして確認されます。
int index, start = prev_calculated - 1; if(prev_calculated == 0) { if(CheckPointer(trend_list_Ptr) != POINTER_INVALID) { trend_list_Ptr.Clear(); } if(CheckPointer(up_list_Ptr) != POINTER_INVALID) { up_list_Ptr.Clear(); } if(CheckPointer(dn_list_Ptr) != POINTER_INVALID) { dn_list_Ptr.Clear(); } // Determine the bar number of the beginning of calculations: if(MaxBars > 0 && rates_total > MaxBars) { start = rates_total - MaxBars; } else { start = 0; } time_prev = 0; trend_prev = 0; }
インディケータ全体を再計算する必要があれば、トレンドラインおよび高値/安値のリストを消去します。また、こういったグラフィカルオブジェクトもグラフから削除されます。そして、インディケータ計算を開始する必要のあるバーの番号を決めます。start 変数外部変数 MaxBars の値がゼロ以上であれば、グラフ上のバー番号は rates_totalとなり、計算開始バーは以下に等しくなります。
start = rates_total - MaxBars;
time-series のバーインデックスはゼロ(最近のバー)から始まることを思い出しましょう。
外部変数 MaxBars の値がゼロ(グラフ上のバーすべてのインディケータを計算する必要あり)、またはグラフ上のバー数より大きければ、グラフ上のすべてのバーに対する全インディケータ値を再計算する必要があります。すなわちstart がゼロ。
次に、トレンドラインの計算サイクルと二番目の高値/安値のポジションがあります。バーの高値および安値の値分析は上記ルールによると、きわめてシンプルですので、説明は必要ないと思います。(GannMicroTrend.mq5ファイルのソーステキストを参照ください。)
トレンドラインのセクションを描くには、以下の簡単な関数を使用します。
//--------------------------------------------------------------------- // Drawing of a section //--------------------------------------------------------------------- void CreateCut(datetime _dt1, double _prc1, datetime _dt2, double _prc2, color _clr, int _wd) { string name = GetUniqName(prefix + " "); CChartObjectTrend* trend_obj = new CChartObjectTrend(); if(CheckPointer(trend_obj) != POINTER_INVALID) { trend_obj.Create(0, name, 0, _dt1, _prc1, _dt2, _prc2); trend_obj.Color(_clr); trend_obj.Width(_wd); trend_list_Ptr.Add(trend_obj); } }
ここで、グラフ内のユニーク名を取得するためにGetUniqName関数を使用します。詳細は、『 標準ライブラリクラス使用による独自のMarket Watch作成』に述べられています。トレンドラインのグラフィカルオブジェクトを問題なく作成した場合、パラメータが指定(色および線幅)され、このオブジェクトは CList:: Add メソッドを呼ぶことでラインリストに追加されます。
二番目の高値/安値ポジションを描くには、それぞれ CreateUpStopLoss/CreateDnStopLoss 関数を使います。それらは CreateCut 関数と似ており、それらのリストに作成したオブジェクトを追加します。
計算修了後、最新の高値および安値パラメータが表示されます。ここで、前ステップで作成したリストを使います。増加に応じて時刻ですでにソート済みのこれらリストを取得し、CList:: GetLastNode メソッドを呼ぶことで、高値または安値の最新オブジェクトを取得します。
記述のインディケータの動作結果は以下の図にあります。
図2 マイナートレンドのインディケータ
2.1. ミドルトレンド
ミドルトレンドのグラフはマーケット動向を表し、2本のバー(2つのバー動向)で描かれます。ミドルトレンドのグラフは図2に示しています。ミドルトレンドグラフを構築するルールについて簡単に考察していきます。
- 上昇中(次のバーの高値が前回の2本のバー動向の高値より高く、次のバーの安値が前回の2本のバー動向バーの安値より高い)、次の高値バーを2本のバー動向の前回高値と組み合わせ、中間トレンドの上昇傾向の線を引きます。
- 下降動向で(次のバーの安値が前回の2本のバー動向の安値より低く、次のバーの高値も前回の2本のバー動向バーの高値より低い)、次の安値バーを2本のバー動向の前回安値と組み合わせ、中間トレンドの下降傾向の線を引きます。
- 上昇中で次のバーの高値が前回の2本のバー動向の高値を越えず、同時に次回バーの安値が前回の2本のバー動向の安値を下回るとき、動きの方向は下降に転じます。
- 上昇中で次のバーの高値が前回の2本のバー動向の高値を越えず、同時に次回バーの安値が前回の2本のバー動向の安値を下回るとき、動きの方向は下降に転じます。
- いずれの動きについても、次回バーの安値が前回の2本のバー動向の安値より高く、同時に次回バーの高値が前回の2本のバー動向の高値を下回るとき、このバーは インサイド(図2参照)と呼ばれ、グラフ構成に加わりません。
- いずれの動きについても、次回バーの高値が前回バーの高値を上回り、同時に次回バーの安値が前回バーの安値を下回るとき、このバーは アウトサイド(図2参照)と呼ばれます。バーの方向(上昇あるいは下降)により、対応するグラフセグメントを構築します。
図3 ミドルトレンド
ミドルトレンド上昇の唯一の逆インディケータは、中央高値レベルの交点です。同様に、下降の唯一の逆インディケータは、中央安値レベルの交点です。
ミドルトレンドは上昇で、マーケットが中間スイング下降で、ミドルスイングの前回安値を更新しなければ、それは修正です。またミドルトレンドが下降で、マーケットがミドルスイング上昇、ミドルスイングの前回高値を更新しなければ、それも修正です。
2.2. GannMiddleTrend インディケータ
ミドルトレンドのグラフを表示するインディケータを作成します。見た目は図2と変わりません。また、画面に最新の高値および安値ポジションを表示する必要があります。このインディケータは本稿付属のGannMiddleTrend.mq5ファイルにあります。
グラフエレメントをレンダリングするため、このインディケータにはインディケータバッファおよび描画タイプDRAW_COLOR_SECTIONを使用します。これは、後に EA作成に必要となります。EAから本インディケータデータにアクセスするには、インディケータバッファを使用します。
画面上でのインディケータの表示パラメータは以下の命令により指定されます。
#property indicator_buffers 2 #property indicator_plots 1 #property indicator_type1 DRAW_COLOR_SECTION #property indicator_color1 LightGreen, LightPink #property indicator_width1 4
ここでは連続して指定します。
- インディケータバッファ数(データバッファおよびカラーインデックスのバッファの2つのみです。)
- 画面に表示されるグラフ数
- インディケータグラフのレンダリングタイプ(色づけされたセクションを用いてレンダリングします。)
- カラーインデックスバッファで指定可能な色
- インディケータグラフの線幅
OnInit 初期化関数では、インディケータバッファへの割当てをバインディングし、その他のインディケータパラメータを指定します。
これは以下に示すコード部分で行われます。
SetIndexBuffer(0, DataBuffer, INDICATOR_DATA); SetIndexBuffer(1, ColorBuffer, INDICATOR_COLOR_INDEX); IndicatorSetInteger(INDICATOR_DIGITS, Digits( )); IndicatorSetString(INDICATOR_SHORTNAME, "GannMiddleTrend"); PlotIndexSetString(0, PLOT_LABEL, "GannMiddleTrend"); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
ここでは連続して指定します。
- データバッファとしてインディケータ内で使用するバッファ(画面上のレンダリング用)
- インディケータグラフのセクション色を指定するバッファ
- 画面にインディケータ値を表示する間の小数点数
- 画面に表示されるインディケータの短縮名
- 画面に表示されるグラフィックシリーズ(データバッファ)名
- 画面に表示される(レンダリングせず)null値に対応している値
インディケータはミクロトレンドGannMicroTrendのインディケータに対するストラクチャおよび外部パラメータに似ています。異なるのは、ここではグラフィカルオブジェクトを使う代わりにインディケータバッファとカラーバッファに直接値を割り当てる点です。よって、実装の詳細は省きます。
インディケータの動作結果は以下の図にあります。
図4 中間トレンドインディケータ
ご覧のように、それは図3の手書きされたものと一致しています。
3.1. メイントレンド
メイントレンドのグラフはマーケット動向を表し、3本のバー(3つのバー動向)で描かれます。メイントレンドのグラフは図5に示しています。メイントレンドを構築するルールについて簡単に考察していきます。
- 上昇動向中(次のバーの高値が前回の3本のバー動向の高値より高く、次のバーの安値も前回の3本のバー動向バーの安値より高い)、次の高値バーを3本のバー動向の前回高値と組み合わせ、メイントレンドの上昇傾向の線を引きます。
- 下降動向で(次のバーの安値が前回の3本のバー動向の安値より低く、次のバーの高値も前回の3本のバー動向バーの高値より低い)、次の安値バーを3本のバー動向の前回安値と組み合わせ、メイントレンドの下降傾向の線を引きます。
- 上昇中で次のバーの高値が前回の3本のバー動向の高値を越えず、同時に次回バーの安値が前回の3本のバー動向の安値を下回るとき、動きの方向は下降に転じます。
- 上昇中で次のバーの高値が前回の3本のバー動向の高値を越えず、同時に次回バーの安値が前回の3本のバー動向の安値を下回るとき、動きの方向は下降に転じます。
- いずれの動きについても、次回バーの安値が前回の3本のバー動向の安値より高く、同時に次回バーの高値が前回の3本のバー動向の高値を下回るとき、このバーは インサイド(図5参照)と呼ばれ、グラフ構成に加わりません。
- いずれの動きについても、次回バーの高値が前回バーの高値を上回り、同時に次回バーの安値が前回バーの安値を下回るとき、このバーは アウトサイド(図5参照)と呼ばれます。バーの方向(上昇あるいは下降)により、対応するグラフセグメントを構築します。
図5 メイントレンド
メイントレンド上昇の唯一の逆インディケータは、メイン高値レベルの交点です。同様に、下降の唯一の逆インディケータは、メイン安値レベルの交点です。
基本トレンドが上昇で、マーケットが下降スイングを形成しながらも、前回安値スイングを更新しなければ、それは修正です。またメインレンドが下降で、マーケットが上昇スイングを形成しながらも、ミドルスイングの前回高値を更新しなければ、それも修正です。
3.2. GannMainTrendインディケータ
メイントレンドのグラフを表示するインディケータを作成します。見た目は図5と変わりません。また、画面に最新の高値および安値ポジションを表示する必要があります。このインディケータは本稿付属のGannMainTrend.mq5ファイルにあります。
インディケータはミドルトレンドGannMiddleTrendのインディケータに対するストラクチャおよび外部パラメータとそっくりです。よって実装については説明を省きます。インディケータの動作結果は以下の図にあります。
図6 メイントレンドのインディケータ
4. スイングチャートを用いたトレーディング
これで、「モデル」に関してマーケットを分析するインスツルメントがそろいました。すなわち、ミクロ、ミドル、メイントレンドのインディケータです。ここから、価格スイングを基にしたシンプルなトレーディングシステムを作成します。
James Hyerczyk氏の本では、以下の戦略が提案されています。
- 長期下降(または上昇)動向セクションを特定する
- 停滞、横方向の動き、マーケット形成後、最新スイングの高値以上で買い発注を行う(安値以下での売り)
- プロテクティブストップは最新スイングの安値のちょうど下(高値のちょうど上)にセットする。
- ポジションをオープンした後、生成された新規スイングの安値(高値)の下でストップは価格について移動する。
これを図に描いてみます。
図7 スイングトレード
極端に高い価格レベルでは、ショートに、極端に低い価格レベルでは、ロングに行く可能性を考慮することが推奨されます。図7はミドルトレンドのグラフを表示します。メイントレンドのグラフで長期動向のセクションを特定します。メイントレンドのグラフで『停滞』マーケットのセクションを特定します。ポジションはミドルトレンドグラフで観測します。
以下は同じセクションがメイントレンドグラフに表示された場合です。
図8 メイントレンドチャートのセクション
長期下降動向(スイング)はメイン高値1.36913 とメイン安値 1.18758の間です。この動向は 1815.5と4桁ポイントを取ります。そして、ほとんど横ばいの1.24664~ 1.21495の『停滞』マーケットセクションがきます。(図7参照)この動きは 316.9 ポイントを取ります。この後、価格はミドルトレンドグラフの最新スイングのミドル高値レベルを突破し、上昇となります。
初期ストップはミドル安値と最新スイング 1.21495のちょうど下に設定し、ミドルトレンドグラフでポジション観測を行います。このトレードの結果、 およそ1.31186 - 1.23966 = 722.0 ポイントの収益を得ます。
5. MQL5 ウィザードで使用するためのトレードシグナルクラス
トレーディングシステムの実装に向けたコードを作成する前に、トレード全体像をスキームとしてイメージしていきます。下図について考察します。
図9 ロングポジショントレーディング
「買い」ポジションの調整は以下で構成されます。
- メイントレンドグラフによって、長期下降動向(図9のセクションA~B)を定義します。動きの継続期間および影響はそれぞれパラメータ dT と dPで指定されます。これらパラメータの値は本インスツルメント履歴をよく見た上で判断する必要があります。
- メイントレンドグラフ(図9ポイントB)上の主要ボタン作成後、ミドルトレンドグラフにポイントC と D が作成されるのを待ちます。これらポイントは、ポイント Bを併せ、ミドルのスイングB-C およびC-Dにからきます。これらスイングの継続と影響が指定値を越えなければ、それらは横ばい傾向(または『停滞』マーケット)になると推測します。
- ミドル C 高値(または、C後に形成される直近のミドル高値)に到達するのを待ちます。ミドル C 高値を越えたのち、ストップをポイントDのミドル安値(または、C後に形成される直近の中間下降)のちょうど下にセットします。
- 形成されたミドル安値の下(ポイントF と Lのすぐ下)にストップを移動しつつ、上昇の動きが継続するポジションを観測します。
- 資本管理モードによって、ポジションボリュームに、形成されたミドル高値(ポイントG とM)の突破ポイントで追加が可能です。
よって、Expert Advisorを構築するには、次のコンポーネントが必要です。売り/買いシグナルを生成するモジュール、オープンしているポジションのトレーリングストップモジュール、また可能であれば『階層』ポジションを管理する(資本管理)モジュール
本項執筆には以下の記事を利用しています。『MQL5ウィザード: オープンポジションのトレーリングモジュール作成方法』、『MQL5 ウィザード: リスクおよび資本管理モジュール作成方法』
トレーディングシグナル作成に関わるモジュール開発は以下のように行います。
- 標準mqhファイルをインクルードするためのプロセッサ命令を追加します。そこにはExpert Advisor作成のためのすべての基本クラスが含まれています。これは次の方法で行われます。
#include <Expert\ExpertSignal.mqh>
トレーディングシグナルを生成するモジュールの冒頭部分にこの命令を挿入します。- コマント形式での特殊ストリングの追加は MetaEditor エディタに対して、このファイルが EA作成の際使用される必要があることを指示しています。
// wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signal based on swings on charts | //| of the middle and main trends according to Gann (iCustom) | //| Type=Signal | //| Name=TGannBreakSignal | //| Class=TGannBreakSignal | //| Page= | //| Parameter=MinMainSwingContinuance,int,5 | //| Parameter=MinMainSwingSize,double,300.0 | //| Parameter=MinMiddleSwingContinuance,int,3 | //| Parameter=MaxMiddleSwingSize,double,200.0 | //| Parameter=OpenPriceSpace,double,5.0 | //| Parameter=StopLossSpace,double,5.0 | //+------------------------------------------------------------------+ // wizard description end
ここにパラメータ Title があります。これはモジュール名を特定し、 EA 作成中MetaEditorリストに表示されます(下記記述を参照ください)。重要なパラメータ :Type これは既定のモジュールがシグナル生成モジュールであることを判断します。また、外部パラメータおよびその初期値も含まれます。
これらすべての行は標準ファイルExpertSignal.mqhのインクルード命令後即座に追加されます。
- 基本クラスの継承クラス記述は ExpertSignal.mqhファイルにあります。このクラスは基本クラスCExpertSignal に足りない関数を実装します。クラス記述は以下のようなものです。(基本部分でない箇所はここでゃ省いています)
class TGannBreakSignal : public CExpertSignal { private: int min_main_swing_continuance; // minimum swing duration time of the main tren double min_main_swing_size_points; // minimum swing amplitude on the chart of the main trend int min_middle_swing_continuance; // minimum swing duration time on the chart of the middle trend double max_middle_swing_size_points; // maximum swing amplitude of the chart of the middle trend double open_price_space; // distance between the open price and peak/bottom double stop_loss_space; // distance between the stop loss price and peak/bottom datetime main_swing_lf_datetime; // time of left point of a swing on the chart of the main trend double main_swing_lf_price; // price of left point of a swing on the chart of the main trend datetime main_swing_rt_datetime; // time of right point of a swing on the chart of the main trend double main_swing_rt_price; // price of right point of a swing on the chart of the main trend int main_swing_continuance; // swing duration time on the chart of the main trend double main_swing_size_points; // swing amplitude (in points) on the chart of the main trend datetime middle_swing_lf_datetime; // time of left point of a swing on the chart of the middle trend double middle_swing_lf_price; // price of left point of a swing on the chart of the middle trend datetime middle_swing_rt_datetime; // time of right point of a swing on the chart of the middle trend double middle_swing_rt_price; // price of right point of a swing on the chart of the middle trend int middle_swing_continuance; // swing duration time on the chart of the middle trend double middle_swing_size_points; // swing amplitude (in points) on the chart of the middle trend int handle_main_swing; int handle_middle_swing; double main_swing_buff[]; double middle_swing_buff[]; datetime time_buff[]; double price_buff[]; public: TGannBreakSignal(); // constuctor ~TGannBreakSignal(); // destructor // Settings: void MinMainSwingContinuance(int _cont); void MinMainSwingSize(double _size); void MinMiddleSwingContinuance(int _cont); void MaxMiddleSwingSize(double _size); void OpenPriceSpace(double _space); void StopLossSpace(double _space); int GetMainSwingContinuance(); // gets swing duration time on the chart of the main trend double GetMainSwingSizePoints(); // gets swing amplitude (in 4-digit points) on the chart of the main trend int GetMiddleSwingContinuance(); // gets swing duration time on the chart of the middle trend double GetMiddleSwingSizePoints(); // gets swing amplitude (in 4-digit points) on the chart of the middle trend // overloaded methods of the CExpertSignal class: virtual bool ValidationSettings(); virtual bool CheckOpenLong(double &price,double &sl,double &tp,datetime &expiration); virtual bool CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration); virtual bool InitIndicators(CIndicators *indicators); // Additional methods: protected: // Sets swing parameters of the main trend void SetMainSwingParameters(datetime _lf_dt,double _lf_price,datetime _rt_dt,double _rt_price); // Sets swing parameters of the middle trend void SetMiddleSwingParameters(datetime _lf_dt,double _lf_price,datetime _rt_dt,double _rt_price); // Gets swing parameters of the main trend int GetMainSwing(); // Gets swing parameters of the middle trend int GetMiddleSwing( ); };
データメンバの目的はコメントにより明白です。クラスのメソッドをいくつか見ます。
まず、基本クラスメソッドを再定義する必要があります。最初のメソッドはEAの指定された外部パラメータの正確性を確認するのに使用されます。
//--------------------------------------------------------------------- // Validation of settings //--------------------------------------------------------------------- bool TGannBreakSignal::ValidationSettings() { if(this.min_main_swing_continuance<=0) { Print("Wrong Parameter: min_main_swing_continuance = ", this.min_main_swing_continuance); return(false); } if(this.min_main_swing_size_points<=0.0) { Print("Wrong Parameter: min_main_swing_size_points = ", DoubleToString(this.min_main_swing_size_points,1)); return(false); } if(this.min_middle_swing_continuance<=0) { Print("Wrong Parameter: min_middle_swing_continuance = ", this.min_middle_swing_continuance); return(false); } if(this.max_middle_swing_size_points<=0.0) { Print("Wrong Parameter: max_middle_swing_size_points = ", DoubleToString(this.max_middle_swing_size_points,1)); return(false); } return(true); }
ここでは、外部パラメータの正確性について簡単なチェックを行います。スイング(ポイント表示)のサイズとバー内の継続時間はゼロ以下にはならないことは明らかです。誤った指定をされた外部パラメータについては、メソッドが falseを返します。
次に、ポジションのオープンに対するシグナルを生成するメソッドについて考察します。
ロングポジションのオープンについてのチェックは、基本クラスから派生したメソッドによって、以下のように行われます。
//--------------------------------------------------------------------- // Checks conditions to open long position //--------------------------------------------------------------------- bool TGannBreakSignal::CheckOpenLong(double &_price,double &_sl, double &_tp,datetime &_expiration) { if(this.GetMainSwing()==-1) { return(false); } if(this.GetMiddleSwing()==-1) { return(false); } // If the main swing upward, exit if(this.main_swing_rt_price>=this.main_swing_lf_price) { return(false); } // If the middle weak swing isn't formed, exit: if(this.middle_swing_rt_price>=this.middle_swing_lf_price) { return(false); } // Check swing parameters on the main trend chart if(this.main_swing_continuance<this.min_main_swing_continuance || this.main_swing_size_points<this.min_main_swing_size_points) { return(false); } // Check swing parameters on the middle trend chart if(this.middle_swing_continuance<this.min_middle_swing_continuance || this.middle_swing_size_points>this.max_middle_swing_size_points) { return(false); } double unit=this.PriceLevelUnit(); // If the price has crossed the peak of the weak middle swing, set signal to open long position: double delta=this.m_symbol.Bid() -(this.middle_swing_lf_price+this.open_price_space*unit); if((delta>=0.0) && (delta<(10.0*unit))) { _price=0.0; _sl = this.m_symbol.NormalizePrice(this.middle_swing_rt_price - stop_loss_space*unit); _tp = 0.0; return(true); } return(false); }
最初に、メイントレンドおよびミドルトレンドグラフに対して最新スイングのパラメータを取得するためのメソッドが呼ばれます。TGannBreakSignal::GetMainSwing とTGannBreakSignal::GetMiddleSwingです。これらメソッド呼び出しに問題なければ、スイングのパラメータを分析することができます。
ロングポジションのオープンに関するシグナルの有無を確認しているので、スイングは下向きです。ポイント A と Bのポジションを比較します。(図9参照)ポイント B の価格がポイント Aよりも低ければ、価格スイングは下向きです。
次に、ポイント C および Dの有無を確認します。(図9参照)また、ポイント D の価格はポイントCよりも低い必要があります。この条件が満たされていれば、メイントレンドとミドルトレンドのスイングパラメータを確認します。. 動きの継続時間と影響が確認されます。
以前の確認がすべてうまくいっていれば、価格がミドルスイングの高値をクロスしているかどうか最終確認が行われます。確認が行われたら、ストップ値が書き込まれ、結果trueが返されます。
ショートポジションのオープンが必要かどうかの確認はメソッドTGannBreakSignal:: CheckOpenShortを呼んで行われます。これは、 TGannBreakSignal:: CheckOpenLong,メソッドに似た確認をしますが、価格軸で同じように行われます。
これで、トレーディングシグナル生成に関係ある基本メソッドとモジュールのストラクチャ確認ができました。上述のモジュールは GannTrendSignal.mqhファイル内の記事に添付されています。
二番目に必要なモジュールはオープンポジションのトレードストップモジュールです。このモジュールも基本クラスから派生しており、以下で構成されています。
- 標準 mqh ファイルをインクルードするためのプリプロセッサ命令の追加。,これにはポジショントレーリングのためのコードを作成する基本クラスが含まれます。
これは次の方法で行われます。
#include <Expert\ExpertTrailing.mqh>
ポジショントレーリングのモジュール冒頭部分にこの命令を挿入します。
- 特別な追加ストリングはコメントとして、EA内でポジショントレーリングの生成にこのファイルが使用されるエディタを示します。
// wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Trailing on peaks/bottoms on the chart of the middle trend | //| Type=Trailing | //| Name=MiddleTrend | //| Class=MiddleTrendTrailing | //| Page= | //| Parameter=StopLossSpace,double,5.0 | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+
ここでは、パラメータType が「トレーリング」値として設定されます。このモジュールがポジション(トレーリング)をサポートするのに使用する必要があります。また、外部パラメータおよびその初期値も含まれます。
記載の行はすべて、基本ファイル ExpertTrailing.mqhのインクルードの命令の直後に追加されます。
- 基本クラスの継承クラス記述は ExpertTrailing.mqhファイル内にて行われます。このクラスは基本クラスCExpertTrailing に足りない関数を実装します。クラス記述は以下のようなものです。(基本部分でない箇所はここでゃ省いています)
class MiddleTrendTrailing : public CExpertTrailing { private: datetime middle_swing_lf_datetime; // time of left point of a swing on the chart of the main trend double middle_swing_lf_price; // price of left point of a swing on the chart of the main trend datetime middle_swing_rt_datetime; // time of right point of a swing on the chart of the main trend double middle_swing_rt_price; // price of right point of a swing on the chart of the main trend double stop_loss_space; // the distance between peak/bottom and stop loss price int handle_middle_swing; double middle_swing_buff[]; datetime time_buff[]; double price_buff[]; public: MiddleTrendTrailing(); // constructor ~MiddleTrendTrailing(); // destructor private: int GetMiddleSwing(); // get parameters of the middle swing public: // Settings: void StopLossSpace(double _space); // Overloaded methods of CExpertTrailing class: virtual bool ValidationSettings(); virtual bool InitIndicators(CIndicators *indicators); virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp); virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp); };
ここのクラスで再定義された基本メソッドはTMiddleTrendTrailing:: CheckTrailingStopLong および MiddleTrendTrailing:: CheckTrailingStopShortです。両者ともそれぞれロングポジション、ショートポジションのストップロス変更用条件確認を行います。
メソッド MiddleTrendTrailing:: CheckTrailingStopLong に関して詳細を見ていきます。
//--------------------------------------------------------------------- // Checks conditions of trailing stop for long position //--------------------------------------------------------------------- bool MiddleTrendTrailing::CheckTrailingStopLong(CPositionInfo *_position,double &_sl,double &_tp) { if(_position==NULL) { return(false); } if(this.GetMiddleSwing()==-1) { return(false); } double sl_req_price = this.m_symbol.NormalizePrice(MathMin(middle_swing_lf_price,middle_swing_rt_price) - this.stop_loss_space * this.m_adjusted_point ); if(_position.StopLoss() >= sl_req_price ) { return(false); } _tp = EMPTY_VALUE; _sl = sl_req_price; return(true); }
まず、ミドルトレンドグラフにおける最新スイング。TGannBreakSignal:: GetMiddleSwingのパラメータ取得のためにメソッドを呼びます。このメソッドが問題なく呼びだされたら(ゼロ値を返したら)スイングのパラメータを分析することができます。
次に、取得したスイングパラメータに基づき、ストップロスセットのための価格レベルを計算します。計算されたストップロスレベルが現在のレベルより低い場合(ロングポジションに対して)は、メソッド _sl に新しい値sl_req_price を書き、trueを返します。それ以外はfalse を返します。これはストップロスレベルが変更を要求しないことを意味しています。
ショートポジションに対するストップロスの変更必要性チェックのメソッドは類似体として構築します。
これで、オープンポジションのトレーリングに関係ある基本メソッドとモジュールのストラクチャ確認ができました。記載のモジュールは GannTrailing.mqhファイル内の記事に添付されています。
トレーディングシグナルに基づく EA 作成
テンプレートによる "Masters MQL5"を使用したEA 作成はきわめて単純なタスクです。いくつかの連続した手順があります。
- ステップ 1
メインメニュー MetaEditor'a File / Newのコマンドを使用し、EA 作成マスタを呼びます。画面に以下のビューのダイアログウィンドウが表示されます。
図10 MQL5 ウィザードにて既製のExpert Advisorダイアログ作成
「EA (作成)」と書かれた『ラジオボタン』を選択し、「次へ」ボタンをクリックします。EA作成の次のステップに進みます。
- ステップ 2
このステップでは、EA の一般的パラメータを指定します。名前、「マジック」ナンバー等そうすると、次のダイアログウィンドウが表示されます。
図11 Expart Advisorの一般的プロパティ
パラメータ EveryTick の値を trueに指定します。ティックごとにEA を動作させる必要があります。「マジック」ナンバーは変更しないままにします。「次へ」ボタンをクリックし、次のステップに進みます。
- ステップ 3
本ステップでは EAへのシグナルのパラメータを指定します。まず、リストからシグナルの特定タイプを選択します。
図12 トレードシグナルモジュールの選択
前に書かれたシグナル名を選択すると、以下のタイプのダイアログが画面に表示されます。
図13 トレーディングシグナルモジュールの入力パラメータ
必要に応じ、パラメータの初期値の修正を行うことが可能です。再び「次へ」ボタンをクリックし、次のステップに進みます。
- ステップ 4
このステップでは、オープンポジションをサポートするためのトレーリングタイプを選択します。リストからどれでも選択可能ですが、以前に作成したトレーリングストップメソッドを選択することとします。
図14 トレーリングポジションタイプ選択
そうすると、次のようなダイアログウィンドウが表示されます。
図15 トレーリングパラメータの指定
ここで、指定された外部パラメータに対する初期値を調整することが可能です。「次へ」ボタンを押し、次のステップに進みます。
- ステップ 5
図16 資金管理パラメータの指定
ここでは、資本管理パラメータの選択が可能です。(取引きロット計算メソッド)現状維持とします。固定トレーディングボリュームにてのトレーディング「終了」ボタンを押すと特定の名前、ポジションオープンのアルゴリズム、トレーリング、資本管理ルールを伴いすぐに利用可能なEA が作成されます。
作成された EA が動作するか検証します。
図17 作成済みExpert Advisorの検証
正しく特定されたトレンドが、完全に取り込まれているか(本メソッドの許容範囲内で)確認することができます。さらに、一般的判断により指定された初期設定のパラメータを使用しました。
おわりに
ギャン理論の最初の部分のみ、そしてモデルとしてトレーディングシステムとマーケット分析にそれを適用することについて考察をしてきました。適用の最良結果はグラフがバーに分割される、トレードの自然なまとまりに相当する期間に出るようです。
株式市場については、これは日次、週次、月次周期のトレードです。通貨市場には、これは取引周期によるトレードです。金融商品市場では、これは日次、週次、月次周期のみならず、マーケットの季節変動も扱うトレードです。
追記
余分な研究をすることにしました。直接今回の話題に関連ある事柄ではなく、ギャン理論の考え方について、です。さらに具体的に言うと、「変動中に価格はいわゆる 『ラウンド』レベルを達成するのか?ということです。ユーロおよび株式に対し金額50と100で終了する価格レベルです。(日本円について『ラウンド価格』レベルは40で終了するものです。)
これには、小数点以下の最後の数字についての高値/安値の分布図を作成します。5桁の相場に関しては、小数点以下最後に3桁あります。(最後の桁は10分の1ポイントです。)日次バーとしてミドルトレンドグラフを利用します。
円形軸上で、価格の最後の桁をゼロから50までプロットします。また、縦軸には、これらレベルで形成された高値/安値の数字をプロットします。高値、安値、合計額と個別に作成します。
2000年、日次時間枠で主要な通貨ペアに対する結果があります。
この結果をどのように解釈できるでしょうか?まず、図にはひずみがあります。すなわち、すべての価格値が同等に高値/安値を形成しているのではなさそうだということです。そして次に、これらの値は「ラウンド」値として正確に一致しているわけではありません。これはもともと予想したことです。これがトレードに使用可能かどうかとなると難しいところです。これにはもう少しつっこんだ研究が必要です。おそらく、実用という見地からすると、株式市場においてもっと興味深い結果が得られることでしょう。
すくなくとも、これは履歴分析のための別のインスツルメントでありその類の中では悪くなさそうなものです。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/219





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索