Python 获取期货历史 k 线数据
前言
玩过股票的几乎都知道,股票历史交易日的开盘价、收盘价、最高价、最低价等指标是选股的重要依据。虽然仅仅依靠它们无法在股市中盘满钵满,但是运用好它确实能在较大程度上提高我们的赚钱概率。
对于期货,以上那几个指标也是存在的。
当前的金融数据查看工具确实够多,例如东方财富、同花顺等知名财经网站。它们的数据很全,但是集成程度太高了,难以满足每个人的个性化需求。比如说我四大期货交易所的全部期货为研究对象,想研究它们的历史日k线数据,那么导出这么多数据无疑是一个巨大的工程。并且这些财经网站可能并不会给免费用户提供批量导出数据的功能。
这个时候还想获取这些数据怎么办呢?冲会员当然是一个选择,不过这样子还是容易受制于人,即使是会员,个性化程度还是不够高。
为了解决“ 期货k线数据难以个性化导出 ”这个问题,我们可以尝试使用 Python 对财经网站进行爬虫以获取源数据,再从里面提取出我们需要的信息,比如本次的k线数据,之后再保存到表格文件里面。
上面的介绍语与之前的分享的 使用Python获取股票k线数据这篇文章几乎是一样的,想看股票数据获取方法的可以转到这篇文章。
嗯,我也不知道说啥了,就稍微改了一下。
开始之前
- Python版本要求
Python 3
如果没有安装 Python,可以参考我写的这篇安装教程
2. 需要安装的库
pandas
requests
库的安装方法是:打开 cmd(命令提示符或者其他终端工具),输入以下代码
pip install pandas requests
输入完毕,按 Enter 键执行代码,等待 successfully 出现即可
代码展示
需求 1 描述
将 4 大期货交易所的期货基本信息,譬如期货名称、代码、期货归属交易所等信息获取下来,并保存到文件 期货信息表.csv 里面。并且选择该信息表里面的一个期货,将它的历史 k 线数据存储到以其名称命名的 cvs 文件中
代码 1 示例
import pandas as pd
import requests
from urllib.parse import urlencode
def get_futures_base_info() -> pd.DataFrame:
获取四个期货交易所全部期货基本信息
EastmoneyHeaders = {
'Host': '19.push2.eastmoney.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'http://quote.eastmoney.com/center/gridlist.html',
params = (
('np', '1'),
('fltt', '2'),
('invt', '2'),
('fields', 'f1,f2,f3,f4,f12,f13,f14'),
('pn', '1'),
('pz', '300000'),
('fid', 'f3'),
('po', '1'),
('fs', 'm:113,m:114,m:115,m:8'),
('forcect', '1'),
rows = []
cfg = {
113: '上期所',
114: '大商所',
115: '郑商所',
8: '中金所'
response = requests.get(
'https://push2.eastmoney.com/api/qt/clist/get', headers=EastmoneyHeaders, params=params)
for item in response.json()['data']['diff']:
code = item['f12']
name = item['f14']
secid = str(item['f13'])+'.'+code
belong = cfg[item['f13']]
row = [code, name, secid, belong]
rows.append(row)
columns = ['期货代码', '期货名称', 'secid', '归属交易所']
df = pd.DataFrame(rows, columns=columns)
return df
def get_ftures_k_history(secid: str, beg: str = '19000101', end: str = '20500101', klt: int = 101, fqt: int = 1) -> pd.DataFrame:
获取k线数据
Parameters
----------
secid : 根据 get_futures_base_info 函数获取
获取4个交易所期货数据,取 secid 列来获取 secid
beg : 开始日期 例如 20200101
end : 结束日期 例如 20200201
klt : k线间距 默认为 101 即日k
klt : 1 1 分钟
klt : 5 5 分钟
klt : 101 日
klt : 102 周
fqt: 复权方式
不复权 : 0
前复权 : 1
后复权 : 2
Return
------
DateFrame : 包含期货k线数据
EastmoneyHeaders = {
'Host': '19.push2.eastmoney.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'http://quote.eastmoney.com/center/gridlist.html',
EastmoneyKlines = {
'f51': '日期',
'f52': '开盘',
'f53': '收盘',
'f54': '最高',
'f55': '最低',
'f56': '成交量',
'f57': '成交额',
'f58': '振幅',
'f59': '涨跌幅',
'f60': '涨跌额',
'f61': '换手率',
fields = list(EastmoneyKlines.keys())
columns = list(EastmoneyKlines.values())
fields2 = ",".join(fields)
params = (
('fields1', 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13'),
('fields2', fields2),
('beg', beg),
('end', end),
('rtntype', '6'),
('secid', secid),
('klt', f'{klt}'),
('fqt', f'{fqt}'),
base_url = 'https://push2his.eastmoney.com/api/qt/stock/kline/get'
url = base_url+'?'+urlencode(params)
json_response = requests.get(
url, headers=EastmoneyHeaders).json()
data = json_response['data']
if data is None:
print(secid, '无数据')
return None
# code = data['code']
# name
# name = data['name']
klines = data['klines']
rows = []
for _kline in klines:
kline = _kline.split(',')
rows.append(kline)
df = pd.DataFrame(rows, columns=columns)
return df
if "__main__" == __name__:
# 获取全市场期货基本数据,即下面的 4 列信息
# ['期货代码', '期货名称', 'secid', '归属交易所']
futures_info_df = get_futures_base_info()
futures_info_df.to_csv('期货信息表.csv',index=None, encoding='utf-8-sig')
print('期货基本信息表如下')
print(futures_info_df)
secids = futures_info_df['secid']
futures_names = futures_info_df['期货名称']
# 随便选了 1 个期货来测试
secid = secids[0]
# 随便选的期货名称
futures_name = futures_names[0]
print(f'正在获取期货:{futures_name} 的历史 k 线数据')
# 获取期货历史 日k 线数据
# secid 可以在文件 期货信息表.csv 中查看,更改 secid 即可获取不同的期货数据
df = get_ftures_k_history(secid)
df.insert(0, '期货名称', [futures_name for _ in range(len(df))])
df.to_csv(f'{futures_name}.csv', index=None, encoding='utf-8-sig')
print(f'期货 : {futures_name} 的 k 线数据已保存到文件 {futures_name}.csv 中')
运行结果
屏幕输出
期货基本信息表如下
期货代码 期货名称 secid 归属交易所
0 ZCM 动力煤主力 115.ZCM 郑商所
1 ZC109 动力煤109 115.ZC109 郑商所
2 ZC108 动力煤108 115.ZC108 郑商所
3 ZC203 动力煤203 115.ZC203 郑商所
4 ZC202 动力煤202 115.ZC202 郑商所
.. ... ... ... ...
780 bum 石油沥青主力 113.bum 上期所
781 bu2106 石油沥青2106 113.bu2106 上期所
782 fus 燃油次主力 113.fus 上期所
783 fu2105 燃油2105 113.fu2105 上期所
784 fb2204 纤维板2204 114.fb2204 大商所
[785 rows x 4 columns]
正在获取期货:动力煤主力 的历史 k 线数据
期货 : 动力煤主力 的 k 线数据已保存到文件 动力煤主力.csv 中
生成的文件 期货信息表.csv 内容展示
所获取的期货 k 线数据展示
以上演示了获取一个期货数据的方法。这里要注意的是,获取期货数据需要 secid 这个参数,我以将 4 个交易所的全部期货基本信息存储在文件 期货基本信息.csv 中,打开即可看到具体信息,大家看按注释修改代码里面的 secid 参数即可,不会的可以留言或者私信我帮你修改。
以上代码展示了怎么获取某个期货的k线数据,如果想批量获取多个期货的数据怎么办呢?譬如获取 期货信息表 里面的前 10 个。我直接上代码吧!
需求 2 描述
获取文件 期货信息表.csv 里面的前 10 个期货历史 k 线数据并存储到各自的 csv 文件里面
代码 2 示例
import pandas as pd
import requests
from urllib.parse import urlencode
def get_futures_base_info() -> pd.DataFrame:
获取四个期货交易所全部期货基本信息
EastmoneyHeaders = {
'Host': '19.push2.eastmoney.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'http://quote.eastmoney.com/center/gridlist.html',
params = (
('np', '1'),
('fltt', '2'),
('invt', '2'),
('fields', 'f1,f2,f3,f4,f12,f13,f14'),
('pn', '1'),
('pz', '300000'),
('fid', 'f3'),
('po', '1'),
('fs', 'm:113,m:114,m:115,m:8'),
('forcect', '1'),
rows = []
cfg = {
113: '上期所',
114: '大商所',
115: '郑商所',
8: '中金所'
response = requests.get(
'https://push2.eastmoney.com/api/qt/clist/get', headers=EastmoneyHeaders, params=params)
for item in response.json()['data']['diff']:
code = item['f12']
name = item['f14']
secid = str(item['f13'])+'.'+code
belong = cfg[item['f13']]
row = [code, name, secid, belong]
rows.append(row)
columns = ['期货代码', '期货名称', 'secid', '归属交易所']
df = pd.DataFrame(rows, columns=columns)
return df
def get_ftures_k_history(secid: str, beg: str = '19000101', end: str = '20500101', klt: int = 101, fqt: int = 1) -> pd.DataFrame:
获取k线数据
Parameters
----------
secid : 根据 get_futures_base_info 函数获取
获取4个交易所期货数据,取 secid 列来获取 secid
beg : 开始日期 例如 20200101
end : 结束日期 例如 20200201
klt : k线间距 默认为 101 即日k
klt : 1 1 分钟
klt : 5 5 分钟
klt : 101 日
klt : 102 周
fqt: 复权方式
不复权 : 0
前复权 : 1
后复权 : 2
Return
------
DateFrame : 包含期货k线数据
EastmoneyHeaders = {
'Host': '19.push2.eastmoney.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'http://quote.eastmoney.com/center/gridlist.html',
EastmoneyKlines = {
'f51': '日期',
'f52': '开盘',
'f53': '收盘',
'f54': '最高',
'f55': '最低',
'f56': '成交量',
'f57': '成交额',
'f58': '振幅',
'f59': '涨跌幅',
'f60': '涨跌额',
'f61': '换手率',
fields = list(EastmoneyKlines.keys())
columns = list(EastmoneyKlines.values())
fields2 = ",".join(fields)
params = (
('fields1', 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13'),
('fields2', fields2),
('beg', beg),
('end', end),
('rtntype', '6'),
('secid', secid),
('klt', f'{klt}'),
('fqt', f'{fqt}'),
base_url = 'https://push2his.eastmoney.com/api/qt/stock/kline/get'
url = base_url+'?'+urlencode(params)
json_response = requests.get(
url, headers=EastmoneyHeaders).json()
data = json_response['data']
if data is None:
print(secid, '无数据')
return None
# code = data['code']
# name
# name = data['name']
klines = data['klines']
rows = []
for _kline in klines:
kline = _kline.split(',')
rows.append(kline)
df = pd.DataFrame(rows, columns=columns)
return df
if "__main__" == __name__:
# 获取全市场期货基本数据,即下面的 4 列信息
# ['期货代码', '期货名称', 'secid', '归属交易所']
futures_info_df = get_futures_base_info()
futures_info_df.to_csv('期货信息表.csv', index=None, encoding='utf-8-sig')
print('期货基本信息表如下')
print(futures_info_df)
secids = futures_info_df['secid']
futures_names = futures_info_df['期货名称']
# 最多获取的期货个数
end = 10
if end >= len(futures_info_df):
end = len(futures_info_df)
for secid, futures_name in list(zip(secids, futures_names))[:end]:
print(f'正在获取期货:{futures_name} 的历史 k 线数据')
# 获取期货历史 日k 线数据
df = get_ftures_k_history(secid)
df.insert(0, '期货名称', [futures_name for _ in range(len(df))])
df.to_csv(f'{futures_name}.csv', index=None, encoding='utf-8-sig')
print(f'期货 : {futures_name} 的 k 线数据已保存到文件 {futures_name}.csv 中')
运行结果
屏幕文字输出
期货基本信息表如下
期货代码 期货名称 secid 归属交易所
0 ZCM 动力煤主力 115.ZCM 郑商所
1 ZC109 动力煤109 115.ZC109 郑商所
2 ZC108 动力煤108 115.ZC108 郑商所
❯ python .\example.py
期货基本信息表如下
期货代码 期货名称 secid 归属交易所
0 ZCM 动力煤主力 115.ZCM 郑商所
1 ZC109 动力煤109 115.ZC109 郑商所
2 ZC108 动力煤108 115.ZC108 郑商所
3 ZC203 动力煤203 115.ZC203 郑商所
4 ZC202 动力煤202 115.ZC202 郑商所
.. ... ... ... ...
780 bum 石油沥青主力 113.bum 上期所
781 bu2106 石油沥青2106 113.bu2106 上期所
782 fus 燃油次主力 113.fus 上期所
783 fu2105 燃油2105 113.fu2105 上期所
784 fb2204 纤维板2204 114.fb2204 大商所
[785 rows x 4 columns]
正在获取期货:动力煤主力 的历史 k 线数据
期货 : 动力煤主力 的 k 线数据已保存到文件 动力煤主力.csv 中
正在获取期货:动力煤109 的历史 k 线数据
期货 : 动力煤109 的 k 线数据已保存到文件 动力煤109.csv 中
正在获取期货:动力煤108 的历史 k 线数据
期货 : 动力煤108 的 k 线数据已保存到文件 动力煤108.csv 中
正在获取期货:动力煤203 的历史 k 线数据
期货 : 动力煤203 的 k 线数据已保存到文件 动力煤203.csv 中
正在获取期货:动力煤202 的历史 k 线数据
期货 : 动力煤202 的 k 线数据已保存到文件 动力煤202.csv 中
正在获取期货:动力煤201 的历史 k 线数据
期货 : 动力煤201 的 k 线数据已保存到文件 动力煤201.csv 中
正在获取期货:动力煤111 的历史 k 线数据
期货 : 动力煤111 的 k 线数据已保存到文件 动力煤111.csv 中