恥は/dev/nullへ by 初心者

~ PC初心者による右往左往の記録 ~

MqlTradeRequest構造体(2)

目次


{ }で初期化した直後の状態

MqlTradeRequest構造体のフィールドの中には4つのENUM項目があります。
action、type、type_filling、type_timeの4つです。

ENUM_TRADE_REQUEST_ACTIONS    action;
ENUM_ORDER_TYPE               type;
ENUM_ORDER_TYPE_FILLING       type_filling;
ENUM_ORDER_TYPE_TIME          type_time;


MqlTradeRequest request = {};

と宣言 and 初期化すると、上記4フィールドは次のようになります。

request.action       = 0
request.type         = 0
request.type_filling = 0
request.type_time    = 0


「MqlTradeRequest構造体(1)」に書いたとおり、actionフィールドに入るenum定数の中には 0 に相当するものが無いので、現状では何も指定していないのと同じです。

一方、type、type_filling、type_timeには、以下のように 0 に相当するものがあります。

// ENUM_ORDER_TYPEに割り当てられている値
ORDER_TYPE_BUY             =  0
ORDER_TYPE_SELL            =  1
ORDER_TYPE_BUY_LIMIT       =  2
ORDER_TYPE_SELL_LIMIT      =  3
ORDER_TYPE_BUY_STOP        =  4
ORDER_TYPE_SELL_STOP       =  5
ORDER_TYPE_BUY_STOP_LIMIT  =  6
ORDER_TYPE_SELL_STOP_LIMIT =  7
ORDER_TYPE_CLOSE_BY        =  8


// ENUM_ORDER_TYPE_FILLINGに割り当てられている値
ORDER_FILLING_FOK    = 0
ORDER_FILLING_IOC    = 1
ORDER_FILLING_BOC    = 3
ORDER_FILLING_RETURN = 2


// ENUM_ORDER_TYPE_TIMEに割り当てられている値
ORDER_TIME_GTC           = 0
ORDER_TIME_DAY           = 1
ORDER_TIME_SPECIFIED     = 2
ORDER_TIME_SPECIFIED_DAY = 3


よって、request = {}で初期化した場合、

type         = ORDER_TYPE_BUY
type_filling = ORDER_FILLING_FOK
type_time    = ORDER_TIME_GTC

という状態になっています。

Execution Modeを調べる

MqlTradeRequest構造体の各フィールドのうち、必ず指定しなくてはならないフィールドはExecution Modeによって異なります。そこで、Execution Modeについて少し触れておきます。

Executionには次の4つがあります。

SYMBOL_TRADE_EXECUTION_REQUEST
SYMBOL_TRADE_EXECUTION_INSTANT
SYMBOL_TRADE_EXECUTION_MARKET
SYMBOL_TRADE_EXECUTION_EXCHANGE


(備考)文字数が多いので、以後「REQUEST」「INSTANT」「MARKET」「EXCHANGE」と表記します。

Execution Modeは自分で選べるものではありません。「使用しているFX業者」「通貨ペア」によって決まっています。Execution Modeを調べてみます。

void OnStart()
{
    ENUM_SYMBOL_TRADE_EXECUTION executionMode =
        (ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_EXEMODE);

    printf("Execution Mode = %s", EnumToString(executionMode));
}


上記スクリプトを実行したら、次のように表示されました。

Execution Mode = SYMBOL_TRADE_EXECUTION_MARKET


このことから、私が上記スクリプトを実行した通貨ペアのExecution Modeは「MARKET」だと分かります。

ちなみに、コードを使わなくてもExecution Modeを調べることは可能です。

「気配値表示」ウィンドウを右クリック → 「仕様」を選ぶ  →  [執行」欄を見る


Execution Modeごとの必須フィールド

ヘルプでMqlTradeRequestのページを見ると、各Execution Modeで必ず指定しなくてはならないフィールドは次のとおりです。

「MARKET」または「EXCHANGE」の場合

•action
•symbol
•volume
•type
•type_filling

「magic」や「comment」も指定可能


「REQUEST」または「INSTANT」の場合

•action
•symbol
•volume
•type
•type_filling
•price
•sl
•tp
•deviation

「magic」や「comment」も指定可能


しかし、MQL5.comにある表を見ると、Execution Modeが REQUESTやINSTANTの場合でも sl, tp, deviation は(必須ではなく)オプションになっています(はて?)。

// the table below is quoted from 
     https://www.mql5.com/en/book/automation/experts/experts_market_buy_sell

Field        |  Request    Instant     Exchange      Market
=============+===============================================
action       |     *          *           *           *
-------------+-----------------------------------------------
symbol       |     *          *           *           *
-------------+-----------------------------------------------
volume       |     *          *           *           *
-------------+-----------------------------------------------
type         |     *          *           *           *
-------------+-----------------------------------------------
type_filling |     *          *           *           *
-------------+-----------------------------------------------
price        |     *          *
-------------+-----------------------------------------------
sl           |     +          +           +           +
-------------+-----------------------------------------------
tp           |     +          +           +           +
-------------+-----------------------------------------------
deviation    |     +          +
-------------+-----------------------------------------------
magic        |     +          +           +           +
-------------+-----------------------------------------------
comment      |     +          +           +           +

* は必須フィールド、 + はオプションフィールド


priceフィールドとdeviationフィールド

Execution ModeがMARKETとEXCHANGEの場合、priceフィールドとdeviationフィールドは無視されますが、ソースコードを簡潔にするために、これらのフィールドに値をセットしてもよいとMQL5.comに書かれています。
つまり、Execution ModeがMARKETとEXCHANGEの場合、これらのフィールドに値を指定しても意味はないけれど、実害もありません。

<情報源>
https://www.mql5.com/en/book/automation/experts/experts_market_buy_sell

初めてMqlTradeRequest構造体を使った頃は、Execution ModeがREQUESTとINSTANTの場合に応じたif文を書いていました。たとえば、次のような感じです。

// Execution Modeを取得
ENUM_SYMBOL_TRADE_EXECUTION executionMode =
    (ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_EXEMODE);

MqlTradeRequest request = {};

request.action       = TRADE_ACTION_DEAL;
request.symbol       = _Symbol;
request.volume       = orderVolume;
request.type         = orderType;
request.type_filling = fillPolicy;
request.magic        = orderMagic;

//-------------------------------------------------------
// Execution modeが INSTANT または REQUESTの場合
//-------------------------------------------------------
if(executionMode == SYMBOL_TRADE_EXECUTION_INSTANT ||
   executionMode == SYMBOL_TRADE_EXECUTION_REQUEST    ) {

    request.sl        = slPrice;
    request.tp        = tpPrice;
    request.deviation = 10;
    request.price     = orderPrice;
}


しかし、Execution ModeがMARKETやEXCHANGEの場合にpriceやdeviationに値をセットしても実害がないのなら、次のように書けば済みます。

MqlTradeRequest request = {};

request.action       = TRADE_ACTION_DEAL;
request.symbol       = _Symbol;
request.volume       = orderVolume;
request.type         = orderType;
request.type_filling = fillPolicy;
request.magic        = orderMagic;
request.sl           = slPrice;
request.tp           = tpPrice;
request.deviation    = 10;
request.price        = orderPrice;

この方がすっきりしていて良いですね。

slフィールド、tpフィールドの注意点

MQL5.comによると、FX業者のサーバー設定によっては、新たなポジションを持つ時に、同時にSL(損切価格)やTP(利確価格)を指定することを禁止している場合があるそうです。

<情報源>
https://www.mql5.com/en/book/automation/experts/experts_market_buy_sell

この場合、slフィールドやtpフィールドに値を設定せずに注文を出し、(約定して)ポジションを持った後で、修正注文(SLの設定やTPの設定)を出すことになります。

ちなみに、「私が使っている業者ではどのようになっているのだろうか?」と思ったので、デモ口座を使って実験してみました。
成行買い注文を出すのと同時にSL・TPを送信したところ、問題なくSL・TPが設定されました。どうやら新規注文と同時にSL・TPを指定することは禁じられていないようです。

私の考えは次のとおりです。

<特定の業者だけを利用する場合>
新規注文時にSLやTPを送信して問題ないか実験する。
問題が無ければ、新規注文時にSLやTPを設定する。


<不特定多数の業者を利用する場合>
・新規注文時はslフィールドとtpフィールドは 0.0 にしておく。
・(約定して)ポジションを持ってから、そのポジションに対してSLやTPを設定する。