Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to add another condition to the solution in this post. I want the stop loss to move by 10 pips when a trade is in 10 pips profit. To be more specific, say I've set a pending buy order and the stop loss is 10 pips below the open price and the take profit is 50 pips. If the trade is 10 pips in profit, then the stop loss would move 10 pips upwards, if the trade moves to 20 pips in profit then the stop loss would move another 10 pips upwards, and the same would occur for 30 and 40 pips in profit till the 50 pips take profit is reached. The idea here is the stop loss increases by 10 pips as profit increases by 10 pips, but the stop loss doesn't go down. So if the stop loss is at 10 pips in profit whiles the price is at 23 pips in profits and it suddenly decreases, it would exit the trade at the 10 pip profit stop loss.

Setting up the above condition seems quite complex for me. I haven't been able to get it done.

Below is the relevant part of the code I'm trying to solve (please note that the rest of the code is the same as the above linked question solution).

//=========================================================
    //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);
                        }

                }
    }
like image 932
TenOutOfTen Avatar asked May 16 '19 21:05

TenOutOfTen


People also ask

How many pips should stop-loss be?

A day trader may want to use a 10% ATR stop, meaning that the stop is placed 10% x ATR pips from the entry price. In this instance, the stop would be anywhere from 11 pips to 14 pips from your entry price. A swing trader might use 50% or 100% of ATR as a stop.

How many pips should my take profit be?

In general, the best ratio is 1:3, so the profit should be 3 times bigger than the loss. For example, if your Stop Loss equals 50 pips, the Take Profit should be 150 pips. In some cases, other Risk/Reward ratios are possible.

Can you set both stop-loss and take profit?

The problem is that using the default sell order options; you can only set 1 sell order at a time. This means you have to either place a “take profit” OR a “stop-loss” order. If you want to set both “take profit” and “stop-loss” orders simultaneously, you have to use the OCO option.


1 Answers

BLOCK-TRAILING What you are looking for is called a Block-Trailing. Unlike a normal Trailing-Stop that comes with MT4, you (will) need:

  1. Only start-trailing upon x-pip profit.
  2. Block-size in pip (only jump SL after each block movement).
  3. Each SL adjustment needs to move by x-pips.

Note: A common problem that comes with this is when trader set the trail to be too close/tight to the current market. MT4 is not a HFT platform. Do not scalp it too close. Most brokers have a minimum Freeze and StopLoss distance. If you set it too near the price-edge, you will receive an "ERROR 130 Invalid Stop" error. Check your broker's setting in the Contract-Specification for the symbol.


Parameters

vsTicketIdsInCSV: List of OPENED TicketIDs to process (eg 123, 124, 123123, 1231 , 1)

viProfitToActivateBlockTrailInPip: Trailing will only start after OrderProfit > this pips.

viTrailShiftProfitBlockInPip: SL will jump each time profit increase by this number of pips.

viTrailShiftOnProfitInPip: Increase the SL by this number of pips.


Example:

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

The Block-Trailing will start when order is floating-profit by 130 pips (100+30). SL will be set to guarantee 20pip profit.

When floating-profit reach 160pips (100+30+30), SL will be set to guarantee 40pips (2x20pips).


I have added this to GitHub: https://github.com/fhlee74/mql4-BlockTrailer An ETH or BTC contribution will be appreciated.

Here is the full code for it:

//+------------------------------------------------------------------+
//|                                                   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);
}

And here is the screen shots showing how it works: enter image description here

like image 63
Joseph Lee Avatar answered Sep 28 '22 15:09

Joseph Lee