feat(운영설정): SCALP 노출·전략 ON/OFF 최상단·손익 한줄 UI
LIVE_STRATEGY_IDS/SWITCH_IDS에 SCALP를 추가하고 EOD·env 필드를 정리한다. 운영설정 CSS로 손익 칩·전략 토글 가로 한 줄 레이아웃을 지원한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,11 +8,11 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
# 웹 탭에 노출할 전략 ID (kis_trader 봇)
|
||||
# ※ SCALP·RANGE_BREAK·DBBAND 는 사용자 지정으로 숨김 (strategy_ids.HIDDEN_STRATEGY_IDS)
|
||||
# → 운영설정 ON/OFF·운용한도·일일익절·휩쏘 폼에서 제외. 실거래 중인 SHORT·BREAKOUT·MOMENTUM + UPDOW 만 노출.
|
||||
# 웹 탭에 노출할 전략 ID (kis_trader 봇) — 오늘 운영 탭·대시보드 순서와 동일
|
||||
# ※ RANGE_BREAK·DBBAND 는 strategy_ids.HIDDEN_STRATEGY_IDS 로 숨김 유지
|
||||
# ※ US_MOMENTUM 은 전략 ON/OFF 에만 노출 (유니버스/KRW 한도 폼은 국내와 축이 다름).
|
||||
LIVE_STRATEGY_IDS: Tuple[str, ...] = (
|
||||
"SCALP",
|
||||
"SHORT",
|
||||
"MOMENTUM",
|
||||
"BREAKOUT",
|
||||
@@ -22,6 +22,7 @@ LIVE_STRATEGY_IDS: Tuple[str, ...] = (
|
||||
# 전략 ON/OFF 전용 — 해외를 맨 위
|
||||
LIVE_STRATEGY_SWITCH_IDS: Tuple[str, ...] = (
|
||||
"US_MOMENTUM",
|
||||
"SCALP",
|
||||
"SHORT",
|
||||
"MOMENTUM",
|
||||
"BREAKOUT",
|
||||
@@ -218,6 +219,12 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
"RAM 미반영·읽기 체인 실패(필터 max_age=0=마지막 RAM 은 예외). "
|
||||
"1·2·3차 같음. 0이면 나이 컷 OFF. 기본 3. 적재(공책)와 분리."
|
||||
)),
|
||||
_f("FEED_STATS_DISCONNECT_SOFT_SEC", "📡 수집통계 끊김(소프트) 초", "int", default=10,
|
||||
hint="수집통계 탭: 종목별 recv_ts 간격 ≥이 값이면 끊김 카운트. 기본 10"),
|
||||
_f("FEED_STATS_DISCONNECT_HARD_SEC", "📡 수집통계 끊김(하드) 초", "int", default=60,
|
||||
hint="수집통계 탭: ≥이 값이면 긴 끊김. 기본 60 (소켓 알람 체감과 유사)"),
|
||||
_f("FEED_STATS_DISCONNECT_CAP_SEC", "📡 수집통계 끊김 상한(초)", "int", default=1800,
|
||||
hint="이보다 긴 공백은 장외·미구독으로 보고 끊김 집계에서 제외. 기본 1800"),
|
||||
_f("TRIGGER_FEED_DETAIL_LOG", "📝 트리거 로그에 틱·호가·벤더 상세", "bool", default=True,
|
||||
hint=(
|
||||
"ON=매수체크(🔍) 로그 끝에 틱1차설정/실제(kis|kiwoom|ls)·현재가·틱타임·"
|
||||
@@ -346,6 +353,12 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
hint="키움 ka10080 → ls_ws_candles INSERT IGNORE. ws_candles 에 넣지 않음."),
|
||||
_f("PERM_LS_FILL_SLEEP_MIN", "확정봉 가져오기 종목간 sleep 최소(초)", "float", default=1.0),
|
||||
_f("PERM_LS_FILL_SLEEP_MAX", "확정봉 가져오기 종목간 sleep 최대(초)", "float", default=3.0),
|
||||
_f("PERM_ALERT_ENABLED", "영구구독 목표가 MM알람", "bool", default=True,
|
||||
hint="ON=목표가 도달 시 Mattermost(permanent 채널). 봇 루프 폴링."),
|
||||
_f("PERM_ALERT_POLL_SEC", "목표가 검사 주기(초)", "int", default=3,
|
||||
hint="heartbeat 에서 검사 간격. 최소 1."),
|
||||
_f("KIS_PERM_SUB_MM_CHANNEL", "영구구독 MM alias", "text", default="permanent",
|
||||
hint="mm_config.json channels 키. 채널 만든 뒤 ID 등록."),
|
||||
_f("KIS_APP_KEY_OB_REAL", "🔑 KIS 실전 호가 전용 앱키 (선택)", "text",
|
||||
hint="호가 전용 2번째 실전 앱키. 미입력 시 메인에 호가 TR 안 붙임(합산 금지). spill 틱용 아님."),
|
||||
_f("KIS_APP_SECRET_OB_REAL", "🔑 KIS 실전 호가 전용 시크릿 (선택)", "text",
|
||||
@@ -599,7 +612,6 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
]
|
||||
|
||||
# 호가필터 — 전략별 (글로벌 ORDERBOOK_* 수치 폐기)
|
||||
# SCALP 는 LIVE_STRATEGY_IDS 에서 숨김이어도 config_scalp 키는 노출
|
||||
from kis_trader.engine.orderbook_env import (
|
||||
OB_DEFAULT_ASK_WALL_MAX_QTY,
|
||||
OB_DEFAULT_ENTRY_ASK_MAX_MULT,
|
||||
@@ -711,7 +723,7 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
"해외 WS(HDFSCNT0)",
|
||||
"bool",
|
||||
default=True,
|
||||
hint="기동 시만 · false=해외 틱 소켓 미기동 · 전략 ON/OFF 와 별개 · 변경 후 재시작",
|
||||
hint="기동 시만 · false=해외 틱 소켓 미기동 · 영구구독 US 시세/알람용(전략 OFF여도 ON 가능) · 변경 후 재시작",
|
||||
),
|
||||
*[
|
||||
_f(
|
||||
@@ -894,11 +906,6 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
ws_fields.append(
|
||||
_f(f"{pfx}_WHIPSAW_FILTER_ENABLED", f"{lbl} 휩쏘 필터", "bool"),
|
||||
)
|
||||
# SCALP 는 LIVE_STRATEGY_IDS 에서 숨겨도 휩쏘는 Optuna·엔진 필수 → 노출
|
||||
if not any(f.get("key") == "SCALP_WHIPSAW_FILTER_ENABLED" for f in ws_fields):
|
||||
ws_fields.append(
|
||||
_f("SCALP_WHIPSAW_FILTER_ENABLED", "스캘핑 휩쏘 필터", "bool"),
|
||||
)
|
||||
groups.append({
|
||||
"id": "whipsaw_strategy",
|
||||
"title": "휩쏘 — 전략별 ON/OFF (진입 차단)",
|
||||
@@ -1368,21 +1375,6 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
],
|
||||
})
|
||||
|
||||
groups.append({
|
||||
"id": "scalp_exit",
|
||||
"title": "스캘핑(SCALP) — EOD",
|
||||
"hint": (
|
||||
"config_scalp · 저장 후 다음 매도 루프부터 반영(재시작 권장). "
|
||||
"실매 기존 하드코딩 15:25 장마감청산과 동일 기본값."
|
||||
),
|
||||
"fields": [
|
||||
_f("SCALP_EOD_ENABLED", "EOD 당일청산 사용", "bool", default=True,
|
||||
hint="ON=설정 시각 이후 보유 전량 장마감청산 · OFF=익절·손절·어깨만"),
|
||||
_f("SCALP_EOD_HM", "EOD 시각 (HH:MM)", "text", default="15:25",
|
||||
hint="실매 기존 15:25 · 정규장 15:30 마감 직전 순차매도"),
|
||||
],
|
||||
})
|
||||
|
||||
groups.append({
|
||||
"id": "breakout_exit",
|
||||
"title": "📉 매도 호가익절·손절 (EXIT_OB/STOP_OB) — 돌파",
|
||||
@@ -1457,6 +1449,10 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
"title": "🌅 EOD 당일청산 설정 (전략 통합)",
|
||||
"hint": "각 전략별로 정해진 시각이 되면 보유 물량을 전량 청산(퇴근)합니다.",
|
||||
"fields": [
|
||||
_f("SCALP_EOD_ENABLED", "스캘핑 EOD 사용", "bool", default=True,
|
||||
hint="ON=설정 시각 이후 보유 전량 장마감청산 · OFF=익절·손절·어깨만"),
|
||||
_f("SCALP_EOD_HM", "스캘핑 EOD 시각 (HH:MM)", "text", default="15:25",
|
||||
hint="실매 기존 15:25 · 정규장 15:30 마감 직전 순차매도"),
|
||||
_f("BREAKOUT_EOD_ENABLED", "돌파 EOD 사용", "bool", default=True),
|
||||
_f("BREAKOUT_EOD_HM", "돌파 EOD 시각 (HH:MM)", "text", default="15:15",
|
||||
hint="예: 15:15 (빠르게 정리)"),
|
||||
@@ -1551,7 +1547,7 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
_f("ORPHAN_PURGE_ACTIVE_AFTER_SELL_HISTORY", "청산후 유령 active 정리", "bool", default=True,
|
||||
hint="ON=active에 남았는데 매수 이후 청산 히스토리면 DB 행 삭제"),
|
||||
_f("GHOST_PURGE_ON_RECONCILE", "고아복구 시 유령잔고 삭제", "bool", default=True,
|
||||
hint="ON=브로커 보유 0·매도가능 0·정정취소가능 매도 없을 때만 active_trades 삭제(수동보호 제외) · Pre/Post EOD"),
|
||||
hint="ON=브로커 0주·매도가능0·정정취소가능 없을 때 active 삭제 · **현재 KIS_MOCK=is_mock 행만** (모의↔실전 교차삭제 금지) · Pre/Post/기동"),
|
||||
_f(
|
||||
"GHOST_PURGE_RECORD_HISTORY",
|
||||
"유령정리 시 거래내역 기록",
|
||||
@@ -1571,6 +1567,11 @@ def build_live_config_groups() -> List[GroupDef]:
|
||||
],
|
||||
})
|
||||
|
||||
# 전략 ON/OFF — 운영설정 탭 최상단
|
||||
sw_idx = next((i for i, g in enumerate(groups) if g.get("id") == "strategy_switch"), None)
|
||||
if sw_idx is not None:
|
||||
sw = groups.pop(sw_idx)
|
||||
groups.insert(0, sw)
|
||||
return groups
|
||||
|
||||
|
||||
|
||||
@@ -122,6 +122,73 @@
|
||||
.live-quote-stale { opacity: 0.55; }
|
||||
/* 파라미터 설명 툴팁 */
|
||||
.param-help { font-size: 10px; color: var(--muted); margin-top: 2px; }
|
||||
/* 운영 설정 — 당일 손익 칩 한 줄 */
|
||||
.lc-status-row {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
.lc-status-chip {
|
||||
flex: 0 0 auto;
|
||||
min-width: 148px;
|
||||
max-width: 220px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
background: rgba(22, 27, 34, 0.55);
|
||||
font-size: 13px;
|
||||
}
|
||||
.lc-status-chip .lc-status-label {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
margin-bottom: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.lc-status-chip .lc-status-value {
|
||||
font-size: 18px;
|
||||
font-weight: 650;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.lc-status-chip .lc-status-meta {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
margin-top: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* 전략 ON/OFF — 토글 한 줄 */
|
||||
.lc-switch-row {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: 10px 14px;
|
||||
overflow-x: auto;
|
||||
padding: 4px 0 2px;
|
||||
}
|
||||
.lc-switch-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.lc-switch-chip input[type="checkbox"] {
|
||||
margin: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.lc-switch-chip .lc-switch-sid {
|
||||
font-size: 10px;
|
||||
color: var(--muted);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
.lc-switch-chip.lc-switch-warn {
|
||||
color: #d29922;
|
||||
}
|
||||
/* 운영 설정 탭 — 최대 2열, 위에서 아래로 읽기 */
|
||||
.lc-field-grid {
|
||||
display: grid;
|
||||
|
||||
Reference in New Issue
Block a user