#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 * * 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 data structures */ /* */ /*********************************************************************************************************************************************************/ /////////////////////////////////////// // // Dynamic scale array base object // template 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 class _generic_scale_array : public _base_scale_array { 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*)p_in).value; return((U*)_base_scale_array::operator=((_base_scale_array*)p_in)); } }; // // END MQL data structures */ //*********************************************************************************************************************************************************/ #endif // LIB_MQLPLUS_BASE_SCALE_ARRAY_TEMPLATES_MQH_INCLUDED