计算上证日K与个股的相关性系数

这算是一个面试的题吧。需求是把与上证日K趋势的相关性系数大于80%的个股挑选出来。

这是一个面试题,当时面试一个做量化交易的公司的一个面试题,不过对方对我这个脚本似乎不太满意,面试的后续就没有后续了。

思路

数据获取

在上交所正常盘面交易的股票大约有3400多只,如果写爬虫去获取每一只股票的相关信息那么工程量肯定不小,当然加上现在各个金融网站的反爬手段,单单写爬虫这点可能都会卡住,就在网上看看有没有什么免费的API可以使用,无意间找到了tushare这个模块,全中文手册,使用全免费,这个当然是不错的。后面在使用的过程中发现在获取当日交易情况的时候会出现不稳定然后中断获取的情况,这个······毕竟免费的而且没有像各个官方的限制,其实还是很不错的,而且也提供了大量的方法可以使用。

数据处理

在获取完数据之后应该对数据进行处理,我查看了一下tushare输出的数据类型,基本上都是DataFormat的类型,这点处理上是比较有利的,但是考虑到tushare在获取数据的时候的稳定性情况,我决定不直接使用网络数据,转而使用把数据保存到本地后再使用,在使用完成后我们可以对本地文件进行删除。在这里我不考虑对每一项数据都进行入库处理,因为tushare提供了一个将数据保存的本地的方法,使用起来也十分方便。

提取结果

每只股票的代码是6位数,相关性系数检验在80%以上的应该不会很多,所以我采用直接将股票代码保存在一个txt文本文件中。

方法

获取有效股票代码

选择使用tushre之后,知道了如何获取个股的数据和上证指数,但是模块中没有提供我想要的单单的股票代码,我也不能用循环去生成股票代码,虽然说股票的代码确实是有顺序的,但是不敢保证生成的股票代码的那只股票现在是否还在市。想想,如果可以获取当日的交易的所有股票行情的话这个问题不就解决了,因为当日还在交易的所有股票肯定还没有退市的。查一下手册,发现有一个函数是一次性获取当前交易所有股票的行情数据,ok就是他了。获取到了之后保存为本地excel表格,再从表格中读取股票代码。

计算K线趋势

后面发现使用tushare获取的数据并没有计算出当日的K线的走势,不过没关系了,他给出的数据中有一天的开盘价,收盘价,最高价和最低价,这些足够计算当日的K线了。正值为红,负值为绿。在计算的过程中发现读出来的数据是一个列表,其中包括表头的值,于是取下标从1开始。列表的计算在python并不是很方便,因为python并没有像c一样提供一个数组的数据结构,幸好前几天刚刚学习了numpy模块,现学现卖了,把读取出来的列表通过numpy模块转换成数组,再使用numpy模块内置算法计算,这样大大的减少了工作量。

相关性系数

Pearson系数也称为是简单相关性系数,但是计算中要求两个计算的量近似服从二维的正态分布,而上证K线的趋势和个股K线的趋势其实并没有什么规律,不能使用这个,于是采用Spearman系数,Spearman系数在计算的过程中并不要求计算的两组数字的分布规律。

工作流程

工作流程就是获取上证指数的信息,保存为表格,读表,计算K线,获取当日交易情况,保存为表格,读表,处理,得出个股编号,再通过编号去获取该股票的历史数据,保存为表格,读表,计算K线,再把个股的K线与上证的K线从获取之日开始计算,得出Spearman系数,最后把大于Spearman系数大于80%的个股编号保存下来,不满足条件的直接忽略。最后计算完该股票后把保存该股票信息的excel表格删掉,减少占用磁盘空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# *-*coding='UTF-8'*-*
import tushare as ts
import numpy as np
import xlrd
import pandas
import time
import os
# 获取上证指数的K线
def getshangzheng_K():
#读取上证指数的日K
shangzheng = ts.get_hist_data('sh',ktype='D',start='2017-07-01')
# 将上证指数的日K存入excel表格
shangzheng.to_excel('sh.xlsx',sheet_name='Sheet1')
(filepath,tempfilename)=os.path.split('sh.xlsx')
return tempfilename
# 读取excel表格
def read_excel(fileName='',sheet='Sheet1'):
workbook=xlrd.open_workbook(fileName)
sheet1=workbook.sheet_by_name(sheet)
return sheet1
# 计算K线的趋势
def K(sheet,open_col_values=False,close_col_values=False):
open_price=sheet.col_values(open_col_values)
close_price=sheet.col_values(close_col_values)
open_price_array=np.array(open_price[1:],dtype=float)
close_price_array=np.array(close_price[1:],dtype=float)
movements=close_price_array-open_price_array
the_k=pandas.Series(movements)
return the_k
# 获取上证交易所中当日正在交易的所有股票信息
def get_today_stock():
todayall=ts.get_today_all()
todayall.to_excel('todays.xlsx')
(filepath,tempfilename)=os.path.split('todays.xlsx')
return tempfilename
# 获取上证中正在交易的股票的代码
def get_stock_num(sheet=''):
todaycols=sheet.col_values(1)
return todaycols
# 获取个股的详细信息
def get_stock_info(stock_num):
stock_number=str(stock_num)
stock_info=ts.get_hist_data(stock_number,start='2017-07-01',ktype='D')
stock_info.to_excel(stock_number+'.xlsx')
(filepath,tempfilename)=os.path.split(stock_number+'.xlsx')
return tempfilename
# 计算相关性系数,因为数据分布无规则,所以计算spearman相关系数
def find_spearman(sh,stock):
corr_spearman=sh.corr(stock,method='spearman')
return corr_spearman
if __name__=='__main__':
#获取上证信息并保存为表格
sh_excel=getshangzheng_K()
#读取上证信息表格
sh_sheet=read_excel(sh_excel,sheet='Sheet1')
# 计算上证日K的趋势
sh_K=K(sh_sheet,open_col_values=1,close_col_values=3)
# 计算个股的日K趋势
today_stock_exccel=get_today_stock()
#实际使用中,read_excel函数的第一个参数可以直接写成文件名,这样不必每次执行都重复去获取数据
today_sheet=read_excel(today_stock_exccel,sheet='Sheet1')
stock_nums=get_stock_num(today_sheet)
for stock_num in stock_nums[1:]:
stock_excel=get_stock_info(stock_num)
stock_sheet=read_excel(fileName=stock_excel,sheet='Sheet1')
stock_K=K(sheet=stock_sheet,open_col_values=1,close_col_values=3)
#以上为计算个股的K线趋势
#此处计算Spearman系数
spearman=find_spearman(sh_K,stock_K)
if spearman>0.800:
with open('save.txt','a+') as fp:
fp.write(str(stock_num).encode('utf8') + '\t')
print 'done one',time.strftime("%Y-%m-%d %X", time.localtime())
else:
print 'let one go',time.strftime("%Y-%m-%d %X", time.localtime())
#这句为删除使用过的表格,如果想保留相关表格,可以将其注释掉
os.remove(str(stock_num)+'.xlsx')

在实际使用的过程中我们可以将上证的表格和当日成交的表格给保留下来,并在代码中注释掉相应的执行语句,将文件名直接填成参数,这样可以避免获取数据的时候tushare的不稳定造成的影响。

最后,计算的结果为300719 300716 002781 000555

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束感谢您的阅读-------------