dinexspace-free-indicators/Indicators/DinexPivotPoints.mq5
173 строки
6,4 КиБ
MQL5
ИсходныйПостоянная ссылкаОбычный видИстория
//+------------------------------------------------------------------+
//| DinexSpace | Pivot Points |
//| Classic, Fibonacci and Camarilla pivot levels from the previous |
//| day, week or month, one segment per period, with labels. |
//| Values come from closed D1/W1/MN1 bars only. |
//| It only draws levels; it gives no trade signals. |
//+------------------------------------------------------------------+
#property copyright "(c) 2026 DinexSpace"
#property version "1.00"
#property description "Classic, Fibonacci and Camarilla pivots from the previous day, week or month."
#property description "One segment per period with price labels. Draws levels only, no signals."
#property strict
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
enum ENUM_PIVOT_TYPE
{
PIVOT_CLASSIC = 0, // Classic
PIVOT_FIBONACCI = 1, // Fibonacci
PIVOT_CAMARILLA = 2 // Camarilla
};
enum ENUM_PIVOT_TF
{
PIVOT_DAY = 0, // Previous day
PIVOT_WEEK = 1, // Previous week
PIVOT_MONTH = 2 // Previous month
};
input group "Pivots"
input ENUM_PIVOT_TYPE InpType = PIVOT_CLASSIC; // Type
input ENUM_PIVOT_TF InpBase = PIVOT_DAY; // Based on
input int InpLevels = 3; // Levels each side (Camarilla up to 4)
input group "Display"
input color InpColP = C'255,176,0'; // Pivot
input color InpColR = clrSpringGreen; // Resistance (R)
input color InpColS = clrAqua; // Support (S)
input int InpHist = 3; // Periods of history
input ENUM_LINE_STYLE InpStyle = STYLE_SOLID; // Line style
input bool InpLabels = true; // Labels with price (current period)
const string PFX = "DNXPV_";
datetime g_lastPeriod = 0;
ENUM_TIMEFRAMES BaseTf()
{
if(InpBase == PIVOT_WEEK) return PERIOD_W1;
if(InpBase == PIVOT_MONTH) return PERIOD_MN1;
return PERIOD_D1;
}
// Level k of the period `d` periods back: 0 = pivot, +1..+4 = R1..R4, -1..-4 = S1..S4.
// Returns false when the level does not exist for this type or the data is not ready.
bool Level(int k, int d, double &y)
{
ENUM_TIMEFRAMES tf = BaseTf();
double h = iHigh(_Symbol, tf, d + 1), l = iLow(_Symbol, tf, d + 1), c = iClose(_Symbol, tf, d + 1);
if(h <= 0 || l <= 0 || c <= 0 || MathAbs(k) > InpLevels)
return false;
double r = h - l, pp = (h + l + c) / 3.0;
int a = MathAbs(k), sg = (k > 0) ? 1 : -1;
if(k == 0) { y = pp; return true; }
if(InpType == PIVOT_CLASSIC)
{
if(a == 1) { y = (k > 0) ? 2 * pp - l : 2 * pp - h; return true; }
if(a == 2) { y = pp + sg * r; return true; }
if(a == 3) { y = (k > 0) ? h + 2 * (pp - l) : l - 2 * (h - pp); return true; }
return false;
}
if(InpType == PIVOT_FIBONACCI)
{
double f[3] = {0.382, 0.618, 1.0};
if(a > 3) return false;
y = pp + sg * f[a - 1] * r;
return true;
}
double cm[4] = {12.0, 6.0, 4.0, 2.0};
y = c + sg * r * 1.1 / cm[a - 1];
return true;
}
string Tag(int k) { return (k == 0) ? "P" : ((k > 0) ? "R" : "S") + IntegerToString(MathAbs(k)); }
color Col(int k) { return (k == 0) ? InpColP : (k > 0 ? InpColR : InpColS); }
void DrawPeriod(int d, datetime t0, datetime t1, bool current)
{
for(int k = -4; k <= 4; k++)
{
string nm = PFX + IntegerToString(d) + "_" + IntegerToString(k + 4);
double y;
if(!Level(k, d, y))
{
ObjectDelete(0, nm);
ObjectDelete(0, nm + "_lbl");
continue;
}
if(ObjectFind(0, nm) < 0)
{
ObjectCreate(0, nm, OBJ_TREND, 0, t0, y, t1, y);
ObjectSetInteger(0, nm, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, nm, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, nm, OBJPROP_BACK, true);
}
ObjectSetInteger(0, nm, OBJPROP_COLOR, Col(k));
ObjectSetInteger(0, nm, OBJPROP_STYLE, InpStyle);
ObjectMove(0, nm, 0, t0, y);
ObjectMove(0, nm, 1, t1, y);
string lb = nm + "_lbl";
if(current && InpLabels)
{
datetime tl = t1 + 2 * PeriodSeconds(_Period);
if(ObjectFind(0, lb) < 0)
{
ObjectCreate(0, lb, OBJ_TEXT, 0, tl, y);
ObjectSetInteger(0, lb, OBJPROP_ANCHOR, ANCHOR_LEFT);
ObjectSetInteger(0, lb, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, lb, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, lb, OBJPROP_HIDDEN, true);
}
ObjectSetInteger(0, lb, OBJPROP_COLOR, Col(k));
ObjectMove(0, lb, 0, tl, y);
ObjectSetString(0, lb, OBJPROP_TEXT, Tag(k) + " " + DoubleToString(y, _Digits));
}
else
ObjectDelete(0, lb);
}
}
int OnInit()
{
if(InpLevels < 1 || InpLevels > 4 || InpHist < 1 || InpHist > 30)
return INIT_PARAMETERS_INCORRECT;
g_lastPeriod = 0;
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, PFX);
}
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(rates_total < 2)
return 0;
ENUM_TIMEFRAMES tf = BaseTf();
if(PeriodSeconds(_Period) >= PeriodSeconds(tf))
return rates_total; // pivots need a chart timeframe below the pivot period
ArraySetAsSeries(time, true);
datetime cur = iTime(_Symbol, tf, 0);
if(cur == 0)
return 0; // history not loaded yet: try again next tick
bool full = (prev_calculated == 0 || cur != g_lastPeriod);
if(full)
ObjectsDeleteAll(0, PFX);
for(int d = full ? InpHist - 1 : 0; d >= 0; d--)
{
datetime t0 = iTime(_Symbol, tf, d);
if(t0 == 0)
continue;
datetime t1 = (d == 0) ? time[0] : iTime(_Symbol, tf, d - 1) - PeriodSeconds(_Period);
DrawPeriod(d, t0, t1, d == 0);
}
g_lastPeriod = cur;
return rates_total;
}
//+------------------------------------------------------------------+