mql5/Experts/ACM/Bots/ACM_Bot_Lettus123.mq5
2025-09-08 06:40:56 -03:00

419 lines
39 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <SymbolTradeMadeSimple.mqh>
#include <Trade/PositionInfo.mqh>
#include <Trade/Trade.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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<ArraySize(ATR) ; i++ ){
// // Print("the ATR " + i + " is " + ATR[i]);
// // }
// }
// double getIndicator(int v)
// {
// int handle = iCustom(curSymbol,Indicator_Period,"Market\\Entry Points Pro for MT5");
// //,1000,true);
// // ,false,false,500,false,"09:00","23:59",false
// //,30,255,3329330,14772545,9,true,true,true,"alert2.wav"
// double myArray[];
// int copy=CopyBuffer(handle,v,0,1,myArray);
// return (double)myArray[0];
// }
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {
Print("Hora: ", now, " Key pressed: ", (char)lparam, " order_sent : ", order_sent, "\nPreço Bid: ", bid, " Preço Ask: ", ask, " Preço Close: ", close, " Preço Open: ", open);
if(id == CHARTEVENT_KEYDOWN) {
if(!order_sent) {
if((char)lparam == 'c' || (char)lparam == 'C') {
// Comprar
SL = close - nTR;
TP = close + nTR * 2;
max_price = close + nTR; // 50% do take profit
PrintFormat("Preço do inicio Trailstop: %.*f", _Digits, max_price);
order_sent = trade.BuyLimit(1.0, bid, _Symbol, SL, TP, ORDER_TIME_DAY, 0, "Manual Buy Limit at " + (string)bid + " SL: " + (string)SL + " TP: " + (string)TP);
if(!order_sent)
Print("Erro ao enviar ordem de compra. Código do erro: ", GetLastError());
}
if((char)lparam == 'v' || (char)lparam == 'V') {
// Vender
SL = close + nTR;
TP = close - nTR * 2;
max_price = close - nTR; // 50% do take profit
PrintFormat("Preço do inicio Trailstop: %.*f", _Digits, max_price);
order_sent = trade.SellLimit(1.0, ask, _Symbol, SL, TP, ORDER_TIME_DAY, 0, "Manual Sell Limit at " + (string)ask + " SL: " + (string)SL + " TP: " + (string)TP);
if(!order_sent)
Print("Erro ao enviar ordem de venda. Código do erro: ", GetLastError());
}
}
if((char)lparam == 'p' || (char)lparam == 'P') {
CloseAllPendingOrders();
}
if((char)lparam == 'r' || (char)lparam == 'R') {
CloseAllOpenOrders();
}
// Fechar todas as ordens abertas e remover o EA do gráfico
if((char)lparam == 'x' || (char)lparam == 'X') {
CloseAllOpenOrders();
ExpertRemove();
}
}
}
//+------------------------------------------------------------------+
//| Robo Lettus123! |
//+------------------------------------------------------------------+
void AbrePosicao() {
//--- Perform trading actions
// CloseAllOpenOrders();
order_sent = PositionSelect(_Symbol);
double ATRBuffer[];
int ATR = iATR(_Symbol, PERIOD_CURRENT, 14);
if(CopyBuffer(ATR, 0, 0, 1, ATRBuffer) <= 0) {
Print("Failed to copy data from the ATR indicator. Error code: ", GetLastError());
return;
}
double nATR = NormalizeDouble(ATRBuffer[0], _Digits);
Comment("in looping trading - ", now, " -> ", 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());
}
}
//+------------------------------------------------------------------+