130 lines
No EOL
5.7 KiB
MQL5
130 lines
No EOL
5.7 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| MomentumShiftLiquidity.mqh |
| |
//| Copyright 2026, Concrete Goonies |
| |
//| https://concrete-goonies.web.app |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2026, Concrete Goonies"
| |
#property link "https://concrete-goonies.web.app"
| |
#property version "1.00"
| |
| |
#include "AbstractLiquidity.mqh"
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
class MomentumShiftLiquidity : public AbstractLiquidity {
| |
private:
| |
double CalcLegPercent(double firstLiquidityPrice, double legExtremePrice, double secondLiquidityPrice) {
| |
double leg = MathAbs(legExtremePrice - firstLiquidityPrice);
| |
if(leg <= 0.0)
| |
return -1.0;
| |
| |
return (MathAbs(secondLiquidityPrice - firstLiquidityPrice) / leg) * 100.0;
| |
}
| |
| |
public:
| |
MomentumShiftLiquidity() {}
| |
~MomentumShiftLiquidity() {}
| |
| |
virtual string GetAnalyserName() override {
| |
return "MomentumShiftLiquidity";
| |
}
| |
| |
virtual void OnSwing(TimePrice &swing, bool isHigh) override {
| |
// ======================================================
| |
// 1. Pullback monitoring (if active)
| |
// ======================================================
| |
if(state.pullbackActive) {
| |
// Draw pullback leg
| |
CreateTrendL("PB_" + IntegerToString(state.pullbackSwingCount),
| |
state.pullbackLastPoint, swing, clrOrange);
| |
state.pullbackLastPoint = swing;
| |
state.pullbackSwingCount++;
| |
| |
// Check if swing count exceeded dynamic maxSwingCount
| |
if(state.pullbackSwingCount > configs.momShiftConfigs.maxSwingCount) {
| |
state.pullbackActive = false;
| |
}
| |
// Check for target reach using MomShift tolerance
| |
else if(NearPrice(swing.y, state.pullbackTargetPrice, configs.momShiftConfigs.tolerance)) {
| |
state.pullbackActive = false;
| |
}
| |
// Check for invalidation: price broke above upper level or below lower level
| |
else if(swing.y > state.pullbackUpperLevel || swing.y < state.pullbackLowerLevel) {
| |
state.pullbackActive = false;
| |
}
| |
}/***/
| |
| |
// ======================================================
| |
// 2. Structural pattern detection
| |
// ======================================================
| |
int index = state.m_swings.Size() - 1;
| |
| |
if(state.m_swings.Size() < 5)
| |
return;
| |
| |
ZigzagSwing s1 = state.m_swings.At(index);
| |
ZigzagSwing s2 = state.m_swings.At(index - 1);
| |
ZigzagSwing s3 = state.m_swings.At(index - 2);
| |
ZigzagSwing s4 = state.m_swings.At(index - 3);
| |
ZigzagSwing s5 = state.m_swings.At(index - 4);
| |
| |
double firstlegDiff = CalcLegPercent(s3.point.y, s2.point.y, s1.point.y);
| |
double seclegDiff = CalcLegPercent(s4.point.y, s3.point.y, s2.point.y);
| |
| |
if(isHigh) {
| |
if((s5.point.y > s3.point.y && s1.point.y >= s3.point.y ) &&
| |
(s4.point.y < s2.point.y)//lows
| |
&& firstlegDiff > configs.momShiftConfigs.minPercent && seclegDiff < configs.momShiftConfigs.maxPercent) {
| |
| |
// Draw structural legs
| |
CreateTrendL("MOM_s1", s1.point, s2.point, clrAqua);
| |
CreateTrendL("MOM_s2", s2.point, s3.point, clrAqua);
| |
CreateTrendL("MOM_s3", s3.point, s4.point, clrAqua);
| |
CreateTrendL("MOM_s4", s4.point, s5.point, clrAqua);
| |
| |
// Activate pullback monitoring
| |
state.pullbackActive = true;
| |
state.pullbackTargetPrice = s4.point.y;
| |
| |
// Replaced eqConfigs.tolerance with momShiftConfigs.tolerance
| |
state.pullbackUpperLevel = s1.point.y + configs.momShiftConfigs.tolerance;
| |
state.pullbackLowerLevel = s4.point.y - configs.momShiftConfigs.tolerance;
| |
state.pullbackSwingCount = 0;
| |
| |
state.pullbackLastPoint = s4.point;
| |
| |
MomentumShiftLiquidityEvent* e = new MomentumShiftLiquidityEvent(bar.symbol, bar.tf, BSL, s4.point.x, s4.point.y, bar.bar.LastBarOpen(), s4.point.y);
| |
eventBus.Push(e);
| |
}
| |
}
| |
// --- Bearish structural pattern (EQL / BOS) ---
| |
else {
| |
if((s5.point.y < s3.point.y && s1.point.y <= s3.point.y ) &&
| |
(s4.point.y > s2.point.y)//lows
| |
&& firstlegDiff > configs.momShiftConfigs.minPercent && seclegDiff < configs.momShiftConfigs.maxPercent) {
| |
| |
// Draw structural legs
| |
CreateTrendL("MOM_s1m", s1.point, s2.point, clrAqua);
| |
CreateTrendL("MOM_s2m", s2.point, s3.point, clrAqua);
| |
CreateTrendL("MOM_s3m", s3.point, s4.point, clrAqua);
| |
CreateTrendL("MOM_s4m", s4.point, s5.point, clrAqua);
| |
| |
// Activate pullback monitoring
| |
state.pullbackActive = true;
| |
state.pullbackTargetPrice = s4.point.y;
| |
| |
// Replaced eqConfigs.tolerance with momShiftConfigs.tolerance
| |
state.pullbackLowerLevel = s1.point.y - configs.momShiftConfigs.tolerance;
| |
state.pullbackUpperLevel = s4.point.y + configs.momShiftConfigs.tolerance;
| |
state.pullbackSwingCount = 0;
| |
| |
state.pullbackLastPoint = s4.point;
| |
| |
MomentumShiftLiquidityEvent* e = new MomentumShiftLiquidityEvent(bar.symbol, bar.tf, SSL, s4.point.x, s4.point.y, bar.bar.LastBarOpen(), s4.point.y);
| |
eventBus.Push(e);
| |
}
| |
}
| |
}
| |
};
| |
//+------------------------------------------------------------------+ |