2
1
포크 0
원본 프로젝트 SahrJohn/RSI-Stoch-MA-EA
RSI-Stoch-MA-EA/Patterncoordinator.mqh

469 lines
13 KiB
MQL5

2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| PatternSystemComplete.mqh |
//| ALL-IN-ONE Pattern Detection System |
//| Single file - Guaranteed to compile with zero dependencies |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
#property copyright "QuarterTheory x VIZION"
#property version "1.00"
2026-01-21 08:24:00 +00:00
#property strict
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
//================ PATTERN ENUMS ==================//
enum ENUM_PATTERN_TYPE
{
PATTERN_NONE,
PATTERN_REVERSAL_BULLISH,
PATTERN_REVERSAL_BEARISH,
PATTERN_CONTINUATION_BULL,
PATTERN_CONTINUATION_BEAR,
PATTERN_INDECISION
};
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
enum ENUM_PATTERN_NAME
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
PATT_HAMMER,
PATT_SHOOTING_STAR,
PATT_DOJI,
PATT_ENGULFING_BULL,
PATT_ENGULFING_BEAR,
PATT_MORNING_STAR,
PATT_EVENING_STAR,
PATT_THREE_WHITE_SOLDIERS,
PATT_THREE_BLACK_CROWS
2026-01-21 07:45:48 +00:00
};
2026-01-21 08:33:11 +00:00
enum ENUM_MARKET_STRUCTURE
{
STRUCTURE_UPTREND,
STRUCTURE_DOWNTREND,
STRUCTURE_RANGING
};
//================ STRUCTURES ==================//
struct PatternSignal
{
ENUM_PATTERN_NAME name;
ENUM_PATTERN_TYPE type;
string name_str;
int strength;
bool generates_warn;
bool generates_praise;
};
struct SwingPoint
{
double price;
datetime time;
bool is_high;
bool is_higher_high;
bool is_lower_high;
bool is_higher_low;
bool is_lower_low;
};
//================ GLOBAL VARIABLES ==================//
PatternSignal g_Patterns[20];
int g_PatternCount = 0;
SwingPoint g_Swings[30];
int g_SwingCount = 0;
ENUM_MARKET_STRUCTURE g_Structure = STRUCTURE_RANGING;
int g_StructureStrength = 0;
2026-01-21 07:45:48 +00:00
int g_TotalWarns = 0;
2026-01-21 08:33:11 +00:00
int g_TotalPraise = 0;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
bool g_ShowMarkers = true;
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| Initialize System |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
bool InitializePatternSystem()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
g_PatternCount = 0;
g_SwingCount = 0;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
Print("✅ Pattern System Initialized");
Print(" - 9 core patterns");
Print(" - Market structure analysis");
2026-01-21 07:45:48 +00:00
return true;
}
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| Main Update Function |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
void UpdatePatternSystem()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
DetectPatterns();
AnalyzeStructure();
GenerateSignals();
2026-01-21 07:45:48 +00:00
}
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| Detect Patterns |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
void DetectPatterns()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
g_PatternCount = 0;
MqlRates rates[];
ArraySetAsSeries(rates, true);
int copied = CopyRates(_Symbol, _Period, 0, 50, rates);
if(copied < 10) return;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
// Check previous closed candle
int idx = 1;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
double o = rates[idx].open;
double h = rates[idx].high;
double l = rates[idx].low;
double c = rates[idx].close;
double body = MathAbs(c - o);
double range = h - l;
double upper_shadow = h - MathMax(o, c);
double lower_shadow = MathMin(o, c) - l;
if(range == 0) return;
// HAMMER - Bullish reversal
if(lower_shadow >= 2 * body && upper_shadow <= 0.3 * body && IsBearTrend(rates, idx))
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
AddPattern(PATT_HAMMER, PATTERN_REVERSAL_BULLISH, "HAMMER", 85, true, false);
2026-01-21 07:45:48 +00:00
}
2026-01-21 08:33:11 +00:00
// SHOOTING STAR - Bearish reversal
if(upper_shadow >= 2 * body && lower_shadow <= 0.3 * body && IsBullTrend(rates, idx))
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
AddPattern(PATT_SHOOTING_STAR, PATTERN_REVERSAL_BEARISH, "SHOOTING_STAR", 85, true, false);
2026-01-21 07:45:48 +00:00
}
2026-01-21 08:33:11 +00:00
// DOJI - Indecision
if(body / range < 0.1)
{
AddPattern(PATT_DOJI, PATTERN_INDECISION, "DOJI", 60, false, false);
}
// Check two-candle patterns
if(copied >= 3)
{
int curr = 1, prev = 2;
double o1 = rates[prev].open, c1 = rates[prev].close;
double o2 = rates[curr].open, c2 = rates[curr].close;
double body1 = MathAbs(c1 - o1);
double body2 = MathAbs(c2 - o2);
// BULLISH ENGULFING
if(c1 < o1 && c2 > o2 && o2 <= c1 && c2 >= o1 && body2 > body1)
{
AddPattern(PATT_ENGULFING_BULL, PATTERN_REVERSAL_BULLISH, "BULLISH_ENGULFING", 90, true, false);
}
// BEARISH ENGULFING
if(c1 > o1 && c2 < o2 && o2 >= c1 && c2 <= o1 && body2 > body1)
{
AddPattern(PATT_ENGULFING_BEAR, PATTERN_REVERSAL_BEARISH, "BEARISH_ENGULFING", 90, true, false);
}
}
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
// Check three-candle patterns
if(copied >= 4)
{
int c1 = 3, c2 = 2, c3 = 1;
// MORNING STAR
if(rates[c1].close < rates[c1].open &&
MathAbs(rates[c2].close - rates[c2].open) < (rates[c1].high - rates[c1].low) * 0.3 &&
rates[c3].close > rates[c3].open &&
rates[c3].close > (rates[c1].open + rates[c1].close) / 2)
{
AddPattern(PATT_MORNING_STAR, PATTERN_REVERSAL_BULLISH, "MORNING_STAR", 95, true, false);
}
// EVENING STAR
if(rates[c1].close > rates[c1].open &&
MathAbs(rates[c2].close - rates[c2].open) < (rates[c1].high - rates[c1].low) * 0.3 &&
rates[c3].close < rates[c3].open &&
rates[c3].close < (rates[c1].open + rates[c1].close) / 2)
{
AddPattern(PATT_EVENING_STAR, PATTERN_REVERSAL_BEARISH, "EVENING_STAR", 95, true, false);
}
// THREE WHITE SOLDIERS
if(rates[c1].close > rates[c1].open &&
rates[c2].close > rates[c2].open &&
rates[c3].close > rates[c3].open &&
rates[c2].close > rates[c1].close &&
rates[c3].close > rates[c2].close)
{
AddPattern(PATT_THREE_WHITE_SOLDIERS, PATTERN_CONTINUATION_BULL, "THREE_WHITE_SOLDIERS", 90, false, true);
}
// THREE BLACK CROWS
if(rates[c1].close < rates[c1].open &&
rates[c2].close < rates[c2].open &&
rates[c3].close < rates[c3].open &&
rates[c2].close < rates[c1].close &&
rates[c3].close < rates[c2].close)
{
AddPattern(PATT_THREE_BLACK_CROWS, PATTERN_CONTINUATION_BEAR, "THREE_BLACK_CROWS", 90, false, true);
}
}
2026-01-21 07:45:48 +00:00
}
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| Analyze Market Structure |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
void AnalyzeStructure()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
MqlRates rates[];
ArraySetAsSeries(rates, true);
int copied = CopyRates(_Symbol, _Period, 0, 100, rates);
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
if(copied < 50) return;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
// Find swing points
g_SwingCount = 0;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
for(int i = 5; i < 50; i++)
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
// Swing high
bool is_high = true;
for(int j = 1; j <= 5; j++)
{
if(rates[i].high <= rates[i-j].high || rates[i].high <= rates[i+j].high)
{
is_high = false;
break;
}
}
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
if(is_high && g_SwingCount < 30)
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
g_Swings[g_SwingCount].price = rates[i].high;
g_Swings[g_SwingCount].time = rates[i].time;
g_Swings[g_SwingCount].is_high = true;
g_SwingCount++;
2026-01-21 07:45:48 +00:00
}
2026-01-21 08:33:11 +00:00
// Swing low
bool is_low = true;
for(int j = 1; j <= 5; j++)
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
if(rates[i].low >= rates[i-j].low || rates[i].low >= rates[i+j].low)
{
is_low = false;
break;
}
}
if(is_low && g_SwingCount < 30)
{
g_Swings[g_SwingCount].price = rates[i].low;
g_Swings[g_SwingCount].time = rates[i].time;
g_Swings[g_SwingCount].is_high = false;
g_SwingCount++;
2026-01-21 07:45:48 +00:00
}
}
2026-01-21 08:33:11 +00:00
// Classify structure
int hh = 0, hl = 0, lh = 0, ll = 0;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
for(int i = 0; i < g_SwingCount - 1; i++)
{
for(int j = i + 1; j < g_SwingCount; j++)
{
if(g_Swings[i].is_high && g_Swings[j].is_high)
{
if(g_Swings[i].price > g_Swings[j].price)
{
hh++;
g_Swings[i].is_higher_high = true;
}
else
{
lh++;
g_Swings[i].is_lower_high = true;
}
break;
}
else if(!g_Swings[i].is_high && !g_Swings[j].is_high)
{
if(g_Swings[i].price > g_Swings[j].price)
{
hl++;
g_Swings[i].is_higher_low = true;
}
else
{
ll++;
g_Swings[i].is_lower_low = true;
}
break;
}
}
}
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
// Determine structure
if(hh >= 2 && hl >= 1)
{
g_Structure = STRUCTURE_UPTREND;
g_StructureStrength = MathMin((hh * 20) + (hl * 15), 100);
}
else if(lh >= 2 && ll >= 1)
{
g_Structure = STRUCTURE_DOWNTREND;
g_StructureStrength = MathMin((lh * 20) + (ll * 15), 100);
}
else
{
g_Structure = STRUCTURE_RANGING;
g_StructureStrength = 30;
}
2026-01-21 07:45:48 +00:00
}
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| Generate Signals |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
void GenerateSignals()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
g_TotalWarns = 0;
g_TotalPraise = 0;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
for(int i = 0; i < g_PatternCount; i++)
{
if(g_Patterns[i].generates_warn)
g_TotalWarns++;
if(g_Patterns[i].generates_praise)
g_TotalPraise++;
if(g_Patterns[i].strength >= 85)
{
string type = g_Patterns[i].generates_warn ? "WARN" :
g_Patterns[i].generates_praise ? "PRAISE" : "NEUTRAL";
Print("🕯️ ", type, " - ", g_Patterns[i].name_str, " [", g_Patterns[i].strength, "%]");
}
}
2026-01-21 07:45:48 +00:00
}
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| Helper Functions |
2026-01-21 07:45:48 +00:00
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
bool IsBullTrend(const MqlRates &rates[], int idx)
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
if(idx + 10 >= ArraySize(rates)) return false;
double fast = 0, slow = 0;
for(int i = idx; i < idx + 5; i++) fast += rates[i].close;
for(int i = idx; i < idx + 10; i++) slow += rates[i].close;
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
return (fast / 5) > (slow / 10);
2026-01-21 07:45:48 +00:00
}
2026-01-21 08:33:11 +00:00
bool IsBearTrend(const MqlRates &rates[], int idx)
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
return !IsBullTrend(rates, idx);
2026-01-21 07:45:48 +00:00
}
2026-01-21 08:33:11 +00:00
void AddPattern(ENUM_PATTERN_NAME name, ENUM_PATTERN_TYPE type, string name_str,
int strength, bool warn, bool praise)
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
if(g_PatternCount >= 20) return;
g_Patterns[g_PatternCount].name = name;
g_Patterns[g_PatternCount].type = type;
g_Patterns[g_PatternCount].name_str = name_str;
g_Patterns[g_PatternCount].strength = strength;
g_Patterns[g_PatternCount].generates_warn = warn;
g_Patterns[g_PatternCount].generates_praise = praise;
g_PatternCount++;
2026-01-21 07:45:48 +00:00
}
//+------------------------------------------------------------------+
//| Public Interface Functions |
//+------------------------------------------------------------------+
int GetTotalWarnCount()
{
return g_TotalWarns;
}
int GetTotalPraiseCount()
{
2026-01-21 08:33:11 +00:00
return g_TotalPraise;
2026-01-21 07:45:48 +00:00
}
2026-01-21 08:33:11 +00:00
bool IsUptrend()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
return g_Structure == STRUCTURE_UPTREND;
}
bool IsDowntrend()
{
return g_Structure == STRUCTURE_DOWNTREND;
}
bool IsRanging()
{
return g_Structure == STRUCTURE_RANGING;
}
int GetStructureStrength()
{
return g_StructureStrength;
}
string GetStructureString()
{
switch(g_Structure)
{
case STRUCTURE_UPTREND: return "UPTREND (HH+HL)";
case STRUCTURE_DOWNTREND: return "DOWNTREND (LH+LL)";
case STRUCTURE_RANGING: return "RANGING";
default: return "UNKNOWN";
}
2026-01-21 07:45:48 +00:00
}
bool HasCriticalWarnings()
{
2026-01-21 08:33:11 +00:00
return g_TotalWarns >= 2;
}
bool ShouldSizeUpTrade()
{
return g_TotalPraise >= 2 && g_StructureStrength > 70;
2026-01-21 07:45:48 +00:00
}
int GetStructureTradeDirection()
{
2026-01-21 08:33:11 +00:00
if(IsUptrend() && g_TotalPraise > g_TotalWarns)
return 1; // Buy
2026-01-21 07:45:48 +00:00
2026-01-21 08:33:11 +00:00
if(IsDowntrend() && g_TotalPraise > g_TotalWarns)
return -1; // Sell
2026-01-21 07:45:48 +00:00
2026-01-21 08:24:00 +00:00
return 0;
2026-01-21 07:45:48 +00:00
}
string GetSignalSummary()
{
string summary = "";
summary += "Structure: " + GetStructureString() + "\n";
2026-01-21 08:33:11 +00:00
summary += "Strength: " + IntegerToString(g_StructureStrength) + "%\n";
summary += "Warns: " + IntegerToString(g_TotalWarns) + "\n";
summary += "Praise: " + IntegerToString(g_TotalPraise) + "\n";
summary += "Patterns Detected: " + IntegerToString(g_PatternCount) + "\n";
2026-01-21 07:45:48 +00:00
return summary;
}
2026-01-21 08:33:11 +00:00
void CleanupPatternSystem()
2026-01-21 07:45:48 +00:00
{
2026-01-21 08:33:11 +00:00
ObjectsDeleteAll(0, "PATTERN_");
Print("🧹 Pattern System cleaned up");
2026-01-21 07:45:48 +00:00
}
//+------------------------------------------------------------------+
2026-01-21 08:33:11 +00:00
//| END OF PATTERN SYSTEM |
//+------------------------------------------------------------------+