鄭志勇 ArisZheng
文本是使用Python實(shí)現(xiàn)Hurst指數(shù)計(jì)算惦辛,作者王瑋珩寝优,從事股票策略研發(fā)兼回測(cè)系統(tǒng)開發(fā)且轨;
Hurst指數(shù)是分形技術(shù)在金融量化分析中的典型應(yīng)用。分形是以非整數(shù)維形式充填空間的形態(tài)特征分形可以說是來自于一種思維上的理論存在1973年,曼德勃羅(B.B.Man-
delbrot) 在法蘭西學(xué)院講課時(shí),首次提出了分維和分形幾何的設(shè)想礁叔。分形(Fractal)一詞,是曼 德勃羅創(chuàng)造出來的,其原意具有不規(guī)則、支離破碎等意義,分形幾何學(xué)是一門以非規(guī)則幾何形態(tài)為研究對(duì)象的幾何學(xué)迄薄。由于不規(guī)則現(xiàn)象在自然界是普遍存在的,因此分形幾何又稱為描述 大自然的幾何學(xué)琅关。分形幾何建立以后,很快就引起了許多學(xué)科的關(guān)注,這是由于它不僅在理論 上,而且在實(shí)用上都具有重要價(jià)值。
一讥蔽、Hurst指數(shù)簡(jiǎn)介
基于重標(biāo)極差(R/S)分析方法基礎(chǔ)上的 Hurst(赫斯特)指數(shù)(H)研究是由英國(guó)水文專家 H.E.Hurst(1900—1978)在研究尼羅河水庫(kù)水流量和貯存能力的關(guān)系時(shí),發(fā)現(xiàn)用有偏的隨機(jī) 游走(分形布朗運(yùn)動(dòng))能夠更好地描述水庫(kù)的長(zhǎng)期貯存能力,并在此基礎(chǔ)上提出了用重標(biāo)極差 (R/S)分析方法來建立 Hurst指數(shù),作為判斷時(shí)間序列數(shù)據(jù)遵從隨機(jī)游走還是有偏的隨機(jī)游 走過程的指標(biāo)涣易。
Hurst指數(shù)有三種形式:
① 如果 H=0.5,表明時(shí)間序列可以用隨機(jī)游走來描述;
② 如果0.5
③ 如果0≤H<0.5,表明粉紅噪聲(反持續(xù)性),即均值回復(fù)過程。< span="">
也就是說,只要 H ≠0.5,就可以用有偏的布朗運(yùn)動(dòng)(分形布朗運(yùn)動(dòng))來描述該時(shí)間序列
數(shù)據(jù)冶伞。
Mandelbrot在1972年首次將 R/S分析應(yīng)用于美國(guó)證券市場(chǎng),分析股票收益的變化,Pe-ters把這種方法作為其分形市場(chǎng)假說最重要的研究工具進(jìn)行了詳細(xì)的討論和發(fā)展,并做了很
多實(shí)證研究新症。經(jīng)典的金融理論一般認(rèn)為股票市場(chǎng)是有效的,已有的信息已經(jīng)充分在股價(jià)上得到了反映,無法幫助預(yù)測(cè)未來走勢(shì),下一時(shí)刻的變動(dòng)獨(dú)立于歷史價(jià)格變動(dòng)。因此股市變化沒有 記憶响禽。實(shí)際上中國(guó)股市并非完全有效,在一定程度上表現(xiàn)出長(zhǎng)期記憶性(LongTermMemo-
ry)徒爹。中國(guó)股市的牛熊交替(2001—2017),伴隨著對(duì)股市趨勢(shì)的記憶的加強(qiáng)和減弱的輪換,分 形理論中的重標(biāo)極差法導(dǎo)出的 Hurst指數(shù)可以反映股市的長(zhǎng)期記憶性的強(qiáng)弱。用移動(dòng)時(shí)間 區(qū)間的 Hurst指數(shù)來對(duì)照股指的變化,可以分析Hurst指數(shù)的高低與市場(chǎng)指數(shù)走勢(shì)的關(guān)系芋类。
赫斯特指數(shù)預(yù)測(cè)股票市值走勢(shì)的三種形式:
① 如果 H=0.5,表明時(shí)間序列可以用隨機(jī)游走來描述瀑焦。股市未來方向(上漲或者下跌)
無法確定,市場(chǎng)處于震蕩行情中。
有方向,若時(shí)間周期序列長(zhǎng)度為120,當(dāng)最近半年市場(chǎng)上漲(橫盤梗肝、下跌),則市場(chǎng)很可能將繼續(xù) 上漲(橫盤榛瓮、下跌),H 值越大市場(chǎng)保持原有趨勢(shì)的慣性越大。
③ 如果0≤H<0.5,表明粉紅噪聲(反持續(xù)性),即均值回復(fù)過程巫击。股市將改變?cè)蟹较? 若時(shí)間周期序列長(zhǎng)度為120,當(dāng)最近半年市場(chǎng)上漲(橫盤禀晓、下跌),則市場(chǎng)很可能將繼續(xù)下跌或="" 者橫盤(上漲或下跌精续、橫盤或上漲),h值越小市場(chǎng)改變?cè)汹厔?shì)的可能性越大。<="" span="">
中國(guó)的證券市場(chǎng)隨著金融產(chǎn)品豐富粹懒、監(jiān)管效率的提高,未來的中國(guó)證券市場(chǎng)的有效性將越 來越高重付。
二、R/S方法計(jì)算 Hurst指數(shù)
具體參見《金融數(shù)量分析基于Matlab編程》第16章
三凫乖、 移動(dòng)平均 Hurst指數(shù)計(jì)算程序
(1)時(shí)間序列分段
子區(qū)間長(zhǎng)度n 是可變的,如果回歸分析需要將時(shí)間序列進(jìn)行分段,例如若時(shí)間序列長(zhǎng)度為
240,則其可以分解成4段長(zhǎng)度為60的等長(zhǎng)子區(qū)間,或者6段長(zhǎng)度為40的等長(zhǎng)子區(qū)間……
時(shí)間序列分段函數(shù)(除因子2外,例如240分為2與120或者120與2,因數(shù)據(jù)段數(shù)太少或
者子區(qū)間長(zhǎng)度太短將影響回歸效果)語法如下:
FactorMatrix,FactorNum = HurstFactorization(x)
x:時(shí)間序列長(zhǎng)度确垫。
輸出參數(shù):
FactorMatrix:時(shí)間序列分段方案;
FactorNum:時(shí)間序列分段方案數(shù)量。
py文件 HurstFactorization.py如下:
# -*- coding: utf-8 -*-
import math
def HurstFactorization(x): # hurstFactorization
# codebyawang6254978@163.com
# 2017 09 20
# 因子分解,以4開始以X/4結(jié)束
# floor函數(shù)表示四舍五入
FactorMatrix = []
N = int(math.floor(x / 4))
# 方案數(shù)量初始為0
FactorNum = 0
for i in range(4, N + 1):
# i可以被x整除,即得到一組分解方案
if x % i == 0:
# 方案數(shù)量+1
FactorNum = FactorNum + 1
# 將可行方案存儲(chǔ)到FactorMatrix中
FactorMatrix.append([i, x / i])
return FactorMatrix, FactorNum
函數(shù)測(cè)試240共有14個(gè)分段方案:
X=240
%調(diào)用HurstFactorization函數(shù)
﹥﹥[FactorMatrix,FactorNum]=HurstFactorization(x)
%分解方案序列
FactorMatrix=
4 60
……
60 4
FactorNum=
14
(2) Hurst指數(shù)計(jì)算
時(shí)間序列 Hurst指數(shù)計(jì)算函數(shù)語法如下:
HurstExponent=HurstCompute(Xtimes)
輸入?yún)?shù):
Xtimes:時(shí)間序列數(shù)據(jù)帽芽。
HurstExponent:為二元向量,第一元素為時(shí)間序列的 Hurst指數(shù),第二元素為回歸分 析常數(shù)項(xiàng)删掀。
注:回歸模型log((R/S)n)=log(K)+Hlog(n)。
PY文件 HurstCompute.py如下:
# -*- coding: utf-8 -*-
import numpy as np
from numpy.matlib import repmat
from HurstFactorization import HurstFactorization
def HurstCompute(Xtimes):
# HurstCompute
#codebyawang6254978@163.com
# 2017-09-20
# 輸入?yún)?shù)為Xtimes
LengthX = len(Xtimes)
# 進(jìn)行因式分解
FactorMatrix, FactorNum =HurstFactorization(LengthX)
# 定義LogRS
LogRS = []
# 定義LogN
#LogN=np.zeros([FactorNum, 1])
LogN = []
# 分組計(jì)算
for i in range(0,FactorNum):
# 根據(jù)因式分解方案,將數(shù)量進(jìn)行分組
# 例如 FactorMatrix(i,:)=[8 30]
# 將240個(gè)元素的列向量,轉(zhuǎn)換為8X30的矩陣
dataM = np.reshape(Xtimes,FactorMatrix[i])
# print dataM.shape
#dataM=reshape(Xtimes,FactorMatrix(i,:))
# 計(jì)算矩陣每列的均值
MeanM = np.mean(dataM, axis=0)
SubM = dataM - repmat(MeanM, FactorMatrix[i][0], 1)
RVector = np.zeros([FactorMatrix[i][1], 1])
SVector = np.zeros([FactorMatrix[i][1], 1])
# 計(jì)算(R/S)n的累加
for j in xrange(0, FactorMatrix[i][1]):
SubVector = np.cumsum(SubM[:, j])
RVector[j] = max(SubVector) - min(SubVector)
SVector[j] = np.std(dataM[:, j])
# 分別計(jì)算LogRS导街、LogN
LogRS.append(np.log(np.sum(RVector / SVector) / FactorMatrix[i][1]))
LogN.append(np.log(FactorMatrix[i][0]))
# 使用最小二乘法進(jìn)行回歸,計(jì)算赫斯特指數(shù)HurstExponent
HurstExponent = np.polyfit(LogN, LogRS, 1)
return HurstExponent
return HurstExponent函數(shù)測(cè)試的 PY 文件testHurstCompute.py如下測(cè)試方法生成一組布朗運(yùn)動(dòng)序列,計(jì)算布朗運(yùn)動(dòng)序列對(duì)數(shù)序列的 Hurst指數(shù),共測(cè)試10次:
# -*- coding: utf-8-*-
from HurstCompute import HurstCompute
import matplotlib.pyplot as plt
testNum = 10
# 并將結(jié)果存儲(chǔ)在result中
result = np.zeros([testNum, 2])
for i in xrange(0, testNum):
n = 120 *(i + 1)
dt = 1
# 生存長(zhǎng)度不同的布朗運(yùn)動(dòng)序列
y =np.cumsum(dt ** 0.5 * np.random.random((1, n)))
# 計(jì)算每組序列的Hurst值
result[i,:] = HurstCompute(np.log(y))
#生成圖表
plt.plot(range(len(result)), result[:, 0], '*')
#設(shè)置標(biāo)題
plt.title("PyPlot First Example")
#顯示圖表
plt.show()
測(cè)試結(jié)果圖像如圖所示披泪。
結(jié)果說明:圖16.1橫軸表示1~10共10次計(jì)算測(cè)試,縱軸表示每次測(cè)試計(jì)算出的 Hurst
指數(shù)值。
(3) 移動(dòng)平均 Hurst指數(shù)計(jì)算
使用上證指數(shù)2000至2017年上證綜指時(shí)間序列數(shù)據(jù),計(jì)算其給定移動(dòng)平均長(zhǎng)度的 Hurst指數(shù)搬瑰。編寫 MoveHurst.m函數(shù),其中cyclength為計(jì)算周期,用戶可根據(jù)需求 進(jìn)行修改款票。
例如計(jì)算120個(gè)交易日的 Husrt指數(shù),使用的數(shù)據(jù)為[t-119,t]的價(jià)格數(shù)據(jù),移動(dòng)平均的意思為根據(jù)t的向前移動(dòng),計(jì)算指數(shù)的數(shù)據(jù)為[t-119,t]的價(jià)格數(shù)據(jù),同時(shí)根據(jù)t進(jìn)行移動(dòng)。代碼如下:
import xlrd
# MoveHurst
# codebyawwheng 2017 9 20
# 讀取xlsx文件
workbook = xlrd.open_workbook("shindex.xlsx")
# 讀取Sheet1工作簿
sheet1 = workbook.sheet_by_name('Sheet1')
# 獲取行指針
rows = sheet1.nrows
Prices = []
dates = []
for i inxrange(rows): # 循環(huán)指針并讀取價(jià)格與時(shí)間數(shù)據(jù)至Prices,dates Prices.append(sheet1.row_values(i)[0])
dates.append(int(sheet1.row_values(i)[1]))
# 數(shù)據(jù)長(zhǎng)度
DataLength = len(Prices)
# 計(jì)算周期
cyclength = 120
# 數(shù)據(jù)長(zhǎng)度是否大于計(jì)算周期,若只有100個(gè)數(shù)據(jù)
# 不可能計(jì)算出120計(jì)算周期的Hurst指數(shù)的
if cyclength> DataLength:
plt.plot(range(1, 100), range(1,100), "r*", range(1, 100), range(100, 1, -1), "ro")
else:
# 將價(jià)格數(shù)據(jù)轉(zhuǎn)換為對(duì)數(shù)數(shù)據(jù)
logData = np.log(Prices)
# 計(jì)算價(jià)格的對(duì)數(shù)數(shù)據(jù)對(duì)應(yīng)的每日收益率
IndexReturn=(np.array(logData[1:])-np.array(logData[:-1]).tolis())
# 生成Hurst指數(shù)并初始化為NaN
hurstE = np.array([np.nan] *DataLength)
# 計(jì)算移動(dòng)的hurst指數(shù)
for i in xrange(0, DataLength -cyclength + 1):
HurstExponent =HurstCompute(IndexReturn[i:i + cyclength - 1])
hurstE[cyclength + i - 1] =HurstExponent[0]
# 創(chuàng)建圖表
plt.figure(1)
# 在圖表1中創(chuàng)建HurstExponent子圖
ax1 = plt.subplot(211)
# 設(shè)置y軸標(biāo)簽
plt.ylabel("HurstExponent")
# 設(shè)置X軸刻度
ax.set_xticklabels(dates,rotation=1)
# 設(shè)置數(shù)據(jù)與數(shù)據(jù)寬度
plt.plot(hurstE, linewidth=0.5)
# 在圖表2中創(chuàng)建logIndex子圖2
ax2 = plt.subplot(212)
plt.ylabel("logIndex")
plt.plot(logData, linewidth=0.5)