若要验证量化交易策略是否有效,需要有足够的历史行情数据作为支撑,故本文将使用Python编写爬虫对上证、深证全部股票的历史行情数据进行爬取。
1.下载上证、深证所有股票历史行情数据到本地数据库
2.每日更新股票行情数据到本地数据库
3.数据库使用mysql
数据来源:
股票代码—https://www.banban.cn/gupiao/list_sh.html
股票行情数据—http://quotes.money.163.com/trade/lsjysj_600018.html
获取所有股票代码
创建数据库STOCK,用于存储股票数据
以“s_股票代码”在数据库STOCK中创建/添加数据表,用于存储每只股票的历史行情数据
遍历各表,读取各表最后一条记录中的开盘日期;输入实际最新开盘日期;两日期比对,若日期为空则表为空 故下载该股全部历史数据,若日期不同,则表中数据非当前最新行情数据,故更新数据至实际最新开盘日期;若日期相同,则表明表中数据已是最新数据,故跳过。
将每只股票的历史行情数据对应存储到各表
导入模块及设置headers
import requests,pymysql,re,datetime
import pandas as pd
from bs4 import BeautifulSoup
from sqlalchemy import create_engine
headers={
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36'
}
DownStockCode()函数,获取所有股票代码,返回结果示例:[‘600002’,‘600003’…]
#获取所有上证、深证的股票代码,return:['600001','600002','600003'...]
def DownStockCode():
print('开始获取上证、深证股票代码')
count = 0
stockcodeList=[]
urlList = ['https://www.banban.cn/gupiao/list_sh.html','https://www.banban.cn/gupiao/list_sz.html']
for url in urlList:
res = requests.get(url=url,headers=headers)
bs_res = BeautifulSoup(res.text,'html.parser')
stocklist=bs_res.find('div',id='ctrlfscont').find_all('li')
for stock in stocklist:
stockhref=stock.find('a')['href']
list_stockhref=stockhref.strip().split('/')
stock_code=list_stockhref[2]
stockcodeList.append(stock_code)
count += 1
print('当前已获取{}只股票代码'.format(count),end='\r')
print('已获取所有上证、深证股票代码:{}个'.format(count))
return stockcodeList
CreateDatabase(host,user,password,dbname)函数,创建本地数据库STOCK
#创建数据库用于存储股票数据表
def CreateDatabase(host,user,password,dbname):
db = pymysql.connect(
host = host,
user = user,
password = password,
port = 3306
)
cursor = db.cursor()
sql = 'create database if not exists '+ dbname
cursor.execute(sql)
db.close()
print('检查/创建本地存储数据库-STOCK')
CreateTable(host,user,password,dbname,codeList) 函数,根据股票代码 为每只股票创建、添加数据表
#根据股票代码,创建添加股票数据表,用于存储每只股票数据,table:s_600001
def CreateTable(host,user,password,dbname,codeList):
print('开始检查/添加股票数据表')
db = pymysql.connect(
host = host,
user = user,
password = password,
database = dbname
)
cursor = db.cursor()
count = len(codeList)
num = 0
for code in codeList:
num += 1
sql = 'create table if not exists s_'+code+'(\
stockName varchar(250) not null,\
dateTime varchar(250) not null, \
startPrice varchar(100), \
maxPrice varchar(100), \
minPrice varchar(100), \
endPrice varchar(100), \
diffPrice varchar(100), \
diffPercent varchar(100), \
turnoverAmount varchar(100), \
amount varchar(100), \
amplitude varchar(100), \
turnoverPercent varchar(100))'
cursor.execute(sql)
print('检查/添加数据库表:s_{},{}/{}'.format(code,num,count),end='\r')
db.close()
print('数据库表已检查/添加完毕!!! ')
GetNearestDate(host,user,password,dbname) 函数,获取每个股票数据表中的最后一条记录 并提取开盘日期,返回结果示例:[[‘600001’,‘2020-12-3’],[‘600002’,‘NULL’]…]
#获取所有表名,遍历每个表并获取最新行情数据日期返回列表:[[股票代码,最新数据日期],['600001','2020-12-3'],['600002','NULL']]
def GetNearestDate(host,user,password,dbname):
print('开始获取数据库表内股票的最后交易日期')
count_empty = 0 #用于记录空表数量
tablelist = [] #存储获取到的数据库表名
nearestdatelist = []#存储股票代码和最新行情日期
db = pymysql.connect(
host = host,
user = user,
password = password,
database = dbname
)
cursor = db.cursor()
sql_showtables = 'show tables'
cursor.execute(sql_showtables) #查询表名
for i in cursor:
tablelist.append(str(i)) #表名存储到列表
for tablename in tablelist:
code = re.sub('\D','',tablename)#取出表名中的数字,即股票代码code
sql_s_dateTime = 'select * from s_'+code+' order by dateTime desc limit 1' #取出数据表最后一行记录
lastrow = pd.read_sql(sql_s_dateTime,db)
if lastrow.empty:
dateTime = 'Null'
count_empty += 1
else:
dateTime = lastrow['dateTime'][0]
nearestdatelist.append([code,dateTime])
print('已获取:{} 的最后交易日期为:{} 当前获取进度:{}/{} '.format(code,dateTime,len(nearestdatelist),len(tablelist)), end='\r')
db.close()
print('个股最后交易日期获取完毕,共计{}只股票,其中需下载全部数据的股票共{}只'.format(len(nearestdatelist),count_empty))
return nearestdatelist