2026-09-11 06:16:08 -04:00 | | | //+------------------------------------------------------------------+
|
| | | //| SignalWyckoffStructure.mqh |
|
| | | //| AnimateDread |
|
| | | //| |
|
| | | //| ADWyckoffFailedStructure + ADWyckoffSignificantBarInversion as |
|
| | | //| one classic vote module. |
|
| | | //| |
|
| | | //| Both indicators publish a SIGNED QUALITY on buffer 0, and this |
|
| | | //| module reads that rather than re-deriving a direction from the |
|
| | | //| flag buffers. That is a deliberate choice, because the flag names |
|
| | | //| are a trap: |
|
| | | //| |
|
| | | //| BullishStructuralFailure -> signedValue += quality -> BULLISH |
|
| | | //| "higher low, no weakness" - it is the DOWN leg that failed. |
|
| | | //| Read as "a bullish structure failed" it inverts the signal. |
|
| | | //| FailedDistribution -> signedValue += quality -> BULLISH |
|
| | | //| "breakdown failed" |
|
| | | //| FailedAccumulation -> signedValue -= quality -> BEARISH |
|
| | | //| "breakout failed" |
|
| | | //| |
|
| | | //| (ADWyckoffFailedStructure.mq5:332-338.) The indicator also makes |
|
| | | //| its two structural flags mutually exclusive precisely so the |
|
| | | //| signed value cannot net to zero - a defect it fixed in v2.0. Using |
|
| | | //| buffer 0 inherits that arbitration instead of re-implementing it |
|
| | | //| here and getting a different answer. |
|
| | | //| |
|
| | | //| The magnitudes are the indicators' own confidence and are carried |
|
| | | //| through: FailedStructure clamps to +-2.5, SignificantBarInversion |
|
| | | //| to +-2.0. Both are scaled to the pattern weight rather than |
|
| | | //| flattened to a flag. |
|
| | | //+------------------------------------------------------------------+
|
| | | #ifndef WARRIOR_SIGNALWYCKOFFSTRUCTURE_MQH
|
| | | #define WARRIOR_SIGNALWYCKOFFSTRUCTURE_MQH
|
| | |
|
2026-09-13 14:32:28 -04:00 | | | #include "..\..\Expert\WarriorSignal.mqh"
|
2026-09-11 06:16:08 -04:00 | | | #include "WyckoffFeed.mqh"
|
| | |
|
| | | //--- The clamps the two indicators apply to their signed quality. Named because they are the
|
| | | //--- denominators that turn a quality into a fraction of a pattern weight; a wrong one here silently
|
| | | //--- rescales the vote rather than breaking it.
|
| | | #define WYK_FAIL_QUALITY_MAX 2.5
|
| | | #define WYK_SBI_QUALITY_MAX 2.0
|
| | |
|
| | | class CSignalWyckoffStructure : public CWarriorSignal
|
| | | {
|
| | | protected:
|
| | | int m_lookback;
|
| | | int m_zigzag;
|
| | | //--- pattern weights (0-100)
|
| | | int m_pattern_0; // structural failure / failed breakout, scaled by its quality
|
| | | int m_pattern_1; // significant bar with a control flip - the strongest SBI case
|
| | | int m_pattern_2; // significant bar alone, scaled by its quality
|
| | |
|
| | | public:
|
| | | CSignalWyckoffStructure(void);
|
| | | ~CSignalWyckoffStructure(void) {}
|
| | | void Lookback(const int v) { m_lookback = v; }
|
| | | void ZigZag(const int v) { m_zigzag = v; }
|
| | | void Pattern_0(const int v) { m_pattern_0 = v; }
|
| | | void Pattern_1(const int v) { m_pattern_1 = v; }
|
| | | void Pattern_2(const int v) { m_pattern_2 = v; }
|
| | | virtual void ApplyPatternWeight(int patternNumber, int weight);
|
| | | virtual bool InitIndicators(CIndicators *indicators);
|
| | | virtual int LongCondition(void) { return Condition(+1); }
|
| | | virtual int ShortCondition(void) { return Condition(-1); }
|
| | |
|
| | | protected:
|
| | | int Condition(const int dir);
|
| | | //--- Names the pattern for the journal; see the note in SignalWyckoffEvent.mqh.
|
| | | void Note(const int pattern, const int dir)
|
| | | {
|
| | | m_active_pattern = "Pattern_" + IntegerToString(pattern);
|
| | | m_active_direction = (dir > 0) ? "Buy" : "Sell";
|
| | | }
|
| | | //--- quality -> 0..weight, saturating at the indicator's own clamp
|
| | | int Scaled(const double quality, const double clamp, const int weight)
|
| | | {
|
| | | const double f = MathMin(MathAbs(quality) / clamp, 1.0);
|
| | | return (int)MathRound(weight * f);
|
| | | }
|
| | | };
|
| | | //+------------------------------------------------------------------+
|
| | | CSignalWyckoffStructure::CSignalWyckoffStructure(void) :
|
| | | m_lookback(50), m_zigzag(3),
|
| | | m_pattern_0(55), m_pattern_1(40), m_pattern_2(25)
|
| | | {
|
| | | m_id = "WYKST";
|
| | | m_pattern_count = 3;
|
| | | m_used_series = USE_SERIES_OPEN + USE_SERIES_HIGH + USE_SERIES_LOW + USE_SERIES_CLOSE
|
| | | + USE_SERIES_TICK_VOLUME;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | void CSignalWyckoffStructure::ApplyPatternWeight(int patternNumber, int weight)
|
| | | {
|
| | | switch(patternNumber)
|
| | | {
|
| | | case 0: Pattern_0(weight); break;
|
| | | case 1: Pattern_1(weight); break;
|
| | | case 2: Pattern_2(weight); break;
|
| | | default: break;
|
| | | }
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | bool CSignalWyckoffStructure::InitIndicators(CIndicators *indicators)
|
| | | {
|
| | | if(indicators == NULL)
|
| | | return(false);
|
| | | if(!CWarriorSignal::InitIndicators(indicators))
|
| | | return(false);
|
| | | if(!WyckoffFeedEnsure(indicators, m_symbol.Name(), m_period, m_lookback, m_zigzag))
|
| | | {
|
| | | PrintFormat("%s: WYCKOFF FEED FAILED - %s. Refusing init rather than voting zeros, which are"
|
| | | " indistinguishable from 'no structure here'.", __FUNCTION__, g_wyckoffFeed.Why());
|
| | | return(false);
|
| | | }
|
| | | return(true);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | int CSignalWyckoffStructure::Condition(const int dir)
|
| | | {
|
| | | if(!g_wyckoffFeed.Ok())
|
| | | return 0;
|
| | |
|
| | | //--- 0: FAILED STRUCTURE. One signed number covering all four of the indicator's cases, already
|
| | | //--- arbitrated by it. Sign is the direction the failure hands control to.
|
| | | const double fail = g_wyckoffFeed.FailValue();
|
| | | if(fail != 0.0 && ((dir > 0) ? (fail > 0.0) : (fail < 0.0)))
|
| | | {
|
| | | Note(0, dir);
|
| | | return Scaled(fail, WYK_FAIL_QUALITY_MAX, m_pattern_0);
|
| | | }
|
| | |
|
| | | //--- 1 and 2: THE SIGNIFICANT BAR. A control FLIP is the book's stronger statement - the bar did
|
| | | //--- not merely show intent, it took control - so it is tested first and weighted above the bar
|
| | | //--- on its own. Quality is signed the same way (+ bull / - bear).
|
| | | const double q = g_wyckoffFeed.BarQuality();
|
| | | if(q != 0.0 && ((dir > 0) ? (q > 0.0) : (q < 0.0)))
|
| | | {
|
| | | const bool flip = (dir > 0) ? (g_wyckoffFeed.BullFlip() != 0.0)
|
| | | : (g_wyckoffFeed.BearFlip() != 0.0);
|
| | | if(flip)
|
| | | {
|
| | | Note(1, dir);
|
| | | return Scaled(q, WYK_SBI_QUALITY_MAX, m_pattern_1);
|
| | | }
|
| | | const bool sig = (dir > 0) ? (g_wyckoffFeed.BullBar() != 0.0)
|
| | | : (g_wyckoffFeed.BearBar() != 0.0);
|
| | | if(sig)
|
| | | {
|
| | | Note(2, dir);
|
| | | return Scaled(q, WYK_SBI_QUALITY_MAX, m_pattern_2);
|
| | | }
|
| | | }
|
| | |
|
| | | return 0;
|
| | | }
|
| | | #endif // WARRIOR_SIGNALWYCKOFFSTRUCTURE_MQH
|