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:
@@ -37,13 +37,20 @@ def tail_backtest_use_tick_db(params: Optional[Dict[str, Any]] = None) -> bool:
|
||||
return _param_bool(params, "backtest_use_tick_db", "TAIL_BACKTEST_USE_TICK_DB", True)
|
||||
|
||||
|
||||
def tail_backtest_use_tick_exit(params: Optional[Dict[str, Any]] = None) -> bool:
|
||||
"""백테 청산에 ws_ticks 사용 (기본 ON — OHLC intrabar 낙관 편향 제거)."""
|
||||
return _param_bool(params, "backtest_use_tick_exit", "TAIL_BACKTEST_USE_TICK_EXIT", True)
|
||||
|
||||
|
||||
def tail_backtest_tick_fallback_ohlc(params: Optional[Dict[str, Any]] = None) -> bool:
|
||||
"""해당 구간 틱 없을 때 3분봉 OHLC 폴백."""
|
||||
return _param_bool(params, "backtest_tick_fallback_ohlc", "TAIL_BACKTEST_TICK_FALLBACK_OHLC", True)
|
||||
"""해당 구간 틱 없을 때 3분봉 OHLC 폴백 (기본 OFF — 유령거래 방지)."""
|
||||
return _param_bool(params, "backtest_tick_fallback_ohlc", "TAIL_BACKTEST_TICK_FALLBACK_OHLC", False)
|
||||
|
||||
|
||||
def tail_backtest_wants_tick_replay(params: Optional[Dict[str, Any]] = None) -> bool:
|
||||
"""limit_atr 또는 align 백테에서 틱 DB 로드·재생이 필요한지."""
|
||||
"""진입(align/limit) 또는 청산 틱 재생이 필요한지."""
|
||||
if tail_backtest_use_tick_exit(params):
|
||||
return True
|
||||
if not tail_backtest_use_tick_db(params):
|
||||
return False
|
||||
mode = short_entry_mode(params)
|
||||
@@ -137,7 +144,7 @@ def align_entry_price_from_ticks(
|
||||
ticks: List[Dict[str, Any]],
|
||||
fallback_open: float,
|
||||
) -> Tuple[float, str]:
|
||||
"""다음 봉 첫 체결 틱 가격 (없으면 시가)."""
|
||||
"""신호 직후(진입봉) 첫 체결 틱 가격 (없으면 시가)."""
|
||||
fo = float(fallback_open or 0)
|
||||
if not ticks:
|
||||
return fo, "ohlc_open"
|
||||
@@ -160,6 +167,51 @@ def align_entry_price_from_ticks(
|
||||
return fo, "ohlc_open"
|
||||
|
||||
|
||||
def resolve_align_entry_bar(
|
||||
candles: List[Dict[str, Any]],
|
||||
signal_idx: int,
|
||||
tf_min: int,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
align 진입봉 — 신호봉 직후 **기대 다음 봉**(signal+tf)을 우선.
|
||||
|
||||
DB 3분 구멍으로 멀리 떨어진 다음 시가에 밀리지 않도록,
|
||||
``candle_time == signal_time+tf`` 봉이 있으면 그걸 쓴다
|
||||
(1M→3M 합성으로 메워진 경우 포함). 없으면 기존처럼 다음 당일 봉.
|
||||
"""
|
||||
from kis_trader.engine.candle_rollup import add_candle_minutes
|
||||
|
||||
if signal_idx < 0 or signal_idx >= len(candles):
|
||||
return None
|
||||
sig = candles[signal_idx]
|
||||
day = str(sig.get("candle_time") or "")[:8]
|
||||
if len(day) < 8:
|
||||
return None
|
||||
expected = add_candle_minutes(str(sig.get("candle_time") or ""), int(tf_min))
|
||||
if not expected:
|
||||
return None
|
||||
for j in range(signal_idx + 1, len(candles)):
|
||||
ct = str(candles[j].get("candle_time") or "")
|
||||
if ct[:8] != day:
|
||||
return None
|
||||
if ct[:12] == expected[:12]:
|
||||
return candles[j]
|
||||
# 기대 봉 없음 → 레거시: 바로 다음 당일 봉
|
||||
if signal_idx + 1 >= len(candles):
|
||||
return None
|
||||
next_c = candles[signal_idx + 1]
|
||||
if str(next_c.get("candle_time") or "")[:8] != day:
|
||||
return None
|
||||
return next_c
|
||||
|
||||
|
||||
def align_entry_execute_time(bar_candle_time: str, tf_min: int) -> str:
|
||||
"""align 체결 시각 = 진입봉 시작 + tf (봉 확정 직후, 실매 check_buy_signal_live 와 동일)."""
|
||||
from kis_trader.engine.candle_rollup import add_candle_minutes
|
||||
|
||||
return add_candle_minutes(str(bar_candle_time or "")[:12], int(tf_min))
|
||||
|
||||
|
||||
def try_limit_fill_on_bar_with_ticks(
|
||||
bar: Dict[str, Any],
|
||||
limit_price: float,
|
||||
|
||||
Reference in New Issue
Block a user