3. 状态分类与遍历性:常返态、瞬态、周期性与非周期性、平稳分布

好,咱们接着聊。上一节我们把马尔可夫链的数学框架搭起来了,知道了转移矩阵怎么用。但光有这些还不够——你想想看,一个状态到底能不能反复回来?会不会一去不返?这些性质直接决定了你的交易策略能不能「长期稳定赚钱」。说白了,这就是状态分类要解决的问题。

我个人习惯把状态分类比作「城市里的不同街区」。有些街区你去了还能回来,有些则是单行道。咱们今天就把这些概念一个个拆开讲清楚。

3.1 常返态与瞬态

先问个问题:一个状态,你从它出发,最终还能回到它自己吗?

能回来的,叫常返态。回不来的,叫瞬态

数学上怎么定义?设 \( f_{ii} \) 为从状态 \( i \) 出发,最终返回状态 \( i \) 的概率。如果 \( f_{ii} = 1 \),那就是常返态;如果 \( f_{ii} < 1 \),那就是瞬态。

我在项目中遇到过这样一个场景:用马尔可夫链建模某只股票的涨跌状态。结果发现「大跌」状态居然是瞬态——也就是说,一旦进入大跌,几乎不可能再回到大跌状态(因为跌到底就反弹了)。嗯,这其实是个有用的信号。

核心判断标准:
  • 常返态:\( f_{ii} = 1 \),一定能回来
  • 瞬态:\( f_{ii} < 1 \),有可能一去不返

还有一个更实用的判断方法:计算从状态 \( i \) 出发,访问状态 \( i \) 的期望次数。如果这个期望次数是无穷大,那就是常返态;如果是有限值,那就是瞬态。

你可能会问:「这跟趋势跟踪有什么关系?」关系大了。如果你的策略依赖某个「震荡状态」反复出现,但这个状态其实是瞬态,那你的策略迟早会失效。我曾经就踩过这个坑——用历史数据回测时某个状态出现频率很高,但实盘时它再也不出现了。后来一分析,原来是个瞬态。

3.2 周期性

好,常返态和瞬态讲完了。接下来看周期性。

什么叫周期性?简单说:从一个状态出发,经过多少步才能回来?如果只能经过某个步长的整数倍回来,那就是有周期。

举个例子:假设你只能在第2步、第4步、第6步...回到状态 \( i \),那周期就是2。如果任何步数都有可能回来,那就是非周期性的。

数学定义:设 \( d \) 为所有可能的返回步数的最大公约数。如果 \( d > 1 \),则状态是周期性的,周期为 \( d \);如果 \( d = 1 \),则是非周期性的。

我的经验:在量化交易中,非周期性状态更常见。因为市场数据很少会严格遵循「每N步回来一次」的规律。如果你发现某个状态有强周期性,那往往意味着数据有问题,或者市场存在某种套利机会。

我记得有一次帮朋友分析一个高频策略,发现他的「买入信号」状态周期为3。也就是说,每3个tick就会出现一次买入信号。这显然不合理——后来发现是他的数据采样频率和策略逻辑产生了共振。嗯,这种坑要小心。

3.3 遍历性与平稳分布

接下来是重头戏:遍历性。

一个马尔可夫链是遍历的,当且仅当它满足两个条件:

  1. 不可约:所有状态互相可达
  2. 非周期性:所有状态都是非周期的

遍历性意味着什么?意味着无论你从哪个状态出发,经过足够长的时间,系统都会「忘记」初始状态,进入一个稳定的分布——这就是平稳分布

平稳分布 \( \pi \) 满足:

π = πP
∑π_i = 1

说白了,平稳分布就是转移矩阵的不动点。你一直转移下去,状态的概率分布就不再变化了。

我建议你在实际项目中这样理解:平稳分布告诉你,长期来看,每个状态出现的概率是多少。比如在趋势跟踪中,如果平稳分布显示「上涨状态」占60%,「下跌状态」占40%,那你的策略就应该偏向做多。

注意:不是所有马尔可夫链都有平稳分布!只有遍历的链才有唯一的平稳分布。如果链不是遍历的,那长期行为可能依赖于初始状态,这时候用平稳分布做预测就会出错。

咱们用一张图来总结一下整个知识体系:

状态分类与遍历性知识体系 马尔可夫链状态分类 常返态 vs 瞬态 周期性 vs 非周期性 常返态:f_ii = 1 瞬态:f_ii < 1 周期性:d > 1 非周期性:d = 1 遍历性 平稳分布 π = πP

3.4 实际应用:如何判断你的链是否遍历

好,理论讲完了。咱们来点实际的。怎么判断一个马尔可夫链是否遍历?

我一般按这个步骤来:

  1. 检查不可约性:画个状态转移图,看是不是所有状态都能互相到达。如果有孤立的状态,那就不是不可约的。
  2. 检查非周期性:看每个状态的周期。如果所有状态周期都是1,那就是非周期的。
  3. 计算平稳分布:解方程 \( \pi = \pi P \),看解是否唯一且所有分量都为正。

给你看个代码示例,怎么用Python判断:

import numpy as np

def is_irreducible(P):
    """检查转移矩阵P是否不可约"""
    n = P.shape[0]
    # 计算可达矩阵 (P^k 的非零元素)
    reachable = np.eye(n, dtype=bool)
    P_power = np.eye(n)
    for _ in range(n):
        P_power = P_power @ P
        reachable = reachable | (P_power > 1e-10)
    # 检查是否所有状态互相可达
    return np.all(reachable)

def is_aperiodic(P):
    """检查是否非周期性"""
    n = P.shape[0]
    for i in range(n):
        # 计算返回步数的最大公约数
        periods = []
        P_power = np.eye(n)
        for k in range(1, 2*n+1):
            P_power = P_power @ P
            if P_power[i, i] > 1e-10:
                periods.append(k)
        if len(periods) == 0:
            return False
        # 计算最大公约数
        gcd = periods[0]
        for p in periods[1:]:
            gcd = np.gcd(gcd, p)
        if gcd > 1:
            return False
    return True

def stationary_distribution(P):
    """计算平稳分布"""
    n = P.shape[0]
    # 解 πP = π, 即 π(P - I) = 0
    A = P.T - np.eye(n)
    # 添加归一化条件
    A = np.vstack([A, np.ones(n)])
    b = np.zeros(n+1)
    b[-1] = 1
    # 最小二乘解
    pi, _, _, _ = np.linalg.lstsq(A, b, rcond=None)
    return pi

# 示例:一个简单的3状态链
P = np.array([
    [0.7, 0.2, 0.1],
    [0.1, 0.8, 0.1],
    [0.2, 0.3, 0.5]
])

print("不可约:", is_irreducible(P))
print("非周期:", is_aperiodic(P))
print("平稳分布:", stationary_distribution(P))
避坑指南:我曾经在计算平稳分布时直接用求逆,结果矩阵奇异报错了。后来改用最小二乘法才搞定。记住,转移矩阵不一定可逆,用最小二乘更稳妥。

最后总结一下:

  • 常返态:能回来的状态,是策略长期有效的基础
  • 瞬态:一去不返的状态,要小心别被历史数据迷惑
  • 周期性:步长规律性,非周期才是常态
  • 遍历性:不可约+非周期,保证平稳分布存在且唯一
  • 平稳分布:长期概率分布,是策略参数优化的依据

嗯,这一节内容不少。你消化一下,下一节咱们会把这些概念用到实际的趋势跟踪策略中去。


专注资料整理