forked from nique_372/MQLArticles
313 lines
12 KiB
MQL5
313 lines
12 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| RMt_Functions.mqh |
| |
//| Niquel y Leo, Copyright 2025 |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Niquel y Leo, Copyright 2025"
| |
#property link "https://www.mql5.com"
| |
#property strict
| |
| |
#ifndef MQLARTICLES_RM_RFUNCTIONS_MQH
| |
#define MQLARTICLES_RM_RFUNCTIONS_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "LoteSizeCalc.mqh"
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
namespace TSN
| |
{
| |
//+------------------------------------------------------------------+
| |
//| Defines |
| |
//+------------------------------------------------------------------+
| |
const bool GetNetProfitOmitirDeal[18] =
| |
{
| |
false, //compra
| |
false, //venta
| |
true, //balance
| |
true, //credito
| |
true, //carga adicionales
| |
false, //correcion
| |
true, //bonos
| |
false, //comisiones adicional
| |
false, //comisions del dia
| |
false, //comision del mes
| |
false, //comosions agente dia
| |
false, //comosiion agenet mes,
| |
false, //interes
| |
false, //compra cancelada
| |
false, //ventan cancelada
| |
false, //dividendo
| |
false, //dividendo frankeado, con beneficions
| |
false //impuestos
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Rm functions |
| |
//+------------------------------------------------------------------+
| |
class CRmFunctions
| |
{
| |
public:
| |
CRmFunctions(void) {}
| |
~CRmFunctions(void) {}
| |
| |
//---
| |
static double GetPositionCommission(ulong ticket);
| |
static inline CGetLote* CreateLotePtr(string symbol);
| |
static double GetTotalPositionProfitNoCurrent(ulong position_ticket);
| |
| |
//---
| |
static inline ulong GetOrderMagic(const ulong ticket);
| |
| |
//---
| |
static double GetNetProfitSince(bool include_all_magic, ulong specific_magic, datetime start_date);
| |
static void CloseAllOrders(int flags, CTrade & obj_trade, ulong magic_number_ = NOT_MAGIC_NUMBER);
| |
| |
//---
| |
static void CRmFunctions::PrintArrayAsTable(double & array[], string fila_descripcion, string columna_prefijo = "Valor");
| |
| |
//---
| |
static void SetDynamicUsingFixedParameters(
| |
double _balance_percentage_to_activate_the_risk_1, double _balance_percentage_to_activate_the_risk_2,
| |
double _balance_percentage_to_activate_the_risk_3, double _balance_percentage_to_activate_the_risk_4,
| |
double _percentage_to_be_modified_1, double _percentage_to_be_modified_2, double _percentage_to_be_modified_3,
| |
double _percentage_to_be_modified_4,
| |
string & percentages_to_activate, string & risks_to_be_applied);
| |
};
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
static double CRmFunctions::GetPositionCommission(ulong ticket)
| |
{
| |
// Verificar si la posición existe y obtener su tiempo de apertura
| |
if(!PositionSelectByTicket(ticket))
| |
return 0.0;
| |
const datetime open_time = (datetime)PositionGetInteger(POSITION_TIME);
| |
// Usar un rango de tiempo estrecho: desde el tiempo de apertura hasta 1 segundo después
| |
if(!HistorySelect(open_time, open_time + 1))
| |
return 0.0;
| |
// Obtener el primer deal del historial
| |
const ulong deal_ticket = HistoryDealGetTicket(0);
| |
if(deal_ticket == 0)
| |
{
| |
return 0.0;
| |
}
| |
// Verificar si el deal corresponde a la posición y es de entrada
| |
if(HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID) == ticket)
| |
{
| |
return HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION);
| |
}
| |
return 0.0;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
static inline CGetLote* CRmFunctions::CreateLotePtr(string symbol)
| |
{
| |
return new CGetLote(symbol);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
static double CRmFunctions::GetTotalPositionProfitNoCurrent(ulong position_ticket)
| |
{
| |
//---
| |
double total_profit = 0.0;
| |
| |
//---
| |
if(HistorySelectByPosition(position_ticket))
| |
{
| |
const int deals_count = HistoryDealsTotal();
| |
for(int i = 0; i < deals_count; i++)
| |
{
| |
const ulong deal_ticket = HistoryDealGetTicket(i);
| |
if(deal_ticket <= 0)
| |
continue;
| |
const ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
| |
if(entry == DEAL_ENTRY_OUT || entry == DEAL_ENTRY_IN)
| |
{
| |
total_profit += HistoryDealGetDouble(deal_ticket, DEAL_PROFIT) +
| |
HistoryDealGetDouble(deal_ticket, DEAL_SWAP) +
| |
HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION);
| |
}
| |
}
| |
}
| |
return total_profit;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
static inline ulong CRmFunctions::GetOrderMagic(const ulong ticket)
| |
{
| |
HistoryOrderSelect(ticket);
| |
return HistoryOrderGetInteger(ticket, ORDER_MAGIC);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
static double CRmFunctions::GetNetProfitSince(bool include_all_magic, ulong specific_magic, datetime start_date)
| |
{
| |
double total_net_profit = 0.0; // Initialize the total net profit
| |
ResetLastError(); // Reset any previous errors
| |
| |
//---
| |
if(start_date > 0 && start_date != D'1971.01.01 00:00')
| |
{
| |
if(!HistorySelect(start_date, TimeCurrent()))
| |
{
| |
Print("Error when selecting orders: ", _LastError);
| |
return 0.00; // Exit if unable to select the history
| |
}
| |
| |
const int total_deals = HistoryDealsTotal(); // Count total deals in the history
| |
| |
for(int i = 0; i < total_deals; i++)
| |
{
| |
const ulong deal_ticket = HistoryDealGetTicket(i); // Get the deal ticket
| |
| |
if(GetNetProfitOmitirDeal[HistoryDealGetInteger(deal_ticket, DEAL_TYPE)])
| |
continue;
| |
| |
//---
| |
const ulong deal_magic = HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
| |
if(!include_all_magic && deal_magic != specific_magic)
| |
continue;
| |
| |
//---
| |
const double deal_profit = HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);
| |
const double deal_commission = HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION);
| |
const double deal_swap = HistoryDealGetDouble(deal_ticket, DEAL_SWAP);
| |
total_net_profit += (deal_profit + deal_commission + deal_swap);
| |
}
| |
}
| |
| |
//---
| |
return total_net_profit;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Function to close orders |
| |
//+------------------------------------------------------------------+
| |
// Converts an order type to its corresponding flag
| |
const int ALL_FLAGS_STOPS = FLAG_ORDER_TYPE_BUY_STOP | FLAG_ORDER_TYPE_SELL_STOP;
| |
const int ALL_FLAGS_LIMITS = FLAG_ORDER_TYPE_BUY_LIMIT | FLAG_ORDER_TYPE_SELL_LIMIT;
| |
const int ALL_FLAGS_ORDERS = (FLAG_ORDER_TYPE_BUY | FLAG_ORDER_TYPE_SELL | FLAG_ORDER_TYPE_BUY_LIMIT |
| |
FLAG_ORDER_TYPE_SELL_LIMIT | FLAG_ORDER_TYPE_BUY_STOP | FLAG_ORDER_TYPE_SELL_STOP |
| |
FLAG_ORDER_TYPE_BUY_STOP_LIMIT | FLAG_ORDER_TYPE_SELL_STOP_LIMIT | FLAG_ORDER_TYPE_CLOSE_BY);
| |
| |
| |
// Close all orders that match the flags in `flags`
| |
static void CRmFunctions::CloseAllOrders(int flags, CTrade & obj_trade, ulong magic_number_ = NOT_MAGIC_NUMBER)
| |
{
| |
ResetLastError();
| |
for(int i = OrdersTotal() - 1; i >= 0; i--)
| |
{
| |
ulong ticket = OrderGetTicket(i);
| |
| |
if(OrderSelect(ticket))
| |
{
| |
ENUM_ORDER_TYPE type_order = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
| |
ulong magic = OrderGetInteger(ORDER_MAGIC);
| |
int bandera = MQLArticles_OrderToFlag(type_order);
| |
if((bandera & flags) != 0 && (magic == magic_number_ || magic_number_ == NOT_MAGIC_NUMBER))
| |
{
| |
if(type_order == ORDER_TYPE_BUY || type_order == ORDER_TYPE_SELL)
| |
obj_trade.PositionClose(ticket);
| |
else
| |
obj_trade.OrderDelete(ticket);
| |
}
| |
}
| |
else
| |
{
| |
PrintFormat("Error selecting order %d, last error %d", ticket, GetLastError());
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
static void CRmFunctions::PrintArrayAsTable(double & array[], string fila_descripcion, string columna_prefijo = "Valor")
| |
{
| |
string header = fila_descripcion;
| |
int len = StringLen(header);
| |
string values;
| |
StringInit(values, len + 2, ' ');
| |
| |
int max_len = StringLen(header);
| |
for(int i = 0; i < ArraySize(array); i++)
| |
{
| |
string col_name = columna_prefijo + " " + IntegerToString(i + 1);
| |
max_len = MathMax(max_len, StringLen(col_name));
| |
}
| |
| |
header = StringFormat("%-" + (string)(max_len + 2) + "s", header);
| |
| |
for(int i = 0; i < ArraySize(array); i++)
| |
{
| |
string col_name = columna_prefijo + " " + IntegerToString(i + 1);
| |
header += StringFormat("| %-10s ", col_name);
| |
values += StringFormat("| %-10.2f ", array[i]);
| |
}
| |
| |
Print(header);
| |
Print(values);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
static void CRmFunctions::SetDynamicUsingFixedParameters(
| |
double _balance_percentage_to_activate_the_risk_1, double _balance_percentage_to_activate_the_risk_2,
| |
double _balance_percentage_to_activate_the_risk_3, double _balance_percentage_to_activate_the_risk_4,
| |
double _percentage_to_be_modified_1, double _percentage_to_be_modified_2, double _percentage_to_be_modified_3,
| |
double _percentage_to_be_modified_4,
| |
string & percentages_to_activate, string & risks_to_be_applied)
| |
{
| |
percentages_to_activate = DoubleToString(_balance_percentage_to_activate_the_risk_1) + "," + DoubleToString(_balance_percentage_to_activate_the_risk_2) + "," + DoubleToString(_balance_percentage_to_activate_the_risk_3)
| |
+ "," + DoubleToString(_balance_percentage_to_activate_the_risk_4);
| |
risks_to_be_applied = DoubleToString(_percentage_to_be_modified_1) + "," + DoubleToString(_percentage_to_be_modified_2) + "," + DoubleToString(_percentage_to_be_modified_3)
| |
+ "," + DoubleToString(_percentage_to_be_modified_4);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
class CAccountGestor : public CAllClassEventsBasic
| |
{
| |
public:
| |
CAccountGestor() {}
| |
~CAccountGestor() {}
| |
| |
//--- Positions
| |
virtual void OnClosePosition(const ROnClosePosition &pos, const int global_pos_index) {}
| |
virtual void OnOpenPosition(const ROnOpenPosition &pos) {}
| |
| |
//--- Position modify
| |
virtual void OnPositionModify(const Position& pos, const uint8_t change_flags) { }
| |
| |
//--- Orders
| |
virtual void OnOrderAdd(const ROrder& order) { }
| |
virtual void OnOrderUpdate(const ROrder& order) { }
| |
virtual void OnOrderDelete(const ROrder& order) { }
| |
| |
//-- Function that is executed only once, where only the account profit fields are filled, such as account_gross_profit
| |
//daily, weekly, etc.
| |
virtual void OnNewProfit(const RAccountProfit &profit, const datetime curr_time) { }
| |
| |
//--- Function that is executed each time TesterDeposit or TesterWithdrawal is called... or capital is added to the account
| |
virtual void OnWithdrawalDeposit(const double value) { } //If the value is positive it means a deposit, otherwise a withdrawal
| |
| |
//--- Function that is executed only once, only if there are previously open trades, only the position structure
| |
virtual void OnInitNewPos(const ROnOpenPosition &position) { }
| |
| |
//---
| |
virtual void OnLossProfit(const double p) {}
| |
};
| |
}
| |
//+------------------------------------------------------------------+
| |
#endif // MQLARTICLES_RM_RFUNCTIONS_MQH
|