MQL5でのトレードオペレーション - 簡単です

MetaQuotes | 2 10月, 2015

ほとんどすべてのトレーダーは利益をあげるためにマーケットに参加しますが、中にはそのプロセス自体を楽しむトレーダーもいます。しかし、手動のトレードだけが、エキサイティングな体験をさせてくれるわけではありません。自動トレードシステムの開発も非常に興味深いものです。トレードロボットの作成は面白いミステリー小説を読むのと同じくらい面白いものです。

トレーディングアルゴリズムを開発するには、もっとも重要なものを含む多くのテクニカルな問題に対処しなければなりません:

  1. 何をトレードするか?
  2. いつトレードするか?
  3. どうトレードするか?

最も適した通貨ペアを選ぶためにためには最初の質問の答えが必要です。私たちの選択は、マーケットでの取引を自動化する能力など、色々な要因に影響を受けます。2つ目の質問には、エントリーとエグジットのポイントに加え、取引の方向を示すための取引ルールの精密化が伴います。3つ目の質問は比較的シンプルに見えます:明確なプログラム言語を使い、売買を行う方法は?

この記事ではMQL5言語を使ったアルゴリズム取引によるトレードオペレーションのインプリメントの仕方について考えていきます。


MQL5のアルゴリズム取引機能p

MQL5はオーダーやポジション、トレードのリクエストなどを行う多くのトレード関数を持つ、トレーディングストラテジーのプログラミング言語です。そのため、MQL5によるトレードロボットの作成は開発者にとって少ない労力で行うことができます。

MQL5の機能ではトレードのリクエストを行いOrderSend()あるいはOrderSendAsync() 関数を使いサーバーに送信したり、その処理の結果を受信したり、トレード履歴を参照したり、通貨ペアの取引条件(スワップポイント) を確認したり、トレードイベントやその他の必要なデータを処理したりできます。

また、MQL5はカスタムテクニカルインディケーターをプログラミングしたり、すでにインプリメントされているものを適用したり、チャートオブジェクトに描画したり、カスタムインターフェースを開発したりできます。インプリメンテーションのサンプルはたくさんの記事で見ることができます。


トレードオペレーション -非常に簡単です!

トレードロボットには、いくつかの基本的なトレードオペレーションが必要です:

  1. 最新の価格での売買、
  2. ある条件に応じた売買の指値注文を出す、
  3. 指値注文の変更/削除、
  4. ポジションを減らしたり反対にするためのクローズ/追加オーダー。

これらすべてのオペレーションはOrderSend()関数を使って行われます。OrderSendAsync()という非同期のバージョンもあります。さまざまなトレードオペレーションは、トレードリクエストのディスクリプションを含むMqlTradeRequestストラクチャによって記述されます。そのため、トレードオペレーションを扱う場合に注意すべきなのはMqlTradeRequest ストラクチャを正しく埋め、リクエストの実行を処理することだけです。

トレードシステムに応じて、現在のマーケットプライスからある距離に指値注文を出したり、現在の価格で売買注文を出したりできます。

これらの標準タイプのオーダーはENUM_ORDER_TYPE一覧に対応しています。

指値注文の変更または削除を行わなければいけないかもしれません。それもOrderSend()/OrderSendAsync()関数を使うことでできます。同じトレードオペレーションを使うため、すでに持っているポジションの変更も簡単にできます。

トレードオペレーションが 複雑で難しいと思っているとしたら、その考えを改める時です。ここでは、MQL5を使いどうやって簡単で素早く売買コードを書くかだけではなく、トレードアカウントや通貨ペアのプロパティをどう扱うかについても示すつもりです。Tradeクラスがこの助けになるでしょう。


自分のトレードアカウントをCAccountInfoでチェックしてみましょう

トレードロボットの開発の際にまず知っておくべきことは、トレードアカウントがそのそのオペレーションのためにどう使われるかということです。私たちが書いているのはトレーニングコードなので、Expert Advisorが実際のアカウントで実行された場合でのチェックを実装します。

CAccountInfoクラスがアカウントを扱う場合に使われます。AccountInfo.mqhファイルインクルージョンを追加し、アカウントクラスの変数を宣言します:

#include <Trade\AccountInfo.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- object for working with the account
   CAccountInfo account;
//--- receiving the account number, the Expert Advisor is launched at
   long login=account.Login();
   Print("Login=",login);
//--- clarifying account type
   ENUM_ACCOUNT_TRADE_MODE account_type=account.TradeMode();
//--- if the account is real, the Expert Advisor is stopped immediately!
   if(account_type==ACCOUNT_TRADE_MODE_REAL)
     {
      MessageBox("Trading on a real account is forbidden, disabling","The Expert Advisor has been launched on a real account!");
      return(-1);
     }
//--- displaying the account type    
   Print("Account type: ",EnumToString(account_type));
//--- clarifying if we can trade on this account
   if(account.TradeAllowed())
      Print("Trading on this account is allowed");
   else
      Print("Trading on this account is forbidden: you may have entered using the Investor password");
//--- clarifying if we can use an Expert Advisor on this account
   if(account.TradeExpert())
      Print("Automated trading on this account is allowed");
   else
      Print("Automated trading using Expert Advisors and scripts on this account is forbidden");
//--- clarifying if the permissible number of orders has been set
   int orders_limit=account.LimitOrders();
   if(orders_limit!=0)Print("Maximum permissible amount of active 指値注文s: ",orders_limit);
//--- displaying company and server names
   Print(account.Company(),": server ",account.Server());
//--- displaying balance and current profit on the account in the end
   Print("Balance=",account.Balance(),"  Profit=",account.Profit(),"   Equity=",account.Equity());
   Print(__FUNCTION__,"  completed"); //---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

上のコードで分かるように、OnInit() 関数内のaccount変数を使うことで多くの有用なデータを受取ることができます。オペレーションを分析する時に、ログを簡単に調べるためにこのコードをExpert Advisorに加えることができます。

自動取引選手権2012でのアカウントで使われたExpert Advisorの結果が下に示されています。


CSymbolInfoによる通貨ペア設定の受信

必要なオペレーションの実行の前には、アカウントのデータだけではなく、取引する予定の通貨ペアのプロパティも知る必要があります。多くのメソッドを含むCSymbolInfo クラスはこれらの目的のためにデザインされています。下のサンプルでは、その一部をお見せします。

#include<Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- object for receiving symbol settings
   CSymbolInfo symbol_info;
//--- set the name for the appropriate symbol
   symbol_info.Name(_Symbol);
//--- receive current rates and display
   symbol_info.RefreshRates();
   Print(symbol_info.Name()," (",symbol_info.Description(),")",
         "  Bid=",symbol_info.Bid(),"   Ask=",symbol_info.Ask());
//--- receive minimum freeze levels for trade operations
   Print("StopsLevel=",symbol_info.StopsLevel()," pips, FreezeLevel=",
         symbol_info.FreezeLevel()," pips");
//--- receive the number of decimal places and point size
   Print("Digits=",symbol_info.Digits(),
         ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits()));
//--- spread info
   Print("SpreadFloat=",symbol_info.SpreadFloat(),", Spread(current)=",
         symbol_info.Spread()," pips");
//--- request order execution type for limitations
   Print("Limitations for trade operations: ",EnumToString(symbol_info.TradeMode()),
         " (",symbol_info.TradeModeDescription(),")");
//--- clarifying trades execution mode
   Print("Trades execution mode: ",EnumToString(symbol_info.TradeExecution()),
         " (",symbol_info.TradeExecutionDescription(),")");
//--- clarifying contracts price calculation method
   Print("Contract price calculation: ",EnumToString(symbol_info.TradeCalcMode()),
         " (",symbol_info.TradeCalcModeDescription(),")");
//--- sizes of contracts
   Print("Standard contract size: ",symbol_info.ContractSize(),
         " (",symbol_info.CurrencyBase(),")");
//--- minimum and maximum volumes in trade operations
   Print("Volume info: LotsMin=",symbol_info.LotsMin(),"  LotsMax=",symbol_info.LotsMax(),
         "  LotsStep=",symbol_info.LotsStep());
//--- 
   Print(__FUNCTION__,"  completed");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

自動取引選手権2012でのEURUSDのプロパティが下に示されています。これで、トレードオペレーションを実行する準備が整いました。


CTrade - トレードオペレーションのための便利なクラス

MQL5でのトレードは2つの関数で行われます - OrderSend() とOrderSendAsync()です。これは実は、1つの関数の2つのインプリメンテーションなのです。In fact, these are two implementations of one function. OrderSend()はトレードリクエストを送信し、その実行結果を待ちますが、非同期のOrderSendAsync() はトレードサーバーの応答を待たずに、リクエストをアプリケーションに送信しそのオペレーションを許可するだけです。このように、MQL5ではすべてのトレードオペレーションを行うのに1つの関数しか使わないので本当に簡単です。

では、何が難しいのでしょうか?両方の関数は10以上のフィールドを最初のパラメータとして持つMqlTradeRequestストラクチャを受け取ります。すべてのフィールドが必要なわけではありません。トレードオペレーションのタイプにより必要なフィールドのセットが決まります。埋められるべき不正な値や空のフィールドはエラーとなり、リクエストはサーバーに送られません。これらのフィールドのうちの5つは既定義一覧からの正しい値を必要とします。

この多くのフィールドは1つのオーダーに含まれる大量のプロパティを記述するために必要です。オーダーは実行ポリシー、有効期限やその他のパラメータによって変わります。しかし、それらをすべて細かく理解する必要はありません。既製のCTradeクラスを使いましょう。トレードロボットでクラスがどう使われるかを示しています:

#include<Trade\Trade.mqh>
//--- object for performing trade operations
CTrade  trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- set MagicNumber for your orders identification
   int MagicNumber=123456;
   trade.SetExpertMagicNumber(MagicNumber);
//--- set available slippage in points when buying/selling
   int deviation=10;
   trade.SetDeviationInPoints(deviation);
//--- order filling mode, the mode allowed by the server should be used
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- logging mode: it would be better not to declare this method at all, the class will set the best mode on its own
   trade.LogLevel(1); 
//--- what function is to be used for trading: true - OrderSendAsync(), false - OrderSend()
   trade.SetAsyncMode(true);
//---
   return(0);
  }

まずはCTradeがトレードオペレーションでどう動くのかみてみましょう。

最新の価格での売買

トレーディングストラテジーは最新の価格ですぐに売買を行うということがあります。この場合CTradeは必要な取引ボリュームだけを尋ねます。すべてのパラメータ(注文価格通貨ペア名、ストップロス、テイクプロフィット、オーダーコメント)はオプションです。

//--- 1. example of buying at the current symbol
   if(!trade.Buy(0.1))
     {
      //--- failure message
      Print("Buy() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

デフォルトでは、通貨ペア名が指定されていない場合、CTradeは実行されているチャート上の通貨ペア名を使用します。これは単純なストラテジーには便利な方法です。多通貨に及ぶストラテジーでは、どの通貨ペアに対してトレードオペレーションを実行するのかを、いつも必ず指定しなければなりません。

//--- 2. example of buying at the specified symbol
   if(!trade.Buy(0.1,"GBPUSD"))
     {
      //--- failure message
      Print("Buy() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Buy() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

すべてのオーダーパラメータを指定しても構いません:ストップロス/テイクプロフィット、約定価格、コメント。

//--- 3. example of buying at the specified symbol with specified SL and TP
   double volume=0.1;
   string symbol="GBPUSD";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                 // unnormalized open price
   price=NormalizeDouble(price,digits);                      // normalizing open price
   int SL_pips=300;                                         // Stop Loss in points
   int TP_pips=500;                                         // Take Profit in points
   double SL=price-SL_pips*point;                           // unnormalized SL value
   SL=NormalizeDouble(SL,digits);                            // normalizing Stop Loss
   double TP=price+TP_pips*point;                           // unnormalized TP value
   TP=NormalizeDouble(TP,digits);                            // normalizing Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Limit %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- everything is ready, sending a Buy Limit 指値注文 to the server
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,<s50>ORDER_TIME_GTC,expiration,comment))
     {
      //--- failure message
      Print("BuyLimit() method failed. turn code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Buy() method executed successfully. turn code=",trade.ResultRetcode(),
            ".

これまでに述べたように、マジックナンバーと許容スリッページはCtradeのコピーの初期化時にセットされます。ですので、それらは必要ありません。しかし、必要であればオペレーションごとにセットできます。

指値注文を出す

指値注文を出すには、BuyLimit()SellLimit()クラスメソッドを使います。省略化したもの(指値価格とボリュームだけが指定されている時)がほとんどの場合、適しています。買いの指値価格は現在の価格より低くなければならず、売りの指値価格は高くなければなりません。これらのオーダーはマーケットに最良の価格でエントリーするために使われ、サポートラインからの反発を期待するストラテジーにもっとも適しています。Expert Advisorが実行されている通貨ペアが使用されます:

//--- 1. example of placing a Buy Limit 指値注文
   string symbol="GBPUSD";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                   // unnormalized open price
   price=NormalizeDouble(price,digits);                       // normalizing open price
//--- everything is ready, sending a Buy Limit 指値注文 to the server
   if(!trade.BuyLimit(0.1,price))
     {
      //--- failure message
      Print("BuyLimit() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyLimit() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

全てのパラメーターを指定するもっと詳細なバージョンも使うことができます:SL/TP レベル、有効期限、シンボル名とオーダーへのコメント。

//--- 2. example of placing a Buy Limit 指値注文 with all parameters
   double volume=0.1;
   string symbol="GBPUSD";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                 // unnormalized open price
   price=NormalizeDouble(price,digits);                      // normalizing open price
   int SL_pips=300;                                         // Stop Loss in points
   int TP_pips=500;                                         // Take Profit in points
   double SL=price-SL_pips*point;                           // unnormalized SL value
   SL=NormalizeDouble(SL,digits);                            // normalizing Stop Loss
   double TP=price+TP_pips*point;                           // unnormalized TP value
   TP=NormalizeDouble(TP,digits);                            // normalizing Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Limit %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- everything is ready, sending a Buy Limit 指値注文 to the server
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,ORDER_TIME_GTC,expiration,comment))
     {
      //--- failure message
      Print("BuyLimit() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyLimit() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }turn code=",trade.ResultRetcode(),
            ".Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

2つ目のバージョンでのタスクはSLとTPのレベルを正しく示すことです。テイクプロフィットのレベルは約定価格よりも高く、ストップロスは低くなければならないことに注意してください・売りの指値注文は逆の関係になります。Expert Advisorを過去のデータでテストすれば、エラーは簡単に分かります。その場合、CTradeクラスは自動的にメッセージを表示します(LogLevel関数を呼び出していない限り)。

逆指値注文を出す

同じようなBuyStop()SellStop()を使い逆指値注文を送信します。買いの逆指値価格は現在の価格より高くなければならず、売りの逆指値価格は低くなければなりません。逆指値注文はロスカットに加え、レジスタンスレベルのブレイクアウト時にマーケットにエントリーするストラテジーで使用されます。シンプルなバージョン:

//--- 1. example of placing a Buy Stop pending order
   string symbol="USDJPY";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                    // unnormalized open price
   price=NormalizeDouble(price,digits);                        // normalizing open price
//--- everything is ready, sending a Buy Stop pending order to the server 
   if(!trade.BuyStop(0.1,price))
     {
      //--- failure message
      Print("BuyStop() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyStop() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

買い逆指値注文のパラメータの最大値を指定しなければいけないより詳細なバージョン:

//--- 2. example of placing a Buy Stop pending order with all parameters
   double volume=0.1;
   string symbol="USDJPY";    // specify the symbol, at which the order is placed
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // number of decimal places
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // point
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // current buy price
   double price=1000*point;                                   // unnormalized open price
   price=NormalizeDouble(price,digits);                       // normalizing open price
   int SL_pips=300;                                          // Stop Loss in points
   int TP_pips=500;                                          // Take Profit in points
   double SL=price-SL_pips*point;                            // unnormalized SL value
   SL=NormalizeDouble(SL,digits);                             // normalizing Stop Loss
   double TP=price+TP_pips*point;                            // unnormalized TP value
   TP=NormalizeDouble(TP,digits);                             // normalizing Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Stop %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- everything is ready, sending a Buy Stop pending order to the server 
   if(!trade.BuyStop(volume,price,symbol,SL,TP,ORDER_TIME_GTC,expiration,comment))
     {
      //--- failure message
      Print("BuyStop() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("BuyStop() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }turn code=",trade.ResultRetcode(),
            ".Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

適切なCTradeクラスメソッドが売り逆指値注文を送信するために使用されます。ここでは、価格の指定は非常な重要性を持ちます。

ポジションの扱い

Buy()やSell()の代わりにポジションを開くためのメソッドを使用することはできますが、この場合、より多くの詳細を指定しなければいけません:

//--- number of decimal places
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- point value
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- receiving a buy price
   double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
//--- calculate and normalize SL and TP levels
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
//--- filling comments
   string comment="Buy "+_Symbol+" 0.1 at "+DoubleToString(price,digits);
//--- everything is ready, trying to open a buy position
   if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,0.1,price,SL,TP,comment))
     {
      //--- failure message
      Print("PositionOpen() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("PositionOpen() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

通貨ペア名だけを指定すれば、残りはCTradeクラスがやってくれます。

//--- closing a position at the current symbol
   if(!trade.PositionClose(_Symbol))
     {
      //--- failure message
      Print("PositionClose() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("PositionClose() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

逆指値とテイクプロフィットのレベルだけが、開いたポジションに対する変更として利用可能です。これはPositionModify()メソッドを使って行われます

//--- number of decimal places
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- point value
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- receiving the current Bid price
   double price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- calculate and normalize SL and TP levels
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
//--- everything is ready, trying to modify the buy position
   if(!trade.PositionModify(_Symbol,SL,TP))
     {
      //--- failure message
      Print("Метод PositionModify() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("PositionModify() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

オーダーの変更と削除

OrderModify()メソッドはCTradeクラス内でインプリメントされ、未決注文のパラメータを変更するために使われます。すべての必要なパラメータはこのメソッドに与えられなければなりません。

//--- this is a sample order ticket, it should be received
   ulong ticket=1234556;
//--- this is a sample symbol, it should be received
   string symbol="EURUSD";
//--- number of decimal places
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- point value
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- receiving a buy price
   double price=SymbolInfoDouble(symbol,SYMBOL_ASK);
//--- calculate and normalize SL and TP levels
//--- they should be calculated based on the order type
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
   //--- setting one day as a lifetime
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);   
//--- everything is ready, trying to modify the order 
   if(!trade.OrderModify(ticket,price,SL,TP,ORDER_TIME_GTC,expiration))
     {
      //--- failure message
      Print("OrderModify() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("OrderModify() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

変更するオーダーのチケットを受け取るはずです。そのタイプに応じて、現在のストップロスとテイクプロフィットのレベルが指定されます。また、新しいオープンプライスは現在の価格に関係して正しくなければなりません。

削除するオーダーのチケットが分かっていなければなりません:

//--- this is a sample order ticket, it should be received
   ulong ticket=1234556;
//--- everyrging is ready, trying to modify a buy position
   if(!trade.OrderDelete(ticket))
     {
      //--- failure message
      Print("OrderDelete() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("OrderDelete() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

このクラスには多目的クラスOrderOpen()メソッドが含まれ、あらゆるタイプの未決の注文をセットすることができます。特化したBuyLimitBuyStopSellLimit SellStopメソッドとは異なり、多くの重要なパラメータを指定する必要があります。もしかしたら、より使いやすいと感じるかもしれません。


他にも解決すべきものがあるでしょうか?

3つの質問のうち、2つの質問には答えました。ストラテジーのためのシンボルを選択し、売買オペレーションやトレードロボットにおける指値注文についてのコードについて説明しました。しかし、トレードクラスセクションにはMQL5の開発者にとってより有用なものがあります:

これらのクラスにより、ストラテジーのテクニカルな問題を最小化し、よりトレードの側に集中できるようになります。また、 CTradeクラスはトレードのリクエストを調べるために使われます。練習を重ねれば、トレードのリクエストと実行結果を処理する必要なロジックを備えた自分独自のクラスを作ることができるようになるはずです。

最後の質問は、トレードシグナルをどう受け取り、MQL5のコードにするかというものでした。アルゴリズムトレーディングの新しい参加者の多くは、シンプルで標準的なトレーディングシステムの勉強から始めます。例えば移動平均の交差に基づくものです。そのためにはまず、テクニカルインディケーターの作成と、そのトレードロボットでの使用について学ばなければいけません。

インディケーターの記事とMT4のサンプル->インディケーターセクションを読むことをおすすめします。もっとも簡単なものから始め、もっとも複雑なものまで進んでいくことができるでしょう。インディケーターの使い方を手早く知りたい場合は、 MQL5初心者のための:Expert Advisorのテクニカルインディケーターのガイドを見てください。


複雑なものをシンプルに

どのような仕事でも、最初の問題は少しづつ、取り組むべき最もシンプルな問題に変わっていきます。ここで紹介されたトレードロボット開発の方法は、初心者のためのものですが、経験者の中にも新しいものや便利なものを発見できるかもしれません。

MQL5言語によってアルゴリズム取引の機会を得るのみならず、最もシンプルかつ、素早い方法でインプリメントすることができるようになります。標準ライブラリのトレードクラス を使い時間を節約して、もっと重要なもののために時間を使いましょう。例えば、すべてのトレーダーの永遠の疑問-トレンドとは何で、どのようにそれをリアルタイムで見つければよいのか。

すぐに、MQL5でのトレードロボットの開発は外国語を学ぶことや、トレンドを発見することに比べれば、遥かに簡単だということに気が付くでしょう!