forked from rosh/MQL5Book
119 lines
5.1 KiB
MQL5
119 lines
5.1 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| ObjectChannels.mq5 |
| |||
//| Copyright 2021, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright 2021, MetaQuotes Ltd."
| |||
#property link "https://www.mql5.com"
| |||
#property version "1.0"
| |||
#property description "Create and update object channels applied on specified number of latest bars.\n"
| |||
"Get estimation of future prices, extrapolated by channel lines (upper and lower)."
| |||
| |||
#property indicator_chart_window
| |||
#property indicator_buffers 0
| |||
#property indicator_plots 0
| |||
| |||
input int WorkPeriod = 10;
| |||
| |||
const string Prefix = "ObjChnl-";
| |||
const string ObjStdDev = Prefix + "StdDev";
| |||
const string ObjRegr = Prefix + "Regr";
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator initialization function |
| |||
//+------------------------------------------------------------------+
| |||
void OnInit()
| |||
{
| |||
CreateObjects();
| |||
UpdateObjects();
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Prepare 2 objects with channels |
| |||
//+------------------------------------------------------------------+
| |||
void CreateObjects()
| |||
{
| |||
ObjectCreate(0, ObjStdDev, OBJ_STDDEVCHANNEL, 0, 0, 0);
| |||
ObjectCreate(0, ObjRegr, OBJ_REGRESSION, 0, 0, 0);
| |||
ObjectSetInteger(0, ObjStdDev, OBJPROP_COLOR, clrBlue);
| |||
ObjectSetInteger(0, ObjStdDev, OBJPROP_RAY_RIGHT, true);
| |||
ObjectSetInteger(0, ObjRegr, OBJPROP_COLOR, clrRed);
| |||
// NB: ray is not enabled for regression channel
| |||
// this will prevent extrapolation of future price levels for it
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Per bar object processing (keep time position on latest bars) |
| |||
//+------------------------------------------------------------------+
| |||
void UpdateObjects()
| |||
{
| |||
const datetime t0 = iTime(NULL, 0, WorkPeriod);
| |||
const datetime t1 = iTime(NULL, 0, 0);
| |||
| |||
// we don't use ObjectMove because the channels require time coordinates only
| |||
ObjectSetInteger(0, ObjStdDev, OBJPROP_TIME, 0, t0);
| |||
ObjectSetInteger(0, ObjStdDev, OBJPROP_TIME, 1, t1);
| |||
ObjectSetInteger(0, ObjRegr, OBJPROP_TIME, 0, t0);
| |||
ObjectSetInteger(0, ObjRegr, OBJPROP_TIME, 1, t1);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Per tick object processing (show prices in anchor points) |
| |||
//+------------------------------------------------------------------+
| |||
void DisplayObjectData()
| |||
{
| |||
const double p0 = ObjectGetDouble(0, ObjStdDev, OBJPROP_PRICE, 0);
| |||
const double p1 = ObjectGetDouble(0, ObjStdDev, OBJPROP_PRICE, 1);
| |||
| |||
// the following conditions are always true due to the channels algorithms:
| |||
// - middle lines of both channels coincide,
| |||
// - binding points are always on the middle line
| |||
// const double d0 = ObjectGetValueByTime(0, ObjStdDev, iTime(NULL, 0, 0), 0); == p1
| |||
// const double r0 = ObjectGetValueByTime(0, ObjRegr, iTime(NULL, 0, 0), 0); == p1
| |||
| |||
// trying to get extrapolation of future prices for WorkPeriod bars
| |||
const double d1 = ObjectGetValueByTime(0, ObjStdDev, iTime(NULL, 0, 0) + WorkPeriod * PeriodSeconds(), 1);
| |||
const double d2 = ObjectGetValueByTime(0, ObjStdDev, iTime(NULL, 0, 0) + WorkPeriod * PeriodSeconds(), 2);
| |||
| |||
const double r1 = ObjectGetValueByTime(0, ObjRegr, iTime(NULL, 0, 0) + WorkPeriod * PeriodSeconds(), 1);
| |||
const double r2 = ObjectGetValueByTime(0, ObjRegr, iTime(NULL, 0, 0) + WorkPeriod * PeriodSeconds(), 2);
| |||
| |||
// display current prices on binding points of the middle line,
| |||
// and future prices along the upper and lower lines of the channels
| |||
Comment(StringFormat("%.*f %.*f\ndev: up=%.*f dn=%.*f\nreg: up=%.*f dn=%.*f",
| |||
_Digits, p0, _Digits, p1,
| |||
_Digits, d1, _Digits, d2,
| |||
_Digits, r1, _Digits, r2));
| |||
// NB: because of intentionally omitted RAY setting for regression channel,
| |||
// it will always produce zeros!
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator iteration function |
| |||
//+------------------------------------------------------------------+
| |||
int OnCalculate(const int rates_total,
| |||
const int prev_calculated,
| |||
const int begin,
| |||
const double &price[])
| |||
{
| |||
static datetime now = 0;
| |||
if(now != iTime(NULL, 0, 0))
| |||
{
| |||
UpdateObjects();
| |||
now = iTime(NULL, 0, 0);
| |||
}
| |||
| |||
DisplayObjectData();
| |||
| |||
return rates_total;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Finalization handler |
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int)
| |||
{
| |||
ObjectsDeleteAll(0, Prefix);
| |||
Comment("");
| |||
}
| |||
//+------------------------------------------------------------------+
|