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