English Русский 中文 Español Deutsch Português
preview
自動で動くEAを作る(第07回):口座の種類(II)

自動で動くEAを作る(第07回):口座の種類(II)

MetaTrader 5トレーディング | 31 3月 2023, 10:33
938 0
Daniel Jose
Daniel Jose

はじめに

前回の「自動で動くEAを作る(第06回):口座の種類(I)」稿で 、自動化されたEAが目的の範囲内で正しく動作することを保証する方法の開発を開始しました。その記事では、EAの動作がおかしいまたは正しくない場合にEAがチャートから削除されるように、管理者として機能するC_Managerクラスを作成しました。

その記事の冒頭で、EAの指値注文や成行注文がトリガーされないようにする方法を説明しました。しかし、EAとC_Ordersクラスとの相互作用については、別の問題があります。この問題は、主にネッティング口座に関連しています。これは、今回取り上げるテーマの1つです。

ただし、いずれにせよ、自動EAを監視なしで実行させることは絶対に避けなければなりません。

EAをインテリジェントにプログラミングするだけでいいとは思わないでください。自動EAが何をしているのか常に意識し、指定されたアクティビティを超えたら、制御不能になる前に、できるだけ早くチャートから削除する必要があります。


EAとC_Ordersクラス間のインタラクションのための新しいルーチン

EAが以下のようにC_Ordersクラスにアクセスできる状態が続けば、これまでの記事で述べたことはすべて無意味になります。

//+------------------------------------------------------------------+
                void CreateOrder(const ENUM_ORDER_TYPE type, const double Price)
                        {
                                C_Orders::CreateOrder(type, Price, m_InfosManager.FinanceStop, m_InfosManager.FinanceTake, m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                        }
//+------------------------------------------------------------------+  
                void ToMarket(const ENUM_ORDER_TYPE type)
                        {
                                C_Orders::ToMarket(type, m_InfosManager.FinanceStop, m_InfosManager.FinanceTake, m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                        }
//+------------------------------------------------------------------+

制限して制御しようとしても、EAは市場に注文を送り、オーダーブックに新しい注文を送ることに成功することに注意してください。これはセキュリティ違反です。なぜなら、EAの初期化中に C_Managerクラスが特定のルールに従うことを強制できた場合、その後、なぜ注文を出し、市場操作を実行できるようにするのでしょうか。ここでは、非常にシンプルでもいいから、何らかの制限を設けなければなりません。簡単なテストで、さまざまな問題を防ぐことができるのです。そこで、EAとC_Ordersクラスにある発注システムとの相互作用という形で、この領域全体を制御するようにしましょう。

//+------------------------------------------------------------------+
                void CreateOrder(const ENUM_ORDER_TYPE type, const double Price)
                        {
                                if ((m_TicketPending > 0) || (m_bAccountHedging && (m_Position.Ticket > 0))) return;
                                m_TicketPending = C_Orders::CreateOrder(type, Price, m_InfosManager.FinanceStop, m_InfosManager.FinanceTake, m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                        }
//+------------------------------------------------------------------+  
                void ToMarket(const ENUM_ORDER_TYPE type)
                        {
                                ulong tmp;
                                
                                if (m_bAccountHedging && (m_Position.Ticket > 0)) return;
                                tmp = C_Orders::ToMarket(type, m_InfosManager.FinanceStop, m_InfosManager.FinanceTake, m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                                m_Position.Ticket = (m_bAccountHedging ? tmp : (m_Position.Ticket > 0 ? m_Position.Ticket : tmp));
                                if (PositionSelectByTicket(m_Position.Ticket)) SetInfoPositions(); else m_Position.Ticket = 0;
                        }
//+------------------------------------------------------------------+

EAがC_Ordersクラスを使う際に、あまり自由度が高くないようにいくつかのルールを追加しました。ここで、何が起きているのかを見てみましょう。まずはCreateOrder関数から始めます。 指値注文チケットを通知する変数に値があれば、新規注文は拒否されますが、ヘッジ口座でポジションを持っている場合にも拒否されます。非常にシンプルです。しかし、これらの条件が許せば、指値注文をオーダーブックに追加するリクエストを送信し、リクエストが成功すれば、発注された注文のチケットを取得することができます。それ以降は、新たな注文を送るすることはできません

さて、ここからが重要になります。 ToMarket関数の中にあります。この場合、注文は成行注文として、すなわち利用可能な最良の価格で発注されます。では、成行注文を出すための条件を見てみましょう。注文の送信は、ヘッジ口座でポジションを持っていない場合にのみ許可されます以下はその詳細です。成行注文を出すことが可能であれば、それをおこなうことになりますが、そもそも呼び出しで返された値を使うことができません。これは、ネッティング口座であれば、ポジションチケットと値が異なる場合があるためです。ポジションチケットの値に直接値を設定すると、この場合、戻り値が一時的なものにしかならない可能性があるため、実際のチケットの値を失う可能性があります。ここに新たなチェックを設けたのはこのためです。これがヘッジ口座であれば、返された値はポジションチケットに安全に格納することができます。しかし、ネッティング口座の場合、ポジションチケットがゼロの場合のみ保存されます。それ以外の場合は、その値は無視されます。これが終わればポジションデータを更新したり、ポジションチケットの値をリセットしたりできるのですが、すべてはチェック次第です


自動売買EAにおけるネッティング口座の問題点

ネッティング口座で自動売買EAを使用する場合、潜在的に危険な問題があります。前回は、ヘッジ口座で起こりうる問題を紹介しましたが、今回は、ネッティング口座でのみ起こる、別の問題を探ってみましょう。EAがロックを持っていない場合、この抜け穴にいつかはたどり着くことになります。多くのEAにこの問題があるにもかかわらず、そのユーザーはこれを知りません。

問題は、次のようなことです。ネッティング口座では、ロングポジションやショートポジションでbid価格が変化すると、取引サーバが自動的に平均ポジション価格を作成します。ショートにする場合、一方的に、平均価格だけでなく、ポジションのボリュームも変化することになります。

手動で操作するEAの場合、サーバへのリクエストの送信はトレーダーがおこなうため、問題はありません。問題は自動化されたEAで発生します。この場合、プログラミングにある種のギャップや脆弱性が存在する場合にトリガーすることがあります。詳しく言えば、問題は取引サーバでもMetaTrader 5プラットフォームでもなく、EAにあります。

誰にでもわかるように説明するつもりですが、理想的には、市場の仕組みについてある程度の知識があると、より理解しやすいと思います。なるべく質問をわかりやすくするようにします。

自動売買EAがポジションを建てるために売買注文を出すときは、何らかのトリガーに基づいておこなわれます。トリガーの話はまだしていませんが、まもなくします。しかし、大多数の場合、トリガーに責任はありません。

ネッティング口座で一旦ポジションが建てられると、EAは、何らかの理由で、ボリュームの一部を決済して別のものを開く.という戦略を使用し始めることがあります。そうすることで、平均価格が動き出します。問題は、EAが乱暴で狂った幻覚のようにこれをやり始めることかもしれません。そうなれば、ボリュームに応じて数分、時には数秒で大金を失うこともあります。

EAが注文を開始し、ポジションを閉じることなくその場に留まり、平均価格を変更するためにサーバに新たなリクエストを送信しているのです。これは、EAを監督している、あるいは監督すべきトレーダーがいないところで起こることが多く、表示されるボリュームは変化しないが、価格は変化するため、トレーダーによってはこの変化に気づかないことがあります。トレーダーが何かおかしいと気づく前に、すでにポジションが大きな損失を出していることもよくあることです。

自動EAの中には、意図的にこのようなストラテジーを使用するようにプログラムされているものもありますが、自動EAにこのようなエラーがあることを知らない、あるいは気づいていない方もいらっしゃいます。場合によっては、ここでトリガーの問題が出てきますが、その人はEAを売買させるタイプのトリガーを使っていて、ある非常に特殊な市場状況において、EAがまさに上記のようなことをするようになることがあります。この事実を知っていれば、トレーダーは気を配ることができます。しかし、この動作が想定されていないと、EAを監督するトレーダーは、EAがおこなうことに恐怖を感じてしまうかもしれません。

どんなにシステムを信頼し、自動EAが安全だと信じていても、甘く見てはいけません。あなどってはいけません。 なぜなら、プログラミング中に予見できなかった抜け道がEAにあることが起こりうるからです。しかし幸いなことに、この欠点を克服し、少なくともその被害を少しでも減らせる、比較的簡単な方法があります。では、どうすればいいのかをプログラミングの面から見てみましょう。


EAで取引量を制限する

前のトピックで説明した問題を少しでも軽減する最も簡単な方法は、EAが実際に扱うことのできるボリュームを制限することです。100%理想的な方法はありませんが、できる限り、私たちの心を和ませるような形を生み出すことは可能です。そして、最も簡単な方法は、EAが実行されている間中、EAが扱うことのできるボリュームを制限することです。

この点に注意してください。ポジションの出来高を制限しろと言っているのではなく、全期間においてEAが取引できる出来高を制限しろと言っているのです。つまり、EAは最小出来高のx倍の取引が可能ですが、制限に達すると、EAは新しいポジションを開くことができなくなります。上限がこのボリュームの50倍である場合に、1つの最小ボリュームに相当するポジションがあるかどうかは関係ありません。EA が既にこのクォータの50に達している場合、それ以上のポジションを開くことも、ポジションを増やすこともできません。

ロックはまさにこのことを前提にしています。でも、ここには注意点があります。100%安全なロックというものは存在しません。すべては、EAを監修するトレーダー次第です。トレーダーが不注意でロックを解除し、EAを再起動した場合、発生しうる障害についてはトレーダーが責任を負わなければなりません。EAがノルマに達し、トレーダーがEAをチャート上で再起動させることになったということもあり得ます。この場合、ロックはありません。

ロックを実装するためには、C_Managerクラス内で、静的でグローバルかつprivateな変数が必要です。以下のコードに示します。

static uint m_StaticLeverage;

しかし、クラス内の静的変数を初期化するためには、クラスコンストラクタを使用することができません。この場合の初期化は、クラス本体の外で、通常はソースファイル内のC_Manager.mqhヘッダーファイルで実装されます。そして、クラス本体の外側には、次のようなコードを用意します。

uint C_Manager::m_StaticLeverage = 0;

大丈夫です。静的変数が初期化されるだけです。ご存じない方のために説明すると、この初期化はクラスコンストラクタが実際に参照される前からおこなわれます。ですから、ある種のコードでは、これはかなり便利です。しかし、変数がクラス本体の外で初期化されたからといって、その変数がクラスの外でアクセスできるようになるわけではありません。覚えておいてください。理由はカプセル化です。すべての変数をprivateとして宣言しなければなりません。これにより、クラスを可能な限り堅牢にすることができます。こうして、セキュリティ侵害やクラスの仕事の信頼性低下を回避しています。

しかし、ここでもう1つ重要な疑問が生じます。C_Managerクラスでprivateかつstaticなグローバル変数を使用するのはなぜでしょうか。少なくとも静的でない変数は使えなかったのでしょうか。答えは「いいえ」です。その理由は、こうです。いかなる状況でも、MetaTrader 5プラットフォームがEAを再起動した場合、静的変数の外に保存されたすべてのデータは失われます。このことに注目してみてください。MetaTrader 5がEAを再起動できるということで、EAを削除してチャート上で再実行するということではありません。この2つの状況は異なります。EAを一旦チャートから外し、再度起動した場合、静的変数に関する情報まで失われます。このような場合は、データをファイルに保存しておき、そのファイルを読み込むことで復元するしかありません。再起動しても、EAが削除されたことにはなりません。これはいくつかの状況で起こりうることで、そのすべてがDeInitイベントのトリガーに関連し、コード内のOnDeInit関数を呼び出すことになります。このリセットは、EAだけでなく、指標にも影響します。そのため、DeInitイベントがアクティブになった場合は、チャート上で動作しているスクリプトを削除することができます。スクリプトはリセットされず(このプロパティを持っていない)、チャートから「離れる」だけなので、MetaTrader5は自動的にリセットしません。

次に、EAが最小限のボリュームを取引できる最大時間を特定するために、クラスのコードに定義を追加する必要があります。この定義を以下に示します。

#define def_MAX_LEVERAGE       10

EAが取引した最小出来高を保存する場所はすでにあり、最大出来高の定義もあります。そこで、今度はこの体積を計算する方法を出すのですが、これがこの作品の一番面白いところです。しかし、その前に、前回のコードを少し変更する必要があります。

//+------------------------------------------------------------------+
                void CreateOrder(const ENUM_ORDER_TYPE type, const double Price)
                        {
                                if ((m_StaticLeverage >= def_MAX_LEVERAGE) || (m_TicketPending > 0) || (m_bAccountHedging && (m_Position.Ticket > 0))) return;
                                m_TicketPending = C_Orders::CreateOrder(type, Price, m_InfosManager.FinanceStop, m_InfosManager.FinanceTake, m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                        }
//+------------------------------------------------------------------+  
                void ToMarket(const ENUM_ORDER_TYPE type)
                        {
                                ulong tmp;
                                
                                if ((m_StaticLeverage >= def_MAX_LEVERAGE) || (m_bAccountHedging && (m_Position.Ticket > 0))) return;
                                tmp = C_Orders::ToMarket(type, m_InfosManager.FinanceStop, m_InfosManager.FinanceTake, m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                                m_Position.Ticket = (m_bAccountHedging ? tmp : (m_Position.Ticket > 0 ? m_Position.Ticket : tmp));
                                if (PositionSelectByTicket(m_Position.Ticket)) SetInfoPositions(); else m_Position.Ticket = 0;
                        }
//+------------------------------------------------------------------+

これらのテストを追加することで、配置されたボリュームが指定された最大ボリュームを超えた場合、EAは操作をおこなうことができないと言っているのです。まだ細かいことはこれから解決していくのですが、とりあえずはこんな感じでやっていきます。また、バランスをくずすのでコードから削除された行があることに注意してください。

次に、C_ManagerクラスがEAの動作を管理できるように、EAとの通信を支援するルーチンが必要です。そのために、まず次のコードに示すような、非常に微妙だが必要な機能を作ることにします。

inline void UpdatePosition(const bool bSwap = false)
                        {
                                int ret;
                                
                                if ((m_bAccountHedging) && (m_Position.Ticket > 0) && (bSwap)) SetUserError(ERR_Unknown);
                                m_Position.Ticket = ((m_Position.Ticket == 0) && (bSwap) ? m_TicketPending : m_Position.Ticket);
                                m_TicketPending = (bSwap ? 0 : m_TicketPending);
                                if (PositionSelectByTicket(m_Position.Ticket))
                                {
                                        ret = SetInfoPositions();
                                        m_StaticLeverage += (ret > 0 ? ret : 0);
                                }
                        }

上記のこのコードを甘く見てはいけません。複雑さという点では価値の低いコードに見えますが、C_ManagerクラスがEAがおこなっていることを管理できるようにするために極めて必要なものです。このコードを理解するためには、EAがいつどのようにこのコードを呼び出すかを理解する必要があります。しかし、EA内部の手順は多くの人がおこなうものとは全く異なるので、これは後述します。

上記のコードを見ただけで、いくつかのことに気づくことができます。ヘッジ口座でポジションを持ち、bSwapがtrueの場合はエラーとなります。この場合、別の場所で処理されるため、エラーを報告するだけです。ポジションチケットの変数が空で、bSwapがtrue'の場合、指値注文がポジションになっていることを意味します。しかし、すでにポジションを持っていた場合、(ネッティング口座の)指値注文は、ポジション量と、場合によってはエントリ価格を変更することになります。そんなシチュエーションをこの行で分析しています

bSwapがtrueに設定されている場合、指値注文が存在しなくなったことを意味するので、ここで修正します。次に、次のようなチェックをしてみましょう。ポジションがあるかどうかを確認します。あれば、、データを更新するプロシージャを実行します。このプロシージャは、アップデート前とアップデート後のボリュームの差を計算し、このボリュームを返すものです。 .返されたデータがプラスであれば、ボリュームまたはロットのボリュームファクターが増加したことを示します。 この状況はネッティング口座ではよくあることですが、ヘッジ口座では常に現在のロットボリュームが戻り値となります。この返された値を、それまで静的変数に入っていた値に追加していきます。このようにして、EAが動作中に使用する、または既に使用したボリュームを考慮することができますが、

あまり深く考えずとも、すぐに別のルーティンが必要だと気づくはずです。ポジションを削除したり、決済したりする役割を果たすことになります。以下に示します。

inline void RemovePosition(void)
                        {
                                if (m_Position.Ticket == 0) return;
                                if (PositionSelectByTicket(m_Position.Ticket)) ClosePosition(m_Position.Ticket);
                                ZeroMemory(m_Position);
                        }

EAがポジションを決済するか、サーバがポジションを決済したことをC_Managerクラスに通知するだけで、リミット(テイクプロフィットまたはストップロス)に到達したため、またはポジションが決済される原因となる何かが起こったため、ここではエラーはありません。しかし、ポジションがない状態で、EAが誤ってこの関数を呼び出した場合、単にロールバックするだけですポジションがあれば決済し、最後にポジションデータが格納されているメモリ領域に存在するデータをすべてクリアします

上記の2つの関数はうまく機能しますが、多くの異なる状況において、実際に必要なことにはあまり適していません。なので、これらの機能を見て、あまり興奮しないでください。今言ったように、それらは機能しますが、十分ではありませんから、優れた堅牢性を持つ自動化EAに適しているとは思わないでください。ここで築いているものには、他のより優れた関数が必要です。しかし、今回は別のタイプの関数を使う理由を紹介する必要があるので、これはしないことにします。正しく理解するためには、EAのコードを表示する必要があります。これは次の記事でおこないます。

このような作業を経て、理論的には堅牢で信頼性の高いシステムが完成し、最終的には人間のトレーダーが監視するだけで動作するような自動化を開始することができます。ただし、理論的にはとしたことに注意してください。。システムで障害が発生する可能性があるからです。ただし、これからはこれらの問題を_LastError変数でチェックすることで、何か問題が起きたかどうかを確認することができるようになります。例えば、前回の記事で説明したカスタムエラー列挙を使用する場合、障害が深刻ならばチャートからEAを削除しなければなりません。

チャートからEAを削除するのは難しい作業ではありません。実は、ExpertRemove関数を呼び出すことで、簡単にできます。 ただし、この作業は私たちの最大の問題ではありません。本当に難しいのは、おそらくまだ存在しているであろうポジションと指値注文をどうするかということです。

最悪の場合、単に決済するか、手動で削除することになります。しかし、ヘッジタイプの口座で、同じ資産に対して、2つ以上のEAを自動的に走らせている場合、これらのEAの1つが単にラインから離れることを決定し、ここがチャートから削除された場合、どうなるでしょうか。あとは、ツールボックスウィンドウの[取引]タブ(図01)で注文とポジションを確認し、閉じられた不良EAによって開かれた取引を決済してみてください。この場合、不良とは、そのEAがひどくプログラムされていることを意味するものではありません。考え方は明確だと思います。

図01

図01:MetaTrader 5プラットフォームで注文とポジションを探す場所

ここでプログラミングが少しは役に立ちますが、奇跡を期待しないでください。その可能性の範囲内でしか、私たちを助けてくれません。では、この具体的なケースで、不良EAが、おかしく動作しながら、回り回って、結局、その悪い癖と不祥事でチャートから追放された、という場合に、プログラミングをどう使うかを見てみましょう。


デストラクタの使用

デストラクタは、どの時点でもコードから本当に呼び出されることのないクラス関数です。実際、コンストラクタは、その「同僚」であるデストラクタと同様に、クラスの存続期間中に一度だけ呼び出されます。コンストラクタはクラスが生まれるときに呼ばれ、デストラクタはクラスが死ぬときに呼ばれます。どちらの状況でも、プログラマーが、クラスがいつ生まれ、いつ死ぬかを知ることはほとんどありません。通常はコンパイラがおこなうのですが、特定のケースでは、プログラマがコードの中のあるものを使って、クラスがいつ生まれ、いつ死ぬかを決めることができます。しかし、命を与える呼び出しは、コンストラクタで使うパラメータが原因で起こることさえあるのです。死ぬときに起こることについては、同じことは言えません。

しかし、今はそんなことは気にしないで大丈夫です。EAコードに入ればよくわかるでしょう。

クラスがいつ死ぬかは別として、そうなったときにどうすればいいかが分かります。このようにして、C_Managerクラスに、EAをチャートから削除するときに、EAによっておこなわれ、残されたもの、つまり、ポジションを決済して、オーダーブックにある指値注文を削除することを伝えることができます。しかし、EAがチャートから追い出されたものの、デストラクタがそのタスクを実行できなかった可能性もあるので、ツールボックスを見て確認することを忘れないでください(図0)。

そのために、エラー列挙に新しい値を追加してみましょう。

class C_Manager : private C_Orders
{
        enum eErrUser {ERR_Unknown, ERR_Excommunicate};
        private :

この値は、デストラクタにEAがチャートから削除されたことを伝え、EAが担当したすべてのことを元に戻さなければならないことを示します。デストラクタがパラメータを通して実際に値を得ることができない場合、どのようにしてこの値を得ることができるかを理解するために、以下のコードを見てください。

                ~C_Manager()
                {
                        if (_LastError == (ERR_USER_ERROR_FIRST + ERR_Excommunicate))
                        {
                                if (m_TicketPending > 0) RemoveOrderPendent(m_TicketPending);
                                if (m_Position.Ticket > 0) ClosePosition(m_Position.Ticket);
                                Print("EA was kicked off the chart for making a serious mistake.");
                        }
                }

コードは非常に単純です。何が起こりうるかを理解するために、_LastErrorの値を確認します。したがって、エラー値が先ほど列挙に加えたものと同じであれば、そのEAは悪行としてチャートから削除されるはずです。この場合、指値注文がある場合は、注文の削除リクエストがサーバに送信されます。また、ポジションがある場合は、決済リクエストがサーバに送信されます。最後に、その時の様子を端末で知らせします

ただし、これはまったく安全ではないことを忘れないでください。私たちはただ、何らかのプログラミングの助けを得ようとしているのです。EAがチャートから削除されたときに注文やポジションを残したならば、トレーダーであるあなたが注意深く削除する必要があります。このトピックは短かったですが、十分にご理解いただけたでしょうか。この記事を終える前に、次のトピックで検討する、もう一つのことを見ておきましょう。


エラー許容レベルの作成

この記事と前回の記事のすべてのコードを見て、私が説明していることを理解できたなら、C_ManagerクラスはEAに対して非常に厳しく、たとえ小さな失敗でも、どんなタイプの失敗も認めないことを想像していらっしゃるに違いありません。確かにそうですが、これは少し変えることができます。エラーにも種類があり、それほど深刻ではないミスや、EAの責任ではないミスもあります。

このようなエラーの1つは、サーバがTRADE_RETCODE_MARKET_CLOSEDを報告する場合です。これは、市場が閉鎖されているために起こります。この種のエラーは、EAの責任ではないので、許容されます。また、TRADE_RETCODE_CLIENT_DISABLES_ATというタイプもあり、これはアルゴリズム取引がプラットフォームでは無効であるために発生します。

EAに過失がない、つまり様々な理由で発生するエラーには様々な種類があります。そのため、うまくいかないことをすべてEAのせいにするようなEAに対する厳しさは、まったく公平ではありません。そのため、ある種のエラーを制御し、許容するための何らかの仕組みを作る必要があります。エラーが深刻でないようであれば、無視してEAをチャートに残しておくこともできます。ただし、本当に重大なエラーである場合は、その重大さに応じて何らかの判断をすることができます。

そこで、C_Managerクラスにpublic関数を作成し、EAがエラーの可能性の重大性に疑問を持ったときに呼び出せるようにします。関数コードを以下に示します。

                void CheckToleranceLevel(void)
                        {
                                switch (_LastError)
                                {
                                        case ERR_SUCCESSreturn;
                                        case ERR_USER_ERROR_FIRST + ERR_Unknown:
                                                Print("A serious error has occurred in the EA system. This one cannot continue on the chart.");
                                                SetUserError(ERR_Excommunicate);
                                                ExpertRemove();
                                                break;
                                        default:
                                                Print("A low severity error has occurred in the EA system. Your code is:", _LastError);
                                                ResetLastError();
                                }
                        }

ここで最終的な解決策を提示しているわけではありませんし、100%正しいわけでもありません。私は、EAで間違いを許容する方法を作るために、どのように進めればよいかを示しているだけです。上のコードは、公差が異なる2つの例を示しています。

より深刻なエラーの可能性もあり、その場合はEAがチャートから削除されます。正しい方法は、2つの関数を使用することで、1つはEA例外エラーを設定し、もう1つはそれを削除するコマンドを設定することです。したがって、C_Managerクラスのデストラクタは、EAがおこなっていたことを削除したり、元に戻したりしようとします。第二の方法として、エラーを軽減する方法があります。この場合、トレーダーに警告を表示し、エラー表示を削除して値を明確に残すだけなので、エラーなしで呼び出しがおこなわれた場合は、関数は単に終了するだけです

理想的には、どのエラーが有効でどのエラーが無効かを1つずつ定義することで、ここでのエラー処理を容易にするべきです。もう1つは、C_Managerクラスの内部でこの呼び出しをしないことで、エラー耐性が非常に高くなることです。これは、本当にやめておいた方がいいです。一定時間ごとに上記関数の呼び出しを追加することで、EAへの呼び出しを忘れないようにすることができますが、今のところ、この呼び出しはEAのコード内で、非常に特定のポイントでおこなわれることになっています。


結論

この記事は前回の記事を補完するものであり、その内容を読んで理解するのはそれほど難しくはありません。タスクを完成するための材料は十分にあったと思います。

ここで紹介したことを使うために、すでにEAのコードを見てみたいという方も多いと思いますが、自動化されたEAとなると、ことはそう単純ではありません。そこで次回は、この件に関する私の経験談を交えながら、EAコーディングの注意点や問題点、リスクについて考えてみたいと思います。この2回を踏まえて、次回以降に紹介するものがあるので、EAコードだけに絞って紹介します。というわけで、次回以降もいろいろとネタが出てきますので、落ち着いて勉強して、このクラスシステムの仕組みを理解するようにしましょう。


MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/11256

MQL5クックブック - マクロ経済イベントデータベース MQL5クックブック - マクロ経済イベントデータベース
この記事では、SQLiteエンジンに基づいてデータベースを処理する可能性について説明します。CDatabaseクラスは、OOP原則を便利かつ効率的に使用するために作成されました。その後、マクロ経済イベントのデータベースの作成と管理に関与しています。この記事では、CDatabaseクラスの複数のメソッドを使用する例を示します。
自動で動くEAを作る(第06回):口座の種類(I) 自動で動くEAを作る(第06回):口座の種類(I)
今日は、自動モードでシンプルかつ安全に動作するエキスパートアドバイザー(EA)を作成する方法を紹介します。このEAは、現状ではどんな状況でも機能しますが、まだ自動化には至っていません。まだ、いくつかの点で工夫が必要です。
MetaTrader 5におけるバイナリーオプション戦略のテストと最適化 MetaTrader 5におけるバイナリーオプション戦略のテストと最適化
今回は、MetaTrader5でのバイナリーオプション戦略の確認と最適化をおこないます。
ニューラルネットワークが簡単に(第33部):分散型Q学習における分位点回帰 ニューラルネットワークが簡単に(第33部):分散型Q学習における分位点回帰
分散型Q学習の研究を続けます。今日は、この方法を反対側から見てみましょう。価格予測問題を解決するために、分位点回帰を利用する可能性を検討します。