fix(HEL-356): preserve derived limit streaks

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总管
2026-09-09 17:24:49 +08:00
co-authored by multica-agent
parent 5f343a6bae
commit c3881af708
4 changed files with 71 additions and 10 deletions
+10 -1
View File
@@ -169,7 +169,16 @@ class DailyMarketMixin:
current = item.get(key) current = item.get(key)
if incoming in (None, "", "--"): if incoming in (None, "", "--"):
continue continue
if current in (None, "", "--", 0, 0.0): # The daily fallback and the board pool can arrive at different
# times. Keep the stronger streak instead of freezing the
# provisional default at one or letting a stale pool lower it.
if key == "limit_times":
item[key] = max(
1,
int(_number(current, 1)),
int(_number(incoming, 1)),
)
elif current in (None, "", "--", 0, 0.0):
item[key] = incoming item[key] = incoming
merged.append(item) merged.append(item)
return merged return merged
+10 -2
View File
@@ -55,16 +55,24 @@ class DashboardMixin:
if not limit_rows: if not limit_rows:
limit_data_source = "derived" limit_data_source = "derived"
notices.append("涨跌停高级接口当日数据尚未更新,已使用日线数据推算。") notices.append("涨跌停高级接口当日数据尚未更新,已使用日线数据推算。")
limit_rows = self._derive_limits(trade_date, daily) limit_rows = self._derive_limits(
trade_date,
daily,
previous_limit_rows=previous_limit_rows,
)
except TushareError as exc: except TushareError as exc:
limit_data_source = "derived" limit_data_source = "derived"
notices.append(f"涨跌停高级接口不可用,已使用日线数据推算:{exc}") notices.append(f"涨跌停高级接口不可用,已使用日线数据推算:{exc}")
limit_rows = self._derive_limits(trade_date, daily)
previous_daily = self._load_daily(previous_trade_date) previous_daily = self._load_daily(previous_trade_date)
previous_limit_rows = [ previous_limit_rows = [
row for row in self._derive_limits(previous_trade_date, previous_daily) row for row in self._derive_limits(previous_trade_date, previous_daily)
if row.get("limit_type") == "U" if row.get("limit_type") == "U"
] ]
limit_rows = self._derive_limits(
trade_date,
daily,
previous_limit_rows=previous_limit_rows,
)
up_rows = [row for row in limit_rows if row.get("limit_type") == "U"] up_rows = [row for row in limit_rows if row.get("limit_type") == "U"]
down_rows = [row for row in limit_rows if row.get("limit_type") == "D"] down_rows = [row for row in limit_rows if row.get("limit_type") == "D"]
+7 -7
View File
@@ -498,8 +498,8 @@
}, },
{ {
"path": "backend/data/providers/tushare_dashboard.py", "path": "backend/data/providers/tushare_dashboard.py",
"bytes": 34777, "bytes": 35001,
"lines": 797 "lines": 805
}, },
{ {
"path": "database.py", "path": "database.py",
@@ -601,6 +601,11 @@
"bytes": 9876, "bytes": 9876,
"lines": 224 "lines": 224
}, },
{
"path": "backend/data/providers/tushare_daily.py",
"bytes": 9539,
"lines": 241
},
{ {
"path": "backend/features/market/insights_themes.py", "path": "backend/features/market/insights_themes.py",
"bytes": 9348, "bytes": 9348,
@@ -611,11 +616,6 @@
"bytes": 9139, "bytes": 9139,
"lines": 199 "lines": 199
}, },
{
"path": "backend/data/providers/tushare_daily.py",
"bytes": 9076,
"lines": 232
},
{ {
"path": "backend/data/providers/tushare_dragon_tiger.py", "path": "backend/data/providers/tushare_dragon_tiger.py",
"bytes": 9059, "bytes": 9059,
+44
View File
@@ -80,6 +80,50 @@ class LimitOverlayTests(unittest.TestCase):
self.assertEqual(rows[0]["fd_amount"], 82000000) self.assertEqual(rows[0]["fd_amount"], 82000000)
self.assertEqual(rows[0]["turnover_ratio"], 18.4) self.assertEqual(rows[0]["turnover_ratio"], 18.4)
def test_overlay_replaces_provisional_first_board_with_observed_streak(self) -> None:
mixin = DailyMarketMixin()
mixin._load_limit_lists = lambda trade_date: []
mixin.try_limit_pool = lambda trade_date: [
{"ts_code": "000737.SZ", "limit_times": 3}
]
rows = mixin._overlay_board_fields(
[{"ts_code": "000737.SZ", "limit_times": 1, "limit_type": "U"}],
"20260909",
)
self.assertEqual(rows[0]["limit_times"], 3)
def test_daily_fallback_extends_yesterday_streak(self) -> None:
mixin = DailyMarketMixin()
mixin.query = lambda *args, **kwargs: []
mixin._load_limit_lists = lambda trade_date: []
rows = mixin._derive_limits(
"20260909",
[
{
"ts_code": "000737.SZ",
"trade_date": "20260909",
"close": 11.0,
"high": 11.0,
"pct_chg": 10.0,
"amount": 100000,
}
],
price_limits=[
{"ts_code": "000737.SZ", "up_limit": 11.0, "down_limit": 9.0}
],
basic_rows=[
{"ts_code": "000737.SZ", "name": "北方铜业", "industry": "有色"}
],
previous_limit_rows=[
{"ts_code": "000737.SZ", "limit_times": 2}
],
)
self.assertEqual(rows[0]["limit_times"], 3)
class ShenwanRealtimeSourceTests(unittest.TestCase): class ShenwanRealtimeSourceTests(unittest.TestCase):
def test_transport_refuses_rt_sw_k(self) -> None: def test_transport_refuses_rt_sw_k(self) -> None: