feat(sector_radar): enhance sector radar functionality with active moneyflow and detailed metrics

- Introduced ActiveMoneyflowSource to fetch optional active-order flow, enhancing the sector radar's data capabilities.
- Updated StockFactRecord and DailyAggregateRecord to include pct_change and active_buy_net_amount_yuan for improved financial insights.
- Modified the build process to incorporate active moneyflow data without invalidating main rankings on failure.
- Enhanced the HTTP API to return detailed sector history and metrics, including pct_change and active buy metrics for members.
- Updated tests to validate the new functionality and ensure data integrity across various scenarios.
This commit is contained in:
yuxuanhui
2026-09-06 16:06:17 +08:00
parent 68282f5d46
commit 7f93d6b0f5
48 changed files with 4883 additions and 95 deletions
@@ -402,3 +402,40 @@ def test_sector_member_codes_rejects_blank_sector_code() -> None:
with pytest.raises(ValueError):
reader.sector_member_codes(TARGET_DATE, " ")
def test_history_appearance_counts_use_each_days_pool_and_metric_version() -> None:
from zhixing_server.modules.sector_radar.application.details import ReadRadarDetails
repository = InMemorySectorRadarRepository()
current_rows = _amount_rankings()
for offset, size in ((-1, 5), (0, 10), (1, 20)):
day = TARGET_DATE + timedelta(days=offset)
running = _running(f"pool-{offset}", day)
repository.create_publication(running)
repository.finish_publication(_finish(running, PublicationStatus.SUCCESS))
observations = tuple(
replace(row.observation, trade_date=day) for row in current_rows[:size]
)
repository.save_rankings(
tuple(
RankingRecord(running.publication_id, row)
for row in rank_metric_observations(observations)
)
)
reader = ReadRadarDetails(repository)
history = reader.history(TARGET_DATE, SectorType.CONCEPT, "BK0002.DC")
assert [point.amount.pool_size for point in history.points] == [5, 10]
assert [point.amount.in_top for point in history.points] == [False, True]
publication = repository.get_successful_publication(TARGET_DATE)
assert publication is not None
extra = reader.ranking_extras(publication, (current_rows[1],), RankSide.TOP)["BK0002.DC"]
assert extra.on_list_count == 1
assert extra.history_available_days == 2
old_version = replace(
current_rows[1],
observation=replace(current_rows[1].observation, metric_version="older-version"),
)
from zhixing_server.modules.sector_radar.application.details import metric_at
assert metric_at((old_version,), SectorType.CONCEPT, "BK0002.DC", MetricKind.AMOUNT).missing