//+------------------------------------------------------------------+
//| Size of candles (text).mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.001"
#property description " "
#property description "The size of the candles in the form of text above each bar"
#property description "---"
#property description "Calculation of candles size: the \"Minuend\" minus the \"Subtrahend\""
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
//---
enum OHLC
{
Open=0, // Open
High=1, // High
Low=2, // Low
Close=3, // Close
};
//--- input parameters
input uchar InpNumberOfBars=3; // Number of bars (do not use "0")
input OHLC InpMinuend = High; // Minuend
input OHLC InpSubtrahend = Low; // Subtrahend
//---
string m_prefix="size_candles_"; // prefix for object
double m_adjusted_point; // point value adjusted for 3 or 5 points
string m_arr_names[]; // array of names of objects OBJ_TEXT
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(InpNumberOfBars==0)
{
Print("\"Number of bars\"==0. Do not use \"0\"");
return(INIT_PARAMETERS_INCORRECT);
}
//---
m_prefix+=EnumToString(Period())+"_";
//--- tuning for 3 or 5 digits
int digits_adjust=1;
if(Digits()==3 || Digits()==5)
digits_adjust=10;
m_adjusted_point=Point()*digits_adjust;
//---
DeleteAll();
ResetLastError();
if(ArrayResize(m_arr_names,InpNumberOfBars)==-1)
{
Print(__FUNCTION__," ArrayResize error");
return(INIT_SUCCEEDED);
}
ArraySetAsSeries(m_arr_names,true);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
DeleteAll();
}
//+------------------------------------------------------------------+
//| 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[])
{
ArraySetAsSeries(time,true);
ArraySetAsSeries(open,true);
ArraySetAsSeries(high,true);
ArraySetAsSeries(low,true);
ArraySetAsSeries(close,true);
if(prev_calculated==0 || prev_calculated!=rates_total)
{
DeleteAll();
ResetLastError();
ArrayFree(m_arr_names);
if(ArrayResize(m_arr_names,InpNumberOfBars)==-1)
{
Print(__FUNCTION__,", prev_calculated==0, ArrayResize error");
return(0);
}
//--- create the texts
int limit=InpNumberOfBars-1;
for(int i=limit;i>=0;i--)
{
string name=m_prefix+"high_"+TimeToString(time[i]);
string text=Calculate(open[i],high[i],low[i],close[i]);
if(!TextCreate(0,name,0,time[i],high[i],text))
return(0);
m_arr_names[i]=name;
}
//---
return(rates_total);
}
double price_ = ObjectGetDouble(0,m_arr_names[0],OBJPROP_PRICE,0);
long time_ = ObjectGetInteger(0,m_arr_names[0],OBJPROP_TIME,0);
string text = Calculate(open[0],high[0],low[0],close[0]);
TextChange(0,m_arr_names[0],text);
if(high[0]>price_)
{
TextMove(0,m_arr_names[0],time_,high[0]);
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Creating Text object |
//+------------------------------------------------------------------+
bool TextCreate(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 double angle=90.0, // text slope
const string font="Lucida Console", // font
const int font_size=10, // font size
const color clr=clrBlue, // color
const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT,// anchor type
const bool back=false, // in the background
const bool selection=false, // highlight to move
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//--- set anchor point coordinates if they are not set
//ChangeTextEmptyPoint(time,price);
//--- reset the error value
ResetLastError();
//--- create Text object
if(!ObjectCreate(chart_ID,name,OBJ_TEXT,sub_window,time,price))
{
Print(__FUNCTION__,
": failed to create \"Text\" object! Error code = ",GetLastError());
return(false);
}
//--- set the text
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- set text font
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- set font size
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- set the slope angle of the text
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- set anchor type
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- set color
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- display in the foreground (false) or background (true)
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the object by mouse
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Move the anchor point |
//+------------------------------------------------------------------+
bool TextMove(const long chart_ID=0, // chart's ID
const string name="Text", // object name
datetime time=0, // anchor point time coordinate
double price=0) // anchor point price coordinate
{
//--- if point position is not set, move it to the current bar having Bid price
if(!time)
time=TimeCurrent();
if(!price)
price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
//--- reset the error value
ResetLastError();
//--- move the anchor point
if(!ObjectMove(chart_ID,name,0,time,price))
{
Print(__FUNCTION__,
": failed to move the anchor point! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| Change the object text |
//+------------------------------------------------------------------+
bool TextChange(const long chart_ID=0, // chart's ID
const string name="Text", // object name
const string text="Text") // text
{
//--- reset the error value
ResetLastError();
//--- change object text
if(!ObjectSetString(chart_ID,name,OBJPROP_TEXT,text))
{
Print(__FUNCTION__,
": failed to change the text! Error code = ",GetLastError());
return(false);
}
//--- successful execution
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void DeleteAll()
{
long chart_id=0; // Chart identifier. 0 means the current chart
const string prefix=m_prefix; // Prefix in object names
int sub_window = 0; // Number of the chart subwindow. 0 means the main chart window
int object_type = OBJ_TEXT; // Type of the object
ObjectsDeleteAll(chart_id,prefix,sub_window,object_type);
//Print(__FUNCTION__);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string Calculate(const double open,const double high,const double low,const double close)
{
double minuend=0.0;
switch(InpMinuend)
{
case Open:
minuend=open;
break;
case High:
minuend=high;
break;
case Low:
minuend=low;
break;
case Close:
minuend=close;
break;
}
double subtrahend=0.0;
switch(InpSubtrahend)
{
case Open:
subtrahend=open;
break;
case High:
subtrahend=high;
break;
case Low:
subtrahend=low;
break;
case Close:
subtrahend=close;
break;
}
string text=DoubleToString((minuend-subtrahend)/m_adjusted_point,0);
//---
return(text);
}
//+------------------------------------------------------------------+
Comments