如何在利润增加时在止损和当前价格之间保持 10 点的利润差距

How to keep a 10 pip profit gap between stop loss and current price as profits increase

我正在尝试向 中的解决方案添加另一个条件。当交易获利 10 点时,我希望止损移动 10 点。更具体地说,假设我设置了挂单买单,止损比开盘价低 10 点,止盈为 50 点。如果交易盈利 10 点,则止损将向上移动 10 点,如果交易盈利 20 点,则止损将再向上移动 10 点,对于 30 和 40 点,止损将向上移动 30 和 40 点获利,直到达到 50 点止盈为止。这里的想法是当利润增加 10 点时止损增加 10 点,但止损不会下降。因此,如果止损位于获利 10 点,而价格位于获利 23 点并且突然下跌,它将在 10 点获利止损处退出交易。

设置上述条件对我来说似乎相当复杂。我一直没能完成它。

下面是我试图解决的代码的相关部分(请注意,其余代码与上面链接的问题解决方案相同)。

//=========================================================
    //CLOSE EXPIRED STOP/EXECUTED ORDERS
    //---------------------------------------------------------
    for( int i=OrdersTotal()-1; i>=0; i-- ) {
        if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
            if( OrderSymbol() == Symbol() )
                if( OrderMagicNumber() == viMagicId) {
                    if( (OrderType() == OP_BUYSTOP) || (OrderType() == OP_SELLSTOP) )
                        if((TimeCurrent()-OrderOpenTime()) >= viDeleteStopOrderAfterInSec)
                            OrderDelete(OrderTicket());

                    if( (OrderType() == OP_BUY) || (OrderType() == OP_SELL) )
                        if((TimeCurrent()-OrderOpenTime()) >= viDeleteOpenOrderAfterInSec) {
                            // For executed orders, need to close them
                            double closePrice = 0;
                            RefreshRates();
                            if(OrderType() == OP_BUY)
                                closePrice  = Bid;
                            if(OrderType() == OP_SELL)
                                closePrice  = Ask;
                            OrderClose(OrderTicket(), OrderLots(), closePrice, int(viMaxSlippageInPip*viPipsToPoint), clrWhite);
                        }

                        // WORKING ON 10 pip Gap for to increase stop loss by 10 pips as profits increase by 10 pips
                        int incomePips = (int) ((OrderProfit() - OrderSwap() - OrderCommission()) / OrderLots());

                        if (incomePips >= 10)   {
                           if(OrderType() == OP_BUY)
                              OrderModify(OrderTicket(), 0, OrderStopLoss() + 10*Point, OrderTakeProfit(), 0);
                           if(OrderType() == OP_SELL)
                              OrderModify(OrderTicket(), 0, OrderStopLoss() - 10*Point, OrderTakeProfit(), 0);
                        }

                }
    }

BLOCK-TRAILING 您要查找的内容称为 Block-Trailing。与 MT4 附带的普通 Trailing-Stop 不同,您(将)需要:

  1. 仅 start-trailing 获利 x-pip。
  2. Block-size in pip(每次区块移动后只跳SL)。
  3. 每个 SL 调整需要移动 x-pips。

注意随之而来的一个常见问题是交易者将追踪设置得过于 close/tight 当前市场。 MT4 不是高频交易平台。不要将它剥得太近。大多数经纪商都有最小冻结和止损距离。如果将其设置得太靠近 price-edge,您将收到 "ERROR 130 Invalid Stop" 错误。检查您的经纪商在 Contract-Specification 中的设置以获取符号。


参数

vsTicketIdsInCSV:要处理的 OPENED TicketID 列表(例如 123、124、123123、1231、1)

viProfitToActivateBlockTrailInPip:追踪只会在 OrderProfit > 这个点之后开始。

viTrailShiftProfitBlockInPip:每次利润增加此点数时,SL 都会跳跃。

viTrailShiftOnProfitInPip:按此点数增加止损。


示例:

viProfitToActivateBlockTrailInPip=100,viTrailShiftProfitBlockInPip=30,viTrailShiftOnProfitInPip=20。

当订单为 floating-profit 130 点 (100+30) 时,Block-Trailing 将开始。将设置SL以保证20pip的利润。

当floating-profit达到160pips(100+30+30)时,将设置SL保证40pips(2x20pips)。


我已将此添加到 GitHub:https://github.com/fhlee74/mql4-BlockTrailer ETH 或 BTC 贡献将不胜感激。

这是它的完整代码:

//+------------------------------------------------------------------+
//|                                                   SO56177003.mq4 |
//|                Copyright 2019, Joseph Lee, TELEGRAM @JosephLee74 |
//|                                             http://www.fs.com.my |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Joseph Lee, TELEGRAM @JosephLee74"
#property link      "http://www.fs.com.my"
#property version   "1.00"
#property strict

#include <stderror.mqh> 
#include <stdlib.mqh> 

//-------------------------------------------------------------------
// APPLICABLE PARAMETERS
//-------------------------------------------------------------------
extern string       vsEAComment1                                = "Telegram @JosephLee74";      // Ego trip
extern string       vsTicketIdsInCSV                            = "123 , 124, 125 ,126 ";       // List of OPENED TicketIDs to process.
extern int          viProfitToActivateBlockTrailInPip   = 10;                                   // Order must be in profit by this to activate BlockTrail
extern int          viTrailShiftProfitBlockInPip            = 15;                                   // For every pip in profit (Profit Block), shift the SL
extern int          viTrailShiftOnProfitInPip               = 10;                                   // by this much
extern int          viMaxSlippageInPip                      = 2;                                    // Max Slippage (pip)


//-------------------------------------------------------------------
// System Variables
//-------------------------------------------------------------------
double  viPipsToPrice               = 0.0001;
double  viPipsToPoint               = 1;
int     vaiTicketIds[];
string  vsDisplay                   = "";

//-------------------------------------------------------------------



//+------------------------------------------------------------------+
//| EA Initialization function
//+------------------------------------------------------------------+
int init() {
    ObjectsDeleteAll(); Comment("");
    // Caclulate PipsToPrice & PipsToPoints (old sytle, but works)
    if((Digits == 2) || (Digits == 3)) {viPipsToPrice=0.01;}
    if((Digits == 3) || (Digits == 5)) {viPipsToPoint=10;}

    // ---------------------------------
    // Transcribe the list of TicketIDs from CSV (comma separated string) to an Int array.
    string vasTickets[];
    StringSplit(vsTicketIdsInCSV, StringGetCharacter(",", 0), vasTickets);
    ArrayResize(vaiTicketIds, ArraySize(vasTickets));
    for(int i=0; i<ArraySize(vasTickets); i++) {
        vaiTicketIds[i] = StringToInteger(StringTrimLeft(StringTrimRight(vasTickets[i])));
    }
    // ---------------------------------
    start();
    return(0);
}
//+------------------------------------------------------------------+
//| EA Stand-Down function
//+------------------------------------------------------------------+
int deinit() {
    ObjectsDeleteAll();
    return(0);
}


//============================================================
// MAIN EA ROUTINE
//============================================================
int start() {

    // ========================================
    // Process all the tickets in the list
    vsDisplay                   = "BLOCK-TRAILER v1.1 (Please note the Minimum Freeze/StopLoss level in Contract Specification to AVOID error 130 Invalid Stop when trailing).\n";
    double  viPrice         = 0;
    for(int i=0; i<ArraySize(vaiTicketIds); i++) {
        if(OrderSelect( vaiTicketIds[i], SELECT_BY_TICKET, MODE_TRADES ))
            if(OrderCloseTime() == 0 ) {
                // Only work on Active orders
                if(OrderType() == OP_BUY) {
                    RefreshRates();
                    double  viCurrentProfitInPip        = (Bid-OrderOpenPrice()) / viPipsToPrice;
                    double  viNewSLinPip                = ((viCurrentProfitInPip - viProfitToActivateBlockTrailInPip)/viTrailShiftProfitBlockInPip) * viTrailShiftOnProfitInPip;
                    double  viSLinPrice                 = NormalizeDouble(OrderOpenPrice() + (viNewSLinPip * viPipsToPrice), Digits);
                    double  viNewSLFromCurrentPrice = NormalizeDouble((Bid-viSLinPrice)/viPipsToPrice, 1);
                    vsDisplay   =   vsDisplay 
                                        + "\n[" + IntegerToString(OrderTicket()) 
                                        + "] BUY: Open@ " + DoubleToStr(OrderOpenPrice(), Digits) 
                                        + " | P/L: $" + DoubleToStr(OrderProfit(), 2) 
                                        + " / " + DoubleToStr(viCurrentProfitInPip, 1) + "pips.";
                    if(viCurrentProfitInPip < (viProfitToActivateBlockTrailInPip+viTrailShiftProfitBlockInPip))
                        vsDisplay   = vsDisplay + " " + int(((viProfitToActivateBlockTrailInPip+viTrailShiftProfitBlockInPip))-viCurrentProfitInPip) + " pips to start Trail.";
                    if(viCurrentProfitInPip >= (viProfitToActivateBlockTrailInPip+viTrailShiftProfitBlockInPip)) {
                        ResetLastError();
                        vsDisplay   = vsDisplay + " TRAILING to [" + DoubleToStr(viSLinPrice, Digits) + " which is " + DoubleToStr(viNewSLFromCurrentPrice, 1) + " pips from Bid]";
                        if((viSLinPrice > OrderStopLoss()) || (OrderStopLoss() == 0))
                            if(OrderModify(OrderTicket(), OrderOpenPrice(), viSLinPrice, OrderTakeProfit(), OrderExpiration())) {
                                vsDisplay = vsDisplay + " --Trailed SL to " + DoubleToStr(viSLinPrice, Digits);
                            }
                            else {
                                int errCode = GetLastError();
                                Print(" --ERROR Trailing " + IntegerToString(OrderTicket()) + " to " + DoubleToStr(viSLinPrice, Digits) + ". [" + errCode + "]: " + ErrorDescription(errCode));
                                vsDisplay = vsDisplay + " --ERROR Trailing to " + DoubleToStr(viSLinPrice, Digits);
                                vsDisplay = vsDisplay + " [" + errCode + "]: " + ErrorDescription(errCode);
                            }
                    }
                }
                if(OrderType() == OP_SELL) {
                    RefreshRates();
                    double  viCurrentProfitInPip    = (OrderOpenPrice()-Ask) / viPipsToPrice;
                    double  viNewSLinPip                = int((viCurrentProfitInPip - viProfitToActivateBlockTrailInPip)/viTrailShiftProfitBlockInPip) * viTrailShiftOnProfitInPip;
                    double  viSLinPrice                 = NormalizeDouble(OrderOpenPrice() - (viNewSLinPip * viPipsToPrice), Digits);
                    double  viNewSLFromCurrentPrice = NormalizeDouble((viSLinPrice-Ask)/viPipsToPrice, 1);
                    vsDisplay   =   vsDisplay 
                                        + "\n[" + IntegerToString(OrderTicket()) 
                                        + "] SELL: Open@ " + DoubleToStr(OrderOpenPrice(), Digits) 
                                        + " | P/L: $" + DoubleToStr(OrderProfit(), 2) 
                                        + " / " + DoubleToStr(viCurrentProfitInPip, 1) + "pips.";
                    if(viCurrentProfitInPip < (viProfitToActivateBlockTrailInPip+viTrailShiftProfitBlockInPip))
                        vsDisplay   = vsDisplay + " " + int(((viProfitToActivateBlockTrailInPip+viTrailShiftProfitBlockInPip))-viCurrentProfitInPip) + " pips to start Trail.";
                    if(viCurrentProfitInPip >= (viProfitToActivateBlockTrailInPip+viTrailShiftProfitBlockInPip)) {
                        ResetLastError();
                        vsDisplay   = vsDisplay + " TRAILING to [" + DoubleToStr(viSLinPrice, Digits) + " which is " + DoubleToStr(viNewSLFromCurrentPrice, 1) + " pips from Ask]";
                        if((viSLinPrice < OrderStopLoss()) || (OrderStopLoss()==0) )
                            if(OrderModify(OrderTicket(), OrderOpenPrice(), viSLinPrice, OrderTakeProfit(), OrderExpiration())) {
                                vsDisplay = vsDisplay + " --Trailed SL to " + DoubleToStr(viSLinPrice, Digits);
                            }
                            else {
                                int errCode = GetLastError();
                                Print(" --ERROR Trailing " + IntegerToString(OrderTicket()) + " to " + DoubleToStr(viSLinPrice, Digits) + ". [" + errCode + "]: " + ErrorDescription(errCode));
                                vsDisplay = vsDisplay + " --ERROR Trailing to " + DoubleToStr(viSLinPrice, Digits);
                                vsDisplay = vsDisplay + " [" + errCode + "]: " + ErrorDescription(errCode);
                            }
                    }
                }
            }
    }
    Comment(vsDisplay);
    return(0);
}

下面是显示其工作原理的屏幕截图:

赏金领取

抱歉完全忘记了这一点:'( 我已经扩展了 https://github.com/fhlee74/mql4-EventTrader 处的原始 EventTrader 以合并此 Block-Trailer。但是,如果有人可以对其进行适当的测试,那就太好了。这是我的初步测试结果:在最初的 10pips 触发后,它从原来的 50pips SL 变为 40pips(这是参数)每 15pips 的利润。

要从此线程中进行测试,请给我发送电子邮件至@JosephLee74 确定后,我们会在这里更新。