feat: Enhance trading system with new e_min_chg_pct parameter and related logic
Changes: - Introduced the `e_min_chg_pct` parameter to define the minimum price change percentage compared to the previous day's close, enhancing the momentum trading strategy. - Updated various functions and classes to incorporate this new parameter, ensuring it is utilized in both backtesting and live trading scenarios. - Improved documentation and comments to clarify the purpose and usage of the new parameter across the codebase. Impact: - This addition allows for more precise control over trading conditions, potentially increasing the effectiveness of the momentum strategy while maintaining system integrity and performance.
This commit is contained in:
78
database.py
78
database.py
@@ -657,8 +657,10 @@ ENV_CONFIG_KEYS = (
|
||||
"USE_KELLY_FORMULA",
|
||||
# 켈리 공식 적용 배수 (0.25 = Full Kelly의 25%, 과도한 베팅 방지)
|
||||
"KELLY_MULTIPLIER",
|
||||
# 시장가 IOC 주문 사용 여부 (실전: true=IOC, false=일반 시장가)
|
||||
# 시장가 IOC 주문 사용 여부 — 매수 (실전: true=IOC13, false=일반01 · 모의는 코드에서 01 고정)
|
||||
"USE_MARKET_IOC",
|
||||
# 시장가 IOC 주문 사용 여부 — 매도 (실전: true=IOC13, false=일반01 · 모의는 코드에서 01 고정)
|
||||
"USE_MARKET_IOC_SELL",
|
||||
# 체결 확인 엄격 모드: true=모의도 fill 없으면 가정 체결 금지 (실전 훈련)
|
||||
"STRICT_FILL_VERIFY",
|
||||
# 주문 직후 체결 조회 대기(초) — 시장가
|
||||
@@ -1136,6 +1138,7 @@ ENV_CONFIG_KEYS = (
|
||||
"MOMENTUM_TRIGGER_REQUIRE_BULL_BAR",
|
||||
"MOMENTUM_USE_VOL_TRIGGER",
|
||||
"MOMENTUM_USE_RSI_FILTER",
|
||||
"MOMENTUM_E_MIN_CHG_PCT",
|
||||
"MOMENTUM_CHASE_LOOKBACK_MIN",
|
||||
"MOMENTUM_PULLBACK_LOOKBACK_MIN",
|
||||
"MOMENTUM_PULLBACK_MIN_PCT",
|
||||
@@ -2424,9 +2427,10 @@ class TradeDB:
|
||||
size_class: str = None,
|
||||
strategy: str = None,
|
||||
realized_pnl_override: float = None,
|
||||
sell_qty: int = None,
|
||||
):
|
||||
"""
|
||||
매도 완료 처리: active_trades 삭제 -> trade_history 이동 (INSERT만, env 스냅샷 포함)
|
||||
매도 완료 처리: active_trades → trade_history (INSERT만, env 스냅샷 포함)
|
||||
|
||||
Args:
|
||||
code: 종목코드
|
||||
@@ -2437,6 +2441,10 @@ class TradeDB:
|
||||
strategy: 봇 전략 ID (SHORT_ANT_SHAKING / SCALP_RSI_REVERSAL 등)
|
||||
지정 시 해당 전략 row만 삭제 (다른 봇의 동일 종목 보호).
|
||||
None이면 code 단독 조회 (단일 봇 운영 환경 호환).
|
||||
realized_pnl_override: 수수료·세금 반영 순손익 (외부 주입)
|
||||
sell_qty: 부분매도 수량. None/전량 이상이면 기존처럼 전량 청산.
|
||||
0 < sell_qty < current_qty 이면 history 기록 후 잔량 유지
|
||||
(시장가 IOC 부분체결 대비).
|
||||
"""
|
||||
try:
|
||||
# 1. 활성 트레이드 정보 조회 (strategy 지정 시 정확히 해당 row만 조회)
|
||||
@@ -2453,9 +2461,16 @@ class TradeDB:
|
||||
logger.warning(f"⚠️ close_trade: {code} 종목이 active_trades에 없음")
|
||||
return False
|
||||
|
||||
# 2. 손익 계산
|
||||
# 2. 손익 계산 (부분매도면 체결분만)
|
||||
buy_price = trade['avg_buy_price']
|
||||
qty = trade['current_qty']
|
||||
pos_qty = int(trade['current_qty'] or 0)
|
||||
if sell_qty is None:
|
||||
qty = pos_qty
|
||||
else:
|
||||
qty = min(max(0, int(sell_qty)), pos_qty)
|
||||
if qty <= 0:
|
||||
logger.warning("⚠️ close_trade: %s sell_qty<=0 (pos=%d)", code, pos_qty)
|
||||
return False
|
||||
# realized_pnl_override 가 있으면 수수료·세금 반영 순손익을 외부에서 주입
|
||||
# 없으면 내부 계산 (수수료 미포함 gross)
|
||||
if realized_pnl_override is not None:
|
||||
@@ -2485,6 +2500,9 @@ class TradeDB:
|
||||
if ML_ENTRY_FEATURE_COLUMNS:
|
||||
cols_th += ", " + ", ".join(ML_ENTRY_FEATURE_COLUMNS)
|
||||
placeholders = ", ".join(["?"] * (14 + len(ML_ENTRY_FEATURE_COLUMNS)))
|
||||
remain_qty = pos_qty - qty
|
||||
inv = float(trade["total_invested"] or 0) if "total_invested" in trade.keys() else 0.0
|
||||
new_inv = (inv * remain_qty / pos_qty) if pos_qty > 0 and remain_qty > 0 else 0.0
|
||||
with self.conn:
|
||||
self.conn.execute(f"""
|
||||
INSERT INTO trade_history (
|
||||
@@ -2507,16 +2525,50 @@ class TradeDB:
|
||||
size_class,
|
||||
) + tuple(feat_vals))
|
||||
|
||||
# 5. active_trades에서 삭제 (strategy 지정 시 해당 봇 row만 삭제)
|
||||
if strategy:
|
||||
self.conn.execute(
|
||||
"DELETE FROM active_trades WHERE code=%s AND strategy=%s",
|
||||
(code, strategy),
|
||||
)
|
||||
# 5. 전량이면 삭제, 부분이면 잔량·투입금 축소
|
||||
if remain_qty <= 0:
|
||||
if strategy:
|
||||
self.conn.execute(
|
||||
"DELETE FROM active_trades WHERE code=%s AND strategy=%s",
|
||||
(code, strategy),
|
||||
)
|
||||
else:
|
||||
self.conn.execute("DELETE FROM active_trades WHERE code=%s", (code,))
|
||||
else:
|
||||
self.conn.execute("DELETE FROM active_trades WHERE code=%s", (code,))
|
||||
|
||||
logger.info(f"✅ [{trade['name']}] 매매 종료: 수익률 {profit_rate:.2f}% ({realized_pnl:+,.0f}원)")
|
||||
if strategy:
|
||||
self.conn.execute(
|
||||
"UPDATE active_trades SET current_qty=%s, target_qty=%s, "
|
||||
"total_invested=%s, updated_at=%s "
|
||||
"WHERE code=%s AND strategy=%s",
|
||||
(
|
||||
remain_qty,
|
||||
remain_qty,
|
||||
new_inv,
|
||||
sell_time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
code,
|
||||
strategy,
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.conn.execute(
|
||||
"UPDATE active_trades SET current_qty=%s, target_qty=%s, "
|
||||
"total_invested=%s, updated_at=%s WHERE code=%s",
|
||||
(
|
||||
remain_qty,
|
||||
remain_qty,
|
||||
new_inv,
|
||||
sell_time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
code,
|
||||
),
|
||||
)
|
||||
|
||||
if remain_qty <= 0:
|
||||
logger.info(f"✅ [{trade['name']}] 매매 종료: 수익률 {profit_rate:.2f}% ({realized_pnl:+,.0f}원)")
|
||||
else:
|
||||
logger.info(
|
||||
"✅ [%s] 부분매도 %d/%d주: 수익률 %.2f%% (%+.0f원) · 잔량 %d주",
|
||||
trade["name"], qty, pos_qty, profit_rate, realized_pnl, remain_qty,
|
||||
)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user