Problem with huge amount of levels

 

Hello,

I found very useful Key Levels indicator from codebase here

But the problem is that it draws lot of lines to the charts and during rapid price movements, like news, this indicator laggs candles, price and charts overall. 

So I would like to know is there any way to reduce the number of those lines somehow? There should only be so many lines to see like active chart is.

#property indicator_chart_window
#property version "2.0"
#property strict

input string H=" --- Mode_Settings ---";
input bool Show_00_50_Levels=true;
input bool Show_20_80_Levels=true;
input color Level_00_Color=clrLime;
input color Level_50_Color=clrGray;
input color Level_20_Color=clrRed;
input color Level_80_Color=clrGreen;

double dXPoint=1;
double Div=0;
double i=0;
double HighPrice= 0;
double LowPrice = 0;
int iDigits;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   iDigits=_Digits;
   if(_Digits==5 || _Digits==3) dXPoint=10;
   if(_Digits==3) iDigits=2;
   if(_Digits==5) iDigits=4;

   Div=0.1/(_Point*dXPoint);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[]
                )
  {
   ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); ArraySetAsSeries(time,true);
   int ih=ArrayMaximum(high, 2); if(ih<0) return rates_total;
   int il=ArrayMinimum(low, 2); if(il<0) return rates_total;
   HighPrice= MathRound((high[ih]+1)*Div);
   LowPrice = MathRound((low[il]-1)*Div);
   if(Show_00_50_Levels)
     {
      for(i=LowPrice; i<=HighPrice; i++)
        {
         if(MathMod(i,5)==0.0)
           {
            string name="RoundPrice "+DoubleToString(i,0);
            if(ObjectFind(0,name)!=0)
              {
               ObjectCreate(0,name,OBJ_HLINE,0,time[1],i/Div);
               ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
               if(MathMod(i,10)==0.0) ObjectSetInteger(0,name,OBJPROP_COLOR,Level_00_Color);
               else ObjectSetInteger(0,name,OBJPROP_COLOR,Level_50_Color);
              }
           }
        }

     }

   if(Show_20_80_Levels)
     {
      for(i=LowPrice; i<=HighPrice; i++)
        {
         if(StringSubstr(DoubleToString(i/Div,iDigits),StringLen(DoubleToString(i/Div,iDigits))-2,2)=="20")
           {
            string name="RoundPrice "+DoubleToString(i,0);
            if(ObjectFind(0,name)!=0)
              {
               ObjectCreate(0,name,OBJ_HLINE,0,time[1],i/Div);
               ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
               ObjectSetInteger(0,name,OBJPROP_COLOR,Level_20_Color);
              }
           }
         if(StringSubstr(DoubleToString(i/Div,iDigits),StringLen(DoubleToString(i/Div,iDigits))-2,2)=="80")
           {
            string name="RoundPrice "+DoubleToString(i,0);
            if(ObjectFind(0,name)!=0)
              {
               ObjectCreate(0,name,OBJ_HLINE,0,time[1],i/Div);
               ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
               ObjectSetInteger(0,name,OBJPROP_COLOR,Level_80_Color);
              }
           }
        }
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
   ObjectsDeleteAll(0,"Round");
  }
//+------------------------------------------------------------------+
KeyLevels
KeyLevels
  • www.mql5.com
The indicator of price levels with round numbers 00, 20, 50, 80.
 
timmytrade:

Hello,

I found very useful Key Levels indicator from codebase here

But the problem is that it draws lot of lines to the charts and during rapid price movements, like news, this indicator laggs candles, price and charts overall. 

So I would like to know is there any way to reduce the number of those lines somehow? There should only be so many lines to see like active chart is.

Hello , try this , it uses the canvas to draw the lines (ideally you'd catch the price range and only recalc levels when it changes)

//warm up 19092024
#property indicator_chart_window
#include <Canvas\Canvas.mqh>
#define SYSTEM_TAG "Key Levels"
input string interested="00,50,20,80";//interested in levels
input string their_colors="Red,Orange,Green,Blue";//parallel colors
input string their_font="Arial";//font
input int their_fontsize=12;//font size

CCanvas OUTPUT;
int screenX=0,screenY=0;
string points[];//we store the points we are interested in here 
color colors[];//and their colors here
bool READY=false;
int OnInit()
  {
  READY=false;
  //extract the points
    ArrayFree(points);
    ArrayFree(colors);
    ushort usep=StringGetCharacter(",",0);
    StringSplit(interested,usep,points);
  //extract the colors
    string parts[];
    StringSplit(their_colors,usep,parts);
    if(ArraySize(parts)>0){
      ArrayResize(colors,ArraySize(parts),0);
      for(int i=0;i<ArraySize(parts);i++){
         colors[i]=StringToColor("clr"+parts[i]);
         }
      }
  //if we have not the same number of points and colors , nah
    if(ArraySize(points)!=ArraySize(colors)){
      if(ArraySize(points)<ArraySize(colors)){Alert("Missing some point values");}
      else{Alert("Missing some colors");}
      return(INIT_FAILED);
      }
  //clean up
    ObjectsDeleteAll(ChartID(),SYSTEM_TAG);
  //create our display
    screenX=(int)ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS,0);
    screenY=(int)ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS,0);
    //we are creating a "screen" bitmap to display your key levels that are in view
    OUTPUT.CreateBitmapLabel(ChartID(),0,SYSTEM_TAG+"_OUTPUT",0,0,screenX,screenY,COLOR_FORMAT_ARGB_NORMALIZE);
    OUTPUT.Erase(0);
    READY=true;
  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[])
  {
  
  return(rates_total);
  }


void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
  if(READY){
    if(id==CHARTEVENT_CHART_CHANGE){
      int scx=(int)ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS,0);
      int scy=(int)ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS,0);
      if(scx!=screenX||scy!=screenY){
        OUTPUT.Resize(scx,scy);
        screenX=scx;
        screenY=scy;
        }
      display_key_levels();
      }
    }
  }

//function to display key levels on our "screen"
void display_key_levels(){
OUTPUT.Erase(0);
/*
okay so what we'll do here
0.First we grab the max price and the min price of the chart
1.each point entry in our array represents some "last digits"
  we'd like to mark when they show up
  So for each point entry :
  ---A.get the digits size
  ---B.obscure those rightmost digits in the max and min price
  ---C.form an integer loop that goes into all the possible candidate prices
  ---D.append the "point entry" we are processing and draw a line and drop a text too maybe
  
*/
double max_price=(double)ChartGetDouble(ChartID(),CHART_PRICE_MAX,0);
double min_price=(double)ChartGetDouble(ChartID(),CHART_PRICE_MIN,0);
//so loop into our "points entries"
for(int i=0;i<ArraySize(points);i++){
//a.how many digits ?
  int entry_digits=StringLen(points[i]);
//b.obscure by multiplying
  int max_int=(int)(MathPow(10.0,_Digits-entry_digits)*max_price);
  int min_int=(int)(MathPow(10.0,_Digits-entry_digits)*min_price);
  int injection_points=StringToInteger(points[i]);
//c.integer loop and draw
  OUTPUT.FontSet(their_font,their_fontsize,FW_NORMAL,0);
  for(int j=min_int;j<=max_int;j++){
     //these are essentially points divided by _Digits-entry_digits
       int in_points=j*(int)(MathPow(10,entry_digits))+injection_points;
       double in_price=NormalizeDouble(((double)in_points)/MathPow(10.0,_Digits),_Digits);
     //now find the y coordinates of the price
       int x=0,y=0;
       ChartTimePriceToXY(ChartID(),0,0,in_price,x,y);
     //and draw a line
       OUTPUT.LineHorizontal(0,screenX,y,ColorToARGB(colors[i],255));
     //and our text
       OUTPUT.TextOut(screenX,y,DoubleToString(in_price,_Digits),ColorToARGB(colors[i],255),TA_RIGHT|TA_BOTTOM);
     }
}
OUTPUT.Update(true);
}
 
Lorentzos Roussos #:

Hello , try this , it uses the canvas to draw the lines (ideally you'd catch the price range and only recalc levels when it changes)

Oh man, absolutely genius! Works like charm. 
Thank you very muych!

 
Lorentzos Roussos #:

Hello , try this , it uses the canvas to draw the lines (ideally you'd catch the price range and only recalc levels when it changes)

Can you help to make it work on Gold pair too? 

I just don't get that digits thing in gold, drives me crazy.

Example: I would like to get line on price 2670.00, 2665.00, 2660.00, 2655.00.. you see the end of price is always 0.00 or 5.00. 
How can I do that?

 
timmytrade #:

Can you help to make it work on Gold pair too? 

I just don't get that digits thing in gold, drives me crazy.

Example: I would like to get line on price 2670.00, 2665.00, 2660.00, 2655.00.. you see the end of price is always 0.00 or 5.00. 
How can I do that?

add 500,000 in the levels 

 
Lorentzos Roussos #:

add 500,000 in the levels 

Cool, thanks!