EAの設計:ポジションのクローズオーダー

 

 

買いまたは売りポジションを持ってたら、必ずいつか相反の操作でクローズして決済する必要があります。

 

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

OrderClose - Trade Functions - MQL4 Reference

 

また、MQL5の場合、OrderCloseがなく、そのままOrderSendを利用する必要があります。ただし、この場合、MqlTradeRequest構造体に設定するtypeを相反のタイプで指定しなければいけません。詳細を別の記事にします。

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

 

ここではMQL4でのOrderClose関数について、利用例を挙げます。

bool CloseOrder(const int orderType, const int ticket, const double lots, const double openPrice)
{
    Print("CloseOrder start : #", ticket, " ", orderType, " ", lots, " ", openPrice);
    
    if ((orderType != OP_BUY) && (orderType != OP_SELL))
        Print(__ERROR__, __FUNCTION__, ", Order type error, orderType:", orderType, " Line:", __LINE__);

    bool closed = false;
    int count = 0;
    double closePrice = 0;

    while (count < ORDER_ERROR_RETRY_COUNT) 
    { 
        closePrice = 0; 
        
        if (orderType == OP_BUY) 
            closePrice = MarketInfo(symbol, MODE_BID); 
        else 
            closePrice = MarketInfo(symbol, MODE_ASK); 
        
        if (closePrice > 0)
        {
            if (orderType == OP_BUY)
                closed = OrderClose(ticket, lots, closePrice, orderSlippage, Yellow);
            else
                closed = OrderClose(ticket, lots, closePrice, orderSlippage, Red);

            if (closed) break;
        }
        else
        {
            ResetLastError();
            Print(__ERROR__, __FUNCTION__, ", Get close price error.");
        }

        count++;
        
        if (IsTradeContextBusy()) Sleep(1000); // 1000 ms.
    }

    if (closed)
    {
        string closeMsg = "";
        if (!isTesting)
        {
            closeMsg = "Close order\n";
            closeMsg = closeMsg + "Loss cut level:" + IntegerToString(Common_GetCurrentLossCutLevel()) + "\n";
            closeMsg = closeMsg + "Equity:"         + DoubleToStr(AccountEquity(), 0) + "\n";
            closeMsg = closeMsg + "Symbol:"         + symbol + "\n";
            closeMsg = closeMsg + "Ticket:"         + IntegerToString(ticket) + "\n";
            closeMsg = closeMsg + "Type:"           + getOrderTypeString(orderType) + "\n";
            closeMsg = closeMsg + "Lots:"           + DoubleToStr(lots, 2) + "\n";
            closeMsg = closeMsg + "OpenPrice:"      + DoubleToStr(NormalizeDouble(openPrice, Digits), 0) + "\n";
            closeMsg = closeMsg + "ClosePrice:"     + DoubleToStr(NormalizeDouble(closePrice, Digits), 0) + "\n";
            if (orderType == OP_BUY)
                closeMsg = closeMsg + "PipPoint:"   + DoubleToStr(((closePrice-openPrice) * (1.0 / Common_GetPipFloat())), 1) + "\n";
            else
                closeMsg = closeMsg + "PipPoint:"   + DoubleToStr(((openPrice-closePrice) * (1.0 / Common_GetPipFloat())), 1) + "\n";
            closeMsg = closeMsg + "Profit:"         + DoubleToStr(OrderProfit() / (OrderLots() / lots), 0) + "\n"; // The real profit is [OrderProfit() + OrderSwap()].
            closeMsg = closeMsg + "Swap profit:"    + DoubleToStr(OrderSwap() / (OrderLots() / lots), 0) + "\n"; // And OrderProfit and OrderSwap can be minus both.
            closeMsg = closeMsg + "MagicNumber:"    + IntegerToString(magicNumber) + "\n";
            closeMsg = closeMsg + "OpenTime:"       + Common_GetTimeString(OrderOpenTime())+ "\n";
            closeMsg = closeMsg + "CloseTime:"      + Common_GetTimeString(TimeCurrent()) + "\n";
            Print(closeMsg + " Line:", __LINE__);

            SendMail("Close order OK.",closeMsg);
            Print(__FUNCTION__, ", Mail send. Line:", __LINE__);
        }
        else
        {
            closeMsg = closeMsg + "Ticket:"         + IntegerToString(ticket) + " ";
            closeMsg = closeMsg + "Type:"           + getOrderTypeString(orderType) + " ";
            closeMsg = closeMsg + "Lots:"           + DoubleToStr(lots, 2) + " ";
            closeMsg = closeMsg + "OpenPrice:"      + DoubleToStr(NormalizeDouble(openPrice, Digits), Digits) + " ";
            closeMsg = closeMsg + "ClosePrice:"     + DoubleToStr(NormalizeDouble(closePrice, Digits), Digits) + " ";
            if (orderType == OP_BUY)
                closeMsg = closeMsg + "PipPoint:"   + DoubleToStr(((closePrice-openPrice) * (1.0 / Common_GetPipFloat())), 1) + " ";
            else
                closeMsg = closeMsg + "PipPoint:"   + DoubleToStr(((openPrice-closePrice) * (1.0 / Common_GetPipFloat())), 1) + " ";
            closeMsg = closeMsg + "Profit:"         + DoubleToStr(OrderProfit() / (OrderLots() / lots), 0) + " "; // The real profit is [OrderProfit() + OrderSwap()].
            closeMsg = closeMsg + "Swap profit:"    + DoubleToStr(OrderSwap() / (OrderLots() / lots), 0) + " ";
            closeMsg = closeMsg + "OpenTime:"       + Common_GetTimeString(OrderOpenTime())+ " ";
            closeMsg = closeMsg + "CloseTime:"      + Common_GetTimeString(TimeCurrent());
            Print(closeMsg + " Line:", __LINE__);
        }

    }
    else
    {
        int lastError       = GetLastError();
        string errorDesc    = ErrorDescription(lastError);
        string errorAlert   = StringConcatenate(__ERROR__, __FUNCTION__,", Error:", lastError, " ", errorDesc);
        string errorLog     = StringConcatenate(errorAlert, " ticket: ", ticket, " lot size:", lots, " close price: ", closePrice);
        
        Print(errorLog, " Line:", __LINE__);
        Alert(errorLog, " Line:", __LINE__);
        SendMail("### Close order error.", errorLog);
        Print(__FUNCTION__, ", Mail send. Line:", __LINE__);
        
        ResetLastError();
    }

    Print("CloseOrder end.");

    return closed;
}

 

基本的にオープンオーダーと同じ使い方です。

一方、上記の関数の使い方について、幾つものシチュエーションも想定できるので、別記事で呼び出し方法を紹介します。

 

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

 

FX

コメント

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