基本思路是获取股价收盘信息后,使用希尔伯特黄变换将股价波动数据拆解为不同周期的波动曲线。再本别利用频谱分析计算每一个曲线的频率。目标是将股价波动数据拆解为不同周期波动的叠加态。
1.获取收盘价
富途有很好的API接口,给我这种小散送了每个月的使用次数也够了。
2.希尔伯特黄变换
利用pyhht包,官方的文档磕磕绊绊看懂。
合起来
import pyhht
from pyhht.visualization import plot_imfs
import numpy as np
import random
from futu import *
import pandas as pd
import sys
import re
def likaiHHT_savefig_imfs(filepath,xlabel,title,signal, imfs, time_samples=None, fignum=None):
if time_samples is None:
time_samples = np.arange(signal.shape[0])
n_imfs = imfs.shape[0]
plt.figure(num=fignum)
axis_extent = max(np.max(np.abs(imfs[:-1, :]), axis=0))
# Plot original signal
ax = plt.subplot(n_imfs + 1, 1, 1)
ax.plot(time_samples, signal)
ax.axis([time_samples[0], time_samples[-1], signal.min(), signal.max()])
ax.tick_params(which='both', left=True, bottom=False, labelleft=True,labelbottom=False)
ax.grid(False)
ax.set_ylabel('signal')
ax.set_title(title)
# Plot the IMFs
for i in range(n_imfs - 1):
print(i + 2)
ax = plt.subplot(n_imfs + 1, 1, i + 2)
ax.plot(time_samples, imfs[i, :])
ax.axis([time_samples[0], time_samples[-1], -axis_extent, axis_extent])
ax.tick_params(which='both', left=True, bottom=False, labelleft=True,labelbottom=False)
ax.grid(False)
ax.set_ylabel('imf' + str(i + 1))
# Plot the residue
ax = plt.subplot(n_imfs + 1, 1, n_imfs + 1)
ax.plot(time_samples, imfs[-1, :], 'r')
ax.axis('auto')
#ax.tick_params(which='both', left=False, bottom=False, labelleft=False,labelbottom=False)
ax.grid(False)
ax.set_ylabel('res.')
ax.set_xlabel(xlabel)
plt.savefig(filepath)
return
def imfs_max_freq(imfs,sample_rate,fft_size):
#计算每一个imfs频谱中最高的那个频率
n_imfs=imfs.shape[0]
max_freq=[]
for i in range(n_imfs-1):
xs=imfs[i,:][:fft_size]
xf=np.fft.rfft(xs)/fft_size
freqs=np.linspace(0,sample_rate/2,fft_size//2+1)
xfp=20*np.log10(np.clip(np.abs(xf), 1e-20, 1e100))
max_freq.append(freqs[np.argmax(xfp)])
return max_freq
def HHTstock(stockid,begindate,enddate):
closelist=[]
quote_ctx = OpenQuoteContext(host='127.0.0.1', port=11111) # 创建行情对象
ret, data, page_req_key = quote_ctx.request_history_kline(stockid, start=begindate, end=enddate, max_count=5) # 每页5个,请求第一页
if ret == RET_OK:
#print(data)
#print(data['code'][0]) # 取第一条的股票代码
#print(data['close'].values.tolist()) # 第一页收盘价转为list
closelist=data['close'].values.tolist()
else:
print('error:', data)
while page_req_key != None: # 请求后面的所有结果
#print('*************************************')
ret, data, page_req_key = quote_ctx.request_history_kline(stockid, start=begindate, end=enddate, max_count=5, page_req_key=page_req_key) # 请求翻页后的数据
if ret == RET_OK:
#print(data)
closelist.extend(data['close'].values.tolist())
else:
print('error:', data)
print('All pages are finished!')
quote_ctx.close() # 关闭对象,防止连接条数用尽
trading_day_num=len(closelist)
t=np.linspace(0,trading_day_num,trading_day_num)
np_close=np.array(closelist)
decomposer=pyhht.EMD(np_close)
imfs=decomposer.decompose()
#plot_imfs(np_close,imfs,t)
likaiHHT_savefig_imfs('./'+stockid+'.png','t/day',stockid,np_close,imfs,t)
ls=imfs_max_freq(imfs,1,1000)#算每一段曲线的频率
print(ls)
return;
def main():
HHTstock('HK.01816','2012-9-11','2020-9-18')
if __name__ == '__main__':
main()
计算结果