stock-tracker
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2019/9/30 13:58
|
||||
Desc:
|
||||
"""
|
||||
@@ -0,0 +1,637 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/7/21 15:00
|
||||
Desc: 期货配置文件
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import pickle
|
||||
import re
|
||||
|
||||
|
||||
futures_inventory_em_symbol_dict = {
|
||||
"a": "A", # 豆一
|
||||
"ag": "AG", # 沪银
|
||||
"al": "AL", # 沪铝
|
||||
"ao": "AO", # 氧化铝
|
||||
"AP": "AP", # 苹果
|
||||
"au": "AU", # 沪金
|
||||
"b": "B", # 豆二
|
||||
"bb": None, # 胶合板 (new中没有对应)
|
||||
"bc": None, # 国际铜 (new中没有对应)
|
||||
"br": "BR", # BR橡胶
|
||||
"bu": "BU", # 沥青
|
||||
"c": "C", # 玉米
|
||||
"CF": "CF", # 棉花/郑棉
|
||||
"CJ": "CJ", # 红枣
|
||||
"cs": "CS", # 淀粉/玉米淀粉
|
||||
"cu": "CU", # 沪铜
|
||||
"CY": "CY", # 棉纱
|
||||
"eb": "EB", # 苯乙烯
|
||||
"ec": "ec", # 集运欧线/集运指数(欧线)
|
||||
"eg": "EG", # 乙二醇
|
||||
"fb": None, # 纤维板 (new中没有对应)
|
||||
"FG": "FG", # 玻璃
|
||||
"PL": "PL", # 丙烯
|
||||
"fu": "FU", # 燃料油/燃油
|
||||
"hc": "HC", # 热卷
|
||||
"i": "I", # 铁矿石
|
||||
"IC": "IC", # 中证500
|
||||
"IF": "IF", # 沪深300
|
||||
"IH": "IH", # 上证50
|
||||
"IM": "IM", # 中证1000
|
||||
"j": "J", # 焦炭
|
||||
"jd": "JD", # 鸡蛋
|
||||
"jm": "JM", # 焦煤
|
||||
"JR": None, # 粳稻 (new中没有对应)
|
||||
"l": "L", # 塑料
|
||||
"lc": "lc", # 碳酸锂
|
||||
"lh": "LH", # 生猪
|
||||
"LR": None, # 晚籼稻 (new中没有对应)
|
||||
"lu": "lu", # LU燃油/低硫燃料油
|
||||
"m": "M", # 豆粕
|
||||
"MA": "MA", # 甲醇
|
||||
"ni": "NI", # 沪镍/镍
|
||||
"nr": "nr", # 20号胶
|
||||
"OI": "OI", # 菜籽油/菜油
|
||||
"p": "P", # 棕榈油/棕榈
|
||||
"pb": "PB", # 沪铅
|
||||
"PF": "PF", # 短纤
|
||||
"pg": "PG", # 液化气/液化石油气
|
||||
"PK": "PK", # 花生
|
||||
"PM": None, # 普麦 (new中没有对应)
|
||||
"pp": "PP", # 聚丙烯
|
||||
"PX": "PX", # 对二甲苯
|
||||
"rb": "RB", # 螺纹钢
|
||||
"RI": None, # 早籼稻 (new中没有对应)
|
||||
"RM": "RM", # 菜籽粕/菜粕
|
||||
"rr": None, # 粳米 (new中没有对应)
|
||||
"RS": "RS", # 油菜籽/菜籽
|
||||
"ru": "RU", # 橡胶
|
||||
"SA": "SA", # 纯碱
|
||||
"sc": None, # 原油 (new中没有对应)
|
||||
"SF": "SF", # 硅铁
|
||||
"SH": "SH", # 烧碱
|
||||
"si": "si", # 工业硅
|
||||
"SM": "SM", # 锰硅
|
||||
"sn": "SN", # 沪锡/锡
|
||||
"sp": "SP", # 纸浆
|
||||
"SR": "SR", # 白糖
|
||||
"ss": "SS", # 不锈钢
|
||||
"T": "T", # 十年国债/10年期国债
|
||||
"TA": "TA", # PTA
|
||||
"TF": "TF", # 五年国债/5年期国债
|
||||
"TL": "TL", # 三十年国债/30年期国债期货
|
||||
"TS": "TS", # 二年国债/2年期国债
|
||||
"UR": "UR", # 尿素
|
||||
"v": "V", # PVC
|
||||
"WH": None, # 强麦 (new中没有对应)
|
||||
"wr": None, # 线材 (new中没有对应)
|
||||
"y": "Y", # 豆油
|
||||
"ZC": None, # 动力煤 (new中没有对应)
|
||||
"zn": "ZN", # 沪锌
|
||||
}
|
||||
|
||||
hq_sina_spot_headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
|
||||
"image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"Host": "finance.sina.com.cn",
|
||||
"Pragma": "no-cache",
|
||||
"Referer": "https://finance.sina.com.cn/futuremarket/",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
|
||||
"(KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36",
|
||||
}
|
||||
|
||||
# zh_sina_spot
|
||||
zh_subscribe_exchange_symbol_url = (
|
||||
"http://vip.stock.finance.sina.com.cn/quotes_service/view/js/qihuohangqing.js"
|
||||
)
|
||||
zh_match_main_contract_url = (
|
||||
"http://vip.stock.finance.sina.com.cn/quotes_service/"
|
||||
"api/json_v2.php/Market_Center.getHQFuturesData"
|
||||
)
|
||||
zh_match_main_contract_payload = {
|
||||
"page": "1",
|
||||
"num": "5",
|
||||
"sort": "position",
|
||||
"asc": "0",
|
||||
"node": "001",
|
||||
"base": "futures",
|
||||
}
|
||||
zh_sina_spot_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/futuremarket/",
|
||||
"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/78.0.3904.97 Safari/537.36",
|
||||
}
|
||||
|
||||
# 99 期货
|
||||
inventory_temp_headers = {
|
||||
"Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Connection": "keep-alive",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Cookie": "UM_distinctid=16c378978de5cc-02cfeac5f7869b-c343162-1fa400-16c378978df8d7; "
|
||||
"__utmz=181566328.1570520149.3.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; "
|
||||
"ASP.NET_SessionId=wj5gxuzl3fvvr25503tquq55; __utmc=181566328; _fxaid=1D9A634AB9F5D026585"
|
||||
"6F7E85E7BC196%1D%2BOOl1inxPE7181fmKs5HCs%2BdLO%2Fq%2FbSvf46UVjo%2BE7w%3D%1DPYphpUa9OlzW"
|
||||
"UzatrOQTXLPOVillbwMhTIJas%2ByfkyVL2Hd5XA1GOSslksqDkMTccXvQ2duLNsc0CHT4789JrYNbakJrpzrxL"
|
||||
"nwtBC5GCTssKHGEpor6EwAZfWJgBUlCs4JYFcGUnh3jIO69A4LsOlRMOGf4c9cd%2FbohSjTx3VA%3D; __utma"
|
||||
"=181566328.1348268634.1564299852.1571066568.1571068391.7; tgw_l7_route=eb1311426274fc07"
|
||||
"631b2135a6431f7d; __utmt=1; __utmb=181566328.7.10.1571068391",
|
||||
"Host": "service.99qh.com",
|
||||
"Referer": "http://service.99qh.com/Storage/Storage.aspx?page=99qh",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
|
||||
"(KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36",
|
||||
}
|
||||
|
||||
# 奇货可查
|
||||
QHKC_INDEX_URL = "https://www.qhkch.com/ajax/index_show.php"
|
||||
QHKC_INDEX_TREND_URL = "https://qhkch.com/ajax/indexes_trend.php"
|
||||
QHKC_INDEX_PROFIT_LOSS_URL = "https://qhkch.com/ajax/indexes_profit_loss.php"
|
||||
QHKC_FUND_BS_URL = "https://qhkch.com/ajax/fund_bs_pie.php"
|
||||
QHKC_FUND_POSITION_URL = "https://qhkch.com/ajax/fund_position_pie.php"
|
||||
QHKC_FUND_POSITION_CHANGE_URL = "https://qhkch.com/ajax/fund_position_chge_pie.php"
|
||||
QHKC_FUND_DEAL_URL = "https://qhkch.com/ajax/fund_deal_pie.php"
|
||||
QHKC_FUND_BIG_CHANGE_URL = "https://qhkch.com/ajax/fund_big_chge.php"
|
||||
QHKC_TOOL_FOREIGN_URL = "https://qhkch.com/ajax/toolbox_foreign.php"
|
||||
QHKC_TOOL_GDP_URL = "https://qhkch.com/dist/views/toolbox/gdp.html?v=1.10.7.1"
|
||||
|
||||
# 键值对: 键为交易所代码, 值为具体合约代码
|
||||
market_exchange_symbols = {
|
||||
"cffex": ["IF", "IC", "IM", "IH", "T", "TF", "TS", "TL"],
|
||||
"dce": [
|
||||
"C",
|
||||
"CS",
|
||||
"A",
|
||||
"B",
|
||||
"M",
|
||||
"Y",
|
||||
"P",
|
||||
"FB",
|
||||
"BB",
|
||||
"JD",
|
||||
"L",
|
||||
"V",
|
||||
"PP",
|
||||
"J",
|
||||
"JM",
|
||||
"I",
|
||||
"EG",
|
||||
"RR",
|
||||
"EB", # 20191009
|
||||
"PG",
|
||||
"LH", # 20210108 生猪期货
|
||||
"LG", # 20241118 原木期货
|
||||
"BZ", # 20250708 纯苯期货
|
||||
],
|
||||
"czce": [
|
||||
"WH",
|
||||
"PM",
|
||||
"CF",
|
||||
"SR",
|
||||
"TA",
|
||||
"OI",
|
||||
"RI",
|
||||
"MA",
|
||||
"ME",
|
||||
"FG",
|
||||
"RS",
|
||||
"RM",
|
||||
"ZC",
|
||||
"JR",
|
||||
"LR",
|
||||
"SF",
|
||||
"SM",
|
||||
"WT",
|
||||
"TC",
|
||||
"GN",
|
||||
"RO",
|
||||
"ER",
|
||||
"SRX",
|
||||
"SRY",
|
||||
"WSX",
|
||||
"WSY",
|
||||
"CY",
|
||||
"AP",
|
||||
"UR",
|
||||
"CJ", # 红枣期货
|
||||
"SA", # 纯碱期货
|
||||
"PK", # 20210201 花生期货
|
||||
"PF", # 短纤
|
||||
"PX", # 对二甲苯
|
||||
"SH", # 烧碱
|
||||
"PR", # 瓶片
|
||||
"PL", # 丙烯
|
||||
],
|
||||
"shfe": [
|
||||
"CU",
|
||||
"AL",
|
||||
"ZN",
|
||||
"PB",
|
||||
"NI",
|
||||
"SN",
|
||||
"AU",
|
||||
"AG",
|
||||
"RB",
|
||||
"WR",
|
||||
"HC",
|
||||
"FU",
|
||||
"BU",
|
||||
"RU",
|
||||
"SC",
|
||||
"NR",
|
||||
"SP",
|
||||
"SS",
|
||||
"LU",
|
||||
"BC",
|
||||
"AO",
|
||||
"BR",
|
||||
"EC", # 集运指数
|
||||
"AD", # 铸造铝合金期货
|
||||
"OP", # 胶版印刷纸期货
|
||||
],
|
||||
"gfex": ["SI", "LC", "PS"],
|
||||
}
|
||||
|
||||
contract_symbols = []
|
||||
[contract_symbols.extend(i) for i in market_exchange_symbols.values()]
|
||||
|
||||
headers = {
|
||||
"Host": "www.czce.com.cn",
|
||||
"Connection": "keep-alive",
|
||||
"Cache-Control": "max-age=0",
|
||||
"Accept": "text/html, */*; q=0.01",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/56.0.2924.87 Safari/537.36",
|
||||
"DNT": "1",
|
||||
"Referer": "http://www.super-ping.com/?ping=www.google.com&locale=sc",
|
||||
"Accept-Encoding": "gzip, deflate, sdch",
|
||||
"Accept-Language": "zh-CN,zh;q=0.8,ja;q=0.6",
|
||||
}
|
||||
|
||||
shfe_headers = {"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"}
|
||||
|
||||
dce_headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,"
|
||||
"*/*;q=0.8,application/signed-exchange;v=b3",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Cache-Control": "max-age=0",
|
||||
"Content-Length": "71",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Host": "www.dce.com.cn",
|
||||
"Origin": "http://www.dce.com.cn",
|
||||
"Proxy-Connection": "keep-alive",
|
||||
"Referer": "http://www.dce.com.cn/publicweb/quotesdata/weekQuotesCh.html",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/77.0.3865.90 Safari/537.36",
|
||||
}
|
||||
|
||||
SYS_SPOT_PRICE_URL = "http://www.100ppi.com/sf/day-{}.html"
|
||||
SYS_SPOT_PRICE_LATEST_URL = "http://www.100ppi.com/sf/"
|
||||
|
||||
SHFE_VOL_RANK_URL = "https://tsite.shfe.com.cn/data/dailydata/kx/pm%s.dat"
|
||||
SHFE_VOL_RANK_URL_20250701 = (
|
||||
"https://www.shfe.com.cn/data/tradedata/future/dailydata/pm%s.dat"
|
||||
)
|
||||
CFFEX_VOL_RANK_URL = "http://www.cffex.com.cn/sj/ccpm/%s/%s/%s_1.csv"
|
||||
DCE_VOL_RANK_URL_1 = (
|
||||
"http://portal.dce.com.cn/publicweb/quotesdata/exportMemberDealPosiQuotesData.html?"
|
||||
"memberDealPosiQuotes.variety=%s&memberDealPosiQuotes.trade_type=0&contract.cont"
|
||||
"ract_id=%s&contract.variety_id=%s&year=%s&month=%s&day=%s&exportFlag=txt"
|
||||
)
|
||||
DCE_VOL_RANK_URL_2 = (
|
||||
"http://portal.dce.com.cn/publicweb/quotesdata/memberDealPosiQuotes.html?memberDeal"
|
||||
"PosiQuotes.variety=%s&memberDealPosiQuotes.trade_type=0&contract.contract_id="
|
||||
"all&contract.variety_id=%s&year=%s&month=%s&day=%s"
|
||||
)
|
||||
CZCE_VOL_RANK_URL_1 = "http://www.czce.com.cn/cn/exchange/jyxx/pm/pm%s.html"
|
||||
CZCE_VOL_RANK_URL_2 = "http://www.czce.com.cn/cn/exchange/%s/datatradeholding/%s.htm"
|
||||
CZCE_VOL_RANK_URL_3 = (
|
||||
"http://www.czce.com.cn/cn/DFSStaticFiles/Future/%s/%s/FutureDataHolding.htm"
|
||||
)
|
||||
|
||||
DCE_RECEIPT_URL = "http://portal.dce.com.cn/publicweb/quotesdata/wbillWeeklyQuotes.html"
|
||||
|
||||
SHFE_RECEIPT_URL_1 = "http://tsite.shfe.com.cn/data/dailydata/%sdailystock.html"
|
||||
SHFE_RECEIPT_URL_2 = "http://tsite.shfe.com.cn/data/dailydata/%sdailystock.dat"
|
||||
SHFE_RECEIPT_URL_20250701 = (
|
||||
"https://www.shfe.com.cn/data/tradedata/future/dailydata/%sdailystock.dat"
|
||||
)
|
||||
CZCE_RECEIPT_URL_1 = "http://www.czce.com.cn/cn/exchange/jyxx/sheet/sheet%s.html"
|
||||
CZCE_RECEIPT_URL_2 = "http://www.czce.com.cn/cn/exchange/%s/datawhsheet/%s.htm"
|
||||
CZCE_RECEIPT_URL_3 = (
|
||||
"http://www.czce.com.cn/cn/DFSStaticFiles/Future/%s/%s/FutureDataWhsheet.htm"
|
||||
)
|
||||
|
||||
CFFEX_DAILY_URL = "http://www.cffex.com.cn/fzjy/mrhq/{}/{}/{}_1.csv"
|
||||
SHFE_DAILY_URL = "http://tsite.shfe.com.cn/data/dailydata/kx/kx%s.dat"
|
||||
SHFE_DAILY_URL_20250630 = (
|
||||
"https://www.shfe.com.cn/data/tradedata/future/dailydata/kx%s.dat"
|
||||
)
|
||||
SHFE_V_WAP_URL = "http://tsite.shfe.com.cn/data/dailydata/ck/%sdailyTimePrice.dat"
|
||||
DCE_DAILY_URL = "http://www.dce.com.cn//publicweb/quotesdata/dayQuotesCh.html"
|
||||
CZCE_DAILY_URL_1 = "http://www.czce.com.cn/cn/exchange/jyxx/hq/hq%s.html"
|
||||
CZCE_DAILY_URL_2 = "http://www.czce.com.cn/cn/exchange/%s/datadaily/%s.txt"
|
||||
CZCE_DAILY_URL_3 = (
|
||||
"http://www.czce.com.cn/cn/DFSStaticFiles/Future/%s/%s/FutureDataDaily.txt"
|
||||
)
|
||||
|
||||
DATE_PATTERN = re.compile(r"^([0-9]{4})[-/]?([0-9]{2})[-/]?([0-9]{2})")
|
||||
FUTURES_SYMBOL_PATTERN = re.compile(r"(^[A-Za-z]{1,2})[0-9]+")
|
||||
|
||||
CFFEX_COLUMNS = [
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"volume",
|
||||
"turnover",
|
||||
"open_interest",
|
||||
"close",
|
||||
"settle",
|
||||
"change1",
|
||||
"change2",
|
||||
]
|
||||
|
||||
CZCE_COLUMNS = [
|
||||
"pre_settle",
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"settle",
|
||||
"change1",
|
||||
"change2",
|
||||
"volume",
|
||||
"open_interest",
|
||||
"oi_chg",
|
||||
"turnover",
|
||||
"final_settle",
|
||||
]
|
||||
|
||||
CZCE_COLUMNS_2 = [
|
||||
"pre_settle",
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"settle",
|
||||
"change1",
|
||||
"volume",
|
||||
"open_interest",
|
||||
"oi_chg",
|
||||
"turnover",
|
||||
"final_settle",
|
||||
]
|
||||
|
||||
SHFE_COLUMNS = {
|
||||
"CLOSEPRICE": "close",
|
||||
"HIGHESTPRICE": "high",
|
||||
"LOWESTPRICE": "low",
|
||||
"OPENINTEREST": "open_interest",
|
||||
"OPENPRICE": "open",
|
||||
"PRESETTLEMENTPRICE": "pre_settle",
|
||||
"SETTLEMENTPRICE": "settle",
|
||||
"VOLUME": "volume",
|
||||
}
|
||||
|
||||
SHFE_V_WAP_COLUMNS = {
|
||||
":B1": "date",
|
||||
"INSTRUMENT_ID": "symbol",
|
||||
"TIME": "time_range",
|
||||
"REF_SETTLEMENT_PRICE": "v_wap",
|
||||
}
|
||||
|
||||
DCE_COLUMNS = [
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"pre_settle",
|
||||
"settle",
|
||||
"change1",
|
||||
"change2",
|
||||
"volume",
|
||||
"open_interest",
|
||||
"oi_chg",
|
||||
"turnover",
|
||||
]
|
||||
|
||||
DCE_OPTION_COLUMNS = [
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"pre_settle",
|
||||
"settle",
|
||||
"change1",
|
||||
"change2",
|
||||
"delta",
|
||||
"volume",
|
||||
"open_interest",
|
||||
"oi_chg",
|
||||
"turnover",
|
||||
"exercise_volume",
|
||||
]
|
||||
|
||||
OUTPUT_COLUMNS = [
|
||||
"symbol",
|
||||
"date",
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"volume",
|
||||
"open_interest",
|
||||
"turnover",
|
||||
"settle",
|
||||
"pre_settle",
|
||||
"variety",
|
||||
]
|
||||
|
||||
OPTION_OUTPUT_COLUMNS = [
|
||||
"symbol",
|
||||
"date",
|
||||
"open",
|
||||
"high",
|
||||
"low",
|
||||
"close",
|
||||
"pre_settle",
|
||||
"settle",
|
||||
"delta",
|
||||
"volume",
|
||||
"open_interest",
|
||||
"oi_chg",
|
||||
"turnover",
|
||||
"implied_volatility",
|
||||
"exercise_volume",
|
||||
"variety",
|
||||
]
|
||||
|
||||
DCE_MAP = {
|
||||
"大豆": "A",
|
||||
"豆一": "A",
|
||||
"豆二": "B",
|
||||
"豆粕": "M",
|
||||
"豆油": "Y",
|
||||
"棕榈油": "P",
|
||||
"玉米": "C",
|
||||
"玉米淀粉": "CS",
|
||||
"鸡蛋": "JD",
|
||||
"纤维板": "FB",
|
||||
"胶合板": "BB",
|
||||
"聚乙烯": "L",
|
||||
"聚氯乙烯": "V",
|
||||
"聚丙烯": "PP",
|
||||
"焦炭": "J",
|
||||
"焦煤": "JM",
|
||||
"铁矿石": "I",
|
||||
"乙二醇": "EG",
|
||||
"粳米": "RR",
|
||||
"苯乙烯": "EB",
|
||||
"液化石油气": "PG",
|
||||
"生猪": "LH",
|
||||
"原木": "LG",
|
||||
"纯苯": "BZ",
|
||||
"聚氯乙烯月均价": "VF",
|
||||
"聚丙烯月均价": "PPF",
|
||||
"聚乙烯月均价": "LF",
|
||||
}
|
||||
|
||||
|
||||
def convert_date(date):
|
||||
"""
|
||||
transform a date string to datetime.date object
|
||||
:param date, string, e.g. 2016-01-01, 20160101 or 2016/01/01
|
||||
:return: object of datetime.date(such as 2016-01-01) or None
|
||||
"""
|
||||
if isinstance(date, datetime.date):
|
||||
return date
|
||||
elif isinstance(date, str):
|
||||
match = DATE_PATTERN.match(date)
|
||||
if match:
|
||||
groups = match.groups()
|
||||
if len(groups) == 3:
|
||||
return datetime.date(
|
||||
year=int(groups[0]),
|
||||
month=int(groups[1]),
|
||||
day=int(groups[2]),
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def get_json_path(name, module_file):
|
||||
"""
|
||||
获取 JSON 配置文件的路径(从模块所在目录查找)
|
||||
:param name: 文件名
|
||||
:param module_file: filename
|
||||
:return: str json_file_path
|
||||
"""
|
||||
module_folder = os.path.abspath(os.path.dirname(os.path.dirname(module_file)))
|
||||
module_json_path = os.path.join(module_folder, "file_fold", name)
|
||||
return module_json_path
|
||||
|
||||
|
||||
def get_pk_path(name, module_file):
|
||||
"""
|
||||
获取 pickle 配置文件的路径(从模块所在目录查找)
|
||||
:param name: 文件名
|
||||
:param module_file: filename
|
||||
:return: str json_file_path
|
||||
"""
|
||||
module_folder = os.path.abspath(os.path.dirname(os.path.dirname(module_file)))
|
||||
module_json_path = os.path.join(module_folder, "file_fold", name)
|
||||
return module_json_path
|
||||
|
||||
|
||||
def get_pk_data(file_name):
|
||||
"""
|
||||
获取交易日历至 2019 年结束, 这里的交易日历需要按年更新
|
||||
:return: json
|
||||
"""
|
||||
setting_file_name = file_name
|
||||
setting_file_path = get_pk_path(setting_file_name, __file__)
|
||||
return pickle.load(open(setting_file_path, "rb"))
|
||||
|
||||
|
||||
def get_calendar():
|
||||
"""
|
||||
获取交易日历, 这里的交易日历需要按年更新, 主要是从新浪获取的
|
||||
:return: 交易日历
|
||||
:rtype: json
|
||||
"""
|
||||
setting_file_name = "calendar.json"
|
||||
setting_file_path = get_json_path(setting_file_name, __file__)
|
||||
with open(setting_file_path, "r", encoding="utf-8") as f:
|
||||
data_json = json.load(f)
|
||||
return data_json
|
||||
|
||||
|
||||
def last_trading_day(day):
|
||||
"""
|
||||
获取前一个交易日
|
||||
:param day: "%Y%m%d" or datetime.date()
|
||||
:return last_day: "%Y%m%d" or datetime.date()
|
||||
"""
|
||||
calendar = get_calendar()
|
||||
|
||||
if isinstance(day, str):
|
||||
if day not in calendar:
|
||||
print("Today is not trading day:" + day)
|
||||
return False
|
||||
pos = calendar.index(day)
|
||||
last_day = calendar[pos - 1]
|
||||
return last_day
|
||||
|
||||
elif isinstance(day, datetime.date):
|
||||
d_str = day.strftime("%Y%m%d")
|
||||
if d_str not in calendar:
|
||||
print("Today is not working day:" + d_str)
|
||||
return False
|
||||
pos = calendar.index(d_str)
|
||||
last_day = calendar[pos - 1]
|
||||
last_day = datetime.datetime.strptime(last_day, "%Y%m%d").date()
|
||||
return last_day
|
||||
|
||||
|
||||
def get_latest_data_date(day):
|
||||
"""
|
||||
获取最新的有数据的交易日
|
||||
:param day: datetime.datetime
|
||||
:return string YYYYMMDD
|
||||
"""
|
||||
calendar = get_calendar()
|
||||
if day.strftime("%Y%m%d") in calendar:
|
||||
if day.time() > datetime.time(17, 0, 0):
|
||||
return day.strftime("%Y%m%d")
|
||||
else:
|
||||
return last_trading_day(day.strftime("%Y%m%d"))
|
||||
else:
|
||||
while day.strftime("%Y%m%d") not in calendar:
|
||||
day = day - datetime.timedelta(days=1)
|
||||
return day.strftime("%Y%m%d")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
d = datetime.datetime(2018, 10, 5, 17, 1, 0)
|
||||
print(get_latest_data_date(d))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,386 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/12/12 17:00
|
||||
Desc: 生意社网站采集大宗商品现货价格及相应基差数据, 数据时间段从 20110104-至今
|
||||
备注:现期差 = 现货价格 - 期货价格(这里的期货价格为结算价)
|
||||
黄金为 元/克, 白银为 元/千克, 玻璃现货为 元/平方米, 鸡蛋现货为 元/公斤, 鸡蛋期货为 元/500千克, 其余为 元/吨.
|
||||
焦炭现货规格是: 一级冶金焦; 焦炭期货规格: 介于一级和二级之间, 焦炭现期差仅供参考.
|
||||
铁矿石现货价格是: 湿吨, 铁矿石期货价格是: 干吨
|
||||
网页地址: https://www.100ppi.com/sf/
|
||||
历史数据可以通过修改 url 地址来获取, 比如: https://www.100ppi.com/sf/day-2017-09-12.html
|
||||
发现生意社的 bugs:
|
||||
1. 2018-09-12 周三 数据缺失是因为生意社源数据在该交易日缺失: https://www.100ppi.com/sf/day-2018-09-12.html
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import re
|
||||
import time
|
||||
import warnings
|
||||
from typing import List
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from akshare.futures import cons
|
||||
from akshare.futures.requests_fun import pandas_read_html_link
|
||||
from akshare.futures.symbol_var import chinese_to_english
|
||||
|
||||
calendar = cons.get_calendar()
|
||||
|
||||
|
||||
def futures_spot_price_daily(
|
||||
start_day: str = "20210201",
|
||||
end_day: str = "20210208",
|
||||
vars_list: list = cons.contract_symbols,
|
||||
):
|
||||
"""
|
||||
指定时间段内大宗商品现货价格及相应基差
|
||||
https://www.100ppi.com/sf/
|
||||
:param start_day: str 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象; 默认为当天
|
||||
:param end_day: str 结束数据 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象; 默认为当天
|
||||
:param vars_list: list 合约品种如 [RB, AL]; 默认参数为所有商品
|
||||
:return: 基差
|
||||
:rtype: pandas.DataFrame
|
||||
展期收益率数据:
|
||||
var 商品品种 string
|
||||
sp 现货价格 float
|
||||
near_symbol 临近交割合约 string
|
||||
near_price 临近交割合约结算价 float
|
||||
dom_symbol 主力合约 string
|
||||
dom_price 主力合约结算价 float
|
||||
near_basis 临近交割合约相对现货的基差 float
|
||||
dom_basis 主力合约相对现货的基差 float
|
||||
near_basis_rate 临近交割合约相对现货的基差率 float
|
||||
dom_basis_rate 主力合约相对现货的基差率 float
|
||||
date 日期 string YYYYMMDD
|
||||
"""
|
||||
start_day = (
|
||||
cons.convert_date(start_day) if start_day is not None else datetime.date.today()
|
||||
)
|
||||
end_day = (
|
||||
cons.convert_date(end_day)
|
||||
if end_day is not None
|
||||
else cons.convert_date(cons.get_latest_data_date(datetime.datetime.now()))
|
||||
)
|
||||
df_list = []
|
||||
while start_day <= end_day:
|
||||
temp_df = futures_spot_price(start_day, vars_list)
|
||||
if temp_df is False:
|
||||
return pd.concat(df_list).reset_index(drop=True)
|
||||
elif temp_df is not None:
|
||||
df_list.append(temp_df)
|
||||
start_day += datetime.timedelta(days=1)
|
||||
if len(df_list) > 0:
|
||||
temp_df = pd.concat(df_list)
|
||||
temp_df.reset_index(drop=True, inplace=True)
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_spot_price(
|
||||
date: str = "20240430", vars_list: list = cons.contract_symbols
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
指定交易日大宗商品现货价格及相应基差
|
||||
https://www.100ppi.com/sf/day-2017-09-12.html
|
||||
:param date: 开始日期 format: YYYY-MM-DD 或 YYYYMMDD 或 datetime.date 对象; 为空时为当天
|
||||
:param vars_list: 合约品种如 RB、AL 等列表 为空时为所有商品
|
||||
:return: pandas.DataFrame
|
||||
展期收益率数据:
|
||||
var 商品品种 string
|
||||
sp 现货价格 float
|
||||
near_symbol 临近交割合约 string
|
||||
near_price 临近交割合约结算价 float
|
||||
dom_symbol 主力合约 string
|
||||
dom_price 主力合约结算价 float
|
||||
near_basis 临近交割合约相对现货的基差 float
|
||||
dom_basis 主力合约相对现货的基差 float
|
||||
near_basis_rate 临近交割合约相对现货的基差率 float
|
||||
dom_basis_rate 主力合约相对现货的基差率 float
|
||||
date 日期 string YYYYMMDD
|
||||
"""
|
||||
date = cons.convert_date(date) if date is not None else datetime.date.today()
|
||||
if date < datetime.date(2011, 1, 4):
|
||||
raise Exception(
|
||||
"数据源开始日期为 20110104, 请将获取数据时间点设置在 20110104 后"
|
||||
)
|
||||
if date.strftime("%Y%m%d") not in calendar:
|
||||
warnings.warn(f"{date.strftime('%Y%m%d')}非交易日")
|
||||
return pd.DataFrame()
|
||||
u1 = "https://www.100ppi.com/sf/"
|
||||
u2 = f"https://www.100ppi.com/sf/day-{date.strftime('%Y-%m-%d')}.html"
|
||||
i = 1
|
||||
while True:
|
||||
for url in [u2, u1]:
|
||||
try:
|
||||
# url = u2
|
||||
headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
|
||||
"image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
|
||||
}
|
||||
r = pandas_read_html_link(url, headers=headers)
|
||||
string = r[0].loc[1, 1]
|
||||
news = "".join(re.findall(r"[0-9]", string))
|
||||
if news[3:11] == date.strftime("%Y%m%d"):
|
||||
records = _check_information(r[1], date)
|
||||
records.index = records["symbol"]
|
||||
var_list_in_market = [i for i in vars_list if i in records.index]
|
||||
temp_df = records.loc[var_list_in_market, :]
|
||||
temp_df.reset_index(drop=True, inplace=True)
|
||||
return temp_df
|
||||
else:
|
||||
time.sleep(3)
|
||||
except Exception as e: # noqa: E722
|
||||
print(
|
||||
f"{date.strftime('%Y-%m-%d')}日生意社数据连接失败[错误信息:{e}],第{str(i)}次尝试,最多5次"
|
||||
)
|
||||
i += 1
|
||||
if i > 5:
|
||||
print(
|
||||
f"{date.strftime('%Y-%m-%d')}日生意社数据连接失败, 如果当前交易日是 2018-09-12, "
|
||||
f"由于生意社源数据缺失, 无法访问, 否则为重复访问已超过5次,您的地址被网站墙了,"
|
||||
f"请保存好返回数据,稍后从该日期起重试"
|
||||
)
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
def _check_information(df_data, date):
|
||||
"""
|
||||
数据验证和计算模块
|
||||
:param df_data: pandas.DataFrame 采集的数据
|
||||
:param date: datetime.date 具体某一天 YYYYMMDD
|
||||
:return: pandas.DataFrame
|
||||
中间数据
|
||||
symbol spot_price near_contract ... near_basis_rate dom_basis_rate date
|
||||
CU 49620.00 cu1811 ... -0.002418 -0.003426 20181108
|
||||
RB 4551.54 rb1811 ... -0.013521 -0.134359 20181108
|
||||
ZN 22420.00 zn1811 ... -0.032114 -0.076271 20181108
|
||||
AL 13900.00 al1812 ... 0.005396 0.003957 20181108
|
||||
AU 274.10 au1811 ... 0.005655 0.020430 20181108
|
||||
WR 4806.25 wr1903 ... -0.180026 -0.237035 20181108
|
||||
RU 10438.89 ru1811 ... -0.020969 0.084406 20181108
|
||||
PB 18600.00 pb1811 ... -0.001344 -0.010215 20181108
|
||||
AG 3542.67 ag1811 ... -0.000754 0.009408 20181108
|
||||
BU 4045.53 bu1811 ... -0.129904 -0.149679 20181108
|
||||
HC 4043.33 hc1811 ... -0.035449 -0.088128 20...
|
||||
"""
|
||||
df_data = df_data.loc[:, [0, 1, 2, 3, 5, 6]]
|
||||
df_data.columns = [
|
||||
"symbol",
|
||||
"spot_price",
|
||||
"near_contract",
|
||||
"near_contract_price",
|
||||
"dominant_contract",
|
||||
"dominant_contract_price",
|
||||
]
|
||||
records = pd.DataFrame()
|
||||
for string in df_data["symbol"].tolist():
|
||||
news = "".join(re.findall(r"[\u4e00-\u9fa5]", string))
|
||||
if news == "":
|
||||
news = string.strip()
|
||||
|
||||
"""
|
||||
if string == "PTA":
|
||||
news = "PTA"
|
||||
else:
|
||||
news = "".join(re.findall(r"[\u4e00-\u9fa5]", string))
|
||||
"""
|
||||
|
||||
if news != "" and news not in [
|
||||
"商品",
|
||||
"价格",
|
||||
"上海期货交易所",
|
||||
"郑州商品交易所",
|
||||
"大连商品交易所",
|
||||
"广州期货交易所",
|
||||
# 某些天网站没有数据,比如 20180912,此时返回"暂无数据",但并不是网站被墙了
|
||||
"暂无数据",
|
||||
]:
|
||||
symbol = chinese_to_english(news)
|
||||
record = pd.DataFrame(df_data[df_data["symbol"] == string])
|
||||
record.loc[:, "symbol"] = symbol
|
||||
record["spot_price"] = record["spot_price"].astype(float)
|
||||
if (
|
||||
symbol == "JD"
|
||||
): # 鸡蛋现货为元/公斤, 鸡蛋期货为元/500千克, 其余元/吨(http://www.100ppi.com/sf/)
|
||||
record.loc[:, "spot_price"] = float(record["spot_price"].iloc[0]) * 500
|
||||
elif (
|
||||
symbol == "FG"
|
||||
): # 上表中现货单位为元/平方米, 期货单位为元/吨. 换算公式:元/平方米*80=元/吨(http://www.100ppi.com/sf/959.html)
|
||||
record.loc[:, "spot_price"] = float(record["spot_price"].iloc[0]) * 80
|
||||
elif (
|
||||
symbol == "LH"
|
||||
): # 上表中现货单位为元/公斤, 期货单位为元/吨. 换算公式:元/公斤*1000=元/吨(http://www.100ppi.com/sf/959.html)
|
||||
record.loc[:, "spot_price"] = float(record["spot_price"].iloc[0]) * 1000
|
||||
records = pd.concat([records, record])
|
||||
|
||||
# 20241129:如果某日没有数据,直接返回返回空表
|
||||
if records.empty:
|
||||
records = df_data.iloc[0:0]
|
||||
records["near_basis"] = pd.Series(dtype="float")
|
||||
records["dom_basis"] = pd.Series(dtype="float")
|
||||
records["near_basis_rate"] = pd.Series(dtype="float")
|
||||
records["dom_basis_rate"] = pd.Series(dtype="float")
|
||||
records["date"] = pd.Series(dtype="object")
|
||||
return records
|
||||
|
||||
records[["near_contract_price", "dominant_contract_price", "spot_price"]] = (
|
||||
records[["near_contract_price", "dominant_contract_price", "spot_price"]
|
||||
].astype("float")
|
||||
)
|
||||
|
||||
records["near_contract"] = records["near_contract"].replace(
|
||||
r"[^0-9]*(\d*)$", r"\g<1>", regex=True
|
||||
)
|
||||
records["dominant_contract"] = records["dominant_contract"].replace(
|
||||
r"[^0-9]*(\d*)$", r"\g<1>", regex=True
|
||||
)
|
||||
|
||||
records["near_month"] = records.loc[:, "near_contract"]
|
||||
records["near_contract"] = records["symbol"] + records.loc[
|
||||
:, "near_contract"
|
||||
].astype("int").astype("str")
|
||||
records["dominant_month"] = records.loc[:, "dominant_contract"]
|
||||
records["dominant_contract"] = records["symbol"] + records.loc[
|
||||
:, "dominant_contract"
|
||||
].astype("int").astype("str")
|
||||
|
||||
records["near_contract"] = records["near_contract"].apply(
|
||||
lambda x: (
|
||||
x.lower()
|
||||
if x[:-4]
|
||||
in cons.market_exchange_symbols["shfe"]
|
||||
+ cons.market_exchange_symbols["dce"]
|
||||
else x
|
||||
)
|
||||
)
|
||||
records["dominant_contract"] = records["dominant_contract"].apply(
|
||||
lambda x: (
|
||||
x.lower()
|
||||
if x[:-4]
|
||||
in cons.market_exchange_symbols["shfe"]
|
||||
+ cons.market_exchange_symbols["dce"]
|
||||
else x
|
||||
)
|
||||
)
|
||||
records["near_contract"] = records["near_contract"].apply(
|
||||
lambda x: (
|
||||
x[:-4] + x[-3:] if x[:-4] in cons.market_exchange_symbols["czce"] else x
|
||||
)
|
||||
)
|
||||
records["dominant_contract"] = records["dominant_contract"].apply(
|
||||
lambda x: (
|
||||
x[:-4] + x[-3:] if x[:-4] in cons.market_exchange_symbols["czce"] else x
|
||||
)
|
||||
)
|
||||
|
||||
records["near_basis"] = records["near_contract_price"] - records["spot_price"]
|
||||
records["dom_basis"] = records["dominant_contract_price"] - records["spot_price"]
|
||||
records["near_basis_rate"] = (
|
||||
records["near_contract_price"] / records["spot_price"] - 1
|
||||
)
|
||||
records["dom_basis_rate"] = (
|
||||
records["dominant_contract_price"] / records["spot_price"] - 1
|
||||
)
|
||||
# records.loc[:, "date"] = date.strftime("%Y%m%d")
|
||||
records.insert(0, "date", date.strftime("%Y%m%d"))
|
||||
records.reset_index(inplace=True, drop=True)
|
||||
return records
|
||||
|
||||
|
||||
def _join_head(content: pd.DataFrame) -> List:
|
||||
headers = []
|
||||
for s1, s2 in zip(content.iloc[0], content.iloc[1]):
|
||||
if s1 != s2:
|
||||
s = f"{s1}{s2}"
|
||||
else:
|
||||
s = s1
|
||||
headers.append(s)
|
||||
return headers
|
||||
|
||||
|
||||
def futures_spot_price_previous(date: str = "20240430") -> pd.DataFrame:
|
||||
"""
|
||||
具体交易日大宗商品现货价格及相应基差
|
||||
https://www.100ppi.com/sf/day-2017-09-12.html
|
||||
:param date: 交易日; 历史日期
|
||||
:type date: str
|
||||
:return: 现货价格及相应基差
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
date = cons.convert_date(date) if date is not None else datetime.date.today()
|
||||
if date < datetime.date(2011, 1, 4):
|
||||
raise Exception(
|
||||
"数据源开始日期为 20110104, 请将获取数据时间点设置在 20110104 后"
|
||||
)
|
||||
if date.strftime("%Y%m%d") not in calendar:
|
||||
warnings.warn(f"{date.strftime('%Y%m%d')}非交易日")
|
||||
return pd.DataFrame()
|
||||
url = date.strftime("https://www.100ppi.com/sf2/day-%Y-%m-%d.html")
|
||||
headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,"
|
||||
"image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
|
||||
}
|
||||
content = pandas_read_html_link(url, headers=headers)
|
||||
main = content[1]
|
||||
# Header
|
||||
header = _join_head(main)
|
||||
# Values
|
||||
values = main[main[4].str.endswith("%")]
|
||||
values.columns = header
|
||||
# Basis
|
||||
# 对于没有数据的天,xml文件中没有数据,所以content[2:-1]可能为空
|
||||
if len(content[2:-1]) > 0:
|
||||
basis = pd.concat(content[2:-1])
|
||||
else:
|
||||
basis = pd.DataFrame(columns=["主力合约基差", "主力合约基差(%)"])
|
||||
|
||||
basis.columns = ["主力合约基差", "主力合约基差(%)"]
|
||||
# 20241125(jasonudu):因为部分日期,存在多个品种的现货价格,比如20151125的白糖、豆粕、豆油等,
|
||||
# 如果用商品名来merge,会出现重复列名,所以改用index来merge
|
||||
# basis["商品"] = values["商品"].tolist()
|
||||
basis.index = values.index
|
||||
basis = pd.merge(
|
||||
values[["商品", "现货价格", "主力合约代码", "主力合约价格"]],
|
||||
basis,
|
||||
left_index=True,
|
||||
right_index=True,
|
||||
)
|
||||
basis = pd.merge(
|
||||
basis,
|
||||
values[
|
||||
[
|
||||
"180日内主力基差最高",
|
||||
"180日内主力基差最低",
|
||||
"180日内主力基差平均",
|
||||
]
|
||||
],
|
||||
left_index=True,
|
||||
right_index=True,
|
||||
)
|
||||
basis.columns = [
|
||||
"商品",
|
||||
"现货价格",
|
||||
"主力合约代码",
|
||||
"主力合约价格",
|
||||
"主力合约基差",
|
||||
"主力合约变动百分比",
|
||||
"180日内主力基差最高",
|
||||
"180日内主力基差最低",
|
||||
"180日内主力基差平均",
|
||||
]
|
||||
basis["主力合约变动百分比"] = basis["主力合约变动百分比"].str.strip("%")
|
||||
basis.reset_index(inplace=True, drop=True)
|
||||
return basis
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_spot_price_daily_df = futures_spot_price_daily(
|
||||
start_day="20260303", end_day="20260303", vars_list=['PL']
|
||||
)
|
||||
print(futures_spot_price_daily_df)
|
||||
|
||||
futures_spot_price_df = futures_spot_price(date="20260303")
|
||||
print(futures_spot_price_df)
|
||||
|
||||
futures_spot_price_previous_df = futures_spot_price_previous(date="20240430")
|
||||
print(futures_spot_price_previous_df)
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2023/11/15 18:00
|
||||
Desc: 东方财富网-数据中心-期货期权-COMEX库存数据
|
||||
https://data.eastmoney.com/pmetal/comex/by.html
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
from akshare.utils.tqdm import get_tqdm
|
||||
|
||||
|
||||
def futures_comex_inventory(symbol: str = "黄金") -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-数据中心-期货期权-COMEX库存数据
|
||||
https://data.eastmoney.com/pmetal/comex/by.html
|
||||
:param symbol: choice of {"黄金", "白银"}
|
||||
:type symbol: str
|
||||
:return: COMEX库存数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
symbol_map = {
|
||||
"黄金": "EMI00069026",
|
||||
"白银": "EMI00069027",
|
||||
}
|
||||
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
|
||||
params = {
|
||||
"sortColumns": "REPORT_DATE",
|
||||
"sortTypes": "-1",
|
||||
"pageSize": "500",
|
||||
"pageNumber": "1",
|
||||
"reportName": "RPT_FUTUOPT_GOLDSIL",
|
||||
"columns": "ALL",
|
||||
"quoteColumns": "",
|
||||
"source": "WEB",
|
||||
"client": "WEB",
|
||||
"filter": f'(INDICATOR_ID1="{symbol_map[symbol]}")(@STORAGE_TON<>"NULL")',
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
total_page = data_json["result"]["pages"]
|
||||
big_df = pd.DataFrame()
|
||||
tqdm = get_tqdm()
|
||||
for page in tqdm(range(1, total_page + 1), leave=False):
|
||||
params.update(
|
||||
{
|
||||
"pageNumber": page,
|
||||
}
|
||||
)
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["result"]["data"])
|
||||
big_df = pd.concat(objs=[big_df, temp_df], axis=0, ignore_index=True)
|
||||
|
||||
big_df.reset_index(inplace=True)
|
||||
big_df["index"] = big_df["index"] + 1
|
||||
big_df.rename(
|
||||
columns={
|
||||
"index": "序号",
|
||||
"REPORT_DATE": "日期",
|
||||
"INDICATOR_NAME": "-",
|
||||
"INDICATOR_ID1": "-",
|
||||
"STORAGE_TON": f"COMEX{symbol}库存量-吨",
|
||||
"STORAGE_OUNCE": f"COMEX{symbol}库存量-盎司",
|
||||
"INDICATOR_ID2": "-",
|
||||
"NETPOSITION_TON": "-",
|
||||
"NETPOSITION_OUNCE": "-",
|
||||
"NETPOSITION_DOLLAR": "-",
|
||||
"INDICATOR_ID3": "-",
|
||||
"OPENPOSI_STOCK": "-",
|
||||
"OPENPOSTOCK_WECHANGE": "-",
|
||||
"OPENPOSI_STOCK_SUM": "-",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
big_df = big_df[
|
||||
[
|
||||
"序号",
|
||||
"日期",
|
||||
f"COMEX{symbol}库存量-吨",
|
||||
f"COMEX{symbol}库存量-盎司",
|
||||
]
|
||||
]
|
||||
big_df[f"COMEX{symbol}库存量-吨"] = pd.to_numeric(
|
||||
big_df[f"COMEX{symbol}库存量-吨"], errors="coerce"
|
||||
)
|
||||
big_df[f"COMEX{symbol}库存量-盎司"] = pd.to_numeric(
|
||||
big_df[f"COMEX{symbol}库存量-盎司"], errors="coerce"
|
||||
)
|
||||
big_df["日期"] = pd.to_datetime(big_df["日期"], errors="coerce").dt.date
|
||||
big_df.sort_values(["日期"], inplace=True, ignore_index=True)
|
||||
big_df["序号"] = range(1, len(big_df) + 1)
|
||||
return big_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_comex_inventory_df = futures_comex_inventory(symbol="黄金")
|
||||
print(futures_comex_inventory_df)
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/7/6 18:00
|
||||
Desc: openctp 期货交易费用参照表
|
||||
http://openctp.cn/fees.html
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
def futures_fees_info() -> pd.DataFrame:
|
||||
"""
|
||||
openctp 期货交易费用参照表
|
||||
http://openctp.cn/fees.html
|
||||
:return: 期货交易费用参照表
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "http://openctp.cn/fees.html"
|
||||
r = requests.get(url)
|
||||
r.encoding = "utf-8"
|
||||
soup = BeautifulSoup(r.text, features="lxml")
|
||||
datetime_str = soup.find("p").string.strip("Generated at ").strip(".")
|
||||
datetime_raw = datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
|
||||
temp_df = pd.read_html(StringIO(r.text))[0]
|
||||
temp_df["更新时间"] = datetime_raw.strftime("%Y-%m-%d %H:%M:%S")
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_fees_info_df = futures_fees_info()
|
||||
print(futures_fees_info_df)
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2026/2/22 15:45
|
||||
Desc: 金十数据-期货手续费
|
||||
https://www.jin10.com/
|
||||
"""
|
||||
import json
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_comm_js(date: str = "20260213") -> pd.DataFrame:
|
||||
"""
|
||||
金十财经-期货手续费
|
||||
https://www.jin10.com/
|
||||
:param date: 日期; 格式为 YYYYMMDD,例如 "20250213"
|
||||
:type date: str
|
||||
:return: 期货手续费数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
headers = {
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/107.0.0.0 Safari/537.36",
|
||||
"x-app-id": "fiXF2nOnDycGutVA",
|
||||
"x-version": "1.0",
|
||||
"referer": "https://www.jin10.com/",
|
||||
"origin": "https://www.jin10.com",
|
||||
}
|
||||
url = "https://mp-api.jin10.com/api/dynamic-data/child"
|
||||
formatted_date = "-".join([date[:4], date[4:6], date[6:]])
|
||||
params = {
|
||||
"tb_name": "_vir_26",
|
||||
"search": json.dumps({"range,date": f"{formatted_date},{formatted_date}", "status": 1}),
|
||||
"order": "date,desc",
|
||||
}
|
||||
r = requests.get(url, params=params, headers=headers)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"])
|
||||
temp_df = temp_df.rename(
|
||||
columns={
|
||||
"date": "日期",
|
||||
"heyue_name": "合约品种",
|
||||
"heyue_code": "合约代码",
|
||||
"pub_date_commission": "手续费公布时间",
|
||||
"pub_date_price": "价格公布时间",
|
||||
"heyue_price": "现价",
|
||||
"up_limit_num": "涨停板",
|
||||
"down_limit_num": "跌停板",
|
||||
"buy_ratio": "保证金/买开",
|
||||
"sell_ratio": "保证金/卖开",
|
||||
"per_lot_price": "保证金/每手",
|
||||
"per_ratio": "每手跳数",
|
||||
"buy_commission": "开仓",
|
||||
"sell_yesterday_commission": "平昨",
|
||||
"sell_cur_commission": "平今",
|
||||
"per_commission_price": "每跳毛利",
|
||||
"per_net_profit": "每跳净利",
|
||||
"jys": "交易所",
|
||||
}
|
||||
)
|
||||
temp_df = temp_df.drop(
|
||||
columns=["id", "status", "created_at", "updated_at", "_date", "_pub_date_commission", "_pub_date_price"],
|
||||
errors="ignore")
|
||||
temp_df['日期'] = pd.to_datetime(temp_df['日期'], errors="coerce").dt.date
|
||||
temp_df['现价'] = pd.to_numeric(temp_df['现价'], errors="coerce")
|
||||
temp_df['涨停板'] = pd.to_numeric(temp_df['涨停板'], errors="coerce")
|
||||
temp_df['跌停板'] = pd.to_numeric(temp_df['跌停板'], errors="coerce")
|
||||
temp_df['每手跳数'] = pd.to_numeric(temp_df['每手跳数'], errors="coerce")
|
||||
temp_df['每跳毛利'] = pd.to_numeric(temp_df['每跳毛利'], errors="coerce")
|
||||
temp_df['每跳净利'] = pd.to_numeric(temp_df['每跳净利'], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_comm_js_df = futures_comm_js(date="20260213")
|
||||
print(futures_comm_js_df)
|
||||
@@ -0,0 +1,284 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/4/11 17:00
|
||||
Desc: 九期网-期货手续费
|
||||
https://www.9qihuo.com/qihuoshouxufei
|
||||
"""
|
||||
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
def _futures_comm_qihuo_process(df: pd.DataFrame, name: str = None) -> pd.DataFrame:
|
||||
"""
|
||||
期货手续费数据细节处理函数
|
||||
https://www.9qihuo.com/qihuoshouxufei
|
||||
:param df: 获取到的 pandas.DataFrame 数据
|
||||
:type df: pandas.DataFrame
|
||||
:param name: 交易所名称
|
||||
:type name: str
|
||||
:return: 处理后的数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
common_temp_df = df.copy()
|
||||
common_temp_df["合约名称"] = (
|
||||
common_temp_df["合约品种"].str.split("(", expand=True).iloc[:, 0].str.strip()
|
||||
)
|
||||
common_temp_df["合约代码"] = (
|
||||
common_temp_df["合约品种"].str.split("(", expand=True).iloc[:, 1].str.strip(")")
|
||||
)
|
||||
common_temp_df["涨停板"] = (
|
||||
common_temp_df["涨/跌停板"].str.split("/", expand=True).iloc[:, 0].str.strip()
|
||||
)
|
||||
common_temp_df["跌停板"] = (
|
||||
common_temp_df["涨/跌停板"].str.split("/", expand=True).iloc[:, 1].str.strip()
|
||||
)
|
||||
common_temp_df["保证金-买开"] = common_temp_df["保证金-买开"].str.strip("%")
|
||||
common_temp_df["保证金-卖开"] = common_temp_df["保证金-卖开"].str.strip("%")
|
||||
common_temp_df["保证金-每手"] = common_temp_df["保证金-保证金/每手"].str.strip("元")
|
||||
common_temp_df["手续费"] = common_temp_df["手续费(开+平)"].str.strip("元")
|
||||
try:
|
||||
temp_df_ratio = (
|
||||
common_temp_df["手续费标准-开仓"][
|
||||
common_temp_df["手续费标准-开仓"].str.contains("万分之")
|
||||
]
|
||||
.str.split("/", expand=True)
|
||||
.iloc[:, 0]
|
||||
.astype(float)
|
||||
/ 10000
|
||||
)
|
||||
except IndexError:
|
||||
temp_df_ratio = pd.NA
|
||||
temp_df_yuan = common_temp_df["手续费标准-开仓"][
|
||||
common_temp_df["手续费标准-开仓"].str.contains("元")
|
||||
]
|
||||
common_temp_df["手续费标准-开仓-万分之"] = temp_df_ratio
|
||||
common_temp_df["手续费标准-开仓-元"] = temp_df_yuan.str.strip("元")
|
||||
try:
|
||||
temp_df_ratio = (
|
||||
common_temp_df["手续费标准-平昨"][
|
||||
common_temp_df["手续费标准-平昨"].str.contains("万分之")
|
||||
]
|
||||
.str.split("/", expand=True)
|
||||
.iloc[:, 0]
|
||||
.astype(float)
|
||||
/ 10000
|
||||
)
|
||||
except IndexError:
|
||||
temp_df_ratio = pd.NA
|
||||
temp_df_yuan = common_temp_df["手续费标准-平昨"][
|
||||
common_temp_df["手续费标准-平昨"].str.contains("元")
|
||||
]
|
||||
common_temp_df["手续费标准-平昨-万分之"] = temp_df_ratio
|
||||
common_temp_df["手续费标准-平昨-元"] = temp_df_yuan.str.strip("元")
|
||||
try:
|
||||
temp_df_ratio = (
|
||||
common_temp_df["手续费标准-平今"][
|
||||
common_temp_df["手续费标准-平今"].str.contains("万分之")
|
||||
]
|
||||
.str.split("/", expand=True)
|
||||
.iloc[:, 0]
|
||||
.astype(float)
|
||||
/ 10000
|
||||
)
|
||||
except IndexError:
|
||||
temp_df_ratio = pd.NA
|
||||
temp_df_yuan = common_temp_df["手续费标准-平今"][
|
||||
common_temp_df["手续费标准-平今"].str.contains("元")
|
||||
]
|
||||
common_temp_df["手续费标准-平今-万分之"] = temp_df_ratio
|
||||
common_temp_df["手续费标准-平今-元"] = temp_df_yuan.str.strip("元")
|
||||
del common_temp_df["手续费标准-开仓"]
|
||||
del common_temp_df["手续费标准-平昨"]
|
||||
del common_temp_df["手续费标准-平今"]
|
||||
del common_temp_df["合约品种"]
|
||||
del common_temp_df["涨/跌停板"]
|
||||
del common_temp_df["手续费(开+平)"]
|
||||
del common_temp_df["保证金-保证金/每手"]
|
||||
common_temp_df["交易所名称"] = name
|
||||
common_temp_df = common_temp_df[
|
||||
[
|
||||
"交易所名称",
|
||||
"合约名称",
|
||||
"合约代码",
|
||||
"现价",
|
||||
"涨停板",
|
||||
"跌停板",
|
||||
"保证金-买开",
|
||||
"保证金-卖开",
|
||||
"保证金-每手",
|
||||
"手续费标准-开仓-万分之",
|
||||
"手续费标准-开仓-元",
|
||||
"手续费标准-平昨-万分之",
|
||||
"手续费标准-平昨-元",
|
||||
"手续费标准-平今-万分之",
|
||||
"手续费标准-平今-元",
|
||||
"每跳毛利",
|
||||
"手续费",
|
||||
"每跳净利",
|
||||
"备注",
|
||||
]
|
||||
]
|
||||
common_temp_df["现价"] = pd.to_numeric(common_temp_df["现价"])
|
||||
common_temp_df["涨停板"] = pd.to_numeric(common_temp_df["涨停板"])
|
||||
common_temp_df["跌停板"] = pd.to_numeric(common_temp_df["跌停板"])
|
||||
common_temp_df["保证金-买开"] = pd.to_numeric(common_temp_df["保证金-买开"])
|
||||
common_temp_df["保证金-卖开"] = pd.to_numeric(common_temp_df["保证金-卖开"])
|
||||
common_temp_df["保证金-每手"] = pd.to_numeric(common_temp_df["保证金-每手"])
|
||||
# common_temp_df["手续费标准-开仓-元"] = pd.to_numeric(common_temp_df["手续费标准-开仓-元"])
|
||||
# common_temp_df["手续费标准-平昨-元"] = pd.to_numeric(common_temp_df["手续费标准-平昨-元"])
|
||||
# common_temp_df["手续费标准-平今-元"] = pd.to_numeric(common_temp_df["手续费标准-平今-元"])
|
||||
common_temp_df["每跳毛利"] = pd.to_numeric(common_temp_df["每跳毛利"])
|
||||
common_temp_df["手续费"] = pd.to_numeric(common_temp_df["手续费"])
|
||||
common_temp_df["每跳净利"] = pd.to_numeric(common_temp_df["每跳净利"])
|
||||
session = requests.Session()
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/125.0.0.0 Safari/537.36",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"Connection": "keep-alive",
|
||||
"Referer": "https://www.9qihuo.com/",
|
||||
"Sec-Fetch-Dest": "document",
|
||||
"Sec-Fetch-Mode": "navigate",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"Sec-Fetch-User": "?1",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"Cache-Control": "max-age=0",
|
||||
}
|
||||
session.get("https://www.9qihuo.com/", headers=headers, timeout=10)
|
||||
r = session.get(
|
||||
"https://www.9qihuo.com/qihuoshouxufei", headers=headers, timeout=10
|
||||
)
|
||||
soup = BeautifulSoup(r.text, features="lxml")
|
||||
raw_date_text = soup.find(name="a", attrs={"id": "dlink"}).previous
|
||||
comm_update_time = raw_date_text.split(",")[0].strip("(手续费更新时间:")
|
||||
price_update_time = (
|
||||
raw_date_text.split(",")[1].strip("价格更新时间:").strip("。)")
|
||||
)
|
||||
common_temp_df["手续费更新时间"] = comm_update_time
|
||||
common_temp_df["价格更新时间"] = price_update_time
|
||||
return common_temp_df
|
||||
|
||||
|
||||
def futures_comm_info(symbol: str = "所有") -> pd.DataFrame:
|
||||
"""
|
||||
九期网-期货手续费
|
||||
https://www.9qihuo.com/qihuoshouxufei
|
||||
:param symbol: choice of {"所有", "上海期货交易所", "大连商品交易所", "郑州商品交易所", "上海国际能源交易中心", "中国金融期货交易所", "广州期货交易所"}
|
||||
:type symbol: str
|
||||
:return: 期货手续费
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
session = requests.Session()
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/125.0.0.0 Safari/537.36",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"Connection": "keep-alive",
|
||||
"Referer": "https://www.9qihuo.com/",
|
||||
"Sec-Fetch-Dest": "document",
|
||||
"Sec-Fetch-Mode": "navigate",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"Sec-Fetch-User": "?1",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"Cache-Control": "max-age=0",
|
||||
}
|
||||
session.get("https://www.9qihuo.com/", headers=headers, timeout=10)
|
||||
r = session.get(
|
||||
"https://www.9qihuo.com/qihuoshouxufei", headers=headers, timeout=10
|
||||
)
|
||||
temp_df = pd.read_html(StringIO(r.text))[0]
|
||||
temp_df.columns = [
|
||||
"合约品种",
|
||||
"现价",
|
||||
"涨/跌停板",
|
||||
"保证金-买开",
|
||||
"保证金-卖开",
|
||||
"保证金-保证金/每手",
|
||||
"手续费标准-开仓",
|
||||
"手续费标准-平昨",
|
||||
"手续费标准-平今",
|
||||
"每跳毛利",
|
||||
"手续费(开+平)",
|
||||
"每跳净利",
|
||||
"备注",
|
||||
"-",
|
||||
"-",
|
||||
]
|
||||
df_0 = temp_df[temp_df["合约品种"].str.contains("上海期货交易所")].index.values[0]
|
||||
df_1 = temp_df[temp_df["合约品种"].str.contains("大连商品交易所")].index.values[0]
|
||||
df_2 = temp_df[temp_df["合约品种"].str.contains("郑州商品交易所")].index.values[0]
|
||||
df_3 = temp_df[
|
||||
temp_df["合约品种"].str.contains("上海国际能源交易中心")
|
||||
].index.values[0]
|
||||
df_4 = temp_df[temp_df["合约品种"].str.contains("广州期货交易所")].index.values[0]
|
||||
df_5 = temp_df[temp_df["合约品种"].str.contains("中国金融期货交易所")].index.values[
|
||||
0
|
||||
]
|
||||
shfe_df = temp_df.iloc[df_0 + 3 : df_1, :].reset_index(drop=True)
|
||||
dce_df = temp_df.iloc[df_1 + 3 : df_2, :].reset_index(drop=True)
|
||||
czce_df = temp_df.iloc[df_2 + 3 : df_3, :].reset_index(drop=True)
|
||||
ine_df = temp_df.iloc[df_3 + 3 : df_4, :].reset_index(drop=True)
|
||||
gfex_df = temp_df.iloc[df_4 + 3 : df_5, :].reset_index(drop=True)
|
||||
cffex_df = temp_df.iloc[df_5 + 3 :, :].reset_index(drop=True)
|
||||
if symbol == "上海期货交易所":
|
||||
return _futures_comm_qihuo_process(shfe_df, name="上海期货交易所")
|
||||
elif symbol == "大连商品交易所":
|
||||
return _futures_comm_qihuo_process(dce_df, name="大连商品交易所")
|
||||
elif symbol == "郑州商品交易所":
|
||||
return _futures_comm_qihuo_process(czce_df, name="郑州商品交易所")
|
||||
elif symbol == "上海国际能源交易中心":
|
||||
return _futures_comm_qihuo_process(ine_df, name="上海国际能源交易中心")
|
||||
elif symbol == "广州期货交易所":
|
||||
return _futures_comm_qihuo_process(gfex_df, name="广州期货交易所")
|
||||
elif symbol == "中国金融期货交易所":
|
||||
return _futures_comm_qihuo_process(cffex_df, name="中国金融期货交易所")
|
||||
else:
|
||||
big_df = pd.DataFrame()
|
||||
big_df = pd.concat(
|
||||
objs=[big_df, _futures_comm_qihuo_process(shfe_df, name="上海期货交易所")],
|
||||
ignore_index=True,
|
||||
)
|
||||
big_df = pd.concat(
|
||||
objs=[big_df, _futures_comm_qihuo_process(dce_df, name="大连商品交易所")],
|
||||
ignore_index=True,
|
||||
)
|
||||
big_df = pd.concat(
|
||||
objs=[big_df, _futures_comm_qihuo_process(czce_df, name="郑州商品交易所")],
|
||||
ignore_index=True,
|
||||
)
|
||||
big_df = pd.concat(
|
||||
objs=[
|
||||
big_df,
|
||||
_futures_comm_qihuo_process(ine_df, name="上海国际能源交易中心"),
|
||||
],
|
||||
ignore_index=True,
|
||||
)
|
||||
big_df = pd.concat(
|
||||
objs=[big_df, _futures_comm_qihuo_process(gfex_df, name="广州期货交易所")],
|
||||
ignore_index=True,
|
||||
)
|
||||
big_df = pd.concat(
|
||||
objs=[
|
||||
big_df,
|
||||
_futures_comm_qihuo_process(cffex_df, name="中国金融期货交易所"),
|
||||
],
|
||||
ignore_index=True,
|
||||
)
|
||||
return big_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_comm_info_df = futures_comm_info(symbol="所有")
|
||||
print(futures_comm_info_df)
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/10/30 17:00
|
||||
Desc: 查询期货合约当前时刻的详情
|
||||
https://finance.sina.com.cn/futures/quotes/V2101.shtml
|
||||
"""
|
||||
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
def futures_contract_detail(symbol: str = "AP2101") -> pd.DataFrame:
|
||||
"""
|
||||
查询期货合约详情
|
||||
https://finance.sina.com.cn/futures/quotes/V2101.shtml
|
||||
:param symbol: 合约
|
||||
:type symbol: str
|
||||
:return: 期货合约详情
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"https://finance.sina.com.cn/futures/quotes/{symbol}.shtml"
|
||||
r = requests.get(url)
|
||||
r.encoding = "gb2312"
|
||||
temp_df = pd.read_html(StringIO(r.text))[6]
|
||||
data_one = temp_df.iloc[:, :2]
|
||||
data_one.columns = ["item", "value"]
|
||||
data_two = temp_df.iloc[:, 2:4]
|
||||
data_two.columns = ["item", "value"]
|
||||
data_three = temp_df.iloc[:, 4:]
|
||||
data_three.columns = ["item", "value"]
|
||||
temp_df = pd.concat(
|
||||
objs=[data_one, data_two, data_three], axis=0, ignore_index=True
|
||||
)
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_contract_detail_em(symbol: str = "v2602F") -> pd.DataFrame:
|
||||
"""
|
||||
查询期货合约详情
|
||||
https://quote.eastmoney.com/qihuo/v2602F.html
|
||||
:param symbol: 合约
|
||||
:type symbol: str
|
||||
:return: 期货合约详情
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"https://quote.eastmoney.com/qihuo/{symbol}.html"
|
||||
r = requests.get(url)
|
||||
soup = BeautifulSoup(r.text, features="lxml")
|
||||
url_text = (
|
||||
soup.find(name="div", attrs={"class": "sidertabbox_tsplit"})
|
||||
.find(name="div", attrs={"class": "onet"})
|
||||
.find("a")["href"]
|
||||
)
|
||||
inner_symbol = url_text.split("#")[-1].strip("futures_")
|
||||
url = f"https://futsse-static.eastmoney.com/redis?msgid={inner_symbol}_info"
|
||||
r = requests.get(url)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame.from_dict(data_json, orient="index")
|
||||
column_mapping = {
|
||||
"vname": "交易品种",
|
||||
"vcode": "交易代码",
|
||||
"jydw": "交易单位",
|
||||
"bjdw": "报价单位",
|
||||
"market": "上市交易所",
|
||||
"zxbddw": "最小变动价格",
|
||||
"zdtbfd": "跌涨停板幅度",
|
||||
"hyjgyf": "合约交割月份",
|
||||
"jysj": "交易时间",
|
||||
"zhjyr": "最后交易日",
|
||||
"zhjgr": "最后交割日",
|
||||
"jgpj": "交割品级",
|
||||
"zcjybzj": "最初交易保证金",
|
||||
"jgfs": "交割方式",
|
||||
}
|
||||
temp_df.rename(index=column_mapping, inplace=True)
|
||||
temp_df.reset_index(drop=False, inplace=True)
|
||||
temp_df.columns = ["item", "value"]
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_contract_detail_df = futures_contract_detail(symbol="V2101")
|
||||
print(futures_contract_detail_df)
|
||||
|
||||
futures_contract_detail_em_df = futures_contract_detail_em(symbol="l2602F")
|
||||
print(futures_contract_detail_em_df)
|
||||
@@ -0,0 +1,779 @@
|
||||
#!/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)
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/3/5 18:00
|
||||
Desc: 外盘期货-历史行情数据-日频率
|
||||
https://finance.sina.com.cn/money/future/hf.html
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
from akshare.futures.futures_hq_sina import (
|
||||
futures_foreign_commodity_subscribe_exchange_symbol,
|
||||
)
|
||||
|
||||
|
||||
def futures_foreign_hist(symbol: str = "ZSD") -> pd.DataFrame:
|
||||
"""
|
||||
外盘期货-历史行情数据-日频率
|
||||
https://finance.sina.com.cn/money/future/hf.html
|
||||
:param symbol: 外盘期货代码, 可以通过 ak.futures_foreign_commodity_subscribe_exchange_symbol() 来获取所有品种代码
|
||||
:type symbol: str
|
||||
:return: 历史行情数据-日频率
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
today = f"{datetime.today().year}_{datetime.today().month}_{datetime.today().day}"
|
||||
url = (
|
||||
f"https://stock2.finance.sina.com.cn/futures/api/jsonp.php/var%20_S{today}=/"
|
||||
f"GlobalFuturesService.getGlobalFuturesDailyKLine"
|
||||
)
|
||||
params = {
|
||||
"symbol": symbol,
|
||||
"_": today,
|
||||
"source": "web",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_text = r.text
|
||||
data_df = pd.read_json(StringIO(data_text[data_text.find("[") : -2]))
|
||||
return data_df
|
||||
|
||||
|
||||
def futures_foreign_detail(symbol: str = "ZSD") -> pd.DataFrame:
|
||||
"""
|
||||
foreign futures contract detail data
|
||||
:param symbol: futures symbol, you can get it from hf_subscribe_exchange_symbol function
|
||||
:type symbol: str
|
||||
:return: contract detail
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"https://finance.sina.com.cn/futures/quotes/{symbol}.shtml"
|
||||
r = requests.get(url)
|
||||
r.encoding = "gbk"
|
||||
data_text = r.text
|
||||
data_df = pd.read_html(StringIO(data_text))[6]
|
||||
return data_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_foreign_hist_df = futures_foreign_hist(symbol="JY")
|
||||
print(futures_foreign_hist_df)
|
||||
|
||||
subscribes = futures_foreign_commodity_subscribe_exchange_symbol()
|
||||
|
||||
for item in subscribes:
|
||||
futures_foreign_detail_df = futures_foreign_detail(symbol=item)
|
||||
print(futures_foreign_detail_df)
|
||||
|
||||
for item in subscribes:
|
||||
futures_foreign_hist_df = futures_foreign_hist(symbol=item)
|
||||
print(futures_foreign_hist_df)
|
||||
@@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/3/9 22:00
|
||||
Desc: 东方财富网-行情中心-期货市场-国际期货
|
||||
https://quote.eastmoney.com/center/gridlist.html#futures_global
|
||||
"""
|
||||
|
||||
import math
|
||||
from typing import Optional
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
from akshare.utils.tqdm import get_tqdm
|
||||
|
||||
|
||||
def __futures_global_hist_market_code(symbol: str = "HG00Y") -> Optional[int]:
|
||||
"""
|
||||
东方财富网-行情中心-期货市场-国际期货-品种市场对照表
|
||||
https://quote.eastmoney.com/center/gridlist.html#futures_global
|
||||
:param symbol: HG00Y, 品种代码;可以通过 ak.futures_global_spot_em() 来获取所有可获取历史行情数据的品种代码
|
||||
:type symbol: str
|
||||
:return: 品种所属于的市场
|
||||
:rtype: str
|
||||
"""
|
||||
# 提取品种代码(去掉年份和月份部分)
|
||||
base_symbol = ""
|
||||
i = 0
|
||||
while i < len(symbol) and not symbol[i].isdigit():
|
||||
base_symbol += symbol[i]
|
||||
i += 1
|
||||
# 如果代码中没有数字(异常情况),则返回整个代码作为基础品种代码
|
||||
if not base_symbol and i == len(symbol):
|
||||
base_symbol = symbol
|
||||
# 金属和贵金属品种 - 101
|
||||
if base_symbol in ["HG", "GC", "SI", "QI", "QO", "MGC", "LTH"]:
|
||||
return 101
|
||||
# 能源品种 - 102
|
||||
if base_symbol in ["CL", "NG", "RB", "HO", "PA", "PL", "QM"]:
|
||||
return 102
|
||||
# 农产品和金融品种 - 103
|
||||
if base_symbol in [
|
||||
"ZW",
|
||||
"ZM",
|
||||
"ZS",
|
||||
"ZC",
|
||||
"XC",
|
||||
"XK",
|
||||
"XW",
|
||||
"YM",
|
||||
"TY",
|
||||
"US",
|
||||
"EH",
|
||||
"ZL",
|
||||
"ZR",
|
||||
"ZO",
|
||||
"FV",
|
||||
"TU",
|
||||
"UL",
|
||||
"NQ",
|
||||
"ES",
|
||||
]:
|
||||
return 103
|
||||
# 中国市场特有品种 - 104
|
||||
if base_symbol in ["TF", "RT", "CN"]:
|
||||
return 104
|
||||
# 软商品期货 - 108
|
||||
if base_symbol in ["SB", "CT", "SF"]:
|
||||
return 108
|
||||
# 特殊L开头品种 - 109
|
||||
if base_symbol in ["LCPT", "LZNT", "LALT", "LTNT", "LLDT", "LNKT"]:
|
||||
return 109
|
||||
# MPM开头品种 - 110
|
||||
if base_symbol == "MPM":
|
||||
return 110
|
||||
# 日本市场品种 - 111
|
||||
if base_symbol.startswith("J"):
|
||||
return 111
|
||||
# 单字母代码品种 - 112
|
||||
if base_symbol in ["M", "B", "G"]:
|
||||
return 112
|
||||
# 如果没有匹配到任何规则,返回一个默认值或者错误
|
||||
return None
|
||||
|
||||
|
||||
def futures_global_spot_em() -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-行情中心-期货市场-国际期货
|
||||
https://quote.eastmoney.com/center/gridlist.html#futures_global
|
||||
:return: 行情数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://futsseapi.eastmoney.com/list/COMEX,NYMEX,COBOT,SGX,NYBOT,LME,MDEX,TOCOM,IPE"
|
||||
params = {
|
||||
"orderBy": "dm",
|
||||
"sort": "desc",
|
||||
"pageSize": "20",
|
||||
"pageIndex": "0",
|
||||
"token": "58b2fa8f54638b60b87d69b31969089c",
|
||||
"field": "dm,sc,name,p,zsjd,zde,zdf,f152,o,h,l,zjsj,vol,wp,np,ccl",
|
||||
"blockName": "callback",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
total_num = data_json["total"]
|
||||
total_page = math.ceil(total_num / 20) - 1
|
||||
tqdm = get_tqdm()
|
||||
big_df = pd.DataFrame()
|
||||
for page in tqdm(range(total_page), leave=False):
|
||||
params.update({"pageIndex": page})
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["list"])
|
||||
big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
|
||||
big_df.reset_index(inplace=True)
|
||||
big_df["index"] = big_df["index"] + 1
|
||||
big_df.rename(
|
||||
columns={
|
||||
"index": "序号",
|
||||
"np": "卖盘",
|
||||
"h": "最高",
|
||||
"dm": "代码",
|
||||
"zsjd": "-",
|
||||
"l": "最低",
|
||||
"ccl": "持仓量",
|
||||
"o": "今开",
|
||||
"p": "最新价",
|
||||
"sc": "-",
|
||||
"vol": "成交量",
|
||||
"name": "名称",
|
||||
"wp": "买盘",
|
||||
"zde": "涨跌额",
|
||||
"zdf": "涨跌幅",
|
||||
"zjsj": "昨结",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
big_df = big_df[
|
||||
[
|
||||
"序号",
|
||||
"代码",
|
||||
"名称",
|
||||
"最新价",
|
||||
"涨跌额",
|
||||
"涨跌幅",
|
||||
"今开",
|
||||
"最高",
|
||||
"最低",
|
||||
"昨结",
|
||||
"成交量",
|
||||
"买盘",
|
||||
"卖盘",
|
||||
"持仓量",
|
||||
]
|
||||
]
|
||||
big_df["最新价"] = pd.to_numeric(big_df["最新价"], errors="coerce")
|
||||
big_df["涨跌额"] = pd.to_numeric(big_df["涨跌额"], errors="coerce")
|
||||
big_df["涨跌幅"] = pd.to_numeric(big_df["涨跌幅"], errors="coerce")
|
||||
big_df["今开"] = pd.to_numeric(big_df["今开"], errors="coerce")
|
||||
big_df["最高"] = pd.to_numeric(big_df["最高"], errors="coerce")
|
||||
big_df["最低"] = pd.to_numeric(big_df["最低"], errors="coerce")
|
||||
big_df["昨结"] = pd.to_numeric(big_df["昨结"], errors="coerce")
|
||||
big_df["成交量"] = pd.to_numeric(big_df["成交量"], errors="coerce")
|
||||
big_df["买盘"] = pd.to_numeric(big_df["买盘"], errors="coerce")
|
||||
big_df["卖盘"] = pd.to_numeric(big_df["卖盘"], errors="coerce")
|
||||
big_df["持仓量"] = pd.to_numeric(big_df["持仓量"], errors="coerce")
|
||||
return big_df
|
||||
|
||||
|
||||
def futures_global_hist_em(symbol: str = "HG00Y") -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-行情中心-期货市场-国际期货-历史行情数据
|
||||
https://quote.eastmoney.com/globalfuture/HG25J.html
|
||||
:param symbol: 品种代码;可以通过 ak.futures_global_spot_em() 来获取所有可获取历史行情数据的品种代码
|
||||
:type symbol: str
|
||||
:return: 历史行情数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
|
||||
market_code = __futures_global_hist_market_code(symbol)
|
||||
params = {
|
||||
"secid": f"{market_code}.{symbol}",
|
||||
"klt": "101",
|
||||
"fqt": "1",
|
||||
"lmt": "6600",
|
||||
"end": "20500000",
|
||||
"iscca": "1",
|
||||
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8",
|
||||
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64",
|
||||
"ut": "f057cbcbce2a86e2866ab8877db1d059",
|
||||
"forcect": "1",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
|
||||
temp_df["code"] = data_json["data"]["code"]
|
||||
temp_df["name"] = data_json["data"]["name"]
|
||||
temp_df.columns = [
|
||||
"日期",
|
||||
"开盘",
|
||||
"最新价",
|
||||
"最高",
|
||||
"最低",
|
||||
"总量",
|
||||
"-",
|
||||
"-",
|
||||
"涨幅",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"持仓",
|
||||
"日增",
|
||||
"代码",
|
||||
"名称",
|
||||
]
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"日期",
|
||||
"代码",
|
||||
"名称",
|
||||
"开盘",
|
||||
"最新价",
|
||||
"最高",
|
||||
"最低",
|
||||
"总量",
|
||||
"涨幅",
|
||||
"持仓",
|
||||
"日增",
|
||||
]
|
||||
]
|
||||
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
|
||||
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"], errors="coerce")
|
||||
temp_df["最新价"] = pd.to_numeric(temp_df["最新价"], errors="coerce")
|
||||
temp_df["最高"] = pd.to_numeric(temp_df["最高"], errors="coerce")
|
||||
temp_df["最低"] = pd.to_numeric(temp_df["最低"], errors="coerce")
|
||||
temp_df["总量"] = pd.to_numeric(temp_df["总量"], errors="coerce")
|
||||
temp_df["涨幅"] = pd.to_numeric(temp_df["涨幅"], errors="coerce")
|
||||
temp_df["日增"] = pd.to_numeric(temp_df["日增"], errors="coerce")
|
||||
# 日增修复为有符号32位整数值
|
||||
unsigned_max, signed_max = (2**32) - 1, (2**31) - 1
|
||||
mask = temp_df["日增"] > signed_max
|
||||
temp_df.loc[mask, "日增"] = temp_df.loc[mask, "日增"] - (unsigned_max + 1)
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_global_spot_em_df = futures_global_spot_em()
|
||||
print(futures_global_spot_em_df)
|
||||
|
||||
futures_global_hist_em_df = futures_global_hist_em(symbol="HG00Y")
|
||||
print(futures_global_hist_em_df)
|
||||
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/2/20 17:00
|
||||
Desc: 东方财富网-期货行情
|
||||
https://qhweb.eastmoney.com/quote
|
||||
"""
|
||||
|
||||
import re
|
||||
from functools import lru_cache
|
||||
from typing import Tuple, Dict
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def __futures_hist_separate_char_and_numbers_em(symbol: str = "焦煤2506") -> tuple:
|
||||
"""
|
||||
东方财富网-期货行情-交易所品种对照表原始数据
|
||||
https://quote.eastmoney.com/qihuo/al2505.html
|
||||
:param symbol: 股票代码
|
||||
:type symbol: str
|
||||
:return: 交易所品种对照表原始数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
char = re.findall(pattern="[\u4e00-\u9fa5a-zA-Z]+", string=symbol)
|
||||
numbers = re.findall(pattern=r"\d+", string=symbol)
|
||||
return char[0], numbers[0]
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def __fetch_exchange_symbol_raw_em() -> list:
|
||||
"""
|
||||
东方财富网-期货行情-交易所品种对照表原始数据
|
||||
https://quote.eastmoney.com/qihuo/al2505.html
|
||||
:return: 交易所品种对照表原始数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://futsse-static.eastmoney.com/redis"
|
||||
params = {"msgid": "gnweb"}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
all_exchange_symbol_list = []
|
||||
for item in data_json:
|
||||
params = {"msgid": str(item["mktid"])}
|
||||
r = requests.get(url, params=params)
|
||||
inner_data_json = r.json()
|
||||
for num in range(1, len(inner_data_json) + 1):
|
||||
params = {"msgid": str(item["mktid"]) + f"_{num}"}
|
||||
r = requests.get(url, params=params)
|
||||
inner_data_json = r.json()
|
||||
all_exchange_symbol_list.extend(inner_data_json)
|
||||
return all_exchange_symbol_list
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def __get_exchange_symbol_map() -> Tuple[Dict, Dict, Dict, Dict]:
|
||||
"""
|
||||
东方财富网-期货行情-交易所品种映射
|
||||
https://quote.eastmoney.com/qihuo/al2505.html
|
||||
:return: 交易所品种映射
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
all_exchange_symbol_list = __fetch_exchange_symbol_raw_em()
|
||||
c_contract_mkt = {}
|
||||
c_contract_to_e_contract = {}
|
||||
e_symbol_mkt = {}
|
||||
c_symbol_mkt = {}
|
||||
for item in all_exchange_symbol_list:
|
||||
c_contract_mkt[item["name"]] = item["mktid"]
|
||||
c_contract_to_e_contract[item["name"]] = item["code"]
|
||||
e_symbol_mkt[item["vcode"]] = item["mktid"]
|
||||
c_symbol_mkt[item["vname"]] = item["mktid"]
|
||||
return c_contract_mkt, c_contract_to_e_contract, e_symbol_mkt, c_symbol_mkt
|
||||
|
||||
|
||||
def futures_hist_table_em() -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-期货行情-交易所品种对照表
|
||||
https://quote.eastmoney.com/qihuo/al2505.html
|
||||
:return: 交易所品种对照表
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
all_exchange_symbol_list = __fetch_exchange_symbol_raw_em()
|
||||
temp_df = pd.DataFrame(all_exchange_symbol_list)
|
||||
temp_df = temp_df[["mktname", "name", "code"]]
|
||||
temp_df.columns = ["市场简称", "合约中文代码", "合约代码"]
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_hist_em(
|
||||
symbol: str = "热卷主连",
|
||||
period: str = "daily",
|
||||
start_date: str = "19900101",
|
||||
end_date: str = "20500101",
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-期货行情-行情数据
|
||||
https://qhweb.eastmoney.com/quote
|
||||
:param symbol: 期货代码
|
||||
:type symbol: str
|
||||
:param period: choice of {'daily', 'weekly', 'monthly'}
|
||||
:type period: str
|
||||
:param start_date: 开始日期
|
||||
:type start_date: str
|
||||
:param end_date: 结束日期
|
||||
:type end_date: str
|
||||
:return: 行情数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
|
||||
period_dict = {"daily": "101", "weekly": "102", "monthly": "103"}
|
||||
c_contract_mkt, c_contract_to_e_contract, e_symbol_mkt, c_symbol_mkt = (
|
||||
__get_exchange_symbol_map()
|
||||
)
|
||||
try:
|
||||
sec_id = f"{c_contract_mkt[symbol]}.{c_contract_to_e_contract[symbol]}"
|
||||
except KeyError:
|
||||
symbol_char, numbers = __futures_hist_separate_char_and_numbers_em(symbol)
|
||||
if re.match(pattern="^[\u4e00-\u9fa5]+$", string=symbol_char):
|
||||
sec_id = str(c_symbol_mkt[symbol_char]) + "." + symbol
|
||||
else:
|
||||
sec_id = str(e_symbol_mkt[symbol_char]) + "." + symbol
|
||||
params = {
|
||||
"secid": sec_id,
|
||||
"klt": period_dict[period],
|
||||
"fqt": "1",
|
||||
"lmt": "10000",
|
||||
"end": "20500000",
|
||||
"iscca": "1",
|
||||
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8",
|
||||
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64",
|
||||
"ut": "7eea3edcaed734bea9cbfc24409ed989",
|
||||
"forcect": "1",
|
||||
}
|
||||
r = requests.get(url, timeout=15, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
|
||||
if temp_df.empty:
|
||||
return temp_df
|
||||
temp_df.columns = [
|
||||
"时间",
|
||||
"开盘",
|
||||
"收盘",
|
||||
"最高",
|
||||
"最低",
|
||||
"成交量",
|
||||
"成交额",
|
||||
"-",
|
||||
"涨跌幅",
|
||||
"涨跌",
|
||||
"_",
|
||||
"_",
|
||||
"持仓量",
|
||||
"_",
|
||||
]
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"时间",
|
||||
"开盘",
|
||||
"最高",
|
||||
"最低",
|
||||
"收盘",
|
||||
"涨跌",
|
||||
"涨跌幅",
|
||||
"成交量",
|
||||
"成交额",
|
||||
"持仓量",
|
||||
]
|
||||
]
|
||||
temp_df.index = pd.to_datetime(temp_df["时间"])
|
||||
temp_df = temp_df[start_date:end_date]
|
||||
temp_df.reset_index(drop=True, inplace=True)
|
||||
temp_df["开盘"] = pd.to_numeric(temp_df["开盘"], errors="coerce")
|
||||
temp_df["收盘"] = pd.to_numeric(temp_df["收盘"], errors="coerce")
|
||||
temp_df["最高"] = pd.to_numeric(temp_df["最高"], errors="coerce")
|
||||
temp_df["最低"] = pd.to_numeric(temp_df["最低"], errors="coerce")
|
||||
temp_df["成交量"] = pd.to_numeric(temp_df["成交量"], errors="coerce")
|
||||
temp_df["成交额"] = pd.to_numeric(temp_df["成交额"], errors="coerce")
|
||||
temp_df["涨跌"] = pd.to_numeric(temp_df["涨跌"], errors="coerce")
|
||||
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
|
||||
temp_df["持仓量"] = pd.to_numeric(temp_df["持仓量"], errors="coerce")
|
||||
temp_df["时间"] = pd.to_datetime(temp_df["时间"], errors="coerce").dt.date
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_hist_table_em_df = futures_hist_table_em()
|
||||
print(futures_hist_table_em_df)
|
||||
|
||||
futures_hist_em_df = futures_hist_em(symbol="热卷主连", period="daily")
|
||||
print(futures_hist_em_df)
|
||||
@@ -0,0 +1,298 @@
|
||||
#!/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)
|
||||
@@ -0,0 +1,57 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
# !/usr/bin/env python
|
||||
"""
|
||||
Date: 2026/4/28 15:00
|
||||
Desc: 中证商品指数
|
||||
http://www.ccidx.com/
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_index_ccidx(symbol: str = "中证商品期货指数") -> pd.DataFrame:
|
||||
"""
|
||||
中证商品指数-商品指数-日频率
|
||||
http://www.ccidx.com/index.html
|
||||
:param symbol: choice of {"中证商品期货指数", "中证商品期货价格指数"}
|
||||
:type symbol: str
|
||||
:return: 商品指数-日频率
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
futures_index_map = {
|
||||
"中证商品期货指数": "100001.CCI",
|
||||
"中证商品期货价格指数": "000001.CCI",
|
||||
}
|
||||
url = "http://www.ccidx.com/CCI-ZZZS/index/getDateLine"
|
||||
params = {"indexId": futures_index_map[symbol]}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(
|
||||
[item for item in data_json["data"]["dateLineJson"]]
|
||||
)
|
||||
temp_df.rename(
|
||||
columns={
|
||||
"tradeDate": "日期",
|
||||
"indexId": "指数代码",
|
||||
"closingPrice": "收盘点位",
|
||||
"settlePrice": "结算点位",
|
||||
"dailyIncreaseAndDecrease": "涨跌",
|
||||
"dailyIncreaseAndDecreasePercentage": "涨跌幅",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
|
||||
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
|
||||
temp_df["收盘点位"] = pd.to_numeric(temp_df["收盘点位"], errors="coerce")
|
||||
temp_df["结算点位"] = pd.to_numeric(temp_df["结算点位"], errors="coerce")
|
||||
temp_df["涨跌"] = pd.to_numeric(temp_df["涨跌"], errors="coerce")
|
||||
temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
|
||||
temp_df.sort_values(by=["日期"], inplace=True)
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_index_ccidx_df = futures_index_ccidx(symbol="中证商品期货指数")
|
||||
print(futures_index_ccidx_df)
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/11/25 18:00
|
||||
Desc: 99 期货网-大宗商品库存数据
|
||||
https://www.99qh.com/
|
||||
"""
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from functools import lru_cache
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def __get_99_symbol_map() -> pd.DataFrame:
|
||||
"""
|
||||
99 期货网-品种代码对照表
|
||||
https://www.99qh.com/data/stockIn?productId=12
|
||||
:return: 品种代码对照表
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore")
|
||||
url = "https://www.99qh.com/data/stockIn"
|
||||
r = requests.get(url, verify=False)
|
||||
soup = BeautifulSoup(r.text, features="lxml")
|
||||
raw_data = soup.find(attrs={"id": "__NEXT_DATA__"}).text
|
||||
data_json = json.loads(raw_data)
|
||||
df_list = []
|
||||
for i, item in enumerate(
|
||||
data_json["props"]["pageProps"]["data"]["varietyListData"]
|
||||
):
|
||||
temp_df = pd.DataFrame(
|
||||
data_json["props"]["pageProps"]["data"]["varietyListData"][i]["productList"]
|
||||
)
|
||||
df_list.append(temp_df)
|
||||
|
||||
big_df = pd.concat(df_list, ignore_index=True)
|
||||
return big_df
|
||||
|
||||
|
||||
def futures_inventory_99(symbol: str = "豆一") -> pd.DataFrame:
|
||||
"""
|
||||
99 期货网-大宗商品库存数据
|
||||
https://www.99qh.com/data/stockIn?productId=12
|
||||
:param symbol: 交易所对应的具体品种; 如:大连商品交易所的 豆一
|
||||
:type symbol: str
|
||||
:return: 大宗商品库存数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore")
|
||||
temp_df = __get_99_symbol_map()
|
||||
symbol_name_map = dict(zip(temp_df["name"], temp_df["productId"]))
|
||||
symbol_code_map = dict(zip(temp_df["code"], temp_df["productId"]))
|
||||
if symbol in symbol_name_map: # 如果输入的是中文名称
|
||||
product_id = symbol_name_map[symbol]
|
||||
elif symbol in symbol_code_map: # 如果输入的是代码
|
||||
product_id = symbol_code_map[symbol]
|
||||
else:
|
||||
raise ValueError(f"未找到品种 {symbol} 对应的编号")
|
||||
|
||||
url = "https://centerapi.fx168api.com/app/qh/api/stock/trend"
|
||||
headers = {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"_pcc": "J7Dwju3vSeTlLLfTOLBnMXMtc9+PI1GWJR82GTEemXB9ORwBKCyPNDNVUQQv8p1jL3mLpZJ0PHt8"
|
||||
"HZ57YtInOoeRj900V6EBBuvPTDAD9bghKWx4sNHiZNJhkzb4cSjlSO9ZcyZPHXuCLp2szfvtZSgCGQSbTFLUnHJsMrUFxJw=",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/58.0.3029.110 Safari/537.3",
|
||||
"referer": "https://www.99qh.com",
|
||||
"origin": "https://www.99qh.com",
|
||||
}
|
||||
params = {
|
||||
"productId": product_id,
|
||||
"type": "1",
|
||||
"pageNo": "1",
|
||||
"pageSize": "5000",
|
||||
"startDate": "",
|
||||
"endDate": f"{datetime.now().date().isoformat()}",
|
||||
"appCategory": "web",
|
||||
}
|
||||
r = requests.get(url, params, headers=headers, verify=False)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"]["list"])
|
||||
temp_df.columns = ["日期", "收盘价", "库存"]
|
||||
temp_df.sort_values(by=["日期"], ignore_index=True, inplace=True)
|
||||
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
|
||||
temp_df["收盘价"] = pd.to_numeric(temp_df["收盘价"], errors="coerce")
|
||||
temp_df["库存"] = pd.to_numeric(temp_df["库存"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_inventory_99_df = futures_inventory_99(symbol="豆一")
|
||||
print(futures_inventory_99_df)
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/3/5 17:30
|
||||
Desc: 东方财富网-数据中心-期货库存数据
|
||||
https://data.eastmoney.com/ifdata/kcsj.html
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from akshare.futures.cons import futures_inventory_em_symbol_dict
|
||||
|
||||
|
||||
def futures_inventory_em(symbol: str = "a") -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-数据中心-期货库存数据
|
||||
https://data.eastmoney.com/ifdata/kcsj.html
|
||||
:param symbol: 支持品种代码和中文名称,中文名称参见:https://data.eastmoney.com/ifdata/kcsj.html
|
||||
:type symbol: str
|
||||
:return: 指定品种的库存数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
|
||||
params = {
|
||||
"reportName": "RPT_FUTU_POSITIONCODE",
|
||||
"columns": "TRADE_MARKET_CODE,TRADE_CODE,TRADE_TYPE",
|
||||
"filter": '(IS_MAINCODE="1")',
|
||||
"pageNumber": "1",
|
||||
"pageSize": "500",
|
||||
"source": "WEB",
|
||||
"client": "WEB",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["result"]["data"])
|
||||
symbol_dict = dict(zip(temp_df["TRADE_TYPE"], temp_df["TRADE_CODE"]))
|
||||
if symbol in symbol_dict.keys():
|
||||
product_id = symbol_dict[symbol]
|
||||
elif symbol in futures_inventory_em_symbol_dict.keys(): # 如果输入的是代码
|
||||
product_id = futures_inventory_em_symbol_dict[symbol]
|
||||
else:
|
||||
raise ValueError(f"请输入正确的 symbol, 可选项为: {symbol_dict}")
|
||||
params = {
|
||||
"reportName": "RPT_FUTU_STOCKDATA",
|
||||
"columns": "SECURITY_CODE,TRADE_DATE,ON_WARRANT_NUM,ADDCHANGE",
|
||||
"filter": f"""(SECURITY_CODE="{product_id}")(TRADE_DATE>='2020-10-28')""",
|
||||
"pageNumber": "1",
|
||||
"pageSize": "500",
|
||||
"sortTypes": "-1",
|
||||
"sortColumns": "TRADE_DATE",
|
||||
"source": "WEB",
|
||||
"client": "WEB",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["result"]["data"])
|
||||
temp_df.columns = ["-", "日期", "库存", "增减"]
|
||||
temp_df = temp_df[["日期", "库存", "增减"]]
|
||||
temp_df.sort_values(["日期"], inplace=True)
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
temp_df["库存"] = pd.to_numeric(temp_df["库存"], errors="coerce")
|
||||
temp_df["增减"] = pd.to_numeric(temp_df["增减"], errors="coerce")
|
||||
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_inventory_em_df = futures_inventory_em(symbol="a")
|
||||
print(futures_inventory_em_df)
|
||||
@@ -0,0 +1,100 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
# !/usr/bin/env python
|
||||
"""
|
||||
Date: 2024/12/26 18:00
|
||||
Desc: 上海金属网-快讯
|
||||
https://www.shmet.com/newsFlash/newsFlash.html?searchKeyword=
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_news_shmet(symbol: str = "全部") -> pd.DataFrame:
|
||||
"""
|
||||
上海金属网-快讯
|
||||
https://www.shmet.com/newsFlash/newsFlash.html?searchKeyword=
|
||||
:param symbol: choice of {"全部", "要闻", "VIP", "财经", "铜", "铝", "铅", "锌", "镍", "锡", "贵金属", "小金属"}
|
||||
:type symbol: str
|
||||
:return: 上海金属网-快讯
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://www.shmet.com/api/rest/news/queryNewsflashList"
|
||||
if symbol == "全部":
|
||||
payload = {"currentPage": 1, "pageSize": 100}
|
||||
else:
|
||||
symbol_map = {
|
||||
"要闻": "0",
|
||||
"VIP": "100",
|
||||
"财经": "999",
|
||||
"铜": "1002",
|
||||
"铝": "1003",
|
||||
"铅": "1005",
|
||||
"锌": "1004",
|
||||
"镍": "1006",
|
||||
"锡": "1007",
|
||||
"贵金属": "1008",
|
||||
"小金属": "1009",
|
||||
}
|
||||
payload = {
|
||||
"currentPage": 1,
|
||||
"pageSize": 2000,
|
||||
"content": "",
|
||||
"flashTag": symbol_map[symbol],
|
||||
}
|
||||
r = requests.post(url, json=payload)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"]["dataList"])
|
||||
temp_df.columns = [
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"发布时间",
|
||||
"-",
|
||||
"内容",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
"-",
|
||||
]
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"发布时间",
|
||||
"内容",
|
||||
]
|
||||
]
|
||||
temp_df["发布时间"] = pd.to_datetime(
|
||||
temp_df["发布时间"], unit="ms", utc=True
|
||||
).dt.tz_convert("Asia/Shanghai")
|
||||
temp_df.sort_values(["发布时间"], inplace=True)
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_news_shmet_df = futures_news_shmet(symbol="铜")
|
||||
print(futures_news_shmet_df)
|
||||
|
||||
for item in [
|
||||
"全部",
|
||||
"要闻",
|
||||
"VIP",
|
||||
"财经",
|
||||
"铜",
|
||||
"铝",
|
||||
"铅",
|
||||
"锌",
|
||||
"镍",
|
||||
"锡",
|
||||
"贵金属",
|
||||
"小金属",
|
||||
]:
|
||||
futures_news_shmet_df = futures_news_shmet(symbol=item)
|
||||
print(futures_news_shmet_df)
|
||||
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/7/16 17:40
|
||||
Desc: 中国期货各合约展期收益率
|
||||
日线数据从 daily_bar 函数获取, 需要在收盘后运行
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import re
|
||||
import warnings
|
||||
|
||||
import math
|
||||
import pandas as pd
|
||||
|
||||
from akshare.futures import cons
|
||||
from akshare.futures.futures_daily_bar import get_futures_daily
|
||||
from akshare.futures.symbol_var import symbol_market, symbol_varieties
|
||||
|
||||
calendar = cons.get_calendar()
|
||||
|
||||
|
||||
def get_roll_yield(date=None, var="BB", symbol1=None, symbol2=None, df=None):
|
||||
"""
|
||||
指定交易日指定品种(主力和次主力)或任意两个合约的展期收益率
|
||||
Parameters
|
||||
------
|
||||
date: string 某一天日期 format: YYYYMMDD
|
||||
var: string 合约品种如 RB、AL 等
|
||||
symbol1: string 合约 1 如 rb1810
|
||||
symbol2: string 合约 2 如 rb1812
|
||||
df: DataFrame或None 从dailyBar得到合约价格,如果为空就在函数内部抓dailyBar,直接喂给数据可以让计算加快
|
||||
"""
|
||||
# date = "20100104"
|
||||
date = cons.convert_date(date) if date is not None else datetime.date.today()
|
||||
if date.strftime("%Y%m%d") not in calendar:
|
||||
warnings.warn("%s非交易日" % date.strftime("%Y%m%d"))
|
||||
return None
|
||||
if symbol1:
|
||||
var = symbol_varieties(symbol1)
|
||||
if not isinstance(df, pd.DataFrame):
|
||||
market = symbol_market(var)
|
||||
df = get_futures_daily(start_date=date, end_date=date, market=market)
|
||||
if var:
|
||||
df = df[
|
||||
~df["symbol"].str.contains("efp")
|
||||
] # 20200304 由于交易所获取的数据中会有比如 "CUefp",所以在这里过滤
|
||||
df = df[df["variety"] == var].sort_values(by=["open_interest"], ascending=False)
|
||||
# df["close"] = df["close"].astype("float")
|
||||
df["close"] = pd.to_numeric(df["close"])
|
||||
if len(df["close"]) < 2:
|
||||
return None
|
||||
symbol1 = df["symbol"].tolist()[0]
|
||||
symbol2 = df["symbol"].tolist()[1]
|
||||
|
||||
close1 = df["close"][df["symbol"] == symbol1].tolist()[0]
|
||||
close2 = df["close"][df["symbol"] == symbol2].tolist()[0]
|
||||
|
||||
a = re.sub(r"\D", "", symbol1)
|
||||
a_1 = int(a[:-2])
|
||||
a_2 = int(a[-2:])
|
||||
b = re.sub(r"\D", "", symbol2)
|
||||
b_1 = int(b[:-2])
|
||||
b_2 = int(b[-2:])
|
||||
c = (a_1 - b_1) * 12 + (a_2 - b_2)
|
||||
if close1 == 0 or close2 == 0:
|
||||
return False
|
||||
if c > 0:
|
||||
return math.log(close2 / close1) / c * 12, symbol2, symbol1
|
||||
else:
|
||||
return math.log(close2 / close1) / c * 12, symbol1, symbol2
|
||||
|
||||
|
||||
def get_roll_yield_bar(
|
||||
type_method: str = "var",
|
||||
var: str = "RB",
|
||||
date: str = "20201030",
|
||||
start_day: str = None,
|
||||
end_day: str = None,
|
||||
):
|
||||
"""
|
||||
展期收益率
|
||||
:param type_method: 'symbol': 获取指定交易日指定品种所有交割月合约的收盘价; 'var': 获取指定交易日所有品种两个主力合约的展期收益率(展期收益率横截面); 'date': 获取指定品种每天的两个主力合约的展期收益率(展期收益率时间序列)
|
||||
:param var: 合约品种如 "RB", "AL" 等
|
||||
:param date: 指定交易日 format: YYYYMMDD
|
||||
:param start_day: 开始日期 format:YYYYMMDD
|
||||
:param end_day: 结束日期 format:YYYYMMDD
|
||||
:return: pandas.DataFrame
|
||||
展期收益率数据(DataFrame)
|
||||
ry 展期收益率
|
||||
index 日期或品种
|
||||
"""
|
||||
date = cons.convert_date(date) if date is not None else datetime.date.today()
|
||||
start_day = (
|
||||
cons.convert_date(start_day) if start_day is not None else datetime.date.today()
|
||||
)
|
||||
end_day = (
|
||||
cons.convert_date(end_day)
|
||||
if end_day is not None
|
||||
else cons.convert_date(cons.get_latest_data_date(datetime.datetime.now()))
|
||||
)
|
||||
|
||||
if type_method == "symbol":
|
||||
df = get_futures_daily(
|
||||
start_date=date, end_date=date, market=symbol_market(var)
|
||||
)
|
||||
df = df[df["variety"] == var]
|
||||
return df
|
||||
|
||||
if type_method == "var":
|
||||
df = pd.DataFrame()
|
||||
for market in ["dce", "cffex", "shfe", "czce", "gfex"]:
|
||||
df = pd.concat(
|
||||
[
|
||||
df,
|
||||
get_futures_daily(start_date=date, end_date=date, market=market),
|
||||
]
|
||||
)
|
||||
var_list = list(set(df["variety"]))
|
||||
for i_remove in ["IO", "MO", "HO"]:
|
||||
if i_remove in var_list:
|
||||
var_list.remove(i_remove)
|
||||
df_l = pd.DataFrame()
|
||||
for var in var_list:
|
||||
ry = get_roll_yield(date, var, df=df)
|
||||
if ry:
|
||||
df_l = pd.concat(
|
||||
[
|
||||
df_l,
|
||||
pd.DataFrame(
|
||||
[ry],
|
||||
index=[var],
|
||||
columns=["roll_yield", "near_by", "deferred"],
|
||||
),
|
||||
]
|
||||
)
|
||||
df_l["date"] = date
|
||||
df_l = df_l.sort_values("roll_yield")
|
||||
return df_l
|
||||
|
||||
if type_method == "date":
|
||||
df_l = pd.DataFrame()
|
||||
while start_day <= end_day:
|
||||
try:
|
||||
ry = get_roll_yield(start_day, var)
|
||||
if ry:
|
||||
df_l = pd.concat(
|
||||
[
|
||||
df_l,
|
||||
pd.DataFrame(
|
||||
[ry],
|
||||
index=[start_day],
|
||||
columns=["roll_yield", "near_by", "deferred"],
|
||||
),
|
||||
]
|
||||
)
|
||||
except: # noqa: E722
|
||||
pass
|
||||
start_day += datetime.timedelta(days=1)
|
||||
return df_l
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
get_roll_yield_bar_range_df = get_roll_yield_bar(
|
||||
type_method="date",
|
||||
var="RB",
|
||||
start_day="20230801",
|
||||
end_day="20230810",
|
||||
)
|
||||
print(get_roll_yield_bar_range_df)
|
||||
|
||||
get_roll_yield_bar_range_df = get_roll_yield_bar(
|
||||
type_method="var",
|
||||
date="20191008",
|
||||
)
|
||||
print(get_roll_yield_bar_range_df)
|
||||
|
||||
get_roll_yield_bar_symbol = get_roll_yield_bar(type_method="var", date="20210201")
|
||||
print(get_roll_yield_bar_symbol)
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/3/31 18:00
|
||||
Desc: 国泰君安期货-交易日历数据表
|
||||
https://www.gtjaqh.com/pc/calendar.html
|
||||
"""
|
||||
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_rule(date: str = "20231205") -> pd.DataFrame:
|
||||
"""
|
||||
国泰君安期货-交易日历数据表
|
||||
https://www.gtjaqh.com/pc/calendar.html
|
||||
:param date: 需要指定为交易日, 且是近期的日期
|
||||
:type date: str
|
||||
:return: 交易日历数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings()
|
||||
url = " https://www.gtjaqh.com/pc/calendar"
|
||||
params = {"date": f"{date}"}
|
||||
r = requests.get(url, params=params, verify=False)
|
||||
big_df = pd.read_html(StringIO(r.text), header=1)[0]
|
||||
big_df["交易保证金比例"] = big_df["交易保证金比例"].str.strip("%")
|
||||
big_df["交易保证金比例"] = pd.to_numeric(big_df["交易保证金比例"], errors="coerce")
|
||||
big_df["涨跌停板幅度"] = big_df["涨跌停板幅度"].str.strip("%")
|
||||
big_df["涨跌停板幅度"] = pd.to_numeric(big_df["涨跌停板幅度"], errors="coerce")
|
||||
big_df["合约乘数"] = pd.to_numeric(big_df["合约乘数"], errors="coerce")
|
||||
big_df["最小变动价位"] = pd.to_numeric(big_df["最小变动价位"], errors="coerce")
|
||||
big_df["限价单每笔最大下单手数"] = pd.to_numeric(
|
||||
big_df["限价单每笔最大下单手数"], errors="coerce"
|
||||
)
|
||||
return big_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_rule_df = futures_rule(date="20250328")
|
||||
print(futures_rule_df)
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/1/17 19:30
|
||||
Desc: 东方财富网-期货行情-品种及交易规则
|
||||
https://portal.eastmoneyfutures.com/pages/service/jyts.html#jyrl
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from akshare.utils.cons import headers
|
||||
|
||||
|
||||
def futures_rule_em() -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-期货行情-品种及交易规则
|
||||
https://portal.eastmoneyfutures.com/pages/service/jyts.html#jyrl
|
||||
:return: 品种及交易规则
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://eastmoneyfutures.com/api/ComManage/GetPZJYInfo"
|
||||
r = requests.get(url, headers=headers)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["Data"])
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_trading_hours_em():
|
||||
"""
|
||||
东方财富网-期货交易时间
|
||||
https://qhweb.eastmoney.com/tradinghours
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_rule_em_df = futures_rule_em()
|
||||
print(futures_rule_em_df)
|
||||
@@ -0,0 +1,415 @@
|
||||
#!/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)
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/1/18 16:25
|
||||
Desc: 新加坡交易所-衍生品-历史数据-历史结算价格
|
||||
https://www.sgx.com/zh-hans/research-education/derivatives
|
||||
https://links.sgx.com/1.0.0/derivatives-daily/5888/FUTURE.zip
|
||||
"""
|
||||
|
||||
import zipfile
|
||||
from io import BytesIO
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def __fetch_ftse_index_futu(date: str = "20231108") -> int:
|
||||
"""
|
||||
新加坡交易所-日历计算
|
||||
https://wap.eastmoney.com/quote/stock/100.STI.html
|
||||
:param date: 交易日
|
||||
:type date: str
|
||||
:return: 日期计算结果
|
||||
:rtype: int
|
||||
"""
|
||||
url = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
|
||||
params = {
|
||||
"secid": "100.STI",
|
||||
"klt": "101",
|
||||
"fqt": "0",
|
||||
"lmt": "10000",
|
||||
"end": date,
|
||||
"iscca": "1",
|
||||
"fields1": "f1,f2,f3,f4,f5,f6,f7,f8",
|
||||
"fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64",
|
||||
"ut": "f057cbcbce2a86e2866ab8877db1d059",
|
||||
"forcect": "1",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame([item.split(",") for item in data_json["data"]["klines"]])
|
||||
temp_df.columns = [
|
||||
"date",
|
||||
"-",
|
||||
"open",
|
||||
"close",
|
||||
"high",
|
||||
"low",
|
||||
"volume",
|
||||
"amount",
|
||||
"_",
|
||||
"-",
|
||||
"open",
|
||||
"close",
|
||||
"high",
|
||||
"low",
|
||||
]
|
||||
num = temp_df["date"].index[-1] + 791
|
||||
return num
|
||||
|
||||
|
||||
def futures_settlement_price_sgx(date: str = "20231107") -> pd.DataFrame:
|
||||
"""
|
||||
新加坡交易所-衍生品-历史数据-历史结算价格
|
||||
https://www.sgx.com/zh-hans/research-education/derivatives
|
||||
:param date: 交易日
|
||||
:type date: str
|
||||
:return: 所有期货品种的在指定交易日的历史结算价格
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
num = __fetch_ftse_index_futu(date)
|
||||
url = f"https://links.sgx.com/1.0.0/derivatives-daily/{num}/FUTURE.zip"
|
||||
r = requests.get(url)
|
||||
with zipfile.ZipFile(BytesIO(r.content)) as file:
|
||||
with file.open(file.namelist()[0]) as my_file:
|
||||
data = my_file.read().decode()
|
||||
if file.namelist()[0].endswith("txt"):
|
||||
data_df = pd.read_table(StringIO(data))
|
||||
else:
|
||||
data_df = pd.read_csv(StringIO(data))
|
||||
return data_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_settlement_price_sgx_df = futures_settlement_price_sgx(date="20240110")
|
||||
print(futures_settlement_price_sgx_df)
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/3/21 12:00
|
||||
Desc: 东方财富网-数据中心-现货与股票
|
||||
https://data.eastmoney.com/ifdata/xhgp.html
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
from akshare.utils import demjson
|
||||
|
||||
|
||||
def futures_spot_stock(symbol: str = "能源") -> pd.DataFrame:
|
||||
"""
|
||||
东方财富网-数据中心-现货与股票
|
||||
https://data.eastmoney.com/ifdata/xhgp.html
|
||||
:param symbol: choice of {'能源', '化工', '塑料', '纺织', '有色', '钢铁', '建材', '农副'}
|
||||
:type symbol: str
|
||||
:return: 现货与股票上下游对应数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
map_dict = {
|
||||
"能源": 0,
|
||||
"化工": 1,
|
||||
"塑料": 2,
|
||||
"纺织": 3,
|
||||
"有色": 4,
|
||||
"钢铁": 5,
|
||||
"建材": 6,
|
||||
"农副": 7,
|
||||
}
|
||||
url = "https://data.eastmoney.com/ifdata/xhgp.html"
|
||||
headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,"
|
||||
"image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"Host": "data.eastmoney.com",
|
||||
"Pragma": "no-cache",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
|
||||
"(KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
|
||||
}
|
||||
r = requests.get(url, headers=headers)
|
||||
data_text = r.text
|
||||
temp_json = demjson.decode(
|
||||
data_text[
|
||||
data_text.find("pagedata") : data_text.find(
|
||||
"/newstatic/js/common/emdataview.js"
|
||||
)
|
||||
]
|
||||
.strip("pagedata= ")
|
||||
.strip(';\n </script>\n <script src="')
|
||||
)
|
||||
date_list = list(temp_json["dates"].values())
|
||||
temp_json = temp_json["datas"]
|
||||
temp_df = temp_json[map_dict.get(symbol)]
|
||||
temp_df = pd.DataFrame(temp_df["list"])
|
||||
xyyh_list = [
|
||||
"-" if item == [] else ", ".join([inner_item["name"] for inner_item in item])
|
||||
for item in temp_df["xyyhs"].tolist()
|
||||
]
|
||||
scs_list = [
|
||||
"-" if item == [] else ", ".join([inner_item["name"] for inner_item in item])
|
||||
for item in temp_df["scss"].tolist()
|
||||
]
|
||||
temp_df["scss"] = scs_list
|
||||
temp_df["xyyhs"] = xyyh_list
|
||||
temp_df.columns = [
|
||||
"商品名称",
|
||||
date_list[0],
|
||||
date_list[1],
|
||||
date_list[2],
|
||||
date_list[3],
|
||||
date_list[4],
|
||||
"最新价格",
|
||||
"近半年涨跌幅",
|
||||
"生产商",
|
||||
"下游用户",
|
||||
]
|
||||
temp_df[date_list[0]] = pd.to_numeric(temp_df[date_list[0]], errors="coerce")
|
||||
temp_df[date_list[1]] = pd.to_numeric(temp_df[date_list[1]], errors="coerce")
|
||||
temp_df[date_list[2]] = pd.to_numeric(temp_df[date_list[2]], errors="coerce")
|
||||
temp_df[date_list[3]] = pd.to_numeric(temp_df[date_list[3]], errors="coerce")
|
||||
temp_df["最新价格"] = pd.to_numeric(temp_df["最新价格"], errors="coerce")
|
||||
temp_df["近半年涨跌幅"] = pd.to_numeric(temp_df["近半年涨跌幅"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_spot_stock_df = futures_spot_stock(symbol="能源")
|
||||
print(futures_spot_stock_df)
|
||||
|
||||
for sector in ["能源", "化工", "塑料", "纺织", "有色", "钢铁", "建材", "农副"]:
|
||||
futures_spot_stock_df = futures_spot_stock(symbol=sector)
|
||||
print(futures_spot_stock_df)
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/4/24 18:10
|
||||
Desc: 上海期货交易所指定交割仓库库存周报
|
||||
https://datacenter.jin10.com/reportType/dc_shfe_weekly_stock
|
||||
https://tsite.shfe.com.cn/statements/dataview.html?paramid=kx
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_stock_shfe_js(date: str = "20240419") -> pd.DataFrame:
|
||||
"""
|
||||
金十财经-上海期货交易所指定交割仓库库存周报
|
||||
https://datacenter.jin10.com/reportType/dc_shfe_weekly_stock
|
||||
:param date: 交易日; 库存周报只在每周的最后一个交易日公布数据
|
||||
:type date: str
|
||||
:return: 库存周报
|
||||
:rtype: pandas.Series
|
||||
"""
|
||||
headers = {
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/107.0.0.0 Safari/537.36",
|
||||
"x-app-id": "rU6QIu7JHe2gOUeR",
|
||||
"x-csrf-token": "x-csrf-token",
|
||||
"x-version": "1.0.0",
|
||||
}
|
||||
url = "https://datacenter-api.jin10.com/reports/list"
|
||||
params = {
|
||||
"category": "stock",
|
||||
"date": "-".join([date[:4], date[4:6], date[6:]]),
|
||||
"attr_id": "1",
|
||||
}
|
||||
r = requests.get(url, params=params, headers=headers)
|
||||
data_json = r.json()
|
||||
columns_list = [item["name"] for item in data_json["data"]["keys"]]
|
||||
temp_df = pd.DataFrame(data_json["data"]["values"], columns=columns_list)
|
||||
for item in columns_list[1:]:
|
||||
temp_df[item] = pd.to_numeric(temp_df[item], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_stock_shfe_js_df = futures_stock_shfe_js(date="20240419")
|
||||
print(futures_stock_shfe_js_df)
|
||||
@@ -0,0 +1,340 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/1/22 20:30
|
||||
Desc: 期货-期转现-交割
|
||||
"""
|
||||
|
||||
from io import StringIO, BytesIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_to_spot_shfe(date: str = "202312") -> pd.DataFrame:
|
||||
"""
|
||||
上海期货交易所-期转现
|
||||
https://tsite.shfe.com.cn/statements/dataview.html?paramid=kx
|
||||
1、铜、铜(BC)、铝、锌、铅、镍、锡、螺纹钢、线材、热轧卷板、天然橡胶、20号胶、低硫燃料油、燃料油、石油沥青、纸浆、不锈钢的数量单位为:吨;黄金的数量单位为:克;白银的数量单位为:千克;原油的数量单位为:桶。
|
||||
2、交割量、期转现量为单向计算。
|
||||
:param date: 年月
|
||||
:type date: str
|
||||
:return: 上海期货交易所期转现
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"https://tsite.shfe.com.cn/data/instrument/ExchangeDelivery{date}.dat"
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/100.0.4896.127 Safari/537.36",
|
||||
}
|
||||
r = requests.get(url, headers=headers)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["ExchangeDelivery"])
|
||||
temp_df.columns = [
|
||||
"_",
|
||||
"日期",
|
||||
"交割量",
|
||||
"_",
|
||||
"期转现量",
|
||||
"合约",
|
||||
"_",
|
||||
"_",
|
||||
]
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"日期",
|
||||
"合约",
|
||||
"交割量",
|
||||
"期转现量",
|
||||
]
|
||||
]
|
||||
temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
|
||||
temp_df["交割量"] = pd.to_numeric(temp_df["交割量"], errors="coerce")
|
||||
temp_df["期转现量"] = pd.to_numeric(temp_df["期转现量"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_delivery_dce(date: str = "202312") -> pd.DataFrame:
|
||||
"""
|
||||
大连商品交易所-交割统计
|
||||
http://www.dce.com.cn/dalianshangpin/xqsj/tjsj26/jgtj/jgsj/index.html
|
||||
:param date: 交割日期
|
||||
:type date: str
|
||||
:return: 大连商品交易所-交割统计
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "http://www.dce.com.cn/publicweb/quotesdata/delivery.html"
|
||||
params = {
|
||||
"deliveryQuotes.variety": "all",
|
||||
"year": "",
|
||||
"month": "",
|
||||
"deliveryQuotes.begin_month": date,
|
||||
"deliveryQuotes.end_month": str(int(date) + 1),
|
||||
}
|
||||
headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"Pragma": "no-cache",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
|
||||
}
|
||||
r = requests.post(url, params=params, headers=headers)
|
||||
temp_df = pd.read_html(StringIO(r.text))[0]
|
||||
temp_df["交割日期"] = (
|
||||
temp_df["交割日期"].astype(str).str.split(".", expand=True).iloc[:, 0]
|
||||
)
|
||||
temp_df = temp_df[~temp_df["品种"].str.contains("小计|总计")]
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
temp_df["交割日期"] = pd.to_datetime(temp_df["交割日期"], errors="coerce").dt.date
|
||||
temp_df["交割量"] = pd.to_numeric(temp_df["交割量"], errors="coerce")
|
||||
temp_df["交割金额"] = pd.to_numeric(temp_df["交割金额"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_to_spot_dce(date: str = "202312") -> pd.DataFrame:
|
||||
"""
|
||||
大连商品交易所-期转现
|
||||
http://www.dce.com.cn/dalianshangpin/xqsj/tjsj26/jgtj/qzxcx/index.html
|
||||
:param date: 期转现日期
|
||||
:type date: str
|
||||
:return: 大连商品交易所-期转现
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "http://www.dce.com.cn/publicweb/quotesdata/ftsDeal.html"
|
||||
params = {
|
||||
"ftsDealQuotes.variety": "all",
|
||||
"year": "",
|
||||
"month": "",
|
||||
"ftsDealQuotes.begin_month": date,
|
||||
"ftsDealQuotes.end_month": date,
|
||||
}
|
||||
r = requests.post(url, params=params)
|
||||
temp_df = pd.read_html(StringIO(r.text))[0]
|
||||
temp_df["期转现发生日期"] = (
|
||||
temp_df["期转现发生日期"].astype(str).str.split(".", expand=True).iloc[:, 0]
|
||||
)
|
||||
temp_df = temp_df[~temp_df["合约代码"].str.contains("小计|总计")]
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
temp_df["期转现发生日期"] = pd.to_datetime(
|
||||
temp_df["期转现发生日期"], errors="coerce"
|
||||
).dt.date
|
||||
temp_df["期转现数量"] = pd.to_numeric(temp_df["期转现数量"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_delivery_match_dce(symbol: str = "a") -> pd.DataFrame:
|
||||
"""
|
||||
大连商品交易所-交割配对表
|
||||
http://www.dce.com.cn/dalianshangpin/xqsj/tjsj26/jgtj/jgsj/index.html
|
||||
:param symbol: 交割品种
|
||||
:type symbol: str
|
||||
:return: 大连商品交易所-交割配对表
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "http://www.dce.com.cn/publicweb/quotesdata/deliveryMatch.html"
|
||||
params = {
|
||||
"deliveryMatchQuotes.variety": symbol,
|
||||
"contract.contract_id": "all",
|
||||
"contract.variety_id": symbol,
|
||||
}
|
||||
r = requests.post(url, params=params)
|
||||
temp_df = pd.read_html(StringIO(r.text))[0]
|
||||
temp_df["配对日期"] = (
|
||||
temp_df["配对日期"].astype(str).str.split(".", expand=True).iloc[:, 0]
|
||||
)
|
||||
temp_df = temp_df.iloc[:-1, :]
|
||||
temp_df["配对日期"] = pd.to_datetime(temp_df["配对日期"], errors="coerce").dt.date
|
||||
temp_df["配对手数"] = pd.to_numeric(temp_df["配对手数"], errors="coerce")
|
||||
temp_df["交割结算价"] = pd.to_numeric(temp_df["交割结算价"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_to_spot_czce(date: str = "20231228") -> pd.DataFrame:
|
||||
"""
|
||||
郑州商品交易所-期转现统计
|
||||
http://www.czce.com.cn/cn/jysj/qzxtj/H770311index_1.htm
|
||||
:param date: 年月日
|
||||
:type date: str
|
||||
:return: 郑州商品交易所-期转现统计
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataTrdtrades.xls"
|
||||
headers = {
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"Host": "www.czce.com.cn",
|
||||
"Pragma": "no-cache",
|
||||
"Referer": "http://www.czce.com.cn/",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
|
||||
}
|
||||
r = requests.get(url, headers=headers)
|
||||
r.encoding = "utf-8"
|
||||
temp_df = pd.read_excel(BytesIO(r.content), skiprows=1)
|
||||
|
||||
temp_df.columns = [
|
||||
"合约代码",
|
||||
"合约数量",
|
||||
]
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"合约代码",
|
||||
"合约数量",
|
||||
]
|
||||
]
|
||||
temp_df["合约数量"] = temp_df["合约数量"].astype(str).str.replace(",", "")
|
||||
temp_df["合约数量"] = pd.to_numeric(temp_df["合约数量"], errors="coerce")
|
||||
temp_df = temp_df[~temp_df["合约代码"].str.contains("小计|合计")]
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_delivery_match_czce(date: str = "20210106") -> pd.DataFrame:
|
||||
"""
|
||||
郑州商品交易所-交割配对
|
||||
http://www.czce.com.cn/cn/jysj/jgpd/H770308index_1.htm
|
||||
:param date: 年月日
|
||||
:type date: str
|
||||
:return: 郑州商品交易所-交割配对
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataDelsettle.xls"
|
||||
r = requests.get(url)
|
||||
r.encoding = "utf-8"
|
||||
temp_df = pd.read_excel(BytesIO(r.content), skiprows=0)
|
||||
index_flag = temp_df[temp_df.iloc[:, 0].str.contains("配对日期")].index.values
|
||||
big_df = pd.DataFrame()
|
||||
for i, item in enumerate(index_flag):
|
||||
try:
|
||||
temp_inner_df = temp_df[index_flag[i] + 1 : index_flag[i + 1]]
|
||||
except: # noqa: E722
|
||||
temp_inner_df = temp_df[index_flag[i] + 1 :]
|
||||
temp_inner_df.columns = temp_inner_df.iloc[0, :]
|
||||
temp_inner_df = temp_inner_df.iloc[1:-1, :]
|
||||
temp_inner_df.reset_index(drop=True, inplace=True)
|
||||
date_contract_str = (
|
||||
temp_df[temp_df.iloc[:, 0].str.contains("配对日期")].iloc[:, 0].values[i]
|
||||
)
|
||||
inner_date = date_contract_str.split(":")[1].split(" ")[0]
|
||||
symbol = date_contract_str.split(":")[-1]
|
||||
temp_inner_df["配对日期"] = inner_date
|
||||
temp_inner_df["合约代码"] = symbol
|
||||
big_df = pd.concat([big_df, temp_inner_df], ignore_index=True)
|
||||
|
||||
big_df.columns = [
|
||||
"卖方会员",
|
||||
"卖方会员-会员简称",
|
||||
"买方会员",
|
||||
"买方会员-会员简称",
|
||||
"交割量",
|
||||
"配对日期",
|
||||
"合约代码",
|
||||
]
|
||||
big_df["交割量"] = big_df["交割量"].str.replace(",", "")
|
||||
big_df["交割量"] = pd.to_numeric(big_df["交割量"])
|
||||
return big_df
|
||||
|
||||
|
||||
def futures_delivery_czce(date: str = "20210112") -> pd.DataFrame:
|
||||
"""
|
||||
郑州商品交易所-月度交割查询
|
||||
http://www.czce.com.cn/cn/jysj/ydjgcx/H770316index_1.htm
|
||||
:param date: 年月日
|
||||
:type date: str
|
||||
:return: 郑州商品交易所-月度交割查询
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataSettlematched.xls"
|
||||
r = requests.get(url)
|
||||
r.encoding = "utf-8"
|
||||
temp_df = pd.read_excel(BytesIO(r.content), skiprows=1)
|
||||
temp_df.columns = [
|
||||
"品种",
|
||||
"交割数量",
|
||||
"交割额",
|
||||
]
|
||||
temp_df["交割数量"] = temp_df["交割数量"].astype(str).str.replace(",", "")
|
||||
temp_df["交割额"] = temp_df["交割额"].astype(str).str.replace(",", "")
|
||||
temp_df["交割数量"] = pd.to_numeric(temp_df["交割数量"], errors="coerce")
|
||||
temp_df["交割额"] = pd.to_numeric(temp_df["交割额"], errors="coerce")
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_delivery_shfe(date: str = "202312") -> pd.DataFrame:
|
||||
"""
|
||||
上海期货交易所-交割情况表
|
||||
https://tsite.shfe.com.cn/statements/dataview.html?paramid=kx
|
||||
注意: 日期 -> 月度统计 -> 下拉到交割情况表
|
||||
:param date: 年月日
|
||||
:type date: str
|
||||
:return: 上海期货交易所-交割情况表
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = f"https://tsite.shfe.com.cn/data/dailydata/{date}monthvarietystatistics.dat"
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/100.0.4896.127 Safari/537.36",
|
||||
}
|
||||
r = requests.get(url, headers=headers)
|
||||
r.encoding = "utf-8"
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["o_curdelivery"])
|
||||
temp_df.columns = [
|
||||
"品种",
|
||||
"品种代码",
|
||||
"_",
|
||||
"交割量-本月",
|
||||
"交割量-比重",
|
||||
"交割量-本年累计",
|
||||
"交割量-累计同比",
|
||||
]
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"品种",
|
||||
"交割量-本月",
|
||||
"交割量-比重",
|
||||
"交割量-本年累计",
|
||||
"交割量-累计同比",
|
||||
]
|
||||
]
|
||||
temp_df["交割量-本月"] = pd.to_numeric(temp_df["交割量-本月"], errors="coerce")
|
||||
temp_df["交割量-比重"] = pd.to_numeric(temp_df["交割量-比重"], errors="coerce")
|
||||
temp_df["交割量-本年累计"] = pd.to_numeric(
|
||||
temp_df["交割量-本年累计"], errors="coerce"
|
||||
)
|
||||
temp_df["交割量-累计同比"] = pd.to_numeric(
|
||||
temp_df["交割量-累计同比"], errors="coerce"
|
||||
)
|
||||
return temp_df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_to_spot_dce_df = futures_to_spot_dce(date="202312")
|
||||
print(futures_to_spot_dce_df)
|
||||
|
||||
futures_to_spot_shfe_df = futures_to_spot_shfe(date="202312")
|
||||
print(futures_to_spot_shfe_df)
|
||||
|
||||
futures_to_spot_czce_df = futures_to_spot_czce(date="20210112")
|
||||
print(futures_to_spot_czce_df)
|
||||
|
||||
futures_delivery_dce_df = futures_delivery_dce(date="202101")
|
||||
print(futures_delivery_dce_df)
|
||||
|
||||
futures_delivery_monthly_czce_df = futures_delivery_czce(date="20251014")
|
||||
print(futures_delivery_monthly_czce_df)
|
||||
|
||||
futures_delivery_shfe_df = futures_delivery_shfe(date="202312")
|
||||
print(futures_delivery_shfe_df)
|
||||
|
||||
futures_delivery_match_dce_df = futures_delivery_match_dce(symbol="a")
|
||||
print(futures_delivery_match_dce_df)
|
||||
|
||||
futures_delivery_match_czce_df = futures_delivery_match_czce(date="20210106")
|
||||
print(futures_delivery_match_czce_df)
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/7/1 16:30
|
||||
Desc: 期货-仓单日报
|
||||
上海期货交易所-仓单日报
|
||||
https://tsite.shfe.com.cn/statements/dataview.html?paramid=dailystock
|
||||
郑州商品交易所-交易数据-仓单日报
|
||||
http://www.czce.com.cn/cn/jysj/cdrb/H770310index_1.htm
|
||||
大连商品交易所-行情数据-统计数据-日统计-仓单日报
|
||||
http://www.dce.com.cn/dalianshangpin/xqsj/tjsj26/rtj/cdrb/index.html
|
||||
广州期货交易所-行情数据-仓单日报
|
||||
http://www.gfex.com.cn/gfex/cdrb/hqsj_tjsj.shtml
|
||||
"""
|
||||
|
||||
import re
|
||||
from io import BytesIO, StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def futures_warehouse_receipt_czce(date: str = "20251103") -> dict:
|
||||
"""
|
||||
郑州商品交易所-交易数据-仓单日报
|
||||
http://www.czce.com.cn/cn/jysj/cdrb/H770310index_1.htm
|
||||
:param date: 交易日, e.g., "20200702"
|
||||
:type date: str
|
||||
:return: 指定日期的仓单日报数据
|
||||
:rtype: dict
|
||||
"""
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
if int(date) > 20251101:
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataWhsheet.xlsx"
|
||||
else:
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataWhsheet.xls"
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/83.0.4103.116 Safari/537.36"
|
||||
}
|
||||
r = requests.get(url, verify=False, headers=headers)
|
||||
temp_df = pd.read_excel(BytesIO(r.content))
|
||||
index_list = temp_df[temp_df.iloc[:, 0].str.find("品种") == 0.0].index.to_list()
|
||||
index_list.append(len(temp_df))
|
||||
big_dict = {}
|
||||
for inner_index in range(len(index_list) - 1):
|
||||
inner_df = temp_df[index_list[inner_index] : index_list[inner_index + 1]]
|
||||
inner_key = re.findall(pattern=r"[a-zA-Z]+", string=inner_df.iloc[0, 0])[0]
|
||||
inner_df = inner_df.iloc[1:, :]
|
||||
inner_df.dropna(axis=0, how="all", inplace=True)
|
||||
inner_df.dropna(axis=1, how="all", inplace=True)
|
||||
inner_df.columns = inner_df.iloc[0, :].to_list()
|
||||
inner_df = inner_df.iloc[1:, :]
|
||||
inner_df.reset_index(inplace=True, drop=True)
|
||||
big_dict[inner_key] = inner_df
|
||||
return big_dict
|
||||
|
||||
|
||||
def futures_warehouse_receipt_dce(date: str = "20251027") -> pd.DataFrame:
|
||||
"""
|
||||
大连商品交易所-行情数据-统计数据-日统计-仓单日报
|
||||
http://www.dce.com.cn/dce/channel/list/187.html
|
||||
:param date: 交易日, e.g., "20200702"
|
||||
:type date: str
|
||||
:return: 指定日期的仓单日报数据
|
||||
:rtype: dict
|
||||
"""
|
||||
url = "http://www.dce.com.cn/dcereport/publicweb/dailystat/wbillWeeklyQuotes"
|
||||
payload = {
|
||||
"tradeDate": date,
|
||||
"varietyId": "all",
|
||||
}
|
||||
r = requests.post(url, json=payload)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"]["entityList"])
|
||||
temp_df.rename(
|
||||
columns={
|
||||
"variety": "品种名称",
|
||||
"whAbbr": "仓库/分库",
|
||||
"deliveryAbbr": "可选提货地点/分库-数量",
|
||||
"lastWbillQty": "昨日仓单量(手)",
|
||||
"wbillQty": "今日仓单量(手)",
|
||||
"diff": "增减(手)",
|
||||
"varietyOrder": "品种代码",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"品种代码",
|
||||
"品种名称",
|
||||
"仓库/分库",
|
||||
"可选提货地点/分库-数量",
|
||||
"昨日仓单量(手)",
|
||||
"今日仓单量(手)",
|
||||
"增减(手)",
|
||||
]
|
||||
]
|
||||
return temp_df
|
||||
|
||||
|
||||
def futures_shfe_warehouse_receipt(date: str = "20200702") -> dict:
|
||||
"""
|
||||
上海期货交易所指定交割仓库期货仓单日报
|
||||
https://tsite.shfe.com.cn/statements/dataview.html?paramid=dailystock¶mdate=20200703
|
||||
:param date: 交易日, e.g., "20200702"
|
||||
:type date: str
|
||||
:return: 指定日期的仓单日报数据
|
||||
:rtype: dict
|
||||
"""
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/83.0.4103.116 Safari/537.36"
|
||||
}
|
||||
url = (
|
||||
f"https://www.shfe.com.cn/data/tradedata/future/dailydata/{date}dailystock.dat"
|
||||
)
|
||||
if date >= "20140519":
|
||||
r = requests.get(url, headers=headers)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["o_cursor"])
|
||||
temp_df["VARNAME"] = temp_df["VARNAME"].str.split(r"$", expand=True).iloc[:, 0]
|
||||
temp_df["REGNAME"] = temp_df["REGNAME"].str.split(r"$", expand=True).iloc[:, 0]
|
||||
temp_df["WHABBRNAME"] = (
|
||||
temp_df["WHABBRNAME"].str.split(r"$", expand=True).iloc[:, 0]
|
||||
)
|
||||
big_dict = {}
|
||||
for item in set(temp_df["VARNAME"]):
|
||||
big_dict[item] = temp_df[temp_df["VARNAME"] == item]
|
||||
else:
|
||||
url = f"https://www.shfe.com.cn/data/tradedata/future/dailydata/{date}dailystock.html"
|
||||
r = requests.get(url, headers=headers)
|
||||
temp_df = pd.read_html(StringIO(r.text))[0]
|
||||
index_list = temp_df[
|
||||
temp_df.iloc[:, 3].str.contains("单位:") == 1
|
||||
].index.to_list()
|
||||
big_dict = {}
|
||||
for inner_index in range(len(index_list)):
|
||||
temp_index_start = index_list[inner_index]
|
||||
if (inner_index + 1) >= len(index_list):
|
||||
if temp_df.iloc[-1, 0].startswith("注:"):
|
||||
temp_index_end = len(temp_df) - 1
|
||||
else:
|
||||
temp_index_end = len(temp_df)
|
||||
else:
|
||||
temp_index_end = index_list[inner_index + 1]
|
||||
inner_df = temp_df[temp_index_start:temp_index_end]
|
||||
inner_df.reset_index(inplace=True, drop=True)
|
||||
inner_key = inner_df.iloc[0, 0]
|
||||
inner_df.columns = inner_df.iloc[1].to_list()
|
||||
inner_df = inner_df[2:]
|
||||
inner_df.reset_index(inplace=True, drop=True)
|
||||
big_dict[inner_key] = inner_df
|
||||
return big_dict
|
||||
|
||||
|
||||
def futures_gfex_warehouse_receipt(date: str = "20240122") -> dict:
|
||||
"""
|
||||
广州期货交易所-行情数据-仓单日报
|
||||
http://www.gfex.com.cn/gfex/cdrb/hqsj_tjsj.shtml
|
||||
:param date: 交易日, e.g., "20240122"
|
||||
:type date: str
|
||||
:return: 指定日期的仓单日报数据
|
||||
:rtype: dict
|
||||
"""
|
||||
url = "http://www.gfex.com.cn/u/interfacesWebTdWbillWeeklyQuotes/loadList"
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/83.0.4103.116 Safari/537.36"
|
||||
}
|
||||
payload = {"gen_date": date}
|
||||
r = requests.post(url=url, data=payload, headers=headers)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"])
|
||||
symbol_list = list(
|
||||
set([item.upper() for item in temp_df["varietyOrder"].tolist() if item != ""])
|
||||
)
|
||||
temp_df.rename(
|
||||
columns={
|
||||
"varietyOrder": "symbol",
|
||||
"variety": "品种",
|
||||
"whAbbr": "仓库/分库",
|
||||
"lastWbillQty": "昨日仓单量",
|
||||
"wbillQty": "今日仓单量",
|
||||
"regWbillQty": "增减",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
temp_df = temp_df[
|
||||
[
|
||||
"symbol",
|
||||
"whType",
|
||||
"品种",
|
||||
"仓库/分库",
|
||||
"昨日仓单量",
|
||||
"今日仓单量",
|
||||
"增减",
|
||||
]
|
||||
]
|
||||
temp_df["whType"] = pd.to_numeric(temp_df["whType"], errors="coerce")
|
||||
temp_df.dropna(
|
||||
subset=["whType"], how="any", axis=0, ignore_index=True, inplace=True
|
||||
)
|
||||
big_dict = dict()
|
||||
for symbol in symbol_list:
|
||||
inner_temp_df = temp_df[temp_df["symbol"] == symbol.lower()].copy()
|
||||
inner_temp_df = inner_temp_df[
|
||||
[
|
||||
"品种",
|
||||
"仓库/分库",
|
||||
"昨日仓单量",
|
||||
"今日仓单量",
|
||||
"增减",
|
||||
]
|
||||
]
|
||||
inner_temp_df["昨日仓单量"] = pd.to_numeric(
|
||||
inner_temp_df["昨日仓单量"], errors="coerce"
|
||||
)
|
||||
inner_temp_df["今日仓单量"] = pd.to_numeric(
|
||||
inner_temp_df["今日仓单量"], errors="coerce"
|
||||
)
|
||||
inner_temp_df["增减"] = pd.to_numeric(inner_temp_df["增减"], errors="coerce")
|
||||
inner_temp_df.reset_index(inplace=True, drop=True)
|
||||
big_dict[symbol] = inner_temp_df
|
||||
return big_dict
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
futures_warehouse_receipt_czce_df = futures_warehouse_receipt_czce(date="20251014")
|
||||
print(futures_warehouse_receipt_czce_df)
|
||||
|
||||
futures_warehouse_receipt_dce_df = futures_warehouse_receipt_dce(date="20251014")
|
||||
print(futures_warehouse_receipt_dce_df)
|
||||
|
||||
futures_shfe_warehouse_receipt_df = futures_shfe_warehouse_receipt(date="20200702")
|
||||
print(futures_shfe_warehouse_receipt_df)
|
||||
|
||||
futures_shfe_warehouse_receipt_df = futures_shfe_warehouse_receipt(date="20140516")
|
||||
print(futures_shfe_warehouse_receipt_df)
|
||||
|
||||
futures_gfex_warehouse_receipt_df = futures_gfex_warehouse_receipt(date="20240122")
|
||||
print(futures_gfex_warehouse_receipt_df)
|
||||
|
||||
futures_gfex_warehouse_receipt_df = futures_gfex_warehouse_receipt(date="20260226")
|
||||
print(futures_gfex_warehouse_receipt_df)
|
||||
@@ -0,0 +1,728 @@
|
||||
#!/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)
|
||||
@@ -0,0 +1,670 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/7/21 15:00
|
||||
Desc: 每日注册仓单数据
|
||||
大连商品交易所, 上海期货交易所, 郑州商品交易所, 广州期货交易所
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import re
|
||||
import warnings
|
||||
from io import BytesIO
|
||||
from typing import List
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
from akshare.futures import cons
|
||||
from akshare.futures.requests_fun import requests_link, pandas_read_html_link
|
||||
from akshare.futures.symbol_var import chinese_to_english
|
||||
|
||||
calendar = cons.get_calendar()
|
||||
shfe_20100126 = pd.DataFrame(
|
||||
{
|
||||
"var": ["CU", "AL", "ZN", "RU", "FU", "AU", "RB", "WR"],
|
||||
"receipt": [29783, 285396, 187713, 116435, 376200, 12, 145648, 0],
|
||||
}
|
||||
)
|
||||
shfe_20101029 = pd.DataFrame(
|
||||
{
|
||||
"var": ["CU", "AL", "ZN", "RU", "FU", "AU", "RB", "WR"],
|
||||
"receipt": [39214, 359729, 182562, 25990, 313600, 27, 36789, 0],
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def get_dce_receipt(date: str = None, vars_list: List = cons.contract_symbols):
|
||||
"""
|
||||
大连商品交易所-注册仓单数据
|
||||
http://www.dce.com.cn/dce/channel/list/187.html
|
||||
:param date: 开始日期: YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象, 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如 RB, AL等列表, 为空时为所有商品数据从 20060106开始,每周五更新仓单数据。直到20090407起,每交易日都更新仓单数据
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
return warnings.warn("vars_list: 必须是列表")
|
||||
date = cons.convert_date(date) if date is not None else datetime.date.today()
|
||||
if date.strftime("%Y%m%d") not in calendar:
|
||||
warnings.warn(f"{date.strftime('%Y%m%d')}非交易日")
|
||||
return None
|
||||
url = "http://www.dce.com.cn/dcereport/publicweb/dailystat/wbillWeeklyQuotes"
|
||||
payload = {
|
||||
"tradeDate": date.strftime("%Y%m%d"),
|
||||
"varietyId": "all",
|
||||
}
|
||||
r = requests.post(url, json=payload)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"]["entityList"])
|
||||
records = pd.DataFrame()
|
||||
for x in temp_df.to_dict(orient="records"):
|
||||
if isinstance(x["variety"], str):
|
||||
if x["variety"][-2:] == "小计":
|
||||
var = x["variety"][:-2]
|
||||
temp_data = {
|
||||
"var": chinese_to_english(var),
|
||||
"receipt": int(x["wbillQty"]),
|
||||
"receipt_chg": int(x["diff"]),
|
||||
"date": date.strftime("%Y%m%d"),
|
||||
}
|
||||
records = pd.concat([records, pd.DataFrame(temp_data, index=[0])])
|
||||
|
||||
if len(records.index) != 0:
|
||||
records.index = records["var"]
|
||||
vars_in_market = [i for i in vars_list if i in records.index]
|
||||
records = records.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_shfe_receipt_1(
|
||||
date: str = None, vars_list: List = cons.contract_symbols
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
上海期货交易所-注册仓单数据-类型1
|
||||
适用 20081006 至 20140518(包括)、20100126、20101029日期交易所格式混乱,直接回复脚本中 pandas.DataFrame, 20100416、20130821日期交易所数据丢失
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如RB、AL等列表为空时为所有商品
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据-类型1
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
raise warnings.warn("symbol_list: 必须是列表")
|
||||
date = (
|
||||
cons.convert_date(date).strftime("%Y%m%d")
|
||||
if date is not None
|
||||
else datetime.date.today()
|
||||
)
|
||||
if date not in calendar:
|
||||
warnings.warn(f"{date.strftime('%Y%m%d')}非交易日")
|
||||
return pd.DataFrame()
|
||||
if date == "20100126":
|
||||
shfe_20100126["date"] = date
|
||||
return shfe_20100126
|
||||
elif date == "20101029":
|
||||
shfe_20101029["date"] = date
|
||||
return shfe_20101029
|
||||
elif date in ["20100416", "20130821"]:
|
||||
print("20100416、20130821交易所数据丢失")
|
||||
return pd.DataFrame()
|
||||
else:
|
||||
var_list = [
|
||||
"天然橡胶",
|
||||
"沥青仓库",
|
||||
"沥青厂库",
|
||||
"热轧卷板",
|
||||
"燃料油",
|
||||
"白银",
|
||||
"线材",
|
||||
"螺纹钢",
|
||||
"铅",
|
||||
"铜",
|
||||
"铝",
|
||||
"锌",
|
||||
"黄金",
|
||||
"锡",
|
||||
"镍",
|
||||
]
|
||||
url = cons.SHFE_RECEIPT_URL_1 % date
|
||||
data = pandas_read_html_link(url)[0]
|
||||
indexes = [x for x in data.index if (data[0].tolist()[x] in var_list)]
|
||||
last_index = [x for x in data.index if "注" in str(data[0].tolist()[x])][0] - 1
|
||||
records = pd.DataFrame()
|
||||
for i in list(range(len(indexes))):
|
||||
if i != len(indexes) - 1:
|
||||
data_cut = data.loc[indexes[i] : indexes[i + 1] - 1, :]
|
||||
else:
|
||||
data_cut = data.loc[indexes[i] : last_index, :]
|
||||
data_cut = data_cut.fillna(method="pad")
|
||||
data_dict = dict()
|
||||
data_dict["var"] = chinese_to_english(data_cut[0].tolist()[0])
|
||||
data_dict["receipt"] = int(data_cut[2].tolist()[-1])
|
||||
data_dict["receipt_chg"] = int(data_cut[3].tolist()[-1])
|
||||
data_dict["date"] = date
|
||||
records = pd.concat([records, pd.DataFrame(data_dict, index=[0])])
|
||||
if len(records.index) != 0:
|
||||
records.index = records["var"]
|
||||
vars_in_market = [i for i in vars_list if i in records.index]
|
||||
records = records.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_shfe_receipt_2(
|
||||
date: str = None, vars_list: List = cons.contract_symbols
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
上海期货交易所-注册仓单数据-类型2
|
||||
适用 20140519(包括)-至今
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如 RB、AL 等列表 为空时为所有商品
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
raise warnings.warn("symbol_list: 必须是列表")
|
||||
date = (
|
||||
cons.convert_date(date).strftime("%Y%m%d")
|
||||
if date is not None
|
||||
else datetime.date.today()
|
||||
)
|
||||
if date not in calendar:
|
||||
warnings.warn("%s 非交易日" % date.strftime("%Y%m%d"))
|
||||
return pd.DataFrame()
|
||||
url = cons.SHFE_RECEIPT_URL_20250701 % date
|
||||
r = requests_link(url, encoding="utf-8", headers=cons.shfe_headers)
|
||||
try:
|
||||
context = r.json()
|
||||
except: # noqa
|
||||
return pd.DataFrame()
|
||||
data = pd.DataFrame(context["o_cursor"])
|
||||
if len(data.columns) < 1:
|
||||
return pd.DataFrame()
|
||||
records = pd.DataFrame()
|
||||
for var in set(data["VARNAME"].tolist()):
|
||||
data_cut = data[data["VARNAME"] == var]
|
||||
if "BC" in var:
|
||||
data_dict = {
|
||||
"var": "BC",
|
||||
"receipt": int(data_cut["WRTWGHTS"].tolist()[-1]),
|
||||
"receipt_chg": int(data_cut["WRTCHANGE"].tolist()[-1]),
|
||||
"date": date,
|
||||
}
|
||||
else:
|
||||
data_dict = {
|
||||
"var": chinese_to_english(re.sub(r"\W|[a-zA-Z]", "", var)),
|
||||
"receipt": int(data_cut["WRTWGHTS"].tolist()[-1]),
|
||||
"receipt_chg": int(data_cut["WRTCHANGE"].tolist()[-1]),
|
||||
"date": date,
|
||||
}
|
||||
records = pd.concat([records, pd.DataFrame(data_dict, index=[0])])
|
||||
temp_records = (
|
||||
records.groupby("var")[["receipt", "receipt_chg"]].sum().reset_index()
|
||||
)
|
||||
temp_records["date"] = date
|
||||
records = temp_records
|
||||
if len(records.index) != 0:
|
||||
records.index = records["var"]
|
||||
vars_in_market = [i for i in vars_list if i in records.index]
|
||||
records = records.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_shfe_receipt_3(
|
||||
date: str = None, vars_list: List = cons.contract_symbols
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
上海期货交易所-注册仓单数据-类型2
|
||||
适用 20140519(包括)-至今
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如 RB、AL 等列表 为空时为所有商品
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
raise warnings.warn("symbol_list: 必须是列表")
|
||||
date = (
|
||||
cons.convert_date(date).strftime("%Y%m%d")
|
||||
if date is not None
|
||||
else datetime.date.today()
|
||||
)
|
||||
if date not in calendar:
|
||||
warnings.warn("%s 非交易日" % date.strftime("%Y%m%d"))
|
||||
return pd.DataFrame()
|
||||
url = f"https://www.shfe.com.cn/data/tradedata/future/stockdata/dailystock_{date}/ZH/all.html"
|
||||
r = requests.get(url, headers=cons.shfe_headers)
|
||||
from io import StringIO
|
||||
|
||||
temp_tables = pd.read_html(StringIO(r.text))
|
||||
len(temp_tables)
|
||||
records = pd.DataFrame()
|
||||
for table_num in range(1, len(temp_tables)):
|
||||
temp_df = pd.read_html(StringIO(r.text))[table_num]
|
||||
data_dict = {
|
||||
"var": chinese_to_english(temp_df.iloc[0, 1]),
|
||||
"receipt": int(temp_df.iloc[-1, 2]),
|
||||
"receipt_chg": int(temp_df.iloc[-1, 3]),
|
||||
"date": date,
|
||||
}
|
||||
records = pd.concat([records, pd.DataFrame(data_dict, index=[0])])
|
||||
temp_records = (
|
||||
records.groupby("var")[["receipt", "receipt_chg"]].sum().reset_index()
|
||||
)
|
||||
temp_records["date"] = date
|
||||
records = temp_records
|
||||
if len(records.index) != 0:
|
||||
records.index = records["var"]
|
||||
vars_in_market = [i for i in vars_list if i in records.index]
|
||||
records = records.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_czce_receipt_1(date: str = None, vars_list: List = cons.contract_symbols):
|
||||
"""
|
||||
郑州商品交易所-注册仓单数据
|
||||
适用 20080222 至 20100824(包括)
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: list
|
||||
:type vars_list: 合约品种如 CF、TA 等列表 为空时为所有商品
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
date = (
|
||||
cons.convert_date(date).strftime("%Y%m%d")
|
||||
if date is not None
|
||||
else datetime.date.today()
|
||||
)
|
||||
if date not in calendar:
|
||||
warnings.warn("%s非交易日" % date.strftime("%Y%m%d"))
|
||||
return None
|
||||
if date == "20090820":
|
||||
return pd.DataFrame()
|
||||
url = cons.CZCE_RECEIPT_URL_1 % date
|
||||
r = requests_link(url, encoding="utf-8", headers=cons.shfe_headers)
|
||||
context = r.text
|
||||
data = pd.read_html(context)[1]
|
||||
records = pd.DataFrame()
|
||||
indexes = [x for x in data.index if "品种:" in str(data[0].tolist()[x])]
|
||||
ends = [x for x in data.index if "总计" in str(data[0].tolist()[x])]
|
||||
for i in list(range(len(indexes))):
|
||||
if i != len(indexes) - 1:
|
||||
data_cut = data.loc[indexes[i] : ends[i], :]
|
||||
data_cut = data_cut.fillna(method="pad")
|
||||
else:
|
||||
data_cut = data.loc[indexes[i] :, :]
|
||||
data_cut = data_cut.fillna(method="pad")
|
||||
if "PTA" in data_cut[0].tolist()[0]:
|
||||
var = "TA"
|
||||
else:
|
||||
var = chinese_to_english(re.sub(r"[A-Z]+", "", data_cut[0].tolist()[0][3:]))
|
||||
if var == "CF":
|
||||
receipt = data_cut[6].tolist()[-1]
|
||||
receipt_chg = data_cut[7].tolist()[-1]
|
||||
else:
|
||||
receipt = data_cut[5].tolist()[-1]
|
||||
receipt_chg = data_cut[6].tolist()[-1]
|
||||
data_dict = {
|
||||
"var": var,
|
||||
"receipt": int(receipt),
|
||||
"receipt_chg": int(receipt_chg),
|
||||
"date": date,
|
||||
}
|
||||
records = pd.concat([records, pd.DataFrame(data_dict, index=[0])])
|
||||
if len(records.index) != 0:
|
||||
records.index = records["var"]
|
||||
vars_in_market = [i for i in vars_list if i in records.index]
|
||||
records = records.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_czce_receipt_2(date: str = None, vars_list: List = cons.contract_symbols):
|
||||
"""
|
||||
郑州商品交易所-注册仓单数据
|
||||
http://www.czce.com.cn/cn/jysj/cdrb/H770310index_1.htm
|
||||
适用 20100825(包括) - 20151111(包括)
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如 CF、TA 等列表为空时为所有商品
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
return warnings.warn("symbol_list: 必须是列表")
|
||||
date = (
|
||||
cons.convert_date(date).strftime("%Y%m%d")
|
||||
if date is not None
|
||||
else datetime.date.today()
|
||||
)
|
||||
if date not in calendar:
|
||||
warnings.warn("%s非交易日" % date.strftime("%Y%m%d"))
|
||||
return None
|
||||
url = cons.CZCE_RECEIPT_URL_2 % (date[:4], date)
|
||||
r = requests.get(url)
|
||||
r.encoding = "utf-8"
|
||||
data = pd.read_html(r.text)[3:]
|
||||
records = pd.DataFrame()
|
||||
for data_cut in data:
|
||||
if len(data_cut.columns) > 3:
|
||||
last_indexes = [
|
||||
x for x in data_cut.index if "注:" in str(data_cut[0].tolist()[x])
|
||||
]
|
||||
if len(last_indexes) > 0:
|
||||
last_index = last_indexes[0] - 1
|
||||
data_cut = data_cut.loc[:last_index, :]
|
||||
if "PTA" in data_cut[0].tolist()[0]:
|
||||
var = "TA"
|
||||
else:
|
||||
strings = data_cut[0].tolist()[0]
|
||||
string = strings.split(" ")[0][3:]
|
||||
var = chinese_to_english(re.sub(r"[A-Z]+", "", string))
|
||||
data_cut.columns = data_cut.T[1].tolist()
|
||||
receipt = data_cut["仓单数量"].tolist()[-1]
|
||||
receipt_chg = data_cut["当日增减"].tolist()[-1]
|
||||
data_dict = {
|
||||
"var": var,
|
||||
"receipt": int(receipt),
|
||||
"receipt_chg": int(receipt_chg),
|
||||
"date": date,
|
||||
}
|
||||
records = pd.concat([records, pd.DataFrame(data_dict, index=[0])])
|
||||
if len(records.index) != 0:
|
||||
records.index = records["var"]
|
||||
vars_in_market = [i for i in vars_list if i in records.index]
|
||||
records = records.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_czce_receipt_3(
|
||||
date: str = None, vars_list: List = cons.contract_symbols
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
郑州商品交易所-注册仓单数据
|
||||
适用 20151008-至今
|
||||
http://www.czce.com.cn/cn/jysj/cdrb/H770310index_1.htm
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如 CF、TA 等列表为空时为所有商品
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
print("vars_list: 必须是列表")
|
||||
return pd.DataFrame()
|
||||
date = (
|
||||
cons.convert_date(date).strftime("%Y%m%d")
|
||||
if date is not None
|
||||
else datetime.date.today()
|
||||
)
|
||||
if date not in calendar:
|
||||
warnings.warn("%s非交易日" % date.strftime("%Y%m%d"))
|
||||
return pd.DataFrame()
|
||||
if int(date) > 20251101:
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataWhsheet.xlsx"
|
||||
else:
|
||||
url = f"http://www.czce.com.cn/cn/DFSStaticFiles/Future/{date[:4]}/{date}/FutureDataWhsheet.xls"
|
||||
r = requests_link(url, encoding="utf-8", headers=cons.shfe_headers)
|
||||
temp_df = pd.read_excel(BytesIO(r.content))
|
||||
temp_df = temp_df[
|
||||
[
|
||||
bool(1 - item)
|
||||
for item in [
|
||||
item if item is not pd.NA else False
|
||||
for item in temp_df.iloc[:, 0].str.contains("非农产品")
|
||||
]
|
||||
]
|
||||
]
|
||||
temp_df.reset_index(inplace=True, drop=True)
|
||||
range_list_one = list(
|
||||
temp_df[
|
||||
[
|
||||
item if not pd.isnull(item) else False
|
||||
for item in temp_df.iloc[:, 0].str.contains("品种")
|
||||
]
|
||||
].index
|
||||
)
|
||||
range_list_two = list(
|
||||
temp_df[
|
||||
[
|
||||
item if not pd.isnull(item) else False
|
||||
for item in temp_df.iloc[:, 0].str.contains("品种")
|
||||
]
|
||||
].index
|
||||
)[1:]
|
||||
range_list_two.append(None)
|
||||
symbol_list = []
|
||||
receipt_list = []
|
||||
receipt_chg_list = []
|
||||
records = pd.DataFrame()
|
||||
for page in range(len(range_list_one)):
|
||||
inner_df = temp_df[range_list_one[page] : range_list_two[page]]
|
||||
reg = re.compile(r"[A-Z]+")
|
||||
try:
|
||||
symbol = reg.findall(inner_df.iloc[0, 0])[0]
|
||||
except: # noqa
|
||||
continue
|
||||
symbol_list.append(symbol)
|
||||
inner_df.columns = inner_df.iloc[1, :]
|
||||
inner_df = inner_df.iloc[2:, :]
|
||||
inner_df = inner_df.dropna(axis=1, how="all")
|
||||
if symbol == "PTA":
|
||||
try:
|
||||
receipt_list.append(
|
||||
inner_df["仓单数量(完税)"].iloc[-1]
|
||||
+ int(inner_df["仓单数量(保税)"].iloc[-1])
|
||||
) # 20210316 TA 分为保税和完税
|
||||
except: # noqa
|
||||
receipt_list.append(0)
|
||||
elif symbol == "MA":
|
||||
try:
|
||||
try:
|
||||
receipt_list.append(
|
||||
inner_df["仓单数量(完税)"].iloc[-2]
|
||||
+ int(inner_df["仓单数量(保税)"].iloc[-2])
|
||||
) # 20210316 MA 分为保税和完税
|
||||
except: # noqa
|
||||
receipt_list.append(
|
||||
inner_df["仓单数量(完税)"].iloc[-2]
|
||||
) # 处理 MA 的特殊格式
|
||||
except: # noqa
|
||||
receipt_list.append(0)
|
||||
else:
|
||||
try:
|
||||
receipt_list.append(inner_df["仓单数量"].iloc[-1])
|
||||
except: # noqa
|
||||
receipt_list.append(0)
|
||||
if symbol == "MA":
|
||||
receipt_chg_list.append(inner_df["当日增减"].iloc[-2])
|
||||
else:
|
||||
receipt_chg_list.append(inner_df["当日增减"].iloc[-1])
|
||||
data_df = pd.DataFrame(
|
||||
[symbol_list, receipt_list, receipt_chg_list, [date] * len(receipt_chg_list)]
|
||||
).T
|
||||
data_df.columns = ["var", "receipt", "receipt_chg", "date"]
|
||||
temp_list = data_df["var"].tolist()
|
||||
data_df["var"] = [item if item != "PTA" else "TA" for item in temp_list]
|
||||
if len(data_df.index) != 0:
|
||||
data_df.index = data_df["var"]
|
||||
vars_in_market = [i for i in vars_list if i in data_df.index]
|
||||
records = data_df.loc[vars_in_market, :]
|
||||
return records.reset_index(drop=True)
|
||||
|
||||
|
||||
def get_gfex_receipt(
|
||||
date: str = None, vars_list: List = cons.contract_symbols
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
广州期货交易所-注册仓单数据
|
||||
http://www.gfex.com.cn/gfex/cdrb/hqsj_tjsj.shtml
|
||||
:param date: 开始日期 format:YYYY-MM-DD 或 YYYYMMDD 或 datetime.date对象 为空时为当天
|
||||
:type date: str
|
||||
:param vars_list: 合约品种如 SI 等列表为空时为所有商品
|
||||
:type vars_list: list
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
raise warnings.warn("vars_list: 必须是列表")
|
||||
date = cons.convert_date(date) if date is not None else datetime.date.today()
|
||||
if date.strftime("%Y%m%d") not in calendar:
|
||||
warnings.warn(f"{date.strftime('%Y%m%d')}非交易日")
|
||||
return pd.DataFrame()
|
||||
url = "http://www.gfex.com.cn/u/interfacesWebTdWbillWeeklyQuotes/loadList"
|
||||
payload = {"gen_date": date.isoformat().replace("-", "")}
|
||||
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)
|
||||
data_json = r.json()
|
||||
temp_df = pd.DataFrame(data_json["data"])
|
||||
temp_df = temp_df[temp_df["variety"].str.contains("小计")]
|
||||
result_df = temp_df[["wbillQty", "diff"]].copy()
|
||||
if result_df.empty:
|
||||
return pd.DataFrame()
|
||||
|
||||
result_df.loc[:, "date"] = date.isoformat().replace("-", "")
|
||||
result_df.loc[:, "var"] = [
|
||||
item.upper() for item in temp_df["varietyOrder"].tolist()
|
||||
]
|
||||
result_df.reset_index(drop=True, inplace=True)
|
||||
result_df.rename(
|
||||
columns={
|
||||
"wbillQty": "receipt",
|
||||
"diff": "receipt_chg",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
result_df = result_df[["var", "receipt", "receipt_chg", "date"]]
|
||||
result_df.set_index(keys=["var"], inplace=True)
|
||||
if "LC" not in result_df.index:
|
||||
vars_list.remove("LC")
|
||||
if "PS" not in result_df.index:
|
||||
vars_list.remove("PS")
|
||||
result_df = result_df.loc[vars_list, :]
|
||||
result_df.reset_index(inplace=True)
|
||||
return result_df
|
||||
|
||||
|
||||
def get_receipt(
|
||||
start_date: str = None,
|
||||
end_date: str = None,
|
||||
vars_list: List = cons.contract_symbols,
|
||||
):
|
||||
"""
|
||||
大宗商品-注册仓单数据
|
||||
: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 vars_list: 合约品种如 RB、AL 等列表为空时为所有商品
|
||||
:type vars_list: str
|
||||
:return: 注册仓单数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if not isinstance(vars_list, list):
|
||||
return warnings.warn("vars_list: 必须是列表")
|
||||
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()))
|
||||
)
|
||||
records = pd.DataFrame()
|
||||
while start_date <= end_date:
|
||||
if start_date.strftime("%Y%m%d") not in calendar:
|
||||
warnings.warn(f"{start_date.strftime('%Y%m%d')} 非交易日")
|
||||
else:
|
||||
print(start_date)
|
||||
for market, market_vars in cons.market_exchange_symbols.items():
|
||||
f = None
|
||||
if market == "dce":
|
||||
if start_date >= datetime.date(2009, 4, 7):
|
||||
f = get_dce_receipt
|
||||
else:
|
||||
print("20090407 起,大连商品交易所每个交易日更新仓单数据")
|
||||
f = None
|
||||
elif market == "shfe":
|
||||
if (
|
||||
datetime.date(2008, 10, 6)
|
||||
<= start_date
|
||||
<= datetime.date(2014, 5, 16)
|
||||
):
|
||||
f = get_shfe_receipt_1
|
||||
elif (
|
||||
datetime.date(2014, 5, 16)
|
||||
<= start_date
|
||||
<= datetime.date(2025, 11, 17)
|
||||
):
|
||||
f = get_shfe_receipt_2
|
||||
elif start_date > datetime.date(2025, 11, 17):
|
||||
f = get_shfe_receipt_3
|
||||
else:
|
||||
f = None
|
||||
print("20081006 起,上海期货交易所每个交易日更新仓单数据")
|
||||
elif market == "gfex":
|
||||
if start_date > datetime.date(2022, 12, 22):
|
||||
f = get_gfex_receipt
|
||||
else:
|
||||
f = None
|
||||
print("20081006 起,上海期货交易所每个交易日更新仓单数据")
|
||||
elif market == "czce":
|
||||
if (
|
||||
datetime.date(2008, 3, 3)
|
||||
<= start_date
|
||||
<= datetime.date(2010, 8, 24)
|
||||
):
|
||||
f = get_czce_receipt_1
|
||||
elif (
|
||||
datetime.date(2010, 8, 24)
|
||||
< start_date
|
||||
<= datetime.date(2015, 11, 11)
|
||||
):
|
||||
f = get_czce_receipt_2
|
||||
elif start_date > datetime.date(2015, 11, 11):
|
||||
f = get_czce_receipt_3
|
||||
else:
|
||||
f = None
|
||||
print("20080303 起,郑州商品交易所每个交易日更新仓单数据")
|
||||
get_vars = [var for var in vars_list if var in market_vars]
|
||||
if market != "cffex" and get_vars != []:
|
||||
if f is not None:
|
||||
records = pd.concat([records, f(start_date, get_vars)])
|
||||
start_date += datetime.timedelta(days=1)
|
||||
records.reset_index(drop=True, inplace=True)
|
||||
if records.empty:
|
||||
return records
|
||||
return records
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
get_receipt_df = get_receipt(
|
||||
start_date="20260130", end_date="20260130", vars_list=["RB"]
|
||||
)
|
||||
print(get_receipt_df)
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2023/9/15 19:00
|
||||
Desc: 请求网站内容的函数: 在链接失败后可重复 20 次
|
||||
"""
|
||||
|
||||
import time
|
||||
from io import StringIO
|
||||
from typing import Dict
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def requests_link(
|
||||
url: str,
|
||||
encoding: str = "utf-8",
|
||||
method: str = "get",
|
||||
data: Dict = None,
|
||||
headers: Dict = None,
|
||||
):
|
||||
"""
|
||||
利用 requests 请求网站, 爬取网站内容, 如网站链接失败, 可重复爬取 20 次
|
||||
:param url: string 网站地址
|
||||
:param encoding: string 编码类型: "utf-8", "gbk", "gb2312"
|
||||
:param method: string 访问方法: "get", "post"
|
||||
:param data: dict 上传数据: 键值对
|
||||
:param headers: dict 游览器请求头: 键值对
|
||||
:return: requests.response 爬取返回内容: response
|
||||
"""
|
||||
i = 0
|
||||
while True:
|
||||
try:
|
||||
if method == "get":
|
||||
r = requests.get(url, timeout=20, headers=headers)
|
||||
r.encoding = encoding
|
||||
return r
|
||||
elif method == "post":
|
||||
r = requests.post(url, timeout=20, data=data, headers=headers)
|
||||
r.encoding = encoding
|
||||
return r
|
||||
else:
|
||||
raise ValueError("请提供正确的请求方式")
|
||||
except: # noqa: E722
|
||||
i += 1
|
||||
print(f"第{str(i)}次链接失败, 最多尝试 20 次")
|
||||
time.sleep(5)
|
||||
if i > 20:
|
||||
return None
|
||||
|
||||
|
||||
def pandas_read_html_link(
|
||||
url: str,
|
||||
encoding: str = "utf-8",
|
||||
method: str = "get",
|
||||
data: Dict = None,
|
||||
headers: Dict = None,
|
||||
):
|
||||
"""
|
||||
利用 pandas 提供的 read_html 函数来直接提取网页中的表格内容, 如网站链接失败, 可重复爬取 20 次
|
||||
:param url: string 网站地址
|
||||
:param encoding: string 编码类型: "utf-8", "gbk", "gb2312"
|
||||
:param method: string 访问方法: "get", "post"
|
||||
:param data: dict 上传数据: 键值对
|
||||
:param headers: dict 游览器请求头: 键值对
|
||||
:return: requests.response 爬取返回内容: response
|
||||
"""
|
||||
i = 0
|
||||
while True:
|
||||
try:
|
||||
if method == "get":
|
||||
r = requests.get(url, timeout=20, headers=headers)
|
||||
r.encoding = encoding
|
||||
r = pd.read_html(StringIO(r.text), encoding=encoding)
|
||||
return r
|
||||
elif method == "post":
|
||||
r = requests.post(url, timeout=20, data=data, headers=headers)
|
||||
r.encoding = encoding
|
||||
r = pd.read_html(StringIO(r.text), encoding=encoding)
|
||||
return r
|
||||
else:
|
||||
raise ValueError("请提供正确的请求方式")
|
||||
except requests.exceptions.Timeout as e:
|
||||
i += 1
|
||||
print(f"第{str(i)}次链接失败, 最多尝试20次", e)
|
||||
time.sleep(5)
|
||||
if i > 20:
|
||||
return None
|
||||
@@ -0,0 +1,359 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2025/7/21 15:00
|
||||
Desc: 期货品种映射表
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from akshare.futures import cons
|
||||
|
||||
|
||||
def symbol_varieties(contract_code: str):
|
||||
"""
|
||||
查找到具体合约代码, 返回大写字母的品种名称
|
||||
:param contract_code: ru1801
|
||||
:return: RU
|
||||
"""
|
||||
symbol_detail = "".join(re.findall(r"\D", contract_code)).upper().strip()
|
||||
if symbol_detail == "PTA":
|
||||
symbol_detail = "TA"
|
||||
return symbol_detail
|
||||
|
||||
|
||||
def symbol_market(symbol_detail: str = "SC"):
|
||||
"""
|
||||
映射出市场代码
|
||||
:param symbol_detail:
|
||||
:return:
|
||||
"""
|
||||
var_item = symbol_varieties(symbol_detail)
|
||||
for market_item, contract_items in cons.market_exchange_symbols.items():
|
||||
if var_item in contract_items:
|
||||
return market_item
|
||||
|
||||
|
||||
def find_chinese(chinese_string: str):
|
||||
"""
|
||||
查找中文字符
|
||||
:param chinese_string: 中文字符串
|
||||
:return:
|
||||
"""
|
||||
p = re.compile(r"[\u4e00-\u9fa5]")
|
||||
res = re.findall(p, chinese_string)
|
||||
return "".join(res)
|
||||
|
||||
|
||||
def chinese_to_english(chinese_var: str):
|
||||
"""
|
||||
映射期货品种中文名称和英文缩写
|
||||
:param chinese_var: 期货品种中文名称
|
||||
:return: 对应的英文缩写
|
||||
"""
|
||||
chinese_list = [
|
||||
"橡胶",
|
||||
"天然橡胶",
|
||||
"石油沥青",
|
||||
"石油沥青(仓库)",
|
||||
"石油沥青(厂库)",
|
||||
"沥青",
|
||||
"沥青仓库",
|
||||
"沥青(仓库)",
|
||||
"沥青厂库",
|
||||
"沥青(厂库)",
|
||||
"热轧卷板",
|
||||
"热轧卷板厂库",
|
||||
"热轧卷板仓库",
|
||||
"热轧卷板(厂库)",
|
||||
"热轧卷板(仓库)",
|
||||
"热轧板卷",
|
||||
"燃料油",
|
||||
"白银",
|
||||
"线材",
|
||||
"螺纹钢",
|
||||
"螺纹钢(仓库)",
|
||||
"螺纹钢(厂库)",
|
||||
"铅",
|
||||
"铜",
|
||||
"铝",
|
||||
"锌",
|
||||
"黄金",
|
||||
"钯金",
|
||||
"锡",
|
||||
"镍",
|
||||
"纸浆",
|
||||
"纸浆(仓库)",
|
||||
"纸浆(厂库)",
|
||||
"豆一",
|
||||
"大豆",
|
||||
"豆二",
|
||||
"胶合板",
|
||||
"玉米",
|
||||
"玉米淀粉",
|
||||
"聚乙烯",
|
||||
"LLDPE",
|
||||
"LDPE",
|
||||
"豆粕",
|
||||
"豆油",
|
||||
"大豆油",
|
||||
"棕榈油",
|
||||
"纤维板",
|
||||
"鸡蛋",
|
||||
"聚氯乙烯",
|
||||
"PVC",
|
||||
"聚丙烯",
|
||||
"PP",
|
||||
"焦炭",
|
||||
"焦煤",
|
||||
"铁矿石",
|
||||
"乙二醇",
|
||||
"强麦",
|
||||
"强筋小麦",
|
||||
" 强筋小麦",
|
||||
"硬冬白麦",
|
||||
"普麦",
|
||||
"硬白小麦",
|
||||
"硬白小麦()",
|
||||
"皮棉",
|
||||
"棉花",
|
||||
"一号棉",
|
||||
"白糖",
|
||||
"PTA",
|
||||
"菜籽油",
|
||||
"菜油",
|
||||
"早籼稻",
|
||||
"早籼",
|
||||
"甲醇",
|
||||
"柴油",
|
||||
"玻璃",
|
||||
"油菜籽",
|
||||
"菜籽",
|
||||
"菜籽粕",
|
||||
"菜粕",
|
||||
"动力煤",
|
||||
"粳稻",
|
||||
"晚籼稻",
|
||||
"晚籼",
|
||||
"硅铁",
|
||||
"锰硅",
|
||||
"硬麦",
|
||||
"棉纱",
|
||||
"苹果",
|
||||
"原油",
|
||||
"中质含硫原油",
|
||||
"尿素",
|
||||
"20号胶",
|
||||
"苯乙烯",
|
||||
"不锈钢",
|
||||
"粳米",
|
||||
"20号胶20",
|
||||
"红枣",
|
||||
"不锈钢仓库",
|
||||
"不锈钢厂库",
|
||||
"不锈钢(厂库)",
|
||||
"不锈钢(仓库)",
|
||||
"纯碱",
|
||||
"液化石油气",
|
||||
"低硫燃料油",
|
||||
"纸浆仓库",
|
||||
"石油沥青厂库",
|
||||
"石油沥青仓库",
|
||||
"螺纹钢仓库",
|
||||
"螺纹钢厂库",
|
||||
"纸浆厂库",
|
||||
"低硫燃料油仓库",
|
||||
"低硫燃料油厂库",
|
||||
"低硫燃料油(仓库)",
|
||||
"低硫燃料油(厂库)",
|
||||
"短纤",
|
||||
"涤纶短纤",
|
||||
"生猪",
|
||||
"花生",
|
||||
"工业硅",
|
||||
"氧化铝",
|
||||
"丁二烯橡胶",
|
||||
"碳酸锂",
|
||||
"氧化铝仓库",
|
||||
"氧化铝厂库",
|
||||
"氧化铝(仓库)",
|
||||
"氧化铝(厂库)",
|
||||
"烧碱",
|
||||
"丁二烯橡胶仓库",
|
||||
"丁二烯橡胶厂库",
|
||||
"丁二烯橡胶(仓库)",
|
||||
"丁二烯橡胶(厂库)",
|
||||
"PX",
|
||||
"原木",
|
||||
"瓶片期货",
|
||||
"瓶片",
|
||||
"纯苯",
|
||||
"多晶硅",
|
||||
"铸造铝合金",
|
||||
"铜(BC)",
|
||||
"胶版印刷纸(仓库)",
|
||||
"胶版印刷纸(厂库)",
|
||||
"丙烯期货",
|
||||
"丙烯",
|
||||
]
|
||||
english_list = [
|
||||
"RU",
|
||||
"RU",
|
||||
"BU",
|
||||
"BU",
|
||||
"BU",
|
||||
"BU",
|
||||
"BU",
|
||||
"BU",
|
||||
"BU2",
|
||||
"BU2",
|
||||
"HC",
|
||||
"HC",
|
||||
"HC",
|
||||
"HC",
|
||||
"HC",
|
||||
"HC",
|
||||
"FU",
|
||||
"AG",
|
||||
"WR",
|
||||
"RB",
|
||||
"RB",
|
||||
"RB",
|
||||
"PB",
|
||||
"CU",
|
||||
"AL",
|
||||
"ZN",
|
||||
"AU",
|
||||
"AU",
|
||||
"SN",
|
||||
"NI",
|
||||
"SP",
|
||||
"SP",
|
||||
"SP",
|
||||
"A",
|
||||
"A",
|
||||
"B",
|
||||
"BB",
|
||||
"C",
|
||||
"CS",
|
||||
"L",
|
||||
"L",
|
||||
"L",
|
||||
"M",
|
||||
"Y",
|
||||
"Y",
|
||||
"P",
|
||||
"FB",
|
||||
"JD",
|
||||
"V",
|
||||
"V",
|
||||
"PP",
|
||||
"PP",
|
||||
"J",
|
||||
"JM",
|
||||
"I",
|
||||
"EG",
|
||||
"WH",
|
||||
"WH",
|
||||
"WH",
|
||||
"PM",
|
||||
"PM",
|
||||
"PM",
|
||||
"PM",
|
||||
"CF",
|
||||
"CF",
|
||||
"CF",
|
||||
"SR",
|
||||
"TA",
|
||||
"OI",
|
||||
"OI",
|
||||
"RI",
|
||||
"ER",
|
||||
"MA",
|
||||
"MA",
|
||||
"FG",
|
||||
"RS",
|
||||
"RS",
|
||||
"RM",
|
||||
"RM",
|
||||
"ZC",
|
||||
"JR",
|
||||
"LR",
|
||||
"LR",
|
||||
"SF",
|
||||
"SM",
|
||||
"WT",
|
||||
"CY",
|
||||
"AP",
|
||||
"SC",
|
||||
"SC",
|
||||
"UR",
|
||||
"NR",
|
||||
"EB",
|
||||
"SS",
|
||||
"RR",
|
||||
"NR",
|
||||
"CJ",
|
||||
"SS",
|
||||
"SS",
|
||||
"SS",
|
||||
"SS",
|
||||
"SA",
|
||||
"PG",
|
||||
"LU",
|
||||
"SP",
|
||||
"BU",
|
||||
"BU",
|
||||
"RB",
|
||||
"RB",
|
||||
"SP",
|
||||
"LU",
|
||||
"LU",
|
||||
"LU",
|
||||
"LU",
|
||||
"PF",
|
||||
"PF",
|
||||
"LH",
|
||||
"PK",
|
||||
"SI",
|
||||
"AO",
|
||||
"BR",
|
||||
"LC",
|
||||
"AO",
|
||||
"AO",
|
||||
"AO",
|
||||
"AO",
|
||||
"SH",
|
||||
"BR",
|
||||
"BR",
|
||||
"BR",
|
||||
"BR",
|
||||
"PX",
|
||||
"LG",
|
||||
"PR",
|
||||
"PR",
|
||||
"BZ",
|
||||
"PS",
|
||||
"AD",
|
||||
"BC",
|
||||
"OP",
|
||||
"OP",
|
||||
"PL",
|
||||
"PL",
|
||||
]
|
||||
pos = chinese_list.index(chinese_var)
|
||||
return english_list[pos]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(chinese_to_english("苹果"))
|
||||
symbol = "rb1801"
|
||||
|
||||
var = symbol_varieties("rb1808")
|
||||
print(var)
|
||||
|
||||
market = symbol_market("SP")
|
||||
print(market)
|
||||
|
||||
chi = find_chinese("a对方水电费dc大V")
|
||||
print(chi)
|
||||
Reference in New Issue
Block a user