Cornflower Quant
Posted: Thu Oct 01, 2026 11:36 am
Code: Select all
//+------------------------------------------------------------------+
//| CornflowerQuant_Dashboard.mq4 |
//+---https://www.forexfactory.com/thread/post/15937217#post15937217
#property copyright "CFQ"
#property version "1.00"
#property strict
#property indicator_chart_window
input bool DisplayDashboard = true;
input int XAxis = 10;
input int YAxis = 100;
input int PanelWidth = 330;
input color TextColor = clrDimGray;
input int FontSize = 8;
input int CalcBars = 300;
input int PlotBars = 80;
input bool ShowEMA = true;
input bool ShowBands = true;
input bool ShowZigZag = true;
input bool ShowLevels = true;
input int EMA1Period = 8;
input int EMA2Period = 12;
input int EMA3Period = 24;
input int TrendEMAPeriod = 72;
input int BBPeriod = 14;
input double BBDeviation = 2.0;
input int CCIPeriod = 14;
input double CCILevel = 50.0;
input double CCIOversold = 100.0;
input int PullbackBars = 12;
input int MACDFast = 12;
input int MACDSlow = 26;
input int ZZDepth = 5;
input int ZZMaxSegments = 12;
input int ATRPeriod = 14;
input double BarSizeMult = 2.0;
input int RecentBars = 10;
input double RecentFrac = 0.9;
input int SessionStart = 10;
input int SessionEnd = 22;
string VER = "1.00";
string PFX = "CFQ_";
int RowH = 15;
int gN = 0;
datetime gLastBar = 0;
datetime gDay = 0;
datetime gSigTime = 0;
int gState = 9;
int gZZUsed = 0;
int gPvCnt = 0;
string gZoneTxt = "";
double gO[], gH[], gL[], gC[], gTP[];
datetime gT[];
long gV[];
double gE1[], gE2[], gE3[], gE4[], gMF[], gMS[];
double gBM[], gBU[], gBL[], gCCI[];
double gATR = 0.0;
double gPdH = 0.0, gPdL = 0.0, gPdC = 0.0;
double gCamH4 = 0.0, gCamH3 = 0.0, gCamPP = 0.0, gCamL3 = 0.0, gCamL4 = 0.0;
int gLamL[8], gLamS[8];
int pvShift[200], pvType[200];
double pvPrice[200];
//+------------------------------------------------------------------+
void DelObjs()
{
int i;
string nm;
for(i = ObjectsTotal() - 1; i >= 0; i--)
{
nm = ObjectName(i);
if(StringFind(nm, PFX) == 0) ObjectDelete(0, nm);
}
}
//+------------------------------------------------------------------+
void SetTL(string nm, datetime t1, double p1, datetime t2, double p2, color clr, int w, int st)
{
if(ObjectFind(0, nm) < 0)
{
ObjectCreate(0, nm, OBJ_TREND, 0, t1, p1, t2, p2);
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, clr);
ObjectSetInteger(0, nm, OBJPROP_WIDTH, w);
ObjectSetInteger(0, nm, OBJPROP_STYLE, st);
}
else
{
ObjectMove(0, nm, 0, t1, p1);
ObjectMove(0, nm, 1, t2, p2);
}
}
//+------------------------------------------------------------------+
void PlotSeries(string tag, double &arr[], int lim, color clr, int w)
{
int k;
for(k = 1; k <= lim; k++)
SetTL(PFX + tag + IntegerToString(k), gT[k], arr[k], gT[k - 1], arr[k - 1], clr, w, STYLE_SOLID);
}
//+------------------------------------------------------------------+
void MakeLabel(string nm, int x, int y, int anchor)
{
if(ObjectFind(0, nm) < 0)
{
ObjectCreate(0, nm, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, nm, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, nm, OBJPROP_ANCHOR, anchor);
ObjectSetInteger(0, nm, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, nm, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, nm, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, nm, OBJPROP_FONTSIZE, FontSize);
ObjectSetString(0, nm, OBJPROP_FONT, "Arial");
}
}
//+------------------------------------------------------------------+
void DrawRow(int row, string label, string val, color vc)
{
int y;
string n1, n2;
y = YAxis + row * RowH;
n1 = PFX + "N_" + IntegerToString(row);
n2 = PFX + "V_" + IntegerToString(row);
MakeLabel(n1, XAxis + PanelWidth, y, ANCHOR_LEFT_UPPER);
ObjectSetString(0, n1, OBJPROP_TEXT, label);
ObjectSetInteger(0, n1, OBJPROP_COLOR, TextColor);
MakeLabel(n2, XAxis, y, ANCHOR_RIGHT_UPPER);
ObjectSetString(0, n2, OBJPROP_TEXT, val);
ObjectSetInteger(0, n2, OBJPROP_COLOR, vc);
}
//+------------------------------------------------------------------+
void DrawLamps(int row, string label, string tag, int &lam[])
{
int k, y;
string nm;
y = YAxis + row * RowH;
nm = PFX + "N_" + IntegerToString(row);
MakeLabel(nm, XAxis + PanelWidth, y, ANCHOR_LEFT_UPPER);
ObjectSetString(0, nm, OBJPROP_TEXT, label);
ObjectSetInteger(0, nm, OBJPROP_COLOR, TextColor);
for(k = 0; k < 8; k++)
{
nm = PFX + tag + IntegerToString(k);
MakeLabel(nm, XAxis + PanelWidth - 50 - k * 32, y, ANCHOR_LEFT_UPPER);
ObjectSetString(0, nm, OBJPROP_TEXT, "#");
if(lam[k] == 1) ObjectSetInteger(0, nm, OBJPROP_COLOR, clrLimeGreen);
else ObjectSetInteger(0, nm, OBJPROP_COLOR, clrFireBrick);
}
}
//+------------------------------------------------------------------+
void DrawHeader(int row)
{
int k, y;
string nm;
string hd[8];
hd[0] = "SES"; hd[1] = "E72"; hd[2] = "STR"; hd[3] = "CRS";
hd[4] = "BAR"; hd[5] = "CCI"; hd[6] = "MAC"; hd[7] = "PUL";
y = YAxis + row * RowH;
nm = PFX + "N_" + IntegerToString(row);
MakeLabel(nm, XAxis + PanelWidth, y, ANCHOR_LEFT_UPPER);
ObjectSetString(0, nm, OBJPROP_TEXT, "MATRIX");
ObjectSetInteger(0, nm, OBJPROP_COLOR, TextColor);
for(k = 0; k < 8; k++)
{
nm = PFX + "H_" + IntegerToString(k);
MakeLabel(nm, XAxis + PanelWidth - 50 - k * 32, y, ANCHOR_LEFT_UPPER);
ObjectSetString(0, nm, OBJPROP_TEXT, hd[k]);
ObjectSetInteger(0, nm, OBJPROP_COLOR, TextColor);
}
}
//+------------------------------------------------------------------+
void UpdateZone()
{
string z;
double b;
if(!DisplayDashboard || gCamH4 == 0.0) return;
b = Bid;
if(b >= gCamH4) z = "ABOVE H4";
else if(b >= gCamH3) z = "H3 - H4";
else if(b >= gCamPP) z = "PP - H3";
else if(b >= gCamL3) z = "L3 - PP";
else if(b >= gCamL4) z = "L4 - L3";
else z = "BELOW L4";
if(z != gZoneTxt)
{
gZoneTxt = z;
DrawRow(14, "PRICE ZONE", z, TextColor);
}
}
//+------------------------------------------------------------------+
void CalcEMA(double &dst[], int period)
{
int i;
double kk;
kk = 2.0 / (period + 1.0);
dst[gN - 1] = gC[gN - 1];
for(i = gN - 2; i >= 0; i--)
dst[i] = dst[i + 1] + kk * (gC[i] - dst[i + 1]);
}
//+------------------------------------------------------------------+
void Calc()
{
int i, j, s, k, q, a, nl, nh, lim, cciLim, hr, segs, newState;
double sum, sq, m, md, sd, tr, h, l, c, lvlMax, lvlMin, refLo, refHi;
double r1, r2, r3, hh, ll, vavg, macd1, bias;
double lastLow = 0.0, prevLow = 0.0, lastHigh = 0.0, prevHigh = 0.0;
double cmin, cmax, rng;
bool isH, isL, inS, sizeOK, rangeOK, barOK, hlOK, lhOK;
datetime dT;
string sLow, sHigh, sigStr, nm;
color sigClr;
gN = MathMin(CalcBars, Bars);
if(gN < 120) return;
ArrayResize(gO, gN); ArrayResize(gH, gN); ArrayResize(gL, gN);
ArrayResize(gC, gN); ArrayResize(gTP, gN); ArrayResize(gT, gN);
ArrayResize(gV, gN);
ArrayResize(gE1, gN); ArrayResize(gE2, gN); ArrayResize(gE3, gN);
ArrayResize(gE4, gN); ArrayResize(gMF, gN); ArrayResize(gMS, gN);
ArrayResize(gBM, gN); ArrayResize(gBU, gN); ArrayResize(gBL, gN);
ArrayResize(gCCI, gN);
for(i = 0; i < gN; i++)
{
h = High[i];
l = Low[i];
c = Close[i];
gO[i] = Open[i];
gH[i] = h;
gL[i] = l;
gC[i] = c;
gT[i] = Time[i];
gV[i] = Volume[i];
gTP[i] = (h + l + c) / 3.0;
}
CalcEMA(gE1, EMA1Period);
CalcEMA(gE2, EMA2Period);
CalcEMA(gE3, EMA3Period);
CalcEMA(gE4, TrendEMAPeriod);
CalcEMA(gMF, MACDFast);
CalcEMA(gMS, MACDSlow);
lim = MathMin(PlotBars, gN - BBPeriod - 3);
if(lim < 2) return;
for(s = 0; s <= lim + 1; s++)
{
sum = 0.0;
for(j = 0; j < BBPeriod; j++) sum += gC[s + j];
m = sum / BBPeriod;
sq = 0.0;
for(j = 0; j < BBPeriod; j++) sq += (gC[s + j] - m) * (gC[s + j] - m);
sd = MathSqrt(sq / BBPeriod);
gBM[s] = m;
gBU[s] = m + BBDeviation * sd;
gBL[s] = m - BBDeviation * sd;
}
cciLim = MathMax(PullbackBars, 2) + 1;
for(s = 0; s <= cciLim; s++)
{
sum = 0.0;
for(j = 0; j < CCIPeriod; j++) sum += gTP[s + j];
m = sum / CCIPeriod;
sq = 0.0;
for(j = 0; j < CCIPeriod; j++) sq += MathAbs(gTP[s + j] - m);
md = sq / CCIPeriod;
if(md > 0.0) gCCI[s] = (gTP[s] - m) / (0.015 * md);
else gCCI[s] = 0.0;
}
sum = 0.0;
for(s = 1; s <= ATRPeriod; s++)
{
tr = gH[s] - gL[s];
if(MathAbs(gH[s] - gC[s + 1]) > tr) tr = MathAbs(gH[s] - gC[s + 1]);
if(MathAbs(gL[s] - gC[s + 1]) > tr) tr = MathAbs(gL[s] - gC[s + 1]);
sum += tr;
}
gATR = sum / ATRPeriod;
if(gATR <= 0.0) gATR = Point;
vavg = 0.0;
for(s = 2; s <= 11; s++) vavg += (double)gV[s];
vavg = vavg / 10.0;
dT = iTime(NULL, PERIOD_D1, 0);
if(dT != gDay)
{
gDay = dT;
gPdH = iHigh(NULL, PERIOD_D1, 1);
gPdL = iLow(NULL, PERIOD_D1, 1);
gPdC = iClose(NULL, PERIOD_D1, 1);
rng = gPdH - gPdL;
gCamH4 = gPdC + rng * 1.1 / 2.0;
gCamH3 = gPdC + rng * 1.1 / 4.0;
gCamPP = (gPdH + gPdL + gPdC) / 3.0;
gCamL3 = gPdC - rng * 1.1 / 4.0;
gCamL4 = gPdC - rng * 1.1 / 2.0;
}
gPvCnt = 0;
for(s = gN - 1 - ZZDepth; s >= ZZDepth; s--)
{
isH = true;
isL = true;
for(j = 1; j <= ZZDepth; j++)
{
if(gH[s - j] > gH[s] || gH[s + j] >= gH[s]) isH = false;
if(gL[s - j] < gL[s] || gL[s + j] <= gL[s]) isL = false;
}
if(isH == isL) continue;
if(isH) q = 1; else q = -1;
if(gPvCnt > 0 && pvType[gPvCnt - 1] == q)
{
if(q == 1 && gH[s] > pvPrice[gPvCnt - 1])
{
pvPrice[gPvCnt - 1] = gH[s];
pvShift[gPvCnt - 1] = s;
}
else if(q == -1 && gL[s] < pvPrice[gPvCnt - 1])
{
pvPrice[gPvCnt - 1] = gL[s];
pvShift[gPvCnt - 1] = s;
}
}
else if(gPvCnt < 200)
{
pvType[gPvCnt] = q;
pvShift[gPvCnt] = s;
if(q == 1) pvPrice[gPvCnt] = gH[s]; else pvPrice[gPvCnt] = gL[s];
gPvCnt++;
}
}
nl = 0;
nh = 0;
for(k = gPvCnt - 1; k >= 0 && (nl < 2 || nh < 2); k--)
{
if(pvType[k] == -1)
{
if(nl == 0) lastLow = pvPrice[k];
else if(nl == 1) prevLow = pvPrice[k];
nl++;
}
else
{
if(nh == 0) lastHigh = pvPrice[k];
else if(nh == 1) prevHigh = pvPrice[k];
nh++;
}
}
hlOK = (nl >= 2 && lastLow > prevLow);
lhOK = (nh >= 2 && lastHigh < prevHigh);
if(nl < 2) sLow = "n/a"; else if(hlOK) sLow = "HL"; else sLow = "LL";
if(nh < 2) sHigh = "n/a"; else if(lhOK) sHigh = "LH"; else sHigh = "HH";
hr = TimeHour(gT[0]);
if(SessionStart < SessionEnd) inS = (hr >= SessionStart && hr < SessionEnd);
else inS = (hr >= SessionStart || hr < SessionEnd);
r1 = gH[1] - gL[1];
r2 = gH[2] - gL[2];
r3 = gH[3] - gL[3];
hh = gH[1];
ll = gL[1];
for(s = 2; s <= RecentBars; s++)
{
if(gH[s] > hh) hh = gH[s];
if(gL[s] < ll) ll = gL[s];
}
sizeOK = (r1 <= BarSizeMult * (r2 + r3) / 2.0);
rangeOK = ((hh - ll) > 0.0 && r1 < RecentFrac * (hh - ll));
barOK = (sizeOK && rangeOK);
lvlMax = MathMax(gBM[1], MathMax(gE1[1], gE2[1]));
lvlMin = MathMin(gBM[1], MathMin(gE1[1], gE2[1]));
refLo = MathMin(gO[1], gC[2]);
refHi = MathMax(gO[1], gC[2]);
macd1 = gMF[1] - gMS[1];
cmin = gCCI[1];
cmax = gCCI[1];
for(s = 2; s <= PullbackBars; s++)
{
if(gCCI[s] < cmin) cmin = gCCI[s];
if(gCCI[s] > cmax) cmax = gCCI[s];
}
cmin = cmin;
gLamL[0] = inS ? 1 : 0;
gLamL[1] = (gC[1] > gE4[1]) ? 1 : 0;
gLamL[2] = hlOK ? 1 : 0;
gLamL[3] = (refLo < lvlMin && gC[1] > lvlMax) ? 1 : 0;
gLamL[4] = barOK ? 1 : 0;
gLamL[5] = (gCCI[1] > CCILevel) ? 1 : 0;
gLamL[6] = (macd1 > 0.0) ? 1 : 0;
gLamL[7] = (cmin < -CCIOversold) ? 1 : 0;
gLamS[0] = inS ? 1 : 0;
gLamS[1] = (gC[1] < gE4[1]) ? 1 : 0;
gLamS[2] = lhOK ? 1 : 0;
gLamS[3] = (refHi > lvlMax && gC[1] < lvlMin) ? 1 : 0;
gLamS[4] = barOK ? 1 : 0;
gLamS[5] = (gCCI[1] < -CCILevel) ? 1 : 0;
gLamS[6] = (macd1 < 0.0) ? 1 : 0;
gLamS[7] = (cmax > CCIOversold) ? 1 : 0;
newState = 0;
sum = 0.0;
for(k = 0; k < 8; k++) sum += gLamL[k];
if(sum == 8.0) newState = 1;
else
{
sum = 0.0;
for(k = 0; k < 8; k++) sum += gLamS[k];
if(sum == 8.0) newState = -1;
}
if(newState != gState)
{
gState = newState;
gSigTime = gT[0];
}
if(ShowEMA)
{
PlotSeries("E1_", gE1, lim, clrLimeGreen, 1);
PlotSeries("E2_", gE2, lim, clrMediumOrchid, 1);
PlotSeries("E3_", gE3, lim, clrAqua, 1);
PlotSeries("E4_", gE4, lim, clrRed, 2);
}
if(ShowBands)
{
PlotSeries("BM_", gBM, lim, clrSlateGray, 1);
PlotSeries("BU_", gBU, lim, clrSteelBlue, 1);
PlotSeries("BL_", gBL, lim, clrSteelBlue, 1);
}
if(ShowLevels && gCamH4 != 0.0)
{
SetTL(PFX + "CAM_H4", gT[gN - 1], gCamH4, gT[0], gCamH4, clrOrangeRed, 1, STYLE_DOT);
SetTL(PFX + "CAM_H3", gT[gN - 1], gCamH3, gT[0], gCamH3, clrDarkOrange, 1, STYLE_DOT);
SetTL(PFX + "CAM_PP", gT[gN - 1], gCamPP, gT[0], gCamPP, clrGray, 1, STYLE_DASH);
SetTL(PFX + "CAM_L3", gT[gN - 1], gCamL3, gT[0], gCamL3, clrDodgerBlue, 1, STYLE_DOT);
SetTL(PFX + "CAM_L4", gT[gN - 1], gCamL4, gT[0], gCamL4, clrRoyalBlue, 1, STYLE_DOT);
}
if(ShowZigZag)
{
segs = 0;
a = MathMax(0, gPvCnt - ZZMaxSegments - 1);
for(k = a; k < gPvCnt - 1; k++)
{
SetTL(PFX + "ZZ_" + IntegerToString(segs), gT[pvShift[k]], pvPrice[k],
gT[pvShift[k + 1]], pvPrice[k + 1], clrGoldenrod, 1, STYLE_SOLID);
segs++;
}
if(gPvCnt > 0)
{
SetTL(PFX + "ZZ_" + IntegerToString(segs), gT[pvShift[gPvCnt - 1]], pvPrice[gPvCnt - 1],
gT[0], gC[0], clrGoldenrod, 1, STYLE_DOT);
segs++;
}
for(k = segs; k < gZZUsed; k++) ObjectDelete(0, PFX + "ZZ_" + IntegerToString(k));
gZZUsed = segs;
}
if(DisplayDashboard)
{
bias = (gC[1] - gE4[1]) / gATR;
DrawRow(0, "CORNFLOWER QUANT", "v" + VER, TextColor);
DrawRow(1, "SYMBOL / TF", Symbol() + " / " + IntegerToString(Period()), TextColor);
DrawRow(2, "SESSION " + IntegerToString(SessionStart) + "-" + IntegerToString(SessionEnd),
inS ? "ACTIVE (hr " + IntegerToString(hr) + ")" : "CLOSED (hr " + IntegerToString(hr) + ")",
inS ? clrLimeGreen : clrFireBrick);
DrawRow(3, "EMA " + IntegerToString(EMA1Period) + " / " + IntegerToString(EMA2Period),
DoubleToString(gE1[1], Digits) + " / " + DoubleToString(gE2[1], Digits), TextColor);
DrawRow(4, "EMA " + IntegerToString(EMA3Period) + " / " + IntegerToString(TrendEMAPeriod),
DoubleToString(gE3[1], Digits) + " / " + DoubleToString(gE4[1], Digits), TextColor);
DrawRow(5, "BIAS VS EMA" + IntegerToString(TrendEMAPeriod) + " (ATR)",
DoubleToString(bias, 2) + (bias >= 0.0 ? " UP" : " DOWN"),
bias >= 0.0 ? clrLimeGreen : clrTomato);
DrawRow(6, "STRUCTURE LOWS / HIGHS", sLow + " / " + sHigh, TextColor);
DrawRow(7, "BB MID / UP / LOW",
DoubleToString(gBM[1], Digits) + " / " + DoubleToString(gBU[1], Digits) + " / " + DoubleToString(gBL[1], Digits),
TextColor);
DrawRow(8, "CCI(" + IntegerToString(CCIPeriod) + ") / MACD",
DoubleToString(gCCI[1], 1) + " / " + DoubleToString(macd1, Digits + 1),
(gCCI[1] > CCILevel && macd1 > 0.0) ? clrLimeGreen : ((gCCI[1] < -CCILevel && macd1 < 0.0) ? clrTomato : TextColor));
DrawRow(9, "ATR(" + IntegerToString(ATRPeriod) + ") / VOLUME",
DoubleToString(gATR, Digits) + " / " + IntegerToString((int)gV[1]), TextColor);
DrawRow(10, "BAR FILTER / PULLBACK",
(barOK ? "OK" : "BLOCK") + " / " + DoubleToString(cmin, 0) + " ~ " + DoubleToString(cmax, 0), TextColor);
DrawRow(11, "CAM H4 / H3", DoubleToString(gCamH4, Digits) + " / " + DoubleToString(gCamH3, Digits), TextColor);
DrawRow(12, "CAM PIVOT", DoubleToString(gCamPP, Digits), TextColor);
DrawRow(13, "CAM L3 / L4", DoubleToString(gCamL3, Digits) + " / " + DoubleToString(gCamL4, Digits), TextColor);
gZoneTxt = "";
UpdateZone();
DrawHeader(15);
DrawLamps(16, "LONG", "L_", gLamL);
DrawLamps(17, "SHORT", "S_", gLamS);
if(gState == 1) { sigStr = "BUY"; sigClr = clrLimeGreen; }
else if(gState == -1) { sigStr = "SELL"; sigClr = clrTomato; }
else { sigStr = "WAIT"; sigClr = TextColor; }
DrawRow(18, "SIGNAL", sigStr + " " + TimeToString(gSigTime, TIME_DATE | TIME_MINUTES), sigClr);
}
}
//+------------------------------------------------------------------+
int init()
{
DelObjs();
gLastBar = 0;
gDay = 0;
gSigTime = 0;
gState = 9;
gZZUsed = 0;
gZoneTxt = "";
gCamH4 = 0.0; gCamH3 = 0.0; gCamPP = 0.0; gCamL3 = 0.0; gCamL4 = 0.0;
IndicatorShortName("Cornflower Quant v" + VER);
return(0);
}
//+------------------------------------------------------------------+
int start()
{
datetime t0;
if(Bars < 120) return(0);
t0 = Time[0];
if(t0 != gLastBar)
{
gLastBar = t0;
Calc();
}
else UpdateZone();
return(0);
}
//+------------------------------------------------------------------+
int deinit()
{
DelObjs();
return(0);
}
//+------------------------------------------------------------------+