//+——————————————————————+
//| Gold_M15_Adaptive_Squeeze (Compact) |
//+——————————————————————+
#property strict
input double InpLotSize = 0.01;
input int InpATRPeriod = 14;
input int InpATRLongPeriod = 100;
input double InpSqueezeRatio = 0.7;
input int InpMaxSpread = 40;
input int InpMagicNumber = 888888;
datetime lastBarTime;
bool initOK = false;
int OnInit() {
Print(“EA init. Period: “, Period());
if(!IsTesting() && Period() != PERIOD_M15) return(INIT_FAILED);
if(Bars >= InpATRLongPeriod + 5) initOK = true;
else Print(“Need more bars: “, Bars, “/”, InpATRLongPeriod+5);
return(INIT_SUCCEEDED);
}
void OnTick() {
if(!initOK && Bars >= InpATRLongPeriod+5) { initOK = true; Print(“Activated”); }
if(!initOK) return;
if(CountPos()>0 && CountPending()>0) DelPending();
if(IsNewBar()) {
if(CountPos()>0) TrailStop();
else if(CountPending()==0) PlaceOrders();
}
}
bool IsNewBar() {
if(Time[0]!=lastBarTime) { lastBarTime=Time[0]; return true; }
return false;
}
void PlaceOrders() {
if(Bars < InpATRLongPeriod+5) return;
double atrNow = iATR(Symbol(),PERIOD_M15,InpATRPeriod,1);
if(atrNow<=0) return;
double sum=0; int cnt=0;
for(int i=1;i<=InpATRLongPeriod;i++) {
double v=iATR(Symbol(),PERIOD_M15,InpATRPeriod,i);
if(v>0) { sum+=v; cnt++; }
}
if(cnt==0) return;
double avg=sum/cnt;
if(avg<=0 || atrNow/avg >= InpSqueezeRatio) return;
if((Ask-Bid)/Point > InpMaxSpread) return;
double h=High[1], l=Low[1];
if((h-l) <= InpMaxSpread*Point) return;
OrderSend(Symbol(),OP_BUYSTOP,InpLotSize,h,3,l,0,”AB”,InpMagicNumber,0,clrBlue);
OrderSend(Symbol(),OP_SELLSTOP,InpLotSize,l,3,h,0,”AS”,InpMagicNumber,0,clrRed);
}
void DelPending() {
for(int i=OrdersTotal()-1;i>=0;i–) {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==InpMagicNumber)
if(OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)
OrderDelete(OrderTicket());
}
}
void TrailStop() {
for(int i=OrdersTotal()-1;i>=0;i–) {
if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES) || OrderMagicNumber()!=InpMagicNumber) continue;
double sl=OrderStopLoss();
if(OrderType()==OP_BUY) {
double newSL=Low[1];
if(newSL>sl && (Bid-newSL)>MarketInfo(Symbol(),MODE_STOPLEVEL)*Point)
OrderModify(OrderTicket(),OrderOpenPrice(),newSL,0,0,clrBlue);
} else if(OrderType()==OP_SELL) {
double newSL=High[1];
if((newSL<sl || sl==0) && (newSL-Ask)>MarketInfo(Symbol(),MODE_STOPLEVEL)*Point)
OrderModify(OrderTicket(),OrderOpenPrice(),newSL,0,0,clrRed);
}
}
}
int CountPos() {
int c=0;
for(int i=0;i<OrdersTotal();i++)
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==InpMagicNumber && (OrderType()==OP_BUY || OrderType()==OP_SELL)) c++;
return c;
}
int CountPending() {
int c=0;
for(int i=0;i<OrdersTotal();i++)
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==InpMagicNumber && (OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)) c++;
return c;
}

