It was described on this part of the article:
The checks a trading robot must pass before publication in the Market - Calling custom indicators with iCustom()

- www.mql5.com
More -
Plactical example:
Forum on trading, automated trading systems and testing trading strategies
Vladimir Karputov, 2021.08.28 19:56
Custom Moving Average as a resource
Code: Custom Moving Average as a resource.mq5
It is often asked: "If an Expert Advisor uses a custom indicator, how should you write the Expert Advisor code correctly to make the Expert Advisor work on the MQL5 VPS"?
The answer is this: the indicator must be created as a resource. See example below:
Please note: I moved the 'Custom Moving Average' indicator to the root folder 'Indicators'
//+------------------------------------------------------------------+ //| Custom Moving Average as a resource.mq5 | //| Copyright © 2021, Vladimir Karputov | //+------------------------------------------------------------------+ #property copyright "Copyright © 2021, Vladimir Karputov" #property version "1.000" #property description "An example of using the MQL5 VPS: the Expert Advisor uses the 'Custom Moving Average' indicator as a resource" #resource "\\Indicators\\Custom Moving Average.ex5" //--- input parameters input int InpMAPeriod = 13; // Period input int InpMAShift = 0; // Shift input ENUM_MA_METHOD InpMAMethod = MODE_SMMA; // Method input bool InpPrintLog = true; // Print log //--- int handle_iCustom; // variable for storing the handle of the iCustom indicator datetime m_prev_bars = 0; // "0" -> D'1970.01.01 00:00'; bool m_init_error = false; // error on InInit //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create timer EventSetTimer(60); //--- create handle of the indicator iCustom handle_iCustom=iCustom(Symbol(),Period(),"::Indicators\\Custom Moving Average.ex5"); //--- if the handle is not created if(handle_iCustom==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", Symbol(), EnumToString(Period()), GetLastError()); //--- the indicator is stopped early m_init_error=true; return(INIT_SUCCEEDED); } Print(__FUNCTION__); //--- double array_ma[]; ArraySetAsSeries(array_ma,true); int start_pos=0,count=3; if(iGetArray(handle_iCustom,0,start_pos,count,array_ma)) { Print("---"); Print(TimeToString(m_prev_bars,TIME_DATE|TIME_MINUTES)); string text=""; for(int i=0; i<count; i++) text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n"; //--- Print(text); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- destroy timer EventKillTimer(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- if(m_init_error) return; //--- we work only at the time of the birth of new bar datetime time_0=iTime(Symbol(),Period(),0); if(time_0==m_prev_bars) return; m_prev_bars=time_0; //--- double array_ma[]; ArraySetAsSeries(array_ma,true); int start_pos=0,count=3; if(!iGetArray(handle_iCustom,0,start_pos,count,array_ma)) { m_prev_bars=0; return; } Print("---"); Print(__FUNCTION__); Print(TimeToString(m_prev_bars,TIME_DATE|TIME_MINUTES)); string text=""; for(int i=0; i<count; i++) text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n"; Print(text); //--- } //+------------------------------------------------------------------+ //| Get value of buffers | //+------------------------------------------------------------------+ bool iGetArray(const int handle,const int buffer,const int start_pos, const int count,double &arr_buffer[]) { bool result=true; if(!ArrayIsDynamic(arr_buffer)) { if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__); return(false); } ArrayFree(arr_buffer); //--- reset error code ResetLastError(); //--- fill a part of the iBands array with values from the indicator buffer int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer); if(copied!=count) { //--- if the copying fails, tell the error code if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d", __FILE__,__FUNCTION__,count,copied,GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } return(result); } //+------------------------------------------------------------------+
I have compiled an indicator and an advisor. The EA attached it to the chart and carried out the migration. The result of working at the MQL5 VPS:
As you can see, everything works great!
I tested and it worked like charm! It allows my EA to run on any other terminal without installing the Indicator.
//+------------------------------------------------------------------+ //| DHT Trader.mq4 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #resource "\\Indicators\\BFS\\DHT.ex4" #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property strict //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { double up = iCustom(_Symbol,_Period,"::Indicators\\BFS\\DHT.ex4",6,0,0); Comment(DoubleToString(up,_Digits)); } //+------------------------------------------------------------------+
I learn that if the indicator keep calculating from the first bar on the chart, the EA will got stuck and timeout. The indicator must have proper handling with the rates_total and prev_calculated.
int limit = MathMin(rates_total -1, rates_total - prev_calculated); //Main loop for(int i=limit; i>=0; i--) { //Code here }

- 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 Respectful Friends,
If my EA use signal and confirmation form custom indicator , Can it be listed on Market? I am worry that it would fail the auto validation.
Thanks.