feat: Add new files and enhance backtesting functionality
Changes: - Introduced new files for strategy definitions and study names. - Enhanced `backtest_web.py` with functions to handle integer display prices and trade data formatting. - Updated backtesting logic to incorporate end-of-day (EOD) parameters for breakout and momentum strategies. - Added EOD configuration options in the database and parameter search files. Impact: - These changes improve the modularity and usability of the backtesting framework, allowing for better integration of EOD strategies and clearer trade data presentation.
This commit is contained in:
@@ -7,6 +7,9 @@ kis_trader/engine/daily_profit_halt.py — 일일 익절 목표 달성 시 신
|
||||
목표 판정: 원(KRW) · 운용한도 대비 %(PCT) **둘 중 하나라도** 달성 시 트리거.
|
||||
분모(%) : ``DAILY_PROFIT_TARGET_BUDGET_KRW`` 또는 ON 전략 ``*_TOTAL_BUDGET_KRW`` 합.
|
||||
|
||||
**활성화(``*_TARGET_ENABLED``)** ON + 목표 설정 → 달성 시 **무조건** 신규매수 차단.
|
||||
**신규매수 중단(``*_HALT_NEW_BUYS``)** = 목표와 무관한 **수동** 매수 잠금(별도 스위치).
|
||||
|
||||
매도(손절·익절)는 계속 — **신규 매수만** 차단.
|
||||
모든 임계값 env/DB — 하드코딩 금지.
|
||||
"""
|
||||
@@ -73,13 +76,23 @@ def _mode(common_key: str, strategy_key: str, default: str = "fixed") -> str:
|
||||
return (g or default).lower()
|
||||
|
||||
|
||||
def _halt_new_buys_flag(common_key: str, strategy_key: str, default: bool = False) -> bool:
|
||||
"""수동 신규매수 중단 — 전략 서브값 우선 → 마스터 → 기본 OFF."""
|
||||
raw = str(get_env_from_db(strategy_key, "")).strip()
|
||||
if raw != "":
|
||||
return get_env_bool(strategy_key, default)
|
||||
return get_env_bool(common_key, default)
|
||||
|
||||
|
||||
def load_global_profit_target() -> Dict[str, Any]:
|
||||
return {
|
||||
"enabled": get_env_bool("DAILY_PROFIT_TARGET_ENABLED", False),
|
||||
"krw": max(0.0, float(get_env_float("DAILY_PROFIT_TARGET_KRW", 0.0))),
|
||||
"pct": max(0.0, float(get_env_float("DAILY_PROFIT_TARGET_PCT", 0.0))),
|
||||
"budget_krw": max(0.0, float(get_env_float("DAILY_PROFIT_TARGET_BUDGET_KRW", 0.0))),
|
||||
"halt_new_buys": get_env_bool("DAILY_PROFIT_HALT_NEW_BUYS", True),
|
||||
"halt_new_buys": _halt_new_buys_flag(
|
||||
"DAILY_PROFIT_HALT_NEW_BUYS", "DAILY_PROFIT_HALT_NEW_BUYS", False,
|
||||
),
|
||||
"notify_mm": get_env_bool("DAILY_PROFIT_NOTIFY_MM", True),
|
||||
# 트레일링 익절 (당일 손익 고점 추적) — fixed 기본이라 미설정 시 동작 불변
|
||||
"mode": _mode("DAILY_PROFIT_MODE", "DAILY_PROFIT_MODE", "fixed"),
|
||||
@@ -110,7 +123,11 @@ def load_strategy_profit_target(strategy_id: str) -> Dict[str, Any]:
|
||||
0.0,
|
||||
),
|
||||
"budget_env": _STRATEGY_BUDGET_ENV.get(pfx, f"{pfx}_TOTAL_BUDGET_KRW"),
|
||||
"halt_new_buys": get_env_bool(f"{pfx}_DAILY_PROFIT_HALT_NEW_BUYS", True),
|
||||
"halt_new_buys": _halt_new_buys_flag(
|
||||
"DAILY_PROFIT_HALT_NEW_BUYS",
|
||||
f"{pfx}_DAILY_PROFIT_HALT_NEW_BUYS",
|
||||
False,
|
||||
),
|
||||
# 트레일링 익절 — 전략 서브값 우선 → 마스터 폴백 (fixed 기본)
|
||||
"mode": _mode("DAILY_PROFIT_MODE", f"{pfx}_DAILY_PROFIT_MODE", "fixed"),
|
||||
# 다단계 트레일 tier — 전략 서브값 우선 → 마스터 폴백 (비면 단일 drop_pct)
|
||||
@@ -290,6 +307,31 @@ def _format_hit_detail(
|
||||
return " · ".join(parts)
|
||||
|
||||
|
||||
def describe_profit_guard_startup(cfg: Dict[str, Any], *, scope: str = "마스터") -> str:
|
||||
"""기동 로그용 — 설정이 매수에 미치는 영향을 한 줄로."""
|
||||
if cfg.get("halt_new_buys"):
|
||||
return (
|
||||
f"⛔ [일일익절·{scope}] 수동 신규매수 중단 ON — "
|
||||
f"목표·손익과 무관하게 신규매수 차단 (매도·손절 유지)"
|
||||
)
|
||||
if not cfg.get("enabled"):
|
||||
return (
|
||||
f"ℹ️ [일일익절·{scope}] 손익 감시 OFF — "
|
||||
f"목표 달성 시에도 신규매수 차단 없음"
|
||||
)
|
||||
if not _guard_active(cfg):
|
||||
return (
|
||||
f"ℹ️ [일일익절·{scope}] 손익 감시 ON 이지만 목표 미설정 "
|
||||
f"(금액·%·트레일 없음) — 달성 차단 없음"
|
||||
)
|
||||
krw = float(cfg.get("krw") or 0)
|
||||
pct = float(cfg.get("pct") or 0)
|
||||
return (
|
||||
f"🎯 [일일익절·{scope}] 손익 감시 ON — 목표 {krw:,.0f}원 / {pct:.2f}% "
|
||||
f"· 달성 시 신규매수 차단 (매도·손절 유지)"
|
||||
)
|
||||
|
||||
|
||||
class DailyProfitHaltGuard:
|
||||
"""
|
||||
Orchestrator 가 주입 — ``buy_allowed(strategy_id)`` 로 신규 매수 차단 여부 판단.
|
||||
@@ -329,7 +371,17 @@ class DailyProfitHaltGuard:
|
||||
sid = _strategy_prefix(strategy_id)
|
||||
|
||||
gcfg = load_global_profit_target()
|
||||
if gcfg.get("halt_new_buys", True) and _guard_active(gcfg):
|
||||
|
||||
# 1) 수동 신규매수 중단 (목표·손익과 무관)
|
||||
if gcfg.get("halt_new_buys"):
|
||||
self._throttled_log(
|
||||
sid,
|
||||
"⛔ [신규매수중단·총합] 수동 중단 ON → 신규매수 차단",
|
||||
)
|
||||
return False, "탈락-신규매수중단(총합)"
|
||||
|
||||
# 2) 일일익절 — 활성화 ON이면 목표 달성 시 무조건 신규매수 차단
|
||||
if _guard_active(gcfg):
|
||||
gpnl, gcnt = self._global_pnl_fn(today)
|
||||
gbudget = resolve_global_operating_budget_krw(self._active_strategies_fn())
|
||||
gpeak = self._update_peak(f"global:{today}", today, gpnl)
|
||||
@@ -341,7 +393,15 @@ class DailyProfitHaltGuard:
|
||||
return False, "탈락-일일익절(총합)"
|
||||
|
||||
scfg = load_strategy_profit_target(sid)
|
||||
if scfg.get("halt_new_buys", True) and _guard_active(scfg):
|
||||
|
||||
if scfg.get("halt_new_buys"):
|
||||
self._throttled_log(
|
||||
sid,
|
||||
f"⛔ [신규매수중단·{sid}] 수동 중단 ON → 해당전략 신규매수 차단",
|
||||
)
|
||||
return False, f"탈락-신규매수중단({sid})"
|
||||
|
||||
if _guard_active(scfg):
|
||||
spnl, scnt = self._strategy_pnl_fn(today, sid)
|
||||
sbudget = resolve_strategy_budget_krw(sid)
|
||||
speak = self._update_peak(f"{sid}:{today}", today, spnl)
|
||||
|
||||
Reference in New Issue
Block a user