Can you control an EA from an Indicator???

 

Ok,

I'm not a total noob to programming and I've been working with MQL4 on and off for a little while now....although not consistently enough I might add.

Here's the question. I have a couple EA's built and a few Custom Indicators and I would like changes made to the external variables of the EA to be reflected on the Chart visually....Please follow the steps below for example:

Steps:

1. Change Moving Average period from EA's external variables (This is passed in to the CustomIndicator during the iCustom call in order to determine trade conditions)

2. EA is now running using new value for Moving Average's period....I would like the chart in the window (Drawn by the CustomIndicator which has it's own external variables) to be redrawn to reflect the new variable values (in this case...the moving average period)

Am I confusing the issue here on how things should work?

Should I even be doing it this way?

Should both the EA and the CustomIndicator share one global External Variable Value????

Thanks...

 

Should both the EA and the CustomIndicator share one global External Variable Value????

They can do that.

Have the EA write the period value, have the indicator read it and use it.

 
phy:

Should both the EA and the CustomIndicator share one global External Variable Value????

They can do that.

Have the EA write the period value, have the indicator read it and use it.



Thanks for the reply phy, but I already do this when calling the iCustom function. I pass the EA's CURRENT values (for Period, Symbol, etc.) to my indicator as they are external variables there. However, I would like my indicator to be redrawn to reflect the new settings when I change them via my EA.

Here's the breakdown. I can have my indicator on a chart and use it independently of the EA...so it has external variables that may or may not match those of the EA. I control what the Indicator looks like via its own external variables. Now...consider adding the EA to the chart that is already running the indicator. The EA also has its own set of External Variables to control how it is making decisions. The iCustom call in the EA is using the indicator on the chart.....The EA uses the Indicator's calculation for signals based on what values it send to it via the iCustom call.....maybe I should have a function to identify when I change the external variable values of the EA and then trigger the indicator to be redrawn using those values?

The confusing part to me is...wouldn't this produce some kind of cyclical issue? How can the EA "control" the Indicator when the Indicator is the one that is supposed to "control" the EA???

Thanks

 

There would be no cyclical issue, unless the output(s) from the indicator affect the indicators input parameters. The OP wants the indicator to use the EAs values.

The simplest method would be for the indicator to read global variables and override its externals when they exist. But this requires changes to both EA and indicator.

Option two would be to have the EA do the following
  1. Perform a template save #define's for known commands that can be used for PostMessageA()
  2. Copy the template file Automated Optimization of a Trading Robot in Real Trading
  3. Read and modify adding/modifying the indicator
  4. Copy back
  5. Perform a template attach.

I don't have the time to try this, but searching shows many would like it.

See also Execute an existing EA from a script/ea

 

unfortunately this is not possible. the indicator loaded by iCustom() and the same indicator manually added to the chart are two separate instances. Unfortunalely iCustom() indicators are always invisible and there is no way to simply unhide them.

I have solved this problem in the past by simply letting my EA plot chart objects (many line segments to plot the indicator curve or arrow objects to visualize arrow buffers) from the values that the EA retrieved through iCustom() into the chart.

 

" I would like changes made to the external variables of the EA to be reflected on the Chart visually...."

Method 1.

Have the EA draw stuff as 7bit suggested.

Method 2.

Modify your indicator to look for parameters using GlobalVariableGet().

Attach your indicator to the chart.

Have the EA write values using GlobalVariableSet() that the Indicator will read using GlobalVariableGet() to control the indicator from the EA.

 
how can I contact you privately..I need help on forex..i lost $150 already and I think i'm getting something wrong...thnks...isaacdjumanji@gmail.com
Tenners:

Ok,

I'm not a total noob to programming and I've been working with MQL4 on and off for a little while now....although not consistently enough I might add.

Here's the question. I have a couple EA's built and a few Custom Indicators and I would like changes made to the external variables of the EA to be reflected on the Chart visually....Please follow the steps below for example:

Steps:

1. Change Moving Average period from EA's external variables (This is passed in to the CustomIndicator during the iCustom call in order to determine trade conditions)

2. EA is now running using new value for Moving Average's period....I would like the chart in the window (Drawn by the CustomIndicator which has it's own external variables) to be redrawn to reflect the new variable values (in this case...the moving average period)

Am I confusing the issue here on how things should work?

Should I even be doing it this way?

Should both the EA and the CustomIndicator share one global External Variable Value????

Thanks...


 
phy:

" I would like changes made to the external variables of the EA to be reflected on the Chart visually...."

Method 1.

Have the EA draw stuff as 7bit suggested.

Method 2.

Modify your indicator to look for parameters using GlobalVariableGet().

Attach your indicator to the chart.

Have the EA write values using GlobalVariableSet() that the Indicator will read using GlobalVariableGet() to control the indicator from the EA.



Thanks for the responses everyone!

I will try to let you know which method turns out to be a good solution for me.

Regards,

T.

 
Try this:
//+------------------------------------------------------------------+
//| EA equivalent of indicator buffers                               |
//+------------------------------------------------------------------+
/*  Example 1:
 *  if (...) Ordermodify(...);
 *  Polyline("SL"+(oo.ticket%99), oo.SL, Color.Dn, 0);
 *
 *  Example 2:
 *  double  ELineCurr = iMA(NULL,0, ELine.Period, 0, MODE_EMA, PRICE_CLOSE, 1);
 *  Polyline("ELine", ELineCurr, Color.ELine, 1);
 ******************************************************************************/
#define POLYLINE_MAX 10 // Must match priceM
double  price0[], price1[], price2[], price3[], price4[],   // \   Export from
        price5[], price6[], price7[], price8[], price9[];   //  \  Polyline
int     LRU[POLYLINE_MAX],  segNo[POLYLINE_MAX];            //   > import to
string  lineName[POLYLINE_MAX];                             // _/  PLHelper
datetime mem0[POLYLINE_MAX];
void Polyline(string name, double price, color clr, int shift){
    if (!Show.Objects)  return;
    for (int idx=0; idx < POLYLINE_MAX; idx++){     LRU[idx]++; }
    for (idx=0; idx < POLYLINE_MAX; idx++){
        bool new = lineName[idx] != name;   if (!new) break;    }
    if (new)    idx=ArrayMaximum(LRU);
    LRU[idx] = 0;   switch (idx){
    case 0: PLHelper(name, price, clr, idx, new, shift, price0); return;
    case 1: PLHelper(name, price, clr, idx, new, shift, price1); return;
    case 2: PLHelper(name, price, clr, idx, new, shift, price2); return;
    case 3: PLHelper(name, price, clr, idx, new, shift, price3); return;
    case 4: PLHelper(name, price, clr, idx, new, shift, price4); return;
    case 5: PLHelper(name, price, clr, idx, new, shift, price5); return;
    case 6: PLHelper(name, price, clr, idx, new, shift, price6); return;
    case 7: PLHelper(name, price, clr, idx, new, shift, price7); return;
    case 8: PLHelper(name, price, clr, idx, new, shift, price8); return;
    case 9: PLHelper(name, price, clr, idx, new, shift, price9); return;
}   }
void PLHelper( string name, double price, color clr, int idx, bool new
             , int shift, double& mem[] ){
    if (new){   ArrayResize(mem, 1);    lineName[idx]=name;     segNo[idx]=0;   }
    else if (Time[shift] != mem0[idx]){ // Shift values m[2]=m[1]; m[1]=m[0]
                ArraySetAsSeries(mem, true);
                        ArrayResize(mem, ArraySize(mem)+1);
                ArraySetAsSeries(mem, false);
        }
    mem0[idx]=Time[shift];      mem[0]=price;   int firstBar=ArraySize(mem)-1;
    if (ObjectMove(name, 1, Time[shift],            price))
        ObjectMove(name, 0, Time[shift+firstBar],   mem[firstBar]);
    else if (!ObjectCreate( name, OBJ_TREND, WINDOW_MAIN,
            Time[shift],            price,
            Time[shift+firstBar],   mem[firstBar] )){                   Alert(
        "ObjectCreate(", name, "Trend) [1] failed: ",GetLastError());   return;}
    else if (!ObjectSet( name, OBJPROP_COLOR, clr ))                Alert(
        "ObjectSet(", name, "Color) [2] failed: ", GetLastError());
    else if (!ObjectSet( name, OBJPROP_RAY, false ))                Alert(
        "ObjectSet(", name, "Ray) [1] failed: ", GetLastError());

    double maxError=0;  int maxBar;
    for (int pos=0; pos <= firstBar; pos++){
        double error=MathAbs(ObjectGetValueByShift(name, pos+shift)-mem[pos]);
        if (error > maxError){  maxError=error; maxBar=pos; }
    }
    if (maxError >= pips2dbl){  // Split the line into two segments at the max.
        segNo[idx]++;   string newName=name+"-"+segNo[idx];
        if (ObjectMove(newName, 0, Time[firstBar+shift], mem[firstBar]))
            ObjectMove(newName, 1, Time[maxBar  +shift], mem[maxBar]);
        else if (!ObjectCreate( newName, OBJ_TREND, WINDOW_MAIN,
            Time[firstBar+shift],   mem[firstBar],
            Time[maxBar  +shift],   mem[maxBar] )){                     Alert(
            "ObjectCreate(", newName, "Trend) [2] failed: ",GetLastError());
                                                                        return;}
        else if (!ObjectSet( newName, OBJPROP_COLOR, clr ))             Alert(
            "ObjectSet(", newName, "Color) [3] failed: ", GetLastError());
        else if (!ObjectSet( newName, OBJPROP_RAY, false ))             Alert(
            "ObjectSet(", newName, "Ray) [2] failed: ", GetLastError());

        ArrayResize(mem, maxBar+1); // Drop firstBar..(maxBar+1)
        if (!ObjectMove(name, 0, Time[maxBar+shift], mem[maxBar])){     Alert(
            "ObjectMove(",name,") [2] failed: ", GetLastError());       return;}
}   }

 
WHRoeder:
Try this:
Small modification to show initial line and handle vertical lines on initial bar
//+------------------------------------------------------------------+
//| EA equivalent of indicator buffers                               |
//+------------------------------------------------------------------+
/*  Example 1:
 *  if (...) Ordermodify(...);
 *  Polyline("SL"+(oo.ticket%99), oo.SL, Color.Dn, 0);
 *
 *  Example 2:
 *  double  ELineCurr = iMA(NULL,0, ELine.Period, 0, MODE_EMA, PRICE_CLOSE, 1);
 *  Polyline("ELine", ELineCurr, Color.ELine, 1);
 ******************************************************************************/
#define POLYLINE_MAX 20 // Must match priceXX
double  price00[], price01[], price02[], price03[], price04[],  // \   Export
        price05[], price06[], price07[], price08[], price09[],  //  \  from
        price10[], price11[], price12[], price13[], price14[],  //  |  Polyline
        price15[], price16[], price17[], price18[], price19[];  //  |
int     LRU[POLYLINE_MAX],  segNo[POLYLINE_MAX];                //   > Import to
string  lineName[POLYLINE_MAX];                                 // _/  PLHelper
datetime time0[POLYLINE_MAX];
void Polyline(string name, double price, color clr, int shift){
    if (!Show.Objects)  return;
    for (int idx=0; idx < POLYLINE_MAX; idx++){     LRU[idx]++; }
    for (idx=0; idx < POLYLINE_MAX; idx++){
        bool new = lineName[idx] != name;   if (!new) break;    }
    if (new){   idx=ArrayMaximum(LRU);  lineName[idx]=name; segNo[idx]=0;   }
    LRU[idx] = 0;   switch (idx){
    case  0: PLHelper(name, price, clr, idx, new, shift, price00); return;
    case  1: PLHelper(name, price, clr, idx, new, shift, price01); return;
    case  2: PLHelper(name, price, clr, idx, new, shift, price02); return;
    case  3: PLHelper(name, price, clr, idx, new, shift, price03); return;
    case  4: PLHelper(name, price, clr, idx, new, shift, price04); return;
    case  5: PLHelper(name, price, clr, idx, new, shift, price05); return;
    case  6: PLHelper(name, price, clr, idx, new, shift, price06); return;
    case  7: PLHelper(name, price, clr, idx, new, shift, price07); return;
    case  8: PLHelper(name, price, clr, idx, new, shift, price08); return;
    case  9: PLHelper(name, price, clr, idx, new, shift, price09); return;
    case 10: PLHelper(name, price, clr, idx, new, shift, price10); return;
    case 11: PLHelper(name, price, clr, idx, new, shift, price11); return;
    case 12: PLHelper(name, price, clr, idx, new, shift, price12); return;
    case 13: PLHelper(name, price, clr, idx, new, shift, price13); return;
    case 14: PLHelper(name, price, clr, idx, new, shift, price14); return;
    case 15: PLHelper(name, price, clr, idx, new, shift, price15); return;
    case 16: PLHelper(name, price, clr, idx, new, shift, price16); return;
    case 17: PLHelper(name, price, clr, idx, new, shift, price17); return;
    case 18: PLHelper(name, price, clr, idx, new, shift, price18); return;
    case 19: PLHelper(name, price, clr, idx, new, shift, price19); return;
}   }
void PLHelper( string name, double price, color clr, int idx, bool new
             , int shift, double& mem[] ){
    datetime    t0  = Time[shift];  int firstBar = ArraySize(mem);
    if (new){   t0 += 60*Period();      firstBar=0; }
    if (new || t0 != time0[idx]){
        ArraySetAsSeries(mem, true);        // Shift values m[2]=m[1]; m[1]=m[0]
        firstBar=ArrayResize(mem, firstBar+1)-1;    if (firstBar < 0){  Alert(
            "ArrayResize failed: ",GetLastError());                     return;}
        ArraySetAsSeries(mem, false);
        time0[idx]=Time[shift];  mem[0]=price;
    }
    else        firstBar--;     
    if (ObjectMove(name, 1, t0,                     price))
        ObjectMove(name, 0, Time[shift+firstBar],   mem[firstBar]);
    else if (!ObjectCreate( name, OBJ_TREND, WINDOW_MAIN
                          , t0,                     price
                          , Time[shift+firstBar],   mem[firstBar] )){   Alert(
        "ObjectCreate(", name, "Trend) [1] failed: ",GetLastError());   return;}
    else if (!ObjectSet( name, OBJPROP_COLOR, clr ))                    Alert(
        "ObjectSet(", name, "Color) [2] failed: ", GetLastError());
    else if (!ObjectSet( name, OBJPROP_RAY, false ))                    Alert(
        "ObjectSet(", name, "Ray) [1] failed: ", GetLastError());

    double maxError=0;  int maxBar;
    for (int pos=1; pos < firstBar; pos++){
        double error=MathAbs(ObjectGetValueByShift(name, pos+shift)-mem[pos]);
        if (error > maxError){  maxError=error; maxBar=pos; }
    }
    if (maxError >= pips2dbl){  // Split the line into two segments at the max.
        segNo[idx]=(segNo[idx]+1)%1000; string newName=name+"-"+segNo[idx];
        /**/ if (ObjectMove(newName, 0, Time[firstBar+shift], mem[firstBar]))
            ObjectMove(newName, 1, Time[maxBar  +shift], mem[maxBar]);
        else if (!ObjectCreate( newName, OBJ_TREND, WINDOW_MAIN,
            Time[firstBar+shift],   mem[firstBar],
            Time[maxBar  +shift],   mem[maxBar] ))                      Alert(
            "ObjectCreate(", newName, "Trend) [2] failed: ",GetLastError());
        else if (!ObjectSet( newName, OBJPROP_COLOR, clr ))             Alert(
            "ObjectSet(", newName, "Color) [3] failed: ", GetLastError());
        else if (!ObjectSet( newName, OBJPROP_RAY, false ))             Alert(
            "ObjectSet(", newName, "Ray) [2] failed: ", GetLastError());

        ArrayResize(mem, maxBar+1); // Drop firstBar..(maxBar+1)
        if (!ObjectMove(name, 0, Time[maxBar+shift], mem[maxBar]))      Alert(
            "ObjectMove(",name,") [2] failed: ", GetLastError());
    }   // Split the line into two segments at the max.
}   // PLHelper
 
New version, handles color changes and exports object name so caller can change other parameters, provide delete capability https://www.mql5.com/en/forum/130907
Reason: