Hi,
...
Structs: https://www.mql5.com/en/docs/basis/types/classes
But first you have to find a unified presentation of all of your indicator parameters.
- www.mql5.com
Thanks, perhaps I do not get your point. Is what your wrote not just a repetition of my question as a task which I'm not able to find out.
But at least I have found out that I can use double as datatype for int parameters. And as far as I can see, my indicators are only using uint, int and double. So probably I just need double as baseclass for parameters ...
One indicator is using a string input, but I have the source code and can modify that indicator and remove that string input.
This is not really a nice solution but for testing good enough. I'll give it a try.
Regards
Daniel
I solved it this way:
struct IndicatorParam { double vals[]; }; struct IndicatorDescriptor { string path; int bufferIndexValue; int bufferIndexSignal; int paramsSetCount; IndicatorParam parameters[4]; }; void initIndicatorMetadata() { ... imd_setMD(IMD_FISHER_TRANSFORM, "crossing/Ehlers Fisher transform (original)", 0, 1); imd_setMD(IMD_ATR_RATIO, "Volume/atrratio", 0, -1); imd_addPs(IMD_ATR_RATIO, 0, 7, 4, 10); // set metadata as initialized metadata_initialized = true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void imd_addPs(int indicatorIdx, int paramNo, double val1, double val2=IMD_INVALID_PARAM, double val3=IMD_INVALID_PARAM) { imd_addP(indicatorIdx, paramNo, val1); if(val2 > IMD_INVALID_PARAM) { imd_addP(indicatorIdx, paramNo, val2); } if(val3 > IMD_INVALID_PARAM) { imd_addP(indicatorIdx, paramNo, val3); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void imd_addP(int indicatorIdx, int paramNo, double val) { int siz = ArraySize(metadata_indicators[indicatorIdx].parameters[paramNo].vals); ArrayResize(metadata_indicators[indicatorIdx].parameters[paramNo].vals, siz+1); metadata_indicators[indicatorIdx].parameters[paramNo].vals[siz] = val; if(metadata_indicators[indicatorIdx].paramsSetCount <= paramNo) { metadata_indicators[indicatorIdx].paramsSetCount = paramNo + 1; } }
You can use MqlParam for this.
int IndicatorInit(int indicatorIdx, MqlParam &pars[]) { switch(indicatorIdx) { case IMD_FISHER_TRANSFORM: return iCustom(NULL, PERIOD_CURRENT, imd_getPath(indicatorIdx), pars[0].integer_value, pars[1].double_value); ...
For documentation about MqlParam see the MQL5 reference. See also the IndicatorCreate() function with generic parameters.
- www.mql5.com
Yes, thats how I do it currently. With 30 indicators you have a lot of redundant code because you need to add each new indicator into the switch case.
Now I have a generic mechanism with any need to extend that code, except I need more than 5 parameters
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int initIndicator(int indicatorIdx, int param1=0, int param2=0, int param3=0, int param4=0, int param5=0) { int handle = INVALID_HANDLE; int valueIdxArr[] = {param1,param2, param3, param4, param5}; initIndicatorMetadata(); if(indicatorIdx == IMD_NONE) { return INVALID_HANDLE; } switch(metadata_indicators[indicatorIdx].paramsSetCount) { case 0: handle = iCustom(NULL, PERIOD_CURRENT, metadata_indicators[indicatorIdx].path); case 1: handle = iCustom(NULL, PERIOD_CURRENT, metadata_indicators[indicatorIdx].path, imd_getP(indicatorIdx, 0, valueIdxArr)); case 2: handle = iCustom(NULL, PERIOD_CURRENT, metadata_indicators[indicatorIdx].path, imd_getP(indicatorIdx, 0, valueIdxArr), imd_getP(indicatorIdx, 1, valueIdxArr)); case 3: handle = iCustom(NULL, PERIOD_CURRENT, metadata_indicators[indicatorIdx].path, imd_getP(indicatorIdx, 0, valueIdxArr), imd_getP(indicatorIdx, 1, valueIdxArr), imd_getP(indicatorIdx, 2, valueIdxArr)); case 4: handle = iCustom(NULL, PERIOD_CURRENT, metadata_indicators[indicatorIdx].path, imd_getP(indicatorIdx, 0, valueIdxArr), imd_getP(indicatorIdx, 1, valueIdxArr), imd_getP(indicatorIdx, 2, valueIdxArr), imd_getP(indicatorIdx, 3, valueIdxArr)); case 5: handle = iCustom(NULL, PERIOD_CURRENT, metadata_indicators[indicatorIdx].path, imd_getP(indicatorIdx, 0, valueIdxArr), imd_getP(indicatorIdx, 1, valueIdxArr), imd_getP(indicatorIdx, 2, valueIdxArr), imd_getP(indicatorIdx, 3, valueIdxArr), imd_getP(indicatorIdx, 4, valueIdxArr)); } return handle; }
Yes, thats how I do it currently. With 30 indicators you have a lot of redundant code because you need to add each new indicator into the switch case.
Now I have a generic mechanism with any need to extend that code, except I need more than 5 parameters
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
I'm writing an EA for testing combinations of different indicators.
For that I want want to have different parameter sets for each indicator.
My problem is that the code is getting a bit redundant I would like to initialize the indicators based on the metadata.
Parameters shal be stored in an structure (see code: ?? parameterSet1[];) including the possible parameters and on initialization (see code initIndicator()) I want to take the data from there.
For only the path that way is working, but I need some help with the ... in iCustom.
here is the code:
struct IndicatorDescriptor { string path; int bufferIndexValue; int bufferIndexSignal; int paramsSetCount; ?? parameterSet1[]; ?? parameterSet2[]; }; bool metadata_initialized = false; // collection of settings // Volume: waddah attar int Waddah_Fast_MA[] = {9, 11, 13, 15, 20, 25, 30, 35, 40}; // Waddah: Period of the fast MACD moving average int Waddah_Slow_MA[] = {30, 35, 40, 47, 55, 60}; // Waddah: Period of the slow MACD moving average int Waddah_BBPeriod[]= {9, 11, 13, 15, 20, 25, 30, 35, 40}; // Waddah: Bollinger period double Waddah_BBDeviation[]= {2}; // Waddah: Number of Bollinger deviations int Waddah_Sensetive[]= {150}; // Waddah: Sensetive // V1: Damiani 7, 65, 1.3 uint Damiani_InpViscosity[] = {5, 7, 9, 11, 15, 10, 12, 13}; // Damiani: Viscosity uint Damiani_InpSedimentation[] = {35, 50, 65}; // Damiani: Sedimentation double Damiani_InpThreshold[] = {1.1}; // Damiani: Threshold // V1: PZ Volatmeter int PZVolat_Fast[] = {5,10,15}; // PZ Volatmeter Fast int PZVolat_Slow[] = {10,15,20}; // PZ Volatmeter Slow // V1: Trend direction and force int TDF_Period[] = {4, 6, 8}; // Trend direction and force Period double TDF_TriggerUpDown[] = {0.05, 0.1, 0.2}; // Trend direction and force Trigger up*down // V1: int ATRR_Period_Fast[] = {7, 4}; int ATRR_Period_Slow[] = {49, 21}; // All indicators to have an unique index for each indicator enum ENUM_MetadataIndicator { IMD_NONE = -1, IMD_REX = 0, IMD_METRO = 1, IMD_TREND_DIRECTION_AND_FORCE = 2, IMD_WADDAH = 3, IMD_DAMIANI = 4, IMD_PZ_VOLATMETER = 5, IMD_FISHER_TRANSFORM = 6, IMD_ATR_RATIO = 7, // add new indicators before _ENUM_MetadataIndicator_ENTRIES _ENUM_MetadataIndicator_ENTRIES // Must be the last entry (!!) }; IndicatorDescriptor metadata_indicators[_ENUM_MetadataIndicator_ENTRIES]; // subset for Volume indicators enum ENUM_MetadataIndicatorV1 { IMD_V1__NONE = IMD_NONE, // No V1 IMD_V1__WADDAH = IMD_WADDAH, // Waddah Attar Explosion IMD_V1__DAMIANI = IMD_DAMIANI, // Damiani Volatmeter IMD_V1__PZ_VOLATMETER = IMD_PZ_VOLATMETER, // PZ Volatmeter 2.0 IMD_V1__TDF = IMD_TREND_DIRECTION_AND_FORCE, // Trend direction and force IMD_V1__ATR_RATIO = IMD_ATR_RATIO // ATR Ratio }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void initIndicatorMetadata() { // if already initialized early out if(metadata_initialized) return; imd_setMD(IMD_REX, "rex", 0, 1); imd_setMD(IMD_METRO,"metro", 1, 2); imd_setMD(IMD_TREND_DIRECTION_AND_FORCE, "Volume/Trend direction and force", 2, -1); imd_setMD(IMD_WADDAH, "Volume/waddah_attar_explosion", 0, 0); imd_setMD(IMD_DAMIANI, "Volume/Damiani_Volatmeter", 0, 0); imd_setMD(IMD_PZ_VOLATMETER, "Market/PZ Volatmeter MT5", 0, 0); imd_setMD(IMD_FISHER_TRANSFORM, "crossing/Ehlers Fisher transform (original)", 0, 1); imd_setMD(IMD_ATR_RATIO, "Volume/atrratio", 0, -1); // set metadata as initialized metadata_initialized = true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void imd_setMD(int idx, string path, int bufferIndexValue, int bufferValueSignal) { metadata_indicators[idx].path = path; metadata_indicators[idx].bufferIndexValue = bufferIndexValue; metadata_indicators[idx].bufferIndexSignal = bufferValueSignal; metadata_indicators[idx].paramsSetCount = 0; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int imd_CopyBufferValue(int indicatorIndex,int handle, int startpos,int count,double &double_array[]) { initIndicatorMetadata(); int buffer_num = metadata_indicators[indicatorIndex].bufferIndexValue; return CopyBuffer(handle,buffer_num,startpos,count,double_array); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string imd_getPath(int indicatorIndex) { initIndicatorMetadata(); return metadata_indicators[indicatorIndex].path; } int initIndicator(int indicatorIdx, int param1, int param2) { return iCustom(NULL, PERIOD_CURRENT, imd_getPath(indicatorIdx), metadata_indicators[indicatorIndex].parameterSet2[param2], metadata_indicators[indicatorIndex].parameterSet2[param2]); } //+------------------------------------------------------------------+Which datatype can I use to store int, double, bool, enums and string which are the parameters fo different indicator?
Thanks for any hint
Regards
Daniel