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);
}
}
}
BLOCK-TRAILING
What you are looking for is called a Block-Trailing. Unlike a normal Trailing-Stop that comes with MT4, you (will) need:
- Only start-trailing upon x-pip profit.
- Block-size in pip (only jump SL after each block movement).
- 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:
BOUNTY CLAIM
Apologies forgot about this completely :'(
I have extended the original EventTrader at https://github.com/fhlee74/mql4-EventTrader to incorporate this Block-Trailer. However, will be great if someone can do proper testing on it. This is my initial test result: It shifted from original 50pips SL to 40pips (which is the parameter) every 15pips profit after the initial 10pips trigger).
To take the testing out of this thread, please telegram me at @JosephLee74
After it is confirmed, then we will update here.