mql5/Shared Projects/ERMT-ML/Modules-ML8x/TechnicalAnalysis_v71.mqh
darashikoh 0fb1bd1b0a Module Integration Summary for External Trade Management
Overview
To fully integrate the enhanced external trade management system, updates are required to 5 out of 7 existing modules. The updates maintain backward compatibility while adding new functionality for external trade handling.
Module Update Requirements
🟢 No Updates Required (2 modules)

TechnicalAnalysis.mqh - Already provides necessary calculations
EntrySystem.mqh - Only handles EA's own entry signals

🟡 Minor Updates (2 modules)

DataTypes.mqh - Add external trade structures and fields
Utilities.mqh - Enhanced logging for external trades

🟠 Moderate Updates (3 modules)

RiskManager.mqh - Enhanced risk enforcement methods
TradeManager.mqh - Improved stop management for externals
Dashboard.mqh - Display external trade information

Integration Steps
Phase 1: Data Structures (DataTypes.mqh)

Add ENUM_EXTERNAL_STATUS enumeration
Extend ManagedTrade structure with external-specific fields
Add ExternalTradeStats structure for metrics
Update DashboardConfig with show_external flag

Key additions:

external_status - Track state of external trade
source_name - Identify where trade came from
stops_modified - Track if we modified the trade
original_sl/tp - Store original values for comparison

Phase 2: Risk Management (RiskManager.mqh)

Add EnforceRiskRulesEnhanced() method
Implement GetExternalExposure() for risk aggregation
Add UpdateExternalStats() for tracking
Enhance ValidateAndAdjustRiskExternal() method

Key features:

Separate risk calculation for external trades
Cache mechanism for performance
Statistical tracking of external positions
Smart risk adjustment without closing trades

Phase 3: Trade Management (TradeManager.mqh)

Add ApplyDefaultStopsEnhanced() with better logic
Implement OverrideExternalStops() with smart override
Create ManageExternalTrade() with different rules
Add ApplyBreakevenExternal() with wider triggers

Key features:

Smart stop override (only improve, never worsen)
Different management rules for external trades
Respect minimum broker distances
Track modification success/failure rates

Phase 4: User Interface (Dashboard.mqh)

Add CreateExternalSection() for display area
Implement UpdateExternalSection() for real-time updates
Add SetCustomText() for flexible display
Create ShowExternalTrades() toggle method

Key features:

Real-time external trade count and risk
Color-coded risk warnings
List of active external positions
Modification statistics display

Phase 5: Logging (Utilities.mqh)

Add LogExternalTrade() for detailed event logging
Create separate CSV log for external trades
Enhance GenerateReportEnhanced() with external section
Add IdentifyTradeSource() for magic number interpretation

Key features:

Separate CSV log for external trade events
Detailed tracking of all modifications
Source identification from magic numbers
Enhanced reporting with external statistics
2025-08-27 14:21:02 +01:00

1186 lines
No EOL
38 KiB
MQL5

//+------------------------------------------------------------------+
//| TechnicalAnalysis_v71.mqh |
//| Enhanced Technical Analysis Module v7.1 |
//| Market Structure, Correlations, Advanced Indicators |
//+------------------------------------------------------------------+
#ifndef TECHNICAL_ANALYSIS_V71_MQH
#define TECHNICAL_ANALYSIS_V71_MQH
#include "DataTypes_v71.mqh"
#include <Math/Stat/Math.mqh>
#include <Indicators/Indicators.mqh>
//+------------------------------------------------------------------+
//| Market Structure |
//+------------------------------------------------------------------+
struct MarketStructure
{
double swing_highs[];
double swing_lows[];
int trend_direction; // 1=up, -1=down, 0=neutral
double trend_strength;
int structure_breaks;
datetime last_break_time;
bool is_ranging;
double range_high;
double range_low;
};
//+------------------------------------------------------------------+
//| Support/Resistance Level |
//+------------------------------------------------------------------+
struct SRLevel
{
double price;
int touches;
double strength;
datetime first_touch;
datetime last_touch;
bool is_broken;
bool is_support;
double volume_at_level;
};
//+------------------------------------------------------------------+
//| Fibonacci Level |
//+------------------------------------------------------------------+
struct FibLevel
{
double level;
double price;
string description;
bool is_touched;
int bounce_count;
};
//+------------------------------------------------------------------+
//| Technical Analysis Class - Enhanced |
//+------------------------------------------------------------------+
class CTechnicalAnalysisV71
{
private:
//--- Indicator handles
int m_atr_handle;
int m_rsi_handle;
int m_macd_handle;
int m_bb_handle;
int m_ma_handles[];
int m_adx_handle;
int m_cci_handle;
int m_stoch_handle;
int m_ichimoku_handle;
//--- Market structure
MarketStructure m_structure;
SRLevel m_sr_levels[];
int m_sr_count;
//--- Correlation tracking
CorrelationMatrix m_correlation_matrix;
datetime m_last_correlation_update;
//--- Multi-timeframe data
struct MTFData
{
ENUM_TIMEFRAMES timeframe;
double trend_direction;
double momentum;
double volatility;
};
MTFData m_mtf_data[];
//--- Pattern detection
bool m_pattern_double_top;
bool m_pattern_double_bottom;
bool m_pattern_head_shoulders;
bool m_pattern_triangle;
//--- Helper methods
void DetectSwings(string symbol, int lookback);
void IdentifyStructure(string symbol);
void FindSRLevels(string symbol);
bool IsSwingHigh(double &highs[], int index, int lookback);
bool IsSwingLow(double &lows[], int index, int lookback);
double CalculateLevelStrength(SRLevel &level, string symbol);
public:
CTechnicalAnalysisV71();
~CTechnicalAnalysisV71();
//--- Initialization
bool Initialize();
bool InitializeEnhanced(int correlation_period);
void Deinitialize();
//--- Market analysis
MarketConditionsV71 AnalyzeMarket(string symbol);
void UpdateMarketStructure(string symbol);
ENUM_MARKET_REGIME IdentifyRegime(string symbol);
//--- Technical indicators
double GetATR(int period, int shift = 0);
double GetRSI(int shift = 0);
double GetMACD(int buffer, int shift = 0);
double GetBB(int buffer, int shift = 0);
double GetMA(int index, int shift = 0);
double GetADX(int shift = 0);
double GetSymbolATR(string symbol, int period);
//--- Support/Resistance
void FindSupportResistance(string symbol, SRLevel &levels[], int &count);
double GetNearestSupport(string symbol, double price);
double GetNearestResistance(string symbol, double price);
bool IsPriceAtLevel(double price, double level, double tolerance);
//--- Fibonacci analysis
void CalculateFibonacci(double high, double low, FibLevel &levels[]);
double GetNearestFibLevel(double price, FibLevel &levels[]);
//--- Market structure
int GetTrendDirection() { return m_structure.trend_direction; }
double GetTrendStrength() { return m_structure.trend_strength; }
bool IsStructureBroken() { return m_structure.structure_breaks > 0; }
bool IsRanging() { return m_structure.is_ranging; }
//--- Correlation analysis
CorrelationMatrix CalculateCorrelationMatrix(string symbols[], int period);
double GetCorrelation(string symbol1, string symbol2, int period = 100);
void UpdateCorrelations(string symbols[]);
//--- Multi-timeframe
void AnalyzeMTF(string symbol, ENUM_TIMEFRAMES timeframes[], int count);
double GetMTFScore(string symbol);
bool IsMTFAligned(string symbol);
//--- Pattern recognition
bool DetectChartPatterns(string symbol);
bool IsDoubleTop() { return m_pattern_double_top; }
bool IsDoubleBottom() { return m_pattern_double_bottom; }
bool IsHeadShoulders() { return m_pattern_head_shoulders; }
//--- Volatility analysis
double GetHistoricalVolatility(string symbol, int period);
double GetImpliedVolatility(string symbol); // Placeholder
double GetVolatilityRank(string symbol, int lookback);
//--- Advanced metrics
double GetHurstExponent(string symbol, int period);
double GetMarketEfficiency(string symbol, int period);
double GetFractalDimension(string symbol, int period);
//--- Pivot points
void GetPivotPoints(string symbol, double &pp, double &r1, double &r2,
double &r3, double &s1, double &s2, double &s3);
void GetCamarillaPivots(string symbol, double &levels[]);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CTechnicalAnalysisV71::CTechnicalAnalysisV71()
{
m_atr_handle = INVALID_HANDLE;
m_rsi_handle = INVALID_HANDLE;
m_macd_handle = INVALID_HANDLE;
m_bb_handle = INVALID_HANDLE;
m_adx_handle = INVALID_HANDLE;
m_cci_handle = INVALID_HANDLE;
m_stoch_handle = INVALID_HANDLE;
m_ichimoku_handle = INVALID_HANDLE;
m_sr_count = 0;
m_last_correlation_update = 0;
//--- Initialize patterns
m_pattern_double_top = false;
m_pattern_double_bottom = false;
m_pattern_head_shoulders = false;
m_pattern_triangle = false;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CTechnicalAnalysisV71::~CTechnicalAnalysisV71()
{
Deinitialize();
}
//+------------------------------------------------------------------+
//| Initialize enhanced version |
//+------------------------------------------------------------------+
bool CTechnicalAnalysisV71::InitializeEnhanced(int correlation_period)
{
//--- Standard initialization
if(!Initialize())
return false;
//--- Additional indicators
m_cci_handle = iCCI(_Symbol, PERIOD_CURRENT, 14, PRICE_TYPICAL);
m_stoch_handle = iStochastic(_Symbol, PERIOD_CURRENT, 14, 3, 3, MODE_SMA, STO_LOWHIGH);
m_ichimoku_handle = iIchimoku(_Symbol, PERIOD_CURRENT, 9, 26, 52);
//--- Multiple MAs for analysis
ArrayResize(m_ma_handles, 5);
m_ma_handles[0] = iMA(_Symbol, PERIOD_CURRENT, 10, 0, MODE_EMA, PRICE_CLOSE);
m_ma_handles[1] = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
m_ma_handles[2] = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE);
m_ma_handles[3] = iMA(_Symbol, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE);
m_ma_handles[4] = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE);
//--- Initialize MTF array
ArrayResize(m_mtf_data, 4);
m_mtf_data[0].timeframe = PERIOD_M5;
m_mtf_data[1].timeframe = PERIOD_M15;
m_mtf_data[2].timeframe = PERIOD_H1;
m_mtf_data[3].timeframe = PERIOD_H4;
//--- Initialize correlation matrix
m_correlation_matrix.period = correlation_period;
m_correlation_matrix.last_update = 0;
Print("TechnicalAnalysisV71 initialized with enhanced features");
return true;
}
//+------------------------------------------------------------------+
//| Standard initialization |
//+------------------------------------------------------------------+
bool CTechnicalAnalysisV71::Initialize()
{
//--- Initialize basic indicators
m_atr_handle = iATR(_Symbol, PERIOD_CURRENT, 14);
m_rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
m_macd_handle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE);
m_bb_handle = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE);
m_adx_handle = iADX(_Symbol, PERIOD_CURRENT, 14);
if(m_atr_handle == INVALID_HANDLE || m_rsi_handle == INVALID_HANDLE ||
m_macd_handle == INVALID_HANDLE || m_bb_handle == INVALID_HANDLE ||
m_adx_handle == INVALID_HANDLE)
{
Print("Failed to initialize technical indicators");
return false;
}
//--- Initialize structure
m_structure.trend_direction = 0;
m_structure.trend_strength = 0;
m_structure.structure_breaks = 0;
m_structure.is_ranging = false;
return true;
}
//+------------------------------------------------------------------+
//| Analyze market conditions |
//+------------------------------------------------------------------+
MarketConditionsV71 CTechnicalAnalysisV71::AnalyzeMarket(string symbol)
{
MarketConditionsV71 conditions;
//--- Update market structure
UpdateMarketStructure(symbol);
//--- Identify regime
conditions.regime = IdentifyRegime(symbol);
//--- Get trend metrics
conditions.trend_strength = m_structure.trend_strength;
conditions.is_trending = (MathAbs(m_structure.trend_direction) > 0.7);
//--- Get volatility
double atr_buffer[1];
if(CopyBuffer(m_atr_handle, 0, 0, 1, atr_buffer) > 0)
{
conditions.volatility = atr_buffer[0] / SymbolInfoDouble(symbol, SYMBOL_BID) * 100;
}
//--- Check if volatile
double vol_rank = GetVolatilityRank(symbol, 100);
conditions.is_volatile = (vol_rank > 70);
//--- Get momentum
double rsi_buffer[1];
if(CopyBuffer(m_rsi_handle, 0, 0, 1, rsi_buffer) > 0)
{
conditions.momentum = (rsi_buffer[0] - 50) / 50; // Normalized -1 to 1
}
//--- Find S/R levels
FindSRLevels(symbol);
//--- Get nearest levels
double current_price = SymbolInfoDouble(symbol, SYMBOL_BID);
conditions.support_level = GetNearestSupport(symbol, current_price);
conditions.resistance_level = GetNearestResistance(symbol, current_price);
//--- Count trend bars
conditions.trend_bars = 0;
double ma_buffer[1];
if(m_ma_handles[1] != INVALID_HANDLE && CopyBuffer(m_ma_handles[1], 0, 0, 1, ma_buffer) > 0)
{
for(int i = 0; i < 20; i++)
{
double close = iClose(symbol, PERIOD_CURRENT, i);
if((m_structure.trend_direction > 0 && close > ma_buffer[0]) ||
(m_structure.trend_direction < 0 && close < ma_buffer[0]))
{
conditions.trend_bars++;
}
else
break;
}
}
//--- Calculate average range
double total_range = 0;
for(int i = 0; i < 20; i++)
{
double high = iHigh(symbol, PERIOD_CURRENT, i);
double low = iLow(symbol, PERIOD_CURRENT, i);
total_range += (high - low);
}
conditions.avg_range = total_range / 20;
//--- Market microstructure
conditions.bid_ask_spread = SymbolInfoInteger(symbol, SYMBOL_SPREAD);
conditions.vwap = 0; // Placeholder
conditions.liquidity_depth = 1.0; // Placeholder
conditions.last_update = TimeCurrent();
return conditions;
}
//+------------------------------------------------------------------+
//| Update market structure |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::UpdateMarketStructure(string symbol)
{
//--- Detect swing points
DetectSwings(symbol, 10);
//--- Identify structure
IdentifyStructure(symbol);
//--- Detect patterns
DetectChartPatterns(symbol);
}
//+------------------------------------------------------------------+
//| Detect swing highs and lows |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::DetectSwings(string symbol, int lookback)
{
//--- Arrays for price data
double highs[], lows[];
int bars = 100;
ArraySetAsSeries(highs, true);
ArraySetAsSeries(lows, true);
if(CopyHigh(symbol, PERIOD_CURRENT, 0, bars, highs) <= 0 ||
CopyLow(symbol, PERIOD_CURRENT, 0, bars, lows) <= 0)
return;
//--- Clear previous swings
ArrayResize(m_structure.swing_highs, 0);
ArrayResize(m_structure.swing_lows, 0);
//--- Find swing points
for(int i = lookback; i < bars - lookback; i++)
{
if(IsSwingHigh(highs, i, lookback))
{
int size = ArraySize(m_structure.swing_highs);
ArrayResize(m_structure.swing_highs, size + 1);
m_structure.swing_highs[size] = highs[i];
}
if(IsSwingLow(lows, i, lookback))
{
int size = ArraySize(m_structure.swing_lows);
ArrayResize(m_structure.swing_lows, size + 1);
m_structure.swing_lows[size] = lows[i];
}
}
}
//+------------------------------------------------------------------+
//| Check if point is swing high |
//+------------------------------------------------------------------+
bool CTechnicalAnalysisV71::IsSwingHigh(double &highs[], int index, int lookback)
{
double high = highs[index];
//--- Check left side
for(int i = index - lookback; i < index; i++)
{
if(i >= 0 && highs[i] >= high)
return false;
}
//--- Check right side
for(int i = index + 1; i <= index + lookback; i++)
{
if(i < ArraySize(highs) && highs[i] > high)
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Check if point is swing low |
//+------------------------------------------------------------------+
bool CTechnicalAnalysisV71::IsSwingLow(double &lows[], int index, int lookback)
{
double low = lows[index];
//--- Check left side
for(int i = index - lookback; i < index; i++)
{
if(i >= 0 && lows[i] <= low)
return false;
}
//--- Check right side
for(int i = index + 1; i <= index + lookback; i++)
{
if(i < ArraySize(lows) && lows[i] < low)
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Identify market structure |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::IdentifyStructure(string symbol)
{
int high_count = ArraySize(m_structure.swing_highs);
int low_count = ArraySize(m_structure.swing_lows);
if(high_count < 2 || low_count < 2)
return;
//--- Check for higher highs and higher lows (uptrend)
bool higher_highs = true;
bool higher_lows = true;
for(int i = 1; i < MathMin(3, high_count); i++)
{
if(m_structure.swing_highs[i] >= m_structure.swing_highs[i-1])
higher_highs = false;
}
for(int i = 1; i < MathMin(3, low_count); i++)
{
if(m_structure.swing_lows[i] >= m_structure.swing_lows[i-1])
higher_lows = false;
}
//--- Check for lower highs and lower lows (downtrend)
bool lower_highs = true;
bool lower_lows = true;
for(int i = 1; i < MathMin(3, high_count); i++)
{
if(m_structure.swing_highs[i] <= m_structure.swing_highs[i-1])
lower_highs = false;
}
for(int i = 1; i < MathMin(3, low_count); i++)
{
if(m_structure.swing_lows[i] <= m_structure.swing_lows[i-1])
lower_lows = false;
}
//--- Determine trend
if(higher_highs && higher_lows)
{
m_structure.trend_direction = 1;
m_structure.trend_strength = 0.8;
}
else if(lower_highs && lower_lows)
{
m_structure.trend_direction = -1;
m_structure.trend_strength = 0.8;
}
else
{
m_structure.trend_direction = 0;
m_structure.trend_strength = 0.2;
}
//--- Check for ranging market
double highest = m_structure.swing_highs[0];
double lowest = m_structure.swing_lows[0];
for(int i = 1; i < MathMin(5, high_count); i++)
{
if(m_structure.swing_highs[i] > highest)
highest = m_structure.swing_highs[i];
}
for(int i = 1; i < MathMin(5, low_count); i++)
{
if(m_structure.swing_lows[i] < lowest)
lowest = m_structure.swing_lows[i];
}
double range = highest - lowest;
double avg_price = (highest + lowest) / 2;
double range_pct = range / avg_price * 100;
//--- Ranging if range is small and no clear trend
if(range_pct < 2 && m_structure.trend_direction == 0)
{
m_structure.is_ranging = true;
m_structure.range_high = highest;
m_structure.range_low = lowest;
}
else
{
m_structure.is_ranging = false;
}
}
//+------------------------------------------------------------------+
//| Find support and resistance levels |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::FindSRLevels(string symbol)
{
//--- Clear previous levels
ArrayResize(m_sr_levels, 0);
m_sr_count = 0;
//--- Get price data
double highs[], lows[], closes[];
int bars = 200;
ArraySetAsSeries(highs, true);
ArraySetAsSeries(lows, true);
ArraySetAsSeries(closes, true);
if(CopyHigh(symbol, PERIOD_CURRENT, 0, bars, highs) <= 0 ||
CopyLow(symbol, PERIOD_CURRENT, 0, bars, lows) <= 0 ||
CopyClose(symbol, PERIOD_CURRENT, 0, bars, closes) <= 0)
return;
//--- Find levels from swing points
for(int i = 0; i < ArraySize(m_structure.swing_highs); i++)
{
SRLevel level;
level.price = m_structure.swing_highs[i];
level.touches = 1;
level.is_support = false;
level.is_broken = false;
level.first_touch = TimeCurrent() - i * PeriodSeconds();
level.last_touch = level.first_touch;
//--- Count touches
for(int j = 0; j < bars; j++)
{
if(IsPriceAtLevel(highs[j], level.price, 10 * SymbolInfoDouble(symbol, SYMBOL_POINT)) ||
IsPriceAtLevel(lows[j], level.price, 10 * SymbolInfoDouble(symbol, SYMBOL_POINT)))
{
level.touches++;
}
}
level.strength = CalculateLevelStrength(level, symbol);
if(level.touches >= 2 && m_sr_count < 20)
{
ArrayResize(m_sr_levels, m_sr_count + 1);
m_sr_levels[m_sr_count] = level;
m_sr_count++;
}
}
//--- Add levels from swing lows
for(int i = 0; i < ArraySize(m_structure.swing_lows); i++)
{
SRLevel level;
level.price = m_structure.swing_lows[i];
level.touches = 1;
level.is_support = true;
level.is_broken = false;
level.first_touch = TimeCurrent() - i * PeriodSeconds();
level.last_touch = level.first_touch;
//--- Count touches
for(int j = 0; j < bars; j++)
{
if(IsPriceAtLevel(highs[j], level.price, 10 * SymbolInfoDouble(symbol, SYMBOL_POINT)) ||
IsPriceAtLevel(lows[j], level.price, 10 * SymbolInfoDouble(symbol, SYMBOL_POINT)))
{
level.touches++;
}
}
level.strength = CalculateLevelStrength(level, symbol);
if(level.touches >= 2 && m_sr_count < 20)
{
ArrayResize(m_sr_levels, m_sr_count + 1);
m_sr_levels[m_sr_count] = level;
m_sr_count++;
}
}
}
//+------------------------------------------------------------------+
//| Calculate level strength |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::CalculateLevelStrength(SRLevel &level, string symbol)
{
double strength = 0;
//--- More touches = stronger level
strength += level.touches * 0.2;
//--- Recent touches are more important
double time_factor = 1.0 - (TimeCurrent() - level.last_touch) / (86400 * 30); // 30 days
strength += time_factor * 0.3;
//--- Volume at level (simplified)
strength += 0.2;
//--- Round number bonus
double round_distance = MathMod(level.price, 100 * SymbolInfoDouble(symbol, SYMBOL_POINT));
if(round_distance < 10 * SymbolInfoDouble(symbol, SYMBOL_POINT))
strength += 0.3;
return MathMin(1.0, strength);
}
//+------------------------------------------------------------------+
//| Check if price is at level |
//+------------------------------------------------------------------+
bool CTechnicalAnalysisV71::IsPriceAtLevel(double price, double level, double tolerance)
{
return MathAbs(price - level) <= tolerance;
}
//+------------------------------------------------------------------+
//| Get nearest support level |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetNearestSupport(string symbol, double price)
{
double nearest = 0;
double min_distance = DBL_MAX;
for(int i = 0; i < m_sr_count; i++)
{
if(m_sr_levels[i].price < price && m_sr_levels[i].is_support)
{
double distance = price - m_sr_levels[i].price;
if(distance < min_distance)
{
min_distance = distance;
nearest = m_sr_levels[i].price;
}
}
}
return nearest;
}
//+------------------------------------------------------------------+
//| Get nearest resistance level |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetNearestResistance(string symbol, double price)
{
double nearest = 0;
double min_distance = DBL_MAX;
for(int i = 0; i < m_sr_count; i++)
{
if(m_sr_levels[i].price > price && !m_sr_levels[i].is_support)
{
double distance = m_sr_levels[i].price - price;
if(distance < min_distance)
{
min_distance = distance;
nearest = m_sr_levels[i].price;
}
}
}
return nearest;
}
//+------------------------------------------------------------------+
//| Identify market regime |
//+------------------------------------------------------------------+
ENUM_MARKET_REGIME CTechnicalAnalysisV71::IdentifyRegime(string symbol)
{
//--- Get ADX for trend strength
double adx_buffer[1];
double adx_value = 0;
if(CopyBuffer(m_adx_handle, 0, 0, 1, adx_buffer) > 0)
adx_value = adx_buffer[0];
//--- Get volatility
double volatility = GetHistoricalVolatility(symbol, 20);
//--- Strong trend
if(adx_value > 40)
{
if(m_structure.trend_direction > 0)
return REGIME_TRENDING_UP;
else if(m_structure.trend_direction < 0)
return REGIME_TRENDING_DOWN;
}
//--- Ranging market
if(m_structure.is_ranging || adx_value < 20)
{
if(volatility > 0.02)
return REGIME_VOLATILE;
else
return REGIME_RANGING;
}
//--- Moderate trend
if(adx_value > 20 && adx_value <= 40)
{
if(m_structure.trend_direction > 0)
return REGIME_TRENDING_UP;
else if(m_structure.trend_direction < 0)
return REGIME_TRENDING_DOWN;
}
//--- Low volatility
if(volatility < 0.005)
return REGIME_QUIET;
//--- Check for regime change
static ENUM_MARKET_REGIME last_regime = REGIME_RANGING;
ENUM_MARKET_REGIME current_regime = REGIME_RANGING;
if(last_regime != current_regime)
{
last_regime = current_regime;
return REGIME_TRANSITIONING;
}
return current_regime;
}
//+------------------------------------------------------------------+
//| Calculate correlation matrix |
//+------------------------------------------------------------------+
CorrelationMatrix CTechnicalAnalysisV71::CalculateCorrelationMatrix(string symbols[], int period)
{
CorrelationMatrix matrix;
int symbol_count = ArraySize(symbols);
//--- Initialize matrix
ArrayResize(matrix.symbols, symbol_count);
ArrayResize(matrix.matrix, symbol_count);
for(int i = 0; i < symbol_count; i++)
{
matrix.symbols[i] = symbols[i];
ArrayResize(matrix.matrix[i], symbol_count);
}
matrix.period = period;
matrix.last_update = TimeCurrent();
//--- Calculate correlations
for(int i = 0; i < symbol_count; i++)
{
for(int j = i; j < symbol_count; j++)
{
if(i == j)
{
matrix.matrix[i][j] = 1.0;
}
else
{
double corr = GetCorrelation(symbols[i], symbols[j], period);
matrix.matrix[i][j] = corr;
matrix.matrix[j][i] = corr; // Symmetric
}
}
}
m_correlation_matrix = matrix;
m_last_correlation_update = TimeCurrent();
return matrix;
}
//+------------------------------------------------------------------+
//| Calculate correlation between two symbols |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetCorrelation(string symbol1, string symbol2, int period)
{
//--- Get returns for both symbols
double returns1[], returns2[];
ArrayResize(returns1, period);
ArrayResize(returns2, period);
for(int i = 1; i <= period; i++)
{
double close1_curr = iClose(symbol1, PERIOD_H1, i-1);
double close1_prev = iClose(symbol1, PERIOD_H1, i);
double close2_curr = iClose(symbol2, PERIOD_H1, i-1);
double close2_prev = iClose(symbol2, PERIOD_H1, i);
if(close1_prev > 0 && close2_prev > 0)
{
returns1[i-1] = (close1_curr - close1_prev) / close1_prev;
returns2[i-1] = (close2_curr - close2_prev) / close2_prev;
}
}
//--- Calculate correlation coefficient
double mean1 = 0, mean2 = 0;
for(int i = 0; i < period; i++)
{
mean1 += returns1[i];
mean2 += returns2[i];
}
mean1 /= period;
mean2 /= period;
double cov = 0, var1 = 0, var2 = 0;
for(int i = 0; i < period; i++)
{
cov += (returns1[i] - mean1) * (returns2[i] - mean2);
var1 += MathPow(returns1[i] - mean1, 2);
var2 += MathPow(returns2[i] - mean2, 2);
}
if(var1 > 0 && var2 > 0)
return cov / MathSqrt(var1 * var2);
return 0;
}
//+------------------------------------------------------------------+
//| Detect chart patterns |
//+------------------------------------------------------------------+
bool CTechnicalAnalysisV71::DetectChartPatterns(string symbol)
{
//--- Reset patterns
m_pattern_double_top = false;
m_pattern_double_bottom = false;
m_pattern_head_shoulders = false;
m_pattern_triangle = false;
int high_count = ArraySize(m_structure.swing_highs);
int low_count = ArraySize(m_structure.swing_lows);
if(high_count < 2 || low_count < 2)
return false;
//--- Double top detection
if(high_count >= 2)
{
double high1 = m_structure.swing_highs[0];
double high2 = m_structure.swing_highs[1];
double tolerance = high1 * 0.002; // 0.2% tolerance
if(MathAbs(high1 - high2) < tolerance)
{
m_pattern_double_top = true;
}
}
//--- Double bottom detection
if(low_count >= 2)
{
double low1 = m_structure.swing_lows[0];
double low2 = m_structure.swing_lows[1];
double tolerance = low1 * 0.002;
if(MathAbs(low1 - low2) < tolerance)
{
m_pattern_double_bottom = true;
}
}
//--- Head and shoulders (simplified)
if(high_count >= 3)
{
double left_shoulder = m_structure.swing_highs[2];
double head = m_structure.swing_highs[1];
double right_shoulder = m_structure.swing_highs[0];
if(head > left_shoulder && head > right_shoulder &&
MathAbs(left_shoulder - right_shoulder) < left_shoulder * 0.002)
{
m_pattern_head_shoulders = true;
}
}
return (m_pattern_double_top || m_pattern_double_bottom || m_pattern_head_shoulders);
}
//+------------------------------------------------------------------+
//| Get historical volatility |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetHistoricalVolatility(string symbol, int period)
{
double returns[];
ArrayResize(returns, period);
//--- Calculate returns
for(int i = 1; i <= period; i++)
{
double close_curr = iClose(symbol, PERIOD_H1, i-1);
double close_prev = iClose(symbol, PERIOD_H1, i);
if(close_prev > 0)
returns[i-1] = MathLog(close_curr / close_prev);
}
//--- Calculate standard deviation
double mean = 0;
for(int i = 0; i < period; i++)
mean += returns[i];
mean /= period;
double variance = 0;
for(int i = 0; i < period; i++)
variance += MathPow(returns[i] - mean, 2);
variance /= period;
//--- Annualize (assuming hourly data)
return MathSqrt(variance) * MathSqrt(24 * 252);
}
//+------------------------------------------------------------------+
//| Get volatility rank |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetVolatilityRank(string symbol, int lookback)
{
//--- Calculate current volatility
double current_vol = GetHistoricalVolatility(symbol, 20);
//--- Calculate volatility over lookback period
double vol_array[];
ArrayResize(vol_array, lookback);
for(int i = 0; i < lookback; i++)
{
//--- Simplified: use ATR as proxy
double atr = iATR(symbol, PERIOD_H1, 14, i);
double price = iClose(symbol, PERIOD_H1, i);
if(price > 0)
vol_array[i] = atr / price;
}
//--- Count how many periods had lower volatility
int lower_count = 0;
for(int i = 0; i < lookback; i++)
{
if(vol_array[i] < current_vol)
lower_count++;
}
//--- Return percentile rank
return (double)lower_count / lookback * 100;
}
//+------------------------------------------------------------------+
//| Calculate Fibonacci levels |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::CalculateFibonacci(double high, double low, FibLevel &levels[])
{
double range = high - low;
//--- Standard Fibonacci levels
ArrayResize(levels, 9);
levels[0].level = 0.0;
levels[0].price = low;
levels[0].description = "0.0%";
levels[1].level = 0.236;
levels[1].price = low + range * 0.236;
levels[1].description = "23.6%";
levels[2].level = 0.382;
levels[2].price = low + range * 0.382;
levels[2].description = "38.2%";
levels[3].level = 0.5;
levels[3].price = low + range * 0.5;
levels[3].description = "50.0%";
levels[4].level = 0.618;
levels[4].price = low + range * 0.618;
levels[4].description = "61.8%";
levels[5].level = 0.786;
levels[5].price = low + range * 0.786;
levels[5].description = "78.6%";
levels[6].level = 1.0;
levels[6].price = high;
levels[6].description = "100.0%";
levels[7].level = 1.272;
levels[7].price = low + range * 1.272;
levels[7].description = "127.2%";
levels[8].level = 1.618;
levels[8].price = low + range * 1.618;
levels[8].description = "161.8%";
//--- Initialize other fields
for(int i = 0; i < 9; i++)
{
levels[i].is_touched = false;
levels[i].bounce_count = 0;
}
}
//+------------------------------------------------------------------+
//| Get multi-timeframe score |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetMTFScore(string symbol)
{
double score = 0;
int aligned = 0;
//--- Check each timeframe
for(int i = 0; i < ArraySize(m_mtf_data); i++)
{
//--- Get trend for timeframe
int ma_handle = iMA(symbol, m_mtf_data[i].timeframe, 20, 0, MODE_EMA, PRICE_CLOSE);
double ma_buffer[2];
if(CopyBuffer(ma_handle, 0, 0, 2, ma_buffer) > 0)
{
double current_price = iClose(symbol, m_mtf_data[i].timeframe, 0);
//--- Determine trend
if(current_price > ma_buffer[0] && ma_buffer[0] > ma_buffer[1])
{
m_mtf_data[i].trend_direction = 1;
aligned++;
}
else if(current_price < ma_buffer[0] && ma_buffer[0] < ma_buffer[1])
{
m_mtf_data[i].trend_direction = -1;
aligned++;
}
else
{
m_mtf_data[i].trend_direction = 0;
}
}
IndicatorRelease(ma_handle);
}
//--- Calculate alignment score
score = (double)aligned / ArraySize(m_mtf_data);
//--- Check if all aligned in same direction
bool same_direction = true;
double first_direction = m_mtf_data[0].trend_direction;
for(int i = 1; i < ArraySize(m_mtf_data); i++)
{
if(m_mtf_data[i].trend_direction != first_direction)
{
same_direction = false;
break;
}
}
if(same_direction && aligned == ArraySize(m_mtf_data))
score = 1.0;
return score;
}
//+------------------------------------------------------------------+
//| Get pivot points |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::GetPivotPoints(string symbol, double &pp, double &r1, double &r2,
double &r3, double &s1, double &s2, double &s3)
{
//--- Get previous day's data
double high = iHigh(symbol, PERIOD_D1, 1);
double low = iLow(symbol, PERIOD_D1, 1);
double close = iClose(symbol, PERIOD_D1, 1);
//--- Calculate pivot point
pp = (high + low + close) / 3;
//--- Calculate support and resistance levels
r1 = 2 * pp - low;
s1 = 2 * pp - high;
r2 = pp + (high - low);
s2 = pp - (high - low);
r3 = high + 2 * (pp - low);
s3 = low - 2 * (high - pp);
}
//+------------------------------------------------------------------+
//| Get ATR value |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetATR(int period, int shift)
{
double buffer[1];
if(CopyBuffer(m_atr_handle, 0, shift, 1, buffer) > 0)
return buffer[0];
return 0;
}
//+------------------------------------------------------------------+
//| Get symbol-specific ATR |
//+------------------------------------------------------------------+
double CTechnicalAnalysisV71::GetSymbolATR(string symbol, int period)
{
int handle = iATR(symbol, PERIOD_CURRENT, period);
if(handle == INVALID_HANDLE)
return 0;
double buffer[1];
if(CopyBuffer(handle, 0, 0, 1, buffer) > 0)
{
IndicatorRelease(handle);
return buffer[0];
}
IndicatorRelease(handle);
return 0;
}
//+------------------------------------------------------------------+
//| Deinitialize indicators |
//+------------------------------------------------------------------+
void CTechnicalAnalysisV71::Deinitialize()
{
if(m_atr_handle != INVALID_HANDLE) IndicatorRelease(m_atr_handle);
if(m_rsi_handle != INVALID_HANDLE) IndicatorRelease(m_rsi_handle);
if(m_macd_handle != INVALID_HANDLE) IndicatorRelease(m_macd_handle);
if(m_bb_handle != INVALID_HANDLE) IndicatorRelease(m_bb_handle);
if(m_adx_handle != INVALID_HANDLE) IndicatorRelease(m_adx_handle);
if(m_cci_handle != INVALID_HANDLE) IndicatorRelease(m_cci_handle);
if(m_stoch_handle != INVALID_HANDLE) IndicatorRelease(m_stoch_handle);
if(m_ichimoku_handle != INVALID_HANDLE) IndicatorRelease(m_ichimoku_handle);
for(int i = 0; i < ArraySize(m_ma_handles); i++)
{
if(m_ma_handles[i] != INVALID_HANDLE)
IndicatorRelease(m_ma_handles[i]);
}
}
#endif // TECHNICAL_ANALYSIS_V71_MQH