extern MqlRates rates[]; class CFvg{ private: //bool isFvgTapped; struct fvg{ double upperBand; double lowerBand; double range; int flag; bool isFvgTapped; }; //ICollection fvg latestFvg; public: //getters //bool getLatestFvgFlag(); double getLatestFvgLowerBand(); double getLatestFvgUpperBand(); double getLatestFvgRange(); bool getIsLatestFvgFresh(); int isFvg(int index=2); //return the flag of fvg formed or NULL bool update(); bool isFvgTapped(); }; //bool CFvg::getLatestFvgFlag(void){ // // return latestFvg.flag; //} double CFvg::getLatestFvgLowerBand(){ return latestFvg.lowerBand; } double CFvg::getLatestFvgUpperBand(void){ return latestFvg.upperBand; } double CFvg::getLatestFvgRange(){ return latestFvg.range; } bool CFvg::getIsLatestFvgFresh(void){ return latestFvg.isFvgTapped; } //int CFvg::isFvg(/*int &flag*/){ // if(rates[1].highrates[3].high){ //tail not meeting head // //flag=1; //bullish fvg found // return 1; // } // //return NULL;} int CFvg::isFvg(int index=2){ if(rates[index-1].highrates[index+1].high){ //tail not meeting head //flag=1; //bullish fvg found return 1; } return NULL;} bool CFvg::update() { if(isFvgTapped()==true){ latestFvg.isFvgTapped=true; } int flag = isFvg(); if (flag == NULL) return false; // no FVG in current 3-candle window // ── Derive candidate FVG bands from the same candles isFvg() inspects ── // Bearish FVG: impulse drove price down; gap sits between // lowerBand = rates[1].high (top of right candle) // upperBand = rates[3].low (bottom of left candle) // Bullish FVG: impulse drove price up; gap sits between // lowerBand = rates[3].high (top of left candle) // upperBand = rates[1].low (bottom of right candle) double upper, lower; if (flag == -1) { // bearish upper = rates[3].low; lower = rates[1].high; } else { // bullish upper = rates[1].low; lower = rates[3].high; } double newRange = upper - lower; if (newRange <= 0) return false; // degenerate gap — skip // ── Consecutive-FVG guard ──────────────────────────────────────────── // If the candidate has the same direction as the stored latestFvg AND // their price bands overlap, this is the same gap that has simply // extended beyond the standard 3-candle window — not a new FVG. // Registering it again would double-count the same structural feature. if (latestFvg.flag == flag && latestFvg.range > 0) { if(isFvg(3)==true){ if(flag==1){ latestFvg.upperBand=upper; latestFvg.range=latestFvg.upperBand-latestFvg.lowerBand; } else{ //prev bearish fvg latestFvg.lowerBand=lower; latestFvg.range=latestFvg.upperBand-latestFvg.lowerBand; } } //if (bandsOverlap) return false; // same FVG extending — skip } // ── New distinct FVG — populate latestFvg ─────────────────────────── latestFvg.flag = flag; latestFvg.upperBand = upper; latestFvg.lowerBand = lower; latestFvg.range = newRange; latestFvg.isFvgTapped = false; // fresh, untouched gap return true; } bool CFvg::isFvgTapped(void){ bool isTapped=(rates[0].high>latestFvg.upperBand && rates[0].lowlatestFvg.lowerBand && rates[0].low