EAの設計:ポジションのオープンオーダー

 

 

EA利用時の買い注文、売り注文のオーダー関数の例です。

 

まず、新規注文に関するOrderSend関数のMQL4リファレンスは次となります。

OrderSend - Trade Functions - MQL4 Reference

また、MQL5の場合、文法が違うので、そちらに合わせて設定する必要があります。

MQL5のドキュメンテーション: 取引関数 / OrderSend

 

一方、僕のこのOpenOrder関数はMQL4のOrderSend関数についての利用だけではなく、より実践的な構成となっています。下記の機能を追加しています。

・注文タイプのチェック
・処理のエラーチェック
・通信エラー発生時のリトライ、カウンターの設定
・処理後のログ出力
・処理結果のメール送信連絡 ※設定方法に関しては別記事

もちろん、必要に応じてアレンジして利用しても良いです。また、指標値を自らのものにするのもおすすめです。ここでは設計観点を提供します。

stopLossAvailable、takeProfitAvailableなどの変数は必要に応じて設定か削除かご調整してください。指値注文しなければ、これら必要ないからです。また、指値注文の場合、openPriceを自らのアルゴリズムに合わせて設定しましょう。

int OpenOrder(const int orderType, const double lots, const color arrowColor)
{
    Print("OpenOrder start : ", orderType, " ", lots);
    
    if ((orderType != OP_BUY) && (orderType != OP_SELL))
        Print(__ERROR__, __FUNCTION__, ", Order type error, orderType:", orderType, " Line:", __LINE__);
    
    double stopLoss = 0;
    double takeProfit = 0;
    double openPrice = 0;
    int ticket = -1;
    int count = 0;
    
    while (count < ORDER_ERROR_RETRY_COUNT) 
    { 
        openPrice = 0; 

        if (orderType == OP_BUY) 
            openPrice = MarketInfo(symbol, MODE_ASK); 
        else 
            openPrice = MarketInfo(symbol, MODE_BID); 
        
        if (stopLossAvailable)
        { 
            if (orderType == OP_BUY) 
                stopLoss = openPrice - stopLossPips * pipsPoint; 
            else 
                stopLoss = openPrice + stopLossPips * pipsPoint; 
        } 
        
        if (takeProfitAvailable) 
        { 
            if (orderType == OP_BUY) 
                takeProfit = openPrice + takeProfitPips * pipsPoint; 
            else 
                takeProfit = openPrice - takeProfitPips * pipsPoint; 
         } 
        
        if (openPrice > 0)
        {
            ticket = OrderSend(symbol, orderType, Common_VerifyLotSize(lots), openPrice, orderSlippage, stopLoss, takeProfit, NULL, magicNumber, 0, arrowColor);
            
            if (ticket > 0) break;
        }
        else
        {
            ResetLastError();
            Print(__ERROR__, __FUNCTION__, ", Get open price error.", " Line:", __LINE__);
        }
        
        count++;
        
        if (IsTradeContextBusy()) Sleep(1000); // 1000 ms.
    }
	
    if (ticket < 0)
    {
        int lastError       = GetLastError();
        string errorDesc    = ErrorDescription(lastError);
        string errorAlert   = StringConcatenate(__ERROR__, __FUNCTION__, ", Open order error:", lastError, " ", errorDesc);
        string errorLog     = StringConcatenate(errorAlert, " order type: ", IntegerToString(orderType), " lot size:", DoubleToStr(lots, Digits), " Line:", __LINE__);
        
        Print(errorLog);
        Alert(errorLog);
        SendMail("Open order Error.", errorLog);
        Print(__FUNCTION__, ", Mail send. Line:", __LINE__);
        
        ResetLastError();
    }
    else
    {
        // Real trade mode.
        if (!isTesting)
        {
            string openMsg = "Open order\n";
            openMsg = openMsg + "Loss cut level:"   + IntegerToString(Common_GetCurrentLossCutLevel()) + "\n";
            openMsg = openMsg + "Equity:"           + DoubleToStr(AccountEquity(), 0) + "\n";
            openMsg = openMsg + "Symbol:"           + StringSubstr(symbol, 0, 6) + "\n";
            openMsg = openMsg + "Type:"             + getOrderTypeString(orderType) + "\n";
            openMsg = openMsg + "Lots:"             + DoubleToStr(lots, 2) + "\n";
            openMsg = openMsg + "OpenPrice:"        + DoubleToStr(NormalizeDouble(openPrice, Digits), Digits) + "\n";
            openMsg = openMsg + "StopLoss:"         + DoubleToStr(NormalizeDouble(stopLoss, Digits), Digits) + "\n";
            openMsg = openMsg + "TakeProfit:"       + DoubleToStr(NormalizeDouble(takeProfit, Digits), Digits) + "\n";
            openMsg = openMsg + "MagicNumber:"      + IntegerToString(magicNumber) + "\n";
            openMsg = openMsg + "Time:"             + Common_GetTimeString(TimeCurrent());
            Print(openMsg);

            SendMail("Open order OK.", openMsg);
            Print(__FUNCTION__, ", Mail send. Line:", __LINE__);
        }
    }
    
    Print("OpenOrder end.");
    
    return ticket;
}

 

エラー状態の取得関数GetLastError、エラー内容の出力関数ErrorDescriptionの説明などを別の記事に紹介していきます。

 

そして上記の関数の呼び出し例は次のもので良いでしょう。

次の例では、注文の前に、注文のタイプと注文のビジー状態、資金状況の確認を行なっています。

int Common_OpenNewPosition(const int orderType, const double lotSize) export
{
    Print("OpenNewPosition start : ", orderType, " ", lotSize);
    
    if ((orderType != OP_BUY) && (orderType != OP_SELL))
        Print(__ERROR__, __FUNCTION__, ", Order type error, orderType:", orderType, " Line:", __LINE__);

    while (IsTradeContextBusy()) Sleep(1000);

    int ticket = EMPTY_DATA;
    
    if (orderType == OP_BUY || orderType == OP_SELL)
    {
        if ((AccountFreeMarginCheck(symbol, orderType, lotSize) <= 0) || (GetLastError() == 134))
        {
            Print(__ERROR__, __FUNCTION__,  ", No enough money to hold a new buy position!");
        }
        else
        {
            if (orderType == OP_BUY)
                ticket = OpenOrder(OP_BUY,  lotSize, Green);
            else
                ticket = OpenOrder(OP_SELL, lotSize, Magenta);
        }
    }

    Print("OpenNewPosition end.\n");
    return ticket;
}

 

コーディングスタイルは本家のMQLそのものではなく、今までの仕事上のC, Javaスタイルそのまま継続します。僕自身はなるべく整ったスタイルを継続しています。

 

EAファイルの作成の方法、関数の命名規格の設計などを別の記事をご参考ください。

FX

 

 

 

 

コメント

error: Content is protected !!
タイトルとURLをコピーしました