//+------------------------------------------------------------------+ //| ACM_Snipper.mq5 | //| Anderson C Mourão | //| https://www.mql5.com | //+------------------------------------------------------------------+ #define MName "Expert Advisor MT5 ACM_Bot_Lettus123" #define MVersion "25.09" #define MBuild "2025-09-06 10:50 UTC(-3)" #define MCopyright "Copyright \x00A9 2025, Anderson C Mourão, All rights reserved" #define MProfile "https://forge.mql5.io/AndersonMourao" #property strict #property version MVersion #property description MName #property description "MetaTrader Expert Advisor (Build " MBuild ")" #property copyright MCopyright #property link MProfile #property strict //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include #include #include //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CTrade trade; bool order_sent = false; MqlDateTime stm, date_struct = {}; datetime tm = TimeTradeServer(); datetime now = tm; datetime vTradingStartTime, vTradingEndTime; double bid, ask, high, low, close, open, SL, TP, nTR, max_price; // int ATRPeriod = 14; // int ATRShift = 0; // Current bar // int ATRHandle; // ATR indicator handle int QtdAberta; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- set chart properties ChartSetInteger(0, CHART_SHOW_TICKER, true); // Display a symbol ticker in the upper left corner. Setting CHART_SHOW_TICKER to 'false' also sets CHART_SHOW_OHLC to 'false' and disables OHLC ChartSetInteger(0, CHART_SHOW_OHLC, true); // Display OHLC values in the upper left corner. Setting CHART_SHOW_OHLC to 'true' also sets CHART_SHOW_TICKER to 'true' and enables the ticker ChartSetInteger(0, CHART_SHOW_BID_LINE, true); // Display Bid values as a horizontal line in a chart ChartSetInteger(0, CHART_SHOW_ASK_LINE, true); // Display Ask values as a horizontal line in a chart ChartSetInteger(0, CHART_SHOW_LAST_LINE, true); // Display Last values as a horizontal line in a chart ChartSetInteger(0, CHART_SHOW_PERIOD_SEP, false); // Remove vertical separators between adjacent periods ChartSetInteger(0, CHART_SHOW_GRID, false); // Remove grid in the chart ChartSetInteger(0, CHART_SHOW_VOLUMES, false); // Remove volume in the chart //--- convert current time to structure TimeToStruct(tm, stm); //--- escrevemos os valores de entrada nos campos correspondentes da estrutura date_struct.year = stm.year; date_struct.mon = stm.mon; date_struct.day = stm.day; //--- convertemos a data e a hora da estrutura em uma variável com o tipo datetime e datetime dia_hoje = StructToTime(date_struct); Print("Inicializando - ", MQL5InfoString(MQL5_PROGRAM_NAME), " - ", MVersion, " - ", MBuild); PrintAccountInfo(); vTradingStartTime = dia_hoje; // vTradingStartTime = dia_hoje + 9 * 3600; vTradingEndTime = dia_hoje + 18 * 3600; Print("Hora local = ", tm, " Hora abertura = ", vTradingStartTime, " Hora fechamento = ", vTradingEndTime); Comment("Wait 5 minutes to startn each looping trading - ", now, "\n", MQL5InfoString(MQL5_PROGRAM_NAME), "\nVersion ", MVersion, " - ", MBuild); EventSetTimer(10); // 5 minuto bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); close = iClose(_Symbol, PERIOD_CURRENT, 0); high = iHigh(_Symbol, PERIOD_CURRENT, 0); low = iLow(_Symbol, PERIOD_CURRENT, 0); open = iOpen(_Symbol, PERIOD_CURRENT, 0); nTR = (((high - low) + MathAbs(close - open)) * 0.5); //--- return INIT_SUCCEEDED if initialization completed successfully return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Print("Finalizando - ", MQL5InfoString(MQL5_PROGRAM_NAME)); EventKillTimer(); PrintAccountInfo(); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check if trading is allowed based on the defined start and end times if(IsTradingBlocked()) { // If not allowed, stop processing the rest of the OnTick function Print("Fora do horário de mercado!"); CloseAllOpenOrders(); ExpertRemove(); } bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); close = iClose(_Symbol, PERIOD_CURRENT, 0); high = iHigh(_Symbol, PERIOD_CURRENT, 0); low = iLow(_Symbol, PERIOD_CURRENT, 0); open = iOpen(_Symbol, PERIOD_CURRENT, 0); order_sent = PositionBuySellTicket() != 0; nTR = (((high - low) + MathAbs(close - open)) * 0.5); QtdAberta = SymbolOpenPositionsTotal(_Symbol); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { if(order_sent && !IsTradingBlocked()) { TrailingStop(); Comment("Looping trading in trailstop ", now, "\nQuantidade de ordens abertas: ", QtdAberta); ChartRedraw(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CloseAllOpenOrders() { Print("Fechando todas as ordens abertas!"); CloseAllPendingOrders(); trade.PositionClose(_Symbol); } //+------------------------------------------------------------------+ void CloseAllPendingOrders() { int total_orders = OrdersTotal(); for(int i = total_orders - 1; i >= 0; i--) { // decrescente mesmo, vai ate 0 ulong ticket = OrderGetTicket(i); trade.OrderDelete(ticket); } } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ ulong PositionBuySellTicket() { //--- in a loop by all account orders ulong ticket = 0; int total_orders = OrdersTotal(); for(int i = total_orders - 1; i >= 0; i--) { //--- get the ticket of the next position by automatically selecting a position to access its properties ticket = OrderGetTicket(i); //--- if the position is not selected, then go to the next iteration of the loop if(ticket == 0) continue; return (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE ? ticket : ticket); } return (0); } //+------------------------------------------------------------------+ //| Display real properties of the selected position in the journal | //+------------------------------------------------------------------+ void PositionPropertiesDoublePrint(const uint header_width = 0) { uint w = 0; string header = ""; double value = 0; //--- get the account currency, position symbol and the number of decimal places for the symbol string currency = AccountInfoString(ACCOUNT_CURRENCY); string symbol = PositionGetString(POSITION_SYMBOL); int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); //--- define the header text and the width of the header field //--- if the header width is passed to the function equal to zero, then the width will be the size of the header line + 1 header = "Volume:"; w = (header_width == 0 ? header.Length() + 1 : header_width); //--- get and display the position volume with the specified header width in the journal if(!PositionGetDouble(POSITION_VOLUME, value)) return; PrintFormat("%-*s%-.2f", w, header, value); //--- display the position price value in the journal header = "Price open:"; w = (header_width == 0 ? header.Length() + 1 : header_width); if(!PositionGetDouble(POSITION_PRICE_OPEN, value)) return; PrintFormat("%-*s%-.*f", w, header, digits, value); //--- display the StopLoss value in the journal header = "StopLoss:"; w = (header_width == 0 ? header.Length() + 1 : header_width); if(!PositionGetDouble(POSITION_SL, value)) return; PrintFormat("%-*s%-.*f", w, header, digits, value); //--- display the TakeProfit value in the journal header = "TakeProfit:"; w = (header_width == 0 ? header.Length() + 1 : header_width); if(!PositionGetDouble(POSITION_TP, value)) return; PrintFormat("%-*s%-.*f", w, header, digits, value); //--- display the 'Price current' value in the journal header = "Price current:"; w = (header_width == 0 ? header.Length() + 1 : header_width); if(!PositionGetDouble(POSITION_PRICE_CURRENT, value)) return; PrintFormat("%-*s%-.*f", w, header, digits, value); //--- display the accumulated swap value in the journal header = "Swap:"; w = (header_width == 0 ? header.Length() + 1 : header_width); if(!PositionGetDouble(POSITION_SWAP, value)) return; PrintFormat("%-*s%-.2f", w, header, value); //--- display the current profit value to the journal header = "Profit:"; w = (header_width == 0 ? header.Length() + 1 : header_width); if(!PositionGetDouble(POSITION_PROFIT, value)) return; PrintFormat("%-*s%-.2f %s", w, header, value, currency); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void TrailingStop() { ulong ticket = PositionBuySellTicket(); if(ticket > 0) { double price_open = PositionGetDouble(POSITION_PRICE_OPEN); double price_current = PositionGetDouble(POSITION_PRICE_CURRENT); double sl = PositionGetDouble(POSITION_SL); double tp = PositionGetDouble(POSITION_TP); int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double new_sl = 0.0; // max_price = (AccountInfoDouble(ACCOUNT_BALANCE) * 0.01); // 1% do saldo // PrintFormat("Ordem %I64u - Tipo %d - Preço Abertura: %.*f - Preço Atual: %.*f - SL Atual: %.*f", ticket, type, digits, price_open, digits, price_current, digits, sl); //--- Trailing Stop para ordens BUY // Move o stop apenas se o preço atual estiver acima do preço de abertura if(type == POSITION_TYPE_BUY) { if(price_current < max_price) return; max_price = price_current + nTR; new_sl = price_current - nTR; // Move SL to 50 points below current price if(new_sl > sl && new_sl > price_open) { // Ensure SL only moves up and is above open price if(trade.PositionModify(_Symbol, new_sl, 0)) { PrintFormat("Trailing Stop moved for BUY position. New SL: %.*f", digits, new_sl); } else { PrintFormat("Failed to move Trailing Stop for BUY position. Error: %d", GetLastError()); } } } else if(type == POSITION_TYPE_SELL) { if(price_current > max_price) return; max_price = price_current - nTR; new_sl = price_current + nTR; // Move SL to 10 points above current price if(new_sl < sl && new_sl < price_open) { // Ensure SL only moves down and is below open price if(trade.PositionModify(_Symbol, new_sl, 0)) { PrintFormat("Trailing Stop moved for SELL position. New SL: %.*f", digits, new_sl); } else { PrintFormat("Failed to move Trailing Stop for SELL position. Error: %d", GetLastError()); } } } } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| PrintAccountInfo() | //+------------------------------------------------------------------+ void PrintAccountInfo() { //--- trade server name string server = AccountInfoString(ACCOUNT_SERVER); //--- account number int login = (int)AccountInfoInteger(ACCOUNT_LOGIN); //--- long value output long leverage = AccountInfoInteger(ACCOUNT_LEVERAGE); printf("%s %d: leverage = 1:%I64d", server, login, leverage); //--- account currency string currency = AccountInfoString(ACCOUNT_CURRENCY); //--- double value output with 2 digits after the decimal point double equity = AccountInfoDouble(ACCOUNT_EQUITY); printf("%s %d: account equity = %.2f %s", server, login, equity, currency); //--- double value output with mandatory output of the +/- sign double profit = AccountInfoDouble(ACCOUNT_PROFIT); printf("%s %d: current result for open positions = %+.2f %s", server, login, profit, currency); //--- double value output with variable number of digits after the decimal point double point_value = SymbolInfoDouble(_Symbol, SYMBOL_POINT); string format_string = StringFormat("%%s: point value = %%.%df", _Digits); printf(format_string, _Symbol, point_value); //--- int value output int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); printf("%s: current spread in points = %d ", _Symbol, spread); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Helper function to check if trading is allowed. | //+------------------------------------------------------------------+ bool IsTradingBlocked() { // Check if it's within the defined start and end times now = TimeTradeServer(); return (now < vTradingStartTime || now > vTradingEndTime); } //+------------------------------------------------------------------+ // void CheckATR(){ // double ATR[]; // ArrayResize(ATR,15); // int hATR = iATR(_Symbol,_Period,15); // //ArraySetAsSeries( ATR, true); // CopyBuffer( hATR, 0, 0, 15, ATR ); //take number of average value // // for ( int i=0 ; i ", close, " -> ", nATR); if(open < close) { Print("Comprando.. ", _Symbol, " - ", now, " - bid: ", bid); double stop = bid - nATR; double take = bid + nATR; order_sent = trade.BuyLimit(1.0, bid, _Symbol, stop, take, ORDER_TIME_DAY, 0, (string)close + " -> " + (string)nATR); if(!order_sent) Print("Erro ao enviar ordem de compra. Código do erro: ", GetLastError()); } else if(open > close) { Print("Vendendo.. ", _Symbol, " - ", now, " - ask: ", ask); double stop = ask + nATR; double take = ask - nATR; order_sent = trade.SellLimit(1.0, ask, _Symbol, stop, take, ORDER_TIME_DAY, 0, (string)close + " <- " + (string)nATR); if(!order_sent) Print("Erro ao enviar ordem de venda. Código do erro: ", GetLastError()); } } //+------------------------------------------------------------------+