121 lines
4.8 KiB
MQL5
121 lines
4.8 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
}
|
|
}
|