125 lines
4.1 KiB
Python
125 lines
4.1 KiB
Python
"""拉取玻璃FG609 7月份所有交易日的前20会员持仓排名数据"""
|
|
import akshare as ak
|
|
import pandas as pd
|
|
import time
|
|
from datetime import date, timedelta
|
|
|
|
def to_int(x):
|
|
if isinstance(x, str):
|
|
return int(x.replace(",", ""))
|
|
return int(x)
|
|
|
|
def get_rank_czce_safe(d):
|
|
"""安全调用,失败重试"""
|
|
try:
|
|
return ak.get_rank_table_czce(date=d)
|
|
except Exception as e:
|
|
print(f" [{d}] 失败: {e}")
|
|
return None
|
|
|
|
# 7月交易日(去掉周末)
|
|
trading_days = []
|
|
start = date(2026, 7, 1)
|
|
end = date(2026, 7, 23)
|
|
d = start
|
|
while d <= end:
|
|
if d.weekday() < 5: # Mon-Fri
|
|
trading_days.append(d)
|
|
d += timedelta(days=1)
|
|
|
|
print(f"共 {len(trading_days)} 个交易日")
|
|
|
|
all_data = {} # date_str -> DataFrame (FG609 member rank)
|
|
|
|
for dt in trading_days:
|
|
ds = dt.strftime("%Y%m%d")
|
|
print(f"拉取 {ds}...", end=" ", flush=True)
|
|
rank = get_rank_czce_safe(ds)
|
|
if rank and "FG609" in rank:
|
|
df = rank["FG609"].copy()
|
|
for col in ["vol", "vol_chg", "long_open_interest", "long_open_interest_chg",
|
|
"short_open_interest", "short_open_interest_chg"]:
|
|
df[col] = df[col].apply(to_int)
|
|
df = df.sort_values("rank")
|
|
all_data[ds] = df
|
|
# 摘要
|
|
total_vol = df["vol"].sum()
|
|
top1 = df.iloc[0]
|
|
top3_vol = df.head(3)["vol"].sum()
|
|
long_sum = df["long_open_interest"].sum()
|
|
short_sum = df["short_open_interest"].sum()
|
|
print(f"OK vol={total_vol/10000:.0f}万 top1={top1['vol_party_name']}({top1['vol']/10000:.0f}万) net={long_sum-short_sum:+,}")
|
|
else:
|
|
print(f"SKIP(无FG609数据)")
|
|
time.sleep(0.3)
|
|
|
|
print(f"\n成功获取 {len(all_data)} 天数据")
|
|
|
|
# ====== 汇总:逐日总成交量 & 前5会员 ======
|
|
print("\n" + "="*80)
|
|
print("【逐日汇总】FG609 前20会员成交量 & 多空净头寸")
|
|
print("="*80)
|
|
print(f"{'日期':>8} {'总成交量':>10} {'总多单':>10} {'总空单':>10} {'净头寸':>10} {'VolTop1':<18} {'VolTop1占比':>8}")
|
|
print("-"*80)
|
|
for ds in sorted(all_data.keys()):
|
|
df = all_data[ds]
|
|
tv = df["vol"].sum()
|
|
ls = df["long_open_interest"].sum()
|
|
ss = df["short_open_interest"].sum()
|
|
t1 = df.iloc[0]
|
|
share = t1["vol"] / tv * 100
|
|
d = f"{ds[:4]}-{ds[4:6]}-{ds[6:]}"
|
|
print(f"{d:>8} {tv:>10,} {ls:>10,} {ss:>10,} {ls-ss:>10,} {t1['vol_party_name']:<18} {share:>7.1f}%")
|
|
|
|
# ====== 重点会员逐日变化 ======
|
|
key_members = ["国泰君安(代客)", "东证期货(代客)", "中信期货(代客)",
|
|
"永安期货(代客)", "华泰期货(代客)", "方正中期(代客)"]
|
|
print("\n" + "="*100)
|
|
print("【重点会员逐日成交量】")
|
|
print("="*100)
|
|
header = f"{'日期':>8}"
|
|
for m in key_members:
|
|
header += f" {m:<16}"
|
|
print(header)
|
|
print("-"*100)
|
|
for ds in sorted(all_data.keys()):
|
|
df = all_data[ds]
|
|
line = f"{ds[:4]}-{ds[4:6]}-{ds[6:]:>8}"
|
|
for m in key_members:
|
|
row = df[df["vol_party_name"] == m]
|
|
if not row.empty:
|
|
vol = row.iloc[0]["vol"]
|
|
chg = row.iloc[0]["vol_chg"]
|
|
line += f" {vol:>6,}({chg:>+6,})"
|
|
else:
|
|
line += f" {'---':>16}"
|
|
print(line)
|
|
|
|
# ====== 重点会员逐日净头寸(多-空) ======
|
|
print("\n" + "="*100)
|
|
print("【重点会员逐日净头寸(多单-空单)】")
|
|
print("="*100)
|
|
header = f"{'日期':>8}"
|
|
for m in key_members:
|
|
header += f" {m:<16}"
|
|
print(header)
|
|
print("-"*100)
|
|
for ds in sorted(all_data.keys()):
|
|
df = all_data[ds]
|
|
line = f"{ds[:4]}-{ds[4:6]}-{ds[6:]:>8}"
|
|
for m in key_members:
|
|
row = df[df["vol_party_name"] == m]
|
|
if not row.empty:
|
|
r = row.iloc[0]
|
|
net = r["long_open_interest"] - r["short_open_interest"]
|
|
line += f" {net:>+8,}"
|
|
else:
|
|
# try other name columns
|
|
row_l = df[df["long_party_name"] == m]
|
|
row_s = df[df["short_party_name"] == m]
|
|
long_v = row_l.iloc[0]["long_open_interest"] if not row_l.empty else 0
|
|
short_v = row_s.iloc[0]["short_open_interest"] if not row_s.empty else 0
|
|
net = long_v - short_v
|
|
line += f" {net:>+8,}"
|
|
print(line)
|