fix(market-time): 非交易日的已交易分钟数按全天算, 量比不再被折算放大

trading_minutes_elapsed_from_dt 的文档写明「非交易日(周末) = 240 (视作全天,
避免量比被折算成 0)」, 但实现里没有周几判断, 只按时刻分段。

compute_enriched_today 用 `time_factor = 240 / elapsed_minutes` 把盘中部分量
折算到全天量级。周末在行情页点「手动刷新」(refresh() 不过 _market_phase 门控)
且行情源不带 quote_ts 时, 兜底会走 trading_minutes_elapsed() ——
周六 9:31 得 1 分钟 → 全市场量比 ×240, 10:00 得 30 分钟 → ×8,
signal_volume_surge(量比 ≥ 2) 整片误触发。

补上文档已声明的周末判定。
This commit is contained in:
kevin9327
2026-09-10 19:39:36 +09:00
parent bb94cd7b29
commit 2b059d4b43
2 changed files with 63 additions and 0 deletions
@@ -0,0 +1,61 @@
"""当日已交易分钟数 — 量比时间折算的分母来源。
compute_enriched_today 用 `time_factor = 240 / elapsed_minutes` 把盘中的部分
成交量折算到全天量级。周末/非交易日没有"当日已交易分钟", 必须按全天 240 算,
否则手动刷新一次行情就会把全市场量比放大 240/已过分钟数 倍, 「放量」
(vol_ratio_5d >= 2) 整片误触发。
"""
from __future__ import annotations
from datetime import datetime, timedelta, timezone
import pytest
from app.market_time import (
trading_minutes_elapsed_from_dt,
trading_minutes_elapsed_from_ts,
)
CN = timezone(timedelta(hours=8))
def _ms(dt: datetime) -> int:
return int(dt.timestamp() * 1000)
@pytest.mark.parametrize(
("moment", "label"),
[
(datetime(2026, 9, 12, 9, 31, tzinfo=CN), "周六 开盘后 1 分钟"),
(datetime(2026, 9, 12, 10, 0, tzinfo=CN), "周六 上午"),
(datetime(2026, 9, 13, 14, 0, tzinfo=CN), "周日 下午"),
],
)
def test_weekend_counts_as_a_full_session(moment, label):
assert trading_minutes_elapsed_from_dt(moment) == 240.0, label
def test_weekend_timestamp_also_counts_as_full_session():
"""行情戳落在周末 (源侧异常戳) 时同样按全天算。"""
assert trading_minutes_elapsed_from_ts(_ms(datetime(2026, 9, 12, 10, 0, tzinfo=CN))) == 240.0
@pytest.mark.parametrize(
("moment", "expected", "label"),
[
(datetime(2026, 9, 11, 9, 0, tzinfo=CN), 0.0, "周五 开盘前"),
(datetime(2026, 9, 11, 9, 31, tzinfo=CN), 1.0, "周五 9:31"),
(datetime(2026, 9, 11, 11, 30, tzinfo=CN), 120.0, "周五 午休起点"),
(datetime(2026, 9, 11, 12, 30, tzinfo=CN), 120.0, "周五 午休中"),
(datetime(2026, 9, 11, 14, 0, tzinfo=CN), 180.0, "周五 14:00"),
(datetime(2026, 9, 11, 15, 30, tzinfo=CN), 240.0, "周五 收盘后"),
],
)
def test_weekday_session_progress_unchanged(moment, expected, label):
"""交易日的分段折算不受影响 (回归保护)。"""
assert trading_minutes_elapsed_from_dt(moment) == expected, label
def test_missing_timestamp_still_counts_as_full_session():
assert trading_minutes_elapsed_from_ts(None) == 240.0
assert trading_minutes_elapsed_from_ts(0) == 240.0