L'Histogramme des prix (Profile du Marché) et son implémentation en MQL5
"Market Profile essaie de fournir cette logique interne dans le contexte du marché.
C'est une méthode d'analyse qui part du principe que le prix seul
ne communique pas d'informations à l’intervenant, tout comme les mots sans syntaxe
ou le contexte peut ne pas avoir de sens Le volume fait partie intégrante de l'expression directe
du marché - comprenez-le et vous comprenez le langage du marché."
Robin Mesh
Introduction
A il y a longtemps, en parcourant un abonnement proposé par des revues, j'ai trouvé un article "Profile du Marché et compréhension du langage du marché" (octobre 2002) dans le journal russe "Valutny Spekulant" (à l'heure actuelle, il s'appelait "Active Trader"). L'article original a été publié dans "Nouvelle Pensée en Analyse Technique : Modèles trading des maîtres".
Le Market Profile a été élaboré par le brillantissime penseur Peter Steidlmayer. Il a trouvé l'expression naturelle du marché (le volume) et l'a organisé de manière lisible (la courbe en cloche), afin que les informations objectives générées par le marché soient accessibles aux intervenants dans le marché. Steidlmayer a suggéré de utiliser la représentation alternative de l'information sur les mouvements " horizontaux" et "verticaux" du marché qui conduisent à un ensemble complètement différent de modèles. Il a supposé qu'il existe une impulsion sous-jacente du marché ou un modèle fondamental appelé cycle d'équilibre et de déséquilibre.
Le Profil de Marché mesure le mouvement horizontal du marché à travers le mouvement vertical. Appelons cela "équilibre" à travers "déséquilibre". Cette relation est le principe organisateur fondamental du marché. Le style de trading d'un trader peut basculer en fonction de la partie du cycle d'équilibre/déséquilibre dans laquelle se trouve le marché. Le Profile du Marché peut déterminer à la fois quand le marché va passer de l'équilibre au déséquilibre et quelle sera l'ampleur du mouvement.
Les deux concepts de base de Market Profile sont :
- Le marché est une enchère, et il évolue dans le sens de la fourchette de prix où l'offre et la demande sont plus ou moins égales.
- Le marché comporte deux phases : l'activité horizontale et l'activité verticale. Le marché se déplace verticalement lorsque l'offre et la demande ne sont pas égales ou en déséquilibre, et horizontalement lorsqu'elles sont en équilibre ou équitables
Le marché d'équilibre illustré à l'aide du Profil de Marché dans le graphique ci-dessous a tendance à former une courbe en forme de cloche presque parfaite, tournée de 90 degrés en raison de l'orientation du graphique :
Fig 1. Le Profil du Marché du marché d'équilibre
Le marché à tendance hors d’équilibré forme également une courbe en cloche, mais son centre est décalé vers le haut ou vers le bas. D'autres configurations qui forment deux pics de cloches, en fonction de l'évolution des prix et de la confiance des acteurs du marché, sont possibles.
Fig 2. Le Profile du Marché du marché de déséquilibre (tendance)
L'utilisation des formes de profil quotidien pour déterminer le degré d'équilibre/de déséquilibre du marché peut être utile, car elle vous offre un point de départ pour comprendre les mouvements entre les différents intervenants du marché.
Une opportunité de trading avec le plus grand bénéfice apparaît lorsque le passage de l'équilibre au déséquilibre est sur le point de se produire. De plus, si vous pouvez identifier cette opportunité de trading et estimer avec exactitude l'ampleur potentielle de ce changement, vous pouvez alors estimer la qualité de ce trade et le temps qui lui est nécessaire.
Vous pouvez trouver l'exemple de méthodologie de travail avec cet outil disponible sur http://www.enthios.com/, où un groupe de traders a étudié l'Histogramme des Prix depuis 1998. Vous y trouverez également la stratégie Enthios Universal et un exemple de son utilisation.
1. Histogramme des Prix
L'histogramme des Prix est un outil très fiable. C'est un peu intuitif mais extrêmement efficace. L'histogramme des prix vous indique simplement les points de trading "les plus pratiques" du marché. C'est un indicateur avancé aa, car il indique les points où le marché peut changer de direction à l'avance. Les indicateurs tels que les moyennes mobiles ou les oscillateurs ne peuvent pas indiquer les points exacts de résistance et de soutien, ils ne peuvent qu’indiquer si le marché est suracheté ou surestimé.
D’habitude, l'Histogramme des Prix (ou Profil du Marché) est appliqué à 30 min. des grilles de prix pour étudier l'activité du marché pendant une journée. Je préfère utiliser le 5 min. graphiques pour les marchés boursiers et 15-30 min. graphiques pour le FOREX.
2. Point de contrôle
Dans la figure ci-dessus, vous pouvez constater le niveau auquel le marché a été tradé pendant la durée maximale ; il est délimité par la ligne la plus longue de l'histogramme. C'est ce qu'on appelle le point de contrôle, ou POC. Parfois, comme on le constate sur la figure, l'histogramme a deux sommets, l'un d'eux est légèrement plus bas. Dans un tel cas, nous voyons que l'indicateur n’indique qu'un seul POC, mais en fait il y en a deux, et il devrait être pris en compte.
De plus, le niveau de pourcentage de la plage dans l'histogramme crée également des niveaux supplémentaires, appelés niveaux POC secondaires :
Fig 3. Points de contrôle
Qu’indique POC ? Le prix dont se rappelle la plupart des traders Plus le marché est tradé à ce prix, plus le marché s'en rappelle
Psychologiquement, POC agit comme un centre d'attraction.
Le graphique suivant indique ce qui s'est passé quelques jours plus tôt. C'est une bonne démonstration de la puissance de l'Histogramme des Prix.
Fig 4. Le point de contrôle n'est pas absolu ; il indique l’étendue du trade
Le point de contrôle n'est pas absolu ; il indique l’étendue du trading Ainsi, le trader doit être prêt à agir lorsque le marché approche du POC. Il permet d'optimiser les commandes, en utilisant les observations historiques.
Examinons la figure 4. Le POC du 29.12.2009 se situe au prix 68,87. Il est clair, même sans l'histogramme et la ligne POC, que le marché était dans la fourchette 68,82 ~ 68,96 presque toute la journée. Le marché a clôturé en fin de journée à 5 points en dessous du POC. Le lendemain, cela a provoqué l'ouverture du marché avec un écart en baisse.
Il est important de comprendre que nous ne pouvons pas prévoir si le marché va monter ou descendre. On ne peut que supposer que le marché reviendra à la ligne POC et à l'accumulation maximale des lignes de l’histogramme. Mais que se passera-t-il lorsque le prix touche le POC ? La même chose qui arrive avec un objet élastique qui tombe au sol, il va se retourner. Si cela se produit rapidement, comme un retour de balle de tennis avec une raquette, le prix reviendra très rapidement au niveau initial.
Après l'ouverture du marché le 30.12.2009, nous constatons qu'il s'agissait d'un écart, puis le marché a touché le POC de la veille, puis est rapidement revenu au prix d'ouverture et a mis à jour le minimum.
Notez que le POC n'est pas tout a fait exact (les traders expérimentés savent qu'il n'y a pas de niveaux de résistance clairs lorsque le prix atteint un maximum, un minimum ou une plage de concentration). Ce qui se passe à ce stade là dépend des acteurs du marché. Si la volonté collective (par exemple, la publication d’informations) coïncide, alors le marché passera par le POC, mais c'est rare et il peut être utilisé pour élaborer un système de trading
Faites attention que l’attitude du marché était la même au 31.12.2009. Lorsque le prix a touché POC, les acheteurs ont cédé aux vendeurs.
3. Point de Contrôle Vierge
Le Virgin POC (Point de Contrôle Vierge) est un niveau que le prix n'a pas atteint dans les prochains jours.
La logique est simple, comme décrit ci-dessus, le POC est un point d'attraction pour le marché. Au fur et à mesure que le prix s'éloigne du POC, la force d'attraction croît. Et plus le prix s'éloigne du Virgin POC, plus grande est la possibilité que lorsqu'il reviendra à ce niveau, un rebond se produira et probablement un renversement de prix se produira également.
Fig 5. Ancien et actuel Virgin POC
Sur la figure 5, les anciens POC Virgin qui étaient les niveaux de support et de résistance sont marqués par des cercles. Les POC vierges en activité sont marqués avec des valeurs de prix.
Une fois que le prix a touché le Virgin POC, il cesse d'être un "vierge". Psychologiquement, le marché ne le considère plus comme un niveau substantiel de support ou de résistance. Les traders peuvent toujours voir les niveaux de prix, qui ont initialement formé le POC, mais comme un simple cumul de prix.
4. Implémentation de l'Histogramme des Prix dans MQL5
Ma première version de Price Histogram est apparue en 2006, elle a été écrite en MQL4 dans MetaTrader4 pour un usage personnel. Au cours de l’élaboration de cet indicateur, j'étais confronté à quelques difficultés , en voici quelques-unes :
- nombre de barres très court dans l'histoire pour M5, sans parler de M1 ;
- la nécessité d’élaborer des fonctions spéciales pour travailler avec l'historique, telles que le retour d'un jour en tenant compte des jours fériés, la vérification de l'heure de clôture du marché le vendredi, la vérification de l'heure d'ouverture et de clôture du marché des CFD, etc.
- recalcul de l'indicateur lors des changements des délais et, par conséquent, des retards terminaux.
Par conséquent, lorsque les tests bêta de МetaТrader5 et MQL5 ont commencé, j'ai décidé de le convertir en MQL5.
Comme on dit, "la première crêpe est toujours un peu délicate", j'ai essayé de l’implémenter comme indicateur.
Commençons par le bon : la présence de la longue histoire de minute cotations pour tous les symboles, la possibilité d'obtenir des données historiques pour une certaine période de temps à n'importe quelle plage de temps.
Maintenant, je vais expliquer pourquoi il a pris fin Je n'ai pas pris en compte les caractéristiques des indicateurs MQL5 :
- la durée d'exécution de l'indicateur est cruciale ;
- les caractéristiques du travail de l'indicateur après la modification du calendrier.
L'exécution de la fonction OnCalculate(), qui correspond au gestionnaire d'événements Calculate, dispose d’ un temps d'exécution crucial En conséquence, le traitement de 260 jours (période annuelle) à l'aide de l'historique des barres des minutes prend beaucoup de temps, jusqu'à plusieurs minutes. Bien sûr, nous pouvons l’admettre, si les calculs effectués à la fois après l'indicateur attaché au graphique. Mais ce n'est pas le cas pour les modifications de calendrier. Lorsque l'indicateur passe à une autre période, l'ancienne copie de l'indicateur est détruite et la nouvelle est créée. C'est pourquoi après les changements de calendrier nous devons recalculer à nouveau les mêmes niveaux et cela prend beaucoup de temps.
Mais comme dit, si vous ne savez pas quoi faire - "Lire la documentation d'abord", dans notre cas, c'est la documentation de MQL5. La solution était très simple - Implémenter cet indicateur en tant qu'Expert Advisor qui ne trade pas.
Les avantages d'Expert Advisor sont :
- le temps de traitement n'est pas critique pour le gestionnaire d'événements Init dans OnTick ();
- la possibilité d'obtenir les paramètres du gestionnaire OnDeinit (const int raison).
Les Expert Advisors diffèrent des indicateurs suivants : après la modification de période, l'Expert Advisor génère simplement l'événement DeInit avec le paramètre de raison REASON_CHARTCHANGE, il ne décharge pas l'Expert Advisor de la mémoire et sert les valeurs des variables globales.. Il nous permet d'effectuer tous les calculs à la fois après l'attachement d'Expert Advisor, en modifiant ses paramètres et en faisant apparaître de nouvelles données, dans notre cas pour un nouveau jour de trading.
Présentons quelques définitions qui seront nécessaires plus tard.
La programmation orientée objet (POO) - est un style de programmation dont les concepts de base sont les concepts d'objets et de classes.
L'Objet est une entité dans l'espace virtuel, avec un état et une attitude spécifiés ; il dispose de quelques valeurs de propriétés (appelées attributs) et des opérations avec elles (appelées en tant que méthodes).
En POO, la classe est un type de données abstrait spécial, caractérisé par sa construction. La classe est un concept principal en POO. La classe est différente des autres types de données abstraits. La définition de données en classe contient également des méthodes de classe de son traitement de données (interface).
En programmation, il existe un concept d'interface logicielle qui englobe une liste de calculs possibles pouvant être effectués par une partie du programme, y compris des algorithmes, une description des arguments et l'ordre des paramètres d'entrée à effectuer et ses valeurs de retour. L'interface de type de données abstrait a été élaborée pour une description formalisée d'une telle liste. Les algorithmes eux-mêmes et le code qui effectueront tous ces calculs ne sont pas indiqués et appelés comme implémentation d'interface.
La création de classe est la création d'une structure avec des champs et des méthodes. La classe entière peut être considérée comme un modèle pour la création d'objets, qui sont des instances de classe. Les instances de classe sont créées à l'aide du même modèle, elles ont donc les mêmes champs et méthodes.
Commençons...
Le code source se trouve dans 4 fichiers. Le fichier principal est PriceHistogram.mq5, les autres fichiers sont : ClassExpert.mqh, ClassPriceHistogram.mqh et ClassProgressBar.mqh. Les fichiers avec l'extension .mqh contiennent la description et les méthodes des classes. Tous les fichiers doivent se trouver dans le même répertoire, Mon répertoire est : \MQL5\ Experts\PriceHistogram.
4.1. PriceHistogram.mq5
La première instruction dans le code source est :
#include "ClassExpert.mqh"
La directive du compilateur #include inclut le texte du fichier indiqué. Dans notre cas, il s'agit de la description de la classe CExpert (discutée ci-dessous).
Le suivant est un bloc de variables d'entrée qui sont des paramètres d'Expert Advisor.
// The block input parameters input int DayTheHistogram = 10; // Days for histogram input int DaysForCalculation= 500; // Days for calculation(-1 all) input uint RangePercent = 70; // Percent range input color InnerRange =Indigo; // Inner range input color OuterRange =Magenta; // Outer range input color ControlPoint =Orange; // Point of Control input bool ShowValue =true; // Show Values
Après cela, la variable ExtExpert (de type classe CExpert) est déclarée.
Le suivant est celui des gestionnaires d'événements standard qui se trouvent dans les programmes MQL5. Les gestionnaires d'événements appellent les méthodes correspondantes de la classe CExpert.
int OnInit() { //--- // We check for symbol synchronization before the start of calculations int err=0; while(!(bool)SeriesInfoInteger(Symbol(),0,SERIES_SYNCRONIZED) && err<AMOUNT_OF_ATTEMPTS) { Sleep(500); err++; } // CExpert class initialization ExtExpert.RangePercent=RangePercent; ExtExpert.InnerRange=InnerRange; ExtExpert.OuterRange=OuterRange; ExtExpert.ControlPoint=ControlPoint; ExtExpert.ShowValue=ShowValue; ExtExpert.DaysForCalculation=DaysForCalculation; ExtExpert.DayTheHistogram=DayTheHistogram; ExtExpert.Init(); return(0); }
Lorsque j'ai rédigé la première version de l'Expert Advisor et que je l'ai exécutée, j'ai du mal à comprendre pourquoi elle se termine avec une erreur après le redémarrage du terminal client ou un changement de symbole. Et cela se produit lorsque le terminal client a été déconnecté ou qu'un symbole n'a pas été utilisé depuis longtemps.
C'est bien que les développeurs aient ajouté le débogueur à MetaEditor5. Je me rappelle de beaucoup de commandes Print() et Comment(), utilisées pour vérifier les valeurs des variables dans MetaEditor4. Un grand merci aux développeurs de MetaEditor5.
Dans mon cas, tout était facile ; l'expert démarre avant la connexion au serveur et la mise à jour des données historiques. Pour résoudre ce problème, j'ai dû utiliser le SeriesInfoInteger(Symbol(),0,SERIES_SYNCRONIZED), qui signale que les données sont synchronisées ou non, et le cycle while (), le cas de l'absence de connexion, il utilise la variable de compteur err.
Une fois les données synchronisées, ou le cycle terminé à cause du compteur en l'absence de connexion, nous passons les paramètres d'entrée de notre classe experte CExpert, et appelons la méthode d'initialisation de classe Init().
Comme vous le constatez, grâce au concept de classes dans MQL5, notre fichier PriceHistogram.mq5 s'est transformé en un simple modèle, et tout le traitement ultérieur se fait dans la classe CExpert, déclarée dans le fichier ClassExpert.mqh.
4.2. ClassExpert.mqh
Examinons sa description.
//+------------------------------------------------------------------+ //| Class CExpert | //| Class description | //+------------------------------------------------------------------+ class CExpert { public: int DaysForCalculation; // Days to calculate (-1 for all) int DayTheHistogram; // Days for Histogram int RangePercent; // Percent range color InnerRange; // Internal range color color OuterRange; // Outer range color color ControlPoint; // Point of Control (POC) Color bool ShowValue; // Show value
La section publique est ouverte et accessible depuis les variables extérieures. Vous remarquerez que les noms des variables coïncident avec les noms de la section des paramètres d'entrée décrite dans PriceHistogram.mq5. Ce n'est pas nécessaire car les paramètres d'entrée sont globaux. Mais dans ce cas - est un hommage aux bonnes règles d'élevage, il est souhaitable d'éviter l’utilisation des variables externes au sein de la classe.
private: CList list_object; // The dynamic list of CObject class instances string name_symbol; // Symbol name int count_bars; // Number of daily bars bool event_on; // Flag of events processing
La section privée est clôturée de l'extérieur et est accessible uniquement à l'intérieur de la classe. Je voudrais décrire la variable list_object de type CList, qui est une classe de la bibliothèque MQL5 standard. La classe CList est une classe dynamique avec une liste d'instances de la classe CObject et de ses héritiers. J’ utiliserai cette liste pour le stockage des références pour les éléments de la classe CPriceHistogram, qui est un héritier de la classe CObject ; nous considérerons les détails ci-dessous. La description de la classe CList se trouve dans List.mqh, et elle est incluse à l'aide de la directive du compilateur #include <Arrays\List.mqh>.
public: // Class constructor CExpert(); // Class destructor ~CExpert(){Deinit(REASON_CHARTCLOSE);} // Initialization method bool Init(); // Deinitialization method void Deinit(const int reason); // Method of OnTick processing void OnTick(); // Method of OnChartEvent() event processing void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); // Method of OnTimer() event processing void OnTimer(); };
Ce qui suit est une section de méthodes publiques. Comme vous l'avez deviné, ces méthodes (fonctions) sont disponibles en dehors de la classe.
Et enfin, l'accolade avec un point-virgule complète la description de la classe.
Examinons les méthodes de classe en détail.
Le constructeur de classe est un bloc spécial d'instructions, appelé lors de la création de l'objet. Le constructeur est similaire à la méthode, mais diffère de la méthode du fait qu'il n'a pas explicitement un certain type de données renvoyées.
En langage MQL5, les constructeurs ne peuvent pas avoir le moindre paramètre d'entrée, et chaque classe ne doit avoir qu'un seul constructeur. Dans notre cas, le constructeur est une initialisation primaire de variables.
Le destructeur est une méthode de classe spéciale utilisée pour la désinitialisation de l'objet (par exemple, la mémoire libre). Dans notre cas, la méthode est appelée comme Deinit (REASON_CHARTCLOSE);
L'Init() est une méthode d'initialisation de classe. C'est la méthode la plus importante de la classe CExpert ; la création d'objets d'histogramme y a été effectuée. veuillez jeter un œil sur les commentaires pour les détails. Mais je voudrais considérer là des points.
Le premier, pour créer un Histogramme des Prix quotidien, nous avons besoin des données de temps d'ouverture des jours pour poursuivre Ici, je voudrais faire une digression et attirer votre attention sur les. caractéristiques du travail avec des séries chronologiques.. Pour la demande de données des autres périodes, nous avions besoin d'un temps, donc les fonctions Bars () et CopyTime (), ainsi que d'autres fonctions pour travailler avec des séries temporelles ne renvoient pas toujours les données souhaitées du premier appel.
J'ai donc dû mettre cette fonction dans la boucle do (...) while (), mais pour la rendre finie, j'ai utilisé la variable counter.
int err=0; do { // Calculate the number of days which available from the history count_bars=Bars(NULL,PERIOD_D1); if(DaysForCalculation+1<count_bars) count=DaysForCalculation+1; else count=count_bars; if(DaysForCalculation<=0) count=count_bars; rates_total=CopyTime(NULL,PERIOD_D1,0,count,day_time_open); Sleep(1); err++; } while(rates_total<=0 && err<AMOUNT_OF_ATTEMPTS); if(err>=AMOUNT_OF_ATTEMPTS) { Print("There is no accessible history PERIOD_D1"); name_symbol=NULL; return(false); }
Deuxièmement, l'historique minute de MetaTrader 5 est égal aux jours disponibles, donc cela peut prendre beaucoup de temps, il est donc nécessaire de visualiser le processus de calcul. La classe CProgressBar (#include "ClassProgressBar.mqh") a été élaboré à cet effet. Il crée la barre de progression dans la fenêtre du graphique et la met à jour pendant le processus de calcul.
// We create the progress bar on the char to shot the loading process CProgressBar *progress=new CProgressBar; progress.Create(0,"Loading",0,150,20); progress.Text("Calculation:"); progress.Maximum=rates_total;
Le troisième, en cycle, à l'aide de l'instruction "new", on crée l'objet CPriceHistogram, on le configure à l'aide de ses méthodes et on l'initialise en appelant le Init(). En cas de succès, nous l'ajoutons à la liste list_object, par contre nous supprimons hist_obj en utilisant l'instruction delete. La description de la classe CPriceHistogram sera présentée plus loin, voir les commentaires dans le code.
// In this cycle there is creation of object CPriceHistogram // its initialization and addition to the list of objects for(int i=0;i<rates_total;i++) { CPriceHistogram *hist_obj=new CPriceHistogram(); // hist_obj.StepHistigram(step); // We set the flag to show text labels hist_obj.ShowLevel(ShowValue); // We set POCs colour hist_obj.ColorPOCs(ControlPoint); // We set colour for inner range hist_obj.ColorInner(InnerRange); // We set colour for outer range hist_obj.ColorOuter(OuterRange); // We set the percent range hist_obj.RangePercent(RangePercent); // hist_obj.ShowSecondaryPOCs((i>=rates_total-DayTheHistogram),PeriodSeconds(PERIOD_D1)); if(hist_obj.Init(day_time_open[i],day_time_open[i]+PeriodSeconds(PERIOD_D1),(i>=rates_total-DayTheHistogram))) list_object.Add(hist_obj); else delete hist_obj; // Delete object if there was an error progress.Value(i); };
Le OnTick() est une méthode appelée lorsque vous recevez un nouveau tick pour un symbole. On compare les valeurs du nombre de jours stockées dans la variable count_bars avec le nombre de barres journalières retournées par Bars (Symbol(), PERIOD_D1) et si elles ne sont pas égales on appelle de force la méthode Init() pour l'initialisation de la classe, effaçant la liste list_object et en changeant la variable en NULL name_symbol . Si le nombre de jours n'a pas changé, la boucle parcourt tous les objets stockés dans la classe CPriceHistogram list_object, et exécute une méthode Redraw(), pour ceux qui sont Virgin ("vierge").
Le Deinit() est une méthode de désinitialisation de classe. Dans le cas de REASON_PARAMETERS (les paramètres d'entrée ont été modifiés par l'utilisateur), nous effaçons la liste list_object et définissons la variable name_symbol sur NULL. Dans d'autres cas, l'expert ne fait rien, mais si vous souhaitez ajouter quelque chose, lisez les commentaires.
Le OnEvent() est une méthode de traitement d’ événement du terminal client. Les événements sont générés par le terminal client lorsque l'utilisateur travaille avec un graphique. Les détails peuvent être trouvés dans la documentation du langage MQL5. Dans cet Expert Advisor, l'événement de graphique CHARTEVENT_OBJECT_CLICK a été utilisé. En cliquant sur l'élément d'histogramme, il affiche les niveaux de POC secondaires et inverse la couleur de l'histogramme.
Le OnTimer(void) est une méthode de traitement des événements de minuterie. Il n'est pas utilisé dans mes programmes, mais si vous souhaitez ajouter des actions de minuterie (par exemple, pour afficher l'heure), c'est ici. Avant utilisation, il est nécessaire d'ajouter la ligne suivante au constructeur de classe :
EventSetTimer(time in seconds);
Et la ligne suivante au destructeur :
EventKillTimer();
avant d'appeler la méthode Deinit (REASON_CHARTCLOSE).
Nous avons considéré la classe CExpert ; elle a été créée pour la démonstration des méthodes de la classe CPriceHistogram.
//+------------------------------------------------------------------+ //| Class CPriceHistogram | //| Class description | //+------------------------------------------------------------------+ class CPriceHistogram : public CObject { private: // Class variables double high_day,low_day; bool Init_passed; // Flag if the initialization has passed or not CChartObjectTrend *POCLine; CChartObjectTrend *SecondTopPOCLine,*SecondBottomPOCLine; CChartObjectText *POCLable; CList ListHistogramInner; // list for inner lines storage CList ListHistogramOuter; // list for outer lines storage bool show_level; // to show values of level bool virgin; // is it virgin bool show_second_poc; // show secondary POC levels double second_poc_top; // value of the top secondary POC level double second_poc_bottom; // value of the bottom secondary POC level double poc_value; // POC level value color poc_color; // color of POC level datetime poc_start_time; datetime poc_end_time; bool show_histogram; // show histogram color inner_color; // inner color of the histogram color outer_color; // outer color of the histogram uint range_percent; // percent range datetime time_start; // start time for construction datetime time_end; // final time of construction public: // Class constructor CPriceHistogram(); // Class destructor ~CPriceHistogram(){Delete();} // Class initialization bool Init(datetime time_open,datetime time_close,bool showhistogram); // To level value void ShowLevel(bool show){show_level=show; if(Init_passed) RefreshPOCs();} bool ShowLevel(){return(show_level);} // To show histogram void ShowHistogram(bool show); bool ShowHistogram(){return(show_histogram);} // To show Secondary POC levels void ShowSecondaryPOCs(bool show){show_second_poc=show;if(Init_passed)RefreshPOCs();} bool ShowSecondaryPOCs(){return(show_second_poc);} // To set color of POC levels void ColorPOCs(color col){poc_color=col; if(Init_passed)RefreshPOCs();} color ColorPOCs(){return(poc_color);} // To set internal colour of histogram void ColorInner(color col); color ColorInner(){return(inner_color);} // To set outer colour of histogram void ColorOuter(color col); color ColorOuter(){return(outer_color);} // To set percent range void RangePercent(uint percent){range_percent=percent; if(Init_passed)calculationPOCs();} uint RangePercent(){return(range_percent);} // Returns value of virginity of POC level bool VirginPOCs(){return(virgin);} // Returns starting time of histogram construction datetime GetStartDateTime(){return(time_start);} // Updating of POC levels bool RefreshPOCs(); private: // Calculations of the histogram and POC levels bool calculationPOCs(); // Class delete void Delete(); };
Dans la description de la classe, j'ai essayé de fournir des commentaires pour les variables et les méthodes de classe. Examinons certains d'entre eux en détail.
//+------------------------------------------------------------------+ //| Class initialization | //+------------------------------------------------------------------+ bool CPriceHistogram::Init(datetime time_open,datetime time_close,bool showhistogram)
Cette méthode utilise trois paramètres d'entrée - l'ouverture du bâtiment, l'heure de fermeture de la construction et un drapeau indiquant la construction d’ un histogramme, ou seulement les niveaux de POC.
Dans mon exemple (classe CExpert) les paramètres d'entrée sont transmis au jour d'ouverture et à l'heure d'ouverture le jour suivant day_time_open [i] + PeriodSeconds (PERIOD_D1). Mais lorsque vous utilisez cette classe, rien n'empêche de demander, par exemple, l'heure de la session européenne, américaine, ou la taille de l'écart dans la semaine, le mois, etc.
//+---------------------------------------------------------------------------------------+ //| Calculations of the histogram and POCs levels | //+---------------------------------------------------------------------------------------+ bool CPriceHistogram::calculationPOCs()
Dans cette méthode, l'origine de tous les niveaux et des calculs de leur construction, c'est une méthode privée fermée, inaccessible de l'extérieur.
// We get the data from time_start to time_end int err=0; do { //--- for each bar we are copying the open time rates_time=CopyTime(NULL,PERIOD_M1,time_start,time_end,iTime); if(rates_time<0) PrintErrorOnCopyFunction("CopyTime",_Symbol,PERIOD_M1,GetLastError()); //--- for each bar we are copying the High prices rates_high=CopyHigh(NULL,PERIOD_M1,time_start,time_end,iHigh); if(rates_high<0) PrintErrorOnCopyFunction("CopyHigh",_Symbol,PERIOD_M1,GetLastError()); //--- for each bar we are copying the Low prices rates_total=CopyLow(NULL,PERIOD_M1,time_start,time_end,iLow); if(rates_total<0) PrintErrorOnCopyFunction("CopyLow",_Symbol,PERIOD_M1,GetLastError()); err++; } while((rates_time<=0 || (rates_total!=rates_high && rates_total!=rates_time)) && err<AMOUNT_OF_ATTEMPTS&&!IsStopped()); if(err>=AMOUNT_OF_ATTEMPTS) { return(false); } poc_start_time=iTime[0]; high_day=iHigh[ArrayMaximum(iHigh,0,WHOLE_ARRAY)]; low_day=iLow[ArrayMinimum(iLow,0,WHOLE_ARRAY)]; int count=int((high_day-low_day)/_Point)+1; // Count of duration of a finding of the price at each level int ThicknessOfLevel[]; // create an array for count of ticks ArrayResize(ThicknessOfLevel,count); ArrayInitialize(ThicknessOfLevel,0); for(int i=0;i<rates_total;i++) { double C=iLow[i]; while(C<iHigh[i]) { int Index=int((C-low_day)/_Point); ThicknessOfLevel[Index]++; C+=_Point; } } int MaxLevel=ArrayMaximum(ThicknessOfLevel,0,count); poc_value=low_day+_Point*MaxLevel;
Tout d'abord, nous obtenons les données d'historique des barres de minutes pour une certaine période de temps (iTime [], iHigh[], iLow[]). Ensuite, nous trouvons l'élément maximum et minimum de iHigh[] et Low[]. Ensuite, nous calculons le nombre de points (compte) du minimum au maximum, et réservons le tableau ThicknessOfLevel avec les éléments ThicknessOfLevel. Dans le cycle, nous parcourons la bougie de chaque minute du bas en haut et en ajoutant les données de la présence de la période à ce niveau de prix. Ensuite nous trouvons l'élément maximal du tableau ThicknessOfLevel, ce sera le niveau auquel prix a été le plus longtemps. C'est notre niveau POC.
// Search for the secondary POCs int range_min=ThicknessOfLevel[MaxLevel]-ThicknessOfLevel[MaxLevel]*range_percent/100; int DownLine=0; int UpLine=0; for(int i=0;i<count;i++) { if(ThicknessOfLevel[i]>=range_min) { DownLine=i; break; } } for(int i=count-1;i>0;i--) { if(ThicknessOfLevel[i]>=range_min) { UpLine=i; break; } } if(DownLine==0) DownLine=MaxLevel; if(UpLine==0) UpLine=MaxLevel; second_poc_top=low_day+_Point*UpLine; second_poc_bottom=low_day+_Point*DownLine;
L'étape suivante consiste à trouver les niveaux de POC secondaires. Rappelons que notre diagramme est divisé. Rappelons que notre histogramme est divisé en deux gammes, la gamme interne et externe (affichées dans des couleurs différentes) et la gamme de taille est définie en pourcentage de temps du prix à ce niveau. La gamme des limites internes sont des niveaux de POC secondaires.
Après avoir trouvé la plage de pourcentage POC secondaire - Bordures, avancez vers la construction de l'histogramme.
// Histogram formation if(show_histogram) { datetime Delta=(iTime[rates_total-1]-iTime[0]-PeriodSeconds(PERIOD_H1))/ThicknessOfLevel[MaxLevel]; int step=1; if(count>100) step=count/100; // Calculate the step of the histogram (100 lines as max) ListHistogramInner.Clear(); ListHistogramOuter.Clear(); for(int i=0;i<count;i+=step) { string name=TimeToString(time_start)+" "+IntegerToString(i); double StartY= low_day+_Point*i; datetime EndX= iTime[0]+(ThicknessOfLevel[i])*Delta; CChartObjectTrend *obj=new CChartObjectTrend(); obj.Create(0,name,0,poc_start_time,StartY,EndX,StartY); obj.Background(true); if(i>=DownLine && i<=UpLine) { obj.Color(inner_color); ListHistogramInner.Add(obj); } else { obj.Color(outer_color); ListHistogramOuter.Add(obj); } } }
Il faut mentionner qu'afin de réduire la charge sur le terminal, j'apporte à l'écran un maximum de 100 lignes pour chaque histogramme. Les lignes de l'histogramme sont stockées dans deux listes, et ListHistogramInner ListHistogramOuter, qui sont les objets que nous connaissons déjà dans la classe CList. Mais ces pointeurs sont stockés dans une classe standard d'objets CChartObjectTrend. Pourquoi deux listes, je pense que vous pouvez deviner à partir du titre, pour pouvoir changer l'histogramme des couleurs.
// We receive data beginning from the final time of the histogram till current time err=0; do { rates_time=CopyTime(NULL,PERIOD_M1,time_end,last_tick.time,iTime); rates_high=CopyHigh(NULL,PERIOD_M1,time_end,last_tick.time,iHigh); rates_total=CopyLow(NULL,PERIOD_M1,time_end,last_tick.time,iLow); err++; } while((rates_time<=0 || (rates_total!=rates_high && rates_total!=rates_time)) && err<AMOUNT_OF_ATTEMPTS); // If there isn't history, the present day, level is virgin, we hoist the colours if(rates_time==0) { virgin=true; } else // Otherwise we check history { for(index=0;index<rates_total;index++) if(poc_value<iHigh[index] && poc_value>iLow[index]) break; if(index<rates_total) // If level has crossed poc_end_time=iTime[index]; else virgin=true; } if(POCLine==NULL) { POCLine=new CChartObjectTrend(); POCLine.Create(0,TimeToString(time_start)+" POC ",0,poc_start_time,poc_value,0,0); } POCLine.Color(poc_color); RefreshPOCs();
J'ai essayé de concevoir le CPriceHistogram avec toutes les méthodes nécessaires, s'il est insuffisant, vous pouvez l'ajouter vous-même et je vous aiderai.
Résumé
Encore une fois, je voudrais rappeler que l'histogramme des prix est fiable, mais l'outil intuitif, les signaux de confirmation sont donc nécessaires à son utilisation.
Merci pour votre intérêt. Je suis prêt à répondre à toutes vos questions.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/17
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation