157 lines
7.2 KiB
MQL5
157 lines
7.2 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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
|
|
|
|
#include "..\..\Expert\WarriorSignal.mqh"
|
|
#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
|