topkek
🧩 Syntax:
//+------------------------------------------------------------------+
//| Expert advisor: CandlePatternRiskTrailingEA_M5.mq5 |
//| Versie voor M5 timeframe |
//| Stop-loss en trailing in euro's, max 1 Buy & 1 Sell positie |
//+------------------------------------------------------------------+
#property strict
//--- inputs
input int GreenCandlesForBuy = 3; // aantal groene candles voor buy
input int RedCandlesForSell = 3; // aantal rode candles voor sell
input double RiskInEuro = 22.0; // stop-loss in euro
input double TrailingInEuro = 5.0; // trailing-afstand in euro
input double TrailingStartEuro = 5.0; // start trailing pas na € winst
input double LotSize = 0.01; // vaste lotgrootte
input bool EnableTrailingStop = true; // trailing aan/uit
//--- globals
datetime lastBarTime = 0;
int minStopsLevel;
double tickValue, tickSize;
//+------------------------------------------------------------------+
//| Expert initialization |
//+------------------------------------------------------------------+
int OnInit()
{
minStopsLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
Print("INIT: minStopsLevel=", minStopsLevel,
" tickValue=", tickValue,
" tickSize=", tickSize);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
int needed = MathMax(GreenCandlesForBuy, RedCandlesForSell) + 2;
MqlRates rates[];
if(CopyRates(_Symbol, PERIOD_M5, 0, needed, rates) < needed) return;
ArraySetAsSeries(rates, true);
if(rates[0].time == lastBarTime) return;
lastBarTime = rates[0].time;
bool hasBuy = false, hasSell = false;
for(int i=0; i<PositionsTotal(); i++)
{
ulong tk = PositionGetTicket(i);
if(tk==0 || !PositionSelectByTicket(tk)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
ENUM_POSITION_TYPE t = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if(t == POSITION_TYPE_BUY) hasBuy = true;
if(t == POSITION_TYPE_SELL) hasSell = true;
}
if(!hasBuy && CountConsecutive(rates, GreenCandlesForBuy, true))
PlaceOrder(ORDER_TYPE_BUY);
if(!hasSell && CountConsecutive(rates, RedCandlesForSell, false))
PlaceOrder(ORDER_TYPE_SELL);
if(EnableTrailingStop)
ApplyTrailing();
}
//+------------------------------------------------------------------+
bool CountConsecutive(const MqlRates &r[], int cnt, bool bullish)
{
for(int i=1; i<=cnt; i++)
{
if(bullish && r[i].close <= r[i].open) return false;
if(!bullish && r[i].close >= r[i].open) return false;
}
return true;
}
//+------------------------------------------------------------------+
void PlaceOrder(ENUM_ORDER_TYPE type)
{
double entry = (type == ORDER_TYPE_BUY)
? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ptsSL = RiskInEuro / (tickValue * LotSize) * (tickSize / _Point);
ptsSL = NormalizeDouble(ptsSL, 0);
int guard = minStopsLevel + 1;
if(ptsSL < guard)
{
Print(" ptsSL <",guard," -> forceren naar ",guard);
ptsSL = guard;
}
double sl_price = (type==ORDER_TYPE_BUY)
? entry - ptsSL * _Point
: entry + ptsSL * _Point;
sl_price = NormalizeDouble(sl_price, _Digits);
MqlTradeRequest rq; MqlTradeResult rs;
ZeroMemory(rq); ZeroMemory(rs);
rq.action = TRADE_ACTION_DEAL;
rq.symbol = _Symbol;
rq.volume = LotSize;
rq.type = type;
rq.price = NormalizeDouble(entry, _Digits);
rq.sl = sl_price;
rq.tp = 0;
rq.deviation = 10;
rq.magic = 20250607;
rq.type_filling = ORDER_FILLING_IOC;
if(!OrderSend(rq, rs))
Print("OrderSend failed: ", rs.retcode);
else if(rs.retcode != TRADE_RETCODE_DONE)
Print("Order rejected: ", rs.retcode, " / ", rs.comment);
else
Print("Order placed: ", EnumToString(type),
" entry=", DoubleToString(rq.price,_Digits),
" SL=", DoubleToString(sl_price,_Digits));
}
//+------------------------------------------------------------------+
void ApplyTrailing()
{
for(int i=0; i<PositionsTotal(); i++)
{
ulong tk = PositionGetTicket(i);
if(tk==0 || !PositionSelectByTicket(tk)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
ENUM_POSITION_TYPE t = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double openP = PositionGetDouble(POSITION_PRICE_OPEN);
double curP = (t==POSITION_TYPE_BUY)
? SymbolInfoDouble(_Symbol, SYMBOL_BID)
: SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double curSL = PositionGetDouble(POSITION_SL);
double vol = PositionGetDouble(POSITION_VOLUME);
double diffPts = MathAbs(curP - openP) / _Point;
double eurGain = diffPts * (tickValue * vol);
if(eurGain < TrailingStartEuro)
continue;
double ptsTR = TrailingInEuro / (tickValue * vol) * (tickSize / _Point);
ptsTR = NormalizeDouble(ptsTR, 0);
int guard = minStopsLevel + 1;
if(ptsTR < guard) ptsTR = guard;
double newSL = (t==POSITION_TYPE_BUY)
? curP - ptsTR * _Point
: curP + ptsTR * _Point;
newSL = NormalizeDouble(newSL, _Digits);
if((t==POSITION_TYPE_BUY && newSL > curSL) ||
(t==POSITION_TYPE_SELL && newSL < curSL))
{
MqlTradeRequest rq; MqlTradeResult rs;
ZeroMemory(rq); ZeroMemory(rs);
rq.action = TRADE_ACTION_SLTP;
rq.position = tk;
rq.sl = newSL;
rq.tp = 0;
if(!OrderSend(rq, rs))
Print("Trailing SL failed: ", rs.retcode);
else
Print("Trailing SL updated pos#",tk,
" to ", DoubleToString(newSL,_Digits));
}
}
}
//+------------------------------------------------------------------+