fa45d8aa5f
- health_checklist.json: 192.168.1.122→node122
- ocr_client.py: docstring IP→node122
- docs/market-data-requirements.md: IP→node122
- 所有API调用通过ProxyHandler({})绕过系统代理
Privoxy对node122:18003返回500,直连正常
780 lines
26 KiB
Python
780 lines
26 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding:utf-8 -*-
|
||
"""
|
||
Date: 2024/11/30 18:00
|
||
Desc: 期货日线行情
|
||
"""
|
||
|
||
import datetime
|
||
import json
|
||
import re
|
||
import zipfile
|
||
from io import BytesIO, StringIO
|
||
|
||
import numpy as np
|
||
import pandas as pd
|
||
import requests
|
||
|
||
from akshare.futures import cons
|
||
from akshare.futures.requests_fun import requests_link
|
||
|
||
calendar = cons.get_calendar()
|
||
|
||
|
||
def _futures_daily_czce(
|
||
date: str = "20100824", dataset: str = "datahistory2010"
|
||
) -> pd.DataFrame:
|
||
"""
|
||
郑州商品交易所-交易数据-历史行情下载
|
||
http://www.czce.com.cn/cn/jysj/lshqxz/H770319index_1.htm
|
||
:param date: 需要的日期
|
||
:type date: str
|
||
:param dataset: 数据集的名称; 此处只需要替换 datahistory2010 中的 2010 即可
|
||
:type dataset: str
|
||
:return: 指定日期的所有品种行情数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
url = f"http://www.czce.com.cn/cn/exchange/{dataset}.zip"
|
||
r = requests.get(url)
|
||
with zipfile.ZipFile(BytesIO(r.content)) as file:
|
||
with file.open(f"{dataset}.txt") as my_file:
|
||
data = my_file.read().decode("gb2312")
|
||
data_df = pd.read_table(StringIO(data), sep=r"|", header=1)
|
||
data_df.columns = [item.strip() for item in data_df.columns]
|
||
data_df.dropna(axis=1, inplace=True)
|
||
for column in data_df.columns:
|
||
try:
|
||
data_df[column] = data_df[column].str.strip("\t")
|
||
data_df[column] = data_df[column].str.replace(",", "")
|
||
except: # noqa: E722
|
||
data_df[column] = data_df[column]
|
||
data_df["昨结算"] = pd.to_numeric(data_df["昨结算"])
|
||
data_df["今开盘"] = pd.to_numeric(data_df["今开盘"])
|
||
data_df["最高价"] = pd.to_numeric(data_df["最高价"])
|
||
data_df["最低价"] = pd.to_numeric(data_df["最低价"])
|
||
data_df["今收盘"] = pd.to_numeric(data_df["今收盘"])
|
||
data_df["今结算"] = pd.to_numeric(data_df["今结算"])
|
||
data_df["涨跌1"] = pd.to_numeric(data_df["涨跌1"])
|
||
data_df["涨跌2"] = pd.to_numeric(data_df["涨跌2"])
|
||
data_df["成交量(手)"] = pd.to_numeric(data_df["成交量(手)"])
|
||
data_df["空盘量"] = pd.to_numeric(data_df["空盘量"])
|
||
data_df["增减量"] = pd.to_numeric(data_df["增减量"])
|
||
data_df["成交额(万元)"] = pd.to_numeric(data_df["成交额(万元)"])
|
||
data_df["交割结算价"] = pd.to_numeric(data_df["交割结算价"])
|
||
data_df["交易日期"] = pd.to_datetime(data_df["交易日期"])
|
||
data_df.columns = [
|
||
"date",
|
||
"symbol",
|
||
"pre_settle",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"settle",
|
||
"-",
|
||
"-",
|
||
"volume",
|
||
"open_interest",
|
||
"-",
|
||
"turnover",
|
||
"-",
|
||
]
|
||
variety_list = [
|
||
re.compile(r"[a-zA-Z_]+").findall(item)[0] for item in data_df["symbol"]
|
||
]
|
||
data_df["variety"] = variety_list
|
||
data_df = data_df[
|
||
[
|
||
"symbol",
|
||
"date",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"volume",
|
||
"open_interest",
|
||
"turnover",
|
||
"settle",
|
||
"pre_settle",
|
||
"variety",
|
||
]
|
||
]
|
||
temp_df = data_df[data_df["date"] == pd.Timestamp(date)].copy()
|
||
temp_df["date"] = date
|
||
temp_df.reset_index(inplace=True, drop=True)
|
||
return temp_df
|
||
|
||
|
||
def get_cffex_daily(date: str = "20100416") -> pd.DataFrame:
|
||
"""
|
||
中国金融期货交易所-日频率交易数据
|
||
http://www.cffex.com.cn/rtj/
|
||
:param date: 交易日; 数据开始时间为 20100416
|
||
:type date: str
|
||
:return: 日频率交易数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
day = cons.convert_date(date) if date is not None else datetime.date.today()
|
||
if day.strftime("%Y%m%d") not in calendar:
|
||
# warnings.warn("%s非交易日" % day.strftime("%Y%m%d"))
|
||
return pd.DataFrame()
|
||
url = f"http://www.cffex.com.cn/sj/historysj/{date[:-2]}/zip/{date[:-2]}.zip"
|
||
headers = {
|
||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||
"Chrome/108.0.0.0 Safari/537.36",
|
||
}
|
||
r = requests.get(url, headers=headers)
|
||
try:
|
||
with zipfile.ZipFile(BytesIO(r.content)) as file:
|
||
with file.open(f"{date}_1.csv") as my_file:
|
||
data = my_file.read().decode("gb2312")
|
||
data_df = pd.read_csv(StringIO(data))
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
data_df = data_df[data_df["合约代码"] != "小计"]
|
||
data_df = data_df[data_df["合约代码"] != "合计"]
|
||
data_df = data_df[~data_df["合约代码"].str.contains("IO")]
|
||
data_df = data_df[~data_df["合约代码"].str.contains("MO")]
|
||
data_df = data_df[~data_df["合约代码"].str.contains("HO")]
|
||
data_df.reset_index(inplace=True, drop=True)
|
||
data_df["合约代码"] = data_df["合约代码"].str.strip()
|
||
symbol_list = data_df["合约代码"].to_list()
|
||
variety_list = [re.compile(r"[a-zA-Z_]+").findall(item)[0] for item in symbol_list]
|
||
if data_df.shape[1] == 15:
|
||
data_df.columns = [
|
||
"symbol",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"volume",
|
||
"turnover",
|
||
"open_interest",
|
||
"_",
|
||
"close",
|
||
"settle",
|
||
"pre_settle",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
]
|
||
else:
|
||
data_df.columns = [
|
||
"symbol",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"volume",
|
||
"turnover",
|
||
"open_interest",
|
||
"_",
|
||
"close",
|
||
"settle",
|
||
"pre_settle",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
]
|
||
data_df["date"] = date
|
||
data_df["variety"] = variety_list
|
||
data_df = data_df[
|
||
[
|
||
"symbol",
|
||
"date",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"volume",
|
||
"open_interest",
|
||
"turnover",
|
||
"settle",
|
||
"pre_settle",
|
||
"variety",
|
||
]
|
||
]
|
||
return data_df
|
||
|
||
|
||
def get_gfex_daily(date: str = "20221223") -> pd.DataFrame:
|
||
"""
|
||
广州期货交易所-日频率-量价数据
|
||
广州期货交易所: 工业硅(上市时间: 20221222)
|
||
http://www.gfex.com.cn/gfex/rihq/hqsj_tjsj.shtml
|
||
:param date: 日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象,默认为当前交易日
|
||
:type date: str or datetime.date
|
||
:return: 广州期货交易所-日频率-量价数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
day = cons.convert_date(date) if date is not None else datetime.date.today()
|
||
if day.strftime("%Y%m%d") not in calendar:
|
||
# warnings.warn(f"{day.strftime('%Y%m%d')}非交易日")
|
||
return pd.DataFrame()
|
||
url = "http://www.gfex.com.cn/u/interfacesWebTiDayQuotes/loadList"
|
||
payload = {"trade_date": date, "trade_type": "0"}
|
||
headers = {
|
||
"Accept": "application/json, text/javascript, */*; q=0.01",
|
||
"Accept-Encoding": "gzip, deflate",
|
||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||
"Cache-Control": "no-cache",
|
||
"Content-Length": "32",
|
||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||
"Host": "www.gfex.com.cn",
|
||
"Origin": "http://www.gfex.com.cn",
|
||
"Pragma": "no-cache",
|
||
"Proxy-Connection": "keep-alive",
|
||
"Referer": "http://www.gfex.com.cn/gfex/rihq/hqsj_tjsj.shtml",
|
||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||
"Chrome/108.0.0.0 Safari/537.36",
|
||
"X-Requested-With": "XMLHttpRequest",
|
||
"content-type": "application/x-www-form-urlencoded",
|
||
}
|
||
r = requests.post(url, data=payload, headers=headers)
|
||
try:
|
||
data_json = r.json()
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
result_df = pd.DataFrame(data_json["data"])
|
||
result_df = result_df[~result_df["variety"].str.contains("小计")]
|
||
result_df = result_df[~result_df["variety"].str.contains("总计")]
|
||
result_df["symbol"] = (
|
||
result_df["varietyOrder"].str.upper() + result_df["delivMonth"]
|
||
)
|
||
result_df["date"] = date
|
||
result_df["open"] = pd.to_numeric(result_df["open"], errors="coerce")
|
||
result_df["high"] = pd.to_numeric(result_df["high"], errors="coerce")
|
||
result_df["low"] = pd.to_numeric(result_df["low"], errors="coerce")
|
||
result_df["close"] = pd.to_numeric(result_df["close"], errors="coerce")
|
||
result_df["volume"] = pd.to_numeric(result_df["volumn"], errors="coerce")
|
||
result_df["open_interest"] = pd.to_numeric(
|
||
result_df["openInterest"], errors="coerce"
|
||
)
|
||
result_df["turnover"] = pd.to_numeric(result_df["turnover"], errors="coerce")
|
||
result_df["settle"] = pd.to_numeric(result_df["clearPrice"], errors="coerce")
|
||
result_df["pre_settle"] = pd.to_numeric(result_df["lastClear"], errors="coerce")
|
||
result_df["variety"] = result_df["varietyOrder"].str.upper()
|
||
result_df = result_df[
|
||
[
|
||
"symbol",
|
||
"date",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"volume",
|
||
"open_interest",
|
||
"turnover",
|
||
"settle",
|
||
"pre_settle",
|
||
"variety",
|
||
]
|
||
]
|
||
return result_df
|
||
|
||
|
||
def get_ine_daily(date: str = "20241129") -> pd.DataFrame:
|
||
"""
|
||
上海国际能源交易中心-日频率-量价数据
|
||
上海国际能源交易中心: 原油期货(上市时间: 20180326); 20号胶期货(上市时间: 20190812)
|
||
trade_price: https://www.ine.cn/statements/daily/?paramid=kx
|
||
trade_note: https://www.ine.cn/data/datanote.dat
|
||
:param date: 日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象,默认为当前交易日
|
||
:type date: str or datetime.date
|
||
:return: 上海国际能源交易中心-日频率-量价数据
|
||
:rtype: pandas.DataFrame or None
|
||
"""
|
||
day = cons.convert_date(date) if date is not None else datetime.date.today()
|
||
if day.strftime("%Y%m%d") not in calendar:
|
||
# warnings.warn(f"{day.strftime('%Y%m%d')}非交易日")
|
||
return pd.DataFrame()
|
||
url = f"https://www.ine.cn/data/tradedata/future/dailydata/kx{day.strftime('%Y%m%d')}.dat"
|
||
r = requests.get(url, headers=cons.shfe_headers)
|
||
result_df = pd.DataFrame()
|
||
try:
|
||
data_json = r.json()
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
temp_df = pd.DataFrame(data_json["o_curinstrument"]).iloc[:-1, :]
|
||
temp_df = temp_df[temp_df["DELIVERYMONTH"] != "小计"]
|
||
temp_df = temp_df[~temp_df["PRODUCTNAME"].str.contains("总计")]
|
||
try:
|
||
result_df["symbol"] = (
|
||
temp_df["PRODUCTGROUPID"].str.upper().str.strip() + temp_df["DELIVERYMONTH"]
|
||
)
|
||
except: # noqa: E722
|
||
result_df["symbol"] = (
|
||
temp_df["PRODUCTID"]
|
||
.str.upper()
|
||
.str.strip()
|
||
.str.split("_", expand=True)
|
||
.iloc[:, 0]
|
||
+ temp_df["DELIVERYMONTH"]
|
||
)
|
||
result_df["date"] = day.strftime("%Y%m%d")
|
||
result_df["open"] = temp_df["OPENPRICE"]
|
||
result_df["high"] = temp_df["HIGHESTPRICE"]
|
||
result_df["low"] = temp_df["LOWESTPRICE"]
|
||
result_df["close"] = temp_df["CLOSEPRICE"]
|
||
result_df["volume"] = temp_df["VOLUME"]
|
||
result_df["open_interest"] = temp_df["OPENINTEREST"]
|
||
try:
|
||
result_df["turnover"] = temp_df["TURNOVER"]
|
||
except: # noqa: E722
|
||
result_df["turnover"] = 0
|
||
result_df["settle"] = temp_df["SETTLEMENTPRICE"]
|
||
result_df["pre_settle"] = temp_df["PRESETTLEMENTPRICE"]
|
||
try:
|
||
result_df["variety"] = temp_df["PRODUCTGROUPID"].str.upper().str.strip()
|
||
except: # noqa: E722
|
||
result_df["variety"] = (
|
||
temp_df["PRODUCTID"]
|
||
.str.upper()
|
||
.str.strip()
|
||
.str.split("_", expand=True)
|
||
.iloc[:, 0]
|
||
)
|
||
result_df = result_df[result_df["symbol"] != "总计"]
|
||
result_df = result_df[~result_df["symbol"].str.contains("efp")]
|
||
return result_df
|
||
|
||
|
||
def get_czce_daily(date: str = "20050525") -> pd.DataFrame:
|
||
"""
|
||
郑州商品交易所-日频率-量价数据
|
||
http://www.czce.com.cn/cn/jysj/mrhq/H770301index_1.htm
|
||
:param date: 日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date 对象,默认为当前交易日; 日期需要大于 20100824
|
||
:type date: str or datetime.date
|
||
:return: 郑州商品交易所-日频率-量价数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
day = cons.convert_date(date) if date is not None else datetime.date.today()
|
||
headers = {
|
||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||
"Chrome/108.0.0.0 Safari/537.36"
|
||
}
|
||
url = ""
|
||
if day.strftime("%Y%m%d") not in calendar:
|
||
# warnings.warn(f"{day.strftime('%Y%m%d')}非交易日")
|
||
return pd.DataFrame()
|
||
if day > datetime.date(2010, 8, 24):
|
||
if day > datetime.date(2015, 11, 11):
|
||
u = cons.CZCE_DAILY_URL_3
|
||
url = u % (day.strftime("%Y"), day.strftime("%Y%m%d"))
|
||
elif day <= datetime.date(2015, 11, 11):
|
||
u = cons.CZCE_DAILY_URL_2
|
||
url = u % (day.strftime("%Y"), day.strftime("%Y%m%d"))
|
||
listed_columns = cons.CZCE_COLUMNS
|
||
output_columns = cons.OUTPUT_COLUMNS
|
||
try:
|
||
r = requests.get(url, headers=headers)
|
||
if datetime.date(2015, 11, 12) <= day <= datetime.date(2017, 12, 27):
|
||
html = str(r.content, encoding="gbk")
|
||
else:
|
||
html = r.text
|
||
except requests.exceptions.HTTPError as reason:
|
||
if reason.response.status_code != 404:
|
||
print(
|
||
cons.CZCE_DAILY_URL_3
|
||
% (day.strftime("%Y"), day.strftime("%Y%m%d")),
|
||
reason,
|
||
)
|
||
return pd.DataFrame()
|
||
if html.find("您的访问出错了") >= 0 or html.find("无期权每日行情交易记录") >= 0:
|
||
return pd.DataFrame()
|
||
html = [
|
||
i.replace(" ", "").split("|")
|
||
for i in html.split("\n")[:-3]
|
||
if i[0][0] != "小"
|
||
]
|
||
|
||
if day > datetime.date(2015, 11, 11):
|
||
if html[1][0] not in ["品种月份", "品种代码", "合约代码"]:
|
||
return pd.DataFrame()
|
||
dict_data = list()
|
||
day_const = int(day.strftime("%Y%m%d"))
|
||
for row in html[2:]:
|
||
m = cons.FUTURES_SYMBOL_PATTERN.match(row[0])
|
||
if not m:
|
||
continue
|
||
row_dict = {
|
||
"date": day_const,
|
||
"symbol": row[0],
|
||
"variety": m.group(1),
|
||
}
|
||
for i, field in enumerate(listed_columns):
|
||
if row[i + 1] == "\r" or row[i + 1] == "":
|
||
row_dict[field] = 0.0
|
||
elif field in [
|
||
"volume",
|
||
"open_interest",
|
||
"oi_chg",
|
||
"exercise_volume",
|
||
]:
|
||
row[i + 1] = row[i + 1].replace(",", "")
|
||
row_dict[field] = int(row[i + 1])
|
||
else:
|
||
row[i + 1] = row[i + 1].replace(",", "")
|
||
row_dict[field] = float(row[i + 1])
|
||
dict_data.append(row_dict)
|
||
return pd.DataFrame(dict_data)[output_columns]
|
||
elif day <= datetime.date(2015, 11, 11):
|
||
dict_data = list()
|
||
day_const = int(day.strftime("%Y%m%d"))
|
||
for row in html[1:]:
|
||
row = row[0].split(",")
|
||
m = cons.FUTURES_SYMBOL_PATTERN.match(row[0])
|
||
if not m:
|
||
continue
|
||
row_dict = {
|
||
"date": day_const,
|
||
"symbol": row[0],
|
||
"variety": m.group(1),
|
||
}
|
||
for i, field in enumerate(listed_columns):
|
||
if row[i + 1] == "\r":
|
||
row_dict[field] = 0.0
|
||
elif field in [
|
||
"volume",
|
||
"open_interest",
|
||
"oi_chg",
|
||
"exercise_volume",
|
||
]:
|
||
row_dict[field] = int(float(row[i + 1]))
|
||
else:
|
||
row_dict[field] = float(row[i + 1])
|
||
dict_data.append(row_dict)
|
||
return pd.DataFrame(dict_data)[output_columns]
|
||
|
||
if day <= datetime.date(2010, 8, 24):
|
||
_futures_daily_czce_df = _futures_daily_czce(date)
|
||
return _futures_daily_czce_df
|
||
|
||
|
||
def get_shfe_daily(date: str = "20220415") -> pd.DataFrame:
|
||
"""
|
||
上海期货交易所-日频率-量价数据
|
||
https://tsite.shfe.com.cn/statements/dataview.html?paramid=kx
|
||
:param date: 日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象, 默认为当前交易日
|
||
:type date: str or datetime.date
|
||
:return: 上海期货交易所-日频率-量价数据
|
||
:rtype: pandas.DataFrame or None
|
||
上期所日交易数据(DataFrame):
|
||
symbol 合约代码
|
||
date 日期
|
||
open 开盘价
|
||
high 最高价
|
||
low 最低价
|
||
close 收盘价
|
||
volume 成交量
|
||
open_interest 持仓量
|
||
turnover 成交额
|
||
settle 结算价
|
||
pre_settle 前结算价
|
||
variety 合约类别
|
||
或 None(给定交易日没有交易数据)
|
||
"""
|
||
day = cons.convert_date(date) if date is not None else datetime.date.today()
|
||
if day.strftime("%Y%m%d") not in calendar:
|
||
# warnings.warn("%s非交易日" % day.strftime("%Y%m%d"))
|
||
return pd.DataFrame()
|
||
try:
|
||
json_data = json.loads(
|
||
requests_link(
|
||
cons.SHFE_DAILY_URL_20250630 % (day.strftime("%Y%m%d")),
|
||
headers=cons.shfe_headers,
|
||
).text
|
||
)
|
||
except requests.HTTPError as reason:
|
||
if reason.response != 404:
|
||
print(cons.SHFE_DAILY_URL_20250630 % (day.strftime("%Y%m%d")), reason)
|
||
return pd.DataFrame()
|
||
|
||
if len(json_data["o_curinstrument"]) == 0:
|
||
return pd.DataFrame()
|
||
|
||
df = pd.DataFrame(
|
||
[
|
||
row
|
||
for row in json_data["o_curinstrument"]
|
||
if row["DELIVERYMONTH"] not in ["小计", "合计"]
|
||
and row["DELIVERYMONTH"] != ""
|
||
]
|
||
)
|
||
try:
|
||
df["variety"] = df["PRODUCTGROUPID"].str.upper().str.strip()
|
||
except KeyError:
|
||
df["variety"] = (
|
||
df["PRODUCTID"]
|
||
.str.upper()
|
||
.str.split("_", expand=True)
|
||
.iloc[:, 0]
|
||
.str.strip()
|
||
)
|
||
df["symbol"] = df["variety"] + df["DELIVERYMONTH"]
|
||
df["date"] = day.strftime("%Y%m%d")
|
||
df["VOLUME"] = df["VOLUME"].apply(lambda x: 0 if x == "" else x)
|
||
try:
|
||
df["turnover"] = df["TURNOVER"].apply(lambda x: 0 if x == "" else x)
|
||
except KeyError:
|
||
df["turnover"] = np.nan
|
||
df.rename(columns=cons.SHFE_COLUMNS, inplace=True)
|
||
df = df[~df["symbol"].str.contains("efp")]
|
||
df = df[cons.OUTPUT_COLUMNS]
|
||
df.reset_index(inplace=True)
|
||
return df
|
||
|
||
|
||
def get_dce_daily(date: str = "20251027") -> pd.DataFrame:
|
||
"""
|
||
大连商品交易所日交易数据
|
||
http://www.dce.com.cn/dalianshangpin/xqsj/tjsj26/rtj/rxq/index.html
|
||
:param date: 交易日, e.g., 20200416
|
||
:type date: str
|
||
:return: 具体交易日的个品种行情数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
day = cons.convert_date(date) if date is not None else datetime.date.today()
|
||
if day.strftime("%Y%m%d") not in calendar:
|
||
# warnings.warn("%s非交易日" % day.strftime("%Y%m%d"))
|
||
return pd.DataFrame()
|
||
url = "http://www.dce.com.cn/dcereport/publicweb/dailystat/dayQuotes"
|
||
payload = {
|
||
"contractId": "",
|
||
"lang": "zh",
|
||
"optionSeries": "",
|
||
"statisticsType": "0",
|
||
"tradeDate": date,
|
||
"tradeType": "1",
|
||
"varietyId": "all",
|
||
}
|
||
r = requests.post(url, json=payload)
|
||
data_json = r.json()
|
||
temp_df = pd.DataFrame(data_json["data"])
|
||
temp_df.rename(
|
||
columns={
|
||
"variety": "品种名称",
|
||
"contractId": "合约",
|
||
"open": "开盘价",
|
||
"high": "最高价",
|
||
"low": "最低价",
|
||
"close": "收盘价",
|
||
"lastClear": "前结算价",
|
||
"clearPrice": "结算价",
|
||
"diff": "涨跌",
|
||
"diff1": "涨跌1",
|
||
"volumn": "成交量",
|
||
"openInterest": "持仓量",
|
||
"diffI": "持仓量变化",
|
||
"turnover": "成交额",
|
||
},
|
||
inplace=True,
|
||
)
|
||
temp_df = temp_df[~temp_df["品种名称"].str.contains("小计")]
|
||
temp_df = temp_df[~temp_df["品种名称"].str.contains("总计")]
|
||
temp_df["variety"] = temp_df["品种名称"].map(lambda x: cons.DCE_MAP[x])
|
||
temp_df["symbol"] = temp_df["合约"]
|
||
del temp_df["品种名称"]
|
||
del temp_df["合约"]
|
||
temp_df.columns = [
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"pre_settle",
|
||
"settle",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"volume",
|
||
"open_interest",
|
||
"_",
|
||
"turnover",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
"variety",
|
||
"symbol",
|
||
]
|
||
temp_df["date"] = date
|
||
temp_df = temp_df[
|
||
[
|
||
"symbol",
|
||
"date",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"volume",
|
||
"open_interest",
|
||
"turnover",
|
||
"settle",
|
||
"pre_settle",
|
||
"variety",
|
||
]
|
||
]
|
||
temp_df = temp_df.astype(
|
||
{
|
||
"open": "float",
|
||
"high": "float",
|
||
"low": "float",
|
||
"close": "float",
|
||
"volume": "float",
|
||
"open_interest": "float",
|
||
"turnover": "float",
|
||
"settle": "float",
|
||
"pre_settle": "float",
|
||
}
|
||
)
|
||
temp_df.reset_index(inplace=True, drop=True)
|
||
return temp_df
|
||
|
||
|
||
def get_futures_daily(
|
||
start_date: str = "20220208",
|
||
end_date: str = "20220208",
|
||
market: str = "CFFEX",
|
||
) -> pd.DataFrame:
|
||
"""
|
||
交易所日交易数据
|
||
:param start_date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||
:type start_date: str
|
||
:param end_date: 结束数据 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||
:type end_date: str
|
||
:param market: 'CFFEX' 中金所, 'CZCE' 郑商所, 'SHFE' 上期所, 'DCE' 大商所 之一, 'INE' 上海国际能源交易中心, "GFEX" 广州期货交易所。默认为中金所
|
||
:type market: str
|
||
:return: 交易所日交易数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
if market.upper() == "CFFEX":
|
||
f = get_cffex_daily
|
||
elif market.upper() == "CZCE":
|
||
f = get_czce_daily
|
||
elif market.upper() == "SHFE":
|
||
f = get_shfe_daily
|
||
elif market.upper() == "DCE":
|
||
f = get_dce_daily
|
||
elif market.upper() == "INE":
|
||
f = get_ine_daily
|
||
elif market.upper() == "GFEX":
|
||
f = get_gfex_daily
|
||
else:
|
||
print("Invalid Market Symbol")
|
||
return pd.DataFrame()
|
||
|
||
start_date = (
|
||
cons.convert_date(start_date)
|
||
if start_date is not None
|
||
else datetime.date.today()
|
||
)
|
||
end_date = (
|
||
cons.convert_date(end_date)
|
||
if end_date is not None
|
||
else cons.convert_date(cons.get_latest_data_date(datetime.datetime.now()))
|
||
)
|
||
|
||
df_list = list()
|
||
while start_date <= end_date:
|
||
df = f(date=str(start_date).replace("-", ""))
|
||
if not df.empty:
|
||
df_list.append(df)
|
||
start_date += datetime.timedelta(days=1)
|
||
|
||
if len(df_list) == 0:
|
||
return pd.DataFrame()
|
||
elif len(df_list) > 0:
|
||
temp_df = pd.concat(df_list).reset_index(drop=True)
|
||
temp_df = temp_df[~temp_df["symbol"].str.contains("efp")]
|
||
return temp_df
|
||
else:
|
||
return pd.DataFrame()
|
||
|
||
|
||
def futures_hist_daily_cffex(date: str = "20260403") -> pd.DataFrame:
|
||
"""
|
||
中国金融期货交易所-交易所日交易数据
|
||
http://www.cffex.com.cn/cn/rtj.html
|
||
:param date: 交易日
|
||
:type date: str
|
||
:return: 交易所日交易数据
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
url = f"http://www.cffex.com.cn/sj/hqsj/rtj/{date[:6]}/{date[6:]}/{date}_1.csv"
|
||
data_df = pd.read_csv(url, encoding="gbk")
|
||
data_df = data_df[data_df["合约代码"] != "小计"]
|
||
data_df = data_df[data_df["合约代码"] != "合计"]
|
||
data_df = data_df[~data_df["合约代码"].str.contains("IO")]
|
||
data_df = data_df[~data_df["合约代码"].str.contains("MO")]
|
||
data_df = data_df[~data_df["合约代码"].str.contains("HO")]
|
||
data_df.reset_index(inplace=True, drop=True)
|
||
data_df["合约代码"] = data_df["合约代码"].str.strip()
|
||
symbol_list = data_df["合约代码"].to_list()
|
||
variety_list = [re.compile(r"[a-zA-Z_]+").findall(item)[0] for item in symbol_list]
|
||
data_df.columns = [
|
||
"symbol",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"volume",
|
||
"turnover",
|
||
"open_interest",
|
||
"_",
|
||
"close",
|
||
"settle",
|
||
"pre_settle",
|
||
"_",
|
||
"_",
|
||
"_",
|
||
]
|
||
data_df["date"] = date
|
||
data_df["variety"] = variety_list
|
||
data_df = data_df[
|
||
[
|
||
"symbol",
|
||
"date",
|
||
"open",
|
||
"high",
|
||
"low",
|
||
"close",
|
||
"volume",
|
||
"open_interest",
|
||
"turnover",
|
||
"settle",
|
||
"pre_settle",
|
||
"variety",
|
||
]
|
||
]
|
||
return data_df
|
||
|
||
|
||
if __name__ == "__main__":
|
||
get_futures_daily_df = get_futures_daily(
|
||
start_date="20250708", end_date="20250708", market="DCE"
|
||
)
|
||
print(get_futures_daily_df)
|
||
|
||
get_dce_daily_df = get_dce_daily(date="20251029")
|
||
print(get_dce_daily_df)
|
||
|
||
get_cffex_daily_df = get_cffex_daily(date="20260401")
|
||
print(get_cffex_daily_df)
|
||
|
||
get_ine_daily_df = get_ine_daily(date="20230818")
|
||
print(get_ine_daily_df)
|
||
|
||
get_czce_daily_df = get_czce_daily(date="20210513")
|
||
print(get_czce_daily_df)
|
||
|
||
get_shfe_daily_df = get_shfe_daily(date="20250630")
|
||
print(get_shfe_daily_df)
|
||
|
||
get_gfex_daily_df = get_gfex_daily(date="20221228")
|
||
print(get_gfex_daily_df)
|
||
|
||
futures_hist_daily_cffex_df = futures_hist_daily_cffex(date="20260302")
|
||
print(futures_hist_daily_cffex_df)
|