MQLplus/lib_structures/base/lib_base_scale_array.mqh
super.admin 466f9ca5c5 convert
2025-05-30 16:09:52 +02:00

399 lines
18 KiB
MQL5

#ifndef LIB_MQLPLUS_BASE_SCALE_ARRAY_TEMPLATES_MQH_INCLUDED
#define LIB_MQLPLUS_BASE_SCALE_ARRAY_TEMPLATES_MQH_INCLUDED
#property version "1.2";
/**********************************************************************************
* Copyright (C) 2010-2022 Dominik Egert <info@freie-netze.de>
*
* This file is the scale array include file.
*
* MQLplus, including this file may not be copied and/or distributed
* without explecit permit by the author.
* Author Dominik Egert / Freie Netze UG.
**********************************************************************************
*
* Version: 1.2
* State: production
*
* File information
* ================
*
*
*
*
*/
#ifdef DBG_MSG_TRACE_FILE_LOADER
DBG_MSG_TRACE_FILE_LOADER;
#endif
///////////////////////////////
//
// Include mt5api Array
//
#include <MQLplus/lib_mqlplus/mt5api/lib_mt5api_Array_tpl.mqh>
/*********************************************************************************************************************************************************/
/* */
/* MQLplus data structures */
/* */
/*********************************************************************************************************************************************************/
///////////////////////////////////////
//
// Dynamic scale array base object
//
template <typename U, typename T>
class _base_scale_array pack(8)
{
protected:
// Dimension structure
class __dim pack(4)
{
public:
// Local storage
long step_size;
long idx_p_factor;
long pivot_point;
int upper_size;
int lower_size;
U* upper_arr[];
U* lower_arr[];
// Default constructor
__dim() :
step_size (1),
idx_p_factor (1),
pivot_point (NULL),
upper_size (NULL),
lower_size (NULL)
{ };
// Custom constructor
__dim(const long _pivot_point) :
step_size (1),
idx_p_factor (1),
pivot_point (_pivot_point),
upper_size (NULL),
lower_size (NULL)
{ };
__dim(const double pivot, const int digits = NULL, const int _step_size = NULL) :
step_size ((_step_size > NULL) ? _step_size : ((int)MathMax(SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE) / _Point, 1.0))),
idx_p_factor ((long)MathPow(10, (digits > NULL) ? digits : _Digits)),
pivot_point ((long)(pivot * idx_p_factor) / step_size),
upper_size (NULL),
lower_size (NULL)
{ };
__dim(const datetime pivot, const int _step_size = NULL) :
step_size ((_step_size > NULL) ? _step_size : (int)(PeriodSeconds(_Period))),
pivot_point ((long)(pivot)),
idx_p_factor (1),
upper_size (NULL),
lower_size (NULL)
{ };
// Destructor
~__dim()
{
for(upper_size--; (upper_size >= NULL); upper_size--) { if(upper_arr[upper_size] != NULL) { delete(upper_arr[upper_size]); } };
for(lower_size--; (lower_size >= NULL); lower_size--) { if(lower_arr[lower_size] != NULL) { delete(lower_arr[lower_size]); } };
};
// Local helper
const int array_resize(const bool lower, const int new_size)
{
if(lower)
{
mqp_ArrayResize(lower_arr, new_size);
for(; (lower_size < new_size) && !_StopFlag; lower_size++)
{ lower_arr[lower_size] = NULL; }
}
else
{
mqp_ArrayResize(upper_arr, new_size);
for(; (upper_size < new_size) && !_StopFlag; upper_size++)
{ upper_arr[upper_size] = NULL; }
}
return(new_size);
};
};
// Local storage
__dim* p_dimension;
// Protected storage
T value;
public:
// Default constructor
_base_scale_array() :
p_dimension (NULL)
{ };
// Custom constructor
_base_scale_array(const double pivot, const int digits = NULL, const int _step_size = NULL) :
p_dimension (new __dim(pivot, digits, _step_size))
{ };
_base_scale_array(const datetime pivot, const int _step_size = NULL) :
p_dimension (new __dim(pivot, _step_size))
{ };
// Destructor
~_base_scale_array()
{ if(p_dimension != NULL) { delete(p_dimension); } };
// Array operator
_base_scale_array* operator=(_base_scale_array* p_in)
{
// Self-Copy protection
if(GetPointer(this) == p_in)
{ return(p_in); }
else if(p_dimension == NULL)
{
p_dimension = p_in.p_dimension;
p_in.p_dimension = NULL;
}
else
{
const int upper_limit = MathMax(p_dimension.upper_size, p_in.p_dimension.upper_size);
mqp_ArrayResize(p_dimension.upper_arr, upper_limit);
for(int cnt = NULL; (cnt < upper_limit) && !_StopFlag; cnt++)
{
if((cnt < p_dimension.upper_size) && (p_dimension.upper_arr[cnt] != NULL)) { delete(p_dimension.upper_arr[cnt]); }
p_dimension.upper_arr[cnt] = (cnt < p_in.p_dimension.upper_size) ? p_in.p_dimension.upper_arr[cnt] : NULL;
}
p_dimension.upper_size = p_in.p_dimension.upper_size;
ArrayResize(p_dimension.upper_arr, p_dimension.upper_size);
const int lower_limit = MathMax(p_dimension.lower_size, p_in.p_dimension.lower_size);
mqp_ArrayResize(p_dimension.lower_arr, lower_limit);
for(int cnt = NULL; (cnt < lower_limit) && !_StopFlag; cnt++)
{
if((cnt < p_dimension.lower_size) && (p_dimension.lower_arr[cnt] != NULL)) { delete(p_dimension.lower_arr[cnt]); }
p_dimension.lower_arr[cnt] = (cnt < p_in.p_dimension.lower_size) ? p_in.p_dimension.lower_arr[cnt] : NULL;
}
p_dimension.lower_size = p_in.p_dimension.lower_size;
ArrayResize(p_dimension.lower_arr, p_dimension.lower_size);
p_dimension.idx_p_factor = p_in.p_dimension.idx_p_factor;
p_dimension.step_size = p_in.p_dimension.step_size;
p_dimension.pivot_point = p_in.p_dimension.pivot_point;
}
return(GetPointer(this));
}
// Dimension function
const int dimensions(int max_depth = NULL, int depth = NULL)
{
depth++;
max_depth = (max_depth < depth) ? depth : max_depth;
if(p_dimension != NULL)
{
for(int cnt = NULL; (cnt < p_dimension.upper_size) && !_StopFlag; cnt++)
{ max_depth = (p_dimension.upper_arr[cnt] == NULL) ? max_depth : p_dimension.upper_arr[cnt].dimensions(max_depth, depth); }
for(int cnt = NULL; (cnt < p_dimension.lower_size) && !_StopFlag; cnt++)
{ max_depth = (p_dimension.lower_arr[cnt] == NULL) ? max_depth : p_dimension.lower_arr[cnt].dimensions(max_depth, depth); }
}
depth--;
return(max_depth);
};
const bool sub_dimensions()
{ return(p_dimension != NULL); }
void remove_dim()
{
if(p_dimension != NULL)
{ delete(p_dimension); }
};
// Array functions
const int size(const bool sub_dimensions = false)
{
if(sub_dimensions)
{
int _size = p_dimension.upper_size + p_dimension.lower_size;
for(int cnt = NULL; (cnt < p_dimension.upper_size) && !_StopFlag; cnt++)
{ _size += (p_dimension.upper_arr[cnt] == NULL) ? NULL : p_dimension.upper_arr[cnt].size(); }
for(int cnt = NULL; (cnt < p_dimension.lower_size) && !_StopFlag; cnt++)
{ _size += (p_dimension.lower_arr[cnt] == NULL) ? NULL : p_dimension.lower_arr[cnt].size(); }
return(_size);
}
return(p_dimension.upper_size + p_dimension.lower_size);
};
void reset()
{
for(int cnt = NULL; (cnt < p_dimension.upper_size) && !_StopFlag; cnt++)
{ if(p_dimension.upper_arr[cnt] != NULL) { delete(p_dimension.upper_arr[cnt]); } }
for(int cnt = NULL; (cnt < p_dimension.lower_size) && !_StopFlag; cnt++)
{ if(p_dimension.lower_arr[cnt] != NULL) { delete(p_dimension.lower_arr[cnt]); } }
p_dimension.pivot_point = NULL;
p_dimension.upper_size = NULL;
p_dimension.lower_size = NULL;
ArrayFree(p_dimension.upper_arr);
ArrayFree(p_dimension.lower_arr);
};
// Element functions
T append(T& p_in)
{
p_dimension = (p_dimension != NULL) ? p_dimension : new __dim();
const int new_idx = p_dimension.array_resize(false, p_dimension.upper_size + 1) - 1;
p_dimension.upper_arr[new_idx] = new U(((U*)GetPointer(this)).dnd(false));
p_dimension.upper_arr[new_idx].operator=(p_in);
return(p_in);
};
T prepend(T& p_in)
{
p_dimension = (p_dimension != NULL) ? p_dimension : new __dim();
const int new_idx = p_dimension.array_resize(true, p_dimension.lower_size + 1) - 1;
p_dimension.lower_arr[new_idx] = new U(((U*)GetPointer(this)).dnd(false));
p_dimension.lower_arr[new_idx].operator=(p_in);
return(p_in);
};
const int assign_range(const datetime source_element, const datetime first_element, const datetime last_element)
{ return(assign_range(operator[](source_element), (long)(first_element / p_dimension.step_size), (long)(last_element / p_dimension.step_size))); };
const int assign_range(const double source_element, const double first_element, const double last_element)
{ return(assign_range(operator[](source_element), (long)MathRound((first_element * p_dimension.idx_p_factor) / p_dimension.step_size, 0), (long)MathRound((last_element * p_dimension.idx_p_factor) / p_dimension.step_size, 0))); };
const int assign_range(const long source_element, const long first_element, const long last_element)
{ return(assign_range(operator[](source_element), (long)MathRound((first_element * p_dimension.idx_p_factor) / p_dimension.step_size, 0), (long)MathRound((last_element * p_dimension.idx_p_factor) / p_dimension.step_size, 0))); };
const int assign_range(U* source_element, const datetime first_element, const datetime last_element)
{ return(assign_range(source_element, (long)(first_element / p_dimension.step_size), (long)(last_element / p_dimension.step_size))); };
const int assign_range(U* source_element, const double first_element, const double last_element)
{ return(assign_range(source_element, (long)MathRound((first_element * p_dimension.idx_p_factor) / p_dimension.step_size, 0), (long)MathRound((last_element * p_dimension.idx_p_factor) / p_dimension.step_size, 0))); };
const int assign_range(U* source_element, const long first_element, const long last_element)
{
long _idx = NULL;
for(long idx = first_element; (idx <= last_element) && !_StopFlag; idx++)
{
if(idx < p_dimension.pivot_point)
{
_idx = fabs(idx - p_dimension.pivot_point) - 1;
p_dimension.lower_size = (_idx >= p_dimension.lower_size) ? p_dimension.array_resize(true, (int)(_idx + 1)) : p_dimension.lower_size;
p_dimension.lower_arr[(int)_idx] = source_element;
}
else
{
_idx = idx - p_dimension.pivot_point;
p_dimension.upper_size = (_idx >= p_dimension.upper_size) ? p_dimension.array_resize(false, (int)(_idx + 1)) : p_dimension.upper_size;
p_dimension.upper_arr[(int)_idx] = source_element;
}
}
return((int)(last_element - first_element) + 1);
};
// Element operator
U* operator[](const datetime time_idx)
{
p_dimension = (p_dimension != NULL) ? p_dimension : (new __dim(time_idx));
return(operator[]((long)(time_idx / p_dimension.step_size)));
};
U* operator[](const double price_idx)
{
p_dimension = (p_dimension != NULL) ? p_dimension : (new __dim(price_idx));
return(operator[]((long)MathRound((price_idx * p_dimension.idx_p_factor) / p_dimension.step_size, 0)));
};
U* operator[](const long idx)
{
//bool tmp = ((U*)GetPointer(this)).dnd();
p_dimension = (p_dimension != NULL) ? p_dimension : (new __dim(idx));
long _idx = idx;
if(idx < p_dimension.pivot_point)
{
_idx = fabs(_idx - p_dimension.pivot_point) - 1;
p_dimension.lower_size = (_idx >= p_dimension.lower_size) ? p_dimension.array_resize(true, (int)(_idx + 1)) : p_dimension.lower_size;
p_dimension.lower_arr[(int)_idx] = (p_dimension.lower_arr[(int)_idx] == NULL) ? (new U(((U*)GetPointer(this)).dnd(false))) : p_dimension.lower_arr[(int)_idx];
return(p_dimension.lower_arr[(int)_idx]);
}
_idx -= p_dimension.pivot_point;
p_dimension.upper_size = (_idx >= p_dimension.upper_size) ? p_dimension.array_resize(false, (int)(_idx + 1)) : p_dimension.upper_size;
p_dimension.upper_arr[(int)_idx] = (p_dimension.upper_arr[(int)_idx] == NULL) ? (new U(((U*)GetPointer(this)).dnd(false))) : p_dimension.upper_arr[(int)_idx];
return(p_dimension.upper_arr[(int)_idx]);
};
};
///////////////////////////////////////
//
// Dynamic scale array generic type
//
template <typename U, typename T>
class _generic_scale_array : public _base_scale_array<U, T>
{
public:
// Buffer functions
const bool dnd(const bool _do_not_destroy = true)
{ return(false); }
// Element function
T get()
{ return(value); }
// Assignment operator
U* operator=(U* p_in)
{
value = ((_base_scale_array<U, T>*)p_in).value;
return((U*)_base_scale_array<U, T>::operator=((_base_scale_array<U, T>*)p_in));
}
};
//
// END MQL data structures */
//*********************************************************************************************************************************************************/
#endif // LIB_MQLPLUS_BASE_SCALE_ARRAY_TEMPLATES_MQH_INCLUDED