MQLArticles/Utils/FA/Atr.mqh

545 lines
36 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 |
//+------------------------------------------------------------------+
#include "SimpleLogger.mqh"
#include "BarControler.mqh"
//+------------------------------------------------------------------+
//| Resources |
//+------------------------------------------------------------------+
#resource "AtrCts.ex5"
//+------------------------------------------------------------------+
//| Class to handle the atr |
//+------------------------------------------------------------------+
class CAtr : public CLoggerBase
{
private:
double arr[];
int handle;
inline bool IsIdxValid(const int idx) const;
public:
~CAtr();
CAtr();
void SetAsSeries(bool flag);
inline void CopyData(int start, int count);
inline void CopyData(int count);
void Create(ENUM_TIMEFRAMES tf, string symb, int period, bool execute_on_bar, bool hide_indicator = true);
inline int Handle() const { return handle; }
void Create(int handle_);
void Free() { ArrayFree(arr); }
double operator[](int _index) const { return IsIdxValid(_index) ? arr[_index] : 0.00; }
};
//+------------------------------------------------------------------+
//| Contructor and Destructor |
//+------------------------------------------------------------------+
CAtr::CAtr(void)
: handle(INVALID_HANDLE)
{
ArrayResize(arr, 0);
}
//+------------------------------------------------------------------+
CAtr::~CAtr()
{
if(handle != INVALID_HANDLE)
IndicatorRelease(handle);
Free();
}
//+------------------------------------------------------------------+
//| Check index |
//+------------------------------------------------------------------+
inline bool CAtr::IsIdxValid(const int idx) const
{
if((int)arr.Size() > idx && idx >= 0)
return true;
else
{
LogError(StringFormat("Acceso al array de atr denegado, indice %d fuera de rango, tama<00>o del array = %u", idx, arr.Size()), FUNCION_ACTUAL);
return false;
}
}
//+------------------------------------------------------------------+
inline void CAtr::CopyData(int start, int count)
{
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);
// FastLog(FUNCION_ACTUAL, INFO_TEXT, StringFormat("El handle del indicador es %s", (handle == INVALID_HANDLE ? "invalido" : "valido")));
}
}
//+------------------------------------------------------------------+
inline void 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);
//FastLog(FUNCION_ACTUAL, INFO_TEXT, StringFormat("El handle del indicador es %s", (handle == INVALID_HANDLE ? "invalido" : "valido")));
}
}
//+------------------------------------------------------------------+
void CAtr::Create(ENUM_TIMEFRAMES tf, string symb, int period, bool execute_on_bar, bool hide_indicator = true)
{
ResetLastError();
if(hide_indicator)
TesterHideIndicators(true);
int handle_ = iCustom(symb, tf, "::AtrCts.ex5", period, execute_on_bar);
if(hide_indicator)
TesterHideIndicators(false);
Create(handle_);
}
//+------------------------------------------------------------------+
void CAtr::Create(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_;
int atemps = 1000;
double dummy[];
bool is = false;
ArrayResize(dummy, 0);
ArraySetAsSeries(dummy, true);
while(atemps-- > 0)
{
CopyBuffer(handle, 0, 0, 500, dummy);
is = DataIsValid(dummy);
if(is)
break;
}
}
//+------------------------------------------------------------------+
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;
double inv_period;
//---
double high[];
double low[];
double close[];
double atr[];
//---
CBarControler* controler_curr;
inline double CalculeTrueRange(int idx);
inline double CalculeTrueRangeForIndexCts(int index);
bool CopyData();
public:
CAtrOptimized(ENUM_TIMEFRAMES tf, string symbol, int index, int period);
~CAtrOptimized(void);
virtual inline double GetAtrValue(datetime curr_time) = 0;
};
//+------------------------------------------------------------------+
//| Constructor and destructor |
//+------------------------------------------------------------------+
CAtrOptimized::CAtrOptimized(ENUM_TIMEFRAMES tf, string symbol, int index, int period)
{
bool custom = false;
if(SymbolExist(symbol, custom) == false)
{
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;
}
m_timeframe = tf;
m_symbol = symbol;
m_index = index;
m_period = period;
m_atr_value = 0.0;
controler_curr = new CBarControler(tf, symbol);
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)
{
ArrayFree(high);
ArrayFree(low);
ArrayFree(close);
ArrayFree(atr);
if(CheckPointer(controler_curr) == POINTER_DYNAMIC && controler_curr != NULL)
delete controler_curr;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define CopyAtrExtraValue 3
#define CopyAtr(p) p*2+CopyAtrExtraValue
//---
bool CAtrOptimized::CopyData()
{
int to_copy = CopyAtr(m_period);
if(CopyHigh(this.m_symbol, this.m_timeframe, m_index, to_copy, high) < to_copy)
{
LogError(StringFormat("Al copiar data de los highs, start = %d - count = %d", m_index, to_copy), FUNCION_ACTUAL);
return false;
}
if(CopyClose(this.m_symbol, this.m_timeframe, m_index, to_copy, close) < to_copy)
{
LogError(StringFormat("Al copiar data de los closes start = %d - count = %d", m_index, to_copy), FUNCION_ACTUAL);
return false;
}
2025-11-10 09:33:53 -05:00