//+------------------------------------------------------------------+ //| 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 #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; double lastAskHit; 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 CAccountInfo m_account; double OpenVolume=0; //+------------------------------------------------------------------+ //| 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() { double dailyHigh = iHigh(Symbol(), PERIOD_M15, 1); // Get the daily high double dailyLow = iLow(Symbol(), PERIOD_M15, 1); // Get the daily low double bidPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID); // Get the current Bid price double askPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK); // Get the current Ask price if(m_account.MarginLevel() < 200) CloseAllPositions(); if(GetAccountOpenPositions(Symbol())>0.20 || GetAccountOpenPositions(Symbol())<-0.20 ) CloseAllPositions(); if(isNewBar()) { // Check if there are no open positions MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = Symbol(); request.volume = 0.01; // Fixed lot size 0.01 request.deviation = 20; // Increased slippage tolerance request.magic = EXPERT_MAGIC; // Use user-defined Magic Number request.comment = "Daily High/Low EA"; // Set order filling mode dynamically ENUM_ORDER_TYPE_FILLING fillingMode; if (SymbolInfoInteger(Symbol(), SYMBOL_FILLING_MODE) & SYMBOL_FILLING_IOC) fillingMode = ORDER_FILLING_IOC; else fillingMode = ORDER_FILLING_RETURN; request.type_filling = fillingMode; request.type_time = ORDER_TIME_GTC; // Good till canceled // ✅ Buy condition: Ask price reaches near the daily high if (askPrice >= dailyHigh & GetAccountOpenPositions(Symbol())<=0) { //if(GetAccountOpenPositions(Symbol())>0) // CloseAllPositions(); request.type = ORDER_TYPE_SELL; request.price = askPrice; // Buying at Ask price request.sl = askPrice + 100 * Point(); Print("Placing BUY order at Ask: ", askPrice); // Send the order if (!OrderSend(request, result)) Print("Trade execution error: ", result.comment); else Print("Order placed: ", result.price, " | Magic Number: ", EXPERT_MAGIC); } // ✅ Sell condition: Bid price reaches near the daily low else if (bidPrice <= dailyLow & GetAccountOpenPositions(Symbol())>=0) { ///if(GetAccountOpenPositions(Symbol())<0) //CloseAllPositions(); request.type = ORDER_TYPE_BUY; request.price = bidPrice; // Selling at Bid price; request.sl = request.price - 100 * Point(); Print("Placing SELL order at Bid: ", bidPrice); // Send the order if (!OrderSend(request, result)) Print("Trade execution error: ", result.comment); else Print("Order placed: ", result.price, " | Magic Number: ", EXPERT_MAGIC); } else return; // No trade condition met } } //+------------------------------------------------------------------+ //| 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<4 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 //request.type=ORDER_TYPE_BUY_LIMIT; //--- form the price for the pending order request.price=GetRandomPrice(request.type); // open price if(request.type==ORDER_TYPE_BUY_LIMIT) { request.tp=iHigh(Symbol(),PERIOD_D1,0); request.sl=iLow(Symbol(),PERIOD_D1,0); } else if(request.type==ORDER_TYPE_SELL_LIMIT) // ORDER_TYPE_SELL_LIMIT or ORDER_TYPE_BUY_STOP { request.tp=iLow(Symbol(),PERIOD_D1,0); request.sl=iHigh(Symbol(),PERIOD_D1,0); } else return false; //--- 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); if(distance<=0) distance=150; else distance+=50; //--- 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-distance*_Point; } else 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+distance*_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 lot,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,lot,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)," ",lot," ",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); } //+------------------------------------------------------------------+ //| Return the volume open in symbol | //+------------------------------------------------------------------+ double GetAccountOpenPositions(string symbol) { double totalVolume=0; // Loop through all open positions and print their volume int totalPositions = PositionsTotal(); // Get the total number of open positions for (int i = 0; i < totalPositions; i++) { if (m_position.SelectByIndex(i)) // Select the position by index { if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) totalVolume += PositionGetDouble(POSITION_VOLUME); // Get the volume of the position if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) totalVolume -= PositionGetDouble(POSITION_VOLUME); // Get the volume of the position } } return totalVolume; }