Account_monitor2/Account_monitor_EA.mq5

700 lines
68 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:38:52 +02:00
<EFBFBD><EFBFBD>#property strict
#include "Telegram\Telegram.mqh"
// MQL5 (MetaQuotes Language 5) is a high-level language designed for developing technical indicators, trading robots and utility applications, which automate financial trading. MQL5 is an object-oriented language that is based on the concepts of the popular C++ programming language.
//
// The code you've posted is an import statement in MQL5, which allows you to use external functions from DLL (Dynamic-Link Library) files. In this case, the function `ShellExecuteW` from the `shell32.dll` library is being imported.
//
// Here's a breakdown of the function:
//
// - `int ShellExecuteW(int hWnd, string Verb, string File, string Parameter, string Path, int ShowCmd);`
//
// This function is used to perform an operation on a specified file. The operation to be performed is specified by the `Verb` parameter and it can be any action that the system associates with the file type.
//
// - `hWnd`: A handle to the parent window used for displaying a UI or error messages.
// - `Verb`: The operation to be performed. This is typically a string like "open", "edit", etc.
// - `File`: The path of the file on which the operation is to be performed.
// - `Parameter`: The parameters to be passed to the application opening the file.
// - `Path`: The default directory.
// - `ShowCmd`: Whether the application window will be shown when the application is opened. This can be one of several values, like SW_SHOW or SW_HIDE.
//
// The function returns an integer value. If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the error.
//
#import "shell32.dll"
int ShellExecuteW(int hWnd, string Verb, string File, string Parameter, string Path, int ShowCmd);
#import
input string TokenFile="Galileu-token.txt";
input string MyName="Galileu Rafael";//Nome do bot no telegram
input double Capital=100000;//Capital disponibilizado na conta
input string Ref1="";//Refer<EFBFBD>ncia 1 para os gr<EFBFBD>ficos
input string Ref2="";//Refer<EFBFBD>ncia 2 para os gr<EFBFBD>ficos
input double TxB3=0.023;//Taxas da B3 (%)
input double TxCorretagem=0;//Taxa de corretagem (%)
int ThisMinute=0;
int ThisDay=0;
string AuxFileName="AccountMonitor.aux";
int AuxDay=0;
bool Shell(string file, string parameters="",string directory="")
{
int r=ShellExecuteW(0, "open", file, parameters, directory, 0);
if (r > 32) return(true);
Alert("Shell failed: ",r);
return(false);
}
//+------------------------------------------------------------------+
//| CMyBot |
//+------------------------------------------------------------------+
// This is a class definition in MQL5 language for a bot that interacts with users through a chat interface. The bot can process different commands and respond accordingly. Here's a brief overview of the class:
//
// - The class `CMyBot` inherits from the `CCustomBot` class.
// - It has two public methods: `SendResult()` and `ProcessMessages()`.
// - `SendResult()` is used to generate charts, sleep for a certain period, and send messages and documents to certain users.
// - `ProcessMessages()` is used to process incoming messages from users. It checks if the message is from a certain user and if it contains certain commands. Depending on the command, it responds with a message or generates and sends a document.
//
// The bot can process the following commands:
// - `/start`: Sends a welcome message and prompts the user to type `/report` for a detailed report.
// - `/help`: Sends a list of all available commands.
// - `/report`: Generates charts and sends a detailed report.
// - `/aggregate`: Generates aggregated results and sends a report.
// - `/profit`: Sends a result message.
// - `/file`: Generates aggregated data and sends it.
//
// The bot uses the `Shell()` function to execute scripts for generating charts, and the `Sleep()` function to pause execution for a certain period. It also uses the `SendMessage()` and `SendDocument()` functions to send messages and documents to users.
//
class CMyBot: public CCustomBot
{
public:
void SendResult(string result)
{
Print(MyName+": gerando gr<00>ficos");
Calc_aggregate();
Shell("AccountMonitor.gp","",TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\");
Shell("AccountMonitor2.gp","",TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\");
Sleep(20000);
long ids[4]={6610010541,329475658,6425802004,5970645071};
//long ids[1]={6610010541};
for(int i=0; i<ArraySize(ids); i++)
{
SendMessage(ids[i],result);
string doc1,doc2;
SendDocument(doc1,ids[i],"AccountMonitor-"+TimeToString(TimeLocal(),TIME_DATE)+".pdf","Resultado "+MyName);
SendDocument(doc2,ids[i],"AccountMonitor-aggregate.pdf","Resultados agregados "+MyName);
if (ids[i]==6425802004)
{
string d1_id,d2_id;
SendDocument(d1_id,ids[i],"AccountMonitor-aggregate.csv","Tabela dados agregados do m<00>s "+MyName);
SendDocument(d2_id,ids[i],"AccountMonitor-aggregate2.csv","Tabela dados agregados mensal "+MyName);
}
}
}
void ProcessMessages(string result)
{
for(int i=0; i<m_chats.Total(); i++)
{
CCustomChat *chat=m_chats.GetNodeAtIndex(i);
//--- se a mensagem n<EFBFBD>o foi processada
if((!chat.m_new_one.done)&&(
(chat.m_new_one.from_username=="rafaelmorgadosilva")||
(chat.m_new_one.from_username=="marciuslima13")||
(chat.m_new_one.from_id==6425802004)||//Guilherme
(chat.m_new_one.from_id==5970645071)//Victor
))
{
chat.m_new_one.done=true;
string text=chat.m_new_one.message_text;
if(text=="/start")//--- in<EFBFBD>cio
{
SendMessage(chat.m_id,"Ol<00> "+chat.m_new_one.from_first_name+"!");
SendMessage(chat.m_id,"Digite /report para obter um relat<00>rio detalhado.");
}
if(text=="/help")//--- ajuda
SendMessage(chat.m_id,"My commands list: \n"+
"/start - mensagem inicial\n"+
"/help - ajuda\n"+
"/profit - relat<00>rio simplificado\n"+
"/report - gera e envia o relat<00>rio detalhado\n"+
"/aggregate - relat<00>rio agregado mensal\n"+
"/file - gera a tabela com os resultados agregados e envia"
);
if(text=="/report")//--- resultado do momento
{
SendMessage(chat.m_id,MyName+": Aguarde, gerando gr<00>ficos");
Shell("AccountMonitor.gp","",TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\");
Sleep(20000);
SendMessage(chat.m_id,result);
string document_id;
SendDocument(document_id,chat.m_id,"AccountMonitor-"+TimeToString(TimeLocal(),TIME_DATE)+".pdf","Resultado "+MyName);
}
if(text=="/aggregate")//--- resultado agregado
{
SendMessage(chat.m_id,MyName+": Aguarde, gerando gr<00>ficos");
Calc_aggregate();
Shell("AccountMonitor2.gp","",TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\");
Sleep(20000);
SendMessage(chat.m_id,result);
string d1_id;
SendDocument(d1_id,chat.m_id,"AccountMonitor-aggregate.pdf","Resultados agregados "+MyName);
}
if(text=="/profit") SendMessage(chat.m_id,result);
if(text=="/file")
{
SendMessage(chat.m_id,MyName+": Aguarde, gerando dados");
Calc_aggregate();
string document_id;
SendDocument(document_id,chat.m_id,"AccountMonitor-aggregate.csv","Tabela dados agregados "+MyName);
}
}
}
}
};
// This is a class definition in MQL5 (MetaQuotes Language 5), which is a high-level language for programming trading strategies. This particular class, `BotTelegram`, is designed to interact with the Telegram Bot API.
//
// Here's a brief explanation of the class members:
//
// - `InpToken`: This is a public string member that stores the token for the Telegram Bot API. This token is used to authenticate the bot with the API.
//
// - `bot`: This is an instance of the `CMyBot` class, which is presumably defined elsewhere in the code. This object is used to interact with the Telegram Bot API.
//
// - `BotTelegram(void)`: This is the constructor for the `BotTelegram` class. It initializes `InpToken` to an empty string.
//
// - `Init(string token)`: This is a method that initializes the bot with the provided token. It sets `InpToken` to the provided token, then calls the `Token` method on the `bot` object to set the token. It then calls the `GetMe` method on the `bot` object to check the token. If there's an error, it prints an error message and returns.
//
// - `Update(string result)`: This method is used to get updates from the Telegram Bot API. It calls the `GetUpdates` method on the `bot` object to read messages, then calls the `ProcessMessages` method on the `bot` object to process the messages.
//
// - `SendResult(string result)`: This method is used to send results back to the Telegram Bot API. It prints a message to the console, then calls the `SendResult` method on the `bot` object to send the results.
//
class BotTelegram
{
public:
string InpToken;//="177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";//Token
CMyBot bot;
BotTelegram(void) {InpToken="";}
void Init(string token)
{
InpToken=token;
bot.Token(InpToken);
int getme_result=bot.GetMe();//--- checagem token
if(getme_result!=0)
{
Print("Error: ",GetErrorDescription(getme_result));//--- mostrar mensagem de erro
return;//(INIT_FAILED);
}
Update("");
}
void Update(string result)
{
bot.GetUpdates();//--- l<EFBFBD> as mensagens - aqui <EFBFBD> onde tem o filtro de usu<EFBFBD>rios
bot.ProcessMessages(result);//--- processando mensagem
}
void SendResult(string result)
{
Print("Sending results");
bot.SendResult(result);
}
};
BotTelegram ThisBot;
// The MQL5 function `calc_volumes(bool type)` calculates the total volume of either buy or sell deals that have been made during the current day. The function takes a boolean argument `type` where `true` represents sell deals and `false` represents buy deals.
//
// Here's a step-by-step breakdown of what the function does:
//
// 1. It initializes a `MqlDateTime` structure `thisday` with the current date and time, and then sets the hour, minute, and second to 0. This effectively sets `thisday` to the start of the current day.
//
// 2. It converts `thisday` to a `datetime` variable `today`.
//
// 3. It selects the history of deals from `today` to the current time.
//
// 4. It gets the total number of deals in the history.
//
// 5. It initializes a variable `varday` to 0. This variable will hold the total volume of the deals.
//
// 6. It loops over each deal in the history. For each deal:
//
// - It gets the deal's ticket number.
//
// - It gets the symbol of the deal.
//
// - If the symbol represents a futures contract, it gets the tick value and tick size of the symbol. Otherwise, it sets the tick value and tick size to 1.
//
// - If the deal's type matches the `type` argument (i.e., if `type` is `true` and the deal is a sell deal, or if `type` is `false` and the deal is a buy deal), it adds the deal's volume (multiplied by the deal's price and the tick value, and divided by the tick size) to `varday`. The volume is rounded to the nearest hundredth.
//
// 7. Finally, it returns `varday`, which is the total volume of the specified type of deals that have been made during the current day.
//
double calc_volumes(bool type)
{
MqlDateTime thisday;
TimeCurrent(thisday);
thisday.hour=0;
thisday.min=0;
thisday.sec=0;
datetime today=StructToTime(thisday);
HistorySelect(today,TimeCurrent());
int total=HistoryDealsTotal();
double varday=0;
for (int i=0;i<total;i++)
{
ulong ticket=HistoryDealGetTicket(i);
bool enable=false;
string psymbol=HistoryDealGetString(ticket,DEAL_SYMBOL);//PositionGetString(POSITION_SYMBOL);
double tick_value=1;
double tick_size=1;
if(SymbolInfoInteger(psymbol,SYMBOL_TRADE_CALC_MODE)==SYMBOL_CALC_MODE_EXCH_FUTURES)//BMF
{
tick_value=SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_VALUE);
tick_size=SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE);
}
else
{
tick_value=1;
tick_size=1;
}
if (ticket!=0)
{
if(((HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_SELL)&&type)||((HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_BUY)&&(!type)))
varday+=MathRound(100*HistoryDealGetDouble(ticket,DEAL_VOLUME)*HistoryDealGetDouble(ticket,DEAL_PRICE)*tick_value/tick_size)/100.0;
}
}
return(varday);
}
// This MQL5 function calculates the total profit for all trades executed on the current day. The function takes one boolean parameter `type`, which determines whether to calculate the profit for sell trades (`type` is `true`) or buy trades (`type` is `false`).
//
// First, it gets the current time and sets the hour, minute, and second to 0, effectively getting the start of the current day. It then selects all trades from the history that were executed from the start of the day until the current time.
//
// It then iterates over each trade in the history. For each trade, it gets the symbol of the trade and checks if the symbol is traded in exchange futures mode. If it is, it gets the tick value and tick size for the symbol. Otherwise, it sets the tick value and tick size to 1.
//
// It then checks if the trade is a sell trade and `type` is `true`, or if the trade is a buy trade and `type` is `false`. If either of these conditions is met, it adds the profit of the trade to the total profit `varday`.
//
// Finally, it returns the total profit `varday`.
//
// This function can be used to calculate the total profit for all sell or buy trades executed on the current day.
//
double calc_profit(bool type)
{
MqlDateTime thisday;
TimeCurrent(thisday);
thisday.hour=0;
thisday.min=0;
thisday.sec=0;
datetime today=StructToTime(thisday);
HistorySelect(today,TimeCurrent());
int total=HistoryDealsTotal();
double varday=0;
for (int i=0;i<total;i++)
{
ulong ticket=HistoryDealGetTicket(i);
bool enable=false;
string psymbol=HistoryDealGetString(ticket,DEAL_SYMBOL);//PositionGetString(POSITION_SYMBOL);
double tick_value=1;
double tick_size=1;
if(SymbolInfoInteger(psymbol,SYMBOL_TRADE_CALC_MODE)==SYMBOL_CALC_MODE_EXCH_FUTURES)//BMF
{
tick_value=SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_VALUE);
tick_size=SymbolInfoDouble(psymbol,SYMBOL_TRADE_TICK_SIZE);
}
else
{
tick_value=1;
tick_size=1;
}
if (ticket!=0)
{
if(((HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_SELL)&&type)||((HistoryDealGetInteger(ticket,DEAL_TYPE)==DEAL_TYPE_BUY)&&(!type)))
varday+=HistoryDealGetDouble(ticket,DEAL_PROFIT);
}
}
return(varday);
}
// The MQL5 code you posted is a function named `Calc_aggregate()`. This function is used to calculate the aggregate results of a trading account for a month and for the last 30 days.
//
// The function works by reading data from a series of CSV files named "AccountMonitor-YYYY.MM.DD.csv" where YYYY.MM.DD is the date. Each file contains data for a single day and includes information such as equity, balance, invested amount, profit, volume, and other trading parameters.
//
// The function calculates the aggregate results by iterating through each day of the month or the last 30 days, reading the data from the corresponding file, and updating the aggregate results. The aggregate results include the total equity, balance, and reference values.
//
// The function also takes into account the transaction costs (TxB3 and TxCorretagem) and adjusts the aggregate results accordingly.
//
// Finally, the function writes the aggregate results to two output CSV files: "AccountMonitor-aggregate.csv" for the monthly aggregate results and "AccountMonitor-aggregate2.csv" for the aggregate results of the last 30 days.
//
// Please note that the function uses some variables and constants that are not defined within the function itself (such as `Capital`, `TxB3`, and `TxCorretagem`). These are likely defined elsewhere in the program.
//
void Calc_aggregate(void)
{
MqlDateTime thistime,temptime;
TimeLocal(thistime);
int filein,fileout;
temptime=thistime;
double multiplicador_eqty=0,multiplicador_saldo=0,multiplicador_ref1=0,multiplicador_ref2=0;
if (FileIsExist("AccountMonitor-aggregate.csv")) FileDelete("AccountMonitor-aggregate.csv");
Print("Calculando o resultado agregado do m<00>s");
for (int i=1;i<=31;i++)
{
temptime.day=i;
filein=FileOpen("AccountMonitor-"+TimeToString(StructToTime(temptime),TIME_DATE)+".csv",FILE_READ|FILE_SHARE_READ|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (filein!=INVALID_HANDLE)
{
//Print("Calculando dia " ,i);
fileout=FileOpen("AccountMonitor-aggregate.csv",FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (fileout!=INVALID_HANDLE)
{
FileSeek(filein,0,SEEK_SET);
FileSeek(fileout,0,SEEK_END);
string data,ref1,ref2;
int positions;
double equity,balance,invested,profit,
profitbuy=0,effbuy,volbuy=0,
profitsell=0,effsell,volsell=0,
profittotal,efftotal,voltotal=0,
refd1=0,refd2=0,
profitrel=0,balrel=0,invested0=0;
int filecnt=0;
while(!FileIsEnding(filein))
{
data=FileReadString(filein);
equity=FileReadNumber(filein);
balance=FileReadNumber(filein);
positions=(int)FileReadNumber(filein);
invested=FileReadNumber(filein);
profit=FileReadNumber(filein);
profitbuy=FileReadNumber(filein);
effbuy=FileReadNumber(filein);
volbuy=FileReadNumber(filein);
profitsell=FileReadNumber(filein);
effsell=FileReadNumber(filein);
volsell=FileReadNumber(filein);
profittotal=FileReadNumber(filein);
efftotal=FileReadNumber(filein);
voltotal=FileReadNumber(filein);
ref1=FileReadString(filein);
refd1=FileReadNumber(filein);
ref2=FileReadString(filein);
refd2=FileReadNumber(filein);
profitrel=FileReadNumber(filein);
balrel=FileReadNumber(filein);
if (filecnt==0) invested0=invested;
filecnt++;
/*string str_data[],str_time[];
StringSplit(data,StringGetCharacter(" ",0),str_data);
StringSplit(str_data[1],StringGetCharacter(":",0),str_time);
if (StringToDouble(str_time[0])>=10)
FileWrite(fileout,data,
ref1,(1+multiplicador_ref1)*(1+refd1)-1,
ref2,(1+multiplicador_ref2)*(1+refd2)-1,
(1+multiplicador_eqty)*(1+profitrel+balrel)-1,
(1+multiplicador_saldo)*(1+balrel)-1);*/
}
double ThisCapital=Capital;
if (balrel!=0) ThisCapital=100*(profitbuy+profitsell)/balrel;
multiplicador_ref1=(1+multiplicador_ref1)*(1+refd1/100)-1;
multiplicador_ref2=(1+multiplicador_ref2)*(1+refd2/100)-1;
multiplicador_eqty=(1+multiplicador_eqty)*(1+(((voltotal==0)&&(invested0!=0))?
(profitrel/invested0):
(profitrel/100))+balrel/100-(volbuy+volsell)*(TxB3+TxCorretagem)/(100*ThisCapital))-1;
//no caso do fermi, isso tem que ser recalculado. se for o primeiro dia do m<EFBFBD>s, com o rebalan<EFBFBD>o n<EFBFBD>o
//para detectar rebalanceamento: balrel n<EFBFBD>o <EFBFBD> zero (rebalanceamento com venda). No caso de rebalanceamento s<EFBFBD> compra
//(reajuste de capital por ex.) o valor de Capital ser<EFBFBD> alterado aqui e no rob<EFBFBD>. voltotal n<EFBFBD>o ser<EFBFBD> zero, mesmo balrel sendo.
//Se for um reajuste de compra, a varia<EFBFBD><EFBFBD>o no dia ser<EFBFBD> a varia<EFBFBD><EFBFBD>o no lucro flutuante/novo saldo (profitrel)
//o melhor teste para detectar rebalanceamento <EFBFBD> ter voltotal diferente de zero. O c<EFBFBD>lculo da varia<EFBFBD><EFBFBD>o vai ser profitrel+balrel
//se voltotal for zero, e invested n<EFBFBD>o for zero, se trata de uma carteira e a varia<EFBFBD><EFBFBD>o no dia vai ser a (varia<EFBFBD><EFBFBD>o no flutuante)/(investido no in<EFBFBD>cio do dia)
//(profitrel*Capital/100)/(invested0*Capital/100)=profitrel/invested0
//
//para tirar as taxas, subtrair de eqty e saldo (volbuy+volsell)*(TxB3+TxCorretagem)/Capital
multiplicador_saldo=(1+multiplicador_saldo)*(1+balrel/100-(volbuy+volsell)*(TxB3+TxCorretagem)/(100*ThisCapital))-1;
string str_data[];
StringSplit(data,StringGetCharacter(" ",0),str_data);
StringAdd(str_data[0]," 00:00:00");
FileWrite(fileout,str_data[0],
ref1,100*multiplicador_ref1,
ref2,100*multiplicador_ref2,
100*multiplicador_eqty,
100*multiplicador_saldo);
FileClose(fileout);
}
FileClose(filein);
}
}
multiplicador_eqty=0;
multiplicador_saldo=0;
multiplicador_ref1=0;
multiplicador_ref2=0;
if (FileIsExist("AccountMonitor-aggregate2.csv")) FileDelete("AccountMonitor-aggregate2.csv");
datetime tmptime=StructToTime(thistime)-30*24*3600;
Print("Calculando o resultado agregado mensal a partir de " ,TimeToString(tmptime,TIME_DATE)," at<00> ",TimeToString(StructToTime(thistime),TIME_DATE));
for (int i=0;i<=30;i++)//at<EFBFBD> 31 dias corridos
{
filein=FileOpen("AccountMonitor-"+TimeToString(tmptime,TIME_DATE)+".csv",FILE_READ|FILE_SHARE_READ|FILE_CSV|FILE_ANSI,';',CP_UTF8);
tmptime+=24*3600;
if (filein!=INVALID_HANDLE)
{
//Print("Calculando " ,TimeToString(tmptime,TIME_DATE));
fileout=FileOpen("AccountMonitor-aggregate2.csv",FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (fileout!=INVALID_HANDLE)
{
FileSeek(filein,0,SEEK_SET);
FileSeek(fileout,0,SEEK_END);
string data,ref1,ref2;
int positions;
double equity,balance,invested,profit,
profitbuy=0,effbuy,volbuy=0,
profitsell=0,effsell,volsell=0,
profittotal,efftotal,voltotal=0,
refd1=0,refd2=0,
profitrel=0,balrel=0,invested0=0;
int filecnt=0;
while(!FileIsEnding(filein))
{
data=FileReadString(filein);
equity=FileReadNumber(filein);
balance=FileReadNumber(filein);
positions=(int)FileReadNumber(filein);
invested=FileReadNumber(filein);
profit=FileReadNumber(filein);
profitbuy=FileReadNumber(filein);
effbuy=FileReadNumber(filein);
volbuy=FileReadNumber(filein);
profitsell=FileReadNumber(filein);
effsell=FileReadNumber(filein);
volsell=FileReadNumber(filein);
profittotal=FileReadNumber(filein);
efftotal=FileReadNumber(filein);
voltotal=FileReadNumber(filein);
ref1=FileReadString(filein);
refd1=FileReadNumber(filein);
ref2=FileReadString(filein);
refd2=FileReadNumber(filein);
profitrel=FileReadNumber(filein);
balrel=FileReadNumber(filein);
if (filecnt==0) invested0=invested;
filecnt++;
}
double ThisCapital=Capital;
if (balrel!=0) ThisCapital=100*(profitbuy+profitsell)/balrel;
multiplicador_ref1=(1+multiplicador_ref1)*(1+refd1/100)-1;
multiplicador_ref2=(1+multiplicador_ref2)*(1+refd2/100)-1;
multiplicador_eqty=(1+multiplicador_eqty)*(1+(((voltotal==0)&&(invested0!=0))?
(profitrel/invested0):
(profitrel/100))+balrel/100-(volbuy+volsell)*(TxB3+TxCorretagem)/(100*ThisCapital))-1;
multiplicador_saldo=(1+multiplicador_saldo)*(1+balrel/100-(volbuy+volsell)*(TxB3+TxCorretagem)/(100*ThisCapital))-1;
string str_data[];
StringSplit(data,StringGetCharacter(" ",0),str_data);
StringAdd(str_data[0]," 00:00:00");
FileWrite(fileout,str_data[0],
ref1,100*multiplicador_ref1,
ref2,100*multiplicador_ref2,
100*multiplicador_eqty,
100*multiplicador_saldo);
FileClose(fileout);
}
FileClose(filein);
}
}
}
void OnDeinit(const int reason)
{
EventKillTimer();
}
int OnInit()
{
EventSetTimer(15);
int tokenfile=FileOpen(TokenFile,FILE_READ|FILE_SHARE_READ|FILE_TXT);
if (tokenfile!=INVALID_HANDLE)
{
ThisBot.Init(FileReadString(tokenfile));//Token
FileClose(tokenfile);
}
return(INIT_SUCCEEDED);
}
string StructToString(MqlDateTime &today)
{
return(IntegerToString(today.year)+"-"+IntegerToString(today.mon)+"-"+IntegerToString(today.day)+" "+
IntegerToString(today.hour)+":"+IntegerToString(today.min)+":"+IntegerToString(today.sec));
}
// The MQL5 code provided is a function that is called every time a timer event occurs. The function is used to monitor the performance of a trading account and write the results to a file.
//
// Here's a brief breakdown of what the function does:
//
// 1. It retrieves the current local time and converts it to a structured format.
//
// 2. It retrieves various account information such as equity, balance, number of open positions, and profit.
//
// 3. It calculates the total amount invested in open positions.
//
// 4. It calculates the volume and profit of buy and sell trades.
//
// 5. It retrieves the daily price change of two reference assets.
//
// 6. If it's a weekday and the time is after 9 AM, it writes the profit, balance, and invested amount to a file.
//
// 7. It reads the profit, balance, and invested amount from the file and calculates the market value change for the day.
//
// 8. It generates a string containing all the calculated information and displays it on the chart.
//
// 9. It updates the bot with the calculated information.
//
// 10. If it's a weekday and the time is between 9 AM and 6 PM, it writes all the calculated information to a CSV file.
//
// 11. If it's a weekday and the time is after 6:30 PM, it sends the calculated information to the bot.
//
// This function is useful for traders who want to monitor their trading performance in real-time and have a record of their daily trading activity.
//
void OnTimer()
{
datetime thistime=TimeLocal();
MqlDateTime strtime;
TimeToStruct(thistime,strtime);
{
double equity=AccountInfoDouble(ACCOUNT_EQUITY);//+10*MathRand()/(double)32767;
double balance=AccountInfoDouble(ACCOUNT_BALANCE);
double positions=(double)PositionsTotal();
double profit=AccountInfoDouble(ACCOUNT_PROFIT);
double invested=0;
for (int i=0;i<positions;i++)
{
if (PositionGetSymbol(i)!="")
invested+=PositionGetDouble(POSITION_PRICE_CURRENT)*PositionGetDouble(POSITION_VOLUME);
}
double volbuy=calc_volumes(false);
double volsell=calc_volumes(true);
double profitbuy=calc_profit(true);
double profitsell=calc_profit(false);
double effbuy=((volsell!=0)?(100.0*profitbuy/volsell):0);
double effsell=((volbuy!=0)?(100.0*profitsell/volbuy):0);
string result="";
StringAdd(result,MyName+"\n");
StringAdd(result,TimeToString(thistime)+"\n");
// StringAdd(result,StringFormat("Realized profit = %.2f \t\t %.2f%%\nEfficiency = %.2f%%\nVolume = %.2f \t\t %.2f%%\n",profitbuy+profitsell,100*(profitbuy+profitsell)/Capital,(((volbuy+volsell)!=0)?(100.0*2*(profitbuy+profitsell)/(volbuy+volsell)):0),(volbuy+volsell),100*(volbuy+volsell)/Capital));
// StringAdd(result,StringFormat("Equity = %.2f\nBalance = %.2f\nPositions = %.0f\nInvested = %.2f \t\t %.2f%%\nFloating profit = %.2f \t\t %.2f%%\n",equity,balance,positions,invested,100*invested/Capital,profit,100*profit/Capital));
double ref1=0,ref2=0;
if (Ref1!="")
{
MqlRates ref[];
ArraySetAsSeries(ref,true);
if(CopyRates(Ref1,PERIOD_D1,0,2,ref)==2)
ref1=100*(ref[0].close-ref[1].close)/ref[1].close;
}
if (Ref2!="")
{
MqlRates ref[];
ArraySetAsSeries(ref,true);
if (CopyRates(Ref2,PERIOD_D1,0,2,ref)==2)
ref2=100*(ref[0].close-ref[1].close)/ref[1].close;
}
//gravar equity,balance e invested no arquivo auxiliar
if ((strtime.day_of_week!=SATURDAY)&&(strtime.day_of_week!=SUNDAY))
if ((strtime.day!=AuxDay)&&
(strtime.hour>=9))
{
if (FileIsExist(AuxFileName))
{
MqlDateTime fdata;
TimeToStruct((datetime)FileGetInteger(AuxFileName,FILE_MODIFY_DATE),fdata);
if (fdata.day!=strtime.day)
{
int auxfile=FileOpen(AuxFileName,FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (auxfile!=INVALID_HANDLE)
{
//FileWrite(auxfile,equity,balance,invested);
FileWrite(auxfile,100*profit/Capital,100*balance/Capital,100*invested/Capital);
FileClose(auxfile);
}
}
}
else
{
int auxfile=FileOpen(AuxFileName,FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (auxfile!=INVALID_HANDLE)
{
FileWrite(auxfile,100*profit/Capital,100*balance/Capital,100*invested/Capital);
FileClose(auxfile);
}
}
AuxDay=strtime.day;
}
double profit0=0,balance0=1,invested0=1;
int fileaux=FileOpen(AuxFileName,FILE_READ|FILE_SHARE_READ|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (fileaux!=INVALID_HANDLE)
{
FileSeek(fileaux,0,SEEK_SET);
profit0=FileReadNumber(fileaux);
balance0=FileReadNumber(fileaux);
invested0=FileReadNumber(fileaux);
FileClose(fileaux);
}
StringAdd(result,StringFormat("Varia<00><00>o no valor de mercado no dia (com taxas): %.2f%%\n",
((((volbuy+volsell)==0)&&(invested0!=0))?(100*(100*profit/Capital-profit0)/invested0):(100*profit/Capital-profit0+100*(profitbuy+profitsell)/Capital-(TxB3+TxCorretagem)*(volbuy+volsell)/Capital))
));
StringAdd(result,StringFormat("Lucro realizado no dia: %.2f \t\t %.2f%%\nEfici<00>ncia: %.2f%%\nVolume: %.2f \t\t %.2f%%\n",profitbuy+profitsell,100*(profitbuy+profitsell)/Capital,(((volbuy+volsell)!=0)?(100.0*2*(profitbuy+profitsell)/(volbuy+volsell)):0),(volbuy+volsell),100*(volbuy+volsell)/Capital));
StringAdd(result,StringFormat("Posi<00><00>es: %.0f\nTotal investido: %.2f \t\t %.2f%%\nLucro flutuante: %.2f \t\t %.2f%%\n",positions,invested,100*invested/Capital,profit,100*profit/Capital));
StringAdd(result,StringFormat("Taxas da B3: %.2f\n",TxB3*(volbuy+volsell)/100));
StringAdd(result,StringFormat("Taxas de corretagem: %.2f\n",TxCorretagem*(volbuy+volsell)/100));
StringAdd(result,"Varia<00><00>o do "+Ref1+" no dia: "+StringFormat(" %.2f%%\n",ref1));
StringAdd(result,"Varia<00><00>o do "+Ref2+" no dia: "+StringFormat(" %.2f%%\n",ref2));
Comment(result);
ThisBot.Update(result);
if ((strtime.day_of_week!=SATURDAY)&&(strtime.day_of_week!=SUNDAY))
if ((strtime.min!=ThisMinute)&&
(strtime.hour>=9)&&
(strtime.hour<=18))
{
int fileout=FileOpen("AccountMonitor-"+TimeToString(thistime,TIME_DATE)+".csv",FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI,';',CP_UTF8);
if (fileout!=INVALID_HANDLE)
{
FileSeek(fileout,0,SEEK_END);
FileWrite(fileout,
StructToString(strtime),
equity,
balance,
positions,
100*invested/Capital,
100*profit/Capital,
profitbuy,
effbuy,
volbuy,
profitsell,
effsell,
volsell,
profitbuy+profitsell,
(((volbuy+volsell)!=0)?(100.0*2.0*(profitbuy+profitsell)/(volbuy+volsell)):0),
100*(volbuy+volsell)/Capital,
Ref1,ref1,Ref2,ref2,
100*profit/Capital-profit0,//100*profit/invested0-profit0*Capital/invested0;$20*Capital/columnhead(5)
100*(profitbuy+profitsell)/Capital
);
FileClose(fileout);
}
ThisMinute=strtime.min;
}
if ((strtime.day_of_week!=SATURDAY)&&(strtime.day_of_week!=SUNDAY))
if ((strtime.day!=ThisDay)&&
(((strtime.hour==18)&&(strtime.min>=30))||(strtime.hour>18))
)
{
ThisBot.SendResult(result);
ThisDay=strtime.day;
}
}
}