how to use indicators handle as input parameters inside another indicator?

 

Hello folks, I have an indicator {indicator_diff} where I need to make use of the handles of other two indicators {indicator_1, indicator_2}.

What my indicator does is output the difference between the other two indicators, given by the handles: {handle_1, handle_2}.

Both handles are passed as input parameters from an external script.

If inside the indicator code below, you uncomment the "way 1" and comment the "way 2" the indicator will works (without the tester script) but I need the script because the indicators (and handles) will be generated outside the indicator code (due to some circunstances I need it like that).

With "way 2" (script way) I get "GetLastError: 4807" ("Wrong indicator handle") and I don't understand why because the indicators have been created properly inside the script. Any idea?.

Thank you!


[File 1/2]: Indicator code (file: "MyIndicators\DiffIndicator.mq5"):

#property indicator_separate_window
#property indicator_buffers             1
#property indicator_plots               1
#property indicator_type1               DRAW_LINE
#property indicator_color1              clrBlue
#property indicator_style1              STYLE_SOLID
#property indicator_width1              2

//---

// * [way 1] To use as indicator only (working version)
//int handle_1 = iMA("EURUSD", PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_CLOSE);
//int handle_2 = iMA("EURUSD", PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);

// * [way 2] To use by running the script: "DiffIndicatorTester" (NOT working version) (I need this way)
input int handle_1;
input int handle_2;

//---

double buffer[];
double data_1[];
double data_2[];

int OnInit() {

        ArraySetAsSeries(buffer, true);
        ArraySetAsSeries(data_1, true);
        ArraySetAsSeries(data_2, true);

        SetIndexBuffer(0, buffer, INDICATOR_DATA);
        IndicatorSetString(INDICATOR_SHORTNAME, "Diff. Indicator");
        IndicatorSetInteger(INDICATOR_DIGITS, _Digits + 1);

        return 0;
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{

        printf("handle_1: %d", handle_1);
        printf("handle_2: %d", handle_2);

        CopyBuffer(handle_1, 0, 0, rates_total, data_1);
        printf("1- GetLastError: %d", GetLastError());
        CopyBuffer(handle_2, 0, 0, rates_total, data_2);
        printf("2- GetLastError: %d", GetLastError());

        int count = MathMin(ArraySize(data_1), ArraySize(data_2));
        
        for (int i = 0; i < count; i++)
                buffer[i] = data_1[i] - data_2[i];
        
        return(rates_total);
}

[File 2/2]: Script code (file: "MyScripts\DiffIndicatorTester.mq5"):

void OnStart() {
        ChartSetInteger(0, CHART_SCALE, 3);
        ChartSetInteger(0, CHART_MODE, CHART_CANDLES);
        
        int handle_1 = iMA("EURUSD", PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_CLOSE);
        int handle_2 = iMA("EURUSD", PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
        
        MqlParam params[];
        ArrayResize(params, 3);
        params[0].type = TYPE_STRING;
        params[0].string_value = "MyIndicators\\DiffIndicator";
        params[1].type = TYPE_INT;
        params[1].integer_value = handle_1;
        params[2].type = TYPE_INT;
        params[2].integer_value = handle_2;
        int handle_diff = IndicatorCreate(_Symbol, PERIOD_CURRENT, IND_CUSTOM, ArraySize(params), params);

        ChartIndicatorAdd(0, 0, handle_1);
        ChartIndicatorAdd(0, 0, handle_2);
        ChartIndicatorAdd(0, 1, handle_diff);
        
}
 

things are half solved, but not totally. There is some inconsistent behaviour.

I added the red higlighted "key code" below.

It seems, that if I don't retrieve information about all indicators on the chart (for example with the function: "ChartIndicatorGet"), then the code inside the "DiffIndicator" is not aware about the indicators existing on the chart. If you remove the "key code", then the handles are like invalid. I don't know why this behaviour.

Here is the new code:

[File 1/2]: Indicator code (file: "MyIndicators\DiffIndicator.mq5"):

#property indicator_separate_window
#property indicator_buffers             1
#property indicator_plots               1
#property indicator_type1               DRAW_LINE
#property indicator_color1              clrBlue
#property indicator_style1              STYLE_SOLID
#property indicator_width1              2

//---

// * [way 1] To use as indicator only (working version)
//int handle_1 = iMA("EURUSD", PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_CLOSE);
//int handle_2 = iMA("EURUSD", PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);

// * [way 2] To use by running the script: "DiffIndicatorTester" (not working version) (I need this way)
input int handle_1;
input int handle_2;

//---

double buffer[];
double data_1[];
double data_2[];

int OnInit() {

        // begin of key code
        int total = (int)ChartGetInteger(0, CHART_WINDOWS_TOTAL);
        for(int w = 0; w < total; w++) {
                for(int i = 0; i < ChartIndicatorsTotal(0, w); i++) {
                        string name = ChartIndicatorName(0, w, i);
                        ChartIndicatorGet(0, w, name);
                }
        }
        // end of key code

        ArraySetAsSeries(buffer, true);
        ArraySetAsSeries(data_1, true);
        ArraySetAsSeries(data_2, true);

        SetIndexBuffer(0, buffer, INDICATOR_DATA);
        IndicatorSetString(INDICATOR_SHORTNAME, "Diff. Indicator");
        IndicatorSetInteger(INDICATOR_DIGITS, _Digits + 1);

        return 0;
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{

        printf("handle_1: %d", handle_1);
        printf("handle_2: %d", handle_2);

        CopyBuffer(handle_1, 0, 0, rates_total, data_1);
        printf("1- GetLastError: %d", GetLastError());
        CopyBuffer(handle_2, 0, 0, rates_total, data_2);
        printf("2- GetLastError: %d", GetLastError());

        int count = MathMin(ArraySize(data_1), ArraySize(data_2));
        
        for (int i = 0; i < count; i++)
                buffer[i] = data_1[i] - data_2[i];
        
        return(rates_total);
}

[File 2/2]: Script code (file: "MyScripts\DiffIndicatorTester.mq5"):

void OnStart() {
        ChartSetInteger(0, CHART_SCALE, 3);
        ChartSetInteger(0, CHART_MODE, CHART_CANDLES);
        
        int handle_1 = iMA("EURUSD", PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_CLOSE);
        int handle_2 = iMA("EURUSD", PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
        // I moved up the following two lines here but the code works with both lines on previous position (before the "ChartIndicatorAdd" below)
        ChartIndicatorAdd(0, 0, handle_1);
        ChartIndicatorAdd(0, 0, handle_2);
        
        MqlParam params[];
        ArrayResize(params, 3);
        params[0].type = TYPE_STRING;
        params[0].string_value = "MyIndicators\DiffIndicator";
        params[1].type = TYPE_INT;
        params[1].integer_value = handle_1;
        params[2].type = TYPE_INT;
        params[2].integer_value = handle_2;
        int handle_diff = IndicatorCreate(_Symbol, PERIOD_CURRENT, IND_CUSTOM, ArraySize(params), params);

        ChartIndicatorAdd(0, 1, handle_diff);
        
}

Any idea?, Thanks!

 

input int is static parameters and it is declared before the code is executed and it can not be changed upon run time.

instead copy the values to a variable.


//---

// * [way 1] To use as indicator only (working version)
//int handle_1 = iMA("EURUSD", PERIOD_CURRENT, 10, 0, MODE_SMA, PRICE_CLOSE);
//int handle_2 = iMA("EURUSD", PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);

// * [way 2] To use by running the script: "DiffIndicatorTester" (not working version) (I need this way)
int handle_1;
int handle_2;

//---
so drop the inputs
 
Marco vd Heijden:

input int is static parameters and it is declared before the code is executed and it can not be changed upon run time.

instead copy the values to a variable.

so drop the inputs

Marco that doesn't work :(

I have tested droping the "input" keywords and then the lines:

        printf("handle_1: %d", handle_1);
        printf("handle_2: %d", handle_2);

returns:

handle_2: 0
handle_1: 0

remember that I need to pass the handles from outside the indicator (becase certain circumstances I cannot change that).

With the "input" keywords the handle values go into the keywork correctly so there is no problem with that.

What it is strange for me is the "necessity" of the "key code", if it is there then the code works, but if I remove it then it doesn't works.

I would like to know if there is some way to write that more clear?

Thanks!

 
cyberglassed:

Marco that doesn't work :(

I have tested droping the "input" keywords and then the lines:

returns:

handle_2: 0
handle_1: 0

remember that I need to pass the handles from outside the indicator (becase certain circumstances I cannot change that).

With the "input" keywords the handle values go into the keywork correctly so there is no problem with that.

What it is strange for me is the "necessity" of the "key code", if it is there then the code works, but if I remove it then it doesn't works.

I would like to know if there is some way to write that more clear?

Thanks!

That's because an handle is not a simple integer, it's like a pointer to some internal information about the indicator (I don't exactly which one). When you create these handles in your script the underlying "internal information" are accessible in the script thread. But these informations are not available in your indicator. By running your "key" code you add these informations in the indicator thread (ChartIndicatorGet returns an handle even if you do not use it).

Not sure it's a reliable way. My suggestion would be to pass the needed data (chart id, window,shortname) to your indicator to retrieve the handle. I little more work but without any doubt reliable.

 
Alain Verleyen:

That's because an handle is not a simple integer, it's like a pointer to some internal information about the indicator (I don't exactly which one). When you create these handles in your script the underlying "internal information" are accessible in the script thread. But these informations are not available in your indicator. By running your "key" code you add these informations in the indicator thread (ChartIndicatorGet returns an handle even if you do not use it).

Not sure it's a reliable way. My suggestion would be to pass the needed data (chart id, window,shortname) to your indicator to retrieve the handle. I little more work but without any doubt reliable.

thank you Alain, I think it is a good idea to pass the indicator name (more reliable).

But I would like to know, once I have created the indicator on the "DiffIndicatorTester" script, ¿is there any way to change it's name in the script so I can pass it's name to the DiffIndicator?, I would like to use sequential names to avoid repeated names in case I have multiple indicators with same name in case there are multiple indicators with same parameters (we know the name of indicators by default is based on it's parameters).

Thanks!

 

yeah you can cycle in a for loop through chart id's, and then,

int  ChartIndicatorGet(....


and you can compile the same script multiple times but with some other name... easy does it.

 
Marco vd Heijden:

yeah you can cycle in a for loop through chart id's, and then,

and you can compile the same script multiple times but with some other name... easy does it.

Marco I don't understand what you say. Could you explain a little more about the goal of what are you saying?

thank you.

 
cyberglassed:

Marco I don't understand what you say. Could you explain a little more about the goal of what are you saying?

thank you.

oh my bad i was thinking you wanted to transfer between multiple charts but it seems u only want to talk from indicator to indicator to indicator on the same chart then the chartid is the same for all 3.

 
Marco vd Heijden:

oh my bad i was thinking you wanted to transfer between multiple charts but it seems u only want to talk from indicator to indicator to indicator on the same chart then the chartid is the same for all 3.

yes, thank you anyway Marco ;)
 
cyberglassed:

thank you Alain, I think it is a good idea to pass the indicator name (more reliable).

But I would like to know, once I have created the indicator on the "DiffIndicatorTester" script, ¿is there any way to change it's name in the script so I can pass it's name to the DiffIndicator?, I would like to use sequential names to avoid repeated names in case I have multiple indicators with same name in case there are multiple indicators with same parameters (we know the name of indicators by default is based on it's parameters).

Thanks!

You can't have 2 times the same indicator with the same parameters attached on a window.

An indicator shortname is defined inside the indicator you can't change is from a script. You can use ChartIndicatorName() to retrive the short name.

Reason: