MQLArticles/IndicatorsCts/Pool.mqh
nique_372 2d8dfa4ddd
2026-09-05 21:12:21 -05:00

1374 lines
42 KiB
MQL5

//+------------------------------------------------------------------+
//| Pool.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com/es/users/nique_372 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Niquel Mendoza."
#property link "https://www.mql5.com/es/users/nique_372"
#property strict
#ifndef MQLARTICLES_INDICATORSCTS_POOL_MQH
#define MQLARTICLES_INDICATORSCTS_POOL_MQH
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include "Main.mqh"
#include "PoolDef.mqh"
//+------------------------------------------------------------------+
//| Defines \ Global \ Structs |
//+------------------------------------------------------------------+
//---
#define INDICATOR_CACHE_DBL_DIG (2)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| Cache de indicadores |
//+------------------------------------------------------------------+
class CIndicatorCache
{
private:
//---
static TSN::CHashMapFastNor<TSN::CBitBuffer, int, TSN::CGenericHash_CBitBuffer> s_hash_str_to_int;
static bool s_is_active;
static CBitBuffer s_bit;
//--- RSI
static CiRsi* s_rsi[];
static IndicatorCacheExtraData s_rsi_data[];
static int s_rsi_r;
static int s_rsi_size;
//--- MA
static CiMa* s_ma[];
static IndicatorCacheExtraData s_ma_data[];
static int s_ma_size;
static int s_ma_r;
//--- CCI
static CiCci* s_cci[];
static IndicatorCacheExtraData s_cci_data[];
static int s_cci_size;
static int s_cci_r;
//--- Stochastic
static CiStocastic* s_stochastic[];
static IndicatorCacheExtraData s_stochastic_data[];
static int s_stochastic_size;
static int s_stochastic_r;
//--- VIDyA
static CiVIDyA* s_vidya[];
static IndicatorCacheExtraData s_vidya_data[];
static int s_vidya_size;
static int s_vidya_r;
//--- Bollinger Bands
static CiBands* s_bands[];
static IndicatorCacheExtraData s_bands_data[];
static int s_bands_size;
static int s_bands_r;
//--- SuperTrend
static CiSuperTrend* s_supertrend[];
static IndicatorCacheExtraData s_supertrend_data[];
static int s_supertrend_size;
static int s_supertrend_r;
//--- VWAP
static CiVwapChange* s_vwap[];
static IndicatorCacheExtraData s_vwap_data[];
static int s_vwap_size;
static int s_vwap_r;
//--- AD
static CiAD* s_ad[];
static IndicatorCacheExtraData s_ad_data[];
static int s_ad_size;
static int s_ad_r;
//--- OBV
static CiObv* s_obv[];
static IndicatorCacheExtraData s_obv_data[];
static int s_obv_size;
static int s_obv_r;
//--- Standard Deviation
static CiStandartDeviation* s_stddev[];
static IndicatorCacheExtraData s_stddev_data[];
static int s_stddev_size;
static int s_stddev_r;
//--- SAR
static CiSar* s_sar[];
static IndicatorCacheExtraData s_sar_data[];
static int s_sar_size;
static int s_sar_r;
//--- ADX
static CiAdx* s_adx[];
static IndicatorCacheExtraData s_adx_data[];
static int s_adx_size;
static int s_adx_r;
//--- ADX Wilder
static CiAdxWilder* s_adx_wilder[];
static IndicatorCacheExtraData s_adx_wilder_data[];
static int s_adx_wilder_size;
static int s_adx_wilder_r;
//--- Funcion template para remover
template <typename T>
static bool RemoveFromArray(T* &element, T* &array[], IndicatorCacheExtraData &data[], int &size);
public:
CIndicatorCache(void) {}
~CIndicatorCache(void) {}
//--- Init - Deinit
static void Init();
static void Deinit(const int reason);
//--- IsActive
static __forceinline bool IsActive() { return s_is_active; }
//--- RSI
static CiRsi* GetRsi(ENUM_TIMEFRAMES timeframe, string symbol, int period, ENUM_APPLIED_PRICE applied, bool series, bool hide);
static __forceinline bool RemoveRsi(CiRsi* element) { return RemoveFromArray(element, s_rsi, s_rsi_data, s_rsi_size); }
//--- MA
static CiMa* GetMa(ENUM_TIMEFRAMES timeframe, string symbol, int period, ENUM_APPLIED_PRICE applied, int ma_shift,
ENUM_MA_METHOD ma_method, bool series, bool hide);
static __forceinline bool RemoveMa(CiMa* element) { return RemoveFromArray(element, s_ma, s_ma_data, s_ma_size); }
//--- CCI
static CiCci* GetCci(ENUM_TIMEFRAMES timeframe, string symbol, int period, ENUM_APPLIED_PRICE applied, bool series, bool hide);
static __forceinline bool RemoveCci(CiCci* element) { return RemoveFromArray(element, s_cci, s_cci_data, s_cci_size); }
//--- Stochastic
static CiStocastic* GetStochastic(ENUM_TIMEFRAMES timeframe, string symbol, int kperiod, int dperiod, int slowing,
ENUM_MA_METHOD ma_method, ENUM_STO_PRICE sto_price, bool series, bool hide);
static __forceinline bool RemoveStochastic(CiStocastic* element) { return RemoveFromArray(element, s_stochastic, s_stochastic_data, s_stochastic_size); }
//--- VIDyA
static CiVIDyA* GetVidya(ENUM_TIMEFRAMES timeframe, string symbol, int cmo_period, int ema_period, int ma_shift,
ENUM_APPLIED_PRICE applied, bool series, bool hide);
static __forceinline bool RemoveVidya(CiVIDyA* element) { return RemoveFromArray(element, s_vidya, s_vidya_data, s_vidya_size); }
//--- Bollinger Bands
static CiBands* GetBands(ENUM_TIMEFRAMES timeframe, string symbol, int bands_period, int bands_shift, double deviation,
ENUM_APPLIED_PRICE applied_price, bool series, bool hide);
static __forceinline bool RemoveBands(CiBands* element) { return RemoveFromArray(element, s_bands, s_bands_data, s_bands_size); }
//--- SuperTrend
static CiSuperTrend* GetSuperTrend(ENUM_TIMEFRAMES timeframe, string symbol, int cci_period, ENUM_APPLIED_PRICE applied, int atr_period, bool series, bool hide);
static __forceinline bool RemoveSuperTrend(CiSuperTrend* element) { return RemoveFromArray(element, s_supertrend, s_supertrend_data, s_supertrend_size); }
//--- VWAP
static CiVwapChange* GetVwap(ENUM_TIMEFRAMES timeframe, string symbol, VWAP_Period period, ENUM_APPLIED_PRICE applied,
bool series, bool hide);
static __forceinline bool RemoveVwap(CiVwapChange* element) { return RemoveFromArray(element, s_vwap, s_vwap_data, s_vwap_size); }
//--- AD
static CiAD* GetAD(ENUM_TIMEFRAMES timeframe, string symbol, ENUM_APPLIED_VOLUME applied, bool series, bool hide);
static __forceinline bool RemoveAD(CiAD* element) { return RemoveFromArray(element, s_ad, s_ad_data, s_ad_size); }
//--- OBV
static CiObv* GetObv(ENUM_TIMEFRAMES timeframe, string symbol, ENUM_APPLIED_VOLUME applied, bool series, bool hide);
static __forceinline bool RemoveObv(CiObv* element) { return RemoveFromArray(element, s_obv, s_obv_data, s_obv_size); }
//--- Standard Deviation
static CiStandartDeviation* GetStdDev(ENUM_TIMEFRAMES timeframe, string symbol, int ma_period, int ma_shift,
ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied, bool series, bool hide);
static __forceinline bool RemoveStdDev(CiStandartDeviation* element) { return RemoveFromArray(element, s_stddev, s_stddev_data, s_stddev_size); }
//--- SAR
static CiSar* GetSar(ENUM_TIMEFRAMES timeframe, string symbol, double step, double maximum, bool series, bool hide);
static __forceinline bool RemoveSar(CiSar* element) { return RemoveFromArray(element, s_sar, s_sar_data, s_sar_size); }
//--- ADX
static CiAdx* GetAdx(ENUM_TIMEFRAMES timeframe, string symbol, int ma_period, bool series, bool hide);
static __forceinline bool RemoveAdx(CiAdx* element) { return RemoveFromArray(element, s_adx, s_adx_data, s_adx_size); }
//--- ADX Wilder
static CiAdxWilder* GetAdxWilder(ENUM_TIMEFRAMES timeframe, string symbol, int ma_period, bool series, bool hide);
static __forceinline bool RemoveAdxWilder(CiAdxWilder* element) { return RemoveFromArray(element, s_adx_wilder, s_adx_wilder_data, s_adx_wilder_size); }
};
//+------------------------------------------------------------------+
//| Init |
//+------------------------------------------------------------------+
static void CIndicatorCache::Init(void)
{
if(s_is_active)
return;
//---
s_is_active = true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename T>
static bool CIndicatorCache::RemoveFromArray(T* &element, T* &array[], IndicatorCacheExtraData &data[], int &size)
{
//---
const ENUM_POINTER_TYPE ptr_type = CheckPointer(element);
if(ptr_type == POINTER_INVALID)
{
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("se esta intentando eliminar un elemento INVALIDO, type = %s", typename(T)));
return false;
}
//--- Find
int idx = -1;
for(int i = 0; i < size; i++)
{
if(array[i] == element)
{
idx = i;
break;
}
}
//--- Verificamos si existe
if(idx == -1)
{
FastLog(FUNCION_ACTUAL, ERROR_TEXT, "El puntero que se busca eliminar ya no existe");
return false;
}
//--- Reducimos y comparamos, en caso ser menor o igual a 0 se termino para esta "key" lo eliminamos
if(--data[idx].ref_count <= 0)
{
//--- Eliminar objeto, solo si es DINAMICO
if(ptr_type == POINTER_DYNAMIC)
delete array[idx];
//--- Removemos del hashmap
if(!s_hash_str_to_int.Remove(data[idx]))
{
FastLog(FUNCION_ACTUAL, CRITICAL_ERROR_TEXT,
StringFormat("No se pudo eliminar el key con hash = '%I64u'", CGenericHash_CBitBuffer::Hash(data[idx])));
return false;
}
//--- Swap con el ultimo elemento
const int last = --size;
bool res = true;
if(last != idx)
{
array[idx] = array[last]; // puntero
data[idx].RobarDe(data[last]); // data
// Nota aqui el objeto que estaba en LAST ahora estara en la posicion IDX por loq ue key es de LAST
res = s_hash_str_to_int.TrySet(data[idx], idx);
}
//---
return res;
}
//--- exito en eliminar (Aqunue como tal no se elimino la ref)
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define MQLA_INDPOOL_CRESERVE(arr, s, r) \
if(s >= r)\
{\
r += (s << 1) + 2;\
ArrayResize(arr, r, r);\
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiRsi* CIndicatorCache::GetRsi(ENUM_TIMEFRAMES timeframe, string symbol, int period, ENUM_APPLIED_PRICE applied,
bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("RSI");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(period);
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_rsi_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_rsi, s_rsi_size, s_rsi_r)
//---
s_rsi[idx] = new CiRsi();
if(!s_rsi[idx].Create(timeframe, symbol, period, applied, series, hide))
{
delete s_rsi[idx];
s_rsi_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_rsi_data[idx] = s_bit; // #1 Copia
s_rsi_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_rsi_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_rsi[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiMa* CIndicatorCache::GetMa(ENUM_TIMEFRAMES timeframe, string symbol, int period, ENUM_APPLIED_PRICE applied, int ma_shift,
ENUM_MA_METHOD ma_method, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("MA");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(period);
s_bit.WriteInteger(applied);
s_bit.WriteInteger(ma_shift);
s_bit.WriteInteger(ma_method);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_ma_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_ma, s_ma_size, s_ma_r)
//---
s_ma[idx] = new CiMa();
if(!s_ma[idx].Create(timeframe, symbol, period, applied, ma_shift, ma_method, series, hide))
{
delete s_ma[idx];
s_ma_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_ma_data[idx] = s_bit; // #1 Copia
s_ma_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_ma_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_ma[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiCci* CIndicatorCache::GetCci(ENUM_TIMEFRAMES timeframe, string symbol, int period, ENUM_APPLIED_PRICE applied, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("CCI");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(period);
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_cci_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_cci, s_cci_size, s_cci_r)
//---
s_cci[idx] = new CiCci();
if(!s_cci[idx].Create(timeframe, symbol, period, applied, series, hide))
{
delete s_cci[idx];
s_cci_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_cci_data[idx] = s_bit; // #1 Copia
s_cci_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_cci_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_cci[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiStocastic* CIndicatorCache::GetStochastic(ENUM_TIMEFRAMES timeframe, string symbol, int kperiod, int dperiod, int slowing,
ENUM_MA_METHOD ma_method, ENUM_STO_PRICE sto_price, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("STOCH");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(kperiod);
s_bit.WriteInteger(dperiod);
s_bit.WriteInteger(slowing);
s_bit.WriteInteger(ma_method);
s_bit.WriteInteger(sto_price);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_stochastic_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_stochastic, s_stochastic_size, s_stochastic_r)
//---
s_stochastic[idx] = new CiStocastic();
if(!s_stochastic[idx].Create(timeframe, symbol, kperiod, dperiod, slowing, ma_method, sto_price, series, hide))
{
delete s_stochastic[idx];
s_stochastic_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_stochastic_data[idx] = s_bit; // #1 Copia
s_stochastic_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_stochastic_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_stochastic[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiVIDyA* CIndicatorCache::GetVidya(ENUM_TIMEFRAMES timeframe, string symbol, int cmo_period, int ema_period, int ma_shift,
ENUM_APPLIED_PRICE applied, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("VIDYA");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(cmo_period);
s_bit.WriteInteger(ema_period);
s_bit.WriteInteger(ma_shift);
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_vidya_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_vidya, s_vidya_size, s_vidya_r)
//---
s_vidya[idx] = new CiVIDyA();
if(!s_vidya[idx].Create(timeframe, symbol, cmo_period, ema_period, ma_shift, applied, series, hide))
{
delete s_vidya[idx];
s_vidya_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_vidya_data[idx] = s_bit; // #1 Copia
s_vidya_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_vidya_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_vidya[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiBands* CIndicatorCache::GetBands(ENUM_TIMEFRAMES timeframe, string symbol, int bands_period, int bands_shift, double deviation,
ENUM_APPLIED_PRICE applied_price, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key (deviation redondeado para mantener retrocompatibilidad de colision)
s_bit.Clear();
s_bit.WriteStringWPadd("BANDS");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(bands_period);
s_bit.WriteInteger(bands_shift);
s_bit.WriteDouble(NormalizeDouble(deviation, INDICATOR_CACHE_DBL_DIG));
s_bit.WriteInteger(applied_price);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_bands_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_bands, s_bands_size, s_bands_r)
//---
s_bands[idx] = new CiBands();
if(!s_bands[idx].Create(timeframe, symbol, bands_period, bands_shift, deviation, applied_price, series, hide))
{
delete s_bands[idx];
s_bands_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_bands_data[idx] = s_bit; // #1 Copia
s_bands_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_bands_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_bands[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiSuperTrend* CIndicatorCache::GetSuperTrend(ENUM_TIMEFRAMES timeframe, string symbol, int cci_period, ENUM_APPLIED_PRICE applied, int atr_period, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("SUPERTREND");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(cci_period);
s_bit.WriteInteger(applied);
s_bit.WriteInteger(atr_period);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_supertrend_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_supertrend, s_supertrend_size, s_supertrend_r)
//---
s_supertrend[idx] = new CiSuperTrend();
if(!s_supertrend[idx].Create(timeframe, symbol, series, hide, cci_period, applied, atr_period))
{
delete s_supertrend[idx];
s_supertrend_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_supertrend_data[idx] = s_bit; // #1 Copia
s_supertrend_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_supertrend_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_supertrend[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiVwapChange* CIndicatorCache::GetVwap(ENUM_TIMEFRAMES timeframe, string symbol, VWAP_Period period, ENUM_APPLIED_PRICE applied,
bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("VWAP");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(int(period));
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_vwap_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_vwap, s_vwap_size, s_vwap_r)
//---
s_vwap[idx] = new CiVwapChange();
if(!s_vwap[idx].Create(timeframe, symbol, period, applied, series, hide))
{
delete s_vwap[idx];
s_vwap_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_vwap_data[idx] = s_bit; // #1 Copia
s_vwap_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_vwap_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_vwap[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiAD* CIndicatorCache::GetAD(ENUM_TIMEFRAMES timeframe, string symbol, ENUM_APPLIED_VOLUME applied, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("AD");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_ad_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_ad, s_ad_size, s_ad_r)
//---
s_ad[idx] = new CiAD();
if(!s_ad[idx].Create(timeframe, symbol, applied, series, hide))
{
delete s_ad[idx];
s_ad_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_ad_data[idx] = s_bit; // #1 Copia
s_ad_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_ad_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_ad[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiObv* CIndicatorCache::GetObv(ENUM_TIMEFRAMES timeframe, string symbol, ENUM_APPLIED_VOLUME applied, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("OBV");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_obv_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_obv, s_obv_size, s_obv_r)
//---
s_obv[idx] = new CiObv();
if(!s_obv[idx].Create(timeframe, symbol, applied, series, hide))
{
delete s_obv[idx];
s_obv_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_obv_data[idx] = s_bit; // #1 Copia
s_obv_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_obv_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_obv[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiStandartDeviation* CIndicatorCache::GetStdDev(ENUM_TIMEFRAMES timeframe, string symbol, int ma_period, int ma_shift,
ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("STDDEV");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(ma_period);
s_bit.WriteInteger(ma_shift);
s_bit.WriteInteger(ma_method);
s_bit.WriteInteger(applied);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_stddev_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_stddev, s_stddev_size, s_stddev_r)
//---
s_stddev[idx] = new CiStandartDeviation();
if(!s_stddev[idx].Create(timeframe, symbol, ma_period, ma_shift, ma_method, applied, series, hide))
{
delete s_stddev[idx];
s_stddev_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_stddev_data[idx] = s_bit; // #1 Copia
s_stddev_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_stddev_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_stddev[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiSar* CIndicatorCache::GetSar(ENUM_TIMEFRAMES timeframe, string symbol, double step, double maximum, bool series, bool hide)
{
//--- Normalizamos timeframe
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key (step/maximum redondeados para mantener retrocompatibilidad de colision)
s_bit.Clear();
s_bit.WriteStringWPadd("SAR");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteDouble(NormalizeDouble(step, INDICATOR_CACHE_DBL_DIG));
s_bit.WriteDouble(NormalizeDouble(maximum, INDICATOR_CACHE_DBL_DIG));
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_sar_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_sar, s_sar_size, s_sar_r)
//---
s_sar[idx] = new CiSar();
if(!s_sar[idx].Create(timeframe, symbol, step, maximum, series, hide))
{
delete s_sar[idx];
s_sar_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_sar_data[idx] = s_bit; // #1 Copia
s_sar_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_sar_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_sar[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiAdx* CIndicatorCache::GetAdx(ENUM_TIMEFRAMES timeframe, string symbol, int ma_period, bool series, bool hide)
{
//---
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("ADX");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(ma_period);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_adx_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_adx, s_adx_size, s_adx_r)
//---
s_adx[idx] = new CiAdx();
if(!s_adx[idx].Create(timeframe, symbol, ma_period, series, hide))
{
delete s_adx[idx];
s_adx_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_adx_data[idx] = s_bit; // #1 Copia
s_adx_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_adx_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_adx[idx];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static CiAdxWilder* CIndicatorCache::GetAdxWilder(ENUM_TIMEFRAMES timeframe, string symbol, int ma_period, bool series, bool hide)
{
//---
if(timeframe == PERIOD_CURRENT)
timeframe = _Period;
//--- Key
s_bit.Clear();
s_bit.WriteStringWPadd("ADXWILDER");
s_bit.WriteStringWPadd(symbol);
s_bit.WriteInteger(timeframe);
s_bit.WriteInteger(ma_period);
s_bit.WriteBool(series);
//--- Verificamos si existe en caso no existe lo creamos
int idx;
if(s_hash_str_to_int.ReserveSlot(s_bit))
{
//---
idx = s_adx_wilder_size++;
//--- Array
MQLA_INDPOOL_CRESERVE(s_adx_wilder, s_adx_wilder_size, s_adx_wilder_r)
//---
s_adx_wilder[idx] = new CiAdxWilder();
if(!s_adx_wilder[idx].Create(timeframe, symbol, ma_period, series, hide))
{
delete s_adx_wilder[idx];
s_adx_wilder_size--;
s_hash_str_to_int.RemoveLastFindCall(); // ultimo call
return NULL;
}
//--- copia por =
(CBitBuffer&)s_adx_wilder_data[idx] = s_bit; // #1 Copia
s_adx_wilder_data[idx].ref_count = 1;
//--- Hashmap
const uint p = s_hash_str_to_int.m_last_pos_tbl;
s_hash_str_to_int.m_table[p].key.RobarDe(s_bit);
s_hash_str_to_int.m_table[p].value = idx;
s_bit.SyncArrayRSize(); // esto por el swap tenemos que acutlizar r
}
else
{
const uint p = s_hash_str_to_int.m_last_pos_tbl;
idx = s_hash_str_to_int.m_table[p].value;
s_adx_wilder_data[idx].ref_count++;
}
//--- Retornamos puntero
return s_adx_wilder[idx];
}
//+------------------------------------------------------------------+
//| Deinit |
//+------------------------------------------------------------------+
static void CIndicatorCache::Deinit(const int reason)
{
//---
if(!s_is_active)
return;
//--- RSI
if(s_rsi_size)
{
for(int i = 0; i < s_rsi_size; i++)
if(CheckPointer(s_rsi[i]) == POINTER_DYNAMIC)
delete s_rsi[i];
s_rsi_size = 0;
}
//--- MA
if(s_ma_size)
{
for(int i = 0; i < s_ma_size; i++)
if(CheckPointer(s_ma[i]) == POINTER_DYNAMIC)
delete s_ma[i];
s_ma_size = 0;
}
//--- CCI
if(s_cci_size)
{
for(int i = 0; i < s_cci_size; i++)
if(CheckPointer(s_cci[i]) == POINTER_DYNAMIC)
delete s_cci[i];
s_cci_size = 0;
}
//--- Stochastic
if(s_stochastic_size)
{
for(int i = 0; i < s_stochastic_size; i++)
if(CheckPointer(s_stochastic[i]) == POINTER_DYNAMIC)
delete s_stochastic[i];
s_stochastic_size = 0;
}
//--- VIDyA
if(s_vidya_size)
{
for(int i = 0; i < s_vidya_size; i++)
if(CheckPointer(s_vidya[i]) == POINTER_DYNAMIC)
delete s_vidya[i];
s_vidya_size = 0;
}
//--- Bollinger Bands
if(s_bands_size)
{
for(int i = 0; i < s_bands_size; i++)
if(CheckPointer(s_bands[i]) == POINTER_DYNAMIC)
delete s_bands[i];
s_bands_size = 0;
}
//--- SuperTrend
if(s_supertrend_size)
{
for(int i = 0; i < s_supertrend_size; i++)
if(CheckPointer(s_supertrend[i]) == POINTER_DYNAMIC)
delete s_supertrend[i];
s_supertrend_size = 0;
}
//--- VWAP
if(s_vwap_size)
{
for(int i = 0; i < s_vwap_size; i++)
if(CheckPointer(s_vwap[i]) == POINTER_DYNAMIC)
delete s_vwap[i];
s_vwap_size = 0;
}
//--- AD
if(s_ad_size)
{
for(int i = 0; i < s_ad_size; i++)
if(CheckPointer(s_ad[i]) == POINTER_DYNAMIC)
delete s_ad[i];
s_ad_size = 0;
}
//--- OBV
if(s_obv_size)
{
for(int i = 0; i < s_obv_size; i++)
if(CheckPointer(s_obv[i]) == POINTER_DYNAMIC)
delete s_obv[i];
s_obv_size = 0;
}
//--- Standard Deviation
if(s_stddev_size)
{
for(int i = 0; i < s_stddev_size; i++)
if(CheckPointer(s_stddev[i]) == POINTER_DYNAMIC)
delete s_stddev[i];
s_stddev_size = 0;
}
//--- SAR
if(s_sar_size)
{
for(int i = 0; i < s_sar_size; i++)
if(CheckPointer(s_sar[i]) == POINTER_DYNAMIC)
delete s_sar[i];
s_sar_size = 0;
}
//--- ADX
if(s_adx_size)
{
for(int i = 0; i < s_adx_size; i++)
if(CheckPointer(s_adx[i]) == POINTER_DYNAMIC)
delete s_adx[i];
s_adx_size = 0;
}
//--- ADX Wilder
if(s_adx_wilder_size)
{
for(int i = 0; i < s_adx_wilder_size; i++)
if(CheckPointer(s_adx_wilder[i]) == POINTER_DYNAMIC)
delete s_adx_wilder[i];
s_adx_wilder_size = 0;
}
//---
s_is_active = false;
}
//+------------------------------------------------------------------+
//| Inicializacion de variables estaticas |
//+------------------------------------------------------------------+
TSN::CHashMapFastNor<TSN::CBitBuffer, int, TSN::CGenericHash_CBitBuffer> CIndicatorCache::s_hash_str_to_int;
bool CIndicatorCache::s_is_active = false;
CBitBuffer CIndicatorCache::s_bit(32);
//--- RSI
CiRsi* CIndicatorCache::s_rsi[] = {};
IndicatorCacheExtraData CIndicatorCache::s_rsi_data[];
int CIndicatorCache::s_rsi_size = 0;
int CIndicatorCache::s_rsi_r = 0;
//--- MA
CiMa* CIndicatorCache::s_ma[] = {};
IndicatorCacheExtraData CIndicatorCache::s_ma_data[];
int CIndicatorCache::s_ma_size = 0;
int CIndicatorCache::s_ma_r = 0;
//--- CCI
CiCci* CIndicatorCache::s_cci[] = {};
IndicatorCacheExtraData CIndicatorCache::s_cci_data[];
int CIndicatorCache::s_cci_size = 0;
int CIndicatorCache::s_cci_r = 0;
//--- Stochastic
CiStocastic* CIndicatorCache::s_stochastic[] = {};
IndicatorCacheExtraData CIndicatorCache::s_stochastic_data[];
int CIndicatorCache::s_stochastic_size = 0;
int CIndicatorCache::s_stochastic_r = 0;
//--- VIDyA
CiVIDyA* CIndicatorCache::s_vidya[] = {};
IndicatorCacheExtraData CIndicatorCache::s_vidya_data[];
int CIndicatorCache::s_vidya_size = 0;
int CIndicatorCache::s_vidya_r = 0;
//--- Bollinger Bands
CiBands* CIndicatorCache::s_bands[] = {};
IndicatorCacheExtraData CIndicatorCache::s_bands_data[];
int CIndicatorCache::s_bands_size = 0;
int CIndicatorCache::s_bands_r = 0;
//--- SuperTrend
CiSuperTrend* CIndicatorCache::s_supertrend[] = {};
IndicatorCacheExtraData CIndicatorCache::s_supertrend_data[];
int CIndicatorCache::s_supertrend_size = 0;
int CIndicatorCache::s_supertrend_r = 0;
//--- VWAP
CiVwapChange* CIndicatorCache::s_vwap[] = {};
IndicatorCacheExtraData CIndicatorCache::s_vwap_data[];
int CIndicatorCache::s_vwap_size = 0;
int CIndicatorCache::s_vwap_r = 0;
//--- AD
CiAD* CIndicatorCache::s_ad[] = {};
IndicatorCacheExtraData CIndicatorCache::s_ad_data[];
int CIndicatorCache::s_ad_size = 0;
int CIndicatorCache::s_ad_r = 0;
//--- OBV
CiObv* CIndicatorCache::s_obv[] = {};
IndicatorCacheExtraData CIndicatorCache::s_obv_data[];
int CIndicatorCache::s_obv_size = 0;
int CIndicatorCache::s_obv_r = 0;
//--- Standard Deviation
CiStandartDeviation* CIndicatorCache::s_stddev[] = {};
IndicatorCacheExtraData CIndicatorCache::s_stddev_data[];
int CIndicatorCache::s_stddev_size = 0;
int CIndicatorCache::s_stddev_r = 0;
//--- SAR
CiSar* CIndicatorCache::s_sar[] = {};
IndicatorCacheExtraData CIndicatorCache::s_sar_data[];
int CIndicatorCache::s_sar_size = 0;
int CIndicatorCache::s_sar_r = 0;
//--- ADX
CiAdx* CIndicatorCache::s_adx[] = {};
IndicatorCacheExtraData CIndicatorCache::s_adx_data[];
int CIndicatorCache::s_adx_size = 0;
int CIndicatorCache::s_adx_r = 0;
//--- ADX Wilder
CiAdxWilder* CIndicatorCache::s_adx_wilder[] = {};
IndicatorCacheExtraData CIndicatorCache::s_adx_wilder_data[];
int CIndicatorCache::s_adx_wilder_size = 0;
int CIndicatorCache::s_adx_wilder_r = 0;
//---
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
#endif // MQLARTICLES_INDICATORSCTS_POOL_MQH