Discussion de l'article "Appliquer un indicateur à un autre"

 

Un nouvel article Appliquer un indicateur à un autre a été publié :

Lors de l'écriture d'un indicateur qui utilise la forme abrégée de l'appel de fonction OnCalculate(), vous pourriez manquer le fait qu'un indicateur peut être calculé non seulement par les données de prix, mais également par les données d'un autre indicateur (qu'il s'agisse du type intégré ou personnalisé). Vous souhaitez améliorer un indicateur pour sa bonne application aux données de l'autre indicateur ? Dans cet article, nous passerons en revue toutes les étapes requises pour une telle modification.

Auteur : MetaQuotes

 

Merci pour ce nouvel article de qualité. Traditionnellement, les articles de la communauté MQL sont devenus un moyen pour moi d'obtenir une éducation post-secondaire (c'est-à-dire le guide de l'éditeur MQL intégré).

Sur ce point, j'ai remarqué une petite faille dans le code. Selon l'idée de l'auteur

//--- drapeau pour l'édition unique des valeurs price[]

variable

   bool printed=false;

devrait être déplacée en dehors de la fonction OnCalculate(), sinon l'impression du tableau se produira à chaque événement.

Il y a également une erreur ici

Правило передачи PLOT_DRAW_BEGIN в параметр begin: Значение входного параметра begin в OnCalculate(), при расчетах пользовательского индикатора A на данных другого (базового) индикатора B, всегда равно значению свойства PLOT_DRAW_BEGIN  нулевого графического построения базового индикатора B.

Ainsi, si nous avons créé un indicateur RSI (indicateur A) avec une période de 14 et que nous avons ensuite construit notre indicateur personnalisé True Strength Index (indicateur B) sur les données de l'indicateur RSI(14) :

D'après la règle et la logique, l'indicateur A est un TSI personnalisé et l'indicateur B (de base) est un RSI.

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 

Cet article contient les connaissances détaillées.

Nous vous remercions.

 

Bonjour,

Cet article est vraiment intéressant et ouvre de nouvelles possibilités de gestion des indicateurs.

Comme je suis débutant en MQL5, j'ai essayé d'implémenter la possibilité d'appliquer un indicateur à un autre. J'ai écrit un petit code qui ne fait que dupliquer

une moyenne mobile adaptative en espérant pouvoir l'utiliser sur n'importe quel indicateur du graphique.

Malheureusement, dans la liste des paramètres qui apparaît au lancement de l'indicateur, je n'ai pas le cas "apply to : previuos indicator's data".

Comment organiser le code pour avoir la possibilité de l'appliquer à un autre indicateur ?

Voici mon code :

#property indicator_separate_window
#property indicator_minimum             1.3
#property indicator_maximum             1.35
//#propriété indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   1
//--- tracer dMA
#property indicator_label1  "dAMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- paramètres d'entrée
input int      AMAPeriod=9;
input int      FastEMA=2;
input int      SlowEMA=20;
//--- tampons d'indicateurs
double         AMABuffer[];
double         dAMABuffer[];

int            h_dAMA;
int            h_AMA;
//+------------------------------------------------------------------+
//| Fonction d'initialisation de l'indicateur personnalisé
//+------------------------------------------------------------------+
int OnInit()
  {
//--- cartographie des tampons d'indicateurs
   SetIndexBuffer(0,dAMABuffer,INDICATOR_DATA);
   SetIndexBuffer(1,AMABuffer,INDICATOR_CALCULATIONS);
   
   
   
   //PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,MAPeriod+1) ;
   
   h_AMA=iAMA(_Symbol,PERIOD_CURRENT,AMAPeriod,FastEMA,SlowEMA,0,PRICE_CLOSE);
   if(h_AMA == INVALID_HANDLE)
    {
      Print("AMA indicator initialization error, Code = ", GetLastError());
      return(-1);
    }
   ArraySetAsSeries(AMABuffer,true);
   ArraySetAsSeries(dAMABuffer,true);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,MathMax(AMAPeriod,SlowEMA));
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Fonction d'itération de l'indicateur personnalisée|
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,    // taille du tableau de prix[]
                const int prev_calculated,// nombre de barres traitées lors de l'appel précédent
                const int begin,          // d'où partent les données significatives
                const double &price[]     // tableau pour le calcul
                )
  {
   
   if(BarsCalculated(h_AMA)<rates_total) return(0);
//--- nous ne pouvons pas copier toutes les données
   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<=0) 
     {
      to_copy=rates_total;
      if(CopyBuffer(h_AMA,0,0,to_copy,AMABuffer)<=0) return(0);
      for (int i=0;i<to_copy-MathMax(AMAPeriod,SlowEMA);i++)
          {
            dAMABuffer[i]=AMABuffer[i];
          }
     }
   else
     {
      to_copy=rates_total-prev_calculated+MathMax(AMAPeriod,SlowEMA)-1;
      //--- la dernière valeur est toujours copiée
      to_copy++;
      if(CopyBuffer(h_AMA,0,0,to_copy,AMABuffer)<=0) return(0); 
      for (int i=0;i<to_copy;i++)
         {
            dAMABuffer[i]=AMABuffer[i];
         }
     }
//--- essayer de copier
   
   Print(dAMABuffer[0]); //pour voir si nous allons jusqu'au bout
//--- valeur de retour de prev_calculated pour l'appel suivant
//---
//--- valeur de retour de prev_calculated pour l'appel suivant
   return(rates_total);
  }
//+------------------------------------------------------------------+
 

Bonjour,

J'ai compris le problème : vous ne pouvez appliquer un indicateur qu'à un autre qui se trouve dans la même fenêtre.

Avez-vous une idée sur la façon d'appliquer un indicateur (et de l'afficher dans une fenêtre séparée) à un autre qui est dans la fenêtre principale ?

Merci de votre compréhension.

Bests

 

Est-il possible de créer un indicateur de manière programmatique (via iCustom, par exemple) et de lui dire de prendre les données d'un autre indicateur en entrée ? Ou, mieux encore, de lui donner un tableau direct de données sur lesquelles il devrait être construit.

 
ds2:

Est-il possible de créer un indicateur de manière programmatique (via iCustom, par exemple) et de lui dire de prendre les données d'un autre indicateur en entrée ? Ou, mieux encore, de lui donner directement un tableau de données sur lequel il doit être construit.

Voir la fonction iCustom:

Si la première forme d'appel est utilisée dans l'indicateur, lorsque vous lancez un indicateur personnalisé dans l'onglet "Paramètres", vous pouvez spécifier en plus sur quelles données il sera calculé. Si le paramètre "Appliquer à" n'est pas sélectionné explicitement, le calcul est effectué par défaut sur les valeurs "Close".

Lors de l'appel d'un indicateur personnalisé à partir d'un programme mql5, le paramètre Applied_Price ou le handle d'un autre indicateur doit être passé en dernier après toutes les variables d'entrée fournies par l'indicateur personnalisé.

 

Bonjour,

C'est un très bon article mais j'ai quelques questions.

1. seuls les indicateurs qui utilisent la forme courte de l' appel de fonctionOnCalculate() peuvent être appliqués à un autre indicateur ou les indicateurs qui utilisent la forme longue de l'appel de fonctionOnCalculate() peuvent être appliqués aussi ? Si oui, comment peut-on appliquer un indicateur avec la forme longue de l' appel de la fonctionOnCalculate() à un autre indicateur ?

2. L'application d'un indicateur à un autre (TSI sur RSI) génère des problèmes d'affichage (voir l'image ci-jointe). Alors que le RSI est tracé de 0 à 100, le second indicateur (TSI) a des valeurs inférieures à 0 également, valeurs qui ne sont pas visibles sur le graphique. Quel est le problème et pourquoi le graphique ne s'ajuste pas correctement pour afficher correctement les deux indicateurs. Peut-on résoudre ce problème ou s'agit-il d'un bug de MetaTrader ?

Dossiers :
RSIcTSI.png  32 kb
 
Rosh:

J'ai décidé de construire un indicateur à partir d'un indicateur et je suis tombé sur une confusion.

Les deux indicateurs sont construits sur la base

int OnCalculate (const int rates_total,      Taille du tableau des prix[] // price[] array size
                 const int prev_calculated,  // barres traitées lors de l'appel précédent
                 const int begin,            // indice à partir duquel les données significatives commencent в массиве price[]
                 const double& price[]       // tableau pour le calcul
   );

En conséquence, l'utilisateur a la possibilité de définir le champ applied_price dans les paramètres.

Ma difficulté est de savoir comment passer le champ applied_price à l'indicateur interne (à partir duquel l'indicateur externe est construit) ?

La solution la plus simple est de faire une entrée et d'avertir l'utilisateur que l'entrée applied_price et le paramètre applied_price doivent être identiques, mais c'est un peu tordu.

 

Avez-vous regardé l'exemple de OnCalculate()?

Для получения значений пользовательского индикатора из других mql5-программ используется функция iCustom(), возвращающая хэндл индикатора для последующих операций. При этом также можно указать необходимый массив  price[] или хэндл другого индикатора. Этот параметр должен передаваться последним в списке  входных переменных пользовательского индикатора.
 
Пример:

void OnStart()
  {
//---
   string terminal_path=StatusInfoString(STATUS_TERMINAL_PATH);
   int handle_customMA=iCustom(Symbol(),PERIOD_CURRENT, "Custom Moving Average",13,0, MODE_EMA,PRICE_TYPICAL);
   if(handle_customMA>0)
      Print("handle_customMA = ",handle_customMA);
   else
      Print("Cannot open or not EX5 file '"+terminal_path+"\\MQL5\\Indicators\\"+"Custom Moving Average.ex5'");
  }

Dans cet exemple, le dernier paramètre transmis est la valeur PRICE_TYPICAL (de l'énumération ENUM_APPLIED_PRICE ), qui indique que l'indicateur personnalisé sera construit par les prix typiques obtenus comme (High+Low+Close)/3. Si le paramètre n'est pas spécifié, l'indicateur est construit par les valeurs PRICE_CLOSE, c'est-à-dire par les prix de clôture de chaque barre.

 
Rosh:

Avez-vous regardé l'exemple de OnCalculate()?


Oui, je l'ai fait,

int handle_customMA=iCustom(Symbol(),PERIOD_CURRENT, "Custom Moving Average",13,0, MODE_EMA,PRICE_TYPICAL);

applied_price est spécifié explicitement lorsque iCustom est appelé, mais dans l'indicateur à partir duquel iCustom est appelé, où l'obtenir ?

Parce que l'utilisateur le définit dans les paramètres, pas dans les entrées.

int OnInit()
  {
//--- cartographie des tampons d'indicateurs
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   hndl=iCustom(_Symbol,_Period,"MyInd",param_ind,???? вот тут нужно указать аплиед_прайс который будет задавать пользователь);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Fonction d'itération de l'indicateur personnalisée
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
 //...
 return(rates_total);
}

PS l'astuce est que l'utilisateur ayant une fois défini le paramètre applied_price et n'en ayant plus rien à faire, cette valeur a traversé toute la pyramide d'appels.