基于马尔可夫链的矩阵预测模型·进阶篇
🔢

基于马尔可夫链的矩阵预测模型·进阶篇

(2/3)·接上篇概念铺垫,本篇用概率矩阵把价格、时间、成交量编织成可迭代的市场状态机

偏理论进阶 第 2/3 篇

接上篇,我们继续深挖马尔可夫矩阵预测模型。很多人把市场当连续函数去拟合,却忽略了价格本身就能被离散化成状态——本篇要做的,是把混沌行情转译成概率语言。

价格、时间、成交量三维拆法

只盯K线容易漏掉市场真正的驱动结构。把行情拆成价格、时间、成交量三个维度,分别回答「正在发生什么」「何时容易发生」「为什么动」,三者联动才更接近真实博弈。 价格维度用经典工具刻画状态:趋势、均线、震荡指标、形态。时间维度不是简单看钟点,而是把日内和月度季节性编码进模型,重大波动往往在特定窗口概率更高。成交量维度看参与强度,分时动态和累积/派发类指标能揭示价格变动的底层推力。 时间处理有个细节容易踩坑:直接用0–23小时整数,23:59到00:00会被模型当成巨大跳跃。用正弦/余弦把小时映射成连续圆周坐标,断层就消失了。下面这段提取逻辑可直接在MT5导出的CSV上跑(Python端),验证三维度字段怎么来。 代码里价格部分给了9/21/50三条EMA及两两交叉信号;时间部分除星期和小时外,重点在hour_sin/hour_cos的连续编码;成交量用14期均量做相对强度rel_volume,单根K线成交量偏离均量越大,行情延续倾向越强(外汇、贵金属属高风险,信号仅作概率参考)。

MQL5 / C++
def add_indicators(df):
    # --- PRICE INDICATORS ---
    df[&class="macro">#x27;ema_9&class="macro">#x27;] = df[&class="macro">#x27;close&class="macro">#x27;].ewm(span=class="num">9, adjust=False).mean()
    df[&class="macro">#x27;ema_21&class="macro">#x27;] = df[&class="macro">#x27;close&class="macro">#x27;].ewm(span=class="num">21, adjust=False).mean()
    df[&class="macro">#x27;ema_50&class="macro">#x27;] = df[&class="macro">#x27;close&class="macro">#x27;].ewm(span=class="num">50, adjust=False).mean()
    df[&class="macro">#x27;ema_cross_9_21&class="macro">#x27;] = (df[&class="macro">#x27;ema_9&class="macro">#x27;] > df[&class="macro">#x27;ema_21&class="macro">#x27;]).astype(class="type">int)
    df[&class="macro">#x27;ema_cross_21_50&class="macro">#x27;] = (df[&class="macro">#x27;ema_21&class="macro">#x27;] > df[&class="macro">#x27;ema_50&class="macro">#x27;]).astype(class="type">int)
    
    # --- TIME INDICATORS ---
    df[&class="macro">#x27;hour&class="macro">#x27;] = df[&class="macro">#x27;time&class="macro">#x27;].dt.hour
    df[&class="macro">#x27;day_of_week&class="macro">#x27;] = df[&class="macro">#x27;time&class="macro">#x27;].dt.dayofweek
    df[&class="macro">#x27;hour_sin&class="macro">#x27;] = np.sin(class="num">2 * np.pi * df[&class="macro">#x27;hour&class="macro">#x27;] / class="num">24)
    df[&class="macro">#x27;hour_cos&class="macro">#x27;] = np.cos(class="num">2 * np.pi * df[&class="macro">#x27;hour&class="macro">#x27;] / class="num">24)
    
    # --- VOLUME INDICATORS ---
    df[&class="macro">#x27;tick_volume&class="macro">#x27;] = df[&class="macro">#x27;tick_volume&class="macro">#x27;].astype(class="type">class="kw">float)
    df[&class="macro">#x27;volume_change&class="macro">#x27;] = df[&class="macro">#x27;tick_volume&class="macro">#x27;].pct_change(class="num">1)
    df[&class="macro">#x27;volume_ma_14&class="macro">#x27;] = df[&class="macro">#x27;tick_volume&class="macro">#x27;].rolling(class="num">14).mean()
    df[&class="macro">#x27;rel_volume&class="macro">#x27;] = df[&class="macro">#x27;tick_volume&class="macro">#x27;] / df[&class="macro">#x27;volume_ma_14&class="macro">#x27;]

「用聚类把行情切成可数的状态」

把连续的价格、时间、成交量直接喂给模型,得到的是一团看不出规律的混沌;真正能拿来统计概率的,是先把它们离散成有限个「状态」。这里每组特征各自跑 K-means,分成 3 个聚类,价格、时间、成交量三组理论上能交叉出 27 种组合,但当前实现只取 9 种最具代表性的状态——这是在估计稳健性和细分度之间做的折中,状态太少会丢信息,太多则每个状态样本量不够、概率估计会飘。 聚类的好处是不用先验假设「什么叫趋势、什么叫震荡」,模型只啃历史数据结构,自己就把高波动段、盘整段、单边段归到不同堆里。你在 MT5 里导出的 tick 或分钟级特征,只要按组整理好,就能复现这套切分。 下面这段是状态聚类的核心函数:每组独立建一个 KMeans(n_clusters=3,random_state=42 保证可复现,n_init=10 避免局部最优),拟合完把标签和模型都存回来。注意它刻意跳过了名为 'all' 的组,避免把混在一起的总特征误当一组去切。 外汇与贵金属杠杆高、跳空频繁,聚类出的状态只在历史样本分布内有效,换周期或换品种后须重新拟合,否则状态含义可能漂移。

MQL5 / C++
def create_state_clusters(feature_groups, n_clusters_per_group=class="num">3):
    group_clusters = {}
    kmeans_models = {}
    
    for group_name, group_data in feature_groups.items():
        if group_name != &class="macro">#x27;all&class="macro">#x27;:
            kmeans = KMeans(n_clusters=n_clusters_per_group, random_state=class="num">42, n_init=class="num">10)
            clusters = kmeans.fit_predict(group_data[&class="macro">#x27;data&class="macro">#x27;])
            
            group_clusters[group_name] = clusters
            kmeans_models[group_name] = kmeans
    
    class="kw">return group_clusters, kmeans_models

◍ 双矩阵驱动的马尔可夫状态推演

预测模型的内核由两张矩阵撑起:状态转移概率矩阵,以及每次转移对应的下一根 K 线收阳概率矩阵。两者拼起来就是一条马尔可夫链——下一刻市场处于什么格局,只挂钩当前状态,和更早的走势痕迹无关。 转移矩阵记的是「从 A 状态跳到 B 状态」的发生频率。比如盘整态之后,市场可能以某个概率切进趋势变动,也可能继续原地横盘,这张表把这种动态结构量化了出来。 上涨概率矩阵更进一层:它为每一种状态跳转标注了下一根 K 线收盘价高于开盘价的概率。于是你不只能猜市场去哪个状态,还能顺带判断价格方向偏多还是偏空。外汇与贵金属波动杠杆高,这类概率仅作倾向参考,实盘仍需风控。 把两张矩阵画出来,常会撞见反直觉的规律。某些状态自我延续性极强,形成稳定格局;另一些只是过路状态,迅速让位给新结构。这种转移结构的不对称,才是读懂盘面动态逻辑的钥匙。 下面这段聚合脚本把状态序列塞进 9×9 的矩阵里做计数与归一,直接可在 MT5 外接 Python 环境跑一遍验证你的状态标签。

MQL5 / C++
def combine_state_clusters(group_clusters, labels):
    # Fill the transition matrix and rise matrix
    for i in range(len(states) - class="num">1):
        curr_state = states[i]
        next_state = states[i + class="num">1]
        
        # Increase the transition counter
        transition_matrix[curr_state, next_state] += class="num">1
        
        # If the next candle is bullish, increase the rise counter
        if i + class="num">1 < len(labels) and labels[i + class="num">1] == class="num">1:
            rise_matrix[curr_state, next_state] += class="num">1
    
    # Normalization of the transition matrix
    state_transitions = np.zeros((class="num">9, class="num">9))
    for i in range(class="num">9):
        row_sum = np.sum(transition_matrix[i, :])
        if row_sum > class="num">0:
            state_transitions[i, :] = transition_matrix[i, :] / row_sum

用概率树把目光放到三根K线之后

马尔可夫框架真正有意思的地方在迭代:它不只给你下一根K线是涨是跌的二分类结论,而是把所有可能路径按转移概率做加权,输出一整张概率分布,并附带置信度。对做外汇或贵金属的人来说,这种分布比单点信号更利于仓位和止损安排——这类品种杠杆高、跳空频繁,盲目信单点结论风险很大。 模型可以顺着转移矩阵连推多步,生成未来 N 根 K 线的概率树。单步预测往往抓不到的偏向性漂移,在第三步、第四步的边际概率里会显形,比如连续三步后多头累计概率从 0.52 爬到 0.61,这种倾向值得盯盘时参考而非当成定论。 下面这段 Python 风格的函数演示了单步加权概率怎么算,逻辑可直接平移进 MQL5 的矩阵运算: def predict_with_matrix(state_transitions, rise_probability_matrix, current_state): # 取当前状态到各下一状态的转移概率向量 next_state_probs = state_transitions[current_state, :] # 初始化加权上涨概率与总概率累加器 weighted_prob = 0 total_prob = 0 # 遍历每个可达下一状态,用转移概率乘对应上涨条件概率并累加 for next_state, prob in enumerate(next_state_probs): weighted_prob += prob * rise_probability_matrix[current_state, next_state] total_prob += prob # 若总概率大于0则做归一化,避免概率和质量不闭合 if total_prob > 0: weighted_prob = weighted_prob / total_prob # 以0.5为界出方向预测,置信度取偏离0.5更远的那一侧 prediction = 1 if weighted_prob > 0.5 else 0 confidence = max(weighted_prob, 1 - weighted_prob) 在 MT5 里把 state_transitions 换成你统计的跳转矩阵,rise_probability_matrix 换成条件上涨概率,就能在 EA 里实时吐出带置信度的多步预测。记得用近 3000 根 K 线滚动重估矩阵,否则旧样本会让概率树慢慢失真。

MQL5 / C++
def predict_with_matrix(state_transitions, rise_probability_matrix, current_state):
    # Probabilities of transition to the next state
    next_state_probs = state_transitions[current_state, :]
    
    # Calculation of the weighted rise probability taking into account all possible transitions
    weighted_prob = class="num">0
    total_prob = class="num">0
    
    for next_state, prob in enumerate(next_state_probs):
        weighted_prob += prob * rise_probability_matrix[current_state, next_state]
        total_prob += prob
    
    # Normalization(if necessary)
    if total_prob > class="num">0:
        weighted_prob = weighted_prob / total_prob
    
    # Forecast
    prediction = class="num">1 if weighted_prob > class="num">0.5 else class="num">0
    confidence = max(weighted_prob, class="num">1 - weighted_prob)

「模型透明才能信得过信号」

拿马尔可夫链和神经网络比,前者不是黑箱:状态、转移概率都是可查的统计量,你拿到预测的同时能反推市场处在什么结构里。这点对做价格行为的老手尤其有用——逻辑看得见,才敢按信号下单。 上面这段 Python 思路可以直接平移到 MT5 的因子分析里:按价格、时间、成交量分组做 K-means,取每个簇中心离零的绝对距离当特征重要性,排前 3 的就是要盯的核心指标。外汇和贵金属波动受事件驱动,过滤掉不显著的噪声因子,能少亏在无意义抖动上。 状态簇往往对应趋势、盘整、反转这类经典形态。统计模型和裸 K 分析因此能接上桥:比如某簇中心显示波动率与成交量因子权重最高,那当前大概率不是窄幅整理,而是变盘前兆,得调紧止损。

MQL5 / C++
for group_name in [&class="macro">#x27;price&class="macro">#x27;, &class="macro">#x27;time&class="macro">#x27;, &class="macro">#x27;volume&class="macro">#x27;]:
    features = feature_groups[group_name][&class="macro">#x27;features&class="macro">#x27;]
    kmeans = kmeans_models[group_name]
    cluster_centers = kmeans.cluster_centers_
    
    for cluster_idx in range(class="num">3):
        center = cluster_centers[cluster_idx]
        # We obtain the importance of each feature as its deviation from zero at the center of the cluster
        importances = np.abs(center)
        sorted_idx = np.argsort(-importances)
        top_features = [(features[i], importances[i]) for i in sorted_idx[:class="num">3]]
让小布替你跑这套
这些状态量化与矩阵迭代的诊断,小布盯盘的 AIGC 已内置,打开对应品种页即可看到转移概率分布,你只管判断当前状态是否可信。

常见问题

马尔可夫性指系统不再显式记忆更早历史,但当前状态本身已由历史压缩而来,所以历史通过状态间接生效,并非完全丢弃。
真实状态如趋势或震荡不可直接观测,只能从价格、成交量等间接信号推断,HMM 正是用观测序列反推隐藏市场状态的概率模型。
多步转移由矩阵连乘得到,随步数增加不确定性放大,远端预测倾向平滑成稳态分布,实战中宜只取近几步且结合形态过滤。
可以,小布在对应品种页内置了基于近期数据的离散状态划分与转移概率视图,省去手动统计,但决策仍由你做。
不宜硬套,贵金属受实物供需与避险情绪扰动更强,状态阈值常需按波动率和时段重新标定,外汇则更吃宏观事件窗口。