feat: 새로운 안전 규칙 및 최적화 적용을 통한 트레이딩 시스템 개선

변경 사항 (Changes):

구문 오류(Syntax error) 및 토큰 낭비를 방지하기 위해 에이전트 쉘(Agent shell)과 파이썬 코드 스니펫에 다수의 신규 안전 규칙(Safety rules)을 추가함.

스키마 검증 및 적절한 SQL 포맷팅을 보장하기 위해 임시(Ad-hoc) 데이터베이스 쿼리 작성 가이드라인을 도입함.

코드 수정 후 UI 기능이 정상 작동하는지 확인하기 위해, 백테스트 웹 서비스 재시작 및 브라우저 검증에 대한 새로운 규칙을 구현함.

시스템 전반의 무결성(Integrity)을 유지하기 위해 실전 매매(Live trading), 웹 백테스팅, 파라미터 탐색(Parameter searches) 간의 일관성 검사(Consistency checks) 체계를 확립함.

기대 효과 (Impact):

이러한 개선 사항들은 트레이딩 시스템의 견고성(Robustness)과 신뢰성을 향상시키며, 에러 발생을 최소화하고 다양한 시스템 컴포넌트 간의 원활한 상호작용을 보장함.
This commit is contained in:
Your Name
2026-07-17 01:09:09 +09:00
parent a4626e0351
commit fc27e726f9
151 changed files with 20718 additions and 6450 deletions

View File

@@ -16,11 +16,16 @@ from kis_trader.backtest.backtest_portfolio_common import (
resolve_portfolio_params,
summarize_trades,
)
from kis_trader.backtest.breakout_tick_loader import (
load_breakout_ticks_by_code,
tick_coverage_stats,
)
from kis_trader.engine.range_break_engine import (
RANGE_BREAK_STRATEGY_ID,
range_break_min_bars_required,
run_range_break_backtest,
)
from kis_trader.engine.tick_exit_common import strategy_use_tick_exit
RANGE_BREAK_STRATEGY_ID = RANGE_BREAK_STRATEGY_ID # noqa: F811 — re-export
@@ -101,6 +106,7 @@ def run_range_break_backtest_web_aligned(
max_stocks: Optional[int] = None,
total_budget_krw: Optional[float] = None,
meta_out: Optional[Dict[str, Any]] = None,
ticks_by_code: Optional[Dict[str, Dict[str, List[Dict]]]] = None,
) -> List[Dict]:
engine_params = dict(params)
engine_params["slot_money"] = float(slot_money)
@@ -115,10 +121,40 @@ def run_range_break_backtest_web_aligned(
engine_params.setdefault("scan_interval_min", 1)
engine_params.setdefault("portfolio_mode", True)
from kis_trader.backtest.backtest_env_timeline import attach_backtest_env_timeline_to_params
attach_backtest_env_timeline_to_params(engine_params, meta_out, "RANGE_BREAK")
loaded_ticks: Dict[str, Dict[str, List[Dict]]] = dict(ticks_by_code or {})
tick_meta: Dict[str, Any] = {}
if strategy_use_tick_exit(engine_params, "RANGE_BREAK_BACKTEST_USE_TICK_EXIT", default=True):
if not loaded_ticks and meta_out is not None:
start_key = str(meta_out.get("start_key") or "")
end_key = str(meta_out.get("end_key") or "")
db = meta_out.get("db")
if db and start_key and end_key:
loaded_ticks, tick_rows = load_breakout_ticks_by_code(
db, start_key, end_key, set(candles_by_code.keys()),
)
tick_meta = tick_coverage_stats(candles_by_code, loaded_ticks)
tick_meta["ws_tick_rows_loaded"] = tick_rows
if tick_rows <= 0:
from kis_trader.utils.logger import get_logger as _get_logger
_get_logger("kis_trader.range_break_backtest").warning(
"⚠️ ws_ticks 데이터 없음 — RANGE_BREAK 틱 청산 스킵 "
"(틱 수집 후 재백테 권장, FALLBACK_OHLC=1 시 OHLC)",
)
elif loaded_ticks:
tick_meta = tick_coverage_stats(candles_by_code, loaded_ticks)
tick_meta["ws_tick_rows_loaded"] = sum(
len(lst) for cm in loaded_ticks.values() for lst in cm.values()
)
trades = run_range_break_backtest(
candles_by_code,
engine_params,
universe_by_slot=universe_by_slot,
ticks_by_code=loaded_ticks or None,
)
attach_scalp_trade_pnl(
trades, fee_rate=fee_rate, sell_tax=sell_tax,
@@ -128,7 +164,18 @@ def run_range_break_backtest_web_aligned(
skip_stats = engine_params.get("_portfolio_skip_stats") or {}
meta_out["skip_stats"] = dict(skip_stats)
meta_out["engine_params"] = engine_params
meta_out["backtest_buy_source"] = "align"
if tick_meta:
from kis_trader.backtest.breakout_tick_loader import enrich_tick_meta_with_traded_codes
tick_meta = enrich_tick_meta_with_traded_codes(
tick_meta, candles_by_code, loaded_ticks, trades,
)
meta_out["tick_backtest"] = tick_meta
if tick_meta.get("ws_tick_rows_loaded", 0) > 0:
meta_out["backtest_buy_source"] = "ws_ticks"
else:
meta_out["backtest_buy_source"] = "ohlc_fallback"
else:
meta_out["backtest_buy_source"] = "align"
return trades