This automated trading script is designed to execute "scalping" strategies on the M15 (15-minute) timeframe. It utilizes a combination of technical price action analysis, dynamic risk management, and a recovery mechanism to manage trades automatically.
Core Trading Logic
The script identifies trading opportunities by monitoring the relationship between the current market price and a dynamically calculated price channel.
- Dynamic Price Channel: The system looks at the highest high and lowest low over a specific number of previous candles to establish a "channel." It then calculates a midline for this range.
- Entry Signals: The script generates buy and sell signals based on whether the price is trending toward or away from this midline, combined with specific momentum indicators.
- Order Types: It primarily uses "Stop" orders (Buy Stop and Sell Stop), which are triggered only when the price moves in the desired direction by a certain amount, helping to ensure the trade is moving with the momentum.
Smart Risk Management & Martingale System
A key feature of this script is its ability to adjust trade sizes based on past performance to protect the account balance:
- Success Scaling: When the system completes a profitable trade, it automatically reduces the lot size for the next trade (down to a minimum of 0.1). This helps lock in gains and reduce exposure after a win.
- Martingale Recovery: If a trade is closed at a loss, the system can activate a "Martingale" mode. This increases the lot size of the next trade to potentially recover the previous loss more quickly.
- Safety Checks: The script includes a "Margin Check" that ensures the trade size never exceeds what the account can safely afford. It also specifically checks for currency pairs involving USD to prevent over-leveraging.
- Loss Buffer: After a losing trade, the script enforces a cooling-off period (a delay) before it is allowed to open another position. This is intended to prevent the system from entering consecutive losing trades in a volatile market.
Trade Management Features
Once a position is opened, the script actively manages it to maximize profit and minimize risk:
- Trailing Stop: If enabled, the script moves the "Stop Loss" dynamically as the price moves in favor of the trade. This allows the system to follow a profitable trend and "lock in" gains while giving the trade room to breathe.
- Visual Feedback: The script draws horizontal lines on the chart to show the current high, low, and midline. It also places arrows on the chart to signal where it detected potential buy or sell opportunities.
- Automatic Cleanup: The system includes logic to monitor and remove "stale" or unexecuted pending orders that are no longer relevant to the current market conditions.
- On-Screen Data: A dashboard is provided at the top of the chart, displaying real-time information such as the current midline, profit/loss status, channel width, and various internal system signals.
//+------------------------------------------------------------------+
//| Scalp-M15.mq4 |
//| Modified by Jazz. |
//| http://www.metaquotes.net/ |
//| âåðñèÿ 2.4 |
//| - Äîáàâëåí êîíòðîëü ëîòà íà äîïóñòèìûé ðàçìåð |
//| (÷òîá no money íå ïîëó÷èòü ) |
//| âåðñèÿ 2.3 |
//| - èçìåíåí ÌÌ: òåïåðü ðàçìåð ëîòà èçìåíÿåòñÿ ïî ñëåä. àëãîðèòìó:|
//| íà÷èíàåòñÿ òîðãîâëÿ ñ ëîòîì = mlot, ïîñëå êàæäîé óñïåøíîé |
//| ñäåëêè ëîò óìåíüøàåòñÿ âäâîå äî ìèíèìàëüíîãî = 0.1, |
//| åñëè âñòðåòèëàñü ïðîèãðàâøàÿ ñäåëêà ëîò ñòàâèòñÿ ïî |
//| ìàðòèíãåéëó äëÿ òîãî, ÷òî áû ñëåäóþùàÿ âîñïîëíèëà óáûòîê |
//| (ïðè óñïåõå ðàçóìååòñÿ :)) èëè = mlot, åñëè ïî Ìà ïîëó÷èëîñü |
//| ìåíüøå ÷åì mlot |
//| - Äîáàâëåíà çàäåðæêà = !!!3 äíÿ!!! ïîñëå íåóñïåøíîé ñäåëêè, ýòî|
//| çà÷àñòóþ ïîçâîëÿåò èçáåæàòü ïîëó÷åíèÿ âòîðîãî ëîñÿ ïîäðÿä |
//| - Èñïðàâëåí êîä, îòâå÷àþùèé çà óäàëåíèå íåñðàáîòàâøèõ îðäåðîâ |
//| (òåïåðü ðàáîòàåò :)) |
//| - Äîáàâëåí ïàðàìåòð UseMG âêëþ÷àþùèé èñïîëüçîâàíèå ÌÌ |
//| - Òåïåðü ýêïåðò ïîä÷èùàåò ÷àðò çà ñîáîé |
//+------------------------------------------------------------------+
#include <stdlib.mqh>
#property copyright "Jazz, Tartan"
extern double TakeProfit = 15;
extern double StopLoss = 100;
extern double Lots = 1.0;
extern double TrailingStop = 10;
extern int per=14;
extern int ttime=60;
extern int m1=0;
extern int zap=15;
extern int msec=45;
extern int Pause=450;
extern double mlot=1.0;
extern bool UseMG=true; // èñïîëüçîâàòü òàêòèêó ìàðòèíãåéëà äëÿ êîìïåíñàöèè ëîñåé
double canal,ob,os,dl,dh,lb,b,s,oppr,porog,hod,MidLine,MaxH,MinL,MaxPr,ls;
double lbsig,ssig,bsig,lssig,pb=200,ps, ord_lot;
datetime ctm1;
string MaxHi="lime";
string MinLow="ww",MidLin="ee";
int korl,korh,blok,i,reg=1,j,MinPr,blokd,Prec=4,k,cmd,cmd1,h;
bool isHedj=false;
//+------------------------------------------------------------------+
int deinit()
{
ObjectsDeleteAll(WindowOnDropped());
return(0);
}
//+------------------------------------------------------------------+
int init() { return(0); }
//+------------------------------------------------------------------+
int start()
{
double price,stl;
int cnt,i,ticket;
string arrup,arrdown;
datetime ctm;
if(m1==Minute() && msec<=Seconds() && j==0) j=j+1;
//---------------------------------------Ïîäñ÷åò îòêðûòûõ ïîçèöèé----------------
b=0; s=0; ob=0; os=0; ls=0; lb=0;
for(cnt=0;cnt<OrdersTotal();cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()==OP_SELL && OrderSymbol()==Symbol()) {b=b+1;oppr=OrderOpenPrice();}
if(OrderType()==OP_BUY && OrderSymbol()==Symbol()) {s=s+1;oppr=OrderOpenPrice();}
if(OrderType()==OP_SELLSTOP && OrderSymbol()==Symbol() && h==0) {os=os+1;oppr=OrderOpenPrice();}
if(OrderType()==OP_BUYSTOP && OrderSymbol()==Symbol() && h==0) {ob=ob+1;oppr=OrderOpenPrice();}
if(OrderType()==OP_SELLLIMIT && OrderSymbol()==Symbol()) {ls=ls+1;oppr=OrderOpenPrice();}
if(OrderType()==OP_BUYLIMIT && OrderSymbol()==Symbol()) {lb=lb+1;oppr=OrderOpenPrice();}
}
if((os+ob)>0) {blok=1;blokd=1;}
if((s+b+os+ob+ls+lb)==0)
{//Print((s+b+os+ob+ls+lb),"+",h);
h=0;
for (cnt=0;cnt<OrdersTotal();cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
Print(OrderType());
if(OrderType()==OP_BUYSTOP && OrderSymbol()==Symbol()) OrderDelete(OrderTicket());
if(OrderType()==OP_SELLSTOP && OrderSymbol()==Symbol()) OrderDelete(OrderTicket());
}
}
//----------------------------------------- MM ----------------------------------------
ord_lot = mlot;
if(UseMG)
{
for(i=HistoryTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL || OrderMagicNumber() > 2) continue; // ýòî îòëîæåíûé îðäåð
//----
if(OrderProfit()>0)
{
ord_lot = NormalizeDouble(OrderLots()/2,1);
if (ord_lot<0.1) ord_lot=0.1;
break;
}
if(OrderProfit()<0 && OrderClosePrice() == OrderStopLoss())
{
ord_lot = OrderLots()*MathRound(StopLoss/TakeProfit);
if(ord_lot < mlot) ord_lot=mlot;
if(ord_lot > NormalizeDouble(AccountFreeMargin()/1000.0,1))
ord_lot = NormalizeDouble(AccountFreeMargin()/1000.0,1);
break;
}
}
}
if (StringSubstr(Symbol(),3,3) == "USD")
{
//Print("USD íå îñíîâíàÿ âàëþòà! Ïðîâåðèì ëîò.");
if (ord_lot > NormalizeDouble(AccountFreeMargin()/1000.0/Bid,1))
ord_lot = NormalizeDouble(AccountFreeMargin()/1000.0/Bid,1);
//Print("Ëîò=",ord_lot);
}
//-----------------------------------------------MiniMax Setting------------------------------------------------
MaxH=High[per];MinL=Low[per];
for (cnt=0;cnt<per;cnt++)
{
if (MaxH<High[cnt]) MaxH=High[cnt];
if (MinL>Low[cnt]) MinL=Low[cnt];
}
MidLine=NormalizeDouble((MaxH+MinL)/2,Prec);
ObjectMove("MaxHi",OBJ_HLINE,CurTime(),MaxH);
ObjectMove("MinLow",OBJ_HLINE,CurTime(),MinL);
ObjectMove("MidLine",OBJ_HLINE,CurTime(),MidLine);
canal=MathRound((MaxH-MinL)/Point);
ObjectCreate(MaxHi, OBJ_HLINE, 0, Time[0], MaxH);
ObjectsRedraw();
ObjectCreate(MinLow, OBJ_HLINE, 0, Time[0], MinL);
ObjectsRedraw();
ObjectCreate(MidLin, OBJ_HLINE, 0, Time[0],MidLine);
ObjectsRedraw();
ObjectSet(MaxHi, OBJPROP_PRICE1,MaxH);
ObjectsRedraw();
ObjectSet(MinLow, OBJPROP_PRICE1,MinL);
ObjectsRedraw();
ObjectSet(MidLin, OBJPROP_PRICE1,MidLine);
ObjectsRedraw();
//Comment("ps - ",ps," pb - ",pb,"\nos - ",os," ob - ",ob);
if(os==1 && ((oppr-MidLine)/Point)>=5) reg=0;
if(ob==1 && ((oppr-MidLine)/Point)<=-5) reg=0;
if((os+ob)==0 && (s+b)==0 && canal<30) return(0);
if(MidLine<oppr && ssig==1) reg=0;
if(MidLine<oppr && bsig==1) reg=1;
if(MidLine>oppr && ssig==1) reg=1;
if(MidLine>oppr && bsig==1) reg=0;
if(mlot==0.1)
{
if(reg==0) porog=canal/10; else porog=5;
if(canal<50) porog=canal/10;
porog=MathRound(porog);
}
if (mlot==1.0)
{
if (reg==0) porog=canal; else porog=50;
if (canal<50) porog=canal;
}
//------------------------------------Îïðåäåëåíèå õîäîâûõ ïàðàìåòðîâ ïàðû---------------------------------
hod=(Open[3]-Close[3]+Open[2]-Close[2]+Open[1]-Close[1]+Open[0]-Close[0])/Point;
if ((MidLine-Close[0])/Point<-5) korh=1; else korh=0;
if ((MidLine-Close[0])/Point>5) korl=1;else korl=0;
//---------------------------------------------Ñíÿòèå ñëèâîê----------------------------------------------
//if((CurTime()-OrderCloseTime())<15) return(0);
if ((s+b+os+ob+ls+lb)>0) {MaxPr=0; MinPr=0;}
if(( b+s)>0 && TrailingStop==0 && h==0)
{
for (cnt=0;cnt<OrdersTotal();cnt++)
{//Comment("HistoryTotal - ",HistoryTotal());
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol())
{
cmd=OrderType();
if(cmd==OP_BUY) {price=Bid;cmd1=OP_SELL;stl=OrderOpenPrice()-Bid;}
if(cmd==OP_SELL) {price=Ask;cmd1=OP_BUY;stl=Ask-OrderOpenPrice();}
//if (OrderProfit()>MaxPr) MaxPr=OrderProfit();
//if (OrderProfit()<MinPr) MinPr=OrderProfit();
if (OrderProfit()>porog||stl>=50*Point)
{
OrderClose(OrderTicket(),OrderLots(),price,5,Violet); // close position
return(0);
}
}
}
}
if ((ob+os)==0 && (b+s)==0 && (ls+lb)==0 && Hour()!=0){blok=0; oppr=0; blokd=0;}
if ((os+ob)>0) {blok=1;blokd=1;}
if (((MathAbs(oppr-Close[0]))/Point)>=15) blokd=0;
if (j>0) { blokd=0;j=0;} else blokd=1;
if (blokd==0)
{
for (cnt=OrdersTotal()-1;cnt>=0;cnt--)
{
if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)==false) { Print("Error in OrderSelect!"); break; }
if (OrderType()==OP_BUYSTOP && OrderSymbol()==Symbol()) OrderDelete(OrderTicket());
if (OrderType()==OP_SELLSTOP && OrderSymbol()==Symbol()) OrderDelete(OrderTicket());
}
}
//-----------------------------------------------Indicators Setting--------------------------------------------
ssig=0;bsig=0;
if ((s+b+os+ob+ls+lb)>0){korh=0;korl=0;}
if (korh==1 && hod>0) {ssig=1;SetIndexArrow(0,242);}
if ((MaxH-Close[0])>10*Point)
{
if (korh==1 && hod<=-5) {bsig=1;SetIndexArrow(0,241);}
}
else
{
if (korh==1 && hod<=-5) {ssig=1;SetIndexArrow(0,242);}
}
if (korl==1 && hod<0) {bsig=1;SetIndexArrow(0,241);}
if ((Close[0]-MinL)>10*Point)
{
if (korl==1 && hod>=5){ssig=1;SetIndexArrow(0,242);}
}
else
{
if (korh==1 && hod>=5) {bsig=1;SetIndexArrow(0,241);}
}
Comment("Data: ",Year(),".",Month(),".",Day()," Time ",Hour(),":",Minute()," MidLine=",(MaxH+MinL)/2," MaxPr: ",MaxPr,
" MinPr=",MinPr," Blok=",blok," TInd=",j," Reg=",reg,"\n","StoProfit=",porog," Canal=",canal,
" Profit=",MathRound(OrderProfit())," Hod=",hod," KorL=",korl," KorH=",korh," DBlok=",blokd," OrdPrice=",oppr);
//-------------------------------------------------Open Positions---------------------------------------------
if ((ob+os+lb+ls)==0) blok=0;
if (blok==0)
{
int t = ttime;
for(i=HistoryTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL || OrderMagicNumber() > 2) continue; // ýòî îòëîæåíûé îðäåð
//----
if(OrderProfit()>0) break;
if(OrderProfit()<0 && OrderClosePrice() == OrderStopLoss())
{
// t = 3600*72; // ïîñëå ëîñÿ âûäåðæèì ïàóçó ÷òî áû íå íàðâàòüñÿ íà åùå îäíîãî
t = 3600; // ïîñëå ëîñÿ âûäåðæèì ïàóçó ÷òî áû íå íàðâàòüñÿ íà åùå îäíîãî
break;
}
}
if((CurTime()-OrderCloseTime())<t) return(0);
if(ssig==1 && s==0 && os==0)
{
arrdown=CharToStr(Time[0]);
ObjectCreate(arrdown, OBJ_ARROW, 0,Time[0],High[0]+10*Point);
ObjectSet(arrdown,OBJPROP_ARROWCODE,242);
ObjectSet(arrdown,OBJPROP_COLOR,Yellow);
ticket=OrderSend(Symbol(),OP_SELLSTOP,ord_lot,Bid-zap*Point,5,Bid+StopLoss*Point-zap*Point,Bid-TakeProfit*Point-zap*Point,"Sculp_Sell",1,CurTime()+3600*6,GreenYellow);
ps=Bid;
return(0);
}
if(bsig==1 && b==0 && ob==0 && (Bid+5*Point)>Ask)
{
arrup=CharToStr(Time[0]);
ObjectCreate(arrup, OBJ_ARROW, 0,Time[0],Low[0]-10*Point);
ObjectSet(arrup,OBJPROP_ARROWCODE,241);
ObjectSet(arrup,OBJPROP_COLOR,Blue);
ticket=OrderSend(Symbol(),OP_BUYSTOP,ord_lot,Ask+zap*Point,5,Ask-StopLoss*Point+zap*Point,Ask+TakeProfit*Point+zap*Point,"Sculp_Buy",2,CurTime()+3600*6,Violet);
pb=Ask;
return(0);
}
}
//----------------------------TrailingStop--------------------------
if((b+s)>0 && TrailingStop>0)
{
for (cnt=0;cnt<OrdersTotal();cnt++)
{
os=0;ob=0;
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()==OP_BUY && OrderSymbol()==Symbol()) // check for symbol
{
if ((Bid-OrderOpenPrice())>TrailingStop*Point)
{
if(OrderStopLoss()<Bid-Point*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
return(0);
}
}
}
if(OrderType()==OP_SELL && OrderSymbol()==Symbol()) // check for symbol
{
if((OrderOpenPrice()-Ask)>Point*TrailingStop)
{
if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
return(0);
}
}
}
}
}
//-------------------------Ïîäòÿíåì îòëîæåííûå îðäåðà--------------------
/*if((ob+os)>0)
{
for (cnt=0;cnt<OrdersTotal();cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()==OP_SELLSTOP && OrderSymbol()==Symbol())
{
//Comment("Hello");
if (ps< Bid)
{
arrdown=CharToStr(Time[0]);
ObjectCreate(arrdown, OBJ_ARROW, 0,Time[0],High[0]+10*Point);
ObjectSet(arrdown,OBJPROP_ARROWCODE,242);
ObjectSet(arrdown,OBJPROP_COLOR,Yellow);
ps=Bid;
OrderModify(OrderTicket(),Bid-zap*Point,0,0,0,Green);
OrderModify(OrderTicket(),Bid-zap*Point,Bid+StopLoss*Point-zap*Point,Bid-Point*TakeProfit-zap*Point,0,Green);
return(0);
}
}
if(OrderType()==OP_BUYSTOP && OrderSymbol()==Symbol())
{
if (pb>Ask)
{
arrup=CharToStr(Time[0]);
ObjectCreate(arrup, OBJ_ARROW, 0,Time[0],Low[0]-10*Point);
ObjectSet(arrup,OBJPROP_ARROWCODE,241);
ObjectSet(arrup,OBJPROP_COLOR,Blue);
pb=Ask;
OrderModify(OrderTicket(),Ask+zap*Point,0,0,0,Violet);
OrderModify(OrderTicket(),Ask+zap*Point,Ask+zap*Point-StopLoss*Point,Ask+zap*Point+TakeProfit*Point,0,Violet);
return(0);
}
}
}
}*/
return(0);
}//---------End------------
Comments