How to open an opposite position immediately after hit SL? An issue in MQL4
How to open an opposite position immediately after hit SL? An issue in MQL4
Loading saved threads...
jeon · External communityPost link
External question — Stack Overflow Stack Exchange
Author: jeon
Original post: https://stackoverflow.com/questions/79232372
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
When a certain buy condition is met, I want to open a buy position and set the take profit (TP) and stop loss (SL) based on the candle length.
I found a Martingale strategy on Forex Factory that is similar to what I want. The main function of this Martingale strategy is that when a buy position hits the SL, it opens an opposite sell position with 2x the lot size.
It is working, but it does not open the sell position immediately once the buy position hits the SL.
Here is the code I modified, but it still does not open immediately.
Any help would be much appreciated!
double barLength = High[1] - Low[1];
if(OrderType() == OP_BUY) {
if(OrderOpenPrice() > OrderClosePrice()) {
SendOrder(Symbol(), OP_SELL, OrderLots() * multiply, Bid, 3, Bid + barLength, Bid - barLength, "martingale sell", magic, Red);
} else {
SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
}
and here is full code :
#property copyright "Copyright 2015, Tomas RD"
#property link "https://www.mql5.com"
#property version "1.01"
#property strict
int MagicNumber=1;
extern int magic=3059823;
extern double lotes=0.01;
extern bool UseRisk = FALSE;
extern double Risk = 0.1;
extern double stop_loss=30;
extern double take_profit =30;
extern double multiply=2.5;
extern string INDICATOR_PARAMETER1 ="=========Candle==========";
extern int SHIFT_CANDLE=1;
double lots=0.01;
int TP=20;
int SL=20;
extern string INDICATOR_PARAMETER2 ="=========Volumes==========";
extern int SHIFT_VOLUME=1;
double Scale, stop_loss_v, take_profit_v;
int LOTS, x, f, g, h, k, y, z, jumlahbuy, jumlahbuylimit, jumlahselllimit, jumlahsell, jumlahbuystop, jumlahsellstop;
double BUY[99], SELL[99], BUYLIMIT[99], SELLLIMIT[99], BUYSTOP[99], SELLSTOP[99], BATAS;
int prec=0;
int a=0;
double pt, i, minlot, stoplevel;
color FontColorUp1 = Red;
color FontColorDn1 = White;
color FontColor = Blue;
color FontColorUp2 = Yellow;
color FontColorDn2 = Lime;
color FontUP = Lime;
color Font = White;
color FontDOWN = Red;
double initialBarLength = 0;
bool buyConditionMet = false;
int OnInit() {
switch(Digits) {
case 1: Scale = 0.1; break;
case 2: Scale = 0.01; break;
case 3: Scale = 0.01; break;
case 4: Scale = 0.0001; break;
case 5: Scale = 0.0001; break;
}
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
for(int i=1; i<=50; i++) {
ObjectDelete("Market_Price_Label" + IntegerToString(i));
}
}
void OnTick() {
if(lotesMarginFree() >= MarketInfo(NULL, MODE_MINLOT)) {
if (UseRisk == TRUE) lotes = (AccountFreeMargin() / 10000) * Risk;
if(vol_ea() == 1 ) {
initialBarLength = High[1] - Low[1];
//buyConditionMet = true/
OpenMartingale();
}
}
modifyOrders();
}
void modifyOrders() {
double tp, sl;
for(int i=OrdersTotal()-1; i>=0; i--) {
if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
if(OrderMagicNumber() == magic) {
if(buyConditionMet) {
double barLength = initialBarLength;
if(OrderType() == OP_BUY) {
sl = OrderOpenPrice() - barLength;
tp = OrderOpenPrice() + barLength;
}
if(OrderType() == OP_SELL) {
sl = OrderOpenPrice() + barLength;
tp = OrderOpenPrice() - barLength;
}
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
if(OrderTakeProfit() == 0 && OrderStopLoss() == 0) {
int p = OrderModify(OrderTicket(), OrderOpenPrice(), sl, tp, 0);
if (p == 0) {
Print("OrderModify failed with error #", GetLastError());
}
}
if(OrderType() == OP_BUY && Bid <= sl) {
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrRed);
SendOrder(Symbol(), OP_SELL, OrderLots(), Bid, 3, Bid + barLength, Bid - barLength, "Opposite sell", magic, Red);
}
if(OrderType() == OP_SELL && Ask >= sl) {
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrBlue);
SendOrder(Symbol(), OP_BUY, OrderLots(), Ask, 3, Ask - barLength, Ask + barLength, "Opposite buy", magic, Blue);
}
if(OrderType() == OP_BUY && Bid >= tp) {
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrGreen);
}
if(OrderType() == OP_SELL && Ask <= tp) {
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrGreen);
}
}
}
}
}
}
void OpenMartingale() {
int value = 0;
int martingaleLevel = 0;
for(int i=OrdersTotal()-1; i>=0; i--) {
if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) {
value++;
if(OrderComment() == "martingale buy" || OrderComment() == "martingale sell") {
martingaleLevel++;
}
}
}
}
if(martingaleLevel >= 3) {
Print("Maximum Martingale level reached. No new Martingale orders will be placed.");
return;
}
if(value == 0) {
for(int i=OrdersHistoryTotal()-1; i>=0; i--) {
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) {
if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) {
value++;
double barLength = High[1] - Low[1];
if(OrderType() == OP_BUY) {
if(OrderOpenPrice() > OrderClosePrice()) {
SendOrder(Symbol(), OP_SELL, OrderLots() * multiply, Bid, 3, Bid + barLength, Bid - barLength, "martingale sell", magic, Red);
} else {
SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
}
}
if(OrderType() == OP_SELL) {
if(OrderOpenPrice() < OrderClosePrice()) {
SendOrder(Symbol(), OP_BUY, OrderLots() * multiply, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
} else {
SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
}
}
break;
}
}
}
}
if(value == 0) {
double barLength = High[1] - Low[1];
SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
}
}
void SendOrder(string symbol, int type, double lot, double price_s, int slippage_v, double stop_loss_v, double take_profit_v, string comment, int magic_v, color color_v) {
int countTentative = 3;
int tentative = 0;
int ticket = 0;
while(IsConnected() && ticket < 1 && tentative <= countTentative) {
RefreshRates();
ticket = OrderSend(symbol, type, lot, price_s, slippage_v, stop_loss_v, take_profit_v, comment, magic_v, 0, color_v);
Sleep(1000);
tentative++;
}
}
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
if(id == CHARTEVENT_OBJECT_CLICK) {
if(sparam == "sell_option") {
stop_loss_v = Bid + stop_loss * Scale;
take_profit_v = Bid - take_profit * Scale;
SendOrder(Symbol(), OP_SELL, lotes, Bid, 3, stop_loss_v, take_profit_v, "sell", magic + 1, Red);
}
if(sparam == "buy_option") {
stop_loss_v = Ask - stop_loss * Scale;
take_profit_v = Ask + take_profit * Scale;
SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, stop_loss_v, take_profit_v, "buy", magic + 1, Blue);
}
if(sparam == "close_this_option") {
closeOrdersSymbol();
}
if(sparam == "close_all_option") {
closeOrdersAll();
}
}
}
void closeOrdersSymbol() {
int p;
for(int i=OrdersTotal()-1; i>=0; i--) {
if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
if(OrderMagicNumber() == magic + 1 && OrderSymbol() == Symbol()) {
if(OrderType() == OP_BUY) {
p = OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrSkyBlue);
} else {
p = OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrPink);
}
}
}
}
}
void closeOrdersAll() {
int p;
for(int i=OrdersTotal()-1; i>=0; i--) {
if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
if(OrderMagicNumber() == magic + 1) {
if(OrderType() == OP_BUY) {
p = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 3, clrSkyBlue);
} else {
p = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 3, clrPink);
}
}
}
}
}
double lotesMarginFree() {
double MargRequired = MarketInfo(Symbol(), MODE_MARGINREQUIRED); // current price * 1000
double Equity = AccountEquity();
return NormalizeDouble(Equity / MargRequired, 1);
}
int vol_ea() {
y = 0; f = 0; g = 0; h = 0; k = 0; z = 0; jumlahbuy = 0; jumlahsell = 0; jumlahbuylimit = 0; jumlahselllimit = 0; jumlahsellstop = 0; jumlahbuystop = 0;
//////////CANDLE///////
double OPEN_3 = iOpen(Symbol(), 0, SHIFT_CANDLE);
double OPEN_2 = iOpen(Symbol(), 0, SHIFT_CANDLE + 2);
double OPEN_1 = iOpen(Symbol(), 0, SHIFT_CANDLE + 3);
double CLOSE_3 = iClose(Symbol(), 0, SHIFT_CANDLE);
double CLOSE_2 = iClose(Symbol(), 0, SHIFT_CANDLE + 2);
double CLOSE_1 = iClose(Symbol(), 0, SHIFT_CANDLE + 3);
////CANDLE 1////
double BULLISH = CLOSE_3 > OPEN_3;
double BEARISH = CLOSE_3 < OPEN_3;
/////////////VOLUME//////////
double VOLUME_3 = iVolume(Symbol(), 0, SHIFT_VOLUME);
double VOLUME_2 = iVolume(Symbol(), 0, SHIFT_VOLUME + 1);
double VOLUME_1 = iVolume(Symbol(), 0, SHIFT_VOLUME + 2);
double VOLUME_0 = iVolume(Symbol(), 0, SHIFT_VOLUME + 3);
double VOLUME_LALU = iVolume(Symbol(), 0, SHIFT_VOLUME + 4);
double VOLUME_OP = ((VOLUME_0 < VOLUME_1) && (VOLUME_1 < VOLUME_2) && (VOLUME_2 < VOLUME_3));
if(jumlahbuy + jumlahsell == 0) {
if (BEARISH == true && VOLUME_OP == true) {
return(1);
}
if (BULLISH == true && VOLUME_OP == true) {
return(1);
}
}
return(0);
}
Quote
Report
user3666197 · External communityPost link
External answer — Stack Overflow Stack Exchange
Author: user3666197
Original post: https://stackoverflow.com/a/79746218
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
Q1 :" open opposite position immediately (...)"
You might already noticed that in FX-trading, you live in a 2D-world.
You decide which way to enter a trade.
If you opt to demand an entry to happen at a given price in the
PriceDOMAIN
-dimension, you cannot know, when the FX-Market moves to meet that price-level with liquidity enough to get your pending XTO filled ( so, you have to wait, until that happens at some future time or never at all, if FX-Market will never have visited a such set pricelevel ).
If you opt to demand an entry to happen at a given moment in the
TimeDOMAIN
-dimension ( the said "now", or "immediately" ), then you cannot demand an exact value in the
PriceDOMAIN
-dimension, but have to admit some
slippage
-parameter-declared proximity "around" the given
OrderSend( ..., price = Bid, ... )
set
PriceDOMAIN
-level.
In case FX-Market has such liquidity ( aka ToB Market Depth ) and your Broker permits, your
OrderSend()
-XTO call will turn out as a trade position taken.
In case FX-Market has not such demanded liquidity matching your sizing, permitted slippage-wide pricing and timing (now), your
OrderSend()
-XTO will get rejected and your code instructs then to wait 1000 [ms] ( this is "for ages" in flow of XTO-s on the FX-Market ), yet your code then re-submits the
OrderSend()
-call filled with "old" prices, so only if and only if the FX-Market has re-visited your "original"
PriceDOMAIN
-range of "now" very "old" initial-call
Bid
+/-
slippage
, only then the loop-iterated
OrderSend()
-XTO attempt may meet the FX-Market state and get filled.
Another advice is to re-read your Broker Terms & Conditions, namely the details about
FREEZELEVEL
-conditions, which in addition to the above often block XTO-s and/or modifications during
FREEZELEVEL
proximity to TP/SL
Quote
Report
Reza Rezaei · External communityPost link
External answer — Stack Overflow Stack Exchange
Author: Reza Rezaei
Original post: https://stackoverflow.com/a/79746515
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
The best approach is to set a pending order at your position's stop-loss price.
You can execute this method either manually or automatically.
Good luck
Quote
Report
Post Reply
Checking account access…