//+------------------------------------------------------------------+ //| Seq.mqh | //| Copyright 2026, Allan NiƱal | //| https://www.allanninal.dev/mql5 | //+------------------------------------------------------------------+ //| 9-13 setup and countdown engine, one CLOSED bar per step (no | //| repaint), used by Sequential Countdown. Variant: | //| docs/SPEC.md; tested against tests/reference.py. | //| Buy setup bar: close < close 4 bars earlier; it starts at 1 | //| only after a flip (previous close > the close 4 bars before | //| it); 9 in a row completes it. Perfected: low of bar 8 or 9 <= | //| lows of bars 6 and 7. Its resistance = highest high of the 9. | //| Buy countdown (from setup bar 9): close <= low 2 bars earlier, | //| not necessarily consecutive; 13 needs low <= close of bar 8 | //| (else deferred). Cancelled by a sell setup or a close above | //| its setup's resistance; a new buy setup restarts it. | //| Sell mirrors everything. | //+------------------------------------------------------------------+ // SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0 (see LICENSE) #ifndef SEQ_MQH #define SEQ_MQH #define SQ_N 16 // ring of recent bars //--- The scanner and the engine tests define the full engine: the setup levels, the latest-event record and the //--- countdown readout the scanner shows. Without it the engine is the Free one: the signals of the closed bar only. struct SQState { int cnt; // bars fed; bar k = the k-th fed bar (0-based) double h[SQ_N],l[SQ_N],c[SQ_N]; int bcnt,scnt; // setup counts int bcd,scd; // countdown counts bool b_on,s_on; // countdowns running double b_c8,s_c8; // close of countdown bar 8 int b_defn,s_defn; // bars deferred at 12 in the running countdown double b_lvl,s_lvl; // level of the setup that started the running countdown //--- the last bar int ev_setup; // +1 buy 9, -1 sell 9 bool perf; // that 9 is perfected int ev_cd; // +1 buy 13, -1 sell 13 int defer; // +1/-1: a countdown bar deferred at 12 ("+") int bmark,smark; // countdown number of this bar (0 none) int show_b,show_s; // setup count of this bar (9 on completion) }; void SQInit(SQState &s) { s.cnt=0; s.bcnt=0; s.scnt=0; s.bcd=0; s.scd=0; s.b_on=false; s.s_on=false; s.b_c8=0; s.s_c8=0; s.b_defn=0; s.s_defn=0; s.b_lvl=0; s.s_lvl=0; s.ev_setup=0; s.perf=false; s.ev_cd=0; s.defer=0; s.bmark=0; s.smark=0; s.show_b=0; s.show_s=0; } double SQH(const SQState &s,const int k) { return(s.h[k%SQ_N]); } double SQL(const SQState &s,const int k) { return(s.l[k%SQ_N]); } double SQC(const SQState &s,const int k) { return(s.c[k%SQ_N]); } //--- feed one CLOSED bar; true when it completed a 9 or a 13 bool SQFeed(SQState &s,const double high,const double low,const double close) { int k=s.cnt; s.h[k%SQ_N]=high; s.l[k%SQ_N]=low; s.c[k%SQ_N]=close; s.cnt++; s.ev_setup=0; s.perf=false; s.ev_cd=0; s.defer=0; s.bmark=0; s.smark=0; if(k>=5) { if(close0) s.bcnt++; else if(SQC(s,k-1)>SQC(s,k-5)) s.bcnt=1; } else s.bcnt=0; if(close>SQC(s,k-4)) { if(s.scnt>0) s.scnt++; else if(SQC(s,k-1)=MathMax(SQH(s,k-3),SQH(s,k-2))); double lo=low; for(int j=1; j<9; j++) lo=MathMin(lo,SQL(s,k-j)); s.scnt=0; s.b_on=false; s.bcd=0; s.b_defn=0; s.s_on=true; s.scd=0; s.s_lvl=lo; s.s_defn=0; } } if(k>=2) { if(s.b_on && close>s.b_lvl) { s.b_on=false; s.bcd=0; } // closed above the setup's resistance: cancelled if(s.s_on && close=SQH(s,k-2)) { if(s.scd<12) { s.scd++; s.smark=s.scd; if(s.scd==8) s.s_c8=close; } else if(high>=s.s_c8) { s.scd=13; s.ev_cd=-1; s.s_on=false; s.smark=13; } else { s.defer=-1; s.s_defn++; } } } s.show_b=(s.ev_setup==1 ? 9 : s.bcnt); s.show_s=(s.ev_setup==-1 ? 9 : s.scnt); if(s.ev_cd==1) s.bcd=0; else if(s.ev_cd==-1) s.scd=0; return(s.ev_setup!=0 || s.ev_cd!=0); } //--- countdown shown for a side: the running count, 13 on the bar it completed, else 0 #endif //+------------------------------------------------------------------+