English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
Expert AdvisorプログラミングにおけるMQL5標準トレードクラスライブラリの使用

Expert AdvisorプログラミングにおけるMQL5標準トレードクラスライブラリの使用

MetaTrader 5トレーディングシステム | 6 10月 2015, 16:03
3 351 0
Samuel Olowoyo
Samuel Olowoyo

はじめに

新しいMQL5プログラムには、トレーダーや開発者がMQL5 Expert Advisors、インディケータ、スクリプトの作成をできるだけしやすくなるような多くの内蔵標準クラスライブラリ が備えられています。

こういったクラスライブラリはMetaTrader 5クライアント端末フォルダのMQL5フォルダ内にある \Include\ フォルダにあります。クラスライブラリは様々に分類されます。 それらは、配列ChartObjectsチャートファイルインディケータストリングトレードクラスです。

本稿では、Expert Advisorを書くための内蔵トレードクラスの使用方法について述べます。The Expert Advisorは要求される条件が満たされるとき、オープンしているポジションをクローズしたり変更したりする戦略を基にしています。

すでにクラスのなんたるか、それがどのように使われるかをご存じであればMQL5言語が提供する機会のもうひとつの世界に歓迎します。

また、MQL5は初めてだとおっしゃる方には、まず初めに以下の2つの記事の一読をお薦めします。『 初心者のためのMQL5でプログラミングをする段階的ガイド』、『MQL5のオブジェクト指向プログラミング手法を使ったExpert Advisorのプログラミング 』、または 新しいMQL5言語に関して入門となる記事はなんでも読んでみてはいかがでしょうか。必要な知識を提供してくれる読み物 はたくさんあります。


1. トレードクラス

トレードクラスフォルダは異なるクラスで構成されています。それは個人使用のためにEAを開発するトレーダーの方や、 ご自分のExpert Advisors (EA)を開発するのに一から始める必要がなく、開発者を楽にしてくれます。

クラス使用の際、クラスの内部動作(それは開発者がしろということをどうやって行うのか)について知る必要があります。問題解決にクラスがどのように使われるかという点に着目するだけです。内蔵クラスライブラリを使うことでそれを使いたい誰もにとって物事が簡単になる理由です。本稿ではExpert Advisorを開発するうえで必要な主要クラスについてみていきます。

クラスといえば、クラスの内部の細かいことで煩わされることはありませんが、クラスが何をすることができるのか、収益性の高いEAを開発するという使命を全うするにはどのように使えばよいかについては詳しくみていきます。ではひとつずつ述べていきます。


1.1 СAccountInfoクラス

CAccountInfoは、ユーザーがクライアント端末において、アカウントプロパティや、現在オープンしている取引アカウント情報にアクセスするのを簡単にします。

もっとよく理解できるよう、このクラスの中で、われわれのEAで使う可能性のある主要なメンバー関数を見ていきます。クラスを使う前に、まずそのクラスのオブジェクトを作成する必要があります。よってCAccountInfoクラスを使うためにこのクラスのオブジェクトを作成します。

そのオブジェクトをmyaccountと呼びます。

//--- The AccountInfo Class Object
CAccountInfo myaccount;

クラスオブジェクトを作成するためには、クラス名に続き付けたいオブジェクト名を使用することを覚えておいてください。

これでmyaccountオブジェクトを使用して CAccountInfo クラスのパブリックメンバー関数にアクセスできます。

メソッド 説明 使用例
myaccount.Login()

この関数は、端末で現在オープンしている取引に対するアカウントナンバーを取得したいときに使用します。

// returns account number, example 7770
long accountno = myaccount.Login()
myaccount.TradeModeDescription() この関数は、端末で現在アクティブなアカウントの取引モード記述を取得したいときに使用します。
// returns Demo trading account, 
// or Real trading account or Contest trading account
string  acc_trading_mode = myaccount.TradeModeDescription();
myaccount.Leverage()

この関数は、端末で現在アクティブなアカウントの取引モード記述を取得したいときに使用します。

// returns leverage given to the active account
long acc_leverage = myaccount.Leverage(); 
myaccount.TradeAllowed()

この関数は、端末で現在アクティブなアカウント上で取引が許可されているか確認したいときに使用します。許可されていなければ、アカウントは取引できません。

if (myaccount.TradeAllowed())
{
    // trade is allowed
}
else
{
  // trade is not allowed
}
myaccount.TradeExpert() この関数は、端末で現在アクティブなアカウントに対しExpert Advisorsが取引を許可されているか確認したいときに使用します。
if (myaccount.TradeExpert())
{
   // Expert Advisor trade is allowed
}
else
{
   // Expert Advisor trade is not allowed
}
myaccount.Balance() この関数は、端末で現在アクティブなアカウントに対してアカウントバランスを提供します。
// returns account balance in the deposit currency
double acс_balance =  myaccount.Balance();
myaccount.Profit()

この関数は、端末でアクティブなアカウントの現在収益情報を取得するのに使用します。

// returns account profit in deposit currency
double acс_profit =  myaccount.Profit();
myaccount.FreeMargin()

この関数は、端末でアクティブなアカウントのフリーマージンを取得するのに使用します。

// returns free margin for active account
double acс_free_margin = myaccount.FreeMargin();
myaccount.Currency()

この関数は、端末でアクティブなアカウントの預金通貨を取得するのに使用します。

string acс_currency = myaccount.Currency();
myaccount.OrderProfitCheck(const string symbol, ENUM_ORDER_TYPE trade_operation, double volume, double price_open, double price_close) この関数は渡されるパラメータに基づき評価された収益を取得します。入力パラメータは、シンボル、トレード処理タイプ、ボリューム、始値/終値です。
double op_profit=myaccount.OrderProfitCheck(_Symbol,ORDER_TYPE_BUY,
1.0,1.2950,1.3235);
Print("The amount of Profit for deal buy EURUSD",
      "at 1.2950 and sell at 1.3235 is: ",op_profit);
myaccount.MarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price) この関数はオーダーをオープンするのに要求されるマージンを取得するのに使われます。この関数は4つ入力パラメータを持っています。シンボル(通貨ペア)、注文タイプ、取引のロット(またはボリューム)、注文価格です。この関数は取引をセットするときたいへん重要なものです。
// depending on the type of position to open - in our case buy
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK); 
double margin_req=myaccount.MarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.FreeMarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price) この関数は注文がセットされるときアクティブなアカウントに残っているフリーマージンの量を取得します。この関数は4つ入力パラメータを持っています。シンボル(通貨ペア)、注文タイプ、取引のロット(またはボリューム)、注文価格です。
double acс_fm=myaccount.FreeMarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.MaxLotCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double price)

この関数は端末でアクティブなアカウントについて注文を出せる最大ロットを取得するのに使われます。この関数は3つ入力パラメータを持っています。シンボル、注文タイプ、注文のオープン価格です。<

double max_lot=myaccount.MaxLotCheck(_Symbol,ORDER_TYPE_BUY,price);


1.2СSymbolInfoクラス

CSymbolInfo クラスはユーザーがすぼやく使用中シンボルのすべてのプロパティにアクセスするようにします。

このクラスを使うには、クラスのオブジェクトを作成する必要があります。この場合をmysymbolと呼びます。

// the CSymbolInfo Class object
CSymbolInfo mysymbol;

われわれのExpert Advisorを書くプロセスで使われる可能性のあるこのクラスの関数をみていきます。

メソッド 説明 使用例
mysymbol.Name(string name)

この関数はクラスオブジェクトにシンボルを設定するのに使われます。入力パラメータとしてシンボル名を取ります。

// set the symbol name for our CSymbolInfo class Object
mysymbol.Name(_Symbol);
mysymbol.Refresh() この関数はすべてのシンボルデータをリフレッシュするのに使われます。また、クラスに新規シンボル名を設定するとき自動的に呼ばれます。
mysymbol.Refresh();
mysmbol.RefreshRates() この関数は直近のクオートデータを確認するのに使われます。うまくいくとtrue、失敗するとfalseを返します。これは有用でなくてはならない関数です。
//--- Get the last price quote using the CSymbolInfo 
// class object function
   if (!mysymbol.RefreshRates())
   {
      // error getting latest price quotes 
   }
mysymbol.IsSynchronized()

この関数は端末上で設定された現在データがサーバー上のデータと同期しているか確認するのに使われます。データが同期していればtrueを、していなければffalseを返します。

// check if symbol data are synchronized with server
  if (!mysymbol.IsSynchronized())
   {
     // error! Symbol data aren't synchronized with server
   }
mysymbol.VolumeHigh()

この関数は設定されたシンボルについてその日の最大ボリュームを取得するのに使われます。

long max_vol = mysymbol.VolumeHigh();
mysymbol.VolumeLow()

この関数は設定されたシンボルについてその日の最小ボリュームを取得するのに使われます。

long min_vol = mysymbol.VolumeLow();
mysymbol.Time()

この関数は設定されたシンボルについて最後の価格クオート時刻を取得するのに使われます。

datetime qtime = mysymbol.Time();
mysymbol.Spread() この関数は設定されたシンボルについて現在のスプレッド値(ポイントで)を取得するのに使われます。
int spread = mysymbol.Spread();
mysymbol.StopsLevel() この関数は設定されたシンボルについてストップロスがセット可能な現クローズ価格に対する現在の最低レベルを取得するのに使われます。「Trailing停止」または注文/ポジションの変更をすることを考えているなら便利な関数です。
int stp_level = mysymbol.StopsLevel();
mysymbol.FreezeLevel() この関数は設定されたシンボルについて凍結取引処理の距離(ポイントで)を取得するのに使われます。
int frz_level = mysymbol.FreezeLevel();
mysymbol.Bid()

この関数は設定されたシンボルについて現在のBID価格を取得するのに使われます。

double bid =  mysymbol.Bid();
mysymbol.BidHigh() この関数は当日の最大/最高BID価格を取得するのに使われます。
double max_bid = mysymbol.BidHigh();
mysymbol.BidLow() この関数は設定されたシンボル当日の最小/最低BID価格を取得するのに使われます。
double min_bid = mysymbol.BidLow();
msymbol.Ask() この関数は設定されたシンボルについて現ASK価格を取得するのに使われます。
double ask = mysymbol.Ask();
mysymbol.AskHigh() この関数は設定されたシンボルについて当日の最大/最高ASK価格を取得するのに使われます。
double max_ask = mysymbol.AskHigh();
mysymbol.AskLow() この関数は日の最小/最低ASK価格を取得するのに使われます。
double min_ask = mysymbol.AskLow();
mysymbol.CurrencyBase() この関数は設定されたシンボルについて基本通貨を取得するのに使われます。
// returns "USD" for USDJPY or USDCAD
string base_currency = mysymbol.CurrencyBase();
mysymbol.ContractSize() この関数は設定したシンボルの取引に対して契約サイズの値を取得するために使われます。
double cont_size =  mysymbol.ContractSize();
mysymbol.Digits() この関数は設定されたシンボルについて少数点以下の桁数を取得するのに使われます。
int s_digits = mysymbol.Digits();
mysymbol.Point() この関数は設定されたシンボルについてひとつのポイントの値を取得するのに使われます。
double s_point =  mysymbol.Point();
mysymbol.LotsMin() この関数は設定されたシンボルについてクラスをクローズするのに要求される最小ボリュームを取得するのに使われます。
double min_lot =  mysymbol.LotsMin();
mysymbol.LotsMax() この関数は設定されたシンボルについてクラスをクローズするのに要求される最大ボリュームを取得するのに使われます。
double max_lot =  mysymbol.LotsMax();
mysymbol.LotsStep() この関数は、設定されたシンボルについて取引をクローズするためボリューム変更の最小ステップを取得するのに使われます。
double lot_step = mysymbol.LotsStep();
mysymbol.NormalizePrice(double price) この関数は、設定されたシンボルの正しい桁に正常化された価格を取得するのに使われます。
// A normalized current Ask price
double n_price = mysymbol.NormalizePrice(mysymbol.Ask()); 
mysymbol.Select() この関数はシンボルがマーケットワッチウィンドウに選択されているか判断するのに使われます。シンボルが選択されていれば、trueを返します。それ以外ではfalseを返します。
if (mysymbol.Select())
{
  //Symbol successfully selected
}
else
{
  // Symbol could not be selected
}
mysymbol.Select(bool select) この関数はマーケットワッチウィンドウでシンボルを選択するか、マーケットワッチウィンドウ内でシンボルを削除するのに使われます。チャートのポジションがすでにオープンになっているチャートが開いているときマーケットワッチウィンドウ内でシンボルを削除するとfalseが返されます。
if (!mysymbol.Select())
{
   //Symbol not selected, Select the symbol
    mysymbol.Select(true);
}
else
{
 // Symbol already selected, 
 // remove Symbol from market watch window
    mysymbol.Select(false);
}
mysymbol.MarginInitial() この関数はマージン通貨において1ロットのボリュームを伴いポジションをオープンにすることに要求される量を取得するのに使われます。
double init_margin = mysymbol.MarginInitial() ;
mysymbol.TradeMode() この関数はシンボルに許可されている注文実行タイプを取得するのに使われます。
if (mysymbol.TradeMode() == SYMBOL_TRADE_MODE_FULL)
{
 // Full trade allowed for this symbol,
 // no trade restrictions 
}
mysymbol.TradeModeDescription() この関数はシンボルに許可されている注文実行タイプの記述を取得するのに使われます。
Print("The trade mode for this symbol is",
       mysymbol.TradeModeDescription());


1.3 СHistoryOrderInfoクラス

CHistoryOrderInfoは、注文履歴プロパティをひじょうに扱いやすくするもう一つのクラスです。

このクラスのオブジェクトを作成したら、そのオブジェクトを使って重大な問題を解決するのに必要な重要なパブリックメンバー関数にアクセスできます。

そのクラスオブジェクトをmyhistoryと名付けます。

// The CHistoryOrderInfo Class object
CHistoryOrderInfo myhistory;

このクラスの主要な関数をいくつか見ていきます。

履歴内の注文詳細を得るためこのクラスを使うにあたり、履歴内の全注文を取得し、それからクラスオブジェクトmyhistoryに注文チケットを渡す必要があります。

//Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))  // get all history orders
{
// Get total orders in history
int tot_hist_orders = HistoryOrdersTotal();

これから使用可能な全履歴注文を反復し、クラスオブジェクトを用いて各履歴注文の詳細を取得します。

ulong h_ticket; // Order ticket

for (int j=0; j<tot_hist_orders; j++)
{
  h_ticket = HistoryOrderGetTicket(j));

  if (h_ticket>0)
  {
    // First thing is to now set the order Ticket to work with by our class object 
メソッド 説明 使用例
myhistory.Ticket(ulong ticket) この関数はプロパティまたは詳細を取得したい注文チケットを選択するのに使われます。
myhistory.Ticket(h_ticket);
myhistory.Ticket() この関数は注文についてオーダーチケットを取得するのに使われます。
ulong o_ticket = myhistory.Ticket();
myhistory.TimeSetup() この関数は注文が実行されたか設定された「時刻」を取得するのに使われます。
datetime os_time = myhistory.TimeSetup();
myhistory.OrderType() この関数は注オーダータイプ(ORDER_TYPE_BUYなど)を取得するのに使われます。
if (myhistory.OrderType() == ORDER_TYPE_BUY)
{
// This is a buy order
}
myhistory.State() この関数は注文の現状を取得するのに使われます。
注文がキャンセル、受けつけ、拒否、セット等されたら
if(myhistory.State() == ORDER_STATE_REJECTED)
{
// order was rejected, not placed.
}
myhistory.TimeDone() この関数は注文がセット、キャンセル、拒否された時刻を取得するのに使われます。
datetime ot_done =  myhistory.TimeDone();
myhistory.Magic() この関数は注文を初期化したExpert Advisor idを取得するのに使われます。
long o_magic = myhistory.Magic();
myhistory.PositionId() この関数は注文がセットされたときインクルードされたポジションのIDを取得するのに使われます。
long o_posid = myhistory.PositionId();
myhistory.PriceOpen() この関数はオーダーの始値を取得するのに使われます。
double o_price =  myhistory.PriceOpen();
myhistory.Symbol() この関数は注文のシンボルプロパティ(通貨ペア)を取得するのに使われます。
string o_symbol =  myhistory.Symbol();

履歴内全オーダーのループ内部でこれら関数を使用したことを忘れないでください。


1.4СOrderInfoクラス

このCOrderInfoはすべての指値注文に簡単にアクセスできるようになるクラスです。このクラスのオブジェクトが作成されたら、それはいつでもこのクラスのパブリックメンバー関数に対して使用可能です。

このクラスの用法はいくらか上述のCHistoryOrderInfoクラスの用法に似ています。

クラスオブジェクトを作成し、それをmyorderと呼びます。

// The OrderInfo Class object
COrderInfo myorder;

指値注文の詳細情報を得るためこのクラスを使えるようにするには、まず使用可能な注文をすべて取得し、それからオーダーチケットによってそれらを選択する必要があります。

// Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))   // get all history orders
   {    
     // get total orders
     int o_total = OrdersTotal();

全注文をループし、作成したオブジェクトを使って対応するプロパティを取得します。

for (int j=0; j<o_total; j++)
{
 // we must confirm if the order is available for us to get its details using the Select function of the COrderInfo Class
メソッド 説明 使用例
myorder.Select(ulong ticket) この関数は注文を操作しやすくするためチケット番号によって注文を選択するのに使われます。
if (myorder.Select(OrderGetTicket(j)) 
   { // order has been selected and can now be manipulated.
   }
myorder.Ticket() この関数は選択された注文についてオーダーチケットを取得するのに使われます。
ulong o_ticket = myorder.Ticket();
myorder.TimeSetup() この関数はこの注文が設定された時刻を取得するのに使われます。
datetime o_setup = myorder.TimeSetup();
myorder.Type() この関数はORDER_TYPE_BUY_STOPなどのようなオーダータイプを取得するのに使われます。
if (myorder.Type() == ORDER_TYPE_BUY_LIMIT)
{
// This is a Buy Limit order, etc
}
myorder.State() この関数は注文の状態を取得するのに使われます。
注文がキャンセル、受けつけ、拒否、セット等されたら
if (myorder.State() ==ORDER_STATE_STARTED)
{
// order has been checked 
// and may soon be treated by the broker
}
myorder.TimeDone() この関数は注文がセット、拒否、キャンセルされた時刻を取得するのに使われます。
datetime ot_done = myorder.TimeDone();
myorder.Magic() この関数は注文を初期化したExpert Advisorのidを取得するのに使われます。
long o_magic =  myorder.Magic();
myorder.PositionId() この関数は注文がセットされたときインクルードされたポジションのIDを取得するのに使われます。
long o_posid = myorder.PositionId();
myorder.PriceOpen() この関数はオーダーの始値を取得するのに使われます。
double o_price = myorder.PriceOpen();
myorder.StopLoss() この関数は注文のストップ ロスを取得するのに使われます。
double  s_loss = myorder.StopLoss();
myorder.TakeProfit() この関数は注文の「テイクプロフィット」を取得するのに使われます。
double t_profit = myorder.TakeProfit();
myorder.PriceCurrent() この関数は注文がセットされたシンボルの現在価格を取得するのに使われます。
double cur_price =  myorder.PriceCurrent();
myorder.Symbol() この関数は注文がセットされたシンボル名を取得するのに使われます。
string o_symbol = myorder.Symbol();
myorder.StoreState() この関数は、のちに注文に何か変更が加えられたら、比較できるように現在の注文詳細情報を保存または保管するのに使われます。
myorder.StoreState();
myorder.CheckState() この関数は、保存または保管された注文の詳細に変更があったか確認するのに使われます。
if (myorder.CheckState() == true)
{
// Our order status or details have changed
}


1.5CDealInfoクラス

CDealInfoクラスにより、すべての取引プロパティ履歴または情報にアクセスが可能になります。ひとたびこのクラスのオブジェクトを作成すれば、履歴中の取引についてあらゆる情報を得ることができます。ちょうどCHistoryOrderInfoに似ています。

そこでこのクラスのオブジェクトを作成したら、それをmydealと名づけます。

// The DealInfo Class object
CDealInfo myinfo;

履歴内の全取引きを取得することから始めます。

if (HistorySelect(0,TimeCurrent()))
   {    
    // Get total deals in history
    int tot_deals = HistoryDealsTotal();

これから使用可能な全履歴注文を反復し、クラスオブジェクトを用いて各履歴注文の詳細を取得します。

ulong d_ticket; // deal ticket
for (int j=0; j<tot_deals; j++)
    {
     d_ticket = HistoryDealGetTicket(j);
     if (d_ticket>0)  
     {
      // First thing is to now set the deal Ticket to work with by our class object 
メソッド 説明 使用例
mydeal.Ticket(ulong ticket) この関数は作成したオブジェクトによってのちに使用するため取引きチケットを設定するのに使われます。
mydeal.Ticket(d_ticket);
mydeal.Ticket() この関数は注取引きチケットを取得するのに使われます。
ulong deal_ticket = mydeal.Ticket();
mydeal.Order() この関数は取引きが実行された注文についてのオーダーチケットを取得するのに使われます。
long deal_order_no =  mydeal.Order();
mydeal.Time() この関数はこの取引きが実行された時刻を取得するのに使われます。
datetime d_time = mydeal.Time();
mydeal.Type() この関数は取引きタイプを取得するのに使われます。それがDEAL_TYPE_SELLなどかどうか。
if (mydeal.Type() == DEAL_TYPE_BUY)
{
// This deal was executed as a buy deal type
}
mydeal.Entry() この関数は取引きの方向を取得するのに使われます。それが DEAL_ENTRY_IN or DEAL_ENTRY_OUTなどかどうか。
if (mydeal.Entry() == DEAL_ENTRY_IN)
{
// This was an IN entry deal
}
mydeal.Magic() この関数は取引きを実行したExpert Advisorのidを取得するのに使われます。
long d_magic = mydeal.Magic();
mydeal.PositionId() この関数は取引きが一部となっているポジションについてユニークポジション識別を取得するのに使われます。
long d_post_id = mydeal.PositionId();
mydeal.Price() この関数は取引きが実行された価格を取得するのに使われます。
double d_price = mydeal.Price();
mydeal.Volume() この関数は取引きのボリューム(ロット)を取得するのに使われます。
double d_vol = mydeal.Volume();
mydeal.Symbol() この関数は取引きが実行されたシンボル(通貨ペア)を取得するのに使われます。
string d_symbol = mydeal.Symbol();


1.6 The CPositionInfo Class

CPositionInfoクラスにより、現在のポジションプロパティに簡単にアクセスできるようになります。ポジションプロパティを取得するのにクラスを使えるようになるには、このクラスのオブジェクトを作成する必要があります。

このクラスオブジェクトを作成し、それをmypositionと呼びます。

// The object of the CPositionInfo class
CPositionInfo myposition;

このオブジェクトを使ってオープンなポジションの詳細情報を取得します。すべての使用可能なオープンポジションを取得することから始めます。

int pos_total = PositionsTotal();

詳細情報を得るためにすべてのオープンポジションにあたります。

for (int j=0; j<pos_total; j++)
    {
メソッド 説明 使用例
myposition.Select(const string symbol) この関数は動作できるように現在のオープンポジションに対応するシンボルを選択するのに使われます。
if (myposition.Select(PositionGetSymbol(j)))
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
OR
// when dealing with the current symbol/chart only
if (myposition.Select(_Symbol)) 
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
myposition.Time() この関数はポジションがオープンされた時刻を取得するのに使われます。
datetime pos_time = myposition.Time();
myposition.Type() この関数はがオープンされたポジションタイプを取得するのに使われます。
if (myposition.Type() == POSITION_TYPE_BUY)
{
// This is a buy position
}
myposition.Magic() この関数はポジションをオープンにしたExpert Advisorのidを取得するのに使われます。
long pos_magic = myposition.Magic();
myposition.Volume() この関数はオープンポジションのボリューム(ロット)を取得するのに使われます。
double pos_vol = myposition.Volume(); // Lots
myposition.PriceOpen() この関数はポジションがオープンになったときの価格、すなわちポジションオープン価格を取得するのに使われます。
double pos_op_price = myposition.PriceOpen();
myposition.StopLoss() この関数はオープンポジションについてのストップロス価格を取得するのに使われます。
double pos_stoploss = myposition.StopLoss();
myposition.TakeProfit() この関数はオープンポジションについてのテイクプロフィット価格を取得するのに使われます。
double pos_takeprofit = myposition.TakeProfit();
myposition.StoreState() この関数はポジションの現状を保管するのに使われます。
// stores the current state of the position
myposition.StoreState();
myposition.CheckState() この関数はオープンポジションの状態に変更があったか確認するのに使われます。
if (!myposition.CheckState())
{
  // position status has not changed yet
}
myposition.Symbol() この関数はポジションがオープンされたシンボル名を取得するのに使われます。
string pos_symbol = myposition.Symbol();


1.7СTradeクラス

CTrade クラスにより、MQL5内のトレード処理に簡単にアクセスできるようになります。このクラスを使うには、クラスのオブジェクトを作成し、必要なトレード処理を行うの使う必要があります。

このクラスのオブジェクトを作成したら、それをmytradeと名づけます。

//An object of the CTrade class
CTrade mytrade;

最初のステップは、トレード処理の作成でオブジェクトが使うパラメータの多くを設定することです。

メソッド 説明 使用例
mytrade.SetExpertMagicNumber(ulong magic) この関数はトレード処理にクラスが使用するエキスパートid(マジックナンバー)を設定するのに使われます。
ulong Magic_No=12345;
mytrade.SetExpertMagicNumber(Magic_No);
mytrade.SetDeviationInPoints(ulong deviation) この関数はまた、偏差値(ポイント表記)を設定し、トレードをセットするときに使えるようにします。
ulong Deviation=20;
mytrade.SetDeviationInPoints(Deviation); 
mytrade.OrderOpen(const string symbol,
ENUM_ORDER_TYPE
order_type,double volume,
double
limit_price,double price,double sl,
double
tp,ENUM_ORDER_TYPE_TIME type_time,
datetime
expiration,const string comment="")
この関数は指値注文を出すのに使われます。 この関数を使うためには、まずパラメータを準備し、この関数に渡します。
// define the input parameters
double Lots = 0.1;
double SL = 0;
double TP = 0;
// latest Bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid()-_Point*550;
// place (BuyStop) pending order
mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELLSTOP,Lots,0.0,Oprice,
                  SL,TP,ORDER_TIME_GTC,0);
mytrade.OrderModify(ulong ticket,double price,
double
sl,double tp,ENUM_ORDER_TYPE_TIME type_time,datetime expiration)
この関数は指既存の指値注文を変更するのに使われます。
// Select total orders in history and get total pending orders 
// (as shown within the COrderInfo class section). 
// Use the CSymbolInfo class object to get the current ASK/BID price
int Stoploss = 400;
int Takeprofit = 550;
for(int j=0; j<OrdersTotal(); j++)
{
  ulong o_ticket = OrderGetTicket(j);
  if(o_ticket != 0)
  {
   // Stoploss must have been defined
   double SL = mysymbol.Bid() + Stoploss*_Point;  
   // Takeprofit must have been defined  
   double TP = mysymbol.Bid() - Takeprofit*_Point; 
   // lastest ask price using CSymbolInfo class object
   double Oprice = mysymbol.Bid();                 
   // modify pending BuyStop order
   mytrade.OrderModify(o_ticket,Oprice,SL,TP,ORDER_TIME_GTC,0);
  }
}
mytrade.OrderDelete(ulong ticket) この関数は指値注文を削除するのに使われます。
// Select total orders in history and get total pending orders
// (as shown within the COrderInfo class section). 

int o_total=OrdersTotal();
for(int j=o_total-1; j>=0; j--)
{
   ulong o_ticket = OrderGetTicket(j);
   if(o_ticket != 0)
   {
    // delete the pending Sell Stop order
    mytrade.OrderDelete(o_ticket);
   }
}
mytrade.PositionOpen(const string symbol,ENUM_ORDER_TYPE order_type,double volume,double price,double sl,double tp,const string comment="") この関数は買いポジション、または売りポジションをオープンするのに使われます。この関数を使うためには、まずすべてのパラメータを準備し、この関数に渡します。
// define the input parameters and use the CSymbolInfo class
// object to get the current ASK/BID price
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point;   
//Takeprofit must have been defined 
double TP = mysymbol.Ask() + Takeprofit*_Point; 
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lots,
                     Oprice,SL,TP,"Test Buy");
mytrade.PositionModify(const string symbol,
double
sl,double tp)
この関数は既存のオープンポジションについてストップロスおよび/またはテイクプロフィットを変更するのに使われます。この関数を使うためには、まずCPositionInfoクラスオブジェクトを使って変更するポジションをすべて選択し、CSymbolInfoクラスオブジェクトを使って現在のBID/ASK価格を取得します。
if (myposition.Select(_Symbol))
{
  int newStoploss = 250;
  int newTakeprofit = 500;
  double SL = mysymbol.Ask() – newStoploss*_Point;    
  double TP = mysymbol.Ask() + newTakeprofit*_Point;  
  //modify the open position for this symbol
 mytrade.PositionModify(_Symbol,SL,TP);
}
mytrade.PositionClose(const string symbol,
ulong
deviation=ULONG_MAX)
この関数は既存のオープンポジションをクローズします。
if (myposition.Select(_Symbol))
{
 //close the open position for this symbol
 mytrade.PositionClose(_Symbol);  
}
mytrade.Buy(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,double tp=0.0,const string comment="") この関数は買いトレードをオープンするのに使われます。この関数を使っているときトレードするのにボリューム(またはロット)を設定することが推奨されます。tp(テイクプロフィット)および sl(ストップロス)がオープンされているポジションの変更によってのちに設定可能な場合トレードをオープンするには現在のAsk価格を使います。
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point; 
//Takeprofit must have been defined
double TP = mysymbol.Ask() +Takeprofit*_Point;
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.Buy(Lots,NULL,Oprice,SL,TP,“Buy Trade”);

//OR
mytrade.Buy(Lots,NULL,0.0,0.0,0.0,“Buy Trade”);
// modify position later
mytrade.Sell(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,double tp=0.0,const string comment="") この関数は売りトレードをオープンするのに使われます。この関数を使っているときトレードするにはボリューム(またはロット)を設定することが推奨されます。 tp(テイクプロフィット)および sl (ストップロス)がオープンされているポジションの変更によってのちに設定可能な場合トレードをオープンするには現在のBid価格を使います。
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Bid() + Stoploss*_Point;
//Takeprofit must have been defined
double TP = mysymbol.Bid() - Takeprofit*_Point; 
// latest bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid();
// open a Sell trade
mytrade.Sell(Lots,NULL,Oprice,SL,TP,“Sell Trade”); 

//OR
mytrade.Sell(Lots,NULL,0.0,0.0,0.0,“Sell Trade”); 
//(modify position later)
mytrade.BuyStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0,
ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")
この関数はBuyStop 指値注文を出すのに使われます。初期設定のオーダータイプはORDER_TIME_GTCで、有効期限は0です。同じオーダータイプ時間を考えているなら、この2つの変数を指定する必要はありません。
double Lot = 0.1;
//Buy price = bar 1 High + 2 pip + spread
 int sprd=mysymbol.Spread();
 double bprice =mrate[1].high + 2*_Point + sprd*_Point;
//--- Buy price
 double mprice=NormalizeDouble(bprice,_Digits); 
//--- Stop Loss
 double stloss = NormalizeDouble(bprice - STP*_Point,_Digits);
//--- Take Profit
 double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits);
//--- open BuyStop order
 mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit);
mytrade.SellStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") This function is used to place a SellStop Pending order with the set parameters. The default Order type time is ORDER_TIME_GTC, and expiration is 0. 同じオーダータイプ時間を考えているなら、この2つの変数を指定する必要はありません。
double Lot = 0.1;
//--- Sell price = bar 1 Low - 2 pip 
//--- MqlRates mrate already declared
 double sprice=mrate[1].low-2*_Point;
//--- SellStop price
 double slprice=NormalizeDouble(sprice,_Digits);
//--- Stop Loss
 double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);
//--- Take Profit
 double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits);
//--- Open SellStop Order
 mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit);
mytrade.BuyLimit(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") この関数は設定したパラメータを使ってBuyLimit注文を出すのに使われます。
Usage:
//--- Buy price = bar 1 Open  - 5 pip + spread
double Lot = 0.1;
int sprd=mysymbol.Spread();
//--- symbol spread
double bprice = mrate[1].open - 5*_Point + sprd*_Point;
//--- MqlRates mrate already declared
double mprice=NormalizeDouble(bprice,_Digits);
//--- BuyLimit price
//--- place buyLimit order, modify stoploss and takeprofit later
mytrade.BuyLimit(Lot,mprice,_Symbol);
mytrade.SellLimit (double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") この関数は設定したパラメータを使ってSell Limit注文を出すのに使われます。
//--- Sell Limit price = bar 1 Open  + 5 pip
double Lot = 0.1;
//--- MqlRates mrate already declared
double sprice = mrate[1].open + 5*_Point;
//--- SellLimit
double slprice=NormalizeDouble(sprice,_Digits);
//place SellLimit order, modify stoploss and takeprofit later
mytrade.SellLimit(Lot,slprice,_Symbol);

トレード結果関数

mytrade.ResultRetcode() この関数はトレード処理について結果コードを取得するのに使われます。
// a trade operation has just been carried out
int return_code = mytrade.ResultRetcode();
mytrade.ResultRetcodeDescription() この関数はトレード処理の返されたコードの完全な記述または解釈を取得するのに使われます。
string ret_message =  ResultRetcodeDescription();
// display it
Alert("Error code - " , mytrade.ResultRetcode() ,
      "Error message - ", ret_message);
mytrade.ResultDeal() この関数はオープンポジションについて取引チケットを取得するのに使われます。
long dl_ticket = mytrade.ResultDeal();
mytrade.ResultOrder() この関数はオープンポジションについてオーダーチケットを取得するのに使われます。
long o_ticket = mytrade.ResultOrder();
mytrade.ResultVolume() この関数はオープンポジションのボリューム(ロット)を取得するのに使われます。
double o_volume = mytrade.ResultVolume();
mytrade.ResultPrice() この関数はオープンポジションについて取引き価格を取得するのに使われます。
double r_price = mytrade.ResultPrice();
mytrade.ResultBid() この関数は設現在のマーケットBID価格(再クオート価格)を取得するのに使われます。
double rq_bid = mytrade.ResultBid;
mytrade.ResultAsk() この関数は現ASK価格(再クオート価格)を取得するのに使われます。
double rq_ask = mytrade.ResultAsk;
mytrade.PrintRequest() / mytrade.PrintResult() 前述の2つの関数はそれぞれジャーナルタブ、トレード依頼パラメータ、結果パラメータに印刷するのに使用可能です。
// after a trade operation
// prints the trade request parameters
mytrade.PrintRequest(); 
//prints the trade results
mytrade.PrintResult();  

トレード依頼関数

mytrade.RequestAction() この関数は送信されたばかりの最後のトレード依頼についての「トレード処理」タイプを取得するのに使われます。
//determine the Trade operation type for the last Trade request
if (mytrade.RequestAction() == TRADE_ACTION_DEAL)
{
  // this is a market order for an immediate execution
}
else if (mytrade.RequestAction() == TRADE_ACTION_PENDING)
{
  // this is a pending order.
}  
mytrade.RequestMagic() この関数は最後の依頼で使用されたエキスパートマジックナンバーを取得するのに使われます。
ulong mag_no = mytrade. RequestMagic();
mytrade.RequestOrder()
この関数は最終依頼で使用されたオーダーチケットを取得するのに使われます。これは主に指値注文の変更に関わるものです。
ulong po_ticket =  mytrade.RequestOrder();
mytrade.RequestSymbol() この関数は最終依頼で使用されたシンボルまたは通貨ペアを取得するのに使われます。
string symb = mytrade.RequestSymbol(); 
mytrade.RequestVolume() この関数は最終依頼でセットされたトレードのボリューム(ロット表記)を取得するのに使われます。
double Lot = mytrade.RequestVolume();  
mytrade.RequestPrice() この関数は最終依頼で使用された 注文価格を取得するのに使われます。
double oprice = mytrade.RequestPrice();   
mytrade.RequestStopLimit() この関数は最終依頼で使用された ストップロス 価格を取得するのに使われます。
double limitprice = mytrade.RequestStopLimit(); 
mytrade.RequestSL() この関数は最終依頼で使用された ストップロス 価格を取得するのに使われます。
double sloss = mytrade.RequestSL();  
mytrade.RequestTP() この関数は最終依頼で使用された テイクプロフィット価格を取得するのに使われます。
double tprofit = mytrade.RequestTP();   
mytrade.RequestDeviation() この関数は最終依頼で使用された 偏差を取得するのに使われます。
ulong dev = mytrade.RequestDeviation();  
mytrade.RequestType() この関数は最終依頼で出されたオーダータイプを取得するのに使われます。
if (mytrade.RequestType() == ORDER_TYPE_BUY)
 {
  // market order Buy was placed in the last request.
mytrade.RequestTypeDescription() この関数は最終依頼で出されたオーダーの記述を取得するのに使われます。
Print("The type of order placed in the last request is :",
      mytrade.RequestTypeDescription());  
mytrade.RequestActionDescription() この関数は最終依頼で使用された依頼の記述を取得するのに使われます。
Print("The request action used in the last request is :", 
      mytrade.RequestTypeDescription());
mytrade.RequestTypeFillingDescription() この関数は最終依頼で使用された注文記述ポリシータイプを取得するのに使われます。
Print("The type of order filling policy used",
      " in the last request is :",
      RequestTypeFillingDescription()); 

注文を出すことに関して発生するエラーを特定するとき、トレードクラス依頼関数はたいへん有用です。発注時にエラーメッセージを受け取ることがあり、なにがうまくいかなかったのかすぐに特定できないと、混乱を招きます。トレードクラス依頼関数の使用により、トレードサーバーに送られた依頼パラメータをいくつか印刷し、なにがいけなかったのか特定できるようになります。そのような使用例に類似したコードを以下に記載します。

//--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           { //--- Request is completed or order placed           
             Alert("A Buy order at price:", mytrade.ResultPrice() , ", vol:",mytrade.ResultVolume(),
                  " has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
            mytrade.PrintResult();
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), ", sl:", mytrade.RequestSL(),
                 ", tp:",mytrade.RequestTP(), ", price:", mytrade.RequestPrice(),
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
            mytrade.PrintRequest();
            return;
           }

上記のコードでは、エラーがあった場合に備え、われわれの依頼にいくつかのパラメータが特定できるようにしようとしました。たとえば、正しいストップロス価格を指定しなかったら、有効でないストップロスエラーを発生し、mytrade.RequestSL() を使ってストップロス値を印刷することで、指定したストップロス価格について何が問題なのか知ることができるのです。

それぞれのクラスがどのように使われるのか示すことに時間を取りましたが、これからは先に述べた関数を実践に使用していきます。

Expert Advisorで使っていく機能性は全て先に記載したことを覚えておいてください。これから書こうとしている関数を見たら先の説明を常に参照するのはよいことだと思います。


2. トレードクラス関数の使用

トレードクラス関数の使い方をお見せするため、以下のタスクを行うExpert Advisorを書いていきます。

  • それは買いまたは売り条件をチェックします。条件が満たされていれば、満たされた条件に応じて買いまたは売り注文を出します。
  • ポジションがオープンになっており、トレードがわれわれの方向に進んだら、ポジションのテイクプロフィットかストップロスを変更します。ただし、取引がわれわれに逆風で収益目標にとどかなければ、ポジションはクローズします。
  • われわれのEAは次のどの通貨に対しても日次トレードに使用されます。 – GBPUSD、AUDUSD、EURUSDなど。


2.1Expert Advisorのプログラミング

まず新規MQL5ドキュメントを起動し、 Expert Advisor (テンプレート)を選択したら、「次へ」ボタンをクリックします。

新規MQL5ドキュメントの起動

図1 新規MQL5ドキュメントを起動します。

Expert Advisorの名前を入力し、「終了」ボタンをクリックします。入力パラメータはのちにマニュアル定義します。

新規ドキュメントに名前をつけます。

図2 Expert Advisorの名づけ

作成した新規ドキュメントは以下に似ているはずです。

エキスパートコードスケルトン

#propertyバージョン行のすぐ後に使っていくすべてのトレードクラスインクルードします。

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The AccountInfo Class
#include <Trade\AccountInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>

われわれの入力パラメータを定義します。

//+------------------------------------------------------------------+
//|  INPUT PARAMETERS                                              |
//+------------------------------------------------------------------+
input int      StopLoss=100;     // Stop Loss
input int      TakeProfit=240;   // Take Profit
input int      ADX_Period=15;    // ADX Period
input int      MA_Period=15;     // Moving Average Period
input ulong    EA_Magic=99977;   // EA Magic Number
input double   Adx_Min=24.0;     // Minimum ADX Value
input double   Lot=0.1;          // Lots to Trade
input ulong    dev=100;          // Deviation 
input long     Trail_point=32;   // Points to increase TP/SL
input int      Min_Bars = 20;    // Minimum bars required for Expert Advisor to trade
input double   TradePct = 25;    // Percentage of Account Free Margin to trade

このExpert Advisorコードで使うその他のパラメータも指定します。

//+------------------------------------------------------------------+
//|  OTHER USEFUL PARAMETERS                                         |
//+------------------------------------------------------------------+
int adxHandle;                     // handle for our ADX indicator
int maHandle;                    // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
double maVal[];                  // Dynamic array to hold the values of Moving Average for each bars
double p_close;                    // Variable to store the close value of a bar
int STP, TKP;                   // To be used for Stop Loss, Take Profit 
double TPC;                        // To be used for Trade percent

ここでインクルードしたクラスそれぞれにオブジェクトを作成します。

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The Trade Class Object
CTrade mytrade;
//--- The PositionInfo Class Object
CPositionInfo myposition;
//--- The AccountInfo Class Object
CAccountInfo myaccount;
//--- The SymbolInfo Class Object
CSymbolInfo mysymbol;

次に行うのは、作業をしやすくする関数の定義です。

これら関数が定義できたら、OnInit()およびOnTick()関数の必要なセクションでそれらを呼びます。


2.1.1. checkTrading関数

この関数はわれわれのExpert Advisorがトレードを行うか行わないかすべての初期確認をするのに使われます。この関数trueを返したら、われわれのEAは先に進みます。それ以外ならEAはトレードを行いません。

//+------------------------------------------------------------------+
//|  Checks if our Expert Advisor can go ahead and perform trading   |
//+------------------------------------------------------------------+
bool checkTrading()
{
  bool can_trade = false;
  // check if terminal is syncronized with server, etc
  if (myaccount.TradeAllowed() && myaccount.TradeExpert() && mysymbol.IsSynchronized())
  {
    // do we have enough bars?
    int mbars = Bars(_Symbol,_Period);
    if(mbars >Min_Bars)
    {
      can_trade = true;
    }
  }
  return(can_trade);
}

ブールデータタイプcan_trade を宣言し、それをfalseとします。トレードが許可されているか、またExpert Advisorsがこのアカウントにおいてトレードを許可されているか確認するためCAccountInfoクラスのオブジェクトを使用しました。同じく端末がトレードサーバーと同期しているか確認するのにはCSymbolInfoクラスを使います。

これら3つの条件が満たされれば、現在バーの合計数がわれわれのEA がトレードを行うのに要求される最小値よりも大きいか確認します。この関数がtrueを返したら、われわれのEAはトレードを行います。それ以外なら、われわれの EAはこの関数での条件が満たされるまで一切のトレードを行いません。

これまで見てきたように、この関数には標準トレードクラスライブラリの必要なオブジェクトを使用して、すべての必要なトレード確認をインクルードすると決めました。


2.1.2. ConfirmMargin関数

//+------------------------------------------------------------------+
//|  Confirms if margin is enough to open an order
//+------------------------------------------------------------------+
bool ConfirmMargin(ENUM_ORDER_TYPE otype,double price)
  {
   bool confirm = false;
   double lot_price = myaccount.MarginCheck(_Symbol,otype,Lot,price); // Lot price/ Margin    
   double act_f_mag = myaccount.FreeMargin();                        // Account free margin 
   // Check if margin required is okay based on setting
   if(MathFloor(act_f_mag*TPC)>MathFloor(lot_price))
     {
      confirm =true;
     }
    return(confirm);
  }

注文を出すにあたり、アカウントのフリーマージンにおいては一定レベルのパーセンテージしか使わないという設定に基づき、トレードに十分なマージンがあるか確認するため、CAccountInfoクラスのオブジェクトを使用します。

要求されるアカウントのフリーマージンのパーセンテージが注文に要求されるマージンより大きければ、この関数はtrueを返し、それ以外はfalseを返します。これにより、関数がtrueを返した場合のみ注文を出したいと思います。この関数は入力パラメータとしてオーダータイプを取ります。


2.1.3. checkBuy関数

//+------------------------------------------------------------------+
//|  Checks for a Buy trade Condition                                |
//+------------------------------------------------------------------+
bool checkBuy()
{
  bool dobuy = false;
  if ((maVal[0]>maVal[1]) && (maVal[1]>maVal[2]) &&(p_close > maVal[1]))
  {
    // MA increases upwards and previous price closed above MA
    if ((adxVal[1]>Adx_Min)&& (plsDI[1]>minDI[1]))
    {
      // ADX is greater than minimum and +DI is greater tha -DI for ADX
      dobuy = true;
    }
  }
  return(dobuy);
}

この関数内で買いトレードをオープンする条件をラップすることとしました。ここではクラスオブジェクトはひとつも使っていません。移動平均値が上向きに増加して、前回バーの終値がその時点での移動平均より大きいという条件の確認をします。

ADX指数の値が入力パラメータに設定された要求される最小値よりも大きく、ADXの正のDI 値が負のDI 値よりも大きくしたいと思います。上記条件が満たされれば、われわれのEA を買い注文にオープンしたいと思います。


2.1.4. heckSell関数

//+------------------------------------------------------------------+
//|  Checks for a Sell trade Condition                               |
//+------------------------------------------------------------------+
bool checkSell()
{
  bool dosell = false;
  if ((maVal[0]<maVal[1]) && (maVal[1]<maVal[2]) &&(p_close < maVal[1]))
  {
    // MA decreases downwards and previuos price closed below MA
    if ((adxVal[1]>Adx_Min)&& (minDI[1]>plsDI[1]))
    {
      // ADX is greater than minimum and -DI is greater tha +DI for ADX
      dosell = true;
    }
  }
  return(dosell);
}

この関数はCheckBuy関数のちょうど逆のチェックをします。ここでもクラスオブジェクトはひとつも使っていません。移動平均値が下向きに減少して、前回バーの終値がその時点での移動平均より低いという条件の確認をします。

ADX指数の値が入力パラメータに設定された要求される最小値よりも大きく、ADXの負のDI 値が正のDI 値よりも大きくしたいと思います。上記条件が満たされれば、われわれのEA を売り注文にオープンしたいと思います。

2.1.5checkClosePos関数
//+------------------------------------------------------------------+
//|  Checks if an Open position can be closed                        |
//+------------------------------------------------------------------+
bool checkClosePos(string ptype, double Closeprice)
{
   bool mark = false;
   if (ptype=="BUY")
   {
      // Can we close this position
     if (Closeprice < maVal[1]) // Previous price close below MA
      {
         mark = true;
      }
   }
   if (ptype=="SELL")
   {
      // Can we close this position
      if (Closeprice > maVal[1]) // Previous price close above MA
      {
         mark = true;
      }
   }
   return(mark);
}

この関数は現在のオープンポジションをクローズすることができるか確認するのに使われます。この関数は前回バーの終値がその時点の移動平均指数値より高いか低いか確認するのに使われます。

すべての条件が満たされればこの関数はtrueを返し、われわれのEAはポジションをクローズすると考えられます。この関数には2つの入力パラメータがあります。オーダータイプ(今回は名前:買いまたは売り)と、前回バーの終値です。


2.1.6. ClosePosition関数

//+------------------------------------------------------------------+
//| Checks and closes an open position                               |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool marker=false;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Magic()==EA_Magic && myposition.Symbol()==_Symbol)
           {
            //--- Check if we can close this position
            if(checkClosePos(ptype,clp)==true)
              {
               //--- close this position and check if we close position successfully?
               if(mytrade.PositionClose(_Symbol)) //--- Request successfully completed 
                 {
                  Alert("An opened position has been successfully closed!!");
                  marker=true;
                 }
               else
                 {
                  Alert("The position close request could not be completed - error: ",
                       mytrade.ResultRetcodeDescription());
                 }
              }
           }
        }
      return(marker);
     }

これは実際に上記の関数(checkclosepos)を使う関数です。CPositionInfoクラスとCTradeクラスのオブジェクトを使います。この関数がCPositionInfoクラスのオブジェクトを使うのは、われわれのEAによってオープンされているポジションと使用中のシンボルにてついて使用可能なオープンポジションを確認するためです。 ポジションが見つかれば、checkclosepos関数を使ってクローズすることが可能か確認します。


checkclosepos関数がtrueを返せば、この関数は, CTradeクラスのオブジェクトを使用しポジションクローズ処理の結果を表示します。問題なくポジションがクローズしたら、trueを返し、それ以外はfalseを返します。

関数は2つの入力パラメータを取ります。オーダータイプ( ポジション名、買いまたは売りと、 前回バーの終値です。)</s2>これらパラメータは実際、それらを使うcheckclosepos関数に渡されます。


2.1.7. CheckModify

//+------------------------------------------------------------------+
//|  Checks if we can modify an open position                        |
//+------------------------------------------------------------------+
bool CheckModify(string otype,double cprc)
{
   bool check=false;
   if (otype=="BUY")
   {
      if ((maVal[2]<maVal[1]) && (maVal[1]<maVal[0]) && (cprc>maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   else if (otype=="SELL")
   {
      if ((maVal[2]>maVal[1]) && (maVal[1]>maVal[0]) && (cprc<maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   return(check);
}

この関数はオープンポジションを変更することができるか条件を確認するのに使われます。オーダータイプ名と前回バーの終値を入力パラメータとして使います。

移動平均値が上向きに増加して、前回バーの終値がその時点での移動平均よりまだ大きく、ADX値もまた要求される最低値(買いポジションへの)より大きいか、一方移動平均値がまだ下向きに減少して、前回バーの終値がその時点(売りポジション)での移動平均より低いかという確認をします。条件が満たされれば、ポジションタイプに応じてEAはポジションの変更を考えます。

関数は2つの入力パラメータを取ります。( ポジション名、買いまたは売りと、 前回バーの終値です。)</s2>


2.1.8. Modify関数

//+------------------------------------------------------------------+
//| Modifies an open position                                        |
//+------------------------------------------------------------------+
   void Modify(string ptype,double stpl,double tkpf)
     {
       //--- New Stop Loss, new Take profit, Bid price, Ask Price
      double ntp,nsl,pbid,pask;                  
      long tsp=Trail_point;
       //--- adjust for 5 & 3 digit prices
      if(_Digits==5 || _Digits==3) tsp=tsp*10;   
       //--- Stops Level
      long stplevel= mysymbol.StopsLevel();      
       //--- Trail point must not be less than stops level
      if(tsp<stplevel) tsp=stplevel;
      if(ptype=="BUY")
        {
          //--- current bid price
         pbid=mysymbol.Bid();           
         if(tkpf-pbid<=stplevel*_Point)
           {
            //--- distance to takeprofit less or equal to Stops level? increase takeprofit
            ntp = pbid + tsp*_Point;
            nsl = pbid - tsp*_Point;
           }
         else
           {
            //--- distance to takeprofit higher than Stops level? dont touch takeprofit
            ntp = tkpf;
            nsl = pbid - tsp*_Point;
           }
        }
      else //--- this is SELL
        {
          //--- current ask price
         pask=mysymbol.Ask();            
         if(pask-tkpf<=stplevel*_Point)
           {
            ntp = pask - tsp*_Point;
            nsl = pask + tsp*_Point;
           }
         else
           {
            ntp = tkpf;
            nsl = pask + tsp*_Point;
           }
        }
      //--- modify and check result
      if(mytrade.PositionModify(_Symbol,nsl,ntp))  
        {
          //--- Request successfully completed    
         Alert("An opened position has been successfully modified!!");
         return;
        }
      else
        {
         Alert("The position modify request could not be completed - error: ",
               mytrade.ResultRetcodeDescription());
         return;
        }

     }

この関数は上記の関数 (checkmodify) に仕事をさせます。CSymbolInfoクラスとCTradeクラスのオブジェクトを使います。まず、新しいテイクプロフィット、ストップロス、bid価格、ask価格を保持するために4つのダブルデータタイプを宣言します。入力パラメータセクションで設定したTrail_point値を保持するため、新規のロングデータタイプtsp を宣言します。

トレールポイント値(tsp) は5桁および 3桁の価格に調整されます。それからCSymbolInfoオブジェクトを使用し、stops level追加したいトレールポイントが要求されるストップレベルを下回らないのを確認します。ストップレベルを下回ると、ストップレベル値を使うことになります。

ポジションタイプに応じてCSymbolInfoクラスオブジェクトを使用し、現在BIDまたはASK価格を取得することになるでしょう。現在のIDまたはASK価格と初期値のテイクプロフィット価格の差がストップレベルより低いか同じであったら、ストップレベルおよびテイクプロフィットの両方を調整します。そうでなければ、ストップロス値のみ調整します。

それから、CTradeクラスオブジェクトを使用しポジションに応じてストップロスとテイクプロフィットを変更します。トレード結果返しコードをもとに、成功または失敗メッセージも表示されます。

仕事を簡単にするユーザー定義関数の定義が終わりました。 EAコードに進んでいきます。


2.1.9. OnInitセクション

//--- set the symbol name for our SymbolInfo Object
   mysymbol.Name(_Symbol);
// Set Expert Advisor Magic No using our Trade Class Object
   mytrade.SetExpertMagicNumber(EA_Magic);
// Set Maximum Deviation using our Trade class object
   mytrade.SetDeviationInPoints(dev);
//--- Get handle for ADX indicator
   adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
   maHandle=iMA(_Symbol,Period(),MA_Period,0,MODE_EMA,PRICE_CLOSE);
//--- What if handle returns Invalid Handle
   if(adxHandle<0 || maHandle<0)
     {
      Alert("Error Creating Handles for MA, ADX indicators - error: ",GetLastError(),"!!");
      return(1);
     }
   STP = StopLoss;
   TKP = TakeProfit;
//--- Let us handle brokers that offers 5 or 3 digit prices instead of 4
   if(_Digits==5 || _Digits==3)
     {
      STP = STP*10;
      TKP = TKP*10;
     }
   
//--- Set trade percent
    TPC = TradePct;
    TPC = TPC/100;
//---

CSymbolInfoクラスオブジェクトについて現在のシンボル設定を決定しました。また、 CTradeクラスオブジェクトを使用しExpert Advisorのマジックナンバーと偏差(ポイント表記) を設定しました。このあと、インディケータ用のハンドルを決め、ハンドルが失敗の場合エラー表示をします。

次に、ストップロスとテイクプロフィットを3桁と5桁の価格に調整し、トレードに使うため、パーセンテージ表記でないフリーアカウントマージンをパーセンテージに変換します。


2.1.10. OnDeinitセクション

//--- Release our indicator handles
   IndicatorRelease(adxHandle);
   IndicatorRelease(maHandle);

すべてのインディケータハンドルを解放します。


2.1.11. OnTickセクション

//--- check if EA can trade
    if (checkTrading() == false) 
   {
      Alert("EA cannot trade because certain trade requirements are not meant");
      return;
   }
//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
/*
     Let's make sure our arrays values for the Rates, ADX Values and MA values 
     is store serially similar to the timeseries array
*/
// the rates arrays
   ArraySetAsSeries(mrate,true);
// the ADX values arrays
   ArraySetAsSeries(adxVal,true);
// the MA values arrays
   ArraySetAsSeries(maVal,true);
// the minDI values array
   ArraySetAsSeries(minDI,true);
// the plsDI values array
   ArraySetAsSeries(plsDI,true);

ここで最初にするのは、EAがトレードを行うか行わないかの確認です。checktrade関数がfalseを返したら、EAは次のティックまで待ち、再び確認をします。

このあと、各バーの価格を取得するためMQL5 MqlRatesストラクチャ宣言を行い、 要求される配列をすべて設定するため ArraySetAsSeries関数を使います。

//--- Get the last price quote using the SymbolInfo class object function
   if (!mysymbol.RefreshRates())
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }

//--- Get the details of the latest 3 bars
   if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      return;
     }

//--- EA should only check for new trade if we have a new bar
// lets declare a static datetime variable
   static datetime Prev_time;
// lest get the start time for the current bar (Bar 0)
   datetime Bar_time[1];
   //copy the current bar time
   Bar_time[0] = mrate[0].time;
// We don't have a new bar when both times are the same
   if(Prev_time==Bar_time[0])
     {
      return;
     }
//Save time into static varaiable, 
   Prev_time = Bar_time[0];

CSymbolInfoクラスを使い、現在価格のクオートを取得します。それからmrates配列に現在バー価格をコピーします。このすぐあとに、新規バーがあるか確認を行います。

新規バーがあればわれわれのEAは買いまたは売り条件が満たされているか確認に進み、そうでなければ新規バーが現れるまで待ちます。

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(adxHandle,0,0,3,adxVal)<3 || CopyBuffer(adxHandle,1,0,3,plsDI)<3
      || CopyBuffer(adxHandle,2,0,3,minDI)<3)
     {
      Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(maHandle,0,0,3,maVal)<3)
     {
      Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
      return;
     }
//--- we have no errors, so continue
// Copy the bar close price for the previous bar prior to the current bar, that is Bar 1

   p_close=mrate[1].close;  // bar 1 close price

ここでは、CopyBuffer関数によってインディケータバッファを配列に取得します。処理中にエラーが発生するとそれが表示されます 前回バーの終値がコピーされます。

//--- Do we have positions opened already?
  bool Buy_opened = false, Sell_opened=false; 
   if (myposition.Select(_Symbol) ==true)  // we have an opened position
    {
      if (myposition.Type()== POSITION_TYPE_BUY)
       {
            Buy_opened = true;  //It is a Buy
          // Get Position StopLoss and Take Profit
           double buysl = myposition.StopLoss();      // Buy position Stop Loss
           double buytp = myposition.TakeProfit();    // Buy position Take Profit
           // Check if we can close/modify position
           if (ClosePosition("BUY",p_close)==true)
             {
                Buy_opened = false;   // position has been closed
                return; // wait for new bar
             }
           else
           {
              if (CheckModify("BUY",p_close)==true) // We can modify position
              {
                  Modify("BUY",buysl,buytp);
                  return; // wait for new bar
              }
           } 
       }
      else if(myposition.Type() == POSITION_TYPE_SELL)
       {
            Sell_opened = true; // It is a Sell
            // Get Position StopLoss and Take Profit
            double sellsl = myposition.StopLoss();    // Sell position Stop Loss
            double selltp = myposition.TakeProfit();  // Sell position Take Profit
             if (ClosePosition("SELL",p_close)==true)
             {
               Sell_opened = false;  // position has been closed
               return;   // wait for new bar
             }
             else
             {
                 if (CheckModify("SELL",p_close)==true) // We can modify position
                 {
                     Modify("SELL",sellsl,selltp);
                     return;  //wait for new bar
                 }
             } 
       }
    }

CPositionInfoクラスオブジェクトを使用し、使用中のシンボルについてオープンポジションがあるか選択し確認します。存在したら、それは「買い」で、Buy_openedをtrueに設定し、CPositionInfoクラスオブジェクトを使用し、 ポジションのストップロスおよび and テイクプロフィットを得ます。関数によって先にClosePositionを定義しました。それでポジションがクローズ可能であるかチェックします。関数がtrueを返したら、ポジションはクローズしました。そこでBuy_openedをfalseに設定すると、初期の「買い」ポジションはクローズとなります。EA は新規ティックを待ちます。

ただし、関数がfalseを返しても、ポジションはまだクローズにはなっていません。では、ポジションを変更できるか確認します。以前に定義したCheckModify関数を使って行います。関数がtrueを返したら、ポジションは変更可能です。よってModify 関数を使用し、ポジション変更を行います。

一方、ポジションが存在し、それが「売り」であれば、Sell_opened をtrue に設定し、CPositionInfoクラスオブジェクトを使用し、ポジションのストップロスとテイクプロフィットを取得します。ポジションがクローズできるか、また変更できるか見るために「買い」ポジションと同じ手順を繰り返しました。

      if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);                //--- latest ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           {
               //--- Request is completed or order placed
             Alert("A Buy order has been successfully placed with deal Ticket#:",
                  mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                  ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                  ", price:", mytrade.RequestPrice(), 
                     " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

またはPositionOpen関数の使用が可能です。

if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- latest Ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         //if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
           {
              //--- Request is completed or order placed            
              Alert("A Buy order has been successfully placed with deal Ticket#:",
            mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

ここで、checkbuy関数を使い、 買いステップの確認とtrueを返すか、「買い」トレード条件は満たされているか確認します。すでに「買い」ポジションにあれば、新規注文は出しません。そしてCSymbolInfoクラスオブジェクトを使用し、現在のASK価格を取得し、要求どおりにストップロスとテイクプロフィットを計算します。

また、ConfirmMargin関数を使用し、発注を許されているアカウントのパーセンテージがこの発注の要求されるマージンよりも大きいか確認します。この関数trueを返したら、先に進み、トレードを行います。それ以外ならトレードは行いません。

CTradeクラスオブジェクトを使用し、発注をし同じコールによってトレード処理リターンコードを取得します。トレード結果に基づき、メッセージが表示されます。

if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
               //---Request is completed or order placed            
               Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }

        }

またはPositionOpen関数の使用が可能です。

if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         //if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
             //---Request is completed or order placed            
             Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(),
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                 ", price:", mytrade.RequestPrice(), 
                   " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

「買い」と同じようにChecksell関数を使い、売りの設定も確認します。true を返したら、すでにオープンしている売りポジションはなく、ConfirmMargin関数を使って、注文をオープンするのに十分な資金があるか確認します。 ConfirmMarginが trueを返したら、CTradeクラスオブジェクトを使用し、発注し、トレードサーバーからの応答に基づき、CTradeクラスオブジェクト関数を用いて、トレード結果が表示されます。

ここまで、Expert Advisorを書く中でのトレードクラスライブラリの使用法を見てきました。次は、ストラテジーテスタを用いてExpert Advisorを検証し、パフォーマンスを確認します。

EAコードをコンパイルし、ストラテジーテスタにロードします。

EAのコンパイルレポート

図3 Expert Advisorコンパイルレポート

GBPUSD日次チャートでは、初期設定を使って テイクプロフィット- 270、ストップロス - 100 、トレールポイント(TP/SL) - 32、 下記の結果を得ました。

図4 Expert Advisorテストレポート - GBPUSD 日次チャート

図5 Expert Advisor テストグラフ結果- GBPUSD日次チャート

図6 Expert Advisor検証レポートはオープンポジションの変更を示しています。 - GBPUSD日次チャート


図7 GBPUSD日次チャートのExpert Advisorテストチャートレポート

テイクプロフィット、ストップロス、トレールポイントの設定を変えて他のシンボルについての日次チャートでEAのテストを自由にやって、どんな結果が出るかみてみてください。

ただし、このExpert Advisorはテスト目的のみで書かれていることを理解する必要があります。

注文/取引詳細を得るため、その他のクラスの使い方を見てみましょう。 (COrderInfoCHistoryOrderInfoCDealInfo)


2.2 指値注文のオープン/削除

この例では、買いまたは売り設定条件がそれぞれみたされているとき、指値注文(BuyStop or SellStop)を出すExpert Advisorを書きます。


2.2.1. 求められるクラスのインクルード

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>
//--- The OrderInfo Class
#include <Trade\OrderInfo.mqh>

今回のExpert Advisor例で使用する4つのクラスをインクルードしました。それは上記の例で説明されています。

すでに説明されているものと同様なので、このExpert Advisorのセクションをひとつひとつ説明することはしませんが、ただ本項で述べようとしているものは何かを説明しようとするExpert Advisorの基本部分はすべて見ていきたいと思います。

ただ一つ異なる点はグローバルスコープでMqlRates mrate[]を宣言することです。

//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];     // To be used to store the prices, volumes and spread of each bar

クラスをインクルードしたら、また各クラスのオブジェクトを作成することを忘れてはいけません。

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The CTrade Class Object
CTrade mytrade;
//--- The CPositionInfo Class Object
CPositionInfo myposition;
//--- The CSymbolInfo Class Object
CSymbolInfo mysymbol;
//--- The COrderInfo Class Object
COrderInfo myorder;

CheckBuy()関数およびCheckSell()関数は先に説明したExpert Advisorと同じです。

ここでしたいのは、買いの設定があるときはBUYSTOPを出し、売りの 設定があるときはSELLSTOPを出すことです。

では、ことが簡単に運ぶよう作成した関数を見ていきます。


2.2.2 CountOrders関数

//+------------------------------------------------------------------+
//|  Count Total Orders for this expert/symbol                             |
//+------------------------------------------------------------------+
int CountOrders()
  {
   int mark=0;

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol) mark++;
        }
     }
   return(mark);
  }

この関数はその時点で可能な指値注文情報をを取得するのに使われます。

myorder.Select()関数により問題なく選択されたらCOrderInfoクラスのオブジェクトを用いて注文詳細情報をチェックします。

クラスオブジェクトによりマジックが返され、返されたシンボルが望むものであったらExpert Advisorにより注文が出されます。そして、数を数えられ、mark変数に保管されます。


2.2.3 DeletePending

//+------------------------------------------------------------------+
//| Checks and Deletes a pending order                                |
//+------------------------------------------------------------------+
bool DeletePending()
  {
   bool marker=false;
//--- check all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol)
           {
            //--- check if order has stayed more than two bars time
            if(myorder.TimeSetup()<mrate[2].time)
              {
               //--- delete this pending order and check if we deleted this order successfully?
                if(mytrade.OrderDelete(myorder.Ticket())) //Request successfully completed 
                  {
                    Alert("A pending order with ticket #", myorder.Ticket(), " has been successfully deleted!!");
                    marker=true;
                  }
                 else
                  {
                    Alert("The pending order # ",myorder.Ticket(),
                             " delete request could not be completed - error: ",mytrade.ResultRetcodeDescription());
                  }

              }
           }
        }
     }
   return(marker);
  }

カウントオーダー関数のようにこの関数もCOrderInfoクラス関数を用いてオーダープロパティを取得するのに使われます。関数が以前に3つのバーを設定し、まだ始動していない指値注文を確認します。

その分類に何か注文が入ったらCTradeのクラス関数であるOrderDeleteにより注文を削除します。この関数は成功のときはtrueを、そうでなければfalseを返します。

上記2つの関数は新規バーが形成された後すぐ、新規取引設定を確認する前に使われます。それぞれの時点で3つ以上の指値注文は出さないことを徹底します。そのため、以下のコードを作成します。

// do we have more than 3 already placed pending orders
if (CountOrders()>3) 
  {
     DeletePending(); 
     return;  
  }

2.2.4 指値注文出し

if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
               ", price:", mytrade.RequestPrice(), 
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

または、BUYSTOP注文を出すには、OrderOpen関数も使用可能です。

if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      //if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
              ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

ここでのBUYSTOP注文を出すにあたり、始値はBar 1 High + 2pip + spreadとなります。

チャートに示されているのはBID価格であり、ロング買い注文には ASK価格が必要です。そのためBar 1 Highにスプレッドを追加し、それに対応して今Ask price + 2pipであることを記憶ください。ストップロスとテイクプロフィットもまた入力パラメータで確定されます。

必要なパラメータをすべて準備したら、注文を出すためにCTradeクラス関数、BuyStopまたはOrderOpenを使用します。ここでのオーダータイプはORDER_TYPE_BUY_STOP (Buy Stop注文)です。制限価格に同じ価格を使用しますが、これはBuyLimit 注文ではありません。また、注文の残り有効期限をキャンセルする、を意味するORDER_TIME_GTCにる注文有効期限を設定します。

ORDER_TIME_GTCまたは ORDER_TIME_DAYを使用すると、有効期限を指定する必要はありません。そのためわれわれは有効期限0に設定します。

if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

また、注文を出すのにOrderOpen関数を使います。

if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      //if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
                ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
              " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

BuyStop注文とちょうど同じで始値はBar 1 low + 2pipです。通常、ショート売り注文を出すためにBID価格が必要なので、ここではスプレッドを追加する必要はありません。

SellStop Orderを出すには同じOrderOpen関数かSellStop関数を使います。ここでのオーダータイプはORDER_TYPE_SELL_STOP (売りストップ注文)です。

以下は今回のシンプルなExpert Advisorの結果です。

図8 指値注文EAの検証レポート

図9 EAのグラフレポート

図10 EAのチャートレポート


2.3注文または取引の詳細情報入手

今回の例では、注文が出されたらどのようにして詳細情報を得るかを見ていきます。

この段階では、指値注文は処理され取引に変換されているのでもうありません。

この手順を完全に理解するために、取引のひとつのジャーナルを見てみます。

注文処理手順

図11 注文処理手順

  • ステップ 1:条件が満たされるのを待って指値注文が出されます。(指値注文)
  • ステップ 2:条件が満たされ、指値注文が実行されます。そして注文は取引になります(指値注文は今履歴に入っています)。
  • ステップ 3: 取引きは処理され、オープンポジションを得ました。(取引きは今履歴に入っています)


2.3.1. オーダープロパティ(履歴)の取得

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\HistoryOrderInfo.mqh>
//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECT                                             |
//+------------------------------------------------------------------+
//--- The HistoryOrderInfo Class Object
CHistoryOrderInfo myhistory;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all orders in History and get their details
   int buystop=0;
   int sellstop=0;
   int buylimit=0;
   int selllimit=0;
   int buystoplimit=0;
   int sellstoplimit=0;
   int buy=0;
   int sell=0;

   int s_started=0;
   int s_placed=0;
   int s_cancelled=0;
   int s_partial=0;
   int s_filled=0;
   int s_rejected=0;
   int s_expired=0;

   ulong o_ticket;
// Get all history records
   if(HistorySelect(0,TimeCurrent())) // get all history orders
     {
      // Get total orders in history
      for(int j=HistoryOrdersTotal(); j>0; j--)
        {
         // select order by ticket
         o_ticket=HistoryOrderGetTicket(j);
         if(o_ticket>0)
           {
            // Set order Ticket to work with
            myhistory.Ticket(o_ticket);
            Print("Order index ",j," Order Ticket is: ",myhistory.Ticket()," !");
            Print("Order index ",j," Order Setup Time is: ",TimeToString(myhistory.TimeSetup())," !");
            Print("Order index ",j," Order Open Price is: ",myhistory.PriceOpen()," !");
            Print("Order index ",j," Order Symbol is: ",myhistory.Symbol() ," !");
            Print("Order index ",j," Order Type is: ", myhistory.Type() ," !");
            Print("Order index ",j," Order Type Description is: ",myhistory.TypeDescription()," !");
            Print("Order index ",j," Order Magic is: ",myhistory.Magic()," !");
            Print("Order index ",j," Order Time Done is: ",myhistory.TimeDone()," !");
            Print("Order index ",j," Order Initial Volume is: ",myhistory.VolumeInitial()," !");
            //
            //
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP) buystop++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP) sellstop++;
            if(myhistory.Type() == ORDER_TYPE_BUY) buy++;
            if(myhistory.Type() == ORDER_TYPE_SELL) sell++;
            if(myhistory.Type() == ORDER_TYPE_BUY_LIMIT) buylimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_LIMIT) selllimit++;
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP_LIMIT) buystoplimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP_LIMIT) sellstoplimit++;

            if(myhistory.State() == ORDER_STATE_STARTED) s_started++;
            if(myhistory.State() == ORDER_STATE_PLACED) s_placed++;
            if(myhistory.State() == ORDER_STATE_CANCELED) s_cancelled++;
            if(myhistory.State() == ORDER_STATE_PARTIAL) s_partial++;
            if(myhistory.State() == ORDER_STATE_FILLED) s_filled++;
            if(myhistory.State() == ORDER_STATE_REJECTED) s_rejected++;
            if(myhistory.State() == ORDER_STATE_EXPIRED) s_expired++;
           }
        }
     }
// Print summary
   Print("Buy Stop Pending Orders : ",buystop);
   Print("Sell Stop Pending Orders: ",sellstop);
   Print("Buy Orders : ",buy);
   Print("Sell Orders: ",sell);
   Print("Total Orders in History is :",HistoryOrdersTotal()," !");
   
   Print("Orders type summary");
   Print("Market Buy Orders: ",buy);
   Print("Market Sell Orders: ",sell);
   Print("Pending Buy Stop: ",buystop);
   Print("Pending Sell Stop: ",sellstop);
   Print("Pending Buy Limit: ",buylimit);
   Print("Pending Sell Limit: ",selllimit);
   Print("Pending Buy Stop Limit: ",buystoplimit);
   Print("Pending Sell Stop Limit: ",sellstoplimit);
   Print("Total orders:",HistoryOrdersTotal()," !");

   Print("Orders state summary");
   Print("Checked, but not yet accepted by broker: ",s_started);
   Print("Accepted: ",s_placed);
   Print("Canceled by client: ",s_cancelled);
   Print("Partially executed: ",s_partial);
   Print("Fully executed: ",s_filled);
   Print("Rejected: ",s_rejected);
   Print("Expired: ",s_expired);
  }

履歴レコードの注文詳細情報の取得方法を示す簡単なスクリプトですCHistoryOrderInfoクラスをインクルードし、クラスオブジェクトを作成します。

注文詳細情報を得るため、このオブジェクトを使用します。

履歴注文スクリプトの結果

図12 履歴注文スクリプトの結果


2.3.2. 取引きプロパティ(履歴)の取得

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The CDealInfo Class
#include <Trade\DealInfo.mqh>
//+------------------------------------------------------------------+
//|  Create class object                                             |
//+------------------------------------------------------------------+
//--- The CDealInfo Class Object
CDealInfo mydeal;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all deals in History and get their details
    int buy=0;
    int sell=0;
    int deal_in=0;
    int deal_out=0;
    ulong d_ticket;
    // Get all history records
    if (HistorySelect(0,TimeCurrent())) 
    {
      // Get total deals in history
      for (int j=HistoryDealsTotal(); j>0; j--)
      {
         // select deals by ticket
         if (d_ticket = HistoryDealGetTicket(j))
         {
          // Set Deal Ticket to work with
          mydeal.Ticket(d_ticket);
          Print("Deal index ", j ," Deal Ticket is: ", mydeal.Ticket() ," !");
          Print("Deal index ", j ," Deal Execution Time is: ", TimeToString(mydeal.Time()) ," !");
          Print("Deal index ", j ," Deal Price is: ", mydeal.Price() ," !");
          Print("Deal index ", j ," Deal Symbol is: ", mydeal.Symbol() ," !");
          Print("Deal index ", j ," Deal Type Description is: ", mydeal.TypeDescription() ," !");
          Print("Deal index ", j ," Deal Magic is: ", mydeal.Magic() ," !");
          Print("Deal index ", j ," Deal Time is: ", mydeal.Time() ," !");
          Print("Deal index ", j ," Deal Initial Volume is: ", mydeal.Volume() ," !");
          Print("Deal index ", j ," Deal Entry Type Description is: ", mydeal.EntryDescription() ," !");
          Print("Deal index ", j ," Deal Profit is: ", mydeal.Profit() ," !");
          //
          if (mydeal.Entry() == DEAL_ENTRY_IN) deal_in++;
          if (mydeal.Entry() == DEAL_ENTRY_OUT) deal_out++;
          if (mydeal.Type() == DEAL_TYPE_BUY) buy++;
          if (mydeal.Type() == DEAL_TYPE_SELL) sell++;
         }
      }
    }
    // Print Summary
    Print("Total Deals in History is :", HistoryDealsTotal(), " !");
    Print("Total Deal Entry IN is : ", deal_in);
    Print("Total Deal Entry OUT is: ", deal_out);
    Print("Total Buy Deal is : ", buy);
    Print("Total Sell Deal is: ", sell);
  }

履歴レコードの取引き詳細情報の取得方法を示す簡単なスクリプトです。

取引きスクリプトの結果

図13 取引きスクリプトの結果


おわりに

本項では、標準的なトレードクラスライブラリの主要な関数に目を通し、ポジション変更、指値注文出し、取引きをセットする前のマージン削除と確定を実装するExpert Advisorsを各のに使用可能は関数の使い方を示しました。

また、注文および取引詳細を取得するのにそれらを使う方法もお見せしました。使用するトレーディング戦略によって、Expert Advisorを書いていく上で使用しなかった関数もあります。ですが、だいたい今回の例で使用したような関数を使っていくと思います。

関数についての項目を改定し、ご自身でExpert Advisorを書く際にどのように利用できるか確認するのは良いことだと思います。

標準クラスライブラリはトレーダー、開発者両者を楽にしてくれます。ぜひご活用ください。

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/138

Expert Advisor動作中のバランス曲線勾配調整 Expert Advisor動作中のバランス曲線勾配調整
トレードシステムのルールを見つけ、それをExpert Advisorにプログラムするのが仕事の半分です。Expert Advisorはトレーディング結果を集積するので、いくらかの処理を修正する必要があります。本項では、バランス曲線の勾配測定のフィードバックを作成することで、Expert Advisorのパフォーマンスを向上させる方法の一つについて述べます。
プロフィット引き出しモデル構築のためのTesterWithdrawal() 関数の使用 プロフィット引き出しモデル構築のためのTesterWithdrawal() 関数の使用
本稿は処理中に資産の特定部分の引き出しをするトレードシステムにおけるリスク見積をするためのTesterWithDrawal()関数使用について述べていきます。また、ストラテジーテスタにおける資産の引き出し計算のアルゴリズムへのこの関数の影響についても述べます。この関数はExpert Advisorsのパラメータ最適化に有用です。
自動トレーディングシステム選手権2010に向けたExpert Advisor迅速作成法 自動トレーディングシステム選手権2010に向けたExpert Advisor迅速作成法
自動トレーディングシステム選手権2010に参加するためのエクスパート開発をめざし、すぐに使えるExpert Advisorテンプレートを使用します。Even novice MQL5プログラマの初心者でもこのタスクをこなすことは可能です。というのも戦略のために基本クラス、関数、テンプレートがすでに準備されているからです。よってみなさんのトレーディングの考えに合う最低限のコードを書いて実装すれば十分です。
指定されたマジックナンバーによるトータルポジションボリューム計算のための最適化された手法 指定されたマジックナンバーによるトータルポジションボリューム計算のための最適化された手法
本稿では指定されたシンボルのトータルポジションボリューム計算とマジックナンバーに関する問題について考察します。提案する手法では取引履歴の最小限を要求し、トータルポジションがゼロに最も近い時刻を見つけ、最近の取引についての計算を行います。クライアント端末のグローバル変数による作業も考察します。