Refactor code structure for improved readability and maintainability
This commit is contained in:
parent
b03a8f7dda
commit
5f7537a01d
|
|
@ -0,0 +1,37 @@
|
|||
============================================================
|
||||
数据质量报告 / Data Quality Report
|
||||
生成时间: 2026-06-07T16:05:29.175368
|
||||
数据源: AKShare (fund_etf_hist_em)
|
||||
============================================================
|
||||
|
||||
159995 (芯片ETF):
|
||||
日期范围: 2021-02-04 ~ 2025-05-30 (1043 天)
|
||||
原始缺失: 265 天 (17.1%)
|
||||
日均收益率: +0.000172
|
||||
日波动率: 0.021145
|
||||
最大日涨幅: +10.01%
|
||||
最大日跌幅: -9.05%
|
||||
|
||||
159819 (人工智能ETF):
|
||||
日期范围: 2021-02-04 ~ 2025-05-30 (1043 天)
|
||||
原始缺失: 421 天 (27.1%)
|
||||
日均收益率: +0.000163
|
||||
日波动率: 0.019471
|
||||
最大日涨幅: +10.07%
|
||||
最大日跌幅: -9.95%
|
||||
|
||||
516160 (新能源ETF):
|
||||
日期范围: 2021-02-04 ~ 2025-05-30 (1043 天)
|
||||
原始缺失: 510 天 (32.8%)
|
||||
日均收益率: -0.000343
|
||||
日波动率: 0.020161
|
||||
最大日涨幅: +10.07%
|
||||
最大日跌幅: -9.98%
|
||||
|
||||
159928 (消费ETF):
|
||||
日期范围: 2021-02-04 ~ 2025-05-30 (1043 天)
|
||||
原始缺失: 0 天 (0.0%)
|
||||
日均收益率: -0.000380
|
||||
日波动率: 0.015514
|
||||
最大日涨幅: +10.01%
|
||||
最大日跌幅: -9.94%
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -32,12 +32,20 @@ from datetime import datetime, timedelta
|
|||
import time
|
||||
import os
|
||||
|
||||
# ── 绕过系统代理,直连东方财富 ──
|
||||
# macOS 上的 Clash/小火箭等代理工具的出口 IP 容易被东方财富反爬封禁。
|
||||
# 设置环境变量让 requests 库对 eastmoney.com 不走代理。
|
||||
os.environ["NO_PROXY"] = os.environ.get("NO_PROXY", "") + ",eastmoney.com,eastmoneyfutures.com,10jqka.com.cn"
|
||||
os.environ["no_proxy"] = os.environ["NO_PROXY"]
|
||||
|
||||
# ── 检查 akshare 是否安装 ──
|
||||
try:
|
||||
import akshare as ak
|
||||
print(f"✓ AKShare 版本: {ak.__version__}")
|
||||
except ImportError:
|
||||
print("请先安装 AKShare: pip install akshare")
|
||||
print("❌ AKShare 未安装。请在 trading conda 环境中执行:")
|
||||
print(" conda activate trading")
|
||||
print(" pip install akshare")
|
||||
raise
|
||||
|
||||
print("=" * 68)
|
||||
|
|
@ -118,18 +126,26 @@ def fetch_etf_safe(code: str, start: str, end: str, max_retries: int = 3):
|
|||
end_date=end,
|
||||
adjust="qfq", # 前复权
|
||||
)
|
||||
time.sleep(0.5) # 礼貌限速,避免被封 IP
|
||||
return df
|
||||
except Exception as e:
|
||||
print(f" ⚠ {code} 第 {attempt+1} 次获取失败: {e}")
|
||||
err_msg = str(e)
|
||||
if "ProxyError" in err_msg or "RemoteDisconnected" in err_msg:
|
||||
wait = (attempt + 1) * 5 # 代理/连接问题,等更久
|
||||
print(f"\n ⚠ {code} 连接被拒绝 (代理/反爬),{wait}s 后重试...")
|
||||
else:
|
||||
wait = 2.0
|
||||
print(f"\n ⚠ {code} 第 {attempt+1} 次获取失败: {e}")
|
||||
if attempt < max_retries - 1:
|
||||
time.sleep(2.0)
|
||||
print(f" ✗ {code} 全部 {max_retries} 次获取失败,跳过")
|
||||
time.sleep(wait)
|
||||
print(f"\n ✗ {code} 全部 {max_retries} 次获取失败,跳过")
|
||||
return None
|
||||
|
||||
|
||||
etf_data = {}
|
||||
for code, name in ETF_UNIVERSE.items():
|
||||
for i, (code, name) in enumerate(ETF_UNIVERSE.items()):
|
||||
if i > 0:
|
||||
# 请求间隔 + 随机抖动,避免触发东方财富反爬
|
||||
time.sleep(2.0 + np.random.uniform(0, 1.5))
|
||||
print(f" 获取 {code} ({name})...", end=" ")
|
||||
df = fetch_etf_safe(code, START_DATE, END_DATE)
|
||||
if df is not None:
|
||||
|
|
@ -234,26 +250,17 @@ if index_data:
|
|||
print("\n[§4] 获取北向资金数据")
|
||||
|
||||
try:
|
||||
# 北向资金日频净流入
|
||||
north_flow = ak.stock_hsgt_north_net_flow_in_em(symbol="北上")
|
||||
if north_flow is not None and len(north_flow) > 0:
|
||||
print(f" 北向资金净流入: {north_flow.shape}")
|
||||
print(f" 列名: {list(north_flow.columns)}")
|
||||
# 标准化为通用格式
|
||||
if "date" in north_flow.columns and "value" in north_flow.columns:
|
||||
north_flow = north_flow.rename(columns={"date": "日期", "value": "净流入_亿"})
|
||||
print(f" 最新数据:\n{north_flow.tail(3)}")
|
||||
else:
|
||||
print(" 未获取到北向资金数据 (接口可能已变更)")
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
# 沪深港通历史资金流向 (更详细)
|
||||
hsgt = ak.stock_hsgt_hist_em(symbol="沪股通")
|
||||
if hsgt is not None and len(hsgt) > 0:
|
||||
print(f"\n 沪深港通历史资金: {hsgt.shape}")
|
||||
print(f" 列名: {list(hsgt.columns)}")
|
||||
print(f" 最新 3 行:\n{hsgt.tail(3)}")
|
||||
# 北向资金: stock_hsgt_hist_em 获取沪股通/深股通历史资金流向
|
||||
for market, label in [("沪股通", "沪股通(北向)"), ("深股通", "深股通(北向)")]:
|
||||
try:
|
||||
hsgt = ak.stock_hsgt_hist_em(symbol=market)
|
||||
if hsgt is not None and len(hsgt) > 0:
|
||||
print(f" {label}: {hsgt.shape}")
|
||||
print(f" 列名: {list(hsgt.columns)}")
|
||||
print(f" 最新 3 行:\n{hsgt.tail(3)}")
|
||||
time.sleep(1.5) # 避免触发反爬
|
||||
except Exception as e:
|
||||
print(f" {label} 获取失败: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f" 北向资金获取失败: {e}")
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ try:
|
|||
import tushare as ts
|
||||
print(f"✓ Tushare 版本: {ts.__version__}")
|
||||
except ImportError:
|
||||
print("请先安装 Tushare: pip install tushare")
|
||||
print("❌ Tushare 未安装。请在 trading conda 环境中执行:")
|
||||
print(" conda activate trading")
|
||||
print(" pip install tushare")
|
||||
raise
|
||||
|
||||
print("=" * 68)
|
||||
|
|
|
|||
|
|
@ -2,3 +2,6 @@ numpy
|
|||
pandas
|
||||
matplotlib
|
||||
scipy
|
||||
scikit-learn
|
||||
akshare
|
||||
tushare
|
||||
Loading…
Reference in New Issue