//+------------------------------------------------------------------+ //| OLAPGUI_Opts.mqh | //| Copyright (c) 2019-2020, Marketeer | //| https://www.mql5.com/en/users/marketeer | //| Online Analytical Processing of trading hypercubes | //| https://www.mql5.com/en/articles/6602 | //| https://www.mql5.com/en/articles/6603 | //| https://www.mql5.com/en/articles/7656 | //+------------------------------------------------------------------+ #include #define MAX_ALGO_CHOICES 9 // NB: this is the number of aggregators (most lengthy row in settings) template class OLAPDialog: public OLAPDialogBase { private: OLAPEngine *olapcore; OLAPDisplay *olapdisplay; public: OLAPDialog(OLAPEngine &olapimpl); ~OLAPDialog(void); virtual int process() override; virtual void setup() override; void setPrintLog(const bool printLog) { if(CheckPointer(olapdisplay) != POINTER_INVALID) olapdisplay.setPrintLog(printLog); } }; template OLAPDialog::OLAPDialog(OLAPEngine &olapimpl) { curveType = CURVE_POINTS; olapcore = &olapimpl; olapdisplay = new OLAPDisplay(&this); } template OLAPDialog::~OLAPDialog(void) { delete olapdisplay; } template void OLAPDialog::setup() override { static const string _settings[ALGO_NUMBER][MAX_ALGO_CHOICES] = { // enum AGGREGATORS 1:1, default - sum {"sum", "average", "max", "min", "count", "profit factor", "progressive total", "identity", "variance"}, // enum RECORD_FIELDS 1:1, default - profit amount {""}, // enum SORT_BY, default - none {"none", "value ascending", "value descending", "label ascending", "label descending"}, // enum ENUM_CURVE_TYPE partially, default - points {"points", "lines", "points/lines", "steps", "histogram"} }; static const int _defaults[ALGO_NUMBER] = {0, FIELD_PROFIT, 0, 0}; const int std = EnumSize(0); const int fields = std + customFieldCount; ArrayResize(settings, fields); ArrayResize(selectors, fields); selectors[0] = "(/field)"; // none selectors[1] = ""; // the only selector, which can be chosen explicitly, it correspods to the 'index' field for(int i = 0; i < ALGO_NUMBER; i++) { if(i == 1) // pure fields { for(int j = 0; j < fields; j++) { settings[j][i] = j < std ? Record::legendFromEnum((F)j) : customFields[j - std]; } } else { for(int j = 0; j < MAX_ALGO_CHOICES; j++) { settings[j][i] = _settings[i][j]; } } } for(int j = 2; j < fields; j++) // 0-th is none { selectors[j] = j < std ? Record::legendFromEnum((F)j) : customFields[j - std]; } ArrayCopy(defaults, _defaults); } template int OLAPDialog::process() override { SELECTORS Selectors[4]; ENUM_FIELDS Fields[4]; AGGREGATORS at = (AGGREGATORS)m_algo[0].Value(); ENUM_FIELDS af = (ENUM_FIELDS)(AGGREGATORS)m_algo[1].Value(); SORT_BY sb = (SORT_BY)m_algo[2].Value(); if(at == AGGREGATOR_IDENTITY) { Print("Sorting is disabled for Identity"); sb = SORT_BY_NONE; } ArrayInitialize(Selectors, SELECTOR_NONE); ArrayInitialize(Fields, FIELD_NONE); int matches[2] = { SELECTOR_NONE, SELECTOR_INDEX }; for(int i = 0; i < AXES_NUMBER; i++) { if(!m_axis[i].IsVisible()) continue; int v = (int)m_axis[i].Value(); if(v < 2) // selectors (which is specialized for a field already) { Selectors[i] = (SELECTORS)matches[v]; } else // pure fields { Selectors[i] = at == AGGREGATOR_IDENTITY ? SELECTOR_SCALAR : SELECTOR_QUANTS; Fields[i] = (ENUM_FIELDS)(v); } } m_plot.CurvesRemoveAll(); if(at == AGGREGATOR_IDENTITY || at == AGGREGATOR_COUNT) af = FIELD_NONE; m_plot.InitXAxis(at != AGGREGATOR_PROGRESSIVE ? new AxisCustomizer(m_plot.getGraphic(), false, false, false, at == AGGREGATOR_IDENTITY) : NULL); m_plot.InitYAxis(at == AGGREGATOR_IDENTITY ? new AxisCustomizer(m_plot.getGraphic(), true, false, false, true) : NULL); m_button_ok.Text("Processing..."); return olapcore.process(Selectors, Fields, at, af, olapdisplay, sb); }