//+------------------------------------------------------------------+ //| ExpertMM1.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property description "Exemplo de EA" #include //Instatiate Library for Positions Information #include input double lots=0.01; // volume em lotes input int slippage=10; // derrapagem admissível input bool revers=false; // invertemos o sinal? input ulong EXPERT_MAGIC=0; // MagicNumber do EA double trade_lot; CTrade m_trade; // Trades Info and Executions library COrderInfo m_order; //Library for Orders information CPositionInfo m_position; // Library for all position features and information //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- definimos o volume correto double min_lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); trade_lot=lots>min_lot? lots:min_lot; //--- criamos o identificador do indicador ATR //--- inicialização bem-sucedida do EA return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- relatamos o código de desligamento do EA Print(__FILE__,": Código de motivo da desinicialização = ",reason); //--- destroy timer EventKillTimer(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- if(isNewBar()) { } //--- fim da função OnTick } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- } //+------------------------------------------------------------------+ //| Trade function | //+------------------------------------------------------------------+ void OnTrade() { //--- } //+------------------------------------------------------------------+ //| TradeTransaction function | //+-----------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { //--- } //+------------------------------------------------------------------+ //| Tester function | //+------------------------------------------------------------------+ double OnTester() { //--- double ret=0.0; //--- //--- return(ret); } //+------------------------------------------------------------------+ //| TesterInit function | //+------------------------------------------------------------------+ void OnTesterInit() { //--- } //+------------------------------------------------------------------+ //| TesterPass function | //+------------------------------------------------------------------+ void OnTesterPass() { //--- } //+------------------------------------------------------------------+ //| TesterDeinit function | //+------------------------------------------------------------------+ void OnTesterDeinit() { //--- } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Returns true if a new bar has appeared for a symbol/period pair | //+------------------------------------------------------------------+ bool isNewBar() { //--- memorize the time of opening of the last bar in the static variable static datetime last_time=0; //--- current time datetime lastbar_time=SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); //--- if it is the first call of the function if(last_time==0) { //--- set the time and exit last_time=lastbar_time; return(false); } //--- if the time differs if(last_time!=lastbar_time) { //--- memorize the time and return true last_time=lastbar_time; return(true); } //--- if we passed to this line, then the bar is not new; return false return(false); } //+------------------------------------------------------------------+ //| Returns type of a pending order in a random way | //+------------------------------------------------------------------+ ENUM_ORDER_TYPE GetRandomType() { int t=MathRand()%2; //--- 0<=t<2 switch(t) { case(0):return(ORDER_TYPE_BUY_LIMIT); case(1):return(ORDER_TYPE_SELL_LIMIT); } //--- incorrect value return(WRONG_VALUE); } //+------------------------------------------------------------------+ //| Deletes all pending orders with specified ORDER_MAGIC | //+------------------------------------------------------------------+ void DeleteAllOrdersByMagic(long const magic_number) { ulong order_ticket; //--- go through all pending orders for(int i=OrdersTotal()-1;i>=0;i--) if((order_ticket=OrderGetTicket(i))>0) //--- order with appropriate ORDER_MAGIC if(magic_number==OrderGetInteger(ORDER_MAGIC)) { MqlTradeResult result={}; MqlTradeRequest request={}; request.order=order_ticket; request.action=TRADE_ACTION_REMOVE; OrderSend(request,result); //--- write the server reply to log Print(__FUNCTION__,": ",result.comment," reply code ",result.retcode); } //--- } int GetOrdersTotalByMagic(long const magic_number) { ulong order_ticket; int total=0; //--- go through all pending orders for(int i=0;i0) if(magic_number==OrderGetInteger(ORDER_MAGIC)) total++; //--- return(total); } //+------------------------------------------------------------------+ //| Buy at a market price with a specified volume | //+------------------------------------------------------------------+ bool Buy(double volume,ulong deviation=10,ulong magicnumber=0) { //--- buy at a market price return (MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber)); } //+------------------------------------------------------------------+ //| Sell at a market price with a specified volume | //+------------------------------------------------------------------+ bool Sell(double volume,ulong deviation=10,ulong magicnumber=0) { //--- sell at a market price return (MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber)); } //+------------------------------------------------------------------+ //| Sets a pending order in a random way | //+------------------------------------------------------------------+ uint SendRandomPendingOrder(long const magic_number) { //--- prepare a request MqlTradeRequest request={}; request.action=TRADE_ACTION_PENDING; // setting a pending order request.magic=magic_number; // ORDER_MAGIC request.symbol=_Symbol; // symbol request.volume=0.01; // volume in 0.01 lots request.sl=0; request.tp=0; // Take Profit is not specified //--- form the order type request.type=GetRandomType(); // order type //--- form the price for the pending order request.price=GetRandomPrice(request.type); // open price if(request.type==ORDER_TYPE_BUY_LIMIT || request.type==ORDER_TYPE_SELL_STOP) { request.tp=SymbolInfoDouble(Symbol(),SYMBOL_BID)+300*_Point; // Stop Loss is not specified request.sl=SymbolInfoDouble(Symbol(),SYMBOL_BID)-200*_Point; } else // ORDER_TYPE_SELL_LIMIT or ORDER_TYPE_BUY_STOP { request.tp=SymbolInfoDouble(Symbol(),SYMBOL_ASK)-300*_Point; request.sl=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+200*_Point; } //--- send a trade request MqlTradeResult result={}; OrderSend(request,result); //--- write the server reply to log Print(__FUNCTION__,":",result.comment); if(result.retcode==10016) Print(result.bid,result.ask,result.price); //--- return code of the trade server reply return result.retcode; } //+------------------------------------------------------------------+ //| Prepare and send a trade request | //+------------------------------------------------------------------+ bool MarketOrder(ENUM_ORDER_TYPE type,double volume,ulong slip,ulong magicnumber,ulong pos_ticket=0) { //--- declaring and initializing structures MqlTradeRequest request={}; MqlTradeResult result={}; double price=SymbolInfoDouble(Symbol(),SYMBOL_BID); if(type==ORDER_TYPE_BUY) price=SymbolInfoDouble(Symbol(),SYMBOL_ASK); if(type==ORDER_TYPE_BUY_LIMIT) price=SymbolInfoDouble(Symbol(),SYMBOL_ASK); if(type==ORDER_TYPE_SELL) price=SymbolInfoDouble(Symbol(),SYMBOL_BID); if(type==ORDER_TYPE_SELL_LIMIT) price=SymbolInfoDouble(Symbol(),SYMBOL_BID); //--- request parameters request.action =TRADE_ACTION_DEAL; // trading operation type request.position =pos_ticket; // position ticket if closing request.symbol =Symbol(); // symbol request.volume =volume; // volume request.type =type; // order type request.price =price; // trade price request.deviation=slip; // allowable deviation from the price request.magic =magicnumber; // order MagicNumber //--- send a request if(!OrderSend(request,result)) { //--- display data on failure PrintFormat("OrderSend %s %s %.2f at %.5f error %d", request.symbol,EnumToString(type),volume,request.price,GetLastError()); return (false); } //--- inform of a successful operation PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order); return (true); } //+------------------------------------------------------------------+ //| Returns price in a random way | //+------------------------------------------------------------------+ double GetRandomPrice(ENUM_ORDER_TYPE type) { int t=(int)type; //--- stop levels for the symbol int distance=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL); //--- receive data of the last tick MqlTick last_tick={}; SymbolInfoTick(_Symbol,last_tick); //--- calculate price according to the type double price; if(t==ORDER_TYPE_BUY_LIMIT ) // ORDER_TYPE_BUY_LIMIT or ORDER_TYPE_SELL_STOP { price=last_tick.bid; // depart from price Bid price=price-((MathRand()%10)*5)*_Point; } if(t==ORDER_TYPE_SELL_LIMIT ) // ORDER_TYPE_SELL_LIMIT or ORDER_TYPE_BUY_STOP { price=last_tick.ask; // depart from price Ask price=price+((MathRand()%10)*5)*_Point; } //--- return(price); } //+------------------------------------------------------------------+ //| Close all positions | //+------------------------------------------------------------------+ void CloseAllPositions() { for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol } //+------------------------------------------------------------------+ //| Is position exists | //+------------------------------------------------------------------+ bool IsPositionExists(void) { for(int i=PositionsTotal()-1;i>=0;i--) if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties return(true); //--- return(false); } bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type) { //--- Getting the opening price MqlTick mqltick; SymbolInfoTick(symb,mqltick); double price=mqltick.ask; if(type==ORDER_TYPE_SELL) price=mqltick.bid; //--- values of the required and free margin double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE); //--- call of the checking function if(!OrderCalcMargin(type,symb,lots,price,margin)) { //--- something went wrong, report and return false Print("Error in ",__FUNCTION__," code=",GetLastError()); return(false); } //--- if there are insufficient funds to perform the operation if(margin>free_margin) { //--- report the error and return false Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError()); return(false); } //--- checking successful return(true); } //+------------------------------------------------------------------+ //| Check the correctness of the order volume | //+------------------------------------------------------------------+ bool CheckVolumeValue(double volume,string &description) { //--- minimal allowed volume for trade operations double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); if(volumemax_volume) { description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume); return(false); } //--- get minimal step of volume changing double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP); int ratio=(int)MathRound(volume/volume_step); if(MathAbs(ratio*volume_step-volume)>0.0000001) { description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f", volume_step,ratio*volume_step); return(false); } description="Correct volume value"; return(true); } //+------------------------------------------------------------------+ //| Check if another order can be placed | //+------------------------------------------------------------------+ bool IsNewOrderAllowed() { //--- get the number of pending orders allowed on the account int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); //--- if there is no limitation, return true; you can send an order if(max_allowed_orders==0) return(true); //--- if we passed to this line, then there is a limitation; find out how many orders are already placed int orders=OrdersTotal(); //--- return the result of comparing return(orders=0) { //--- if we have exhausted the volume if(max_volume-opened_volume<=0) return(0); //--- volume of the open position doesn't exceed max_volume double orders_volume_on_symbol=PendingsVolume(symbol); allowed_volume=max_volume-opened_volume-orders_volume_on_symbol; if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume; } return(allowed_volume); }