feat(selection): expose run sector aggregates and sector filter on results API
- sector_radar: add batch sector-count aggregation and sector member lookup
over the strict last-good membership snapshot (postgres + in-memory fakes)
- selection: add SelectionSectorReader port, list_sector_counts use case,
and sector_stock_codes filtering via run identity resolution; queries stay
inside the selection context per ADR 0001
- http: add GET /api/v1/selection/sectors and forward sector param on
/results and /runs/{run_id}
- fix stale positional args in pattern-scoring run tests; cover new behavior
with read-service, application, and HTTP contract tests
This commit is contained in:
@@ -136,7 +136,13 @@ class FakeStore:
|
||||
kwargs["error_message"] = error_message
|
||||
self.finished = (run_id, status, kwargs)
|
||||
|
||||
def get_run(self, run_id: str, *, query: SelectionResultQuery | None = None):
|
||||
def get_run(
|
||||
self,
|
||||
run_id: str,
|
||||
*,
|
||||
query: SelectionResultQuery | None = None,
|
||||
sector_stock_codes: Sequence[str] | None = None,
|
||||
):
|
||||
return None
|
||||
|
||||
def get_latest_run(
|
||||
@@ -145,9 +151,16 @@ class FakeStore:
|
||||
target_trade_date: date | None = None,
|
||||
*,
|
||||
query: SelectionResultQuery | None = None,
|
||||
sector_stock_codes: Sequence[str] | None = None,
|
||||
):
|
||||
return None
|
||||
|
||||
def get_run_identity(self, run_id: str):
|
||||
return None
|
||||
|
||||
def get_latest_run_identity(self, strategy: str, target_trade_date: date | None = None):
|
||||
return None
|
||||
|
||||
|
||||
class BatchStore(FakeStore):
|
||||
def __init__(self) -> None:
|
||||
@@ -427,8 +440,8 @@ def test_execute_loads_cases_once_and_scores_only_selected_stocks() -> None:
|
||||
reader,
|
||||
store,
|
||||
evaluator,
|
||||
loader,
|
||||
scorer,
|
||||
pattern_case_loader=loader,
|
||||
pattern_scorer=scorer,
|
||||
pattern_scoring_enabled=True,
|
||||
batch_size=1,
|
||||
)
|
||||
@@ -463,8 +476,8 @@ def test_execute_isolates_pattern_scoring_failure_from_selection_status() -> Non
|
||||
BatchReader(source),
|
||||
store,
|
||||
evaluator,
|
||||
loader,
|
||||
scorer,
|
||||
pattern_case_loader=loader,
|
||||
pattern_scorer=scorer,
|
||||
pattern_scoring_enabled=True,
|
||||
)
|
||||
|
||||
@@ -497,8 +510,8 @@ def test_execute_skips_pattern_dependencies_when_feature_flag_is_disabled() -> N
|
||||
BatchReader(source),
|
||||
store,
|
||||
evaluator,
|
||||
loader,
|
||||
scorer,
|
||||
pattern_case_loader=loader,
|
||||
pattern_scorer=scorer,
|
||||
pattern_scoring_enabled=False,
|
||||
)
|
||||
|
||||
@@ -535,8 +548,8 @@ def test_execute_marks_scores_failed_when_case_library_is_unavailable() -> None:
|
||||
BatchReader(source),
|
||||
store,
|
||||
evaluator,
|
||||
loader,
|
||||
scorer,
|
||||
pattern_case_loader=loader,
|
||||
pattern_scorer=scorer,
|
||||
pattern_scoring_enabled=True,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user