Files
MoFin/venv/lib/python3.12/site-packages/akshare/futures/futures_zh_sina.py
T
知微 fa45d8aa5f fix: 小果地址统一node122(兼容LAN+EasyTier)
- 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,直连正常
2026-06-30 02:56:35 +08:00

729 lines
26 KiB
Python

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2024/3/20 16:00
Desc: 新浪财经-国内期货-实时数据获取
https://vip.stock.finance.sina.com.cn/quotes_service/view/qihuohangqing.html#titlePos_3
P.S. 注意采集速度, 容易封禁 IP, 如果不能访问请稍后再试
"""
import json
import time
from functools import lru_cache
import pandas as pd
import requests
import py_mini_racer
from akshare.futures.cons import (
zh_subscribe_exchange_symbol_url,
zh_match_main_contract_url,
zh_match_main_contract_payload,
)
from akshare.futures.futures_contract_detail import futures_contract_detail
from akshare.utils import demjson
@lru_cache()
def futures_symbol_mark() -> pd.DataFrame:
"""
期货的品种和代码映射
https://vip.stock.finance.sina.com.cn/quotes_service/view/js/qihuohangqing.js
:return: 期货的品种和代码映射
:rtype: pandas.DataFrame
"""
url = (
"https://vip.stock.finance.sina.com.cn/quotes_service/view/js/qihuohangqing.js"
)
r = requests.get(url)
r.encoding = "gb2312"
data_text = r.text
raw_json = data_text[data_text.find("{") : data_text.find("}") + 1]
data_json = demjson.decode(raw_json)
czce_mark_list = [item[1] for item in data_json["czce"][1:]]
dce_mark_list = [item[1] for item in data_json["dce"][1:]]
shfe_mark_list = [item[1] for item in data_json["shfe"][1:]]
cffex_mark_list = [item[1] for item in data_json["cffex"][1:]]
gfex_mark_list = [item[1] for item in data_json["gfex"][1:]]
all_mark_list = (
czce_mark_list
+ dce_mark_list
+ shfe_mark_list
+ cffex_mark_list
+ gfex_mark_list
)
czce_market_name_list = [data_json["czce"][0]] * len(czce_mark_list)
dce_market_name_list = [data_json["dce"][0]] * len(dce_mark_list)
shfe_market_name_list = [data_json["shfe"][0]] * len(shfe_mark_list)
cffex_market_name_list = [data_json["cffex"][0]] * len(cffex_mark_list)
gfex_market_name_list = [data_json["gfex"][0]] * len(gfex_mark_list)
all_market_name_list = (
czce_market_name_list
+ dce_market_name_list
+ shfe_market_name_list
+ cffex_market_name_list
+ gfex_market_name_list
)
czce_symbol_list = [item[0] for item in data_json["czce"][1:]]
dce_symbol_list = [item[0] for item in data_json["dce"][1:]]
shfe_symbol_list = [item[0] for item in data_json["shfe"][1:]]
cffex_symbol_list = [item[0] for item in data_json["cffex"][1:]]
gfex_symbol_list = [item[0] for item in data_json["gfex"][1:]]
all_symbol_list = (
czce_symbol_list
+ dce_symbol_list
+ shfe_symbol_list
+ cffex_symbol_list
+ gfex_symbol_list
)
temp_df = pd.DataFrame([all_market_name_list, all_symbol_list, all_mark_list]).T
temp_df.columns = [
"exchange",
"symbol",
"mark",
]
return temp_df
def futures_zh_realtime(symbol: str = "PTA") -> pd.DataFrame:
"""
期货品种当前时刻所有可交易的合约实时数据
https://vip.stock.finance.sina.com.cn/quotes_service/view/qihuohangqing.html#titlePos_1
:param symbol: 品种名称;可以通过 ak.futures_symbol_mark() 获取所有品种命名表
:type symbol: str
:return: 期货品种当前时刻所有可交易的合约实时数据
:rtype: pandas.DataFrame
"""
_futures_symbol_mark_df = futures_symbol_mark()
symbol_mark_map = dict(
zip(_futures_symbol_mark_df["symbol"], _futures_symbol_mark_df["mark"])
)
url = "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQFuturesData"
params = {
"page": "1",
"sort": "position",
"asc": "0",
"node": symbol_mark_map[symbol],
"base": "futures",
}
r = requests.get(url, params=params)
data_json = r.json()
temp_df = pd.DataFrame(data_json)
temp_df["trade"] = pd.to_numeric(temp_df["trade"], errors="coerce")
temp_df["settlement"] = pd.to_numeric(temp_df["settlement"], errors="coerce")
temp_df["presettlement"] = pd.to_numeric(temp_df["presettlement"], errors="coerce")
temp_df["open"] = pd.to_numeric(temp_df["open"], errors="coerce")
temp_df["high"] = pd.to_numeric(temp_df["high"], errors="coerce")
temp_df["low"] = pd.to_numeric(temp_df["low"], errors="coerce")
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["bidprice1"] = pd.to_numeric(temp_df["bidprice1"], errors="coerce")
temp_df["askprice1"] = pd.to_numeric(temp_df["askprice1"], errors="coerce")
temp_df["bidvol1"] = pd.to_numeric(temp_df["bidvol1"], errors="coerce")
temp_df["askvol1"] = pd.to_numeric(temp_df["askvol1"], errors="coerce")
temp_df["volume"] = pd.to_numeric(temp_df["volume"], errors="coerce")
temp_df["position"] = pd.to_numeric(temp_df["position"], errors="coerce")
temp_df["preclose"] = pd.to_numeric(temp_df["preclose"], errors="coerce")
temp_df["changepercent"] = pd.to_numeric(temp_df["changepercent"], errors="coerce")
temp_df["bid"] = pd.to_numeric(temp_df["bid"], errors="coerce")
temp_df["ask"] = pd.to_numeric(temp_df["ask"], errors="coerce")
temp_df["prevsettlement"] = pd.to_numeric(
temp_df["prevsettlement"], errors="coerce"
)
return temp_df
def zh_subscribe_exchange_symbol(symbol: str = "cffex") -> pd.DataFrame:
"""
交易所具体的可交易品种
https://vip.stock.finance.sina.com.cn/quotes_service/view/qihuohangqing.html#titlePos_1
:param symbol: choice of {'czce', 'dce', 'shfe', 'cffex', 'gfex'}
:type symbol: str
:return: 交易所具体的可交易品种
:rtype: dict
"""
r = requests.get(zh_subscribe_exchange_symbol_url)
r.encoding = "gbk"
data_text = r.text
data_json = demjson.decode(
data_text[data_text.find("{") : data_text.find("};") + 1]
)
if symbol == "czce":
data_json["czce"].remove("郑州商品交易所")
return pd.DataFrame(data_json["czce"])
if symbol == "dce":
data_json["dce"].remove("大连商品交易所")
return pd.DataFrame(data_json["dce"])
if symbol == "shfe":
data_json["shfe"].remove("上海期货交易所")
return pd.DataFrame(data_json["shfe"])
if symbol == "cffex":
data_json["cffex"].remove("中国金融期货交易所")
return pd.DataFrame(data_json["cffex"])
if symbol == "gfex":
data_json["gfex"].remove("广州期货交易所")
return pd.DataFrame(data_json["gfex"])
def match_main_contract(symbol: str = "cffex") -> str:
"""
新浪财经-期货-主力合约
https://vip.stock.finance.sina.com.cn/quotes_service/view/qihuohangqing.html#titlePos_1
:param symbol: choice of {'czce', 'dce', 'shfe', 'cffex', 'gfex'}
:type symbol: str
:return: 主力合约的字符串
:rtype: str
"""
subscribe_exchange_list = []
exchange_symbol_list = zh_subscribe_exchange_symbol(symbol).iloc[:, 1].tolist()
for item in exchange_symbol_list:
# item = 'sngz_qh'
zh_match_main_contract_payload.update({"node": item})
res = requests.get(
zh_match_main_contract_url, params=zh_match_main_contract_payload
)
data_json = demjson.decode(res.text)
data_df = pd.DataFrame(data_json)
try:
main_contract = data_df[data_df.iloc[:, 3:].duplicated()]
print(main_contract["symbol"].values[0])
subscribe_exchange_list.append(main_contract["symbol"].values[0])
except: # noqa: E722
if len(data_df) == 1:
subscribe_exchange_list.append(data_df["symbol"].values[0])
print(data_df["symbol"].values[0])
else:
print(item, "无主力合约")
continue
print(f"{symbol}主力合约获取成功")
return ",".join([item for item in subscribe_exchange_list])
def futures_zh_spot(
symbol: str = "V2309",
market: str = "CF",
adjust: str = "0",
) -> pd.DataFrame:
"""
期货的实时行情数据
https://vip.stock.finance.sina.com.cn/quotes_service/view/qihuohangqing.html#titlePos_1
:param symbol: 合约名称的字符串组合
:type symbol: str
:param market: CF 为商品期货
:type market: str
:param adjust: '1' or '0';字符串的 0 或 1;返回合约、交易所和最小变动单位的实时数据, 返回数据会变慢
:type adjust: str
:return: 期货的实时行情数据
:rtype: pandas.DataFrame
"""
file_data = "Math.round(Math.random() * 2147483648).toString(16)"
ctx = py_mini_racer.MiniRacer()
rn_code = ctx.eval(file_data)
subscribe_list = ",".join(["nf_" + item.strip() for item in symbol.split(",")])
url = f"https://hq.sinajs.cn/rn={rn_code}&list={subscribe_list}"
headers = {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Cache-Control": "no-cache",
"Host": "hq.sinajs.cn",
"Pragma": "no-cache",
"Proxy-Connection": "keep-alive",
"Referer": "https://vip.stock.finance.sina.com.cn/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/97.0.4692.71 Safari/537.36",
}
r = requests.get(url, headers=headers)
data_df = pd.DataFrame(
[
item.strip().split("=")[1].split(",")
for item in r.text.split(";")
if item.strip() != ""
]
)
data_df.iloc[:, 0] = data_df.iloc[:, 0].str.replace('"', "")
data_df.iloc[:, -1] = data_df.iloc[:, -1].str.replace('"', "")
if adjust == "1":
contract_name_list = [item.split("_")[1] for item in subscribe_list.split(",")]
contract_min_list = []
contract_exchange_list = []
for contract_name in contract_name_list:
temp_df = futures_contract_detail(symbol=contract_name)
exchange_name = temp_df[temp_df["item"] == "上市交易所"]["value"].values[0]
contract_exchange_list.append(exchange_name)
contract_min = temp_df[temp_df["item"] == "最小变动价位"]["value"].values[0]
contract_min_list.append(contract_min)
if market == "CF":
data_df.columns = [
"symbol",
"time",
"open",
"high",
"low",
"last_close",
"bid_price",
"ask_price",
"current_price",
"avg_price",
"last_settle_price",
"buy_vol",
"sell_vol",
"hold",
"volume",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
]
data_df = data_df[
[
"symbol",
"time",
"open",
"high",
"low",
"current_price",
"bid_price",
"ask_price",
"buy_vol",
"sell_vol",
"hold",
"volume",
"avg_price",
"last_close",
"last_settle_price",
]
]
data_df["exchange"] = contract_exchange_list
data_df["contract"] = contract_name_list
data_df["contract_min_change"] = contract_min_list
data_df["open"] = pd.to_numeric(data_df["open"], errors="coerce")
data_df["high"] = pd.to_numeric(data_df["high"], errors="coerce")
data_df["low"] = pd.to_numeric(data_df["low"], errors="coerce")
data_df["current_price"] = pd.to_numeric(
data_df["current_price"], errors="coerce"
)
data_df["bid_price"] = pd.to_numeric(data_df["bid_price"], errors="coerce")
data_df["ask_price"] = pd.to_numeric(data_df["ask_price"], errors="coerce")
data_df["buy_vol"] = pd.to_numeric(data_df["buy_vol"], errors="coerce")
data_df["sell_vol"] = pd.to_numeric(data_df["sell_vol"], errors="coerce")
data_df["hold"] = pd.to_numeric(data_df["hold"], errors="coerce")
data_df["volume"] = pd.to_numeric(data_df["volume"], errors="coerce")
data_df["avg_price"] = pd.to_numeric(data_df["avg_price"], errors="coerce")
data_df["last_close"] = pd.to_numeric(
data_df["last_close"], errors="coerce"
)
data_df["last_settle_price"] = pd.to_numeric(
data_df["last_settle_price"], errors="coerce"
)
data_df.dropna(subset=["current_price"], ignore_index=True, inplace=True)
return data_df
else:
data_df.columns = [
"open",
"high",
"low",
"current_price",
"volume",
"amount",
"hold",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"__",
"time",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"symbol",
]
data_df = data_df[
[
"symbol",
"time",
"open",
"high",
"low",
"current_price",
"hold",
"volume",
"amount",
]
]
data_df["exchange"] = contract_exchange_list
data_df["contract"] = contract_name_list
data_df["contract_min_change"] = contract_min_list
data_df["open"] = pd.to_numeric(data_df["open"], errors="coerce")
data_df["high"] = pd.to_numeric(data_df["high"], errors="coerce")
data_df["low"] = pd.to_numeric(data_df["low"], errors="coerce")
data_df["current_price"] = pd.to_numeric(
data_df["current_price"], errors="coerce"
)
data_df["hold"] = pd.to_numeric(data_df["hold"], errors="coerce")
data_df["volume"] = pd.to_numeric(data_df["volume"], errors="coerce")
data_df["amount"] = pd.to_numeric(data_df["amount"], errors="coerce")
data_df.dropna(subset=["current_price"], ignore_index=True, inplace=True)
return data_df
else:
if market == "CF":
# 此处由于 20220601 接口变动,增加了字段,此处增加异常判断,except 后为新代码
try:
data_df.columns = [
"symbol",
"time",
"open",
"high",
"low",
"last_close",
"bid_price",
"ask_price",
"current_price",
"avg_price",
"last_settle_price",
"buy_vol",
"sell_vol",
"hold",
"volume",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
]
except: # noqa: E722
data_df.columns = [
"symbol",
"time",
"open",
"high",
"low",
"last_close",
"bid_price",
"ask_price",
"current_price",
"avg_price",
"last_settle_price",
"buy_vol",
"sell_vol",
"hold",
"volume",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
]
data_df = data_df[
[
"symbol",
"time",
"open",
"high",
"low",
"current_price",
"bid_price",
"ask_price",
"buy_vol",
"sell_vol",
"hold",
"volume",
"avg_price",
"last_close",
"last_settle_price",
]
]
data_df["open"] = pd.to_numeric(data_df["open"], errors="coerce")
data_df["high"] = pd.to_numeric(data_df["high"], errors="coerce")
data_df["low"] = pd.to_numeric(data_df["low"], errors="coerce")
data_df["current_price"] = pd.to_numeric(
data_df["current_price"], errors="coerce"
)
data_df["bid_price"] = pd.to_numeric(data_df["bid_price"], errors="coerce")
data_df["ask_price"] = pd.to_numeric(data_df["ask_price"], errors="coerce")
data_df["buy_vol"] = pd.to_numeric(data_df["buy_vol"], errors="coerce")
data_df["sell_vol"] = pd.to_numeric(data_df["sell_vol"], errors="coerce")
data_df["hold"] = pd.to_numeric(data_df["hold"], errors="coerce")
data_df["volume"] = pd.to_numeric(data_df["volume"], errors="coerce")
data_df["avg_price"] = pd.to_numeric(data_df["avg_price"], errors="coerce")
data_df["last_close"] = pd.to_numeric(
data_df["last_close"], errors="coerce"
)
data_df["last_settle_price"] = pd.to_numeric(
data_df["last_settle_price"], errors="coerce"
)
data_df.dropna(subset=["current_price"], ignore_index=True, inplace=True)
return data_df
else:
data_df.columns = [
"open",
"high",
"low",
"current_price",
"volume",
"amount",
"hold",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"__",
"time",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"_",
"symbol",
]
data_df = data_df[
[
"symbol",
"time",
"open",
"high",
"low",
"current_price",
"hold",
"volume",
"amount",
]
]
data_df["open"] = pd.to_numeric(data_df["open"], errors="coerce")
data_df["high"] = pd.to_numeric(data_df["high"], errors="coerce")
data_df["low"] = pd.to_numeric(data_df["low"], errors="coerce")
data_df["current_price"] = pd.to_numeric(
data_df["current_price"], errors="coerce"
)
data_df["hold"] = pd.to_numeric(data_df["hold"], errors="coerce")
data_df["volume"] = pd.to_numeric(data_df["volume"], errors="coerce")
data_df["amount"] = pd.to_numeric(data_df["amount"], errors="coerce")
data_df.dropna(subset=["current_price"], inplace=True, ignore_index=True)
return data_df
def futures_zh_minute_sina(symbol: str = "IF2008", period: str = "1") -> pd.DataFrame:
"""
中国各品种期货分钟频率数据
https://vip.stock.finance.sina.com.cn/quotes_service/view/qihuohangqing.html#titlePos_3
:param symbol: 可以通过 match_main_contract(symbol="cffex") 获取, 或者访问网页获取
:type symbol: str
:param period: choice of {"1": "1分钟", "5": "5分钟", "15": "15分钟", "30": "30分钟", "60": "60分钟"}
:type period: str
:return: 指定 symbol 和 period 的数据
:rtype: pandas.DataFrame
"""
url = "https://stock2.finance.sina.com.cn/futures/api/jsonp.php/=/InnerFuturesNewService.getFewMinLine"
params = {
"symbol": symbol,
"type": period,
}
r = requests.get(url, params=params)
temp_df = pd.DataFrame(json.loads(r.text.split("=(")[1].split(");")[0]))
temp_df.columns = [
"datetime",
"open",
"high",
"low",
"close",
"volume",
"hold",
]
temp_df["open"] = pd.to_numeric(temp_df["open"], errors="coerce")
temp_df["high"] = pd.to_numeric(temp_df["high"], errors="coerce")
temp_df["low"] = pd.to_numeric(temp_df["low"], errors="coerce")
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["volume"] = pd.to_numeric(temp_df["volume"], errors="coerce")
temp_df["hold"] = pd.to_numeric(temp_df["hold"], errors="coerce")
return temp_df
def futures_zh_daily_sina(symbol: str = "RB0") -> pd.DataFrame:
"""
中国各品种期货日频率数据
https://finance.sina.com.cn/futures/quotes/V2105.shtml
:param symbol: 可以通过 match_main_contract(symbol="cffex") 获取, 或者访问网页获取
:type symbol: str
:return: 指定 symbol 的数据
:rtype: pandas.DataFrame
"""
date = "20210412"
url = (
"https://stock2.finance.sina.com.cn/futures/api/jsonp.php/var%20_V21052021_4_12="
"/InnerFuturesNewService.getDailyKLine"
)
params = {
"symbol": symbol,
"type": "_".join([date[:4], date[4:6], date[6:]]),
}
r = requests.get(url, params=params)
temp_df = pd.DataFrame(json.loads(r.text.split("=(")[1].split(");")[0]))
temp_df.columns = [
"date",
"open",
"high",
"low",
"close",
"volume",
"hold",
"settle",
]
temp_df["open"] = pd.to_numeric(temp_df["open"], errors="coerce")
temp_df["high"] = pd.to_numeric(temp_df["high"], errors="coerce")
temp_df["low"] = pd.to_numeric(temp_df["low"], errors="coerce")
temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
temp_df["volume"] = pd.to_numeric(temp_df["volume"], errors="coerce")
temp_df["hold"] = pd.to_numeric(temp_df["hold"], errors="coerce")
temp_df["settle"] = pd.to_numeric(temp_df["settle"], errors="coerce")
return temp_df
if __name__ == "__main__":
match_main_contract_df = match_main_contract(symbol="gfex")
print(match_main_contract_df)
futures_zh_spot_df = futures_zh_spot(symbol="V2405,V2409", market="CF", adjust="0")
print(futures_zh_spot_df)
futures_zh_spot_df = futures_zh_spot(symbol="V2405", market="CF", adjust="0")
print(futures_zh_spot_df)
futures_symbol_mark_df = futures_symbol_mark()
print(futures_symbol_mark_df)
futures_zh_realtime_df = futures_zh_realtime(symbol="工业硅")
print(futures_zh_realtime_df)
futures_zh_minute_sina_df = futures_zh_minute_sina(symbol="RB0", period="1")
print(futures_zh_minute_sina_df)
futures_zh_daily_sina_df = futures_zh_daily_sina(symbol="RB0")
print(futures_zh_daily_sina_df)
futures_zh_daily_sina_df = futures_zh_daily_sina(symbol="RB2410")
print(futures_zh_daily_sina_df)
dce_text = match_main_contract(symbol="dce")
czce_text = match_main_contract(symbol="czce")
shfe_text = match_main_contract(symbol="shfe")
gfex_text = match_main_contract(symbol="gfex")
while True:
time.sleep(3)
futures_zh_spot_df = futures_zh_spot(
symbol=",".join([dce_text, czce_text, shfe_text, gfex_text]),
market="CF",
adjust="0",
)
print(futures_zh_spot_df)