
プライスアクション分析ツールキットの開発(第17回):TrendLoom EAツール
内容
はじめに
トレンドアナリストによって、市場分析やエントリーの確認方法はさまざまです。多くのトレーダーは、M1・M5・M15や、H1・H4・W1といった複数の時間枠を確認し、エントリーの妥当性を判断し、シグナルの信頼性を高めています。しかし、時間枠をいちいち切り替えずに、ボタンを1回押すだけでリアルタイムに更新された情報が表示され、自動的に最新のトレンドが反映される方法があったら便利だと思いませんか。短い時間枠で売りが出ていたために取引を始め、その後、長い時間枠のチャートを見て実は買いトレンドだったと気付いたことはありませんか。
TrendLoom EAは、そういった間違いを防ぐために設計されています。このツールには、7つのボタンからなるパネルが搭載されており、それぞれ異なる取引スタイルに対応しています。各ボタンは3つの時間枠を同時に分析し、移動平均線を使ってBUY(買い)、SELL(売り)、NEUTRAL(中立)のようなシグナルを表示します。この強力なツールはシグナルを検出するたびに迅速に更新され、常に関連する情報を表示します。
戦略の概要
TrendLoom EAは、パネル形式のグラフィカルインターフェイスで構成されています。パネルには、特定の取引戦略に対応する7つのボタンがあります。- 短期フォーカス(M1・M5・M15)
- スキャルピング/デイトレード(M5・M15・H1)
- スイングトレード(M15・H1・H4)
- トレンドトレード(H1・H4・D1)
- MTFトレンド確認(H1・H4・W1)
- ショートスキャルパー/中期トレンド(M5・H1・D1)
- 長期トレンド(H1・D1・W1)
以下は、ボタンが押されたときにEAがBUY、SELL、NEUTRALのシグナルを生成する流れです。
- データ収集:選択された3つの時間枠(例:M1、M5、M15)について、それぞれ直近で確定したローソク足の終値を取得します。
- SMAの計算: 各時間枠ごとに、50期間のSMA(Simple Moving Average、単純移動平均)を算出します。SMAは現在価格の基準として使用されます。
- 終値がSMAより上 → +1(強気)
- 終値がSMAより下 → -1(弱気)
- 終値がSMAと等しい → 0(中立)
シグナルの統合
- 3つの時間枠から得られた個別シグナルを合計します。
- 最終シグナルの決定:
- 合計が+2以上 → 強い上昇モメンタム → BUY(買い)
- 合計が-2以下 → 強い下降モメンタム → SELL(売り)
- 上記以外 → シグナルは混在または中立 → NEUTRAL(中立)
プロセスをよりよく理解するために、次の図を確認してみましょう。
図1:フローチャート
MQL5での実装
ファイルの最上部には、ヘッダーコメントとEAのプロパティ定義が記述されています。これらの行はEAのメタデータとして機能し、著作権情報、バージョン、ソースとの関連付けを示しています。#property strictディレクティブは、より厳格なコンパイルルールを適用するために使用され、一般的なコーディングミスを防ぐのに役立ちます。
//+------------------------------------------------------------------+ //| TrendLoom EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/ja/users/lynnchris" #property version "1.00" #property strict
次に、コードには複数のヘッダーファイルが含まれており、ダイアログ、ボタン、ラベル、パネルなどのコントロールを提供しています。また、チャート上にテキストを表示するためのチャートオブジェクトコントロールも取り込まれています。このようにモジュール形式でファイルを読み込むことで、EAはユーザーインターフェイス構築のために、あらかじめ用意されたクラスを利用することができます。
これらの#includeディレクティブは、MetaEditorの「Include」フォルダ内のライブラリを参照しています。Controlsサブフォルダにあるファイルは、ダイアログやボタン用の組み込みクラスを提供し、ラベルやパネル用のクラスも含まれています。これにより、コードを一から書き直すことなく、対話型インターフェイスの構築が簡単になります。また、ChartObjectsサブフォルダにあるChartObjectsTxtControls.mqhファイルは、チャート上に動的なテキストを表示するための機能を提供します。
#include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder)
次に、テキストの配置と色の値の定数を定義します。これにより、コードの明瞭性と保守性が向上します。
#ifndef ALIGN_LEFT #define ALIGN_LEFT 0 #endif #ifndef ALIGN_CENTER #define ALIGN_CENTER 1 #endif #ifndef ALIGN_RIGHT #define ALIGN_RIGHT 2 #endif #define clrSilver 0xC0C0C0
EAでは、パネルおよびそのボタンの外観や位置を調整するための入力パラメータが宣言されています。PanelX、PanelY、PanelWidthはパネルの配置やサイズを設定します。カラー関連の入力は、パネル全体のビジュアルテーマを決定します。ボタンのサイズや間隔は、btnWidth、btnHeight、btnSpacingによって制御されており、レイアウトや配色を自由にカスタマイズできるようになっています。このような構成により、ユーザーインターフェイスを自分の好みに合わせて柔軟に調整することが可能です。
//---- Input parameters ----------------------------------------------- input int PanelX = 10; input int PanelY = 10; input int PanelWidth = 250; input int btnWidth = 220; input int btnHeight = 30; input int btnSpacing = 5; input color PanelBackgroundColor = clrDimGray; input color PanelHeaderColor = clrBlueViolet; input color ButtonBgColor = clrBlack; input color ButtonTextColor = clrBlueViolet; input color AnalysisTextColor = clrLime;
ボタンの名前や表示テキストは配列に格納されており、新しいボタンの追加や既存ボタンの更新を素早く簡単におこなうことができます。この設計により、ボタンに関する情報が一箇所に集中管理されるため、変更が必要な場合でも最小限の修正で済みます。また、ユーザーインターフェイス全体の一貫性が保たれ、エラーの発生リスクも軽減されます。この手法は、将来的な機能拡張にも柔軟に対応でき、コードの整理や保守性の向上にも寄与します。
//---- Button Names and Texts (7 analysis options) -------------------- string buttonNames[7] = { "btnShortTerm", "btnScalping", "btnSwing", "btnTrend", "btnMTFTrend", "btnShortScalper", "btnLongTerm" }; string buttonTexts[7] = { "Short Term Focus\n(M1, M5, M15)", "Scalping/Intraday\n(M5, M15, H1)", "Swing Trading\n(M15, H1, H4)", "Trend Trading\n(H1, H4, D1)", "MTF Trend Confirm\n(H1, H4, W1)", "Short Scalper/Mid Trend\n(M5, H1, D1)", "Long Term Trend\n(H1, D1, W1)" };
グローバルマクロでは、パネルのヘッダー名や分析ラベル名が定義されています。これらのマクロは、コード全体での一貫性を保つ役割を果たし、これらの識別子の唯一の参照元として機能します。名前を一箇所に集約することで、パネルの各コンポーネントを更新する際も簡単になり、タイプミスのリスクも減少します。 この手法により、保守性が向上し、コード全体がシンプルかつ明確になります。
// Global object names for panel header and analysis label #define PANEL_BG "PanelBG" #define PANEL_HEADER "PanelHeader" #define ANALYSIS_LABEL "AnalysisResult"
コードは次に、2つの補助関数を宣言しています。GetSMAは単純移動平均(SMA)を計算し、AnalyzeTimeframesは複数の時間枠にわたる市場分析を実行します。これらの関数は、市場分析の中核となるロジックを構成しています。
//--- Helper function declarations double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift); string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3);
カスタムクラスCTrendLoomPanelはCAppDialogを継承しています。このクラスは、ヘッダーラベル、メインパネル、ボタン、結果ラベルなど、すべてのユーザーインターフェイス要素をまとめています。この設計により、モジュール化されたインターフェイスが構築され、管理や拡張が容易になります。
パネルの作成
CreateTrendPanelメソッドは、まずダイアログウィンドウを作成します。その後、カスタムテキスト、色、フォントサイズ、フォントスタイルを設定したヘッダーラベルを準備します。配置はObjectSetInteger関数を使って設定されます。
bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2) { if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2)) { Print("Failed to create TrendLoom dialog."); return false; } if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30)) { Print("Failed to create header label."); return false; } m_lblHeader.Text("TrendLoom EA"); m_lblHeader.Color(PanelHeaderColor); m_lblHeader.FontSize(14); m_lblHeader.Font("Segoe UI"); Add(m_lblHeader); if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER)) Print("Failed to set header alignment");
メソッドは続けてメインパネルを作成し、そのサイズを動的に計算します。次に、それぞれのボタンを作成し、順番に配置していきます。最後に、ボタンの下に分析結果を表示するための結果ラベルが追加されます。
イベントの処理
OnEventメソッドはユーザーの操作を処理します。ボタンがクリックされると、対応する時間枠のパラメータを使ってAnalyzeTimeframesを呼び出します。分析結果はパネルに表示され、アラートも表示されます。
bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(sparam == "btnShortTerm") { string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15); string out = "Short Term Focus: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnScalping") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1); string out = "Scalping/Intraday: " + res; UpdateResults(out); Alert(out); return true; } // Additional conditions for other buttons return false; }
UIの更新
UpdateResultsメソッドは、新しい分析データを用いて、結果ラベルを更新します。その後、ChartRedrawを呼び出して、更新された情報を即座にチャートに反映させます。
void UpdateResults(const string &result) { m_lblResults.Text("Analysis Result: " + result); ChartRedraw(); }
コア分析関数
単純移動平均(SMA)の計算
GetSMA関数は、iMA関数を使ってインジケーターハンドルを作成し、SMAを計算します。インジケーターバッファからSMAの値をコピーし、その後ハンドルを解放してリソースを開放します。
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift) { int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Failed to create iMA handle for timeframe ", timeframe); return 0.0; } double sma[]; if(CopyBuffer(handle, 0, shift, 1, sma) <= 0) { Print("Failed to copy buffer for timeframe ", timeframe); IndicatorRelease(handle); return 0.0; } double result = sma[0]; IndicatorRelease(handle); return result; }
多時間枠の分析
AnalyzeTimeframes関数は、3つの時間枠における終値とSMAを取得し、終値がSMAを上回る場合は強気シグナル、下回る場合は弱気シグナルを割り当てます。これらの個別シグナルを合計し、合計が2以上ならBUY、-2以下ならSELL、それ以外はNEUTRALの最終推奨シグナルを生成します。各時間枠は独立して評価され、市場トレンドのバランスの取れた見方を実現しています。また、shiftパラメータにより、分析対象は最後に確定したローソク足のみに限定されます。複数の時間枠のシグナルを組み合わせることで、一時的な市場ノイズの影響を軽減し、SMAの期間を調整することで、取引シグナルの感度をさらに最適化することが可能です。
string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3) { int period = 50; int shift = 1; // last completed candle double price1 = iClose(_Symbol, tf1, shift); double sma1 = GetSMA(_Symbol, tf1, period, shift); int signal1 = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0); double price2 = iClose(_Symbol, tf2, shift); double sma2 = GetSMA(_Symbol, tf2, period, shift); int signal2 = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0); double price3 = iClose(_Symbol, tf3, shift); double sma3 = GetSMA(_Symbol, tf3, period, shift); int signal3 = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0); int sum = signal1 + signal2 + signal3; if(sum >= 2) return "BUY"; else if(sum <= -2) return "SELL"; else return "NEUTRAL"; }EAのライフサイクル関数は、初期化、クリーンアップ、イベント処理を担当します。OnInit関数は、入力パラメータを使ってTrendLoomパネルを作成します。パネルの作成に失敗した場合、EAは初期化エラーを返します。
int OnInit() { if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400)) { Print("Failed to create TrendLoom Panel."); return INIT_FAILED; } return INIT_SUCCEEDED; }
OnDeinit関数は、EAが削除されるかチャートが閉じられた際に、パネルを破棄してクリーンアップをおこないます。
void OnDeinit(const int reason) { TrendPanel.Destroy(reason); }
最後に、OnChartEvent関数はチャートイベントをパネルのイベントハンドラに転送し、インターフェイスの応答性を維持します。
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { TrendPanel.ChartEvent(id, lparam, dparam, sparam); }
MetaEditorでは、必要なファイルは「Include」フォルダに格納されています。コード内で指定されているファイルにアクセスするには、以下の図のようにサブフォルダを参照してください。このフォルダ構成により、コンパイラはダイアログ、ボタン、ラベル、パネルのコントロールファイルを「Include/Controls」フォルダから、チャートオブジェクトのコントロールファイルを「Include/ChartObjects」フォルダから正しく読み込むことができます。
#include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder)
ステップ1
図2:手順1
手順2
図3:手順2
MQL5コード
//+------------------------------------------------------------------+ //| TrendLoom EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/ja/users/lynnchris" #property version "1.00" #property strict #include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder) // Define alignment constants if not already defined #ifndef ALIGN_LEFT #define ALIGN_LEFT 0 #endif #ifndef ALIGN_CENTER #define ALIGN_CENTER 1 #endif #ifndef ALIGN_RIGHT #define ALIGN_RIGHT 2 #endif #define clrSilver 0xC0C0C0 //---- Input parameters ----------------------------------------------- input int PanelX = 10; // Top-left X coordinate of panel input int PanelY = 10; // Top-left Y coordinate of panel input int PanelWidth = 250; // Panel width (for longer text) input int btnWidth = 220; // Button width input int btnHeight = 30; // Button height input int btnSpacing = 5; // Spacing between buttons input color PanelBackgroundColor = clrDimGray; // Panel background color input color PanelHeaderColor = clrBlueViolet; // Panel header text color input color ButtonBgColor = clrBlack; // Button background color input color ButtonTextColor = clrBlueViolet; // Button text color input color AnalysisTextColor = clrLime; // Analysis result text color //---- Button Names and Texts (7 analysis options) -------------------- string buttonNames[7] = { "btnShortTerm", "btnScalping", "btnSwing", "btnTrend", "btnMTFTrend", "btnShortScalper", "btnLongTerm" }; string buttonTexts[7] = { "Short Term Focus\n(M1, M5, M15)", "Scalping/Intraday\n(M5, M15, H1)", "Swing Trading\n(M15, H1, H4)", "Trend Trading\n(H1, H4, D1)", "MTF Trend Confirm\n(H1, H4, W1)", "Short Scalper/Mid Trend\n(M5, H1, D1)", "Long Term Trend\n(H1, D1, W1)" }; // Global object names for panel header and analysis label #define PANEL_BG "PanelBG" #define PANEL_HEADER "PanelHeader" #define ANALYSIS_LABEL "AnalysisResult" //--- Helper function declarations double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift); string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3); //------------------------------------------------------------------------------ // CTrendLoomPanel class - A modern, modular panel for TrendLoom EA //------------------------------------------------------------------------------ class CTrendLoomPanel : public CAppDialog { private: CLabel m_lblHeader; CPanel m_panelMain; CButton m_btnShortTerm; CButton m_btnScalping; CButton m_btnSwing; CButton m_btnTrend; CButton m_btnMTFTrend; CButton m_btnShortScalper; CButton m_btnLongTerm; CLabel m_lblResults; public: // Create the TrendLoom Panel dialog bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2) { if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2)) { Print("Failed to create TrendLoom dialog."); return false; } // Create header label if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30)) { Print("Failed to create header label."); return false; } m_lblHeader.Text("TrendLoom EA"); m_lblHeader.Color(PanelHeaderColor); m_lblHeader.FontSize(14); m_lblHeader.Font("Segoe UI"); Add(m_lblHeader); // Set header text alignment to center using ObjectSetInteger if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER)) Print("Failed to set header alignment"); // Create main panel background int panelBottom = 50 + (btnHeight + btnSpacing) * 7 + btnSpacing; if(!m_panelMain.Create(0, "TrendLoomPanel", 0, 10, 50, x2 - x1 - 10, panelBottom)) { Print("Failed to create main panel."); return false; } m_panelMain.Color(PanelBackgroundColor); m_panelMain.BorderType(BORDER_RAISED); m_panelMain.ColorBorder(clrSilver); Add(m_panelMain); // Starting coordinates for buttons int btnX = 20; // relative to dialog int btnY = 60; int buttonWidth = btnWidth; int buttonHeight = btnHeight; // Create each button with a modern look if(!m_btnShortTerm.Create(0, buttonNames[0], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnShortTerm.Text(buttonTexts[0]); m_btnShortTerm.Font("Segoe UI"); m_btnShortTerm.FontSize(12); m_btnShortTerm.Color(ButtonBgColor); Add(m_btnShortTerm); btnY += buttonHeight + btnSpacing; if(!m_btnScalping.Create(0, buttonNames[1], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnScalping.Text(buttonTexts[1]); m_btnScalping.Font("Segoe UI"); m_btnScalping.FontSize(12); m_btnScalping.Color(ButtonBgColor); Add(m_btnScalping); btnY += buttonHeight + btnSpacing; if(!m_btnSwing.Create(0, buttonNames[2], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnSwing.Text(buttonTexts[2]); m_btnSwing.Font("Segoe UI"); m_btnSwing.FontSize(12); m_btnSwing.Color(ButtonBgColor); Add(m_btnSwing); btnY += buttonHeight + btnSpacing; if(!m_btnTrend.Create(0, buttonNames[3], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnTrend.Text(buttonTexts[3]); m_btnTrend.Font("Segoe UI"); m_btnTrend.FontSize(12); m_btnTrend.Color(ButtonBgColor); Add(m_btnTrend); btnY += buttonHeight + btnSpacing; if(!m_btnMTFTrend.Create(0, buttonNames[4], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnMTFTrend.Text(buttonTexts[4]); m_btnMTFTrend.Font("Segoe UI"); m_btnMTFTrend.FontSize(12); m_btnMTFTrend.Color(ButtonBgColor); Add(m_btnMTFTrend); btnY += buttonHeight + btnSpacing; if(!m_btnShortScalper.Create(0, buttonNames[5], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnShortScalper.Text(buttonTexts[5]); m_btnShortScalper.Font("Segoe UI"); m_btnShortScalper.FontSize(12); m_btnShortScalper.Color(ButtonBgColor); Add(m_btnShortScalper); btnY += buttonHeight + btnSpacing; if(!m_btnLongTerm.Create(0, buttonNames[6], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnLongTerm.Text(buttonTexts[6]); m_btnLongTerm.Font("Segoe UI"); m_btnLongTerm.FontSize(12); m_btnLongTerm.Color(ButtonBgColor); Add(m_btnLongTerm); btnY += buttonHeight + btnSpacing; // Create results label below the buttons if(!m_lblResults.Create(0, "TrendResults", 0, btnX, btnY, btnX + buttonWidth, btnY + 30)) return false; m_lblResults.Text("Analysis Result: [Waiting for Input]"); m_lblResults.Font("Segoe UI"); m_lblResults.FontSize(12); m_lblResults.Color(AnalysisTextColor); Add(m_lblResults); // Set results text alignment to left using ObjectSetInteger if(!ObjectSetInteger(0L, m_lblResults.Name(), OBJPROP_ALIGN, (long)ALIGN_LEFT)) Print("Failed to set results alignment"); Show(); return true; } // Process events (button clicks) bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(sparam == "btnShortTerm") { string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15); string out = "Short Term Focus: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnScalping") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1); string out = "Scalping/Intraday: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnSwing") { string res = AnalyzeTimeframes(PERIOD_M15, PERIOD_H1, PERIOD_H4); string out = "Swing Trading: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnTrend") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_D1); string out = "Trend Trading: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnMTFTrend") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_W1); string out = "MTF Trend Confirm: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnShortScalper") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_H1, PERIOD_D1); string out = "Short Scalper/Mid Trend: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnLongTerm") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_D1, PERIOD_W1); string out = "Long Term Trend: " + res; UpdateResults(out); Alert(out); return true; } return false; } bool ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { return OnEvent(id, lparam, dparam, sparam); } // Update the results label and refresh the chart void UpdateResults(const string &result) { m_lblResults.Text("Analysis Result: " + result); ChartRedraw(); } }; // Global instance of the TrendLoom Panel CTrendLoomPanel TrendPanel; //------------------------------------------------------------------------------ // Helper functions (core analysis logic) //------------------------------------------------------------------------------ double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift) { int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Failed to create iMA handle for timeframe ", timeframe); return 0.0; } double sma[]; // dynamic array to store SMA values if(CopyBuffer(handle, 0, shift, 1, sma) <= 0) { Print("Failed to copy buffer for timeframe ", timeframe); IndicatorRelease(handle); return 0.0; } double result = sma[0]; IndicatorRelease(handle); return result; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3) { int period = 50; int shift = 1; // last completed candle double price1 = iClose(_Symbol, tf1, shift); double sma1 = GetSMA(_Symbol, tf1, period, shift); int signal1 = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0); double price2 = iClose(_Symbol, tf2, shift); double sma2 = GetSMA(_Symbol, tf2, period, shift); int signal2 = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0); double price3 = iClose(_Symbol, tf3, shift); double sma3 = GetSMA(_Symbol, tf3, period, shift); int signal3 = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0); int sum = signal1 + signal2 + signal3; if(sum >= 2) return "BUY"; else if(sum <= -2) return "SELL"; else return "NEUTRAL"; } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400)) { Print("Failed to create TrendLoom Panel."); return INIT_FAILED; } return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { TrendPanel.Destroy(reason); } //+------------------------------------------------------------------+ //| Chart Event Handler | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { TrendPanel.ChartEvent(id, lparam, dparam, sparam); } //+------------------------------------------------------------------+
結果
すべてのトレーダーにとって、システムを実際の取引で使用する前に十分にテストすることは非常に重要です。テストでは、過去のデータを使ったバックテストを行い、資金をリスクにさらすことなくシステムのパフォーマンスを確認できます。また、デモライブ口座を使ってリアルタイムの実際の動きを観察することも可能です。このプロセスにより、より信頼性の高いツールを調整・開発し、自信を持ってライブ口座で使えるようになります。私自身は、EAのテストと改良にかなりの時間を費やし、より堅牢な結果を追求しています。
このセクションでは、チャート上でEAを稼働させたテスト結果を紹介します。Volatility 75 (1s)でテストしたところ、素晴らしく利益を生む結果となりました。すべてのボタンが意図した通りに動作し、ボタンを押すと分析結果がほぼ即時に更新されます。以下に最初のテストを振り返ってみましょう。
図4:Volatility 75 (1s)テスト
以下の図は、提示されたシグナルに基づいて取引を行った後の市場の動きを示しています。この図は、上記のGIFで示した取引の続きです。取引の全体像を把握しやすくするために、M1の時間枠を使用しています。
図5:V 75(1秒)テスト
結論
EAを作成・テストした結果、市場分析に対してポジティブな効果があることを自信を持って確認できます。迅速なシグナル処理と全体的なトレンド評価により、ボラティリティインデックスで強力な成果を上げました。ただし、このツールは最終的なシグナル発信源というよりも補助的な支援ツールとして機能します。ご自身で十分にテストし、パラメータを好みに合わせて調整することをおすすめします。また、ボタンの見た目をカスタマイズするためにさらに改良することも可能です。全体的な取引戦略の確認にぜひ活用してください。私自身、その使い方で効果を実感しています。
日付 | ツール名 | 詳細 | バージョン | アップデート | 備考 |
---|---|---|---|---|---|
01/10/24 | ChartProjector | 前日のプライスアクションをゴースト効果でオーバーレイするスクリプト | 1.0 | 初回リリース | ツール番号1 |
18/11/24 | Analytical Comment | 前日の情報を表形式で提供し、市場の将来の方向性を予測する | 1.0 | 初回リリース | ツール番号2 |
27/11/24 | Analytics Master | 2時間ごとに市場指標を定期的に更新 | 1.01 | v.2 | ツール番号3 |
02/12/24 | Analytics Forecaster | Telegram統合により、2時間ごとに市場指標を定期的に更新 | 1.1 | v.3 | ツール番号4 |
09/12/24 | Volatility Navigator | ボリンジャーバンド、RSI、ATR指標を使用して市場の状況を分析するEA | 1.0 | 初回リリース | ツール番号5 |
19/12/24 | Mean Reversion Signal Reaper | 平均回帰戦略を用いて市場を分析し、シグナルを提供する | 1.0 | 初回リリース | ツール番号6 |
9/01/25 | Signal Pulse | 多時間枠分析ツール | 1.0 | 初回リリース | ツール番号7 |
17/01/25 | Metrics Board | 分析用のボタン付きパネル | 1.0 | 初回リリース | ツール番号8 |
21/01/25 | External Flow | 外部ライブラリによる分析 | 1.0 | 初回リリース | ツール番号9 |
27/01/25 | VWAP | 出来高加重平均価格 | 1.3 | 初回リリース | ツール番号10 |
02/02/25 | Heikin Ashi | トレンドの平滑化と反転シグナルの識別 | 1.0 | 初回リリース | ツール番号11 |
04/02/25 | FibVWAP | Python分析によるシグナル生成 | 1.0 | 初回リリース | ツール番号12 |
14/02/25 | RSI DIVERGENCE | プライスアクションとRSIのダイバージェンス | 1.0 | 初回リリース | ツール番号13 |
17/02/25 | Parabolic Stop and Reverse (PSAR) | PSAR戦略の自動化 | 1.0 | 初回リリース | ツール番号14 |
20/02/25 | Quarters Drawerスクリプト | チャートにクォーターレベルを描く | 1.0 | 初回リリース | ツール番号15 |
27/02/25 | Intrusion Detector | 価格がクォーターレベルに達したときに検出して警告する | 1.0 | 初回リリース | ツール番号16 |
27/02/25 | TrendLoom Tool | タ時間枠分析パネル | 1.0 | 初回リリース | ツール番号17 |
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/17329
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
ワオ、ファンタスティック!これに多くの努力が注がれているのがわかるよ。