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