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,直连正常
299 lines
9.4 KiB
Python
299 lines
9.4 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding:utf-8 -*-
|
|
"""
|
|
Date: 2025/3/5 18:00
|
|
Desc: 新浪财经-外盘期货
|
|
https://finance.sina.com.cn/money/future/hf.html
|
|
"""
|
|
|
|
import time
|
|
from typing import Union, List
|
|
|
|
import pandas as pd
|
|
import requests
|
|
from bs4 import BeautifulSoup
|
|
|
|
from akshare.utils import demjson
|
|
|
|
|
|
def _get_real_name_list() -> list:
|
|
"""
|
|
新浪-外盘期货所有品种的中文名称
|
|
https://finance.sina.com.cn/money/future/hf.html
|
|
:return: 外盘期货所有品种的中文名称
|
|
:rtype: list
|
|
"""
|
|
url = "https://finance.sina.com.cn/money/future/hf.html"
|
|
r = requests.get(url)
|
|
r.encoding = "gb2312"
|
|
data_text = r.text
|
|
need_text = data_text[
|
|
data_text.find("var oHF_1 = ") + 12 : data_text.find("var oHF_2") - 2
|
|
].replace("\n\t", "")
|
|
data_json = demjson.decode(need_text)
|
|
name_list = [item[0].strip() for item in data_json.values()]
|
|
return name_list
|
|
|
|
|
|
def futures_foreign_commodity_subscribe_exchange_symbol() -> list:
|
|
"""
|
|
需要订阅的行情的代码
|
|
https://finance.sina.com.cn/money/future/hf.html
|
|
:return: 需要订阅的行情的代码
|
|
:rtype: list
|
|
"""
|
|
url = "https://finance.sina.com.cn/money/future/hf.html"
|
|
r = requests.get(url)
|
|
r.encoding = "gb2312"
|
|
data_text = r.text
|
|
data_json = demjson.decode(
|
|
data_text[
|
|
data_text.find("var oHF_1 = ") + 12 : data_text.find("var oHF_2 = ") - 2
|
|
]
|
|
)
|
|
code_list = list(data_json.keys())
|
|
return code_list
|
|
|
|
|
|
def futures_hq_subscribe_exchange_symbol() -> pd.DataFrame:
|
|
"""
|
|
将品种字典转化为 pandas.DataFrame
|
|
https://finance.sina.com.cn/money/future/hf.html
|
|
:return: 品种对应表
|
|
:rtype: pandas.DataFrame
|
|
"""
|
|
inner_dict = {
|
|
"新加坡铁矿石": "FEF",
|
|
"马棕油": "FCPO",
|
|
"日橡胶": "RSS3",
|
|
"美国原糖": "RS",
|
|
"CME比特币期货": "BTC",
|
|
"NYBOT-棉花": "CT",
|
|
"LME镍3个月": "NID",
|
|
"LME铅3个月": "PBD",
|
|
"LME锡3个月": "SND",
|
|
"LME锌3个月": "ZSD",
|
|
"LME铝3个月": "AHD",
|
|
"LME铜3个月": "CAD",
|
|
"CBOT-黄豆": "S",
|
|
"CBOT-小麦": "W",
|
|
"CBOT-玉米": "C",
|
|
"CBOT-黄豆油": "BO",
|
|
"CBOT-黄豆粉": "SM",
|
|
"日本橡胶": "TRB",
|
|
"COMEX铜": "HG",
|
|
"NYMEX天然气": "NG",
|
|
"NYMEX原油": "CL",
|
|
"COMEX白银": "SI",
|
|
"COMEX黄金": "GC",
|
|
"CME-瘦肉猪": "LHC",
|
|
"布伦特原油": "OIL",
|
|
"伦敦金": "XAU",
|
|
"伦敦银": "XAG",
|
|
"伦敦铂金": "XPT",
|
|
"伦敦钯金": "XPD",
|
|
"欧洲碳排放": "EUA",
|
|
}
|
|
temp_df = pd.DataFrame.from_dict(inner_dict, orient="index")
|
|
temp_df.reset_index(inplace=True)
|
|
temp_df.columns = ["symbol", "code"]
|
|
return temp_df
|
|
|
|
|
|
def futures_foreign_commodity_realtime(symbol: Union[str, List[str]]) -> pd.DataFrame:
|
|
"""
|
|
新浪-外盘期货-行情数据
|
|
https://finance.sina.com.cn/money/future/hf.html
|
|
:param symbol: 通过调用 ak.futures_hq_subscribe_exchange_symbol() 函数来获取
|
|
:type symbol: list or str
|
|
:return: 行情数据
|
|
:rtype: pandas.DataFrame
|
|
"""
|
|
if isinstance(symbol, list):
|
|
payload = "?list=" + ",".join(["hf_" + item for item in symbol])
|
|
else:
|
|
symbol = symbol.split(",")
|
|
payload = "?list=" + ",".join(["hf_" + item for item in symbol])
|
|
url = "https://hq.sinajs.cn/" + payload
|
|
headers = {
|
|
"Accept": "*/*",
|
|
"Accept-Encoding": "gzip, deflate, br",
|
|
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
|
"Cache-Control": "no-cache",
|
|
"Connection": "keep-alive",
|
|
"Host": "hq.sinajs.cn",
|
|
"Pragma": "no-cache",
|
|
"Referer": "https://finance.sina.com.cn/",
|
|
"sec-ch-ua": '" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"',
|
|
"sec-ch-ua-mobile": "?0",
|
|
"sec-ch-ua-platform": '"Windows"',
|
|
"Sec-Fetch-Dest": "script",
|
|
"Sec-Fetch-Mode": "no-cors",
|
|
"Sec-Fetch-Site": "cross-site",
|
|
"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_text = r.text
|
|
data_df = pd.DataFrame(
|
|
[
|
|
item.strip().split("=")[1].split(",")
|
|
for item in data_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('"', "")
|
|
|
|
# 处理伦敦金 XAU 的情况
|
|
if len(data_df.columns) == 14:
|
|
data_df["temp"] = None
|
|
|
|
data_df.columns = [
|
|
"current_price",
|
|
"-",
|
|
"bid",
|
|
"ask",
|
|
"high",
|
|
"low",
|
|
"time",
|
|
"last_settle_price",
|
|
"open",
|
|
"hold",
|
|
"-",
|
|
"-",
|
|
"date",
|
|
"symbol",
|
|
"current_price_rmb",
|
|
]
|
|
temp_symbol_code_df = futures_hq_subscribe_exchange_symbol()
|
|
temp_symbol_code_dict = dict(
|
|
zip(temp_symbol_code_df["code"], temp_symbol_code_df["symbol"])
|
|
)
|
|
data_df["symbol"] = [temp_symbol_code_dict[subscribe] for subscribe in symbol]
|
|
data_df = data_df[
|
|
[
|
|
"symbol",
|
|
"current_price",
|
|
"current_price_rmb",
|
|
"bid",
|
|
"ask",
|
|
"high",
|
|
"low",
|
|
"time",
|
|
"last_settle_price",
|
|
"open",
|
|
"hold",
|
|
"date",
|
|
]
|
|
]
|
|
data_df.columns = [
|
|
"名称",
|
|
"最新价",
|
|
"人民币报价",
|
|
"买价",
|
|
"卖价",
|
|
"最高价",
|
|
"最低价",
|
|
"行情时间",
|
|
"昨日结算价",
|
|
"开盘价",
|
|
"持仓量",
|
|
"日期",
|
|
]
|
|
data_df.dropna(how="all", inplace=True)
|
|
data_df["最新价"] = pd.to_numeric(data_df["最新价"], errors="coerce")
|
|
data_df["人民币报价"] = pd.to_numeric(data_df["人民币报价"], errors="coerce")
|
|
data_df["买价"] = pd.to_numeric(data_df["买价"], errors="coerce")
|
|
data_df["卖价"] = pd.to_numeric(data_df["卖价"], errors="coerce")
|
|
data_df["最高价"] = pd.to_numeric(data_df["最高价"], errors="coerce")
|
|
data_df["最低价"] = pd.to_numeric(data_df["最低价"], errors="coerce")
|
|
data_df["昨日结算价"] = pd.to_numeric(data_df["昨日结算价"], errors="coerce")
|
|
data_df["开盘价"] = pd.to_numeric(data_df["开盘价"], errors="coerce")
|
|
data_df["持仓量"] = pd.to_numeric(data_df["持仓量"], errors="coerce")
|
|
data_df["涨跌额"] = data_df["最新价"] - data_df["昨日结算价"]
|
|
data_df["涨跌幅"] = (
|
|
(data_df["最新价"] - data_df["昨日结算价"]) / data_df["昨日结算价"] * 100
|
|
)
|
|
data_df = data_df[
|
|
[
|
|
"名称",
|
|
"最新价",
|
|
"人民币报价",
|
|
"涨跌额",
|
|
"涨跌幅",
|
|
"开盘价",
|
|
"最高价",
|
|
"最低价",
|
|
"昨日结算价",
|
|
"持仓量",
|
|
"买价",
|
|
"卖价",
|
|
"行情时间",
|
|
"日期",
|
|
]
|
|
]
|
|
|
|
# 获取转换比例数据
|
|
url = "https://finance.sina.com.cn/money/future/hf.html"
|
|
r = requests.get(url)
|
|
r.encoding = "utf-8"
|
|
soup = BeautifulSoup(r.text, features="lxml")
|
|
data_text = soup.find_all(name="script", attrs={"type": "text/javascript"})[
|
|
-2
|
|
].string.strip()
|
|
raw_text = data_text[data_text.find("oHF_1 = ") : data_text.find("oHF_2")]
|
|
need_text = raw_text[raw_text.find("{") : raw_text.rfind("}") + 1]
|
|
data_json = demjson.decode(need_text)
|
|
price_mul = pd.DataFrame(
|
|
[
|
|
[item[0] for item in data_json.values()],
|
|
[item[1][0] for item in data_json.values()],
|
|
]
|
|
).T
|
|
price_mul.columns = ["symbol", "price"]
|
|
price_mul = price_mul[price_mul["symbol"].isin(data_df["名称"])]
|
|
price_mul.reset_index(inplace=True, drop=True)
|
|
price_mul["price"] = pd.to_numeric(price_mul["price"], errors="coerce")
|
|
|
|
# 获取汇率数据
|
|
url = "https://hq.sinajs.cn/?list=USDCNY"
|
|
r = requests.get(url, headers=headers)
|
|
data_text = r.text
|
|
usd_rmb = float(
|
|
data_text[data_text.find('"') + 1 : data_text.find(",美元人民币")].split(",")[
|
|
-1
|
|
]
|
|
)
|
|
|
|
# 计算人民币报价
|
|
data_df["最新价"] = pd.to_numeric(data_df["最新价"], errors="coerce")
|
|
data_df["人民币报价"] = data_df["最新价"] * price_mul["price"] * float(usd_rmb)
|
|
data_df.dropna(thresh=4, inplace=True)
|
|
return data_df
|
|
|
|
|
|
if __name__ == "__main__":
|
|
futures_hq_subscribe_exchange_symbol_df = futures_hq_subscribe_exchange_symbol()
|
|
print(futures_hq_subscribe_exchange_symbol_df)
|
|
|
|
print("开始接收实时行情, 每秒刷新一次")
|
|
subscribes = futures_foreign_commodity_subscribe_exchange_symbol()
|
|
|
|
futures_foreign_commodity_realtime_df = futures_foreign_commodity_realtime(
|
|
symbol="CT,NID"
|
|
)
|
|
print(futures_foreign_commodity_realtime_df)
|
|
|
|
futures_foreign_commodity_realtime_df = futures_foreign_commodity_realtime(
|
|
symbol=["XAU"]
|
|
)
|
|
print(futures_foreign_commodity_realtime_df)
|
|
|
|
while True:
|
|
futures_foreign_commodity_realtime_df = futures_foreign_commodity_realtime(
|
|
symbol=subscribes
|
|
)
|
|
print(futures_foreign_commodity_realtime_df)
|
|
time.sleep(3)
|