自動で動くEAを作る(第14回):自動化(VI)
はじめに
前回の「自動で動くEAを作る(第13回):自動化(V)」稿では 、プログラミングの知識がなくても、トレーダーが取引システムを自動化EAに変換するために必要な基盤を作成できる方法を説明しました。これが、この連載を通して私たちがやってきたことです。これらの概念と情報は、自分で作成するものを含め、あらゆるEAに適用されます。今回は、このタスクを達成するための数ある方法の1つを考えてみましょう。
ここで説明することを真に理解するためには、前回の記事の内容を十分に理解することが非常に重要です。この知識がなければ、この記事の内容を理解するのは難しいかもしれません。前回の記事をまだお読みでない方は、先に進む前にお読みになることをお勧めします。さて、この記事の本題に移りましょう。当初は手動だったエキスパートアドバイザー(EA)を自動化する方法です。
C_Automatonクラスの誕生
前回の記事で以下の図を見ました。
図01:手動モード
この図は、トレーダーが取引サーバー上でポジションをオープンしたりクローズしたりするために、プラットフォームとどのようにやり取りするかを示しています。このプロセスを自動化するには、この図にいくつかの変更を加える必要があります。つまり、手動モデルを表す図01は図02になります。この図は、プログラミングの段階で定義されたいくつかの運用ルールに基づいて自動的に動作するEAを表しています。
図02:自動モード
図02には、システムスーパーバイザーを務める人物の画像が含まれていることに注意してください。自動化されたシステムは、決して監視なしで操作してはなりません。トレーダーは、ただ見ているだけで何もしなくても、常にそのプロセスをコントロールしなければなりません。
同じ図には、EAとC_Managerクラスの間にC_Automatonと呼ばれるクラスが追加されています。この記事では、主にこのクラスとEAとの関連、そしてポジションをオープンしたりクローズしたりオーダーブックに未決注文を入れたりする際にトレーダーの代わりとなるC_Managerクラスについて説明します。
繰り返しになりますが、C_Automatonクラスを実装する前に、すでに正しく、安全に、確実に、堅牢に、安定的に動作しているはずの既存のシステムに変更を加えているわけではないことに注意することが重要です。また、システム自体に何か変更を加えたい場合は、C_Automatonクラスを削除してC_Mouseを復元し、すべての変更を加えてシステムをテストする必要があります。システムが完璧に動作することを確認してから、再びC_Automatonクラスを追加してEAを人間の介入なしに動作させることができます。しかし、監督が必要であることを常に忘れないでください。人間の介入は最後の手段であるべきですが、監視は常におこなわれるべきです。
C_Automatonがどのようにプログラムされているかを見る前に、自動化用に変更されたEAコードを見てみましょう。以下は完全なEAコードです。
#property copyright "Daniel Jose" #property description "This one is an automatic Expert Advisor" #property description "for demonstration. To understand how to" #property description "develop yours in order to use a particular" #property description "operational, see the articles where there" #property description "is an explanation of how to proceed." #property version "1.14" #property link "https://www.mql5.com/pt/articles/11318" //+------------------------------------------------------------------+ #include <Generic Auto Trader\C_Automaton.mqh> //+------------------------------------------------------------------+ C_Automaton *automaton; //+------------------------------------------------------------------+ input int user01 = 1; //Leverage Factor input double user02 = 100; //Take Profit ( FINANCE ) input double user03 = 75; //Stop Loss ( FINANCE ) input bool user04 = true; //Day Trade ? input double user08 = 35; //BreakEven ( FINANCE ) //+------------------------------------------------------------------+ input string user90 = "00:00 - 00:00"; //Sunday input string user91 = "09:05 - 17:35"; //Monday input string user92 = "10:05 - 16:50"; //Tuesday input string user93 = "09:45 - 13:38"; //Wednesday input string user94 = "11:07 - 15:00"; //Thursday input string user95 = "12:55 - 16:25"; //Friday input string user96 = "00:00 - 00:00"; //Saturday //+------------------------------------------------------------------+ #define def_MAGIC_NUMBER 987654321 //+------------------------------------------------------------------+ int OnInit() { string szInfo; automaton = new C_Automaton(def_MAGIC_NUMBER, user03, user02, user01, user04, user08, PERIOD_M5); for (ENUM_DAY_OF_WEEK c0 = SUNDAY; c0 <= SATURDAY; c0++) { switch (c0) { case SUNDAY : szInfo = user90; break; case MONDAY : szInfo = user91; break; case TUESDAY : szInfo = user92; break; case WEDNESDAY : szInfo = user93; break; case THURSDAY : szInfo = user94; break; case FRIDAY : szInfo = user95; break; case SATURDAY : szInfo = user96; break; } (*automaton).SetInfoCtrl(c0, szInfo); } (*automaton).CheckToleranceLevel(); EventSetMillisecondTimer(100); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { delete automaton; EventKillTimer(); } //+------------------------------------------------------------------+ void OnTick() { } //+------------------------------------------------------------------+ void OnTimer() { (*automaton).Triggers(); } //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result) { switch (trans.type) { case TRADE_TRANSACTION_POSITION: (*automaton).UpdatePosition(trans.position); break; case TRADE_TRANSACTION_ORDER_DELETE: if (trans.order == trans.position) (*automaton).PendingToPosition(); else { (*automaton).UpdatePosition(trans.position); (*automaton).EraseTicketPending(trans.order); } break; case TRADE_TRANSACTION_ORDER_UPDATE: (*automaton).UpdatePending(trans.order); break; case TRADE_TRANSACTION_REQUEST: if ((request.symbol == _Symbol) && (result.retcode == TRADE_RETCODE_DONE) && (request.magic == def_MAGIC_NUMBER)) switch (request.action) { case TRADE_ACTION_DEAL: (*automaton).UpdatePosition(request.order); break; case TRADE_ACTION_SLTP: (*automaton).UpdatePosition(trans.position); break; case TRADE_ACTION_REMOVE: (*automaton).EraseTicketPending(request.order); break; } break; } } //+------------------------------------------------------------------+
このコードに加えられた変更はわずかです。OnChartEventハンドラは不要になったため削除され、OnTimeイベントに新しい関数が追加されました。 詳細は後ほどお伝えします。残りのコードは、以前の手動操作モードと同じままです。EAを自動化する際には、EAコード全体を変更しないことが非常に重要です。必要な変更だけをおこなえばよいのです。この場合、タイムイベントに新しい関数を追加するだけです。
何はともあれ、このEAコードは決定的で不変のコードではありません。使用するシステムによっては、ユーザーによって定義されるべきことが多かれ少なかれあります。したがって、C_Automatonクラスのコンストラクタにバリエーションがあるかもしれません。必要なパラメータは多いかもしれないし、少ないかもしれません。 このコードがすべてのケースで使えるとは思わないでください。
ただし、先に述べた点を除けば、基本的には大きな変更はないので、ご自分が使おうとしているシステムで本当に必要なことを勉強することをお勧めします。トレーダーが調整すべきでない部分はあらかじめ設定しておき、使用するシナリオに応じて必要な部分のみを調整できるようにします。
もう1つお気づきかもしれませんが、C_AutomatonクラスはC_Managerクラスを継承しています。このため、実質、コードに変更はありません。つまり、すべてはC_Automatonクラスの内部で起こります。
私が紹介しているのと同じEAの構造とクラスを使いたいのであれば、C_Automatonクラスを修正して、このクラスの中にご自分の取引システムを入れるので十分です。それらの唯一の違いはC_Automatonクラス自体であるため、異なる取引システムを利用する新しいEAの作成は、より速く、より安全で、より一貫性のあるものになります。クラスを作成する際、コンストラクタを使用することで、取引システム自体に従って、いくつかの特別なことを知らせることができます。これにより、柔軟性、使いやすさ、堅牢性、再利用性を高いレベルで維持することができます。
EAは、常に実際のユーザーが求める品質レベルを備えることになります。何にしても、物事をもっと面白くするために、いくつかの変更を加えることができるので、おそらく将来、これらの改造のいくつかを公表します。いずれにせよ、システムを変更し、ご自分の作戦モードに合わせることをお勧めします。結局のところ、私がこのような記事を書き、コードへの自由なアクセスを提供しているのはそのためです。
ただ1つお願いがあるとすれば、もし一部でも利用する場合は、出典を明記してほしいということです。恥ずべきことではありませんが、出典を示さずに何かを使用したり配布したりするのはよくありません。
では、C_Automatonクラスのブラックボックスの中身を見てみましょう。
C_Automatonクラスコードの分析
上述したように、EAコードもC_Automatonクラスコードも、何を、どのように、いつ取引するかによって決まります。しかし、これに関係なく、C_Automatonクラスには基本的に3つの内部関数があります。コンストラクタ、EAのタイムイベントによって呼び出される関数、クラスの別の内部関数とprivate関数です。
この3つの関数に注意を払うことが重要です。他の何らかの理由で、この3つを助けるために必要な関数が増えたり減ったりすることはあるかもしれませんが、本質的にあるのは常にこの3つの関数です。
理論だけにとらわれず、下のビデオを見てみましょう。長く感じるかもしれませんが、それでも見る価値はあります。強調したいのは、どのようなシステムで取引しても、例外なく誰もが大小にかかわらず何らかの損失を抱えるということです。しかし、まずはビデオを見て、これから説明されることを理解しましょう。
ビデオ01:自動EAのデモンストレーション(約25分)
このビデオでは、EAが新しいバーの開始時にエントリを作成するために使用する9期間の指数移動平均に基づいた取引システムを使用しています。このシステムの作り方については前回の記事で説明したので、すべての基本的なプロセスを理解するために、その記事を注意深くお読みになることをお勧めします。繰り返しますが、理論だけにとらわれるのはやめましょう。C_AutomatonクラスがEAにどのように取引を作成、管理、決済させるかを理解するために、具体的な設定を作成するコード例を見てみましょう。
各手法の説明に従い、どのように開発され、コード化されたかを確認します。こうすれば、もう少しコードが必要になるような特殊なケースはあるものの、実質的にどんなセットアップでも開発できるようになります。しかし、そのようなケースは稀であり、大多数が実際に指標を使用するため、これらの例は100%自動モデルを作成する上で大いに役立つでしょう。コードに入る前に、細かい部分を見てみましょう。
共通部分、従属部分
例を見るときにC_Automatonクラスで混乱しないように、いくつかの説明をする必要があります。
C_Automatonクラスのコードは非常に特殊ですが、経験豊富なプログラマーにとってはごく一般的なものです。すべての業務に共通する部分と、特定の業務に特化した部分があります。前回の記事で紹介したような方法を説明する際には、この点にご注意ください。というのも、すべてのモデルには共通部分があることを理解していないと、C_Automatonクラスがご自分のモデルをカバーできないと思われるかもしれないからです。実際にはどのモデルもカバーできます。時には変数を追加する必要があるかもしれませんが、どのようなモデルタイプにも対応できるよう、正しい方法を紹介します。
共通のコード部分は、使いたいモデルに関係なく、常に繰り返されます。依存部分はモデルをユニークなものにし、他のモデルで繰り返されることはありません。
以下は、どのモデルにも共通するコードです。
#property copyright "Daniel Jose" //+------------------------------------------------------------------+ #include "C_Manager.mqh" //+------------------------------------------------------------------+ class C_Automaton : public C_Manager { protected: enum eTrigger {TRIGGER_NONE, TRIGGER_BUY, TRIGGER_SELL}; private : struct st00 { int Shift, nBars; double OverBought, OverSold; }m_Infos; double m_Buff[]; int m_nBars, m_Handle; ENUM_TIMEFRAMES m_TF; //+------------------------------------------------------------------+ static eTrigger m_Memory; //+------------------------------------------------------------------+ inline eTrigger CheckTrigger(void) { int iRet; if (((iRet = iBars(NULL, m_TF)) > m_nBars) && (m_Handle != INVALID_HANDLE)) { } return TRIGGER_NONE; } //+------------------------------------------------------------------+ public : //+------------------------------------------------------------------+ C_Automaton(const ulong magic, double FinanceStop, double FinanceTake, uint Leverage, bool IsDayTrade, double Trailing, const ENUM_TIMEFRAMES iPeriod, const double OverBought = 70, const double OverSold = 30, const int iShift = 1) :C_Manager(magic, FinanceStop, FinanceTake, Leverage, IsDayTrade, Trailing, true, 10), m_TF(iPeriod), m_Handle(INVALID_HANDLE) { m_Infos.Shift = iShift; m_Infos.OverBought = OverBought; m_Infos.OverSold = OverSold; ArraySetAsSeries(m_Buff, true); m_nBars = iBars(NULL, m_TF); } //+------------------------------------------------------------------+ inline virtual void Triggers(void) final { if (!CtrlTimeIsPassed()) ClosePosition(); else switch (CheckTrigger()) { case TRIGGER_BUY: if (m_Memory == TRIGGER_SELL) ClosePosition(); if (m_Memory != TRIGGER_BUY) ToMarket(ORDER_TYPE_BUY); m_Memory = TRIGGER_BUY; break; case TRIGGER_SELL: if (m_Memory == TRIGGER_BUY) ClosePosition(); if (m_Memory != TRIGGER_SELL) ToMarket(ORDER_TYPE_SELL); m_Memory = TRIGGER_SELL; break; } }; //+------------------------------------------------------------------+ }; //+------------------------------------------------------------------+ static C_Automaton::eTrigger C_Automaton::m_Memory = TRIGGER_NONE; //+------------------------------------------------------------------+
上記のコードにあるものはすべて、どのモデルにも存在する共通コードの一部です。モデルに関係なく、このコードは常に使用されます。確かに、コード例を見ればわかるように、新しい変数やC_Managerの呼び出しがあるかもしれませんが、基本的には上記のコードはほぼそのまま残ります。
上記のコードにないものは、ご自分のモデルに固有のモデル依存コードの一部です。では、その仕組みを理解するためにコードを見てみましょう。こうすることで、より具体的なモデルをカバーするために、コードに何を追加すべきか、あるいは追加すべきでないかを理解することができます。
次のコードでクラス宣言から始めましょう。
#include "C_Manager.mqh" //+------------------------------------------------------------------+ class C_Automaton : public C_Manager { protected: enum eTrigger {TRIGGER_NONE, TRIGGER_BUY, TRIGGER_SELL};
ここでは、C_AutomatonクラスがC_Managerクラスからpublicに継承されることを宣言しています。これにより、C_Automatonクラスを使用する際に、C_Managerクラスのプロシージャにアクセスできるようになります。これは、コントロールクラスに関連するいくつかのメンバーの初期化のために重要です。EAのコードを見ると、プロシージャーがアクセスされるこれらのポイントを見ることができます。これらの手続きはC_Automatonクラスでは宣言されていませんが、他のクラスから来ています。これについては、本連載の別の記事ですでに説明しています。
また、クラス内でハイクラスプログラミングができるように、列挙者も作成しました。 この列挙は、どのタイプのトリガーが起動されたかを示します。もう1つ細かいことを言うと、この列挙子はコードのprotected部分で宣言されていますが、クラスの外部で使われることはありません。静的なクラス変数を初期化できるようにするためには、この部分に入れる必要があったのです。それについては後で詳しく見ることにしましょう。
次に、以下のコードの変数を見てみましょう。
private : struct st00 { int Shift, nBars; double OverBought, OverSold; }m_Infos; double m_Buff[]; int m_nBars, m_Handle; ENUM_TIMEFRAMES m_TF; //+------------------------------------------------------------------+ static eTrigger m_Memory;
これは、指標に関連する幅広いケースをカバーしているため、ほとんど変更する必要のない構造体です。複数の指標を使用する場合は、さらに構造体を追加する必要があるかもしれませんが、構造体そのものの要素を変更する必要はありません。
これを理解するために、次の例を見てみましょう。構造体は1つの変数によって参照されています。これにより、どんな指標であれ、1つの指標を使うことができます。しかし、複数の指標を使う必要がある場合はどうでしょうか。この場合、どうすればいいのでしょうか。この場合、いくつかの追加を実装する必要があります。それらは例で示されます。とりあえず、このシンプルなシステムを理解するために、基本的なことに集中しましょう。
また、指標の値を受け取るバッファとして機能する変数、チャート上のバーの数を格納する変数、指標の参照用の変数、指標に使用する時間枠を決定する変数もあります。そして最後にもうひとつ、最後のトリガー状態を格納する変数です。この静的変数は、以下のコードに示すように、クラス本体の外で初期化されます。
static C_Automaton::eTrigger C_Automaton::m_Memory = TRIGGER_NONE;
このトリガーは、トリガーシステムに対してクエリがおこなわれていないことを意味する、ニュートラルなトリガーで初期化されなければならないことにご注意ください。偶発的なトリガーは避けます。ただし、取引モデルによっては、この静的変数はあまり役に立ちません。しかし、チャート上にEAを配置した直後にランダムなトリガーが発生するのを避けるために、この変数を使用して、起動時や取引手の変更時にランダムなことが起こらないようにしています。
次に注意すべき点は、以下に示すクラスのprivate関数です。
inline eTrigger CheckTrigger(void) { int iRet; if (((iRet = iBars(NULL, m_TF)) > m_nBars) && (m_Handle != INVALID_HANDLE)) { }; return TRIGGER_NONE; }
デフォルトでは、この関数は常にNULLトリガーを返します。 ご自分の取引モデルのための特定の計算は、この関数で実装されます。そのため、さらなる計算は異なる可能性があります。
新しいバーがない場合、計算は無視されます。また、ハンドルは有効なものを指していなければなりません。EA運用中の問題を回避するためには、これらのルールを明確に定義することが重要です。
次の関数はクラスのコンストラクタです。
C_Automaton(const ulong magic, double FinanceStop, double FinanceTake, uint Leverage, bool IsDayTrade, double Trailing, const ENUM_TIMEFRAMES iPeriod, const double OverBought = 70, const double OverSold = 30, const int iShift = 1) :C_Manager(magic, FinanceStop, FinanceTake, Leverage, IsDayTrade, Trailing, true, 10), m_TF(iPeriod), m_Handle(INVALID_HANDLE) { m_Infos.Shift = iShift; m_Infos.OverBought = OverBought; m_Infos.OverSold = OverSold; ArraySetAsSeries(m_Buff, true); m_nBars = iBars(NULL, m_TF); }
このコンストラクタを完全に理解することは極めて重要です。経験の浅い方や、これから始めようとする方にとって、このコードが分かりづらいかもしれないことは分かっていますが、このコードを理解することは、C_Automatonクラスを最大限に活用し、完全に自動化されたEAを作成するために非常に重要です。まずは、この一見わかりにくい文章が実際に何をしているのかを理解することから始めましょう。
C_AutomatonはC_Managerを継承しているので、C_Managerコンストラクタを初期化しなければなりません。 このため、EAからデータを受け取り、そのデータは初期化のためにC_Managerクラスに渡されます。
さらに2つのパラメータにご注意ください。 必要であれば、EAに戻すこともできますが、これはC_Automatonクラスで作成される取引タイプに依存します。その意味を明確にするために、ここでこれらのパラメータについて触れておきます。これらのパラメータは、C_Managerを見れば理解できます。クラスコンストラクタを説明するコードは以前の記事にあるので、ここでは繰り返しません。
EAは、C_Automatonクラスで使用するチャート期間も通知します。このパラメータはそのために使われます。
自動システムは、監督者が何を見ようとも、常に一定の時間枠内で機能することが重要です。自動化クラスで、スーパーバイザーに見える同じ時間枠を使用すると、EAを不適切な時間に誤ってトリガーさせることができます。これは一部のEAで非常によく見られるエラーで、プログラマーはユーザーがEAの作業時間中にチャートの時間枠を変更できることを認識していません。これは非常に不便です。しかし、そうすることで、トレーダーに何が見えるかに関係なく、EAが常に同じ時間枠で動作することを保証します。
この時点でデフォルト値のパラメータがいくつかあります。従って、EAコードで宣言されることもあれば、されないこともあります。
デフォルト値を使用しても、EAコードで別の値を指定したり、EA起動時にトレーダーが値を定義したりすることはできません。しかし、大半の場合、これらの値は変わらず実際に使われない場合もあるので、コンストラクタのオーバーロードを避けるために、これらのパラメータにデフォルト値を定義しています。これにより、コードがよりコンパクトになり、解析や理解がよりシンプルになります。これらの値は、さらに使用するために内部構造体に保存されることにご注意ください。
重要なことが1つあります。使用する指標の種類によって、これらの値をトレーダーが変更できるシステムを使用している場合、より多くの変数に対応するために、このコードを変更する必要があるかもしれません。この場合、同じデータを使っている限り、1つの指標でも複数の指標でも使用できます。
最後に、ハンドルの値を初期化し、インジケータを指さないようにします。 これは、万が一ハンドルが未知のものを指していた場合に備えて、セキュリティーを破ることを避けるために重要です。さらに、最後のシステム変数を調整します。このコンストラクターは基本中の基本であり、実装されるシステムのタイプに応じて、さらに数行のコードが追加されます。しかし、これはコード例で示します。
C_Automatonクラスの基本コードを終えるために、最後のコード部分を見てみましょう。
inline virtual void Triggers(void) final { if (!CtrlTimeIsPassed()) ClosePosition(); else switch (CheckTrigger()) { case TRIGGER_BUY: if (m_Memory == TRIGGER_SELL) ClosePosition(); if (m_Memory != TRIGGER_BUY) ToMarket(ORDER_TYPE_BUY); m_Memory = TRIGGER_BUY; break; case TRIGGER_SELL: if (m_Memory == TRIGGER_BUY) ClosePosition(); if (m_Memory != TRIGGER_SELL) ToMarket(ORDER_TYPE_SELL); m_Memory = TRIGGER_SELL; break; } };
上記の手順は100%完成したコードではないので、取引システムによっては若干の変更があるかもしれません。基本的には、OnTimeイベントから来る各コールで何が起こるかを示しています。多くの人はこれをOnTickイベントに移したいと思うかもしれないが、そうすべきでない理由はすでに説明しました。その理由を理解するには、これまでの記事を読むことをお勧めします。
このコードでは、C_Managerクラスが常に市場要件で動作するように指示しています。実装しているモデルに応じて注文システムが異なる可能性があるため、コードは100%完成していないと言うのはこのためです。取引サイドがどのように変わるかでも、このコードは違って見える。
もう1つは、上記のコードでは、新しいシグナルが発生したときにEAがポジションを増やすことができないということです。 メモリ変数を使っているからです。
新しいエントリシグナルが発生した場合、EAがポジションを増やすのを防ぎます。しかし、プログラミングの知識があれば、このブロックを回避することができるでしょう。適切な知識なしにおこなおうとすると、EAが無秩序に注文を実行し、数秒のうちに利用可能な残高をすべて失う可能性があるため、確実に口座に深刻な損失をもたらすことになります。自分が何をしているのかよくわからない場合は、このコードを変更しないでください。.
そのため、このコードについてはあまり深く説明しません。ただ、例に移る前に言っておきたいことがあります。一見、奇妙で意味のないように思えるこの手順の宣言です。
その理由を考えてみましょう。システム全体がクラスシステムを採用するように設計されています。これは、コードの信頼性、安全性、堅牢性を高めるだけでなく、時間の経過に伴う拡張を可能にします。というのも、クラスシステムによって、物事をよりモジュール化することができるため、複雑さを増す一方でコードを減らすことができるからです。
C_Automatonは最終的なクラスではないので、より大きなシステムの中でプロシージャー宣言をそのままおこないます。この特定のプロシージャーが他のクラスで変更されることがないように、コンパイラに指示します。これにより、継承されたクラスシステム全体を通して一意であることが保証されます。
このようなことは、モジュール化され、非常によく構造化されたコードを扱う場合に非常に重要です。なぜなら、どんなに構造化しても、遅かれ早かれ、継承したプロシージャを上書きしてしまうというミスを犯す可能性があるからです。もしそうなれば、すべてのコードが危険にさらされることになります。しかし幸運なことに、MLQ5言語にはこの種の問題を回避するためのツールが用意されています。
C_AutomatonクラスがEAの自動化にどのように役立つかを理解するために、いくつかのコード例を見てみましょう。その前に、はっきりさせておかなければならないことがいくつかあります。
- どんな自動取引システムも100%安全ではありません。
- すべての操作で利益を保証するシステムは存在しません。
- ビデオ01で見ることができるように、システムが最初に機能していても、騙されてはいけません。
- すでに知っているシステムだけを使うか、自動化します。より良い結果が得られると思って、複数の戦略を組み合わせることは避けてください。シンプルさがすべてです。
- ここに示したモデルは、利益を生むこともあれば損失を生むこともあることを承知の上で、自己責任で使用してください。
コードの適用方法をよりよく理解するために、各モデルには特定のEAが付属しているので、コードを比較して研究してください。
結論
トピックのボリュームが多いため、この記事では自動化の3つの例のみを紹介しました。対応するコードについては、この連載の最後になるかもしれない次回の記事で説明します。次回の記事もお見逃しなく。次回は、これらの要素がどのように完璧に組み合わされ、自分が指定したパターンに従いながら完全自動モードでEAを作動させるかを見ていきます。
MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/11318
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索