![知っておくべきMQL5ウィザードのテクニック(第25回):多時間枠のテストと取引](https://c.mql5.com/2/82/MQL5_Wizard_Techniques_you_should_know_Part_25_600x314.jpg)
知っておくべきMQL5ウィザードのテクニック(第25回):多時間枠のテストと取引
はじめに
前回の記事では、ピタゴラス平均について見ました。ピタゴラス平均は移動平均のグループであり、テストレポートで示唆したように、一部のトレーダーに利益をもたらす可能性があるにもかかわらず、その一部は非常に目新しく、十分に普及していません。これらのピタゴラス平均は、半円の直径に加算される2つの不等な値を提示したときに各平均値が何であるかをまとめた半円図で表されました。記事では触れられていない半円内の弦の値の中には、2つの値aとbの二乗平均平方根を表す「Q」として示される値がありました。
Quadratic Mean(QM、二乗平均平方根はRoot Mean Square (RMS)とも呼ばれます。平均値としては、平均値が求められる集合内のより大きな値に重み付けされる傾向があり、これは前回の記事で見た幾何平均や調和平均とは異なります。また、幾何平均は正の値しか返さないので、平均を求めるサンプル集合は正の値だけを持つ必要があります。しかし、この記事のタイトルは、ウィザードで組み立てられたEAに多時間枠戦略を実装するとあり、QMは単に、ウィザードで構築されたEAで複数の時間枠をテストする方法を示すために使用するツールです。
では、なぜウィザードで作成したEAでは複数時間枠でのテストが難しいのでしょうか。私の意見では、このカスタマイズはウィザードのアセンブリスペースで追加された各シグナルに対しておこなわれるべきであり、これがしばしば見落とされるからです。ウィザードで組み立てたEAの銘柄名と時間枠のカスタマイズは、ウィザードのシグナル選択ステップでおこなうことができます。多くの場合、一度シグナルを選択すると、銘柄と期間を選択することになると思われがちですが、ウィザードの組み立てではそうではないはずです。この以前の記事では、組み立てられたソースコードを修正することで、ウィザードで組み立てられたEAの複数銘柄取引に対応するさまざまな方法を紹介しました。私が共有しなかった明白かつ主要なアプローチの1つは、複数のシグナルの添付を実行することです。各シグナルの添付は特定の銘柄用になります。まったく同じシグナルを添付しているにもかかわらず、このような複数の添付が発生します。銘柄を割り当てる際のシグナルのカスタマイズは、以下に示す手順でおこなう必要があります。
同様に、シグナル内のEAごとに複数時間枠を入力パラメータとしてカスタマイズすることができます(このサンプルコードを添付します)。しかし、望ましいアプローチとしては、必要な時間枠をそれぞれシグナルに割り当て、ウィザードアセンブリでこのシグナルを独立して取り付けることが考えられます。各シグナルの時間枠をカスタマイズする手順は、多銘柄取引で上記でお伝えしたことと非常によく似ています。
多時間枠戦略は、例えば、より速い(またはより短い)時間枠での短期的な弱気トレンドが、より長い時間枠での主要な強気トレンドを背景に起こっている場合、主要なシグナルとなる可能性があるなど、追跡した時間枠間のダイバージェンスの機会を探す場合などに役立ちます。あるいは、複数時間枠の戦略は、2つまたは複数のテストされた時間枠の間の確認設定を中心に発展させることができます。これらの理由やその他の理由から、ウィザードで組み立てたEAでの多時間枠戦略の実装について掘り下げていきます。
同様に、この記事で既にみた多銘柄取引についても、トレーダーの可能性は確実に広がります。この記事では、アービトラージの設定で互いに相殺し合う可能性のある3つの通貨ペアを考えますが、ヘッジされたアービトラージシステムを開発したりテストしたりするのではなく、すべてのペアが1つのEAで取引されている場合に共通する移動平均の設定があれば、それを探ってみたいと思います。
多時間枠取引や多銘柄取引は非常に興味深いものですが、ウィザードで組み立てられたEAがどのようにコードされているかによって、ウィザードの組み立て時に並列または複数のシグナルが追加され、追加された各シグナルが特定の銘柄や時間枠に対応するという固有の設計になっています。この主な原因は、ウィザードで組み立てられたEAの初期化フェーズにあると私は考えています。CExpertBaseクラスには4つの初期化フェーズがあり、シグナルだけでなく資金管理やトレーリングストップ管理のアンカークラスとしても機能します。これらのフェーズは、初期化の開始、パラメータ値の設定、パラメータ値のチェック、そして最終的な初期化の終了です。
具体的には、パラメータ設定段階では、Expertシグナルクラスのインスタンスに取引銘柄と時間枠が割り当てられます。ドキュメントによると、これはパラメータチェックの段階でも起こり得ます。パラメータを設定する段階をチューニング段階と呼ぶのだと思いますが、その旨の文書を見つけることができませんでした。そのため、取引銘柄は、どのOHLC価格をロードするか、ポイントサイズなど、シグナルクラスが依存するパラメータの多くを決定するため、これは設計上、初期化時に一度設定されるものです。同様に、OHLC価格バッファを取得するために使用される時間枠は、事前に決定される必要があり、これはまた、初期化中に発生し、後に発生することはありません。
したがって、このような設計上の制約から、複数の銘柄と時間枠を使用する意図的な方法は、これらの銘柄と時間枠の値が定数パラメータとして機能するように、ウィザードの組み立て中にシグナルクラスのインスタンスが事前に割り当てられることを意味します。
しかし、このウィザード内の事前割り当て体制で多銘柄を取引する場合、まだ注意点があります。多通貨の 記事で見たように、CExpertクラスの配列インスタンスを作成し、この配列内の各EAクラスのインスタンスに目的の取引銘柄を再割り当てする必要があります。ウィザードの銘柄割り当てがおこなうのは、USED_SERIES列挙の下でOHLC価格データを取得する際に使用される銘柄を決定することだけであるようです。しかし、m_symbol Symbol-Infoクラスで初期化された後に取引される実際の銘柄は、ウィザードの最初のステップで割り当てられる銘柄であり、シグナルが選択される前のものです。
多銘柄取引におけるこの制約は、多時間枠取引には反映されません。ウィザードの組み立て中に時間枠をシグナルに割り当てるだけで、EAが取引を開始すると、割り当てられた時間枠がシグナル処理に使用されるようになるからです。
初期化における調整フェーズの意味
取引銘柄や時間枠のカスタマイズは初期化時にしか設定できないため、この制約があると、いったんEAが組み立てられると、取引可能な銘柄や理想的な時間枠を探索したり最適化したりすることができません。この回避策として、求められた取引銘柄または時間枠をカスタムシグナルクラスの入力パラメータとして使用する方法があります。このような入力パラメータは、それぞれ文字列と時間枠の列挙の形をとります。一般的に、カスタム時間枠の値の割り当ては、すでに設定されているENUM_TIMEFRAMES列挙から選択するため、より簡単なはずです。しかし、取引用の銘柄名に関しては、入力された銘柄名が実際に有効で、気配値表示に掲載され、取引可能であることを確認するために、特別なステップや機能を使用する必要があります。
二次移動平均
英語ではQuadratic Averages (QA)ともRoot Mean Square (RMS)とも呼ばれる二乗平均平方根は、単に集合内のすべての2乗値の平均の平方根です。ほとんどの非算術平均と同様に、これらにはバイアスまたは優先重み付けがあり、これは幾何平均や調和平均とは異なり、セット内のより大きな値に向けられます。前回の記事で示した半円図では、2つの等しい値aとbの異なるタイプの平均が半円内のスケールに表され、2 次平均も示され、Qでマークされた弦の長さに等しくなりました。
![](https://c.mql5.com/2/82/4748754854977.png)
ここで
- nは集合内の値の数
- xはそれぞれのインデックスにおける集合の値
QMを使用して、複数の時間枠で取引するカスタムシグナルと、複数の銘柄で取引する別のカスタムシグナルを開発し、テストしています。前回の記事では、幾何平均と調和平均のセットでは小さい値への偏りや選好の重み付けがあるため、大きい値への偏りを持つミラー平均を開発しました。MQL5におけるQMの実装は以下のコードで示されています。
//+------------------------------------------------------------------+ //| Quadratic Mean | //+------------------------------------------------------------------+ double CSignalQM::QM(int Index, int Mask = 8) { vector _f; _f.CopyRates(m_symbol.Name(), m_period, Mask, Index, m_length); vector _p = _f*_f; double _m = _p.Mean(); return(sqrt(_m)); }
可能性のあるアプリケーションを掘り下げて調べ始める前に、QMはより大きな値に傾いているので、QM'とラベル付けされたミラー平均をより小さな値に重みを置くことによって、QMについても同様のことをするのが賢明でしょう。このように、値の重みを小さくするのと大きくするのとで、低価格バッファと高価格バッファをそれぞれ導き出すことができます。
前回の記事では、エンベロープ(ボリンジャーバンド)とダイバージェンスシグナルを生成するために、これらのバッファペアを使用しました。この2つのアプリケーションの他に、例えばOSMAシグナルを導き出せば、別のアプリケーションを生み出すことができます。しかし、この記事の主な目的はQMや平均の紹介そのものではなく、複数の銘柄の取引と複数の時間枠での取引であるため、すでに前の記事で紹介したアプリケーションにこだわることにします。いつものように、読者はQMの他の実装方法を探求するために、添付のコードを独自に変更することができます。
QMのミラーである「QM'」は、前回の記事で紹介したものと同様の式で与えることができます。
//+------------------------------------------------------------------+ //| Inverse Quadratic Mean | //+------------------------------------------------------------------+ double CSignalQM::QM_(int Index, int Mask = 8) { double _am = AM(Index, Mask); double _qm = QM(Index, Mask); return(_am + (_am - _qm)); }
この公式の中心的なテーゼは、算術平均が最も公平で公正な平均を提供するということであり、この生の算術平均を鏡の線と見なせば、この平均から別の平均までのどのような距離も「鏡に映す」ことができるということを示唆しています。したがって、これを実装するMQL5のソースコードは、すでに私たちが共有したものと同じであり、ここでは共有しません。以下に添付します。
今回も、多銘柄多時間枠取引を紹介することが目的です。2種類のEAです。従って、QMをボリンジャーバンドシグナルとして使用することもできるし、ダイバージェンスシグナルを使用することもできます。両方の実装は前回の記事ですでに紹介されています。
上記で強調したように、MQL5ウィザードが組み立てたEAは、シグナルごとに多時間枠多銘柄のテスト(および取引)ができるように設計されています。EAで使用される各シグナルは、ウィザードで追加される前にカスタム銘柄と時間枠を取得します。このことは、多銘柄多時間枠についてどのようなシグナルでもテストできたことを意味しますが、前回は新奇な平均について調べたばかりなので、今回はその続きとして二乗平均平方根を取り上げます。
QMAによるカスタムシグナルクラスの開発
多通貨銘柄EAのテストはおこないません。なぜなら、ウィザードで組み立てられているものは、この記事ですでに取り上げた修正が必要だからです。上述したように、多銘柄と多時間枠のEAのテストは、これらの銘柄と時間枠の値がシグナルごとに割り当てられているため、同じシグナルファイルでおこなうことができます。ロングとショートの条件の処理は、前回の記事で幾何平均のシグナルを生成したときの全体的なアプローチに従います。しかし、前回の記事ではシグナルを1つしか扱っていなかったため、弱気シグナルを探すときに探した上限バンドのプライスクロスや、強気シグナルを探すときに探した下限バンドのクロスなど、鋭いエントリポイントを探す余裕があったが、今回は少し変更します。
この記事では、複数のシグナルを並行して扱っているため、すべてのシグナルが同時にクロスする可能性は低く、そのような鋭いエントリポイントを探す代わりに、2つのバンドの基準線に対して終値がどれだけ上(弱気の場合)または下(強気の場合)にあるかを測定することで、バンドを強気と弱気の確率ゲージとして使用します。つまり、現在の終値が基準線より上にあればあるほど弱気のウェイトが高くなり、同様に終値が基準線より下にあればあるほど強気のウェイトが高くなります。
つまり、使用されたシグナルはそれぞれ異なる時間枠で作動し、それぞれの終値の位置によって強気または弱気の条件を提供します。そして、これらの条件は、加重平均によって、個々の最適化されたシグナルの重みを用いて組み合わされ、1つの条件となります。この平均によって、現在のポジションをクローズできるかどうか、また新規ポジションを建てるかどうかが決定されます。修正した売買条件のコードを以下に示します。
//+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalQM::LongCondition(void) { int result = 0; m_close.Refresh(-1); if(m_close.GetData(StartIndex()) > m_close.GetData(StartIndex() + 1) && m_close.GetData(StartIndex()) > BandsDn(StartIndex()) && m_close.GetData(StartIndex() + 1) < BandsDn(StartIndex() + 1)) { result = int(round(100.0 * ((m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1))/(fabs(m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1)) + fabs(BandsUp(StartIndex()) - BandsDn(StartIndex())))))); } return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalQM::ShortCondition(void) { int result = 0; m_close.Refresh(-1); if(m_close.GetData(StartIndex()) < m_close.GetData(StartIndex() + 1) && m_close.GetData(StartIndex()) < BandsUp(StartIndex()) && m_close.GetData(StartIndex() + 1) > BandsUp(StartIndex() + 1)) { result = int(round(100.0 * ((m_close.GetData(StartIndex()+1) - m_close.GetData(StartIndex()))/(fabs(m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1)) + fabs(BandsUp(StartIndex()) - BandsDn(StartIndex())))))); } return(result); }
実践的な実装とテスト
上記のシグナルを使用するEAがウィザードで組み立てられると、複数の時間枠を使用している場合、*MQ5ファイルのヘッダー部分は以下のようになります。
//+------------------------------------------------------------------+ //| qm.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include <Expert\Expert.mqh> //--- available signals #include <Expert\Signal\My\SignalWZ_25.mqh> //--- available trailing #include <Expert\Trailing\TrailingNone.mqh> //--- available money management #include <Expert\Money\MoneyFixedMargin.mqh> //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ //--- inputs for expert input string Expert_Title = "qm_frame"; // Document name ulong Expert_MagicNumber = 2028; // bool Expert_EveryTick = false; // //--- inputs for main signal input int Signal_ThresholdOpen = 10; // Signal threshold value to open [0...100] input int Signal_ThresholdClose = 10; // Signal threshold value to close [0...100] input double Signal_PriceLevel = 0.0; // Price level to execute a deal input double Signal_StopLevel = 50.0; // Stop Loss level (in points) input double Signal_TakeLevel = 50.0; // Take Profit level (in points) input int Signal_Expiration = 4; // Expiration of pending orders (in bars) input int Signal_0_QM_Length = 50; // QM(50) H1 Averaging Length input double Signal_0_QM_Weight = 1.0; // QM(50) H1 Weight [0...1.0] input int Signal_1_QM_Length = 50; // QM(50) H4 Averaging Length input double Signal_1_QM_Weight = 1.0; // QM(50) H4 Weight [0...1.0] input int Signal_2_QM_Length = 50; // QM(50) D1 Averaging Length input double Signal_2_QM_Weight = 1.0; // QM(50) D1 Weight [0...1.0] //--- inputs for money input double Money_FixMargin_Percent = 10.0; // Percentage of margin
見てわかるように、移動平均の長さパラメータと重み付けパラメータを、選択した3つの時間枠(この場合はPERIOD_H1、PERIOD_H4、PERIOD_D1)にそれぞれ割り当てています。EAで生成されるシグナルは、終値とボリンジャーバンドのベースラインとの距離の加重平均であるため、前回の記事で幾何平均を使って探った急激なエントリとは異なり、いつでもシグナルがあることを意味します。つまり、ストップロスやテイクプロフィットのようなエグジット用のプライス目標なしでテストをおこなうのは良いアイデアだろうということです。前回の記事で使用した目標株価は、テイクプロフィットだけでした。ストップロスの設定は、常に健全な損失限定戦略として宣伝されていますが、ストップロス価格は決して保証されていません。また、広範なテストから、ほとんどの口座が証拠金不足に陥っているのは、ストップロスを設定していないのとは対照的に、ポジションサイジングが楽観的すぎたためです。もちろん、ストップロスの重要性についての議論は今後も続くでしょうが、これが私の考えです。この記事では、テイクプロフィットのみの目標価格にこだわりますが、読者の皆様は、ご自身の損失管理手法に合うように、テスト時に入力パラメータを変更することを歓迎します。
ストラテジーテスターのレポートと分析
EURJPYペアの1時間足、4時間足、日足からバランスの取れたシグナルを求めながら、1時間足で2023年をテストすると、公正な結果の一部として以下のようになります。
ある意味、上バンドと下バンドのプライスクロスからの鋭いエントリに頼っていたときの結果とは大違いです。そこで、ボリンジャーバンドの価格クロスオーバーからの鋭いエントリを利用しながら、複数の時間枠でテストを行ったところ、驚くべきことに、パフォーマンスはさておき、これらのクロスオーバーを待っているときの取引回数は、上記で採用した加重平均アプローチよりも多かったのです。以下はその結果です。
結論
結論として、ウィザードで組み立てたEAで複数の時間枠をどのように使用できるかを示しました。ウィザードの組み立てプロセスでは、各シグナルが独自の時間枠を持つだけでなく、独自の取引銘柄も持つことができます。特定の時間枠を割り当ててシグナルをカスタマイズすることは、そのシグナルのOHLCバッファがその時間枠にバインドされることを意味し、これは特定の銘柄を取引するためにシグナルをカスタマイズするのとは異なり、比較的単純なプロセスです。これは、シグナルが特定の銘柄を取引するために割り当てられる場合、取引される各銘柄に対応するために配列形式であるべきCExpertクラスインスタンスに余分な変更を加える必要があるためです。多時間枠取引のデモンストレーションでは、前回の記事と同様に、二乗平均平方根をシグナルとして使用し、デフォルトでは二乗平均平方根がより大きな値に重みがあることを考慮して、平均化されたセットの中でより小さな値に重みがあるミラーバージョンを導出しました。一方は常に確率を評価し、もう一方は特定のエントリシグナルを探すという2つの設定でテストしたところ、どちらのアプローチでも大きく異なる結果が得られました。
一般的に多時間枠取引は、マクロトレンドの大きな時間枠を監視しながら、実際のエントリのシグナルを短い時間枠で選ぶことで、鋭い、あるいは「最も正しい」エントリポイントを狙うものです。この目的のためには、異なる時間枠でそれぞれ異なるシグナルを使用し、大きい時間枠は上記の最初のテストケースで検討した確率的アプローチをとり、小さい時間枠は実際のクロスオーバーポイントをシグナルのトリガーポイントとして考慮する方がより賢明だったかもしれません。
これらのシグナルクラスの両方のインスタンスは下部に添付されているため、読者はこれを実装してテストすることができます。さらに、指標の時間枠を入力として受け取ることができる別の多時間枠の実装があります。このアプローチは、ウィザードの組み立て中に時間枠がシグナルに割り当てられたときに存在する最適な時間枠を選択できないという問題を回避します。これをシグナルの入力パラメータとすることで、戦略に最適化することができます。興味深いことに、この方法は、カスタムOHLCシリーズバッファに時間枠を割り当てるのに使用することもできます。その主な欠点は、多銘柄取引において、パラメータである銘柄名から価格や指標の読み取りが可能であるにもかかわらず、上記のように組み立てられたEAファイルに変更が加えられない限り、取引の発注ができないことです。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15185
![Candlestick Trend Constraintモデルの構築(第5回):通知システム(パート3)](https://c.mql5.com/2/83/Building_A_Candlestick_Trend_Constraint_Model__Part_5___CONT___LOGO.png)
![エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法](https://c.mql5.com/2/17/94_1.gif)
![古典的な戦略をPythonで再構築する:MAクロスオーバー](https://c.mql5.com/2/83/Reimagining_Classic_Strategies_in_Python___LOGO.png)
![MQL5 - MetaTrader 5クライアントターミナルにビルトインされたトレードストラテジーの言語](https://c.mql5.com/i/registerlandings/logo-2.png)
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索