fix: handle efinance index open column fallback (#1051)

* fix: handle efinance index open column fallback
This commit is contained in:
mumu
2026-04-19 22:27:25 +08:00
committed by GitHub
parent 0e8728fdcf
commit efd2bce694
3 changed files with 93 additions and 2 deletions

View File

@@ -842,7 +842,7 @@ class EfinanceFetcher(BaseFetcher):
price_col = '最新价' if '最新价' in df.columns else 'price'
pct_col = '涨跌幅' if '涨跌幅' in df.columns else 'pct_chg'
chg_col = '涨跌额' if '涨跌额' in df.columns else 'change'
open_col = '' if '开盘' in df.columns else 'open'
open_cols = [column for column in ('', '开盘', 'open') if column in df.columns]
high_col = '最高' if '最高' in df.columns else 'high'
low_col = '最低' if '最低' in df.columns else 'low'
vol_col = '成交量' if '成交量' in df.columns else 'volume'
@@ -851,6 +851,14 @@ class EfinanceFetcher(BaseFetcher):
current = safe_float(item.get(price_col, 0))
change_amount = safe_float(item.get(chg_col, 0))
open_price = 0.0
for column in open_cols:
candidate = safe_float(item.get(column), default=None)
if candidate not in (None, 0.0):
open_price = candidate
break
if open_price == 0.0 and open_cols:
open_price = safe_float(item.get(open_cols[0], 0), 0)
results.append({
'code': full_code,
@@ -858,7 +866,7 @@ class EfinanceFetcher(BaseFetcher):
'current': current,
'change': change_amount,
'change_pct': safe_float(item.get(pct_col, 0)),
'open': safe_float(item.get(open_col, 0)),
'open': open_price,
'high': safe_float(item.get(high_col, 0)),
'low': safe_float(item.get(low_col, 0)),
'prev_close': current - change_amount if current or change_amount else 0,

View File

@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
<!-- 每条独立一行追加到本段末尾,无需分类标题,合并时冲突最小 -->
- [修复] 大盘复盘链路接入 `REPORT_LANGUAGE``REPORT_LANGUAGE=en`A 股/合并复盘的 Prompt、章节标题、模板兜底文案与通知包装标题统一改为英文避免出现英文正文外包中文标题的问题。
- [修复] `EfinanceFetcher.get_main_indices()` 对东方财富指数实时行情的开盘价映射改为兼容 `今开 -> 开盘 -> open`,修复部分 `efinance` 版本下指数开盘价被读成缺失值的问题fixes #1043
- [修复] `AGENT_MAX_STEPS` 在 orchestrator 多 Agent 模式下统一明确为“默认作为各子 Agent 的步数上限而非硬覆盖TechnicalAgent 等高默认值 Agent 会被封顶、低默认值 Agent 保持原值;当用户主动调高(>10再统一覆盖所有子 Agent 采用全局值”,同时修复用户设置 12 但 TechnicalAgent 仍以默认 6 步运行并报 "Agent exceeded max steps" 的问题fixes #1026
- [修复] SpecialistSkillAgent 失败不再中断整个分析管线,改为与 intel/risk 相同的优雅降级策略
- [改进] Agent 超步数错误信息增加 AGENT_MAX_STEPS 调整提示,帮助用户自助排查

View File

@@ -0,0 +1,82 @@
import os
import sys
import types
import unittest
from unittest.mock import patch
import pandas as pd
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from data_provider.efinance_fetcher import EfinanceFetcher
class TestEfinanceMainIndices(unittest.TestCase):
def test_get_main_indices_prefers_jinkai_column_for_open_price(self):
fetcher = EfinanceFetcher()
fake_df = pd.DataFrame(
{
"股票代码": ["000001"],
"最新价": [3200.0],
"涨跌幅": [0.63],
"涨跌额": [20.0],
"今开": [3188.0],
"开盘": [0.0],
"最高": [3215.0],
"最低": [3170.0],
"成交量": [123456789],
"成交额": [9876543210.0],
"振幅": [1.2],
}
)
fake_efinance = types.SimpleNamespace(
stock=types.SimpleNamespace(get_realtime_quotes=lambda *args, **kwargs: fake_df)
)
with patch.dict(sys.modules, {"efinance": fake_efinance}):
with patch.object(fetcher, "_set_random_user_agent", return_value=None), patch.object(
fetcher, "_enforce_rate_limit", return_value=None
):
data = fetcher.get_main_indices(region="cn")
self.assertIsNotNone(data)
self.assertEqual(len(data), 1)
self.assertEqual(data[0]["code"], "sh000001")
self.assertEqual(data[0]["name"], "上证指数")
self.assertAlmostEqual(data[0]["open"], 3188.0)
self.assertAlmostEqual(data[0]["current"], 3200.0)
def test_get_main_indices_falls_back_to_kaipan_when_jinkai_is_missing(self):
fetcher = EfinanceFetcher()
fake_df = pd.DataFrame(
{
"股票代码": ["000001"],
"最新价": [3200.0],
"涨跌幅": [0.63],
"涨跌额": [20.0],
"今开": [""],
"开盘": [3186.0],
"最高": [3215.0],
"最低": [3170.0],
"成交量": [123456789],
"成交额": [9876543210.0],
"振幅": [1.2],
}
)
fake_efinance = types.SimpleNamespace(
stock=types.SimpleNamespace(get_realtime_quotes=lambda *args, **kwargs: fake_df)
)
with patch.dict(sys.modules, {"efinance": fake_efinance}):
with patch.object(fetcher, "_set_random_user_agent", return_value=None), patch.object(
fetcher, "_enforce_rate_limit", return_value=None
):
data = fetcher.get_main_indices(region="cn")
self.assertIsNotNone(data)
self.assertEqual(len(data), 1)
self.assertAlmostEqual(data[0]["open"], 3186.0)
if __name__ == "__main__":
unittest.main()