mql5/Include/MarkovAnalysis.mqh

121 lines
4.8 KiB
MQL5
Raw Permalink Normal View History

2026-03-03 13:52:15 +00:00
//+------------------------------------------------------------------+
//| MarkovAnalysis.mqh |
//| Copyright 2024, Trading Agent |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Trading Agent"
#property link "https://www.mql5.com"
#property strict
// Define States
enum ENUM_MARKOV_STATE
{
STATE_STRONG_BEAR = 0, // Strong Bearish
STATE_WEAK_BEAR = 1, // Weak Bearish
STATE_NEUTRAL = 2, // Neutral/Doji
STATE_WEAK_BULL = 3, // Weak Bullish
STATE_STRONG_BULL = 4, // Strong Bullish
STATE_COUNT = 5
};
//+------------------------------------------------------------------+
//| Class CMarkovChain |
//+------------------------------------------------------------------+
class CMarkovChain
{
private:
double m_matrix[STATE_COUNT][STATE_COUNT]; // Transition Counts
int m_total_transitions[STATE_COUNT]; // Total exits from each state
ENUM_MARKOV_STATE m_last_state;
double m_threshold_pct; // Percentage of ADR or similar to define "Strong"
public:
CMarkovChain(double threshold_pct = 0.5);
~CMarkovChain() {}
void Reset();
void AddTransition(ENUM_MARKOV_STATE from, ENUM_MARKOV_STATE to);
ENUM_MARKOV_STATE CalculateState(double open, double high, double low, double close, double point);
double GetProbability(ENUM_MARKOV_STATE from, ENUM_MARKOV_STATE to);
void GetProbabilities(ENUM_MARKOV_STATE from, double &probs[]);
ENUM_MARKOV_STATE GetLastState() { return m_last_state; }
void SetLastState(ENUM_MARKOV_STATE state) { m_last_state = state; }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CMarkovChain::CMarkovChain(double threshold_pct)
{
m_threshold_pct = threshold_pct;
Reset();
}
//+------------------------------------------------------------------+
//| Reset Matrix |
//+------------------------------------------------------------------+
void CMarkovChain::Reset()
{
ArrayFill(m_matrix, 0, STATE_COUNT * STATE_COUNT, 0);
ArrayFill(m_total_transitions, 0, STATE_COUNT, 0);
m_last_state = STATE_NEUTRAL;
}
//+------------------------------------------------------------------+
//| Add a transition to the matrix |
//+------------------------------------------------------------------+
void CMarkovChain::AddTransition(ENUM_MARKOV_STATE from, ENUM_MARKOV_STATE to)
{
if(from < 0 || from >= STATE_COUNT || to < 0 || to >= STATE_COUNT) return;
m_matrix[from][to]++;
m_total_transitions[from]++;
}
//+------------------------------------------------------------------+
//| Calculate state from OHLC |
//+------------------------------------------------------------------+
ENUM_MARKOV_STATE CMarkovChain::CalculateState(double open, double high, double low, double close, double point)
{
double body = close - open;
double range = high - low;
if(MathAbs(body) < 10 * point) return STATE_NEUTRAL; // Very small body
// We'll use a simple fixed threshold for now, can be improved with volatility scaling
double threshold = 50 * point;
if(body > 0)
{
return (body > threshold) ? STATE_STRONG_BULL : STATE_WEAK_BULL;
}
else
{
return (MathAbs(body) > threshold) ? STATE_STRONG_BEAR : STATE_WEAK_BEAR;
}
}
//+------------------------------------------------------------------+
//| Get probability of transition |
//+------------------------------------------------------------------+
double CMarkovChain::GetProbability(ENUM_MARKOV_STATE from, ENUM_MARKOV_STATE to)
{
if(from < 0 || from >= STATE_COUNT || to < 0 || to >= STATE_COUNT) return 0;
if(m_total_transitions[from] == 0) return 0;
return m_matrix[from][to] / m_total_transitions[from];
}
//+------------------------------------------------------------------+
//| Get all probabilities from a specific state |
//+------------------------------------------------------------------+
void CMarkovChain::GetProbabilities(ENUM_MARKOV_STATE from, double &probs[])
{
ArrayResize(probs, STATE_COUNT);
for(int i = 0; i < STATE_COUNT; i++)
{
probs[i] = GetProbability(from, (ENUM_MARKOV_STATE)i);
}
}