
MQL5でのトレードオペレーション - 簡単です
ほとんどすべてのトレーダーは利益をあげるためにマーケットに参加しますが、中にはそのプロセス自体を楽しむトレーダーもいます。しかし、手動のトレードだけが、エキサイティングな体験をさせてくれるわけではありません。自動トレードシステムの開発も非常に興味深いものです。トレードロボットの作成は面白いミステリー小説を読むのと同じくらい面白いものです。
トレーディングアルゴリズムを開発するには、もっとも重要なものを含む多くのテクニカルな問題に対処しなければなりません:
- 何をトレードするか?
- いつトレードするか?
- どうトレードするか?
最も適した通貨ペアを選ぶためにためには最初の質問の答えが必要です。私たちの選択は、マーケットでの取引を自動化する能力など、色々な要因に影響を受けます。2つ目の質問には、エントリーとエグジットのポイントに加え、取引の方向を示すための取引ルールの精密化が伴います。3つ目の質問は比較的シンプルに見えます:明確なプログラム言語を使い、売買を行う方法は?
この記事ではMQL5言語を使ったアルゴリズム取引によるトレードオペレーションのインプリメントの仕方について考えていきます。
MQL5のアルゴリズム取引機能p
MQL5はオーダーやポジション、トレードのリクエストなどを行う多くのトレード関数を持つ、トレーディングストラテジーのプログラミング言語です。そのため、MQL5によるトレードロボットの作成は開発者にとって少ない労力で行うことができます。
MQL5の機能ではトレードのリクエストを行いOrderSend()あるいはOrderSendAsync() 関数を使いサーバーに送信したり、その処理の結果を受信したり、トレード履歴を参照したり、通貨ペアの取引条件(スワップポイント) を確認したり、トレードイベントやその他の必要なデータを処理したりできます。
また、MQL5はカスタムテクニカルインディケーターをプログラミングしたり、すでにインプリメントされているものを適用したり、チャートオブジェクトに描画したり、カスタムインターフェースを開発したりできます。インプリメンテーションのサンプルはたくさんの記事で見ることができます。
トレードオペレーション -非常に簡単です!
トレードロボットには、いくつかの基本的なトレードオペレーションが必要です:
- 最新の価格での売買、
- ある条件に応じた売買の指値注文を出す、
- 指値注文の変更/削除、
- ポジションを減らしたり反対にするためのクローズ/追加オーダー。
これらすべてのオペレーションは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()メソッドが含まれ、あらゆるタイプの未決の注文をセットすることができます。特化したBuyLimit、 BuyStop、 SellLimit や SellStopメソッドとは異なり、多くの重要なパラメータを指定する必要があります。もしかしたら、より使いやすいと感じるかもしれません。
他にも解決すべきものがあるでしょうか?
3つの質問のうち、2つの質問には答えました。ストラテジーのためのシンボルを選択し、売買オペレーションやトレードロボットにおける指値注文についてのコードについて説明しました。しかし、トレードクラスセクションにはMQL5の開発者にとってより有用なものがあります:
- COrderInfo - オーダーを扱うためのもの;
- CHistoryOrderInfo -過去のデータで実行されたオーダーを扱うためのもの;
- CPositionInfo - ポジションを扱うためのもの;
- CDealInfo - 取引に関するもの;
- CTerminalInfo - ターミナルのデータを受け取るもの(これはとても興味深いです)。
これらのクラスにより、ストラテジーのテクニカルな問題を最小化し、よりトレードの側に集中できるようになります。また、 CTradeクラスはトレードのリクエストを調べるために使われます。練習を重ねれば、トレードのリクエストと実行結果を処理する必要なロジックを備えた自分独自のクラスを作ることができるようになるはずです。
最後の質問は、トレードシグナルをどう受け取り、MQL5のコードにするかというものでした。アルゴリズムトレーディングの新しい参加者の多くは、シンプルで標準的なトレーディングシステムの勉強から始めます。例えば移動平均の交差に基づくものです。そのためにはまず、テクニカルインディケーターの作成と、そのトレードロボットでの使用について学ばなければいけません。
インディケーターの記事とMT4のサンプル->インディケーターセクションを読むことをおすすめします。もっとも簡単なものから始め、もっとも複雑なものまで進んでいくことができるでしょう。インディケーターの使い方を手早く知りたい場合は、 MQL5初心者のための:Expert Advisorのテクニカルインディケーターのガイドを見てください。
複雑なものをシンプルに
どのような仕事でも、最初の問題は少しづつ、取り組むべき最もシンプルな問題に変わっていきます。ここで紹介されたトレードロボット開発の方法は、初心者のためのものですが、経験者の中にも新しいものや便利なものを発見できるかもしれません。
MQL5言語によってアルゴリズム取引の機会を得るのみならず、最もシンプルかつ、素早い方法でインプリメントすることができるようになります。標準ライブラリのトレードクラス を使い時間を節約して、もっと重要なもののために時間を使いましょう。例えば、すべてのトレーダーの永遠の疑問-トレンドとは何で、どのようにそれをリアルタイムで見つければよいのか。
すぐに、MQL5でのトレードロボットの開発は外国語を学ぶことや、トレンドを発見することに比べれば、遥かに簡単だということに気が付くでしょう!
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/481





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
皆さんこんにちは!
私はプログラミング言語MQL5の 勉強を続けています。自分にとって有益な情報を求めて、ほとんど全てのサイトを検索しました。サイトにある情報のほとんどは、すでにプログラミングの基本的な理解を持っている人向けです。
そしてこちら!多くのことを理解し、自分のEAを改良するのに役立った! 著者がこのシリーズを書き続けず、2012年だけに限定したのは残念だ。しかし、同じように、私はこの人に大きな敬意を 表し、すべての初心者を代表して同じように大きな ありがとうを言います!
敬意を込めて、ウラジミール。
こんにちは、とても参考になる投稿をありがとうございます。私はMT5初心者で、EAの作成について勉強中なので、サンプルコードをコピーしてCtrade.Buyを実行しましたが、バックテストに失敗しました。詳細は以下の通りです:
1) 口座:基本通貨をNZDとしたライブ口座です。
2) バックテスト用のMetaEditor設定:
3) コードhttps://www.mql5.com/ja/articles/481 からコピー:
//+------------------------------------------------------------------+
//| demo.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#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 execution mode
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);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
BuySample1();
}
//--- Buy sample
//+------------------------------------------------------------------+
//| Buying a specified volume at the current symbol |
//+------------------------------------------------------------------+
void BuySample1()
{
//--- 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(),")");
}
//---
}
4) エラーログ (EUR/USD でのみテストしていることに注意してください):
GJ 0 19:36:44.410 127.0.0.1 ログイン (ビルド 1730)
HH 0 19:36:44.420 ネットワーク 38520 バイトの口座情報をロード
JO 0 19:36:44.420 ネットワーク 1482 バイトのテスターパラメータをロード
QE 0 19:36:44.420 ネットワーク 188 バイトの入力パラメータをロード
FR 0 19:36:44.421 ネットワーク 443 バイトの記号リストをロード
IF 0 19:36:44.421 テスターエキスパートファイルが追加された: Expertsdemo.ex5.46684バイトがロードされた
QH 0 19:36:44.433 テスター初期預金10000.00 NZD、レバレッジ1:100
JN 0 19:36:44.437 テスターの初期化に成功
ES 0 19:36:44.437 ネットワーク 46 Kb の初期化データを受信
PP 0 19:36:44.437 テスター Intel Core i7-4510U @ 2.00GHz、8103 MB
RJ 0 19:36:44.799 シンボル EURUSD: 同期されるシンボル
HR 0 19:36:44.800 シンボル EURUSD: シンボルが同期、3624 バイトのシンボル情報を受信
NJ 0 19:36:44.800 ヒストリー EURUSD: ヒストリーの同期開始
GO 0 19:36:44.856 History EURUSD: 27バイトのヒストリデータをロードして0:00:00.000に同期します。
RQ 0 19:36:44.856 History EURUSD: 2012.01.01から2017.11.15までの履歴が同期されました。
EF 0 19:36:44.993 History EURUSD,Daily: 履歴キャッシュが1010本分割り当てられ、2014.01.01 00:00 から 2014.12.31 00:00 までの312本が含まれています。
ND 0 19:36:44.993 History EURUSD,Daily: 履歴は2014.01.01 00:00から開始。
OL 0 19:36:44.996 Tester EURUSD,Daily (HalifaxPlus-Live): 毎ティック生成
GN 0 19:36:44.996 Tester EURUSD,Daily: Expertsdemo.ex5の2015.01.01 00:00から2017.11.15 00:00までのテスト開始
CK 0 19:36:56.288 Symbols NZDUSD: 同期されるシンボル
IS 0 19:36:56.288 Symbols NZDUSD: シンボルが同期、3624バイトのシンボル情報を受信
JL 0 19:36:56.288 ヒストリー NZDUSD: ヒストリーの同期開始
HJ 0 19:36:56.575 History NZDUSD: 14 Kbのヒストリデータをロードして0:00:00.078に同期します。
LS 0 19:36:56.575 History NZDUSD: 2013.01.01から2017.11.15までの履歴が同期されました。
CO 0 19:36:56.579 Symbols EURNZD: 同期されるシンボル
OJ 0 19:36:56.580 シンボル EURNZD: シンボルの同期が完了、3624バイトのシンボル情報を受信
DL 0 19:36:56.580 ヒストリー EURNZD: ヒストリーの同期開始
MK 0 19:36:56.656 ヒストリー EURNZD: 27バイトのヒストリーデータをロードし、0:00:00.000に同期します。
OD 0 19:36:56.656 History EURNZD: 2013.01.01から2017.11.15までの履歴が同期されました。
IN 0 19:36:56.665 トレード 2015.01.02 03:00:00 マーケット買い 0.10 EURUSD (1.20538 / 1.20549 / 1.20538)
PE 0 19:36:56.665トレード2015.01.02 03:00:00取引#2買い0.10 EURUSD at 1.20549完了(注文#2に基づく)
FH 0 19:36:56.666 トレード 2015.01.02 03:00:00 ディール実行 [#2 buy 0.10 EURUSD at 1.20549] (注文 #2 に基づく)
OG 0 19:36:56.666 Trade 2015.01.02 03:00:00 order performed buy 0.10 at 1.20549 [#2 buy 0.10 EURUSD at 1.20549].
FO 0 19:36:56.670 demo (EURUSD,D1) 2015.01.02 03:00:00 Buy()メソッドが正常に実行されました。リターンコード=10009 (1.20549で実行)
NM 2 19:37:15.823 History NZDUSD 2016.09.21 23:01:00: corrupted history detected (s:-73370, o:73433, h:+48, l:-123, c:-117 -- tv:63, rv:11250111).
JF 2 19:37:15.823 History NZDUSD 2016.09.21, バッドコンテナが見つかりました。
LQ 2 19:37:16.106 テスター履歴 未定義関数でエラー9
OH 2 19:37:16.106 Tester stopped on 0% of testing interval with error '20 NZDUSD'.
何が間違っているのか、どうすれば解決できるのか教えてください。
こんにちは、とても参考になる投稿をありがとうございます。私はMT5初心者で、EAの作成について勉強中なので、サンプルコードをコピーしてCtrade.Buyを実行しましたが、バックテストに失敗しました。詳細は以下の通りです:
1) 口座:基本通貨をNZDとしたライブ口座です。
2) バックテスト用のMetaEditor設定:
3) コードhttps://www.mql5.com/ja/articles/481 からコピー:
//+------------------------------------------------------------------+
//| demo.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#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 execution mode
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);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
BuySample1();
}
//--- Buy sample
//+------------------------------------------------------------------+
//| Buying a specified volume at the current symbol |
//+------------------------------------------------------------------+
void BuySample1()
{
//--- 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(),")");
}
//---
}
4) エラーログ (EUR/USD でのみテストしていることに注意してください):
GJ 0 19:36:44.410 127.0.0.1 ログイン (ビルド 1730)
HH 0 19:36:44.420 ネットワーク 38520 バイトの口座情報をロード
JO 0 19:36:44.420 ネットワーク 1482 バイトのテスターパラメータをロード
QE 0 19:36:44.420 ネットワーク 188 バイトの入力パラメータをロード
FR 0 19:36:44.421 ネットワーク 443 バイトの記号リストをロード
IF 0 19:36:44.421 テスターエキスパートファイルが追加された: Expertsdemo.ex5.46684バイトがロードされた
QH 0 19:36:44.433 テスター初期預金10000.00 NZD、レバレッジ1:100
JN 0 19:36:44.437 テスターの初期化に成功
ES 0 19:36:44.437 ネットワーク 46 Kb の初期化データを受信
PP 0 19:36:44.437 テスター Intel Core i7-4510U @ 2.00GHz、8103 MB
RJ 0 19:36:44.799 シンボル EURUSD: 同期されるシンボル
HR 0 19:36:44.800 シンボル EURUSD: シンボルが同期、3624 バイトのシンボル情報を受信
NJ 0 19:36:44.800 ヒストリー EURUSD: ヒストリーの同期開始
GO 0 19:36:44.856 History EURUSD: 27バイトのヒストリデータをロードして0:00:00.000に同期します。
RQ 0 19:36:44.856 History EURUSD: 2012.01.01から2017.11.15までの履歴が同期されました。
EF 0 19:36:44.993 History EURUSD,Daily: 履歴キャッシュが1010本分割り当てられ、2014.01.01 00:00 から 2014.12.31 00:00 までの312本が含まれています。
ND 0 19:36:44.993 History EURUSD,Daily: 履歴は2014.01.01 00:00から開始。
OL 0 19:36:44.996 Tester EURUSD,Daily (HalifaxPlus-Live): 毎ティック生成
GN 0 19:36:44.996 Tester EURUSD,Daily: Expertsdemo.ex5の2015.01.01 00:00から2017.11.15 00:00までのテスト開始
CK 0 19:36:56.288 Symbols NZDUSD: 同期されるシンボル
IS 0 19:36:56.288 Symbols NZDUSD: シンボルが同期、3624バイトのシンボル情報を受信
JL 0 19:36:56.288 ヒストリー NZDUSD: ヒストリーの同期開始
HJ 0 19:36:56.575 History NZDUSD: 14 Kbのヒストリデータをロードして0:00:00.078に同期します。
LS 0 19:36:56.575 History NZDUSD: 2013.01.01から2017.11.15までの履歴が同期されました。
CO 0 19:36:56.579 Symbols EURNZD: 同期されるシンボル
OJ 0 19:36:56.580 シンボル EURNZD: シンボルの同期が完了、3624バイトのシンボル情報を受信
DL 0 19:36:56.580 ヒストリー EURNZD: ヒストリーの同期開始
MK 0 19:36:56.656 ヒストリー EURNZD: 27バイトのヒストリーデータをロードし、0:00:00.000に同期します。
OD 0 19:36:56.656 History EURNZD: 2013.01.01から2017.11.15までの履歴が同期されました。
IN 0 19:36:56.665 トレード 2015.01.02 03:00:00 マーケット買い 0.10 EURUSD (1.20538 / 1.20549 / 1.20538)
PE 0 19:36:56.665トレード2015.01.02 03:00:00取引#2買い0.10 EURUSD at 1.20549完了(注文#2に基づく)
FH 0 19:36:56.666 トレード 2015.01.02 03:00:00 ディール実行 [#2 buy 0.10 EURUSD at 1.20549] (注文 #2 に基づく)
OG 0 19:36:56.666 Trade 2015.01.02 03:00:00 order performed buy 0.10 at 1.20549 [#2 buy 0.10 EURUSD at 1.20549].
FO 0 19:36:56.670 demo (EURUSD,D1) 2015.01.02 03:00:00 Buy()メソッドが正常に実行されました。リターンコード=10009 (1.20549で実行)
NM 2 19:37:15.823 History NZDUSD 2016.09.21 23:01:00: corrupted history detected (s:-73370, o:73433, h:+48, l:-123, c:-117 -- tv:63, rv:11250111).
JF 2 19:37:15.823 History NZDUSD 2016.09.21, バッドコンテナが見つかりました。
LQ 2 19:37:16.106 テスター履歴 未定義関数でエラー9
OH 2 19:37:16.106 Tester stopped on 0% of testing interval with error '20 NZDUSD'.
何が間違っているのか、どうすれば解決できるのか教えてください。
指値注文と逆指値注文をあちこちで開いたときの記事で
と書いている人は、記事のコードを挿入しているの だろうか?