Displaying indicator created within EA (iCustom) on chart...

 

Hello All,

As an example, I'd like to display an indicator created by an EA on the parent chart. I can do this using the below code, I worked this out with a little help from Google and on line help, so you'll probably recognise the code (ish). Here is my open code:

/* open_indicator()
 *
 * Initialise the super_signal indicator handle.
 *
 * Params: Void
 *
 * Returns: positive integer on success
 *          INVALID_HANDLE on failure
 */
int ig_cb_indicator::open_indicator()
{
   m_handle = iCustom(m_symbol, m_period,
      m_path,  /* Path to the indicator */
      m_csv,   /* Block times expressed as a csv hours:mins-hours:mins like 00:00-03:59,16:45-17:30 */
      m_debug);/* Whether to dump info about the indicator to the log */
   printf("%s[%d], %s: channel_breakout handle[%d] open%s",
      __FILE__, __LINE__, __FUNCTION__,
      m_handle, m_handle == INVALID_HANDLE ? " failed" : "ed");
   if ( m_handle != INVALID_HANDLE && m_show_indicator ) {
      /* Fetch the number of a new subwindow, to which we will try to add the indicator */
      /* now make an attempt to add the indicator to the main window & check for error  */
      if ( ! ChartIndicatorAdd(0, 0, m_handle) ) {
         PrintFormat("%s[%d], %s: Failed to add indicator %s to chart window[%d]. Error code[%d]", 
            __FILE__, __LINE__, __FUNCTION__, m_path, m_subwindow, GetLastError()); 
         return m_handle;
      }
      
      long chart_id = ChartID(); 
      int  wnd_total= (int)ChartGetInteger(0, CHART_WINDOWS_TOTAL); 
      for( int w = 0; w < wnd_total ; w++ ) { 
         int ind_total=ChartIndicatorsTotal(chart_id, w); 
         PrintFormat("%s[%d], %s: Chart window %d indicators: ", __FILE__, __LINE__, __FUNCTION__, w); 
         for( int i = 0; i < ind_total ; i++ )
            printf("%s[%d], %s:  Found indicator %s",
               __FILE__, __LINE__, __FUNCTION__, ChartIndicatorName(chart_id, w, i));
      }
      m_added_to_chart = true;
   }
   return m_handle;
}

I'd also like to remove the indicator (which has a semi-dynamic short name), the short name always commences with a seed string. Here is my destructor code:

ig_cb_indicator::~ig_cb_indicator()
{
   int w = 0, i = 0;
   string full_name, short_stem;
   bool found_ind = false;

   if ( m_show_indicator && m_added_to_chart && m_short_name_stem.Length() > 0 ) {
      long chart_id = ChartID();
      int  wnd_total= (int)ChartGetInteger(0, CHART_WINDOWS_TOTAL); 
      for( w = 0; w < wnd_total ; w++ ) { 
         int ind_total=ChartIndicatorsTotal(chart_id, w); 
         for( i = 0; i < ind_total ; i++ ) {
            full_name = ChartIndicatorName(chart_id, w, i);
            short_stem = StringSubstr(full_name, 0, m_short_name_stem.Length());
            if ( m_short_name_stem.Find(short_stem, 0) == 0 ) {
               found_ind = true;
               printf("%s[%d], %s:  Found indicator %s[%d] for stem %s[%d]",
                  __FILE__, __LINE__, __FUNCTION__, full_name, full_name.Length(), m_short_name_stem, m_short_name_stem.Length());
               break;
            }         }
         if ( found_ind )
            break;
      }
   }

   if ( m_handle != INVALID_HANDLE ) {
      if ( IndicatorRelease(m_handle) )
         printf("%s[%d], %s: channel breakout indicator done!", __FILE__, __LINE__, __FUNCTION__);
      else
         printf("%s[%d], %s: Can't delete %s, error code %d",
            __FILE__, __LINE__, __FUNCTION__, m_name, GetLastError());
   }
   if ( found_ind ) {
      if ( ChartIndicatorDelete(w, i, full_name) ) {
         printf("%s[%d], %s: Deleted %s from main chart!", __FILE__, __LINE__, __FUNCTION__, full_name);
      } else
         printf("%s[%d], %s: Failed to delete indicator %s chart #%d from window #%d. Error code %d",
            __FILE__, __LINE__, __FUNCTION__, full_name, w, i, GetLastError());
   }
}

Here is what I get in the 'Experts' tab log:

2024.10.21 10:48:24.608 ea_inputs.mq5[533]: OnDeinit, deleting channel_breakout object
2024.10.21 10:48:24.694 indicator_channel_breakout.mqh[162], ig_cb_indicator::~ig_cb_indicator:  Found indicator Channel-breakout 00:00-03:59,16:45-17:30[40] for stem Channel-breakout[16]
2024.10.21 10:48:24.694 indicator_channel_breakout.mqh[172], ig_cb_indicator::~ig_cb_indicator: channel breakout indicator done!
2024.10.21 10:48:24.694 indicator_channel_breakout.mqh[182], ig_cb_indicator::~ig_cb_indicator: Failed to delete indicator Channel-breakout 00:00-03:59,16:45-17:30 chart #0 from window #1. Error code 4115

I thought this might be to do with my order of deletion, but I have tried a ChartIndicatorDelete() both before & after IndicatorRelease() with the same dreaded 4115.

If you can have a look I will be very grateful; I'll be even more excited if you can spot what I am doing wrong.

Thanks for looking!

With my best regards, ESB.

 
Earthy Stag beetle:
IndicatorRelease(m_handle)

I'd suggest to call IndicatorRelease(m_handle) right after you did ChartIndicatorAdd, because from now on it's the chart who locks the indicator, and you don't need to keep your own reference. m_handle will still be valid unless a user removes the indicator manually.

The call to IndicatorRelease(m_handle) is processed in a postponded way, so when you call ChartIndicatorDelete right after IndicatorRelease, the indicator is most likely not yet released.

 
Stanislav Korotky #:

I'd suggest to call IndicatorRelease(m_handle) right after you did ChartIndicatorAdd, because from now on it's the chart who locks the indicator, and you don't need to keep your own reference. m_handle will still be valid unless a user removes the indicator manually.

The call to IndicatorRelease(m_handle) is processed in a postponded way, so when you call ChartIndicatorDelete right after IndicatorRelease, the indicator is most likely not yet released.

You learn something new every day! I didn't know or think of that.

Thank you very much!

It was an experiment really, with what you have told me I am not sure I trust the user enough to give him the ability to destory the indicator whilst the EA is still running, so maybe I'll rollback and leave it as is.

It was interesting!

With my best regards, ESB.