double TradeSizeOptimized(string Psymbol,double slot,bool maxlimit) { double lot=slot; //--- normalize and check limits double stepvol=SymbolInfoDouble(Psymbol,SYMBOL_VOLUME_STEP); if (stepvol!=0) lot=stepvol*MathFloor(lot/stepvol); else lot=0; double minvol=SymbolInfoDouble(Psymbol,SYMBOL_VOLUME_MIN); if(lotmaxvol)&&maxlimit) lot=stepvol*MathFloor(maxvol/stepvol);; return (lot); } double NormalizePrice(string Psymbol,double price,bool type) { double ret=0,stepprice=SymbolInfoDouble(Psymbol,SYMBOL_TRADE_TICK_SIZE); if (stepprice!=0) { if (type) ret=stepprice*floor(price/stepprice); else ret=stepprice*ceil(price/stepprice); } return(ret); } double CalcVol(string psymbol,double atr,double risco) { double vol=0; double tick_size=SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE); double tick_value=SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_VALUE); double SaldoConta=Money.Balance(); double RiscoMaximoPar=risco*SaldoConta;//100.000*0,005=500 if ((atr!=INT_MIN)&&(atr>0))//INT_MIN==fixed(!VolFixed) { if(SymbolInfoInteger(psymbol,SYMBOL_TRADE_CALC_MODE)==SYMBOL_CALC_MODE_FOREX)//FOREX { int bIsUSD; double TickLote, Ask, AskNomeSegundoPar, ValorPipProjetado; string NomeSegundoPar; TickLote = tick_value; Ask = atr; bIsUSD = 1+StringFind(psymbol,"USD",0); ValorPipProjetado = (RiscoMaximoPar)*tick_size; AskNomeSegundoPar = 0; NomeSegundoPar = ""; //bIsUSD == 4 implica XXX/USD if(bIsUSD==4){if ((TickLote!=0)&&(Ask!=0)){vol = ValorPipProjetado/(TickLote*Ask); vol = TradeSizeOptimized(psymbol,vol,false); //PrintTest(bIsUSD,ValorPipProjetado,tick_size,tick_value,TickLote,NomeSegundoPar,AskNomeSegundoPar,Ask,vol); return(vol);}} //bIsUSD == 1 implica USD/XXX if(bIsUSD==1){if ((TickLote!=0)&&(Ask!=0)){vol = ValorPipProjetado/(TickLote/Ask); vol = TradeSizeOptimized(psymbol,vol,false); //PrintTest(bIsUSD,ValorPipProjetado,tick_size,tick_value,TickLote,NomeSegundoPar,AskNomeSegundoPar,Ask,vol); return(vol);}} /////////////////////////////////////////////////// // bIsUSD == 0 implica XXX/XXX; // // XXX/XXX implica 2 casos, exemplos: // // // // Caso 1 (AUDNZD) = (NZDUSD) / (AUDNZD) // // // // Caso 2 (EURCHF) = (1/USDCHF) / (EURCHF) // // // /////////////////////////////////////////////////// NomeSegundoPar = psymbol; string TresUltimosCaracteresDoPar = StringSubstr(NomeSegundoPar,3); //Setando valores iniciais... NomeSegundoPar = TresUltimosCaracteresDoPar+"USD"; AskNomeSegundoPar = SymbolInfoDouble(NomeSegundoPar,SYMBOL_ASK); //Caso 1 if(AskNomeSegundoPar != 0 ){vol = ValorPipProjetado/((TickLote*AskNomeSegundoPar)/Ask); vol = TradeSizeOptimized(psymbol,vol,false); //PrintTest(bIsUSD,ValorPipProjetado,tick_size,tick_value,TickLote,NomeSegundoPar,AskNomeSegundoPar,Ask,vol); return(vol);} //Caso 2 if(AskNomeSegundoPar == 0 ){NomeSegundoPar = "USD"+TresUltimosCaracteresDoPar; AskNomeSegundoPar = SymbolInfoDouble(NomeSegundoPar,SYMBOL_ASK); if(AskNomeSegundoPar != 0 ){vol = ValorPipProjetado/((TickLote*(1.0/AskNomeSegundoPar)/Ask)); vol = TradeSizeOptimized(psymbol,vol,false); //PrintTest(bIsUSD,ValorPipProjetado,tick_size,tick_value,TickLote,NomeSegundoPar,AskNomeSegundoPar,Ask,vol); return(vol);}} } //ACIMA = FOREX, ABAIXO = FUTURO if(SymbolInfoInteger(psymbol,SYMBOL_TRADE_CALC_MODE)==SYMBOL_CALC_MODE_EXCH_FUTURES)//BMF { if (tick_value!=0) vol=TradeSizeOptimized(psymbol,RiscoMaximoPar*tick_size/(tick_value*atr),false); } else { vol=TradeSizeOptimized(psymbol,RiscoMaximoPar/atr,false); } return (vol); } else if (atr==INT_MIN) return(Nvol*SymbolInfoDouble(psymbol,SYMBOL_VOLUME_MIN)); //else if (atr<0) return(Nvol*SymbolInfoDouble(psymbol,SYMBOL_VOLUME_MIN)) else return(0); } double calc_profit(string psymbol,ENUM_DEAL_TYPE type,ulong magic=ALL_LOCKS) { MqlDateTime thisday; TimeLocal(thisday); thisday.hour=9; thisday.min=0; thisday.sec=0; //thisday.day=1; datetime today=StructToTime(thisday); HistorySelect(today,TimeLocal()); int total=HistoryDealsTotal(); double varday=0; for (int i=0;i100) { Print("ERROR Creating position data for ",symbol); return(false); } cnt++; } return(false); } //grava as variáveis no disco bool SavePositionData() { int fhandle=FileOpen(fname,FILE_TXT|FILE_WRITE|FILE_CSV,";"); if (fhandle!=INVALID_HANDLE) { FileWrite(fhandle,sl,tp,priceref,atr,trailing_target,last_time,order_type); FileClose(fhandle); return(true); } return(false); } //lê as variáveis do disco bool LoadPositionData() { int fhandle=FileOpen(fname,FILE_TXT|FILE_READ|FILE_CSV,";"); if (fhandle!=INVALID_HANDLE) { sl=FileReadNumber(fhandle); tp=FileReadNumber(fhandle); priceref=FileReadNumber(fhandle); atr=FileReadNumber(fhandle); trailing_target=FileReadNumber(fhandle); last_time=(datetime)FileReadNumber(fhandle); order_type=(OrderTypes)FileReadNumber(fhandle); FileClose(fhandle); return(true); } return(false); } //retorna os dados da ordem void GetPositionData(double& osl,double& otp,OrderTypes& ot,double& opriceref,double& oatr,double& otarget,datetime& otime) { otp=tp; osl=sl; ot=order_type; opriceref=priceref; oatr=atr; otarget=trailing_target; otime=last_time; } //seta os dados da ordem bool SetPositionData(double osl,double otp,OrderTypes ot,double opriceref,double oatr,double otarget,datetime otime) { sl=osl; tp=otp; order_type=ot; priceref=opriceref; atr=oatr; trailing_target=otarget; last_time=otime; if (!book) { MarketBookAdd(symbol); book=true; } return(SavePositionData()); } //verifica se a pendente expirou e a deleta void CheckPendingExpiration(int orderexpiration,bool auction) { datetime ordertime=(datetime)OrderGetInteger(ORDER_TIME_SETUP); datetime thistime=TimeCurrent(); if ((thistime>(ordertime+OrdExp*60))&&(!auction)) Trade.OrderDelete(OrderGetInteger(ORDER_TICKET)); } // This MQL5 function is used to manage trailing orders in a trading system. It takes several parameters related to different trailing strategies and modifies the order based on these strategies and current market conditions. // // The function first retrieves the current bid and ask prices, as well as the tick size for the symbol. It then gets the open price and volume of the order. // // The function then retrieves the market book information and determines the maximum buy and sell volumes and the corresponding prices. It also determines the back price, which is the price behind the current order price in the market book. // // The function then checks if the order is a buy limit or sell limit order and adjusts the back price and maximum price accordingly. // // The function then determines the target price based on various trailing strategies. If the order is a buy limit order, it checks if the current price is not equal to the target price and if the tolerance and target conditions are met. If these conditions are met, it modifies the order to the target price. If not, it checks if the aggression strategy is enabled and if the current price is not equal to the ask price. If these conditions are met, it modifies the order to the ask price. // // If the order is a sell limit order, it does a similar check and modifies the order to the target price or bid price based on the conditions. // // This function is used to dynamically adjust the order price based on market conditions and the specified trailing strategies. It helps to maximize the profit and minimize the loss in a trading system. // void OrderTrailing(/*TrailingTypes trailing*/bool TTTop,bool TTMountain,bool TTSoma1,bool TTEscape,bool TTAlvo,bool TTTol,double TTTolFrac,bool TTAggression) { double bid=SymbolInfoDouble(symbol,SYMBOL_BID); double ask=SymbolInfoDouble(symbol,SYMBOL_ASK); double ticksize=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE); double backprice=0,maxbuy=0,maxsell=0,max=0; double myprice=OrderGetDouble(ORDER_PRICE_OPEN); double myvolume=OrderGetDouble(ORDER_VOLUME_CURRENT); backprice=myprice; //---------book--------- MqlBookInfo BookInfo[]; MarketBookGet(_Symbol,BookInfo); for(int i=0;imaxsell) { maxsell=BookInfo[i].volume_real; max=BookInfo[i].price; } if ((BookInfo[i].price==myprice)&&(i!=0)) backprice=BookInfo[i-1].price; } if ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_LIMIT)&&(BookInfo[i].type==BOOK_TYPE_BUY)) { if (BookInfo[i].volume>maxbuy) { maxbuy=BookInfo[i].volume_real; max=BookInfo[i].price; } if ((BookInfo[i].price==myprice)&&(i!=(ArraySize(BookInfo)-1))) backprice=BookInfo[i+1].price; } } if (OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_LIMIT) {backprice+=ticksize;if (maxbuy>myvolume) max+=ticksize;} else if (OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_LIMIT) {backprice-=ticksize;if (maxsell>myvolume) max-=ticksize;} //backprice=price -> tem que pegar pelo book - soma 1 ticksize se for buy, subtrai 1 ticksize se for sell //max=price -> max deveria ser preço do volume máximo (maxbuy,maxsell) (+1,-1) //se sou o máximo, não muda max //---------------------- if (OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_LIMIT) { double tgtprice=(TTTop?bid:(TTMountain?max:bid)); datetime tempo=TimeLocal()-last_time; if (TTSoma1&&(!TTEscape)&&(myprice==MathMax(tgtprice,myprice))&&(tempo>60)) tgtprice=MathMax(tgtprice,myprice)+ticksize;//soma 1 double tol=(tgtprice-priceref)/atr; if ((!TTSoma1)&&TTEscape&&(myprice==tgtprice)&&(myprice!=backprice))//Escape: se sou bid/ask e o preço atrás de mim +-1 ticksize não sou eu, elimine o gap Trade.OrderModify(OrderGetInteger(ORDER_TICKET),NormalizePrice(symbol,backprice,true),0,0,(ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME),(datetime)OrderGetInteger(ORDER_TIME_EXPIRATION)); else if ((myprice!=tgtprice)//me coloca no bid ou antes da montanha &&(TTTol?(tol60)) tgtprice=MathMin(tgtprice,myprice)-ticksize;//soma 1 double tol=(priceref-tgtprice)/atr; if ((!TTSoma1)&&TTEscape&&(myprice==tgtprice)&&(myprice!=backprice))//Escape: se sou bid/ask e o preço atrás de mim +-1 ticksize não sou eu, elimine o gap Trade.OrderModify(OrderGetInteger(ORDER_TICKET),NormalizePrice(symbol,backprice,true),0,0,(ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME),(datetime)OrderGetInteger(ORDER_TIME_EXPIRATION)); else if ((myprice!=tgtprice)//me coloca no bid ou antes da montanha &&(TTTol?(tol=trailing_target):true)//Alvo ) { Trade.OrderModify(OrderGetInteger(ORDER_TICKET),NormalizePrice(symbol,tgtprice,true),0,0,(ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME),(datetime)OrderGetInteger(ORDER_TIME_EXPIRATION)); last_time=TimeLocal(); } else if (TTAggression&&(myprice!=bid)//Se não posso escapar, e já sou o ask ou antes da montanha, testa a agressão &&(TTTol?(((priceref-bid)/atr)=trailing_target):true)//Alvo ) { Trade.OrderModify(OrderGetInteger(ORDER_TICKET),NormalizePrice(symbol,bid,true),0,0,(ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME),(datetime)OrderGetInteger(ORDER_TIME_EXPIRATION)); last_time=TimeLocal(); } } } }; bool PositionClosePartial(string psymbol,double myvol,bool usepending) { double pvol=PositionGetDouble(POSITION_VOLUME); double cvol=myvol; if (cvol>pvol) cvol=pvol; if (usepending) { if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) return(Trade.SellLimit(cvol,SymbolInfoDouble(psymbol,SYMBOL_ASK),psymbol,0,0,ORDER_TIME_SPECIFIED,TimeLocal()+OrdExp*60,"Close")); if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) return(Trade.BuyLimit(cvol,SymbolInfoDouble(psymbol,SYMBOL_BID),psymbol,0,0,ORDER_TIME_SPECIFIED,TimeLocal()+OrdExp*60,"Close")); } else { if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) return(Trade.Sell(cvol,psymbol,0,0,0,"Close")); if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) return(Trade.Buy(cvol,psymbol,0,0,0,"Close")); } return (false); } bool PositionClose(bool usepending,string psymbol,CLock &lock,bool usevollimit=false,double vollimitfrac=0.01,double mvol=0) { double thisvol=PositionGetDouble(POSITION_VOLUME); if (usevollimit) { if (thisvol>(vollimitfrac*mvol)) thisvol=TradeSizeOptimized(psymbol,vollimitfrac*mvol,false);//limita o volume a x% da média if (PositionClosePartial(psymbol,thisvol,usepending)) { MyPrint("Closing: "+psymbol); lock.SetLock(CLOSE_LOCK,TimeLocal()+15,0); return(true); } } else { if (usepending) { if (PositionClosePartial(psymbol,thisvol,usepending)) { MyPrint("Closing: "+psymbol); lock.SetLock(CLOSE_LOCK,TimeLocal()+15,0); return(true); } } else { if (Trade.PositionClose(psymbol))//(PositionClosePartial(psymbol,thisvol)) { MyPrint("Closing: "+psymbol); lock.SetLock(CLOSE_LOCK,TimeLocal()+15,0); return(true); } } } MyPrint("Error closing: "+psymbol); return(false); } bool CheckDT(bool possel,string psymbol,bool not_locked,CLock &lock,bool usevollimit,double vollimitfrac,double mvol) { bool dtend=false; MqlDateTime today; TimeLocal(today); if (Forex2) return(false); if (((today.hour>=DTHour)&&(today.min>=DTMin))||(today.hour>=(DTHour+1)))//horário de fechamento day trade { if (possel&¬_locked) { // if(Trade.PositionClose(psymbol)) if (PositionClose(false,psymbol,lock,usevollimit,vollimitfrac,mvol))//não fechar usando pendentes { MyPrint("Closing horário day trade: "+psymbol); // lock.SetLock(CLOSE_LOCK,TimeLocal()+15,0); } } dtend=true; } if (((today.hour<=OCHour)&&(today.min<=OCMin))||(today.hour<(OCHour))) dtend=false;//horário operacional else dtend=true; return(dtend); } bool ExpiraPos(bool usepending,OrderData &PosData,string psymbol,int Pexp,bool not_locked,CLock &lock,bool usevollimit,double vollimitfrac,double mvol) { if ((TimeLocal()>(PositionGetInteger(POSITION_TIME)+Pexp*3600))&¬_locked)//expiração de posições { if (usepending) { double sl=0,tp=0,priceref=0,atr=0,target=0; datetime lasttime=0; OrderTypes ot=OTNone; PosData.GetPositionData(sl,tp,ot,priceref,atr,target,lasttime); double bid=SymbolInfoDouble(psymbol,SYMBOL_BID),ask=SymbolInfoDouble(psymbol,SYMBOL_ASK); if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) priceref=ask; else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) priceref=bid; //TODO: set the target if (PosData.SetPositionData(sl,tp,OTClose,priceref,atr,target,TimeLocal())) if (PositionClose(true,psymbol,lock,usevollimit,vollimitfrac,mvol)) { MyPrint("Closing expiração: "+psymbol); lock.SetLock(CLOSE_LOCK,TimeLocal()+15,0); } } else { if (PositionClose(false,psymbol,lock,usevollimit,vollimitfrac,mvol)) { MyPrint("Closing expiração: "+psymbol); lock.SetLock(CLOSE_LOCK,TimeLocal()+15,0); } } return true; } return false; } bool open_buy(string psymbol,double ATR,double vol, ENUM_STOP_TYPES Sl_TypeA,double SLLevelA,ENUM_TIMEFRAMES SlTimeframeA,int SlBarsA, ENUM_STOP_TYPES Tp_TypeA,double TPLevelA,ENUM_TIMEFRAMES TpTimeframeA,int TpBarsA, string op_cmt,int op_magic,bool UsePending,double OSlippage,CLock &lock,double SlFixed,double TpFixed ) { double price=SymbolInfoDouble(psymbol,SYMBOL_ASK); double bid=SymbolInfoDouble(psymbol,SYMBOL_BID); double sl=0; double tp=0; sl=set_sl_tp(psymbol,price,ATR,Sl_TypeA,SLLevelA,SlTimeframeA,SlBarsA,SlFixed); tp=set_tp_sl(psymbol,price,ATR,Tp_TypeA,TPLevelA,TpTimeframeA,TpBarsA,TpFixed); if ((sl>=0)&&(tp>=0)&&(vol>0) &&(sl!=0?(slprice):true) ) { //Print (MyName+": "+psymbol+": "+op_cmt+" SL:",sl," TP:",tp); Trade.SetExpertMagicNumber(op_magic); if (UsePending) { if (OSlippage!=0) price=NormalizePrice(psymbol,bid+OSlippage,true); double posvol=0; if (PositionSelect(psymbol)) { posvol=PositionGetDouble(POSITION_VOLUME); if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) posvol=-posvol; } if (Trade.BuyLimit(vol,price,psymbol,0,0,ORDER_TIME_SPECIFIED,TimeLocal()+OrdExp*60,op_cmt)) { MyPrint (MyName+": "+psymbol+": "+op_cmt+" SL:",DoubleToString(sl,2)," TP:",DoubleToString(tp,2)); lock.SetLock(op_magic,TimeLocal()+15,vol+posvol); } } else { double posvol=0; if (PositionSelect(psymbol)) { posvol=PositionGetDouble(POSITION_VOLUME); if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) posvol=-posvol; } if (Trade.Buy(vol,psymbol,price,sl,tp,op_cmt)) { MyPrint (MyName+": "+psymbol+": "+op_cmt+" SL:",DoubleToString(sl,2)," TP:",DoubleToString(tp,2)); lock.SetLock(op_magic,TimeLocal()+15,vol+posvol); } } return true; } return false; } bool open_sell(string psymbol,double ATR,double vol, ENUM_STOP_TYPES Sl_TypeA,double SLLevelA,ENUM_TIMEFRAMES SlTimeframeA,int SlBarsA, ENUM_STOP_TYPES Tp_TypeA,double TPLevelA,ENUM_TIMEFRAMES TpTimeframeA,int TpBarsA, string op_cmt,int op_magic,bool UsePending,double OSlippage,CLock &lock,double SlFixed,double TpFixed ) { double price=SymbolInfoDouble(psymbol,SYMBOL_BID); double ask=SymbolInfoDouble(psymbol,SYMBOL_ASK); double sl=0; double tp=0; sl=set_tp_sl(psymbol,price,ATR,Sl_TypeA,SLLevelA,SlTimeframeA,SlBarsA,SlFixed); tp=set_sl_tp(psymbol,price,ATR,Tp_TypeA,TPLevelA,TpTimeframeA,TpBarsA,TpFixed); if ((sl>=0)&&(tp>=0)&&(vol>0) &&(sl!=0?(sl>price):true) &&(tp!=0?(tp