MQL5Book/Indicators/p5/ObjectChannels.mq5

120 lines
5.1 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:09:41 +02:00
//+------------------------------------------------------------------+
//| 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("");
}
//+------------------------------------------------------------------+