English Русский 中文 Español Deutsch Português
preview
自動で動くEAを作る(第09回):自動化(I)

自動で動くEAを作る(第09回):自動化(I)

MetaTrader 5トレーディング | 3 5月 2023, 10:19
652 0
Daniel Jose
Daniel Jose

はじめに

前回の「自動で動くEAを作る(第08回):OnTradeTransaction」稿では、ちょっと面白いイベント処理関数を使って、MetaTrader 5プラットフォームを活用する方法を説明しました。ここでは、EAに最初のレベルの自動化を構築することから始めます。

既存の多くのメカニズムとは異なり、EAやプラットフォームに負荷をかけないメカニズムを考えていくことにします。このメカニズムは、主にネッティング口座を対象としていますが、ヘッジ口座でも利用可能です。

まずは、OCO注文を使った簡単なシステムから紹介します。その後、機能を拡張し、特に注文を逃すリスクが高い非常に不安定な市場での取引を好む方向けに、さらに信頼性が高く興味深いシステムを提供する予定です。


OCO注文のブレイクイーブンとトレーリングストップの作成

ご存じない方のために説明します。OCO (One-Cancels-the-Other)発注システムとは、テイクプロフィットやストップロスを注文やポジションそのものに設定するシステムです。注文がキャンセルされるか、ポジションが決済されると、これらのテイクプロフィットまたはストップロス注文もキャンセルされます。

テイクプロフィット注文やストップロス注文は、いつでも削除・追加することができます。実用上、またコードを複雑にしないために、これらは常に、EAが取引サーバーに注文を送信する瞬間に作成され、リミットのいずれかに到達してポジションが決済されると存在しなくなるものとします。

トリガーメカニズムを作るために、C_Managerクラスを使用することにします。ここでは、ブレイクイーブンとトレーリングストップのトリガーシステムを得るためのほぼすべての準備が整っています。まず、ポジションのブレイクイーブンレベルを生成する関数を追加してみましょう。この関数の全コードを以下に示します。

inline void TriggerBreakeven(void)
                        {
                                if (PositionSelectByTicket(m_Position.Ticket))
                                        if (PositionGetDouble(POSITION_PROFIT) >= m_Trigger)
                                                m_Position.EnableBreakEven = (ModifyPricePoints(m_Position.Ticket, m_Position.PriceOpen, m_Position.PriceOpen, m_Position.TP) ? false : true);
                        }

おそらく、ここに示したものよりはるかに複雑な関数を期待されたでしょうが、驚くことに、このシンプルな関数がポジションのブレイクイーブンレベルをトリガーすることができるのです。どうしてこんなことができるのかわからないという方は、このシンプルな関数以外は必要ないと思っていただけるように、この仕組みを分析してみましょう。

まず、PositionSelectByTicket関数を呼び出します。ポジションに関するすべての更新情報をダウンロードする関数です。次に、POSITION_PROFIT引数を指定してPositionGetDouble関数を使用し、PositionSelectByTicketの呼び出しによって読み込まれた最新の財務値を取得します。この値と、クラス初期化時のコンストラクタ呼び出しで入力された値とを比較します。

値がそれ以上であれば(これはトリガーです)、ブレイクイーブンに到達できることを示唆しています。そして、ポジションが建てられた時の価格値をC_Ordersクラスの関数に送ります。この対話が成功すれば、クラスはブレイクイーブンに達したことを示します。

この関数は結構シンプルだと思いませんか。ただし、その定義はコードのprivate部分に含まれており、EAがアクセスすることになります。それは、以下に示すトレーリングストップ関数です。

inline void TriggerTrailingStop(void)
                        {
                                double price;
                                
                                if ((m_Position.Ticket == 0) || (m_Position.SL == 0)) return;
                                if (m_Position.EnableBreakEven) TriggerBreakeven(); else
                                {
                                        price = SymbolInfoDouble(_Symbol, (GetTerminalInfos().ChartMode == SYMBOL_CHART_MODE_LAST ? SYMBOL_LAST : (m_Position.IsBuy ? SYMBOL_ASK : SYMBOL_BID)));
                                        if (MathAbs(price - m_Position.SL) >= (m_Position.Gap * 2))
                                                ModifyPricePoints(m_Position.Ticket, m_Position.PriceOpen, (m_Position.SL + (m_Position.Gap * (m_Position.IsBuy ? 1 : -1))), m_Position.TP);
                                }
                        }

ブレイクイーブンをトリガーして実行した後、次にEAがTriggerTrailingStop関数を呼び出したら、ストップロスを移動(トレール)する可能性を確認します。

しかしその前に、ブレイクイーブン関数が実際に呼び出される場所に注目してください。トレーリングストップの動きは、ブレイクイーブンの動きよりも少し複雑なトリガーメカニズムを持っています。今回は、少し違った方法でおこないます。資産、チャートモード、市場タイプに依存せず、ポジションの利益水準のみが重要なブレイクイーブンと異なり、、トレーリングストップでは、チャートの種類とポジションの種類という2つのことを知ることが必要です。

EA開発者の中には、トレーリングストップトリガーを作成する際に使用するチャートのプロット方法を気にしない人も時々います。これは、場合によっては正しいことです。もし、その資産が歴史上比較的高いスプレッド分散(最良の売り手と最良の買い手の差)を持っているならば、たとえLast priceに基づいたチャートであっても、プロッティングモードを無視することができます。なぜなら、もし動きがスプレッドの範囲内であれば、ストップロス注文が間違ったポイントになるため、問題が発生する可能性が非常に高いからです。

このようなトリガーを適切に開発するために資産をよく研究し、理解することがとても重要なのはこのためです。ここでの考え方は、どうやってでも資産価格をキャプチャすることです。この値はどうしても必要です。これができたら、ストップロスがある点からこの価格を引きます。この場合、売りか買いかは関係なく、価値は自動的に金額ではなくポイントでの価値に変換されます。この値は、取引サーバーの更新ごとに必ず計算するポイント数の2倍以上である必要があります。成功した場合は、ギャップポイントの数だけストップロスの位置を移動させます。したがって、間隔は常に同じになり、サイクルがやり直されることになります。

このトリガーメカニズムは、どんな状況でも完璧に機能します。重要なのは、信じられないほど計量かつ高速だとあることです。このトリガーは、ねずみ取りのようなものだと考えてください。仕掛けが複雑すぎたり、実行時間が長かったりすると、ねずみは結局、罠が発動する前にチーズを掴んで逃げてしまいます。

上記の関数を呼び出すために必要な関数やイベントハンドラは何なのでしょうか。イベントハンドラはOnTick関数であるべきだと考える方が多いかもしれません。これは正しいですか。正しくありません.説明するために、次の話題に移りましょう。


トリガーの呼び出し元としてOnTickを使ってはいけないのは何故でしょうか。

OnTick関数を他の関数を呼び出す方法として使うのがとても魅力的なことはわかっていますが、これは間違いなく最大の間違いです。正しい方法は、以下のようにOnTimeイベントを使用することです。

//+------------------------------------------------------------------+
int OnInit()
{
        manager = new C_Manager(def_MAGIC_NUMBER, user03, user02, user01, user04, user08);
        mouse = new C_Mouse(user05, user06, user07, user03, user02, user01);
        (*manager).CheckToleranceLevel();
        EventSetMillisecondTimer(100);

        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        delete manager;
        delete mouse;
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick() { }
//+------------------------------------------------------------------+
void OnTimer()
{
        (*manager).TriggerTrailingStop();
}
//+------------------------------------------------------------------+

OnInitイベントでは、OnTimeイベントが生成されるように短い値を定義しています。EventSetMillisecondTimer関数を使用しておこないます。ほとんどの場合、50ミリ秒から始まり、任意の値を設定することができます。しかし、OnDeInitイベント内でEventKillTimer関数を呼び出すことも忘れてはいけません。こうすることで、EAがOnTimeイベントをリリースするので、MetaTrader 5プラットフォームがイベントを生成し続けることはありません。プラットフォームがこの問題を解決し、イベントの発生を停止することができたとしても、システムをリリースすることは良いことです。つまり、この場合、100ミリ秒ごと、つまり1秒間に約10回、上のトピックで示したトリガーの検証をおこなうことになります。

しかし、それは質問の答えにはなっていません。トリガーの呼び出し元としてOnTickイベントハンドラ関数を使用してはいけないのはなぜでしょうか。実は、上記の説明では、この疑問には答えられないのですが、なぜこれをやってはいけないのか、もう少し詳しく考えてみましょう。

OnTickイベントは、サーバーが取引するティックごとにトリガーされます。1分足チャートでもバーチャートを見てしまうと、本当の意味で何が起こっているのかがわからなくなってしまいます。そのためには、機関投資家向けロボットとして知られている、HFT高頻度取引)のレベルまで下がる必要があるでしょう。

これが取引サーバーから何百キロも離れたコンピュータにインストールされたプラットフォームで動作するEAでは不可能であることを知らない人が多いようです。数メートル離れた専用サーバーで稼働するHFTと比較できる可能性は微塵もないのです。データがサーバーに届くまでの時間である、いわゆる遅延のためです。オンラインゲームをされる方ならお分かりになると思いますが、そうでない方のために申し上げると、取引サーバーがおこなう操作の頻度に比べて、遅延がはるかに高いのです。つまり、HFTに匹敵する性能に到達することは不可能です。

OnTickイベントの話に戻りますが、わずか1ミリ秒の間に、サーバーはこのようなイベントを10個以上発生させることができると言えます。サーバーがトリガーしたすべてのイベントをトリガーするために非常に多くのイベントがプラットフォームに到達した場合、あなたのEAが動作し始めると同時に、プラットフォームはクラッシュします。これは、プロセッサが処理しきれないほど多くのイベントを処理するのに完全に忙しくなるためです。つまり、どのように整理しても、同じ関数(この場合はトレーリングストップのトリガー)を大量に呼び出すため、必要なアクションを実行することができないのです。

しばらくはこのようなことが実際には発生せず、プラットフォームが円滑に稼働し続けるかもしれません。しかし、システムが私たちの位置を検知してトリガーの確認を開始すると、プラットフォームがクラッシュする確率が非常に高くなるため、深刻な問題に直面することになります。

この確率は、資産のボラティリティが急激に上昇した場合、さらに大きくなる場合があります。特に指数先物のような資産ではよくあることです。ですから、OnTickをトリガーを発動する方法として使おうとはしないでください。このEAイベントハンドラのことは忘れてください。私たち凡人が使うものではなく、HFTが取引サーバーを監視できるようにするためのものです。

そこで、トリガーシステムの確認方法として最も適切なのが、OnTimeイベントを利用することです。すべてのトリガーを確認する可能性を提供しながら、品質を損なわないように、十分に短い時間で確認するように構成されています。こうすることで、安全で堅牢、静かで信頼性の高いEAを手に入れることができるのです。

トレーリングストップイベントのトリガーに関連する別の問題があります。EAシステムの中には、実際にトレーリングストップが発動する前にブレイクイーブンが発生しないものもあります。ポジションを建てた瞬間からトレーリングストップを使用するのです。これは少し奇妙に思えるかもしれませんが、実は要は、OSや構成ですでにこの概念を実行しているということなのです。この場合、システムは上に示したものと非常によく似ていますが、使用するトレーリング距離が異なります。ただし、概念そのものは変わりません。

このモデルの他に、実はトレーリングストップやブレイクイーブンを設けないモデルもあるのです。私たちはもう1つ、市場が私たちのポジションに逆らうようになった場合に、エグジットを保証するシステムを持っています。これは別のタイプのトリガーであり、別の記事で検討することにします。


トレーリングストップとブレイクイーブンを未決注文でおこなう

OCO発注システムに基づいたポジションを持ちたい場合、上で紹介したシステムは非常に有効です。しかし、このOCO発注システムには、ボラティリティという問題があります。ボラティリティが非常に高い場合、注文がスキップされ、好ましくない状況になることがあります。

この問題には「解決策」があり、それは未決注文を使用してエグジットを保証することです。しかし、この「解決策」はヘッジシステムには実装できない、つまり、提示されたEAでは使用できないのです。これをヘッジ口座で使おうとすると、C_Managerクラスに対して重大なミスを犯すことになるので、EAはチャートから追放されることになります。しかし、C_Managerクラスでいくつかの調整をおこない、EAがヘッジ口座で反対方向の2つのポジションを持つことができるようにすることができます。ネッティング口座を使っている場合にも同様のことができるので、その方法を紹介します。

しかし、考えてみれば、ネッティング口座で逆方向のポジションを建てる意味はないのです。注文サーバーが未決注文をキャプチャした場合、両方のポジションを決済する要求をサーバーに送信するのがよいでしょう。これにより、ヘッジ口座のEAがネッティング口座と同じような挙動をするようになります。未決注文を使用してポジションを決済することになります。

このアイデアはいかがでしょうか。実装に入る前に、いくつかの詳細と疑問があります。

まず、未決注文は、必ずしも指定した時点で執行されるとは限りません。未決注文は、どこまでも価格を追いかけていきます。また、EAに重大な障害が発生し、ポジションや注文がキャンセルまたは決済された場合、もう一方の脚は相手がいない状態になる可能性があることも問題です。

しかし、利点もあります。すべてがうまくいってサーバーとの接続が失われた場合、同じ数量の反対方向の未決注文がポジションを決済する(ネッティング口座)か、価格を固定する(ヘッジ口座)ことになります。

このように、この手法にはメリットとデメリットがあります。

これを使うには、C_Managerクラスを少し変更する必要があります。変更はわかりやすく、使いたくなければ元に戻すことができます。ただし、ここでひとつ重要なことがあります。この方法を使用する場合は、EAが発注した未決注文を削除しないように注意してください。削除した場合、決済を担当する脚がない状態になってしまいます。

このシステムの場合、一度コンパイルしたコードをユーザーが変更できるようにすることは推奨されません。適さない場合は、EAから切り離すことができます。常時オンまたはオフを維持する必要があります。そのために、C_Managerクラスのコードに新しい定義を作成することにします。以下を参照してください。

//+------------------------------------------------------------------+
#define def_MAX_LEVERAGE                10
#define def_ORDER_FINISH                false
//+------------------------------------------------------------------+

この定義がtrueに設定されている場合、システムは未決注文を介してストップメソッドを使用します。つまり、テイクプロフィットポイントがなくなると、いろいろとややこしくなり、反対側の脚が使えなくなる可能性があるためです。このパラメータをfalseに設定すると、この記事の最初のトピックで検討したブレイクイーブンとトレーリングストップのメソッドを使用し、そうすることで、OCO発注システムを利用することになります。デフォルトでfalseのままにしておきます。本トピックで説明するメソッドを使用する場合は、この値をfalseからtrueに変更して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, (def_ORDER_FINISH ? 0 : m_InfosManager.FinanceStop), (def_ORDER_FINISH ? 0 : 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, (def_ORDER_FINISH ? 0 : m_InfosManager.FinanceStop), (def_ORDER_FINISH ? 0 : m_InfosManager.FinanceTake), m_InfosManager.Leverage, m_InfosManager.IsDayTrade);
                                m_Position.Ticket = (m_bAccountHedging ? tmp : (m_Position.Ticket > 0 ? m_Position.Ticket : tmp));
                        }
//+------------------------------------------------------------------+

これらの部分を修正し、テイクプロフィットやストップロスの価格が実際には作成されないようにする必要があります。そうすると、サーバーはこれらの価格が作成されないことを理解し、利益制限と損失制限のない注文を持つことになります。ストップロスを含まない成行注文を出したり、ストップロスを含まない未決注文を出したりしていることに恐怖を感じるかもしれません。でも、ご安心ください。その実態を知るには、システムを試してみることです。これができたら、次のような修正をする必要があります。

                void PendingToPosition(void)
                        {
                                ResetLastError();
                                if ((m_bAccountHedging) && (m_Position.Ticket > 0))
                                {
                                        if (def_ORDER_FINISH)
                                        {
                                                if (ClosePosition(m_Position.Ticket)) ZeroMemory(m_Position.Ticket);
                                                ClosePosition(m_TicketPending);                                         
                                        }else SetUserError(ERR_Unknown);
                                }else m_Position.Ticket = (m_Position.Ticket == 0 ? m_TicketPending : m_Position.Ticket);
                                m_TicketPending = 0;
                                if (_LastError != ERR_SUCCESS) UpdatePosition(m_Position.Ticket);
                                CheckToleranceLevel();
                        }

ここで、EAが未決注文がポジションになったことを通知するとき、ヘッジ口座にすでにポジションを持っている場合、問題が発生することがあります。この場合、パラメータにfalseが設定されているとエラーメッセージが表示されます。trueが設定されている場合、元のポジションを決済する要求を送り、そのメモリ領域をリセットします。また、新たに建てられたポジションを決済します。なお、サーバーとの接続が良好であれば、両方のポジションを正常に決済することができ、市場でのエクスポージャーをゼロにすることができます。

次に、システムで、決済注文として、つまりストップロスとして使用される未決注文を作成し、オーダーブックに残しておく必要があります。この点は、おそらくシステム全体の中で最も重要です。なぜなら、うまく計画されないと、ストップレベルがないまま放置される口座に深刻な問題が発生するからです。このため、以下を確認することで、EAが何をするのか意識する必要があります。

図01

図01:未決注文とポジションを確認する場所

図01に示すウィンドウは、EAがサーバー上でどのような動作をおこなうかを分析できるように、常に開いておく必要があります。どんなに信頼できそうなEAであっても、盲目的に信用してはいけません。

EAの意図を常に監視します。つまり、EAにストップロスポイントを持たせるためには、C_Managerクラスが未決注文を作成する必要があります。以下のように作成されています。

                void UpdatePosition(const ulong ticket)
                        {
                                int ret;
                                double price;
                                
                                if ((ticket == 0) || (ticket != m_Position.Ticket)) return;
                                if (PositionSelectByTicket(m_Position.Ticket))
                                {
                                        ret = SetInfoPositions();
                                        if (def_ORDER_FINISH)
                                        {
                                                price = m_Position.PriceOpen + (FinanceToPoints(m_InfosManager.FinanceStop, m_Position.Leverage) * (m_Position.IsBuy ? -1 : 1));
                                                if (m_TicketPending > 0) if (OrderSelect(m_TicketPending))
                                                {
                                                        price = OrderGetDouble(ORDER_PRICE_OPEN);
                                                        C_Orders::RemoveOrderPendent(m_TicketPending);
                                                }
                                                m_TicketPending = C_Orders::CreateOrder(m_Position.IsBuy ? ORDER_TYPE_SELL : ORDER_TYPE_BUY, price, 0, 0, m_Position.Leverage, m_InfosManager.IsDayTrade);
                                        }
                                        m_StaticLeverage += (ret > 0 ? ret : 0);
                                }else
				{
					ZeroMemory(m_Position);
                                	if (def_ORDER_FINISH)
					{
						RemoveOrderPendent(m_TicketPending);
						m_TicketPending = 0;
					}
				}
                                ResetLastError();
                        }

まず、発注システムが「true」の値に設定されているかどうかを確認します。この条件を満たした場合、組み立てを開始する価格帯を計算し、未決注文をポジションストップとして使用します。次に、すでに注文があるかどうかを確認します。もしあれば、その価格をそのままキャプチャし、注文をブックから削除します。いずれにせよ、新しい未決注文を作ろうとします。すべてが正しい場合、ストップロス注文として機能する未決注文をオーダーブックに表示します。

注意:ポジションが決済された場合、未決注文はキャンセルされなければなりません。これは、次のコードラインを使用しておこなうことができます。

ここで、SetInfoPosition関数を変更して、ブレイクイーブンを作る必要があるのか、それともトレーリングストップですぐに始められるのか、正しく表示されるようにする必要があります。新しい関数は次のとおりです。

inline int SetInfoPositions(void)
                        {
                                double v1, v2;
                                int tmp = m_Position.Leverage;
                                
                                m_Position.Leverage = (int)(PositionGetDouble(POSITION_VOLUME) / GetTerminalInfos().VolMinimal);
                                m_Position.IsBuy = ((ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE)) == POSITION_TYPE_BUY;
                                m_Position.TP = PositionGetDouble(POSITION_TP);
                                v1 = m_Position.SL = PositionGetDouble(POSITION_SL);
                                v2 = m_Position.PriceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
                                if (def_ORDER_FINISH) if (m_TicketPending > 0) if (OrderSelect(m_TicketPending)) v1 = OrderGetDouble(ORDER_PRICE_OPEN);
                                m_Position.EnableBreakEven = (def_ORDER_FINISH ? m_TicketPending == 0 : m_Position.EnableBreakEven) || (m_Position.IsBuy ? (v1 < v2) : (v1 > v2));
                                m_Position.Gap = FinanceToPoints(m_Trigger, m_Position.Leverage);

                                return m_Position.Leverage - tmp;
                        }

ここでは、未決注文が位置する価格をキャプチャするために一連のテストをおこないます。何らかの理由で未決注文チケットがまだ作成されていない場合、目的に応じてブレイクイーブン指標を適切に起動させることになります。

今のところ、未決注文をストップポイントとするシステムでは、ブレイクイーブンもトレーリングストップも実際には使用できません。このシステムを実現するためには、トリガーはすでに設定されているので、本当に必要ありません。ブレイクイーブンについては、動きを実装するために、以下を追加します。

inline void TriggerBreakeven(void)
                        {
                                double price;
                                
                                if (PositionSelectByTicket(m_Position.Ticket))
                                        if (PositionGetDouble(POSITION_PROFIT) >= m_Trigger)
                                        {
                                                price = m_Position.PriceOpen + (GetTerminalInfos().PointPerTick * (m_Position.IsBuy ? 1 : -1));
                                                if (def_ORDER_FINISH)
                                                {
                                                        if (m_TicketPending > 0) m_Position.EnableBreakEven = !ModifyPricePoints(m_TicketPending, price, 0, 0);
                                                }else m_Position.EnableBreakEven = !ModifyPricePoints(m_Position.Ticket, m_Position.PriceOpen, price, m_Position.TP);
                                        }
                        }

ブレイクイーブンの実行を担当するこの関数の以前のバージョンでは、ストップ注文の価格はポジションの開始価格と正確に等しくなっていました。多くのトレーダーは、たとえ小さくても、何らかの利益を得たいものです。そこで、ブレイクイーブンが発生したときに、始値から1ティックずらした注文を出すように関数を修正することにしました。したがって、トレーダーは少なくとも1ティックの利益を得ることができます。

このシステムは、どのような資産や市場タイプにも対応し、資産そのものから得られるデータを使って、ストップラインをどこに設定すべきかを知ることができるからです。

これが終わると、未決注文に基づくストップモデルを使用しているかどうかを確認します。使用していれば、未決注文変数に値があるかどうかを確認します。 もしそのような値があれば、注文を出したポイントを新しいポジションに変更する要求を送ります。OCO注文に基づくシステムを使用する場合は、上記の方法を使用します。これらの確認は無意味に思えるかもしれませんが、サーバーに無効な要求を送ることを防いでくれます。

では、この場合のトレーリングストップ関数の働きを見てみましょう。

inline void TriggerTrailingStop(void)
                        {
                                double price, v1;
                                
                                if ((m_Position.Ticket == 0) || (def_ORDER_FINISH ? m_TicketPending == 0 : m_Position.SL == 0)) return;
                                if (m_Position.EnableBreakEven) TriggerBreakeven(); else
                                {
                                        price = SymbolInfoDouble(_Symbol, (GetTerminalInfos().ChartMode == SYMBOL_CHART_MODE_LAST ? SYMBOL_LAST : (m_Position.IsBuy ? SYMBOL_ASK : SYMBOL_BID)));
                                        v1 = m_Position.SL;
                                        if (def_ORDER_FINISH) if (OrderSelect(m_TicketPending)) v1 = OrderGetDouble(ORDER_PRICE_OPEN);
                                        if (v1 > 0) if (MathAbs(price - v1) >= (m_Position.Gap * 2)) 
                                        {
                                                price = v1 + (m_Position.Gap * (m_Position.IsBuy ? 1 : -1));
                                                if (def_ORDER_FINISH) ModifyPricePoints(m_TicketPending, price, 0, 0);
                                                else ModifyPricePoints(m_Position.Ticket, m_Position.PriceOpen, price, m_Position.TP);
                                        }
                                }
                        }

この関数は、一般の人には珍しいものを使っているので、一見すると不思議な感じがするかもしれません。では、その様子をご覧ください。まず、ポジションがあるかどうかを確認します。これは最も簡単な部分です。しかし、ここで不思議なのは ここで使用されるのは非常に珍しい三項演算子です。ここでは、未決チケットによる確認とストップロスの価格値による確認を分けています。この比較は、ポジション比較と併用されます。テストの結果、何もする必要がないと判断された場合は、単に呼び出し元へ戻るだけです。

何か必要なことがあれば、ブレイクイーブンをテストします。すでに実行されている場合は、トレーリングストップを有効にできるかどうかを確認するために、現在の資産価格のキャプチャを開始します。未決注文が発注された価格が必要な場合もあり、ファクタリングも同じになるので、ストップロスラインとして使用できる可能性のある値で一時変数を開始します。しかし、未決注文をストップポイントとして使用するかもしれません。この場合、動かなければならないので、価格があるところでキャプチャします。ファクタリングをおこない、ストップレベルを動かすべきかどうかを確認します。それが可能であれば、注文が動く価格を調整し、それに応じて未決注文やストップロスラインを移動させます。実際に何が動くかは、私たちが使っているシステムによって異なります。

下の動画は、このシステムが動作する様子を示したものです。何か違う、機能がない、と想像している方は、動画を見て結論を出してみてください。ただし、何が起こっているかを理解するためにおこなう最善のことは、EAをコンパイルし、デモ口座で独自のテストをおこなうことです。そうすることで、システム全体の理解がより確かで明確になります。

ビデオ01:未決注文によるストップシステムのデモ


結論

今回は、多くの方が好むあるいは欲しいと思っている、EAに組み込める最もシンプルなトリガーシステムを取り上げました。ただし、このシステムは、EAをポートフォリオ設定に使用したい場合には適していません。その場合は手動システムを使うことをお勧めしますが、読者がこの知識をどのように使うのかは正確にはわからないので、これはあくまで私のアドバイスです。

添付ファイルには完全なコードが含まれており、このタイプのメカニズムについてより詳しく学ぶことができます。このコードでは、最初にストップラインを使用するEAを用意することになります。ストップに未決注文を使うには、この記事で紹介したようにEAを修正する必要があります。

これで、残りのステップを実行するために最低限必要な自動化は完了しました。次回は、100%自動化されたEAの作り方についてご紹介します。幸運をお祈りします。

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

添付されたファイル |
自動で動くEAを作る(第10回):自動化(II) 自動で動くEAを作る(第10回):自動化(II)
自動化は、そのスケジュールを制御できなければ意味がありません。1日24時間働く効率的な労働者はいません。しかし、多くの人は、自動化されたシステムは24時間稼働するべきだと考えています。しかし、EAの稼働時間範囲を設定する手段を持つことは常に良いことです。この記事では、このような時間範囲を適切に設定する方法を検討します。
母集団最適化アルゴリズム:モンキーアルゴリズム(MA) 母集団最適化アルゴリズム:モンキーアルゴリズム(MA)
今回は、最適化アルゴリズムであるモンキーアルゴリズム(MA、Monkey Algorithm)について考えてみたいと思います。この動物が難関を乗り越え、最もアクセスしにくい木のてっぺんまで到達する能力が、MAアルゴリズムのアイデアの基礎となりました。
ニューラルネットワークの実験(第4回):テンプレート ニューラルネットワークの実験(第4回):テンプレート
この記事では、実験と非標準的な方法を使用して収益性の高い取引システムを開発し、ニューラルネットワークがトレーダーに役立つかどうかを確認します。ニューラルネットワークを取引に活用するための自給自足ツールとしてMetaTrader 5を使用します。簡単に説明します。
アラン・アンドリュースとその時系列分析手法 アラン・アンドリュースとその時系列分析手法
アラン・アンドリュースは、取引の分野において、現代世界で最も有名な「教育者」の一人です。彼の「ピッチフォーク」は、現代のほとんどの相場分析プログラムに搭載されています。しかし、ほとんどのトレーダーは、このツールが提供するチャンスのほんの一部も利用していません。その上、アンドリュースのオリジナルのトレーニングコースには、ピッチフォークだけでなく(ピッチフォークが主要な道具であることに変わりはないが)、他のいくつかの便利な構造についても説明があります。この記事では、アンドリュースがオリジナルのコースで教えていた驚異的なチャート分析法を紹介しています。画像がたくさん出てきますのでご注意ください。