一、数据来源
1、tushare
(1)优点
数据很全,经得起验证,准确率不错;学生党免费使用!这点必须夸爆,这么好的接口居然可以对学生免费;文档查阅方便,接口使用实例详实,点赞!
(2)缺点
有积分制度和频率限制,写程序必须考虑频率限制比如每分钟获取次数;需要注册和登录,比较繁琐;
(3)解决高频访问历史行情数据方法
构建本地数据库,每日更新,不直接访问tushare。只支持日级行情数据,高频数据还得花钱。
二、数据结构
所有数据存放在名为stock data的文件夹里,每只股票分别存放在csv文件里,例如中国平安的行情数据文件夹名为000001.SZ.csv,每个csv文件包含的股票行情数据有:日期,开盘价,收盘价,最低价,最高价,交易量,涨跌,macd,dif,dea。存储数据结构如下图所示
指标名称 | 变量名 |
---|---|
日期 | date |
开盘价 | open |
收盘价 | close |
最低价 | high |
最高价 | low |
交易量 | vol |
涨跌 | x |
macd | macd |
dif | dif |
dea | dea |
三、更新方式
用一个txt文件保存上一次更新的日期的下一次,那么,下一次更新数据时,先读取txt文件,然后,只需获取文件中日期到当日的数据。
1、读取上一次存储时间
# 读取上一次存储时间
with open('date.txt', 'r',encoding='utf-8') as file:
last_time=file.read()
2、保存本次更新时间
today=datetime.now()#当日
import datetime
next_day=today+datetime.timedelta(days=1)#下一日
#转换成字符串
today=today.strftime('%Y%m%d')
next_day=next_day.strftime('%Y%m%d')
# 保存本次更新时间
with open('date.txt', 'w',encoding='utf-8') as file:
file.write(next_day)
四、完整代码
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import tushare as ts
import baostock as bs
from datetime import datetime
'''
需要输出哪些数据?
return:
日期,开盘价,收盘价,最低价,最高价,涨跌,macd,dif,dea
date,open,close,low,high,vol,涨跌,macd,diff,dea
'''
today=datetime.now()#当日
import datetime
next_day=today+datetime.timedelta(days=1)#下一日
#转换成字符串
today=today.strftime('%Y%m%d')
next_day=next_day.strftime('%Y%m%d')
#获取股票代码
# 读取上一次存储时间
with open('date.txt', 'r',encoding='utf-8') as file:
last_time=file.read()
def macd(code,start_date=last_time,end_date=today):
#获取数据
pro=ts.pro_api('你的TOKEN')
#获取日k线数据
df=pro.daily(ts_code=code,start_date=last_time,end_date=today)
#删除不需要的数据
df=df.drop('ts_code',axis=1)
df=df.drop('pre_close',axis=1)
df=df.drop('change',axis=1)
df=df.drop('pct_chg',axis=1)
df=df.drop('amount',axis=1)
df=df.sort_values(by='trade_date')
#将成交量缩小一万倍
df.loc[:,['vol']]=df.loc[:,['vol']].apply(lambda x:x/10000)
df.loc[:,['vol']]=df.loc[:,['vol']].round(2)
#ema计算函数
def ema(num,data=df):
ema = [data['close'][0]] * len(data)
for i in range(1, len(data)):
ema[i] = ema[i-1] * (num-1)/(num+1) + data['close'][i] * 2/(num+1)
return ema
#计算dea
def dea(num,data):#传入数组numpy.array
dea = [data[0]] * len(data)
for i in range(1, len(data)):
dea[i] = dea[i-1] * (num-1)/(num+1) + data[i] * 2/(num+1)
return np.array(dea)
ema_12=np.array(ema(12))
ema_26=np.array(ema(26))
dif=ema_12-ema_26
dea=dea(9,dif)
macd=(dif-dea)*2
#转化为pd
df1={'macd':macd,'dif':dif,'dea':dea}
df1=pd.DataFrame(df1)
#连接数据
df=df.join(df1)
df=df.round(2)
print(df)
#判断涨跌,1为涨,0为跌
def f(x):
if x>=0:
return 1
else:
return 0
x=(df['close']-df['open']).apply(f)
#调整列顺序
df=df.loc[:,['trade_date','open','close','low','high','vol','macd','dif','dea']]
#插入涨跌数据
df.insert(loc=6,column='x',value=x)
df.to_csv('./stock_data/%s.csv'%code,mode='a',header=False)
#存储成功,更新存储时间
code_list=['601288.SH','001979.SZ','600048.SH','002920.SZ','000560.SZ',
'002377.SZ','002574.SZ','600115.SH','002410.SZ','300285.SZ',
'300760.SZ','601963.SH','601328.SH','601916.SH','601318.SH',
'601628.SH','000333.SZ','000001.SZ','600016.SH','601988.SH',
'601398.SH','601939.SH','600036.SH','601633.SH','002594.SZ',
'000625.SZ','300059.SZ']
for i in code_list:
print(i)
macd(code=i)
# 保存本次更新时间
with open('date.txt', 'w',encoding='utf-8') as file:
file.write(next_day)
五、后续改进
数据库只保存开盘价、收盘价、最低价、最高价等行情数据,macd等指标由历史数据导入之后再进行计算且不进行保存。
参考文献
日期转字符串
python datetime.timedelta()函数介绍
pandas官网
重置dataframe索引