399 lines
18 KiB
MQL5
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
|