feat(flask): OHLCV 端点自动附加 ETF 净值和溢价率

flask_server.py:
- 当 asset_type 为 china_etf 时,自动调用 fetch_etf_with_nav
- 响应中添加 nav、premium_series、latest_premium、premium_stats

flask_api_source.py:
- 解析 ETF 数据中的净值和溢价率信息
- 将 nav_df、premium_series、premium_stats 存入 DataFrame.attrs
This commit is contained in:
2026-05-14 00:57:37 +08:00
parent d4047d4cf4
commit d62763b0bd
2 changed files with 62 additions and 0 deletions

View File

@@ -142,6 +142,30 @@ class FlaskAPIDataSource:
if 'info' in data:
df.attrs['info'] = data['info']
# ETF 数据自动附加净值和溢价率信息
if data.get('asset_type') == 'china_etf':
# 净值数据
nav_section = data.get('nav', {})
if nav_section.get('data'):
nav_df = pd.DataFrame(nav_section['data'])
if 'date' in nav_df.columns:
nav_df['date'] = pd.to_datetime(nav_df['date'])
nav_df = nav_df.set_index('date')
df.attrs['nav'] = nav_df
# 溢价率序列
if 'premium_series' in data:
df.attrs['premium_series'] = data['premium_series']
# 最新溢价率
if 'latest_premium' in data:
df.attrs['latest_premium'] = data['latest_premium']
df.attrs['premium_date'] = data.get('premium_date')
# 溢价率统计
if 'premium_stats' in data:
df.attrs['premium_stats'] = data['premium_stats']
print(f"{code}: {len(df)} 条数据 ({start_date} ~ {end_date})")
return df

View File

@@ -630,6 +630,44 @@ def get_ohlcv():
result['cached'] = is_cached
result['asset_type'] = final_type.value # 使用最终类型
# 如果是中国 ETF自动附加净值和溢价率数据
if final_type == AssetType.CHINA_ETF:
try:
f = get_fetcher()
with f:
price_df, nav_df, premium_series = f.fetch_etf_with_nav(code, start, end)
# 添加净值数据
if nav_df is not None and len(nav_df) > 0:
result['nav'] = dataframe_to_json(nav_df)
# 添加溢价率序列
if premium_series is not None and len(premium_series) > 0:
premium_data = [
{"date": date.strftime('%Y-%m-%d'), "premium": round(premium, 6)}
for date, premium in premium_series.items()
]
result['premium_series'] = premium_data
# 最新溢价率
latest_premium = premium_series.iloc[-1]
latest_date = premium_series.index[-1].strftime('%Y-%m-%d')
result['latest_premium'] = round(latest_premium, 6)
result['premium_date'] = latest_date
# 溢价率统计
result['premium_stats'] = {
"mean": round(premium_series.mean(), 6),
"std": round(premium_series.std(), 6),
"min": round(premium_series.min(), 6),
"max": round(premium_series.max(), 6),
"median": round(premium_series.median(), 6),
}
except Exception as e:
# 净值获取失败不影响主数据返回
result['nav_error'] = str(e)
# 如果用户指定了类型但与自动检测不同,显示提示
if asset_type_param and detected_type != final_type:
result['type_override'] = {