备忘:到第37课已经全部学完。
一、一些资源
1.购买数据
https://www.yucezhe.com/product/data/trading
2.采集数据
新浪财经、腾讯财经、东方财富
二、获取实时数据
from urllib.request import urlopen
import pandas as pd
pd.set_option('expand_frame_repr',False) #当列太多时不换行
pd.set_option('display.max_rows',5000) #最多显示数据的行数
#返回一个股票的数据:http://hq.sinajs.cn/list=sh600000
#返回一串股票的数据:http://hq.sinajs.cn/list=sh600000,sz000002,sz300001
stock_code_list = ['sh600000','sz000002','sh600002','sz000003','sz300001']
url = 'http://hq.sinajs.cn/list=' + ','.join(stock_code_list)
content = urlopen(url).read().decode('gbk')
content = content.strip() #去掉文本前后的空格、回车等
date_line = content.split('\n') #每行是一个股票的数据
date_line = [i.replace('var hq_str_','').split(',') for i in date_line]
df = pd.DataFrame(date_line,dtype='float')
print(df)
df[0]=df[0].str.split('="')
df['stock_code'] = df[0].str[0].str.strip()
df['stock_name'] = df[0].str[-1].str.strip()
df['candel_end_time'] = df[30] + ' ' + df[31]
print(df)
执行结果

三、获取日线数据
第32课
from urllib.request import urlopen
import json
from random import randint
import pandas as pd
pd.set_option('expand_frame_repr', False)
pd.set_option('display.max_rows', 5000)
# =====创建随机数的函数
def _random(n=16):
"""
创建一个n位的随机整数
:param n:
:return:
"""
start = 10**(n-1)
end = (10**n)-1
return str(randint(start, end))
#http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_dayhfq¶m=sh600103,day,,,320,hfq&r=0.9860043111257255
stock_code = 'sz000001'
type = 'day' # day, week, month分别对用日线、周线、月线
num = 640 # 股票最多不能超过640,指数、etf等没有限制
# 构建url
url = 'http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_%sqfq¶m=%s,%s,,,%s,qfq&r=0.%s'
url = url % (type, stock_code, type, num, _random())
content = urlopen(url).read().decode()
content = content.split('=', maxsplit=1)[-1]
content = json.loads(content)
data = content['data'][stock_code]
if type in data:
data = data[type]
elif 'qfq' + type in data: # qfq是前复权的缩写
data = data['qfq' + type]
else:
raise ValueError('已知的key在dict中均不存在,请检查数据')
df = pd.DataFrame(data)
print(df.head())
#对数据进行整理,其中amout单位是手
rename_dict = {0: 'candle_end_time', 1: 'open', 2: 'close', 3: 'high', 4: 'low', 5: 'amount',6: 'info'}
df.rename(columns = rename_dict,inplace = True)
df['candle_end_time'] = pd.to_datetime(df['candle_end_time'])
if 'info' not in df:
df['info'] = None
print(df.head())
执行结果

备注:
获取5分钟数据:http://ifzq.gtimg.cn/appstock/app/kline/mkline?param=sh600020,m5,,800&_var=m5_today
四、对股票进行复权
import pandas as pd
pd.set_option('expand_frame_repr', False)
pd.set_option('display.max_rows', 5000)
path = "E:\\stock\\01\\data\\sz300001_sample.csv"
df = pd.read_csv(path,encoding = 'gbk',skiprows = 0)
#计算复权涨跌幅
df['涨跌幅'] = df['收盘价']/df['前收盘价']-1
#计算复权因子:假设你一开始有1元钱,投资到这个股票,最终会变成多少钱
df['复权因子'] = (1+df['涨跌幅']).cumprod()
#计算后复权价
df['收盘价_后复权']=df['复权因子']*(df.iloc[0]['收盘价']/df.iloc[0]['复权因子'])
print("计算后复权价")
print(df[['股票代码','股票名称','交易日期','开盘价','最高价','最低价','收盘价','收盘价_后复权']].head())
print("-"*80)
#计算后复权价另一种计算方法:
#initial_price = df.iloc[0]['收盘价'] / (1 + df.iloc[0]['涨跌幅']) # 计算上市价格
#df['收盘价_后复权'] = initial_price * df['复权因子'] # 相乘得到复权价
#计算前复权价
df['收盘价_前复权']= df['复权因子'] *(df.iloc[-1]['收盘价']/df.iloc[-1]['复权因子'])
print("计算前复权价")
print(df[['股票代码','股票名称','交易日期','开盘价','最高价','最低价','收盘价','收盘价_后复权','收盘价_前复权']].head())
print("-"*80)
#计算复权的开盘价、最高价、最低价
df['开盘价_复权'] = df['开盘价']/df['收盘价']*df['收盘价_后复权']
df['最高价_复权'] = df['最高价']/df['收盘价']*df['收盘价_后复权']
df['最低价_复权'] = df['最低价']/df['收盘价']*df['收盘价_后复权']
print("计算复权的开盘价、最高价、最低价:")
print(df.head())
#df.to_csv('output_fuquan_sz300001.csv',index=False,mode='w',float_format='%.15f',header=None,encoding='gbk')
执行结果:

五、对所有股票数据进行采集
通过下面的代码,可以每天将上证的所有股票日线数据采集下来,并且存储到自己电脑的csv文件,方便以后调用。
import os
import json
import pandas as pd
from datetime import datetime
import time
import re
from urllib.request import urlopen
pd.set_option('expand_frame_repr', False)
pd.set_option('display.max_rows', 5000)
def get_content_from_internet(url,max_try_num=10,sleep_time=5):
get_success = False
for i in range(max_try_num):
try:
content = urlopen(url=url,timeout=10).read()
get_success = True
break
except Exception as e:
print("抓取数据报错次数:",i+1,"报错内容:",e)
time.sleep(sleep_time)
#判断是否成功抓取内容
if get_success:
return content
else:
raise ValueError("使用urlopen抓取网页数据不断报错,达到尝试上限,停止程序,请尽快检查。")
def get_today_data_from_sinajs(code_list):
url = 'http://hq.sinajs.cn/list=' + ','.join(code_list)
content = get_content_from_internet(url)
content = content.decode('gbk')
#将数据转换成DataFrame
content = content.strip() #去掉文本前后的空格、回车等
date_line = content.split('\n') #每行是一个股票的数据
date_line = [i.replace('var hq_str_','').split(',') for i in date_line]
df = pd.DataFrame(date_line,dtype='float')
#对DateFrame进行整理
df[0]=df[0].str.split('="')
df['stock_code'] = df[0].str[0].str.strip()
df['stock_name'] = df[0].str[-1].str.strip()
df['candle_end_time'] = df[30] + ' ' + df[31]
df['candle_end_time'] = pd.to_datetime(df['candle_end_time'])
#amount单位是手,volume是元
rename_dict = { 1: 'open', 2: 'pre_close', 3: 'close', 4: 'high', 5: 'low',6:'buy1',7:'sell1',8: 'amount',9:'volume',32:'status'}
df.rename(columns = rename_dict,inplace = True)
# df['status']=df['status'].str.strip('";')
df = df[['stock_code','stock_name','candle_end_time','open','high','low','close','pre_close','amount','volume','buy1','sell1','status']]
return df
print(df)
#http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=1&num=40&sort=symbol&asc=1&node=cyb&_s_r_a=init
#http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=1&num=40&sort=symbol&asc=1&node=hs_a&symbol=_s_r_a=sort
def get_all_today_stock_data_from_sina_marketcenter():
raw_url = "http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=%s&num=40&sort=symbol&asc=1&node=hs_a&symbol=_s_r_a=sort"
page_num = 1
#存储数据的dataframe
all_df = pd.DataFrame()
#开始逐页遍历,获取股票数据
while True:
url = raw_url % (page_num)
print("开始抓取页数:",page_num)
#抓取数据
content = get_content_from_internet(url)
content = content.decode('gbk')
if 'null' in content:
print("抓取到页数的尽头,退出循环。")
break
#通过正则,将key加上引号
content = re.sub(r'(?<={|,)([a-zA-Z][a-zA-Z0-9]*)(?=:)',r'"\1"',content)
#将数据转换成dict格式
content = json.loads(content)
df = pd.DataFrame(content)
#添加交易日期
df['trade_date'] = pd.to_datetime(datetime.now().date())
#取需要的列,trade是收盘价,settlement是前收,volume不是手,是股,amount是元
df = df[['code','name','trade_date','open','high','low','trade','settlement','volume','amount']]
#合并数据
all_df = all_df.append(df,ignore_index=True)
return all_df #加了这一句,只采集第1页
page_num+=1
time.sleep(1)
exit()
# return all_df
#判断今天是否是交易日
def is_today_trading_day():
#获取上证指数今天的数据
df = get_today_data_from_sinajs(code_list=['sh000001'])
sh_date = df.iloc[0]['candle_end_time'] #上证指数最近交易日
#判断今天日期和sh_date是否相同
return datetime.now().date() == sh_date.date()
if is_today_trading_day() is False:
print("今天不是交易日,不需要更新股票数据,退出程序")
exit()
if datetime.now().hour < 15: #保险起见可以小于16
print('今天股票尚未收盘,不更新股票数据,退出程序')
exit()
# df = get_today_data_from_sinajs(code_list=['sh600000'])
# print(df)
df = get_all_today_stock_data_from_sina_marketcenter()
#对股票进行存储:
for i in df.index:
t = df.iloc[i:i+1,:]
stock_code = t.iloc[0]['code']
#构建存储文件
path = 'E:\\stock\\01\\mydata\\'+stock_code + '.csv'
#文件存在,不是新股
if os.path.exists(path):
t.to_csv(path,header= None,index = False,mode='a',encoding='gbk')
else:
#文件不存在
#先将头文件输出
pd.DataFrame(columns = ["数据由xx整理"]).to_csv(path,index=False,encoding='gbk')
t.to_csv(path,index = False,mode='a',encoding='gbk' )
print(stock_code+"数据存储成功")