1186 lines
38 KiB
MQL5
1186 lines
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
|