Merge pull request 'feat: 레거시 컨텍스트 정리 스케줄러 연결 (issue #89)' (#125) from feature/issue-89-legacy-context-cleanup into main
Some checks failed
CI / test (push) Has been cancelled

Reviewed-on: #125
This commit was merged in pull request #125.
This commit is contained in:
2026-02-14 23:38:11 +09:00
2 changed files with 49 additions and 2 deletions

View File

@@ -22,6 +22,7 @@ from src.broker.overseas import OverseasBroker
from src.config import Settings
from src.context.aggregator import ContextAggregator
from src.context.layer import ContextLayer
from src.context.scheduler import ContextScheduler
from src.context.store import ContextStore
from src.core.criticality import CriticalityAssessor
from src.core.priority_queue import PriorityTaskQueue
@@ -772,6 +773,35 @@ async def _handle_market_close(
)
def _run_context_scheduler(
scheduler: ContextScheduler, now: datetime | None = None,
) -> None:
"""Run periodic context scheduler tasks and log when anything executes."""
result = scheduler.run_if_due(now=now)
if any(
[
result.weekly,
result.monthly,
result.quarterly,
result.annual,
result.legacy,
result.cleanup,
]
):
logger.info(
(
"Context scheduler ran (weekly=%s, monthly=%s, quarterly=%s, "
"annual=%s, legacy=%s, cleanup=%s)"
),
result.weekly,
result.monthly,
result.quarterly,
result.annual,
result.legacy,
result.cleanup,
)
async def run(settings: Settings) -> None:
"""Main async loop — iterate over open markets on a timer."""
broker = KISBroker(settings)
@@ -782,6 +812,10 @@ async def run(settings: Settings) -> None:
decision_logger = DecisionLogger(db_conn)
context_store = ContextStore(db_conn)
context_aggregator = ContextAggregator(db_conn)
context_scheduler = ContextScheduler(
aggregator=context_aggregator,
store=context_store,
)
# V2 proactive strategy components
context_selector = ContextSelector(context_store)
@@ -1015,6 +1049,7 @@ async def run(settings: Settings) -> None:
while not shutdown.is_set():
# Wait for trading to be unpaused
await pause_trading.wait()
_run_context_scheduler(context_scheduler, now=datetime.now(UTC))
try:
await run_daily_session(
@@ -1053,6 +1088,7 @@ async def run(settings: Settings) -> None:
while not shutdown.is_set():
# Wait for trading to be unpaused
await pause_trading.wait()
_run_context_scheduler(context_scheduler, now=datetime.now(UTC))
# Get currently open markets
open_markets = get_open_markets(settings.enabled_market_list)

View File

@@ -1,16 +1,17 @@
"""Tests for main trading loop integration."""
from datetime import UTC, date
from datetime import UTC, date, datetime
from unittest.mock import ANY, AsyncMock, MagicMock, patch
import pytest
from src.context.layer import ContextLayer
from src.context.scheduler import ScheduleResult
from src.core.risk_manager import CircuitBreakerTripped, FatFingerRejected
from src.db import init_db, log_trade
from src.evolution.scorecard import DailyScorecard
from src.logging.decision_logger import DecisionLogger
from src.main import _handle_market_close, safe_float, trading_cycle
from src.main import _handle_market_close, _run_context_scheduler, safe_float, trading_cycle
from src.strategy.models import (
DayPlaybook,
ScenarioAction,
@@ -1295,3 +1296,13 @@ async def test_handle_market_close_without_lessons_stores_once() -> None:
)
assert reviewer.store_scorecard_in_context.call_count == 1
def test_run_context_scheduler_invokes_scheduler() -> None:
"""Scheduler helper should call run_if_due with provided datetime."""
scheduler = MagicMock()
scheduler.run_if_due = MagicMock(return_value=ScheduleResult(cleanup=True))
_run_context_scheduler(scheduler, now=datetime(2026, 2, 14, tzinfo=UTC))
scheduler.run_if_due.assert_called_once()