Comment faire en sorte que les objets dessinés par XY changent en douceur (MT4 vs MT5)
Aidez à résoudre un problème sur le terminal MT5.
J'ai décidé de transférer mon produit de mql4 à mql5.
Il utilise des rectangles qui sont dessinés sur des coordonnées XY.
Dans MT4, il est très fluide et sans à-coups lors du changement d'échelle verticale, mais dans MT5, la même approche conduit à quelques freezes et à une "non-lisse" notable.
J'ai spécialement fabriqué un prototype simplifié pour démontrer l'effet. Il en va de même pour MT4 et MT5. Comparez la différence lorsque vous changez l'échelle verticale (avec une souris sur l'échelle des prix).
Dans MT5 tout sera sans freins, mais le redécoupage est saccadé. Plus il y a d'objets, pire c'est. Mais dans MT4, tout est fluide.
Je joins les fichiers sources mq4 et mq5 et je colle le code mq5.
S'il vous plaît, aidez-moi à le rendre plus facile.
Je veux comprendre : est-ce " tel et tel " MT5 ou " tel et tel " mon code pour MT5.
J'essaie de prouver à MQ depuis des années que ces fonctions ne devraient pas être asynchrones, parce que la table des propriétés du graphique existe déjà et qu'il suffit de prendre ces propriétés et qu'il n'y a aucun intérêt à exécuter un processus asynchrone.
Mais tous les efforts sont vains.
Cela pue vraiment l'idiotie.
Je sais de quoi je parle, car je programme dans de nombreux langages, y compris Kanvas, et j'utilise activement le modèle piloté par les événements.
Et dans la préhistoire de MQL4, ce problème est minime.
Oui, vous avez 4 fonctions asynchrones qui prennent 99,76% du temps.
...
Et dans le MQL4 préhistorique, ce problème est minime.
Oui, tout vole dans MT4.
Si cela ne vous dérange pas, pouvez-vous me donner un exemple de la façon de mieux le faire ?
Oui, tout vole dans MT4.
Si cela ne vous dérange pas, pouvez-vous me donner un exemple de la façon de le faire plus intelligemment ?
Le moyen le plus court est de joindre ma biblio iCanvas, ce qui permettra de ne pas utiliser les fonctions asynchrones en boucle.
Vous n'avez pas besoin d'utiliser la toile elle-même. Il sera accroché à votre tableau pendant toute la durée de l'opération, mais il sera vide et transparent.
Si vous souhaitez une méthode plus longue sans utiliser iCanvas, vous devrez alors consulter à nouveau cette bible, car elle y est implémentée, mais ce n'est pas pour les peureux. :))
Je vais essayer d'expliquer brièvement ce que fait iCanvas.
Elle dispose d'un gestionnaire interneOnChartEvent, qui attrape l'événementCHARTEVENT_CHART_CHANGE et remplit sa structure interne W, en utilisant toutes les mêmes fonctions ChartGet asynchrones, mais ne le fait qu'une fois à l'occurrence de cet événement.
Cela permet d'optimiser plus ou moins la vitesse.
Cette bibliothèque contient également l'objet Canvas, qui étire l'écran entier et s'y adapte lorsque l'écran change.
Ici, par exemple, trois lignes de code ont été ajoutées et de nombreuses lignes ont été supprimées :
#property indicator_chart_window #include <Canvas\iCanvas.mqh> //https://www.mql5.com/ru/code/22164 #property indicator_buffers 0 #property indicator_plots 0 string obj_name = "Asd_"; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if(NewBar()) { DrawObj(); } return(rates_total); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_CHART_CHANGE) { DrawObj(); } } //+------------------------------------------------------------------+ //| Выводим на график | //+------------------------------------------------------------------+ void DrawObj() { string GenName = obj_name; double startPricePos = SymbolInfoDouble(Symbol(),SYMBOL_BID); int step_Pips = 50; for(int i=1; i<=20; i++) { double stp = (step_Pips*i)*SymbolInfoDouble(Symbol(),SYMBOL_POINT); RectLabelCreate(GenName+"UP_"+IntegerToString(i),startPricePos + stp); RectLabelCreate(GenName+"DN_"+IntegerToString(i),startPricePos - stp); } ChartRedraw(0); } //+------------------------------------------------------------------+ //| Создает прямоугольную метку | //+------------------------------------------------------------------+ void RectLabelCreate(string name, // имя метки double price // цена ) { const long chart_ID=0; // ID графика int sub_window=0; // номер подокна int x=0; // координата по оси X int y=0; // координата по оси Y x=W.Width/2; y = Round(Canvas.Y(price)); //x=(int)(ChartGetInteger(chart_ID,CHART_WIDTH_IN_PIXELS,sub_window)/2); //ChartXYToTimePrice(chart_ID,x,y,sub_window,time_pos_X_centr,price_pos_Y_tmp); //ChartTimePriceToXY(chart_ID,sub_window,time_pos_X_centr,price,x,y); const int width=50; // ширина const int height=10; // высота const color back_clr=C'236,233,216'; // цвет фона const ENUM_BORDER_TYPE border=BORDER_SUNKEN; // тип границы const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER; // угол графика для привязки const color clr=clrRed; // цвет плоской границы (Flat) const ENUM_LINE_STYLE style=STYLE_SOLID; // стиль плоской границы const int line_width=1; // толщина плоской границы const bool back=false; // на заднем плане const bool selection=false; // выделить для перемещений const bool hidden=true; // скрыт в списке объектов const long z_order=0; // приоритет на нажатие мышью if(ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,0,0)) { ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width); ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height); ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr); ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border); ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style); ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width); ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); } else Print(_LastError); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool NewBar() { static int countLastBar=0; int curBars = iBars(Symbol(),PERIOD_CURRENT); bool flg = false; if(countLastBar!=curBars) { countLastBar=curBars; flg=true; } return(flg); } //+------------------------------------------------------------------+Dans tous les cas, vous pouvez augmenter le nombre d'objets avec cet algorithme et cela n'affectera pas trop les performances.
Ou peut-être que ce n'est pas un bug mais une fonctionnalité ? Il y a quelque chose d'optimisé avec les graphiques. Et cela fonctionne mal parce qu'il est souhaitable d'utiliser toutes les choses aux fins prévues. Il existe des objets graphiques spécialisés qui sont liés aux coordonnées de prix - ils doivent donc être utilisés pour cette tâche.
C'est ce que je pensais aussi, jusqu'à ce que j'acquière plus de connaissances sur le sujet.
La raison est sans ambiguïté : la sous-réflexion.
Une certaine "autorité" a fait une erreur au début (il y a environ 10 ans) et personne ne pense encore qu'il aurait pu faire une erreur.
https://www.mql5.com/ru/forum/1111/page2780#comment_16886162
Ils semblent même avoir accepté et promis de l'améliorer, mais non - c'est fini. C'est toujours là.
https://www.mql5.com/ru/forum/1111/page2781#comment_16904132
Le moyen le plus court est de joindre mon bibblet iCanvas, qui vous permettra d'éviter d'utiliser des fonctions asynchrones dans la boucle.
Vous n'avez pas besoin d'utiliser le canevas lui-même. Il sera accroché à votre tableau pendant toute la durée de l'opération, mais il sera vide et transparent.
S'il existe un moyen plus long sans utiliser iCanvas, vous devrez alors consulter à nouveau cette bible, car elle est mise en œuvre à cet endroit, mais ce n'est pas pour les peureux. :))
Je vais essayer d'expliquer brièvement ce que fait iCanvas.
Il dispose d'un gestionnaire interneOnChartEvent, qui attrape l'événementCHARTEVENT_CHART_CHANGE et remplit sa structure interne W, en utilisant toutes les mêmes fonctions ChartGet asynchrones, mais ne le fait qu'une seule fois à l'occurrence de cet événement.
Cela permet d'optimiser plus ou moins la vitesse.
Cette bibliothèque contient également l'objet Canvas, qui étire l'écran entier et s'y adapte lorsque l'écran change.
Ici, par exemple, trois lignes de code ont été ajoutées et de nombreuses lignes ont été supprimées :
Merci pour cette solution similaire au problème. En effet, la vitesse de rendu a augmenté. On dirait que je vais devoir maîtriser la bibliothèque.
Je tiens également à préciser la nuance suivante. Il compile avec cette formulation avec un avertissement :
y = Canvas.Y(price);
Et il compile avec celui-ci sans avertissement, mais la vitesse est un peu plus lente.
y = (int)Canvas.Y(price);
Qu'est-ce qui est le plus correct ?)
Merci pour ce type de solution au problème. En effet, la vitesse de rendu s'est améliorée. On dirait que je vais devoir apprendre la bibliothèque.
Je voudrais également clarifier la nuance suivante. Il compile avec cette formulation avec un avertissement :
Et il compile avec celui-ci sans avertissement, mais la vitesse est un peu plus lente.
Qu'est-ce qui est le plus correct ?)
Quel type de "y" avez-vous ?
parce que si int et objectivement"la vitesse baisse un peu" c'est un SAC
- 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
Aidez à résoudre un problème sur le terminal MT5.
J'ai décidé de transférer mon produit de mql4 à mql5.
Il utilise des rectangles qui sont dessinés sur des coordonnées XY.
Dans MT4, il est très fluide et sans à-coups lors du changement d'échelle verticale, mais dans MT5, la même approche conduit à quelques freezes et à une "non-lisse" notable.
J'ai spécialement fabriqué un prototype simplifié pour démontrer l'effet. Il en va de même pour MT4 et MT5. Comparez la différence lorsque vous changez l'échelle verticale (avec une souris sur l'échelle des prix).
Dans MT5 tout sera sans freins, mais le redécoupage est saccadé. Plus il y a d'objets, pire c'est. Mais dans MT4, tout est fluide.
Je joins les fichiers sources mq4 et mq5 et je colle le code mq5.
S'il vous plaît, aidez-moi à le rendre plus facile.
Je veux comprendre : "ceci est" MT5 ou "ceci est" mon code pour MT5.