网上下载的,因为是2年前的代码,有两处因为函数升级,报错,用了2天才完善好,分享有缘人。让大家少走弯路。
使用前需要有tushare的KEY才能下载股票数据,注册后就可获得
Tushare大数据社区Tushare为金融数据分析提供便捷、快速的接口,与投研和量化策略无缝对接https://tushare.pro/register?reg=520288
正式代码:
"""
@Author: mukden
@data:
@desc: 每日获得每天股票数据 交易日每天15点~16点之间入库。本接口是未复权行情
"""
import pandas as pd
import os
import tushare as ts
import datetime
import time
from tqdm import tqdm
# 获得股票数据
def get_data(ticker, start_date, end_date, retry_count=3, pause=2):
for _ in range(retry_count):
try:
df = pro.daily(**{
"ts_code": ticker,
"trade_date": "",
"start_date": start_date,
"end_date": end_date,
"offset": "",
"limit": ""
}, fields=[
"ts_code",
"trade_date",
"open",
"high",
"low",
"close",
"pre_close",
"change",
"pct_chg",
"vol",
"amount"
])
except:
time.sleep(pause)
return df
# 更新当天价格
def stock_price_intraday(ticker, folder, default_date='20000101'):
file = folder + '/' + ticker + '.csv'
# 若数据已存在,则选取上次结束日期
# 若数据未存在,则自定义全部数据起始日期
if os.path.exists(file):
# index_col = 指定索引 在默认为None的时候,pandas会自动动将第一列作为索引,并额外添加一列。所以大多我们会使用index_col=0,直接将第一列作为索引, 不额外添加列。
df_old = pd.read_csv(file, index_col=0)
if df_old.empty:
# 空的,从头更新
start_date = default_date
else:
# 不是空的就使用最近更新日期 sort_values = 数据排序 ascending是否按指定列的数组升序排列,默认为True,即升序排列
# iloc 提取数据开始位置 0 第一行 1 第二列 没有冒号:仅提取一个
start_date = str(df_old.sort_values('trade_date', ascending=False).iloc[0, 1]) # 倒序提取最后一天日期,也就是最后一天日期 默认存的数据是升序
start_date = pd.to_datetime(start_date, format='%Y%m%d') + pd.Timedelta(1, 'days') # 日期格式化+1天
start_date = start_date.strftime('%Y%m%d') # 日期格式化 print(start_date)
else:
# 文件不存在,从头更新
start_date = default_date
# 更新到今天
end_date = datetime.date.today().strftime('%Y%m%d')
if start_date == end_date:
# 如果今天反复执行,那么什么也不做,直接return 0
return 0
# 遍历股票代码获取数据 print(' end_date:'+end_date + 'n')
# 拉取数据 #print('nstart_date=' + start_date + ' end_date=' + end_date)
intraday = get_data(ticker=ticker, start_date=start_date, end_date=end_date)
if intraday.empty:
# 拉不到时
# 可能从开始到截止日期未产生数据, 意为从start_date到end_date还没有产生交易数据(闭市) 或股票不存在
if os.path.exists(file):
if not df_old.empty: # 以前获取到过数据,说明此股票存在,只是未产生交易数据
df_old.to_csv(file) # 再保存一次(为了更新修改文件的日期)
else:
# 如果旧文件即为空的,说明股票不存在,删掉文件
os.remove(file)
else:
# 文件不存在, 也拉不到新数据的时候,什么也不做
pass
else:
# 拉得到时
if os.path.exists(file):
# 旧文件存在且非空
if not df_old.empty:
# 新追加旧
df_old = df_old.sort_values('trade_date', ascending=False) # print('n旧文件内容n', df_old) #print('n追加前文件内容n', intraday)
# 1. append() 方法改为返回值, 2. ignore_index避免出现相同的index
intraday = intraday.append(df_old,ignore_index=True)
#print('n追加后文件内容n', intraday)
else:
# 旧文件空的
# 啥也不做
pass
else:
# 旧文件不存在
# 啥也不做
pass
# 当能拉到新数据时, 通过上述判断是否合并旧文件,然后,保存文件
# inplace = True:不创建新的对象,直接对原始对象进行修改;其默认的数值是False,即创建新的对象进行修改,原对象不变
# trade_date 日期列排序搞了2小时不好使,用open列就可以 看来是日期格式问题
#print('类型为 type() = n',type(intraday.iloc[0, 1])) # 输出结果: 添加了下面一行更换数据类型
intraday['trade_date'] = intraday['trade_date'].astype(int)
intraday.sort_values('trade_date', ascending=True, inplace=True) # for backtrader
#print('n排序后新文件内容n', intraday)
intraday.index.name = 'timestap'
intraday.to_csv(file)
return 1
def main(folder, test=True):
# 股票列表
# SZ | SH | BJ
if test:
tickers = pro.stock_basic().ts_code.tolist()[:3]
else:
tickers = pro.stock_basic(market='主板').ts_code.tolist()
for ticker in tqdm(tickers):
status = stock_price_intraday(ticker, folder) # 0 pass 1 success
if status == 0:
continue
if status == 1:
time.sleep(0) # 出现频繁调用错误再设置时间
print('All data got')
if __name__ == '__main__':
# 初始化pro接口
pro = ts.pro_api('你的KEY')
# 设置存数据文件夹路径
folder = '../stock/daily'
# 更新数据 默认false 只下载主板股票, true 下载前3只测试用
main(folder, test=False)



