//+------------------------------------------------------------------+
//| BarNumbers.mq4 |
//| Samuel Beer |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Samuel Beer"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#property indicator_chart_window
int FirstBar;
int LastBar;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
FirstBar = Bars-1-(int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
LastBar = FirstBar+(int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "bn_");
}
//+------------------------------------------------------------------+
//| 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 (prev_calculated == rates_total) // inside bar tick
{
ObjectSetDouble(0, StringFormat("bn_ser_%d", Bars-1), OBJPROP_PRICE, High[0]);
ObjectSetDouble(0, StringFormat("bn_abs_%d", Bars-1), OBJPROP_PRICE, Low[0]);
}
else // new bar
{
int limit = rates_total - prev_calculated;
int first_bar = Bars-1-FirstBar;
int last_bar = Bars-1-LastBar;
for (int i = first_bar; i >= last_bar && i >= 0; --i)
{
// change text of series numbers
if (i >= limit)
ObjectSetString(0, StringFormat("bn_ser_%d", Bars-1-i), OBJPROP_TEXT, StringFormat("%d", i));
// recreate abs numbers only from where we left of
else if (i < limit)
NumbersCreate(i);
}
}
//--- return value of prev_calculated for next call
return rates_total;
}
void OnChartEvent(const int id, // Event ID
const long& lparam, // Parameter of type long event
const double& dparam, // Parameter of type double event
const string& sparam // Parameter of type string events
)
{
// when the chart changes, update the display of objects
if (id != CHARTEVENT_CHART_CHANGE) return ;
int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
int last_bar = first_bar-(int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);
int prev_first = Bars-1-FirstBar;
int prev_last = Bars-1-LastBar;
// if the viewport shifted to a complete new position -> redraw all
if (first_bar < prev_last || last_bar > prev_first)
{
ObjectsDeleteAll(0, "bn_");
for (int i=first_bar; i >= last_bar && i >= 0; --i)
NumbersCreate(i);
}
else
{
int end = MathMin(last_bar, prev_last);
for (int i=MathMax(first_bar, prev_first); i >= end && i >= 0; --i)
{
if (i > first_bar)
NumbersDelete(i);
else if (i > prev_first)
NumbersCreate(i);
/*else
{
Print ("would jump to ", MathMax(last_bar, prev_last));
i = MathMax(last_bar, prev_last);
continue;
}*/
if (i < last_bar)
NumbersDelete(i);
else if (i < prev_last)
NumbersCreate(i);
}
}
FirstBar = Bars-1-first_bar;
LastBar = Bars-1-last_bar;
}
//+------------------------------------------------------------------+
bool NumberCreate(const long chart_ID=0, // chart's ID
const string name="Text", // object name
const int sub_window=0, // subwindow index
datetime time=0, // anchor point time
double price=0, // anchor point price
const string text="Text", // the text itself
const string font="Arial", // font
const int font_size=10, // font size
const color clr=clrRed, // color
const double angle=0.0, // text slope
const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER) // anchor type
{
ObjectCreate(chart_ID,name,OBJ_TEXT,sub_window,time,price);
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
return(true);
}
void NumbersCreate(int i) // i in series coordinates
{
NumberCreate(0, StringFormat("bn_ser_%d", Bars-1-i), 0, Time[i], High[i], StringFormat("%d", i), "Arial", 10, clrSteelBlue, 90, ANCHOR_LEFT);
NumberCreate(0, StringFormat("bn_abs_%d", Bars-1-i), 0, Time[i], Low[i], StringFormat("%d", Bars-1-i), "Arial", 10, clrGray, 90, ANCHOR_RIGHT);
}
void NumbersDelete(int i)
{
ObjectDelete(0, StringFormat("bn_ser_%d", Bars-1-i));
ObjectDelete(0, StringFormat("bn_abs_%d", Bars-1-i));
}
Comments