Ajudar a resolver um problema no terminal MT5.
Decidi transferir meu produto de mql4 para mql5.
Ela utiliza retângulos que são desenhados em coordenadas XY.
No MT4 tudo é suave e sem solavancos ao mudar a escala vertical, mas no MT5 a mesma abordagem leva a alguns congelamentos e a uma notável "não-moleza".
Eu fiz especialmente um protótipo simplificado para demonstrar o efeito. É o mesmo para MT4 e MT5. Compare a diferença quando você muda a escala vertical (com um mouse na escala de preços).
No MT5 tudo estará sem freios, mas o redesenho é estúpido. Quanto mais objetos, pior. Mas no MT4 tudo é suave.
Eu anexei arquivos mq4 e mq5 de origem e colei código mq5.
Por favor, ajude-me a facilitar as coisas.
Quero entender: é "tal e tal" MT5 ou "tal e tal" meu código para MT5.
Eu venho tentando provar à MQ há anos que estas funções não devem ser assíncronas, porque a tabela de propriedades do gráfico já existe e basta tomar estas propriedades e não adianta executar um processo assíncrono.
Mas todos os esforços são em vão.
Isto realmente tresanda a idiotice.
Sei do que estou falando, porque estou programando em muitas linguagens incluindo Kanvas e usando ativamente o modelo orientado a eventos.
E no MQL4 pré-histórico este problema é mínimo.
Sim, você tem 4 funções assíncronas que levam 99,76% de todo o tempo.
...
E na MQL4 pré-histórica este problema é mínimo.
Sim, tudo voa no MT4.
Se você não se importa, pode me dar um exemplo de como fazê-lo melhor?
Sim, tudo voa no MT4.
Se você não se importa, pode me dar um exemplo de como fazer isso de forma mais inteligente?
O caminho mais curto é anexar meu biblio iCanvas, que permitirá não utilizar funções assíncronas em loop.
Você não precisa usar a tela em si. Ele ficará pendurado em sua ficha para tudo isso, mas será vazio e transparente.
Se um método mais longo sem usar iCanvas, então você terá que procurar nesta bíblia novamente, como ela é implementada ali, mas não é para os fracos de coração. :)
Vou tentar explicar brevemente o que o iCanvas faz.
Possui manipulador internoOnChartEvent, que captura o eventoCHARTEVENT_CHART_CHANGE e preenche sua estrutura interna W, usando todas as mesmas funções assíncronas ChartGet, mas o faz apenas uma vez com a ocorrência deste evento.
Isto permite mais ou menos otimizar a velocidade.
Também nesta biblioteca pendura o objeto Canvas, que estica a tela inteira e se ajusta a ela quando a tela muda.
Aqui, por exemplo, três linhas de código foram adicionadas e muitas linhas descartadas:
#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); } //+------------------------------------------------------------------+Em qualquer caso, você pode aumentar o número de objetos com este algoritmo e isso não afetará muito o desempenho.
Ou talvez não seja um bug, mas uma característica? Algo lá é otimizado com gráficos. E funciona mal porque é desejável usar todas as coisas para os fins a que se destinam. Existem objetos gráficos especializados que estão vinculados a coordenadas de preço - portanto, devem ser utilizados para esta tarefa.
Eu também pensava assim, até adquirir mais conhecimento sobre o assunto.
A razão é inequívoca - subentendida.
Alguma "autoridade" cometeu um erro no início (cerca de 10 anos atrás) e ninguém ainda pensa que ele poderia ter cometido um erro.
Eles até parecem ter concordado e prometido melhorá-lo, mas não -acabou. Ainda está lá.
O caminho mais curto é anexar minha bíblia iCanvas, o que lhe permitirá evitar o uso de funções assíncronas no laço.
Você não precisa usar a tela em si. Ele ficará pendurado em sua ficha para tudo isso, mas será vazio e transparente.
Se um caminho mais longo sem usar iCanvas, então você terá que procurar nesta bíblia novamente, como ela é implementada ali, mas não é para os fracos de coração. :)
Vou tentar explicar brevemente o que o iCanvas faz.
Possui manipulador internoOnChartEvent, que captura o eventoCHARTEVENT_CHART_CHANGE e preenche sua estrutura interna W, usando todas as mesmas funções assíncronas ChartGet, mas o faz apenas uma vez com a ocorrência deste evento.
Isto permite mais ou menos otimizar a velocidade.
Também nesta biblioteca pendura o objeto Canvas, que estica a tela inteira e se ajusta a ela quando a tela muda.
Aqui, por exemplo, três linhas de código foram adicionadas e muitas linhas foram descartadas:
Obrigado por uma solução semelhante para o problema. De fato, a velocidade de renderização aumentou. Parece que vou ter que dominar a biblioteca.
Também gostaria de especificar a seguinte nuança. Ela se compila com esta formulação com um aviso:
y = Canvas.Y(price);
E se compila com este sem um aviso, mas a velocidade é um pouco mais lenta.
y = (int)Canvas.Y(price);
O que é mais correto?)
Obrigado por este tipo de solução para o problema. De fato, a velocidade de renderização melhorou. Parece que vou ter que aprender a biblioteca.
Gostaria também de esclarecer a seguinte nuance. Ela se compila com esta formulação com um aviso:
E se compila com este sem um aviso, mas a velocidade é um pouco mais lenta.
O que é mais correto?)
Que tipo de "y" você tem?
porque se int e objetivamente"a velocidade cai um pouco" isto é um BAG
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Ajudar a resolver um problema no terminal MT5.
Decidi transferir meu produto de mql4 para mql5.
Ela utiliza retângulos que são desenhados em coordenadas XY.
No MT4 é muito suave e sem solavancos ao mudar de escala vertical, mas no MT5 a mesma abordagem leva a alguns congelamentos e à notória "não-moleza".
Eu fiz especialmente um protótipo simplificado para demonstrar o efeito. É o mesmo para MT4 e MT5. Compare a diferença quando você muda a escala vertical (com um mouse na escala de preços).
No MT5 tudo estará sem freios, mas o redesenho é estúpido. Quanto mais objetos, pior. Mas no MT4 tudo é suave.
Eu anexei arquivos mq4 e mq5 de origem e colei código mq5.
Por favor, ajude-me a facilitar as coisas.
Quero entender: "isto é" MT5 ou "isto é" meu código para MT5.