首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

HMM、信号、时序、降噪(附代码)

1 前言

我所处理的大多数信号都是有噪声的,反映了潜在价格、成交量、成交额等的噪声。许多基于这些指标的传统策略可能是:

1、利用信号开仓买卖。

2、考虑信号的特定等级来表示一个状态,例如:long {+1},short {-1},neutral {0}

下图是一个检测测下行动量信号的策略。我们的目标是当动量向下时信号为1,当动量向不下时信号为0。一种简单的方法可能是设置一个阈值,在阈值之上将原始信号映射为1,在阈值之下将原始信号映射为0。

在上述情况下,没有阈值水平可以避免0和1状态之间的不必要振荡。例如,在将阈值设置为0.75的情况下,有2次入侵低于阈值(将被映射到状态0)。尝试其他阈值(例如0.5)可以避免在动量期间产生噪音,但此后会遇到噪音。

去噪的信号(如图中的绿线所示)使用隐藏的马尔可夫模型(HMM)。

2 一种解决方案

在上述应用中,我们感兴趣的是配置状态+1和0,以消除信号中的噪声。让我们考虑一种常见的情况,我们想要将{Short,Neutral,Long}状态分配给一个有噪声的信号。

为此,可以构建一个三态系统并分配转换概率,例如从Long到Short,从Neutral到Long,保持在相同状态的转移概率等。

可以将相同的状态概率视为定义给定状态的“粘性”,以及对噪声的抵抗力,否则噪声可能导致我们转移到另一种状态。例如,如果我们给Pshort→short分配一个较高的概率,给脱离那个状态的转移分配一个相应的较低的概率,我们将能够在不转移到另一个状态的情况下承受更多的噪音。

上面的状态系统为我们提供了一个转换矩阵:

请注意,每行的概率总和必须为1,即对于转移矩阵M:∑jMi,j=1 。如果要根据对相同状态的“粘性”来定义降噪模型,则可以将三态转移矩阵的概率确定为:

对于二态矩阵,则为:

3 观测分布

接下来,我们需要考虑如何将(噪声)信号映射到这些状态。HMM采取的方法是引入观测分布p(y|x),其中 y 是我们的观测值(在这种情况下为原始信号),x 是特定的“隐藏状态”。

我们的下一步是为每个状态设计一个观测分布,提供分离以使p(y|x=si)对比p(y|x=sj)的概率对于应该映射到状态si与sj的信号值来说有显著的不同。在下面的示例中,我们使用正态分布将一个有噪声的信号映射到两种状态(long,short):

  • Long状态: p(y|x=long)=N(+0.65,σ)或者
  • Short状态: p(y|x=short)=N(−0.65,σ)

4 与HMM结合

观测分布为我们提供了 p(y|x=s),但我们正在寻找的是 p(x=s|yn,yn−1,..y0),即在给定观测序列(我们的噪声信号)的情况下处于“ s”状态的概率,yn,yn−1,..y0

HMM模型将转移概率矩阵M联系起来,我们的观测概率分布p(y|x=s)和状态概率先验πs=short,πs=neutral,πs=long进入一个模型,该模型确定我们沿着观测序列进行时最可能的状态。(先验通常被确定为每个状态的频率,例如1 / 3、1 / 3、1 / 3)。

在序列中的每个时间步上,我们都会计算处于xt=s状态的概率如下:

αt(xt)=p(yt|xt)∑xt−1p(xt|xt−1)αt−1(xt−1)

其中p(xt|xt−1) 是我们在所有可能状态组合中的转移概率,由M 和 p(yt|xt) 是我们在给定xt状态下的观测分布 。对于t = 0, αt(xt)根据每个状态的先验分布定义为 p(y0|x0=s)πs

以上内容被分解为动态编程问题。伪代码中的算法如下:

代码语言:javascript
复制
# initialize time step 0 using state priors and observation dist p(y | x = s)
for si in states:
    alpha[t = 0, state = si] = pi[si] * p(y[0] | x = si)

# determine alpha for t = 1 .. n
for t in 1 .. n:
    for sj in states:
        alpha[t,sj] = max([alpha[t-1,si] * M[si,sj] for si in states]) * p(y[t] | x = sj)

# determine current state at time t
return argmax(alpha[t,si] over si)

请注意,以上内容将在对数似然空间中重申,以避免下溢和避免必须计算分布CDF。

5 过滤

总之,映射Long/Short信号或可选状态配置的方法是:

  • 以分离信号域中状态的方式定义观测分布
  • 定义控制“粘性”(状态转换噪声的数量)的转移概率矩阵
  • 定义先验(通常对每个状态的预期频率)
  • 使用正向维特比模型确定状态序列 xt:0作为观测到的原始信号序列 yt:0的函数

这是一个示例(我们并未尝试对其进行优化):

代码语言:javascript
复制
from tseries_patterns.ml.hmm import HMM2State
from tseries_patterns.data import YahooData
from talib import ADX


# get price bars
aapl = YahooData.getOHLC("AAPL", Tstart='2019-1-1')

# compute our raw signal (not a very good one, FYI)
rawsignal = ADX(aapl.high, aapl.low, aapl.close, timeperiod=20)

# denoise signal
hmm = HMM2State (means = [10, 40], ss_prob = 0.9999)
## predict 0 and 1 states, rescaling to 10, 40 to align with scale of ADX
denoised = 10 + hmm.predict(rawsignal.dropna()) * 30

# plot
...

上面的HMM2State类显式定义:

  • 转移概率矩阵:
    • i=j→0.9999和
    • i≠j→1−0.9999
  • 观测分布为:
    • S0=N(μ=10,σdefault)和
    • S1=N(μ=40,σdefault)
  • 先验概率为πi=1/2

然后使用前向维特比方法确定hmm.predict()调用中的状态。HMM2State 是定义模型的底层scikit hmmlearn实现的简单包装,它绕过了fit() 阶段,定义了模型。

6 替代方案(效果不佳)

HMM的典型方法涉及使用前向—后向算法自动确定:

  • 转移概率
  • 观测分布
  • 先验

例如:

代码语言:javascript
复制
from hmmlearn.hmm import GaussianHMM

rawsignal = ...
model = GaussianHMM(n_components=3)
model.fit (rawsignal)

states = model.decode(rawsignal)

尽管这将找到三种状态,但不太可能不会达到所需的过滤效果:

  • 原始信号中的偏差可能会使3个观测值分布产生偏斜
  • 转移概率不太可能代表所需的“粘性”,因此也不太可能表示期望的去噪

一般来说,通过自己定义观测分布和转移概率矩阵将会获得更好的结果。

下一篇
举报
领券