| //+------------------------------------------------------------------+
|
| //| 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;
|
| }
|
| //+------------------------------------------------------------------+
|