Page 1 sur 1

Re: Sublime indicateur Prorealtime qu'il faudrait coder en mt4

Publié : 09 juin 2010, 00:10
par Tyrese
Salut à tous,

Je viens de voir sur un forum, un indic qui à l'air super, mais je ne peux le tester car il est sous Prorealtime, je voudrais savoir si quelqu'un pourrais m'aider à le coder en mq4,

Merci par avance,

Code :
// Magic Trend modifié et adapté pour Prorealtime
// par http://www.o-bo.com

if (CCI[50](typicalPrice)>=0) then
magic=Low[0]-AverageTrueRange[5](close)
endif

if (CCI[50](typicalPrice)<0) then
magic=High[0]+AverageTrueRange[5](close)
endif

if (CCI[50](typicalPrice)>=0 and magic<magic[1]) then
magic=magic[1]
endif

if (CCI[50](typicalPrice)<0 and magic>magic[1]) then
magic=magic[1]
endif

return magic


Voilà,

Merci pour vos feedback,

Apparement c'est ca :

//+------------------------------------------------------------------+
//| TrendMagic.mq4 |
//| Tidied up by TudorGirl 28 May 2009 |
//| [email protected] |
//+------------------------------------------------------------------+

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_width1 2
#property indicator_color2 Red
#property indicator_width2 2

//+------------------------------------------------------------------+

extern int CCI = 50;
extern int ATR = 5;

//+------------------------------------------------------------------+

double bufferUp[];
double bufferDn[];

//+------------------------------------------------------------------+

int init()
{
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
SetIndexBuffer(0, bufferUp);
SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
SetIndexBuffer(1, bufferDn);
return (0);
}

//+------------------------------------------------------------------+

int deinit()
{
return (0);
}

//+------------------------------------------------------------------+

int start()
{
double thisCCI;
double lastCCI;

int counted_bars = IndicatorCounted();
if (counted_bars < 0) return (-1);
if (counted_bars > 0) counted_bars--;
int limit = Bars - counted_bars;

for (int shift = limit; shift >= 0; shift--)
{
thisCCI = iCCI(NULL, 0, CCI, PRICE_TYPICAL, shift);
lastCCI = iCCI(NULL, 0, CCI, PRICE_TYPICAL, shift + 1);

if (thisCCI >= 0 && lastCCI < 0) bufferUp[shift + 1] = bufferDn[shift + 1];
if (thisCCI <= 0 && lastCCI > 0) bufferDn[shift + 1] = bufferUp[shift + 1];

if (thisCCI >= 0)
{
bufferUp[shift] = Low[shift] - iATR(NULL, 0, ATR, shift);
if (bufferUp[shift] < bufferUp[shift + 1])
bufferUp[shift] = bufferUp[shift + 1];
}
else
{
if (thisCCI <= 0)
{
bufferDn[shift] = High[shift] + iATR(NULL, 0, ATR, shift);
if (bufferDn[shift] > bufferDn[shift + 1])
bufferDn[shift] = bufferDn[shift + 1];
}
}
}

return (0);
}

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
Comment en faire un indic?

Merci


Peace,

Re: Sublime indicateur Prorealtime qu'il faudrait coder en mt4

Publié : 09 juin 2010, 12:45
par Fabien Labrousse
Salut Tyrese,

J'ai déplacé ton sujet car il n'était pas dans le forum approprié.

Pour ma part je t'avoue que je ne suis pas un pro de la programmation, j'essayerai de m'y pencher mais je suis un peu déborder en ce moment donc je ne peu te garantir aucun délai désolé.

En quoi consiste ton indicateur exactement?

Re: Sublime indicateur Prorealtime qu'il faudrait coder en mt4

Publié : 10 juin 2010, 23:40
par Fabien Labrousse
Mais il voulait le convertir dans un autre langage de programmation je croix non?

Re: Sublime indicateur Prorealtime qu'il faudrait coder en mt4

Publié : 11 juin 2010, 00:12
par madjes
ben il s'est pas rendu compte qu'il avait devant lui le code PRT et le code mql4. Et il le voulait en mql4 :wink:

Retour sur le Trend Magic, seize ans après — le code est correct, mais il y a deux subtilités

Publié : 04 mars 2025, 12:42
par xvilain
Ce fil est resté sans conclusion technique, et madjes avait raison au message #4 : Tyrese avait effectivement les deux versions sous les yeux. Comme cet indicateur circule toujours et qu'il illustre bien un piège classique de conversion entre plateformes, ça vaut la peine de le décortiquer.

1. Ce que fait réellement cet indicateur

Le principe est astucieux et tient en trois lignes.
  • Un CCI 50 sur le prix typique sert uniquement de filtre de régime : positif, on est en mode haussier ; négatif, en mode baissier.
  • En mode haussier, on trace une ligne sous le marché, à un ATR(5) sous le plus bas de la bougie. En mode baissier, une ligne au-dessus, à un ATR(5) au-dessus du plus haut.
  • Et surtout : cette ligne ne peut jamais reculer. En mode haussier elle ne descend pas, en mode baissier elle ne monte pas.
C'est donc un stop suiveur adaptatif à la volatilité, piloté par un filtre de tendance. La famille est la même que le Parabolic SAR ou le SuperTrend, avec deux différences : le déclencheur de retournement est un oscillateur plutôt que le prix lui-même, et l'écartement est proportionnel à l'ATR, donc il s'élargit quand le marché s'agite et se resserre quand il se calme.

C'est ce qui explique l'enthousiasme du message #1 : visuellement, une ligne qui suit proprement la tendance et qui bascule de l'autre côté aux retournements, ça a l'air magique. D'où le nom.

2. Les deux codes ne font pas exactement la même chose

C'est le point intéressant, et personne ne l'a relevé à l'époque.

Le code ProRealTime utilise un seul tampon (la variable magic), qui change simplement de côté du prix selon le signe du CCI. Le code MQL4 en utilise deux, bufferUp et bufferDn, plus deux lignes de raccordement :

Code : Tout sélectionner

if (thisCCI >= 0 && lastCCI < 0) bufferUp[shift + 1] = bufferDn[shift + 1];
if (thisCCI <= 0 && lastCCI > 0) bufferDn[shift + 1] = bufferUp[shift + 1];
Ces deux lignes servent uniquement à l'esthétique : au moment du basculement, elles recopient la dernière valeur de l'ancien tampon dans le nouveau, pour que la ligne bleue et la ligne rouge se rejoignent au lieu de laisser un trou. C'est de la cosmétique de tracé, pas de la logique.

En revanche, il y a une vraie divergence fonctionnelle. Regardez la condition de réinitialisation. En PRT :

Code : Tout sélectionner

if (CCI[50](typicalPrice)>=0 and magic<magic[1]) then
   magic=magic[1]
endif
La variable magic est unique. Quand le CCI repasse positif après une phase baissière, magic[1] contient la valeur baissière de la bougie précédente, située au-dessus du prix. La contrainte "ne pas descendre" s'applique donc à partir d'un niveau haut, et la ligne met plusieurs bougies à redescendre coller au marché.

En MQL4, bufferUp[shift+1] contient la dernière valeur haussière connue, qui peut dater de très longtemps. Le comportement au retournement diffère donc, parfois de façon visible.

Conséquence pratique : si vous comparez les deux versions sur le même graphique, ne vous étonnez pas de voir les lignes diverger juste après chaque basculement. Aucun des deux codes n'est faux — ils n'implémentent simplement pas la même règle de reprise.

3. Le vrai bug du code MQL4, qui est resté dans toutes les copies

Celui-là mérite d'être signalé, parce que le code circule encore.

Les tampons ne sont jamais réinitialisés à EMPTY_VALUE. Résultat : quand le marché est en mode haussier, bufferDn conserve sa dernière valeur au lieu d'être vide, et le tracé garde une ligne rouge horizontale fantôme sur toute la période. Beaucoup d'utilisateurs l'ont interprétée comme un "niveau de résistance mémorisé" alors que c'est un artefact.

La correction tient en trois lignes, à l'intérieur de la boucle :

Code : Tout sélectionner

if (thisCCI >= 0)
  {
   bufferUp[shift] = Low[shift] - iATR(NULL, 0, ATR, shift);
   if (bufferUp[shift] < bufferUp[shift + 1] && bufferUp[shift + 1] != EMPTY_VALUE)
      bufferUp[shift] = bufferUp[shift + 1];
   bufferDn[shift] = EMPTY_VALUE;          // <-- ligne manquante
  }
else
  {
   bufferDn[shift] = High[shift] + iATR(NULL, 0, ATR, shift);
   if (bufferDn[shift] > bufferDn[shift + 1] && bufferDn[shift + 1] != EMPTY_VALUE)
      bufferDn[shift] = bufferDn[shift + 1];
   bufferUp[shift] = EMPTY_VALUE;          // <-- ligne manquante
  }
À compléter dans init() par :

Code : Tout sélectionner

SetIndexEmptyValue(0, EMPTY_VALUE);
SetIndexEmptyValue(1, EMPTY_VALUE);
Un mot aussi sur la structure d'origine : la variable externe s'appelle CCI et la fonction native s'appelle iCCI. Ça compile, mais nommer une variable comme un concept du langage est une mauvaise habitude qui produit des erreurs difficiles à repérer dès que le code grossit. Préférez CCIPeriod et ATRPeriod.

4. Ce que cet indicateur peut et ne peut pas faire

Puisque le message #2 demandait en quoi il consiste, autant conclure sur l'usage.

Ce pour quoi il est bon :
  • Un stop suiveur objectif et adaptatif. C'est son vrai métier, et il le fait bien. Placer son stop sur la ligne dans le sens de la position est un usage parfaitement défendable.
  • Un filtre de régime binaire pour un système plus large : on ne prend que les achats quand la ligne est sous le prix.
  • Une lecture visuelle propre de la structure de tendance.
Ce pour quoi il n'est pas bon :
  • Comme signal d'entrée autonome. Il est entièrement construit sur des données passées et il n'anticipe rien. En marché sans direction, le CCI 50 oscille autour de zéro et la ligne bascule sans arrêt : c'est le hachoir garanti.
  • Comme "indicateur sublime". Aucun indicateur dérivé du prix n'ajoute d'information au prix — il la réorganise. Sa valeur vient de la discipline qu'il impose, pas d'une capacité prédictive.
Et le test qui tranche, valable pour n'importe quel indicateur qu'on découvre : ne demandez pas s'il "a l'air bon" sur le graphique, où tout paraît évident a posteriori. Faites-le tourner sur trois cents signaux, mesurez l'espérance par trade en multiples de R et le drawdown, et comparez à une règle mécanique bête — par exemple un stop suiveur à 2 ATR sans aucun filtre. Si l'indicateur ne bat pas cette référence, il ne sert qu'à rendre le graphique plus joli.

5. Deux remarques de contexte, seize ans après
  • MetaQuotes ne délivre plus de nouvelles licences MT4 et l'écosystème est passé à MT5. Ce code est en MQL4 ; en MQL5, la structure diffère sensiblement — OnCalculate au lieu de start, handles d'indicateurs à créer dans OnInit, tampons indexés dans l'autre sens par défaut. Si vous reprenez ce projet aujourd'hui, autant le réécrire directement pour MT5.
  • Sur la conversion PRT vers MQL en général : les deux pièges récurrents sont le sens d'indexation des barres (l'indice 0 est la bougie courante dans les deux, mais la logique de boucle diffère) et la définition exacte des indicateurs natifs. Le prix typique, le mode de lissage de l'ATR ou la constante du CCI ne sont pas toujours identiques d'une plateforme à l'autre. Avant de conclure qu'une conversion est ratée, comparez d'abord les valeurs brutes des indicateurs sous-jacents sur quelques bougies — c'est là que se cache la différence neuf fois sur dix.
Si quelqu'un veut la version MQL5 corrigée, je peux la poster : c'est une trentaine de lignes et ça fera un bon exercice de comparaison pour ceux qui migrent.