MQLArticles/Utils/FA/Atr.mqh

576 lines
39 KiB
MQL5

2025-10-01 12:22:08 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Atr.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com/es/users/nique_372/news |
//+------------------------------------------------------------------+
2025-11-10 09:33:53 -05:00
#property copyright "Copyright 2025, Niquel Mendoza."
2025-10-01 12:22:08 -05:00
#property link "https://www.mql5.com/es/users/nique_372/news"
#property strict
#ifndef MQLARTICLES_UTILS_FA_ATR_MQH
#define MQLARTICLES_UTILS_FA_ATR_MQH
//+------------------------------------------------------------------+
//| Includes |
//+------------------------------------------------------------------+
2026-01-06 13:03:52 -05:00
#include "SimpleLogger.mqh"
2025-10-01 12:22:08 -05:00
#include "BarControler.mqh"
//+------------------------------------------------------------------+
2026-01-06 13:03:52 -05:00
2026-01-13 14:49:49 -05:00
//| Resources |
//+------------------------------------------------------------------+
2025-10-01 12:22:08 -05:00
2026-03-05 12:10:29 -05:00
#resource "AtrCts.ex5"
2025-10-01 12:22:08 -05:00
2026-01-06 13:03:52 -05:00
2026-03-05 12:10:29 -05:00
//+------------------------------------------------------------------+
2026-03-23 12:25:12 -05:00
//| Class to handle the atr |
2026-01-06 13:03:52 -05:00
//+------------------------------------------------------------------+
2026-01-13 14:49:49 -05:00
class CAtr : public CLoggerBase
2025-10-01 12:22:08 -05:00
{
2026-01-06 13:03:52 -05:00
2026-01-13 14:49:49 -05:00
private:
2025-10-01 12:22:08 -05:00
double arr[];
2026-01-06 13:03:52 -05:00
2025-10-01 12:22:08 -05:00
ENUM_TIMEFRAMES timeframe;
int handle;
2026-01-06 13:03:52 -05:00
2025-10-01 12:22:08 -05:00
public:
~CAtr();
CAtr();
2026-01-06 13:03:52 -05:00
//---
2025-10-01 12:22:08 -05:00
inline bool IsIdxValid(const int idx, const string& function_name) const;
2026-01-13 14:49:49 -05:00
2025-10-01 12:22:08 -05:00
//---
2026-01-13 14:49:49 -05:00
2025-10-01 12:22:08 -05:00
void SetAsSeries(bool flag);
bool CopyData(int start, int count);
2026-01-13 14:49:49 -05:00
2025-10-01 12:22:08 -05:00
bool CopyData(int count);
//---
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
void Create(ENUM_TIMEFRAMES tf, const string& symb, int period, bool execute_on_bar, bool hide_indicator = true);
2026-03-05 12:10:29 -05:00
void Create(const int handle_);
2025-10-01 12:22:08 -05:00
bool Sincronize(const int min_bars_calc, const int ms_sleep, int attemps = 100);
2026-03-05 12:10:29 -05:00
2026-01-06 13:03:52 -05:00
2026-03-05 12:10:29 -05:00
//---
2025-10-01 12:22:08 -05:00
inline ENUM_TIMEFRAMES Timeframe() const { return timeframe; }
inline int Handle() const { return handle; }
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
void Free() { ArrayFree(arr); }
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
//---
2026-03-05 12:10:29 -05:00
// Para evitar erroers use el check..
double operator[](int _index) const { return arr[_index]; }
2025-10-01 12:22:08 -05:00
};
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
//+------------------------------------------------------------------+
//| Contructor and Destructor |
2026-03-23 12:25:12 -05:00
2025-10-01 12:22:08 -05:00
//+------------------------------------------------------------------+
CAtr::CAtr(void)
2026-03-23 12:25:12 -05:00
2026-03-05 12:10:29 -05:00
: handle(INVALID_HANDLE), timeframe(WRONG_VALUE)
2025-10-01 12:22:08 -05:00
2026-03-23 12:25:12 -05:00
{
2025-10-01 12:22:08 -05:00
ArrayResize(arr, 0);
2026-03-23 12:25:12 -05:00
}
//+------------------------------------------------------------------+
CAtr::~CAtr()
{
if(handle != INVALID_HANDLE)
2025-10-01 12:22:08 -05:00
IndicatorRelease(handle);
//Free();
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
}
//+------------------------------------------------------------------+
//| Check index |
2026-01-13 14:49:49 -05:00
//+------------------------------------------------------------------+
2025-10-01 12:22:08 -05:00
2026-03-23 12:25:12 -05:00
inline bool CAtr::IsIdxValid(const int idx, const string& function_name) const
2025-10-01 12:22:08 -05:00
2026-03-23 12:25:12 -05:00
{
if(int(arr.Size()) > idx && idx >= 0)
return true;
2026-01-13 14:49:49 -05:00
2026-03-23 12:25:12 -05:00
else
2025-10-01 12:22:08 -05:00
2026-03-23 12:25:12 -05:00
{
LogError(StringFormat("Acceso al array de atr denegado, indice %d fuera de rango, tama<00>o del array = %u", idx, arr.Size()), function_name);
return false;
}
2025-10-01 12:22:08 -05:00
2026-03-23 12:25:12 -05:00
}
//+------------------------------------------------------------------+
2025-10-01 12:22:08 -05:00
bool CAtr::CopyData(int start, int count)
2026-03-23 12:25:12 -05:00
{
2025-10-01 12:22:08 -05:00
ResetLastError();
if(CopyBuffer(handle, 0, start, count, arr) != count)
{
LogError(StringFormat("No se pudo copiar data del indicador de atr [start %d -> count: %d], ultimo error = %d", start, count, GetLastError()), FUNCION_ACTUAL);
return false;
}
// FastLog(FUNCION_ACTUAL, INFO_TEXT, StringFormat("El handle del indicador es %s", (handle == INVALID_HANDLE ? "invalido" : "valido")));
return true;
}
2026-01-06 13:03:52 -05:00
2025-10-01 12:22:08 -05:00
//+------------------------------------------------------------------+
bool CAtr::CopyData(int count)
{
ResetLastError();
if(CopyBuffer(handle, 0, 0, count, arr) != count)
{
LogError(StringFormat("No se pudo copiar data del indicador de atr [0 -> count: %d], ultimo error = %d", count, GetLastError()), FUNCION_ACTUAL);
return false;
2026-03-05 12:10:29 -05:00
//FastLog(FUNCION_ACTUAL, INFO_TEXT, StringFormat("El handle del indicador es %s", (handle == INVALID_HANDLE ? "invalido" : "valido")));
2025-10-01 12:22:08 -05:00
}
return true;
2026-02-14 17:00:45 -05:00
}
2025-10-01 12:22:08 -05:00
2026-03-05 12:10:29 -05:00
2026-02-14 17:00:45 -05:00
2025-10-01 12:22:08 -05:00
//+------------------------------------------------------------------+
void CAtr::Create(ENUM_TIMEFRAMES tf, const string& symb, int period, bool execute_on_bar, bool hide_indicator = true)
2026-02-14 17:00:45 -05:00
{
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
ResetLastError();
2026-02-14 17:00:45 -05:00
2025-10-01 12:22:08 -05:00
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
//---
if(hide_indicator)
TesterHideIndicators(true);
//---
const int handle_ = iCustom(symb, (timeframe = tf), "::AtrCts.ex5", period, execute_on_bar);
2026-02-14 17:00:45 -05:00
2025-10-01 12:22:08 -05:00
//---
if(hide_indicator)
TesterHideIndicators(false);
2026-02-14 17:00:45 -05:00
2025-10-01 12:22:08 -05:00
//---
if(handle_ == INVALID_HANDLE)
{
LogFatalError(StringFormat("No se pudo crear el handle para el indicador atr, ultimo error = %d", GetLastError()), FUNCION_ACTUAL);
2026-01-06 13:03:52 -05:00
Remover();
2025-10-01 12:22:08 -05:00
}
else
{
this.handle = handle_;
}
}
//+------------------------------------------------------------------+
void CAtr::Create(const int handle_)
{
if(handle_ == INVALID_HANDLE)
{
LogFatalError(StringFormat("No se pudo crear el handle para el indicador atr, ultimo error = %d", GetLastError()), FUNCION_ACTUAL);
Remover();
return;
}
//---
this.handle = handle_;
}
//+------------------------------------------------------------------+
2026-02-07 08:52:57 -05:00
//| |
2025-10-01 12:22:08 -05:00
//+------------------------------------------------------------------+
bool CAtr::Sincronize(const int min_bars_calc, const int ms_sleep, int attemps = 100)
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
{
//---
while(attemps-- > 0)
2026-03-05 12:10:29 -05:00
2025-10-01 12:22:08 -05:00
{
if(BarsCalculated(this.handle) >= min_bars_calc)
{
return true;
}
2026-01-06 13:03:52 -05:00
2025-10-01 12:22:08 -05:00
//---
Sleep(ms_sleep);
}
2026-02-14 17:00:45 -05:00
//---
2025-10-01 12:22:08 -05:00
LogError(StringFormat("Fallo al obtener data del indicador Atr | # Intenos = %d | Min Bars = %d | SleepMs = %d", attemps, min_bars_calc, ms_sleep), FUNCION_ACTUAL);
2026-02-14 17:00:45 -05:00
//---
2025-10-01 12:22:08 -05:00
return false;
}
2026-02-14 17:00:45 -05:00
2025-10-01 12:22:08 -05:00
//+------------------------------------------------------------------+
void CAtr::SetAsSeries(bool flag)
{
ArraySetAsSeries(this.arr, flag);
}
//+------------------------------------------------------------------+
bool DataIsValid(const double &arr[])
{
for(int i = 0; i < (int)arr.Size(); i++)
{
if(arr[i] == 0.00 || arr[i] == EMPTY_VALUE)
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Base class to implement the atr |
//+------------------------------------------------------------------+
class CAtrOptimized : public CLoggerBase
{
protected:
ENUM_TIMEFRAMES m_timeframe;
string m_symbol;
int m_index;
int m_period;
double m_atr_value; // Valor ATR espec<EFBFBD>fico para m_index
double wilder_factor;
2026-02-14 17:00:45 -05:00
double inv_period;
2025-10-01 12:22:08 -05:00
//---
2026-02-14 17:00:45 -05:00
double high[];
2025-10-01 12:22:08 -05:00
double low[];
double close[];
2026-01-06 13:03:52 -05:00
2025-10-01 12:22:08 -05:00
double atr[];
2026-02-14 17:00:45 -05:00
2025-10-01 12:22:08 -05:00
//---
CBarControler controler_curr;
inline double CalculeTrueRange(int idx);
inline double CalculeTrueRangeForIndexCts(int index);
bool CopyData();
public:
CAtrOptimized(ENUM_TIMEFRAMES tf, const string& symbol, int index, int period);
~CAtrOptimized(void);
//---
virtual inline double GetAtrValue(const datetime curr_time) = 0;
};
//+------------------------------------------------------------------+
//| Constructor and destructor |
//+------------------------------------------------------------------+
CAtrOptimized::CAtrOptimized(ENUM_TIMEFRAMES tf, const string& symbol, int index, int period)
: controler_curr(tf)
{
//---
bool custom = false;
if(!SymbolExist(symbol, custom))
{
LogFatalError(StringFormat("El simbolo %s, es invalido", symbol), FUNCION_ACTUAL);
Remover();
return;
}
if(period <= 0)
{
LogFatalError(StringFormat("El periodo del atr %d, es invalido", period), FUNCION_ACTUAL);
Remover();
return;
}
//---
2026-03-05 12:10:29 -05:00
m_timeframe = tf;
2025-10-01 12:22:08 -05:00
m_symbol = symbol;
m_index = index;
2026-03-05 12:10:29 -05:00
m_period = period;
m_atr_value = 0.0;
2025-10-01 12:22:08 -05:00
wilder_factor = (double)(m_period - 1) / m_period; // 13/14 para per<EFBFBD>odo 14
inv_period = 1.0 / m_period; // 1/14 para per<EFBFBD>odo 14
//---
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArrayResize(high, 0);
ArrayResize(low, 0);
ArrayResize(close, 0);
ArrayResize(atr, m_period + 2);
}
//+------------------------------------------------------------------+
CAtrOptimized::~CAtrOptimized(void)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define CopyAtrExtraValue 3
#define CopyAtr(p) p*2+CopyAtrExtraValue
2026-01-06 13:03:52 -05:00