天天看點

時序分析(12) -- 基于回歸的平滑技術時序分析(12)

時序分析(12)

基于回歸的平滑技術

    上一篇文章中,我們着重探讨了金融時序分析中應用非常廣泛的指數平滑技術。本篇文章我們補充介紹在工業中也起着重要作用的基于回歸方法的平滑技術,主要包括:

  • Spline Smoothing
  • LOESS/LOWESS Smoothing
  • Kernel Smoothing
  1. Spline Smoothing

    Spine的核心目标是為了最小化下式:

    J [ s ] = α ∫ ( d s 2 d 2 t ) 2 d t + ( 1 − α ) ∑ i w i ( y i − s ( x i ) ) 2 J[s]=\alpha \int(\frac {ds^2}{d^2t})^2dt+(1-\alpha)\sum_i w_i(y_i-s(x_i))^2 J[s]=α∫(d2tds2​)2dt+(1−α)i∑​wi​(yi​−s(xi​))2

    式中, s s s 是平滑後的時序, α \alpha α 是混合因子, w i w_i wi​ 是權重參數, y i y_i yi​ 是實際時序。 仔細觀察後可以發現,第二項代表的是平方誤差和;而第一項中的二階導數代表曲線的曲率,也就是說代表平滑程度。

    剛才介紹的是最常見的單變量三次Spline平滑,下面我們來深入讨論一下spline平滑的思想:

        什麼是Spline呢?我們說k階spline是一個分段k階多項式連續函數,在其結點處有具有連續的1到k − 1階導數。

        即函數 f : R → R f:R \rightarrow R f:R→R為一個 k k k 階spline,其拐點為 t 1 < . . . < t m t_1 \lt ... \lt t_m t1​<...<tm​,那麼 f f f 在每一段間隔 ( − ∞ , t 1 ] , [ t 1 , t 2 ] , . . . [ t m , ∞ ) (-\infty,t_1],[t_1,t_2],...[t_m,\infty) (−∞,t1​],[t1​,t2​],...[tm​,∞) 是一個 k k k 階多項式,且 f f f 的0到k-1階導數在結點 t 1 , . . . , t m t_1,...,t_m t1​,...,tm​ 上連續。

        最常見的情況是k = 3,也就是剛才所講的cubic spline.

        當然,spline平滑不僅可以應用于單變量,也可應用于多變量。

        實踐中,spline的參數多是通過交叉驗證得到的。

  2. LOESS/LOWESS Smoothing

    spline具有全局優化目标,造成其對局部細節資訊不敏感。而LOESS(Local Weighted Regression Spline)解決了這個問題。

    LOESS通過低階多項式(通常是線性的)回歸來近似資料的局部特征,其權重配置設定的原則是離待平滑點近的點的權重要高于距離較遠的點,這種方式稱為Local Weighting.

    讓我們先考慮一個簡單的一階LOESS:

        本地近似采用線性形式,a + bx,我們需要通過最小化下式,

    χ 2 = ∑ i w ( x − x i ; h ) ( a + b x i − y i ) 2 \chi^2=\sum_i w(x-x_i;h)(a+bx_i-y_i)^2 χ2=i∑​w(x−xi​;h)(a+bxi​−yi​)2

        來找到參數 a , b a,b a,b.

    這裡, 是權重函數,它應該是平滑的且具有很強的尖峰。基本上是一個核函數(關于核函數,我們将在下一節讨論)。

    在LOESS中,經常采用的核函數為 K ( x ) = ( 1 − ∣ x ∣ 3 ) 3 K(x)=(1-|x|^3)^3 K(x)=(1−∣x∣3)3,當 x < 1 x \lt 1 x<1時;否則 K = 0 K=0 K=0. h h h 控制了kernel的寬度。

    以上就是LOESS的基本思想,我們可以看到這個方法時很容易擴充的,例如更改 a + b x a+bx a+bx為高階關系或者更改核函數等。

    需要注意的是,LOESS是計算敏感的,每一次計算平滑值時都需要所有點參與計算。

  3. Kernel Smoothing

    Kernel Smoothing又稱為KDE(Kernel Density Estimator),它與前面所講的平滑技術有所不同。一般的平滑技術都是用來平滑時序資料的觀測值,而KDE多用來對某随機變量的機率密度函數進行平滑和降噪。

    前面提到過,核函數一般是一個具有較強的尖峰平滑函數。建構KDE一般就是在每一個點上放置一個Kernel,然後把所有Kernel的貢獻加起來構成一個平滑曲線。 我們來看一下常見的三種Kernel:

    時序分析(12) -- 基于回歸的平滑技術時序分析(12)
    一些kernel的圖像如下:
    時序分析(12) -- 基于回歸的平滑技術時序分析(12)

    KDE的公式為:

    D h ( x , { x i } ) = ∑ i = 1 n 1 h K ( x − x i h ) D_h(x,\{x_i\})=\sum_{i=1}^n\frac {1}{h}K(\frac{x-x_i}{h}) Dh​(x,{xi​})=i=1∑n​h1​K(hx−xi​​)

    h代表kernel的寬度。 通過上式,我們可以計算出任何一點的平滑值。

    可以看出,和LOESS類似,KDE的計算要求較高。

實踐

  • Spline Smoothing

    我們用指數函數加上随機抖動模拟原資料

from scipy.interpolate import UnivariateSpline
from numpy import linspace,exp
from numpy.random import randn
x = linspace(-3, 3, 100)
y = exp(-x**2) + randn(100)/10
s = UnivariateSpline(x, y, s=1)
           
xs = linspace(-3, 3, 1000)
ys = s(xs)
plt.plot(x, y, '.-',label='Raw')
plt.plot(xs, ys,label='Spline')
plt.legend()
plt.show()
           
時序分析(12) -- 基于回歸的平滑技術時序分析(12)
  • LOESS Smoothing

    我們假造一些資料來模拟原資料

from scipy.interpolate import interp1d
import statsmodels.api as sm
# introduce some floats in our x-values
x = list(range(3, 33)) + [3.2, 6.2]
y = [1,2,1,2,1,1,3,4,5,4,5,6,5,6,7,8,9,10,11,11,12,11,11,10,12,11,11,10,9,8,2,13]
# lowess will return our "smoothed" data with a y value for at every x-value
lowess = sm.nonparametric.lowess(y, x, frac=.3)
# unpack the lowess smoothed points to their values
lowess_x = list(zip(*lowess))[0]
lowess_y = list(zip(*lowess))[1]
# run scipy's interpolation. There is also extrapolation I believe
f = interp1d(lowess_x, lowess_y, bounds_error=False)
xnew = [i/10. for i in range(400)]
# this this generate y values for our xvalues by our interpolator
# it will MISS values outsite of the x window (less than 3, greater than 33)
# There might be a better approach, but you can run a for loop
#and if the value is out of the range, use f(min(lowess_x)) or f(max(lowess_x))
ynew = f(xnew)
plt.plot(x, y, 'o',label='Raw')
plt.plot(lowess_x, lowess_y, '*',label='Loess Point')
plt.plot(xnew, ynew, '-',label='Loess Curve')
plt.legend(loc='upper left')
           
時序分析(12) -- 基于回歸的平滑技術時序分析(12)
  • KDE

    我們将會重點展示KDE的實作,不但是因為這個方法有非常廣泛的應用,而且在《量化投資技術篇》中我們

    将會采用此技術作為估算收益率的方法之一。 主要步驟如下:

  1. 計算周收益率
  2. 得到周收益率的直方圖和經驗分布
  3. 估算參數
  4. 得到KDE

1. 計算周收益率

index_ret_w = indexs_sub.dropna().resample('W').apply(lambda x: (x[-1] - x[0])/ x[0] if len(x) > 0 e
index_ret_w.dropna(inplace=True)
           

2. 得到直方圖和經驗分布

時序分析(12) -- 基于回歸的平滑技術時序分析(12)

3. 估算bandwidth參數

fund_ret = index_ret_w[['國内股票']].as_matrix()
fund_ret = fund_ret[fund_ret != 0]
           
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KernelDensity
           

gridSearch搜尋參數

grid = GridSearchCV(KernelDensity(), {'bandwidth': np.arange(0.001, 0.3, 0.001) }, cv=5)
grid.fit(fund_ret.reshape(-1,1))
print(grid.best_params_)
           

{‘bandwidth’: 0.016}

Scott和Sliverman準則估算參數

from scipy import stats
from scipy.stats import norm
           
kde1 = stats.gaussian_kde(fund_ret)
kde2 = stats.gaussian_kde(fund_ret, bw_method='silverman')
print("scott rule band width:",fund_ret.size**(-1./(1+4)))
print("Sliverman rule band width:",(fund_ret.size * (1 + 2) / 4.)**(-1. / (1 + 4)))
print(kde1.factor,kde2.factor)
           

scott rule band width: 0.329363947250484

Sliverman rule band width: 0.34887014530965604

0.329363947250484 0.34887014530965604

三種方式估算參數的KDE比較

x_grid = np.linspace(-0.1, 0.1, 100000)

kde3 = grid.best_estimator_
pdf3_ = np.exp(kde3.score_samples(x_grid[:, None]))

fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111)

ax.plot(fund_ret, np.zeros(fund_ret.shape), 'b+', ms=20) # rug plot
#x_eval = np.linspace(-0.015, 0.015, num=500)
ax.hist(fund_ret, 100, fc='gray', histtype='stepfilled', alpha=0.5, normed=True)
Scott = ax.plot(x_grid, kde1(x_grid), 'k-', label="Scott's Rule")
Silverman = ax.plot(x_grid, kde2(x_grid), 'r-', label="Silverman's Rule")
GridSearch = ax.plot(x_grid, pdf3_, linewidth=1, alpha=0.5, label='GridSearch' %   kde3.bandwidth)

plt.legend(loc='upper left')
plt.show()
           
時序分析(12) -- 基于回歸的平滑技術時序分析(12)

總結

    本文介紹了平滑技術中的基于回歸的平滑,包括Spline,LOESS,KDE。當然前兩者在時序資料平滑中很少采用,而後者主要用在機率密度函數平滑中。其實平滑的核心作用是為了降噪,在實作的代碼和圖形展示中我們已經看到了這一點。

繼續閱讀