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
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:
36
src/main.py
36
src/main.py
@@ -22,6 +22,7 @@ from src.broker.overseas import OverseasBroker
|
|||||||
from src.config import Settings
|
from src.config import Settings
|
||||||
from src.context.aggregator import ContextAggregator
|
from src.context.aggregator import ContextAggregator
|
||||||
from src.context.layer import ContextLayer
|
from src.context.layer import ContextLayer
|
||||||
|
from src.context.scheduler import ContextScheduler
|
||||||
from src.context.store import ContextStore
|
from src.context.store import ContextStore
|
||||||
from src.core.criticality import CriticalityAssessor
|
from src.core.criticality import CriticalityAssessor
|
||||||
from src.core.priority_queue import PriorityTaskQueue
|
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:
|
async def run(settings: Settings) -> None:
|
||||||
"""Main async loop — iterate over open markets on a timer."""
|
"""Main async loop — iterate over open markets on a timer."""
|
||||||
broker = KISBroker(settings)
|
broker = KISBroker(settings)
|
||||||
@@ -782,6 +812,10 @@ async def run(settings: Settings) -> None:
|
|||||||
decision_logger = DecisionLogger(db_conn)
|
decision_logger = DecisionLogger(db_conn)
|
||||||
context_store = ContextStore(db_conn)
|
context_store = ContextStore(db_conn)
|
||||||
context_aggregator = ContextAggregator(db_conn)
|
context_aggregator = ContextAggregator(db_conn)
|
||||||
|
context_scheduler = ContextScheduler(
|
||||||
|
aggregator=context_aggregator,
|
||||||
|
store=context_store,
|
||||||
|
)
|
||||||
|
|
||||||
# V2 proactive strategy components
|
# V2 proactive strategy components
|
||||||
context_selector = ContextSelector(context_store)
|
context_selector = ContextSelector(context_store)
|
||||||
@@ -1015,6 +1049,7 @@ async def run(settings: Settings) -> None:
|
|||||||
while not shutdown.is_set():
|
while not shutdown.is_set():
|
||||||
# Wait for trading to be unpaused
|
# Wait for trading to be unpaused
|
||||||
await pause_trading.wait()
|
await pause_trading.wait()
|
||||||
|
_run_context_scheduler(context_scheduler, now=datetime.now(UTC))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await run_daily_session(
|
await run_daily_session(
|
||||||
@@ -1053,6 +1088,7 @@ async def run(settings: Settings) -> None:
|
|||||||
while not shutdown.is_set():
|
while not shutdown.is_set():
|
||||||
# Wait for trading to be unpaused
|
# Wait for trading to be unpaused
|
||||||
await pause_trading.wait()
|
await pause_trading.wait()
|
||||||
|
_run_context_scheduler(context_scheduler, now=datetime.now(UTC))
|
||||||
|
|
||||||
# Get currently open markets
|
# Get currently open markets
|
||||||
open_markets = get_open_markets(settings.enabled_market_list)
|
open_markets = get_open_markets(settings.enabled_market_list)
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
"""Tests for main trading loop integration."""
|
"""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
|
from unittest.mock import ANY, AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from src.context.layer import ContextLayer
|
from src.context.layer import ContextLayer
|
||||||
|
from src.context.scheduler import ScheduleResult
|
||||||
from src.core.risk_manager import CircuitBreakerTripped, FatFingerRejected
|
from src.core.risk_manager import CircuitBreakerTripped, FatFingerRejected
|
||||||
from src.db import init_db, log_trade
|
from src.db import init_db, log_trade
|
||||||
from src.evolution.scorecard import DailyScorecard
|
from src.evolution.scorecard import DailyScorecard
|
||||||
from src.logging.decision_logger import DecisionLogger
|
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 (
|
from src.strategy.models import (
|
||||||
DayPlaybook,
|
DayPlaybook,
|
||||||
ScenarioAction,
|
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
|
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()
|
||||||
|
|||||||
Reference in New Issue
Block a user