AI_auto_traders_JBS/Adaptive_MultiMarket_EA_v1.mq5
421 líneas
19 KiB
MQL5
Jubaer KCTV
2026-11-02 00:09:02 +00:00
//+------------------------------------------------------------------+
//| Adaptive MultiMarket EA v1.00 |
//| Prototype based on the first five user-defined feature groups. |
//| AI is optional and OFF by default; configure a compatible local |
//| HTTP service to enable it. |
//+------------------------------------------------------------------+
#property strict
#property version "1.00"
#property description "Multi-symbol configurable EA: technical/momentum confirmation, ATR exits, recovery sizing, profit lock, CSV log."
#include <Trade/Trade.mqh>
CTrade trade;
//--- General
input ulong InpMagicNumber=2026110201;
input bool InpAllowBuy=true;
input bool InpAllowSell=true;
input int InpMaxSlippagePoints=30;
input bool InpOnePositionPerSymbol=true;
input bool InpUseGlobalRecoveryLock=true;
input int InpLossesBeforeGlobalLock=3; // lock other new entries after 3 consecutive losses, starting with recovery trade #4
//--- Confirmation switches (any selected filters must pass)
input bool InpUseTechnicalConfirmation=true;
input bool InpUseMomentumConfirmation=true;
input bool InpUseAIConfirmation=false; // OFF until a compatible local/API endpoint is configured
input double InpAIMinProbability=51.0;
input string InpAIEndpoint=""; // HTTP endpoint; response should contain buy_probability and sell_probability numbers
input int InpAIRequestTimeoutMs=2500;
input int InpAIHorizonMinutes=15; // 15, 30 or 60
Jubaer KCTV
2026-11-02 00:12:58 +00:00
input int InpSignalCheckSeconds=5; // evaluate a fresh signal every five minutes
Jubaer KCTV
2026-11-02 00:09:02 +00:00
//--- Indicators / technical filters
input ENUM_TIMEFRAMES InpTrendTF1=PERIOD_H1;
input ENUM_TIMEFRAMES InpTrendTF2=PERIOD_M15;
input ENUM_TIMEFRAMES InpFastTF=PERIOD_M5;
input int InpSMAFast=14;
input int InpSMASlow=21;
input int InpADXPeriod=14;
input double InpADXMinimum=18.0;
input int InpRSIPeriod=14;
input double InpRSIBuyMinimum=52.0;
input double InpRSISellMaximum=48.0;
input int InpMACDFast=12;
input int InpMACDSlow=26;
input int InpMACDSignal=9;
input int InpATRPeriod=14;
//--- Momentum: Points mode or ADR/ratio mode
input bool InpUseAutomaticADRMovement=true;
input int InpADRDays=30;
input double InpADRDivisor=200.0;
input double InpManualMovementPoints=15.0;
input int InpMomentumWindowSeconds=60; // 30 or 60
input double InpMomentumMultiplier=1.0;
//--- ATR exits / manual exits
input bool InpUseATRStops=true;
input double InpSL_ATR_Multiplier=1.5;
input double InpTP_ATR_Multiplier=2.0;
input double InpManualSLPoints=300.0;
input double InpManualTPPoints=400.0;
//--- Lot sizing and loss recovery
input bool InpAutoRiskLot=true;
input bool InpRiskUseEquity=false;
input double InpRiskPercent=1.0;
input double InpManualLot=0.01;
input double InpLossLotMultiplier=2.0;
input double InpMinimumLot=0.01;
input double InpMaximumLot=5.0;
//--- Position management
input bool InpEnableProfitLock=true;
input double InpLockStartPercent=60.0;
input double InpLockStartSLPercent=30.0;
input double InpLockStepPercent=10.0;
input double InpLockStepSLStart=30.0;
input double InpLockAt95Percent=85.0;
input double InpPost95TrailKeepPercent=32.0;
input bool InpExtendTPAfter95=true;
input double InpExtendedTP_ATR_Multiplier=3.0;
//--- Reporting
input bool InpEnableCSVReport=true;
input bool InpSeparateReportByDate=true;
input string InpReportFolder="AdaptiveEA";
int hFast1=INVALID_HANDLE,hSlow1=INVALID_HANDLE,hFast2=INVALID_HANDLE,hSlow2=INVALID_HANDLE;
int hADX=INVALID_HANDLE,hRSI=INVALID_HANDLE,hMACD=INVALID_HANDLE,hATR=INVALID_HANDLE;
datetime g_lastSignalCheck=0;
double g_recentBid=0.0;
datetime g_recentTickTime=0;
double g_momentumStartBid=0.0;
datetime g_momentumStartTime=0;
string g_symbol;
string Key(const string suffix){ return "AM_EA_"+(string)InpMagicNumber+"_"+g_symbol+"_"+suffix; }
string GlobalLockKey(){ return "AM_EA_"+(string)InpMagicNumber+"_GLOBAL_LOCK"; }
string GlobalOwnerKey(){ return "AM_EA_"+(string)InpMagicNumber+"_GLOBAL_OWNER"; }
double SymbolCode(){ double h=0.0; for(int i=0;i<StringLen(g_symbol);i++) h=h*31.0+(double)StringGetCharacter(g_symbol,i); return h; }
bool ReadBuffer(const int handle,const int buffer,const int shift,double &value)
{
if(handle==INVALID_HANDLE) return false;
double a[]; ArraySetAsSeries(a,true);
if(CopyBuffer(handle,buffer,shift,1,a)!=1) return false;
if(!MathIsValidNumber(a[0])) return false;
value=a[0]; return true;
}
double NormalizeVolume(double lots)
{
double step=SymbolInfoDouble(g_symbol,SYMBOL_VOLUME_STEP);
double minv=SymbolInfoDouble(g_symbol,SYMBOL_VOLUME_MIN);
double maxv=SymbolInfoDouble(g_symbol,SYMBOL_VOLUME_MAX);
if(step<=0) step=0.01;
minv=MathMax(minv,InpMinimumLot); maxv=MathMin(maxv,InpMaximumLot);
lots=MathMax(minv,MathMin(maxv,lots));
lots=MathFloor(lots/step+1e-8)*step;
int digits=2; if(step<0.01) digits=3; if(step<0.001) digits=4;
return NormalizeDouble(lots,digits);
}
int ConsecutiveLosses()
{
if(!HistorySelect(0,TimeCurrent())) return 0;
int losses=0; ulong lastSeen=0;
for(int i=HistoryDealsTotal()-1;i>=0;i--)
{
ulong d=HistoryDealGetTicket(i); if(d==0) continue;
if(HistoryDealGetString(d,DEAL_SYMBOL)!=g_symbol) continue;
if((ulong)HistoryDealGetInteger(d,DEAL_MAGIC)!=InpMagicNumber) continue;
ENUM_DEAL_ENTRY e=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(d,DEAL_ENTRY);
if(e!=DEAL_ENTRY_OUT && e!=DEAL_ENTRY_OUT_BY) continue;
if(d==lastSeen) continue; lastSeen=d;
double net=HistoryDealGetDouble(d,DEAL_PROFIT)+HistoryDealGetDouble(d,DEAL_SWAP)+HistoryDealGetDouble(d,DEAL_COMMISSION);
if(net<0.0) losses++; else if(net>0.0) break;
}
return losses;
}
bool HasOurPosition()
{
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i); if(ticket==0) continue;
if(PositionGetString(POSITION_SYMBOL)==g_symbol && (ulong)PositionGetInteger(POSITION_MAGIC)==InpMagicNumber) return true;
}
return false;
}
bool GlobalLockActive()
{
if(!InpUseGlobalRecoveryLock) return false;
if(!GlobalVariableCheck(GlobalLockKey())) return false;
return GlobalVariableGet(GlobalLockKey())>0.5;
}
void SetGlobalLock(const bool on){ if(InpUseGlobalRecoveryLock){ GlobalVariableSet(GlobalLockKey(),on?1.0:0.0); if(on) GlobalVariableSet(GlobalOwnerKey(),SymbolCode()); } }
bool GetATR(double &atr){ return ReadBuffer(hATR,0,1,atr) && atr>0.0; }
double AverageDailyRange()
{
int n=MathMax(1,InpADRDays); MqlRates rates[]; ArraySetAsSeries(rates,true);
int got=CopyRates(g_symbol,PERIOD_D1,1,n,rates);
if(got<=0) return 0.0;
double sum=0.0; int count=0;
for(int i=0;i<got;i++){ double r=rates[i].high-rates[i].low; if(r>0){sum+=r;count++;} }
if(count==0) return 0.0;
return sum/(double)count;
}
double RequiredMovementPrice()
{
if(InpUseAutomaticADRMovement)
{
double adr=AverageDailyRange();
if(adr>0.0 && InpADRDivisor>0.0) return (adr/InpADRDivisor)*InpMomentumMultiplier;
}
return InpManualMovementPoints*_Point*InpMomentumMultiplier;
}
bool TechnicalSignal(int &direction,double &atr,double &rsi,double &adx,double &macdMain,double &macdSignal)
{
direction=0;
double f1,s1,f2,s2;
if(!ReadBuffer(hFast1,0,1,f1)||!ReadBuffer(hSlow1,0,1,s1)||!ReadBuffer(hFast2,0,1,f2)||!ReadBuffer(hSlow2,0,1,s2)) return false;
if(!ReadBuffer(hADX,0,1,adx)||!ReadBuffer(hRSI,0,1,rsi)||!ReadBuffer(hMACD,0,1,macdMain)||!ReadBuffer(hMACD,1,1,macdSignal)||!GetATR(atr)) return false;
double close1=iClose(g_symbol,InpTrendTF2,1); if(close1<=0) return false;
bool buy=(f1>s1 && f2>s2 && close1>f2 && adx>=InpADXMinimum && rsi>=InpRSIBuyMinimum && macdMain>macdSignal);
bool sell=(f1<s1 && f2<s2 && close1<f2 && adx>=InpADXMinimum && rsi<=InpRSISellMaximum && macdMain<macdSignal);
if(buy) direction=1; else if(sell) direction=-1;
return true;
}
bool MomentumPass(const int direction,double &moved)
{
moved=0.0; if(!InpUseMomentumConfirmation) return true;
MqlTick tick; if(!SymbolInfoTick(g_symbol,tick)) return false;
datetime now=TimeCurrent();
if(g_momentumStartTime==0 || (now-g_momentumStartTime)>MathMax(1,InpMomentumWindowSeconds))
{ g_momentumStartTime=now; g_momentumStartBid=tick.bid; return false; }
moved=MathAbs(tick.bid-g_momentumStartBid);
double need=RequiredMovementPrice(); if(need<=0) return false;
if(direction>0) return (tick.bid-g_momentumStartBid)>=need;
if(direction<0) return (g_momentumStartBid-tick.bid)>=need;
return false;
}
// Optional HTTP JSON service. Add endpoint to MT5: Tools > Options > Expert Advisors > Allow WebRequest.
bool AIConfirm(const int direction,double &probability)
{
probability=0.0;
if(!InpUseAIConfirmation) return true;
if(StringLen(InpAIEndpoint)==0) return false;
string payload="{\"symbol\":\""+g_symbol+"\",\"horizon_minutes\":"+(string)InpAIHorizonMinutes+",\"direction\":\""+(direction>0?"BUY":"SELL")+"\"}";
char data[],result[]; StringToCharArray(payload,data,0,WHOLE_ARRAY,CP_UTF8);
string headers="Content-Type: application/json\r\n"; string response_headers;
ResetLastError(); int code=WebRequest("POST",InpAIEndpoint,headers,InpAIRequestTimeoutMs,data,result,response_headers);
if(code<200 || code>=300) return false;
string body=CharArrayToString(result,0,WHOLE_ARRAY,CP_UTF8);
string key=(direction>0?"buy_probability":"sell_probability"); int pos=StringFind(body,key);
if(pos<0) return false; pos=StringFind(body,":",pos); if(pos<0) return false;
string tail=StringSubstr(body,pos+1); StringReplace(tail," ",""); StringReplace(tail,"\"","");
int end=StringFind(tail,","); if(end<0) end=StringFind(tail,"}"); if(end<0) return false;
probability=StringToDouble(StringSubstr(tail,0,end));
return probability>=InpAIMinProbability;
}
bool CalculateStops(const int direction,const double atr,double &sl,double &tp)
{
MqlTick t; if(!SymbolInfoTick(g_symbol,t)) return false;
double slDist,tpDist;
if(InpUseATRStops){ slDist=atr*InpSL_ATR_Multiplier; tpDist=atr*InpTP_ATR_Multiplier; }
else { slDist=InpManualSLPoints*_Point; tpDist=InpManualTPPoints*_Point; }
if(slDist<=0||tpDist<=0) return false;
int digits=(int)SymbolInfoInteger(g_symbol,SYMBOL_DIGITS);
if(direction>0){ sl=NormalizeDouble(t.ask-slDist,digits); tp=NormalizeDouble(t.ask+tpDist,digits); }
else { sl=NormalizeDouble(t.bid+slDist,digits); tp=NormalizeDouble(t.bid-tpDist,digits); }
long stops=SymbolInfoInteger(g_symbol,SYMBOL_TRADE_STOPS_LEVEL); double minDist=stops*_Point;
if(direction>0 && (t.ask-sl<minDist || tp-t.ask<minDist)) return false;
if(direction<0 && (sl-t.bid<minDist || t.bid-tp<minDist)) return false;
return true;
}
double CalculateLots(const double slDistance)
{
int losses=ConsecutiveLosses();
double base=InpManualLot;
if(InpAutoRiskLot)
{
double capital=InpRiskUseEquity?AccountInfoDouble(ACCOUNT_EQUITY):AccountInfoDouble(ACCOUNT_BALANCE);
double riskMoney=capital*InpRiskPercent/100.0;
double tickVal=SymbolInfoDouble(g_symbol,SYMBOL_TRADE_TICK_VALUE);
double tickSize=SymbolInfoDouble(g_symbol,SYMBOL_TRADE_TICK_SIZE);
if(tickVal>0 && tickSize>0 && slDistance>0) base=riskMoney/(slDistance/tickSize*tickVal);
}
double lots=base*MathPow(MathMax(1.0,InpLossLotMultiplier),losses);
return NormalizeVolume(lots);
}
void WriteReport(const string event,const int direction,const double probability,const double rsi,const double adx,const double macd,const double atr,const double moved,const double lots,const double price,const double sl,const double tp,const double pnl=0.0)
{
if(!InpEnableCSVReport) return;
string day=TimeToString(TimeCurrent(),TIME_DATE); StringReplace(day,".","");
string filename=InpReportFolder+"/"+g_symbol+"_"+day+".csv";
int flags=FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI|FILE_SHARE_READ|FILE_SHARE_WRITE;
int f=FileOpen(filename,flags,';'); if(f==INVALID_HANDLE) return;
if(FileSize(f)==0) FileWrite(f,"Time","Event","Symbol","Direction","AI_Probability","RSI","ADX","MACD_Main","ATR","Momentum_PriceMove","Lots","Price","SL","TP","NetPnL");
FileSeek(f,0,SEEK_END);
FileWrite(f,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),event,g_symbol,(direction>0?"BUY":(direction<0?"SELL":"NA")),DoubleToString(probability,2),DoubleToString(rsi,2),DoubleToString(adx,2),DoubleToString(macd,6),DoubleToString(atr,_Digits),DoubleToString(moved,_Digits),DoubleToString(lots,2),DoubleToString(price,_Digits),DoubleToString(sl,_Digits),DoubleToString(tp,_Digits),DoubleToString(pnl,2));
FileClose(f);
}
void ManagePosition()
{
if(!InpEnableProfitLock) return;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i); if(ticket==0) continue;
if(PositionGetString(POSITION_SYMBOL)!=g_symbol || (ulong)PositionGetInteger(POSITION_MAGIC)!=InpMagicNumber) continue;
long type=PositionGetInteger(POSITION_TYPE); bool buy=(type==POSITION_TYPE_BUY);
double entry=PositionGetDouble(POSITION_PRICE_OPEN),sl=PositionGetDouble(POSITION_SL),tp=PositionGetDouble(POSITION_TP);
double current=buy?SymbolInfoDouble(g_symbol,SYMBOL_BID):SymbolInfoDouble(g_symbol,SYMBOL_ASK);
double initialTP=GlobalVariableCheck(Key("INITIAL_TP"))?GlobalVariableGet(Key("INITIAL_TP")):tp;
double initialSL=GlobalVariableCheck(Key("INITIAL_SL"))?GlobalVariableGet(Key("INITIAL_SL")):sl;
double full=MathAbs(initialTP-entry); if(full<=0) continue;
double progress=(buy?(current-entry):(entry-current))/full*100.0;
double desiredSL=sl;
if(progress>=InpLockAt95Percent)
{
double locked=full*(InpLockAt95Percent/100.0);
double extra=MathMax(0.0,(buy?(current-entry):(entry-current))-locked);
double lockDist=locked+extra*InpPost95TrailKeepPercent/100.0;
desiredSL=buy?entry+lockDist:entry-lockDist;
if(InpExtendTPAfter95)
{
double atr; if(GetATR(atr))
{
double ext=atr*InpExtendedTP_ATR_Multiplier;
double newTP=buy?current+ext:current-ext;
if(buy && newTP>tp) tp=newTP; if(!buy && newTP<tp) tp=newTP;
}
}
}
else if(progress>=InpLockStartPercent)
{
double step=InpLockStepPercent; if(step<=0) step=10;
double stage=MathFloor((progress-InpLockStartPercent)/step);
double lockPct=InpLockStepSLStart+stage*step;
if(progress>=InpLockAt95Percent) lockPct=InpLockAt95Percent;
lockPct=MathMin(lockPct,InpLockAt95Percent);
if(lockPct<InpLockStartSLPercent) lockPct=InpLockStartSLPercent;
desiredSL=buy?entry+full*lockPct/100.0:entry-full*lockPct/100.0;
}
int digits=(int)SymbolInfoInteger(g_symbol,SYMBOL_DIGITS); desiredSL=NormalizeDouble(desiredSL,digits);
bool improve=(buy?(desiredSL>sl && desiredSL<current):(sl==0.0 || (desiredSL<sl && desiredSL>current)));
if(improve || (tp!=PositionGetDouble(POSITION_TP))) trade.PositionModify(ticket,improve?desiredSL:sl,tp);
}
}
void TryOpenTrade()
{
if(InpOnePositionPerSymbol && HasOurPosition()) return;
if(GlobalLockActive()) return;
int dir=0; double atr=0,rsi=0,adx=0,macd=0,macds=0;
if(InpUseTechnicalConfirmation)
{
if(!TechnicalSignal(dir,atr,rsi,adx,macd,macds) || dir==0) return;
}
else
{
if(!GetATR(atr)) atr=SymbolInfoDouble(g_symbol,SYMBOL_POINT)*100.0;
// Without technical filter, direction is inferred from short-term SMA on M5.
double a=iClose(g_symbol,InpFastTF,1),b=iClose(g_symbol,InpFastTF,2); if(a==0||b==0||a==b) return; dir=(a>b?1:-1);
}
if((dir>0&&!InpAllowBuy)||(dir<0&&!InpAllowSell)) return;
double prob=0.0;
if(InpUseAIConfirmation && !AIConfirm(dir,prob)) return;
double moved=0.0;
if(InpUseMomentumConfirmation && !MomentumPass(dir,moved)) return;
double sl,tp; if(!CalculateStops(dir,atr,sl,tp)) return;
double price=(dir>0?SymbolInfoDouble(g_symbol,SYMBOL_ASK):SymbolInfoDouble(g_symbol,SYMBOL_BID));
double lots=CalculateLots(MathAbs(price-sl)); if(lots<=0) return;
trade.SetExpertMagicNumber(InpMagicNumber); trade.SetDeviationInPoints(InpMaxSlippagePoints);
bool ok=(dir>0?trade.Buy(lots,g_symbol,0.0,sl,tp,"AdaptiveEA BUY"):trade.Sell(lots,g_symbol,0.0,sl,tp,"AdaptiveEA SELL"));
if(ok)
{
GlobalVariableSet(Key("INITIAL_TP"),tp); GlobalVariableSet(Key("INITIAL_SL"),sl);
if(ConsecutiveLosses()>=InpLossesBeforeGlobalLock) SetGlobalLock(true);
WriteReport("OPEN",dir,prob,rsi,adx,macd,atr,moved,lots,price,sl,tp,0.0);
}
}
int OnInit()
{
g_symbol=_Symbol;
hFast1=iMA(g_symbol,InpTrendTF1,InpSMAFast,0,MODE_SMA,PRICE_CLOSE);
hSlow1=iMA(g_symbol,InpTrendTF1,InpSMASlow,0,MODE_SMA,PRICE_CLOSE);
hFast2=iMA(g_symbol,InpTrendTF2,InpSMAFast,0,MODE_SMA,PRICE_CLOSE);
hSlow2=iMA(g_symbol,InpTrendTF2,InpSMASlow,0,MODE_SMA,PRICE_CLOSE);
hADX=iADX(g_symbol,InpFastTF,InpADXPeriod); hRSI=iRSI(g_symbol,InpFastTF,InpRSIPeriod,PRICE_CLOSE);
hMACD=iMACD(g_symbol,InpFastTF,InpMACDFast,InpMACDSlow,InpMACDSignal,PRICE_CLOSE);
hATR=iATR(g_symbol,InpFastTF,InpATRPeriod);
trade.SetExpertMagicNumber(InpMagicNumber); trade.SetDeviationInPoints(InpMaxSlippagePoints);
if(InpEnableCSVReport) FolderCreate(InpReportFolder);
EventSetTimer(1);
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
EventKillTimer();
if(hFast1!=INVALID_HANDLE) IndicatorRelease(hFast1); if(hSlow1!=INVALID_HANDLE) IndicatorRelease(hSlow1);
if(hFast2!=INVALID_HANDLE) IndicatorRelease(hFast2); if(hSlow2!=INVALID_HANDLE) IndicatorRelease(hSlow2);
if(hADX!=INVALID_HANDLE) IndicatorRelease(hADX); if(hRSI!=INVALID_HANDLE) IndicatorRelease(hRSI);
if(hMACD!=INVALID_HANDLE) IndicatorRelease(hMACD); if(hATR!=INVALID_HANDLE) IndicatorRelease(hATR);
}
void OnTick()
{
ManagePosition();
Jubaer KCTV
2026-11-02 00:12:58 +00:00
int checkInterval=MathMax(1,InpSignalCheckSeconds);
if(InpUseMomentumConfirmation)
{
int maxInterval=MathMax(1,InpMomentumWindowSeconds/6);
checkInterval=MathMin(checkInterval,maxInterval);
}
Jubaer KCTV
2026-11-02 00:09:02 +00:00
datetime now=TimeCurrent();
Jubaer KCTV
2026-11-02 00:12:58 +00:00
if(g_lastSignalCheck==0 ||
(now-g_lastSignalCheck)>=checkInterval)
{
g_lastSignalCheck=now;
TryOpenTrade();
}
Jubaer KCTV
2026-11-02 00:09:02 +00:00
}
void OnTimer()
{
ManagePosition();
// Global lock is released by the recovery-owner chart after its profitable recovery close.
}
void OnTradeTransaction(const MqlTradeTransaction &trans,const MqlTradeRequest &request,const MqlTradeResult &result)
{
if(trans.type!=TRADE_TRANSACTION_DEAL_ADD || trans.deal==0) return;
if(!HistoryDealSelect(trans.deal)) return;
if(HistoryDealGetString(trans.deal,DEAL_SYMBOL)!=g_symbol) return;
if((ulong)HistoryDealGetInteger(trans.deal,DEAL_MAGIC)!=InpMagicNumber) return;
ENUM_DEAL_ENTRY e=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
if(e!=DEAL_ENTRY_OUT && e!=DEAL_ENTRY_OUT_BY) return;
double pnl=HistoryDealGetDouble(trans.deal,DEAL_PROFIT)+HistoryDealGetDouble(trans.deal,DEAL_SWAP)+HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
if(pnl>0.0 && ConsecutiveLosses()==0 && GlobalLockActive() && GlobalVariableCheck(GlobalOwnerKey()) && GlobalVariableGet(GlobalOwnerKey())==SymbolCode()) SetGlobalLock(false);
WriteReport("CLOSE",0,0,0,0,0,0,0,HistoryDealGetDouble(trans.deal,DEAL_VOLUME),HistoryDealGetDouble(trans.deal,DEAL_PRICE),0,0,pnl);
}
//+------------------------------------------------------------------+