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,直连正常
416 lines
16 KiB
Python
416 lines
16 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding:utf-8 -*-
|
||
"""
|
||
Date: 2026/2/20 10:00
|
||
Desc: 期货结算信息
|
||
期货交易所结算参数数据
|
||
- 中金所: 结算参数(保证金、手续费等) - 已实现
|
||
- 郑商所: 结算参数 - 已实现
|
||
- 上期所: 结算参数 - 已实现
|
||
- 广期所: 结算参数 - 已实现
|
||
- 上能中心: 结算参数 - 已实现
|
||
- 大商所: 待解决(网站反爬虫保护,所有接口返回412错误)
|
||
"""
|
||
|
||
import datetime
|
||
|
||
import pandas as pd
|
||
import requests
|
||
from io import StringIO
|
||
|
||
from akshare.futures import cons
|
||
from akshare.utils.cons import headers
|
||
|
||
gfex_headers = {
|
||
"Accept": "application/json, text/javascript, */*; q=0.01",
|
||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||
"Origin": "http://www.gfex.com.cn",
|
||
"Referer": "http://www.gfex.com.cn/gfex/rjycs/ywcs.shtml",
|
||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
|
||
"X-Requested-With": "XMLHttpRequest",
|
||
}
|
||
|
||
# 统一的结算参数字段
|
||
SETTLE_OUTPUT_COLUMNS = [
|
||
"date",
|
||
"symbol",
|
||
"variety",
|
||
"settle_price",
|
||
"long_margin_ratio",
|
||
"short_margin_ratio",
|
||
"spec_long_margin_ratio",
|
||
"spec_short_margin_ratio",
|
||
"hedge_long_margin_ratio",
|
||
"hedge_short_margin_ratio",
|
||
"trade_fee_ratio",
|
||
"close_today_fee_ratio",
|
||
"delivery_fee_ratio",
|
||
"is_single_market",
|
||
"single_market_days",
|
||
"limit_ratio",
|
||
"position_limit",
|
||
"trade_limit",
|
||
"rise_limit_rate",
|
||
"fall_limit_rate",
|
||
]
|
||
|
||
|
||
def _normalize_settle_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||
"""
|
||
统一结算参数字段,将各交易所的字段映射到统一字段
|
||
:param df: 原始DataFrame
|
||
:type df: pandas.DataFrame
|
||
:return: 统一格式的DataFrame
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
if df.empty:
|
||
return pd.DataFrame(columns=SETTLE_OUTPUT_COLUMNS)
|
||
|
||
# 字段映射关系
|
||
field_mapping = {
|
||
# 统一字段 -> 可能的来源字段
|
||
"settle_price": ["settle_price", "SETTLEMENTPRICE", "当日结算价"],
|
||
"long_margin_ratio": ["long_margin_ratio", "margin_ratio", "SPECLONGMARGINRATIO", "specBuyRate", "spec_buy_rate"],
|
||
"short_margin_ratio": ["short_margin_ratio", "SPECSHORTMARGINRATIO", "hedgeBuyRate", "hedge_buy_rate"],
|
||
"spec_long_margin_ratio": ["spec_long_margin_ratio", "SPECLONGMARGINRATIO", "spec_buy_rate"],
|
||
"spec_short_margin_ratio": ["spec_short_margin_ratio", "SPECSHORTMARGINRATIO", "hedge_buy_rate"],
|
||
"hedge_long_margin_ratio": ["hedge_long_margin_ratio", "HEDGLONGMARGINRATIO", "hedge_buy_rate"],
|
||
"hedge_short_margin_ratio": ["hedge_short_margin_ratio", "HEDGSHORTMARGINRATIO", "spec_buy_rate"],
|
||
"trade_fee_ratio": ["trade_fee_ratio", "TRADEFEERATIO", "交易手续费"],
|
||
"close_today_fee_ratio": ["close_today_fee_ratio", "TTRADEFEERATIO", "日内平今仓交易手续费"],
|
||
"delivery_fee_ratio": ["delivery_fee_ratio", "COMMODITYDELIVFEERATIO", "交割手续费"],
|
||
"is_single_market": ["is_single_market", "是否单边市"],
|
||
"single_market_days": ["single_market_days", "连续单边市天数"],
|
||
"limit_ratio": ["limit_ratio", "涨跌停板(%)"],
|
||
"position_limit": ["position_limit", "日持仓限额", "clientBuyPosiQuota", "client_buy_posi_quota"],
|
||
"trade_limit": ["trade_limit", "交易限额"],
|
||
"rise_limit_rate": ["rise_limit_rate", "riseLimitRate", "rise_limit_rate"],
|
||
"fall_limit_rate": ["fall_limit_rate", "fallLimit", "fall_limit"],
|
||
}
|
||
|
||
# 确保必要的字段存在
|
||
for col in ["date", "symbol", "variety"]:
|
||
if col not in df.columns:
|
||
if col == "variety" and "symbol" in df.columns:
|
||
df["variety"] = df["symbol"].str.extract(r"([A-Za-z]+)", expand=False)
|
||
else:
|
||
df[col] = None
|
||
|
||
# 映射字段
|
||
for target_field, possible_sources in field_mapping.items():
|
||
if target_field not in df.columns:
|
||
for source in possible_sources:
|
||
if source in df.columns:
|
||
df[target_field] = df[source]
|
||
break
|
||
else:
|
||
df[target_field] = None
|
||
|
||
# 返回统一格式
|
||
return df[SETTLE_OUTPUT_COLUMNS]
|
||
|
||
|
||
def _parse_pipe_data(text: str) -> pd.DataFrame:
|
||
"""
|
||
解析管道符分隔的数据
|
||
:param text: 原始文本数据
|
||
:type text: str
|
||
:return: 解析后的DataFrame
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
lines = text.strip().split("\n")
|
||
if len(lines) < 2:
|
||
return pd.DataFrame()
|
||
columns = [col.strip() for col in lines[1].split("|")]
|
||
data_lines = [line for line in lines[2:] if line.strip()]
|
||
data_list = []
|
||
for line in data_lines:
|
||
row = [col.strip() for col in line.split("|")]
|
||
if len(row) >= len(columns):
|
||
data_list.append(row[:len(columns)])
|
||
return pd.DataFrame(data_list, columns=columns)
|
||
|
||
|
||
def futures_settle_cffex(date: str = "20260119") -> pd.DataFrame:
|
||
"""
|
||
中国金融期货交易所-结算参数
|
||
http://www.cffex.com.cn/jscs/
|
||
: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()
|
||
date = day.strftime("%Y%m%d")
|
||
url = f"http://www.cffex.com.cn/sj/jscs/{date[:4]}{date[4:6]}/{date[6:8]}/{date}_1.csv"
|
||
r = requests.get(url, headers=headers)
|
||
r.encoding = "gbk"
|
||
if r.status_code != 200:
|
||
return pd.DataFrame()
|
||
# 检查是否返回的是 HTML 页面(页面不存在或数据未发布)
|
||
if r.text.strip().startswith("<") or "要查看的页面不存在" in r.text:
|
||
return pd.DataFrame()
|
||
try:
|
||
data_df = pd.read_csv(StringIO(r.text), skiprows=1)
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
if data_df.shape[0] < 5:
|
||
return pd.DataFrame()
|
||
data_df.columns = [
|
||
"symbol",
|
||
"long_margin_ratio",
|
||
"short_margin_ratio",
|
||
"trade_fee_ratio",
|
||
"delivery_fee_ratio",
|
||
"close_today_fee_ratio",
|
||
]
|
||
data_df = data_df[data_df["symbol"].notna()]
|
||
data_df = data_df[data_df["symbol"].str.contains(
|
||
r"^[A-Z]+", na=False, regex=True)]
|
||
data_df["variety"] = data_df["symbol"].str.extract(r"([A-Z]+)")
|
||
data_df["date"] = date
|
||
data_df = data_df[
|
||
["date", "symbol", "variety", "long_margin_ratio", "short_margin_ratio",
|
||
"trade_fee_ratio", "delivery_fee_ratio", "close_today_fee_ratio"]
|
||
]
|
||
return data_df
|
||
|
||
|
||
def futures_settle_czce(date: str = "20260119") -> pd.DataFrame:
|
||
"""
|
||
郑州商品交易所-结算参数
|
||
http://www.czce.com.cn/cn/jysj/jscs/H077003003index_1.htm
|
||
: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()
|
||
date = day.strftime("%Y%m%d")
|
||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataClearParams.txt"
|
||
r = requests.get(url, headers=headers)
|
||
r.encoding = "utf-8"
|
||
if r.status_code != 200:
|
||
return pd.DataFrame()
|
||
try:
|
||
data_df = _parse_pipe_data(r.text)
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
if data_df.shape[0] < 5:
|
||
return pd.DataFrame()
|
||
data_df.columns = [
|
||
"symbol", "settle_price", "is_single_market", "single_market_days",
|
||
"margin_ratio", "limit_ratio", "trade_fee", "fee_type",
|
||
"delivery_fee", "close_today_fee", "position_limit", "trade_limit"
|
||
]
|
||
data_df = data_df[data_df["symbol"].notna()]
|
||
data_df = data_df[~data_df["symbol"].str.contains("小计|合计|总计", na=False)]
|
||
data_df["variety"] = data_df["symbol"].str.extract(r"([A-Za-z]+)")
|
||
data_df["date"] = date
|
||
data_df = data_df[
|
||
["date", "symbol", "variety", "settle_price", "is_single_market", "single_market_days",
|
||
"margin_ratio", "limit_ratio", "trade_fee", "fee_type", "delivery_fee",
|
||
"close_today_fee", "position_limit", "trade_limit"]
|
||
]
|
||
return data_df
|
||
|
||
|
||
def futures_settle_gfex(date: str = "20260119") -> pd.DataFrame:
|
||
"""
|
||
广州期货交易所-结算参数
|
||
http://www.gfex.com.cn/gfex/rjycs/ywcs.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()
|
||
date = day.strftime("%Y%m%d")
|
||
url = "http://www.gfex.com.cn/u/interfacesWebTtQueryTradPara/loadDayList"
|
||
payload = {"trade_type": "0"}
|
||
r = requests.post(url, data=payload, headers=gfex_headers)
|
||
if r.status_code != 200:
|
||
return pd.DataFrame()
|
||
# 检查是否返回了反爬虫的 JavaScript 代码
|
||
if r.text.strip().startswith("<script") or "function" in r.text[:100]:
|
||
return pd.DataFrame()
|
||
try:
|
||
json_data = r.json()
|
||
if json_data.get("code") != "0":
|
||
return pd.DataFrame()
|
||
data_list = json_data.get("data", [])
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
if not data_list:
|
||
return pd.DataFrame()
|
||
# 过滤掉期权合约,只保留期货合约
|
||
data_list = [
|
||
item for item in data_list if "-" not in item.get("contractId", "")]
|
||
if not data_list:
|
||
return pd.DataFrame()
|
||
data_df = pd.DataFrame(data_list)
|
||
data_df.columns = [
|
||
"symbol", "spec_buy_rate", "spec_buy", "hedge_buy_rate", "hedge_buy",
|
||
"rise_limit_rate", "rise_limit", "fall_limit", "agent_tot_buy_posi_quota",
|
||
"self_tot_buy_posi_quota", "client_buy_posi_quota", "self_tot_buy_ser_limit",
|
||
"client_buy_ser_limit", "trade_type"
|
||
]
|
||
data_df["variety"] = data_df["symbol"].str.extract(r"([A-Za-z]+)")
|
||
data_df["date"] = date
|
||
data_df = data_df[
|
||
["date", "symbol", "variety", "spec_buy_rate", "spec_buy", "hedge_buy_rate",
|
||
"hedge_buy", "rise_limit_rate", "rise_limit", "fall_limit",
|
||
"agent_tot_buy_posi_quota", "self_tot_buy_posi_quota", "client_buy_posi_quota"]
|
||
]
|
||
return data_df
|
||
|
||
|
||
def futures_settle_shfe(date: str = "20260119") -> pd.DataFrame:
|
||
"""
|
||
上海期货交易所-结算参数
|
||
https://www.shfe.com.cn/reports/tradedata/dailyandweeklydata/
|
||
: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()
|
||
date = day.strftime("%Y%m%d")
|
||
url = f"https://www.shfe.com.cn/data/tradedata/future/dailydata/js{date}.dat"
|
||
r = requests.get(url, headers=cons.shfe_headers)
|
||
if r.status_code != 200:
|
||
return pd.DataFrame()
|
||
try:
|
||
data_json = r.json()
|
||
data_list = data_json.get("o_cursor", [])
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
if not data_list:
|
||
return pd.DataFrame()
|
||
data_df = pd.DataFrame(data_list)
|
||
data_df.columns = [
|
||
"symbol", "trade_fee_ratio", "close_today_fee_ratio", "delivery_fee_unit",
|
||
"spec_long_margin_ratio", "hedge_long_margin_ratio", "delivery_fee_ratio",
|
||
"product_id", "product_name", "close_today_fee_unit", "trade_fee_unit",
|
||
"hedge_short_margin_ratio", "settle_price", "uni_direction",
|
||
"spec_short_margin_ratio", "is_close_today"
|
||
]
|
||
data_df["variety"] = data_df["symbol"].str.extract(r"([A-Za-z]+)")
|
||
data_df["date"] = date
|
||
data_df = data_df[
|
||
["date", "symbol", "variety", "settle_price", "spec_long_margin_ratio",
|
||
"hedge_long_margin_ratio", "spec_short_margin_ratio", "hedge_short_margin_ratio",
|
||
"trade_fee_ratio", "close_today_fee_ratio", "is_close_today"]
|
||
]
|
||
return data_df
|
||
|
||
|
||
def futures_settle_ine(date: str = "20260119") -> pd.DataFrame:
|
||
"""
|
||
上海国际能源交易中心-结算参数
|
||
https://www.ine.cn/reports/businessdata/prmsummary/
|
||
: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()
|
||
date = day.strftime("%Y%m%d")
|
||
url = f"https://www.ine.cn/data/tradedata/future/dailydata/js{date}.dat"
|
||
r = requests.get(url, headers=cons.shfe_headers)
|
||
if r.status_code != 200:
|
||
return pd.DataFrame()
|
||
try:
|
||
data_json = r.json()
|
||
data_list = data_json.get("o_cursor", [])
|
||
except: # noqa: E722
|
||
return pd.DataFrame()
|
||
if not data_list:
|
||
return pd.DataFrame()
|
||
data_df = pd.DataFrame(data_list)
|
||
data_df.columns = [
|
||
"symbol", "trade_fee_ratio", "close_today_fee_ratio", "delivery_fee_unit",
|
||
"spec_long_margin_ratio", "hedge_long_margin_ratio", "delivery_fee_ratio",
|
||
"product_id", "product_name", "close_today_fee_unit", "trade_fee_unit",
|
||
"hedge_short_margin_ratio", "settle_price", "uni_direction",
|
||
"spec_short_margin_ratio", "is_close_today"
|
||
]
|
||
data_df["variety"] = data_df["symbol"].str.extract(r"([A-Za-z]+)")
|
||
data_df["date"] = date
|
||
data_df = data_df[
|
||
["date", "symbol", "variety", "settle_price", "spec_long_margin_ratio",
|
||
"hedge_long_margin_ratio", "spec_short_margin_ratio", "hedge_short_margin_ratio",
|
||
"trade_fee_ratio", "close_today_fee_ratio", "is_close_today"]
|
||
]
|
||
return data_df
|
||
|
||
|
||
def futures_settle(date: str = "20260119", market: str = "CFFEX") -> pd.DataFrame:
|
||
"""
|
||
期货交易所结算参数
|
||
:param date: 结算日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象,默认为当前交易日
|
||
:type date: str or datetime.date
|
||
:param market: 交易所代码: CFFEX-中金所, CZCE-郑商所, SHFE-上期所, DCE-大商所, INE-上能中心, GFEX-广期所
|
||
:type market: str
|
||
:return: 结算参数数据(统一格式)
|
||
:rtype: pandas.DataFrame
|
||
"""
|
||
if market.upper() == "CFFEX":
|
||
df = futures_settle_cffex(date)
|
||
elif market.upper() == "CZCE":
|
||
df = futures_settle_czce(date)
|
||
elif market.upper() == "SHFE":
|
||
df = futures_settle_shfe(date)
|
||
elif market.upper() == "GFEX":
|
||
df = futures_settle_gfex(date)
|
||
elif market.upper() == "INE":
|
||
df = futures_settle_ine(date)
|
||
else:
|
||
print(f"Unsupported market: {market}")
|
||
return pd.DataFrame(columns=SETTLE_OUTPUT_COLUMNS)
|
||
temp_df = _normalize_settle_columns(df)
|
||
return temp_df
|
||
|
||
|
||
if __name__ == "__main__":
|
||
futures_settle_cffex_df = futures_settle_cffex(date="20260119")
|
||
print("=== 中金所结算参数 ===")
|
||
print(futures_settle_cffex_df)
|
||
|
||
futures_settle_czce_df = futures_settle_czce(date="20260119")
|
||
print("\n=== 郑商所结算参数 ===")
|
||
print(futures_settle_czce_df)
|
||
|
||
futures_settle_shfe_df = futures_settle_shfe(date="20260119")
|
||
print("\n=== 上期所结算参数 ===")
|
||
print(futures_settle_shfe_df)
|
||
|
||
futures_settle_gfex_df = futures_settle_gfex(date="20260119")
|
||
print("\n=== 广期所结算参数 ===")
|
||
print(futures_settle_gfex_df)
|
||
|
||
futures_settle_ine_df = futures_settle_ine(date="20250117")
|
||
print("\n=== 上能中心结算参数 ===")
|
||
print(futures_settle_ine_df)
|
||
|
||
futures_settle_df = futures_settle(date="20260119", market="CFFEX")
|
||
print("\n=== 通用接口-CFFEX ===")
|
||
print(futures_settle_df)
|
||
|
||
futures_settle_df = futures_settle(date="20260119", market="CZCE")
|
||
print("\n=== 通用接口-CZCE ===")
|
||
print(futures_settle_df)
|
||
|
||
futures_settle_df = futures_settle(date="20260119", market="SHFE")
|
||
print("\n=== 通用接口-SHFE ===")
|
||
print(futures_settle_df)
|
||
|
||
futures_settle_df = futures_settle(date="20260119", market="GFEX")
|
||
print("\n=== 通用接口-GFEX ===")
|
||
print(futures_settle_df)
|
||
|
||
futures_settle_df = futures_settle(date="20260119", market="INE")
|
||
print("\n=== 通用接口-INE ===")
|
||
print(futures_settle_df)
|