Files
kis_trader/templates/backtest.html
Your Name 2c7ad867f4 거래 빠르게 안티에서 병신만든거 커서로
feat: Implement backtest source management and enhance candle data handling

Changes:
- Introduced a new function `_apply_backtest_source_env_from_request` to manage the environment variables for candle, tick, and order book sources based on incoming requests.
- Added a teardown function `_teardown_backtest_source_env` to ensure that environment variables do not persist between requests, enhancing the stability of the backtesting environment.
- Refactored existing code to utilize the new source management functions, improving code readability and maintainability.
- Added new utility functions in `bt_candle_source.py` for fetching and managing candle data, ensuring consistency with live trading data sources.

Impact:
- These changes improve the flexibility and reliability of the backtesting framework, allowing for better management of data sources and reducing the risk of cross-request contamination.
2026-08-13 16:03:40 +09:00

3941 lines
259 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ko" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>📈 KIS Quant 백테스트 대시보드</title>
<link rel="icon" href="data:,">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/backtest.css') }}">
</head>
<body>
<!-- 로딩 오버레이 -->
<div class="spin-overlay" id="spinner">
<div class="spinner"></div>
</div>
<nav class="navbar px-4 py-2" style="background:var(--surface); border-bottom:1px solid var(--border)">
<div class="d-flex align-items-center flex-wrap gap-3 w-100">
<span class="navbar-brand mb-0">📈 KIS Quant Dashboard</span>
<!-- Optuna 전역 미니 프로그레스 (어느 탭에서든) -->
<div id="optuna_nav_bar" class="optuna-nav-bar d-none flex-grow-1" style="max-width:420px;cursor:pointer"
title="Optuna 탭으로 이동" onclick="optunaGoTab()">
<div class="d-flex justify-content-between align-items-center" style="font-size:11px;color:var(--muted)">
<span id="optuna_nav_label">Optuna</span>
<span id="optuna_nav_pct">0%</span>
</div>
<div class="optuna-prog-track">
<div class="optuna-prog-fill" id="optuna_nav_fill" style="width:0%"></div>
</div>
</div>
<!-- 전략 백테 CLI 잡 전역 미니 프로그레스 (탭 이동해도 유지, 전역 1잡) -->
<div id="btjob_nav_bar" class="optuna-nav-bar d-none flex-grow-1" style="max-width:360px;cursor:pointer"
title="해당 전략 탭으로 이동" onclick="btJobGoTab()">
<div class="d-flex justify-content-between align-items-center" style="font-size:11px;color:var(--muted)">
<span id="btjob_nav_label">백테 잡</span>
<span id="btjob_nav_pct">0%</span>
</div>
<div class="optuna-prog-track">
<div class="optuna-prog-fill" id="btjob_nav_fill" style="width:0%"></div>
</div>
</div>
<span class="text-muted ms-auto" id="lastRefresh" style="font-size:12px"></span>
<!-- 매매 모의/실전(KIS_MOCK) — 저장 시 kis_trader_main 재시작. 시세 실키는 유지 -->
<div id="kis_mock_nav" class="d-flex align-items-center gap-2 ms-2"
title="매매 계좌만 전환(시세=실키). 저장 시 봇 재시작">
<span class="text-muted" style="font-size:11px;white-space:nowrap">매매</span>
<div class="btn-group btn-group-sm" role="group" aria-label="KIS_MOCK">
<button type="button" class="btn btn-outline-warning" id="kis_mock_btn_mock"
onclick="kisMockSet(true)">모의</button>
<button type="button" class="btn btn-outline-danger" id="kis_mock_btn_live"
onclick="kisMockSet(false)">실전</button>
</div>
<div class="d-flex flex-column ms-1">
<span id="kis_mock_status" class="text-muted" style="font-size:11px;white-space:nowrap"></span>
<span id="live_source_status" class="text-muted" style="font-size:10px;white-space:nowrap;cursor:help" title="로딩 중…">시세: - | 호가: - | DB: -</span>
</div>
</div>
</div>
</nav>
<div class="container-fluid px-4 py-3">
<!---->
<ul class="nav nav-tabs mb-4" id="mainTab">
<li class="nav-item"><a class="nav-link active" data-tab="actual" href="#">📊 실거래 분석</a></li>
<li class="nav-item"><a class="nav-link" data-tab="dashboard" href="#">📈 오늘 운영</a></li>
<li class="nav-item"><a class="nav-link" data-tab="liveconfig" href="#">⚙️ 운영 설정</a></li>
<li class="nav-item"><a class="nav-link" data-tab="portfolio" href="#">💼 보유·매도</a></li>
<li class="nav-item"><a class="nav-link" data-tab="backtest" href="#">📉 스캘핑 백테스트</a></li>
<li class="nav-item"><a class="nav-link" data-tab="tail" href="#">🎣 꼬리잡기 백테스트</a></li>
<li class="nav-item" style="display:none"><a class="nav-link" data-tab="dbband" href="#">📊 DBBAND</a></li>
<li class="nav-item"><a class="nav-link" data-tab="breakout" href="#">🚀 돌파매매 백테스트</a></li>
<li class="nav-item" style="display:none"><a class="nav-link" data-tab="range_break" href="#">📦 박스권돌파</a></li>
<li class="nav-item"><a class="nav-link" data-tab="momentum" href="#">🌊 모멘텀 백테스트</a></li>
<li class="nav-item"><a class="nav-link" data-tab="us_momentum" href="#">🇺🇸 해외 모멘텀</a></li>
<li class="nav-item"><a class="nav-link" data-tab="optuna" href="#">🔬 Optuna</a></li>
<li class="nav-item"><a class="nav-link" data-tab="holding" href="#">📈 홀딩 전략</a></li>
<li class="nav-item"><a class="nav-link" data-tab="updownbox" href="#">📦 박스엔진</a></li>
<li class="nav-item"><a class="nav-link" data-tab="updow" href="#">📡 영구구독 관리</a></li>
<li class="nav-item"><a class="nav-link" data-tab="dart" href="#">📢 DART 수주</a></li>
</ul>
<!-- ═══ 오늘 운영 (전략별·합계) ═══════════════════════════════════════════ -->
<div id="tab-dashboard" style="display:none">
<div class="card p-3 mb-3">
<div class="row g-3 align-items-end">
<div class="col-auto">
<label class="form-label param-row" style="color:var(--muted);font-size:12px">기준일 (KST)</label>
<input type="date" id="dash_date" class="form-control form-control-sm" style="width:160px">
</div>
<div class="col-auto">
<button class="btn btn-sm btn-primary" onclick="loadDashboard()">새로고침</button>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-outline-secondary" onclick="dashGoActual()">전략별 상세 → 실거래 분석</button>
</div>
<div class="col">
<small id="dash_meta" class="text-muted"></small>
</div>
</div>
</div>
<div class="row g-3 mb-3" id="dash_cards">
<div class="col-md-3">
<div class="card p-3 stat-card">
<div class="stat-label">당일 거래대금 (합)</div>
<div class="stat-value" id="dash_card_turnover"></div>
<small class="text-muted" id="dash_card_turnover_sub"></small>
</div>
</div>
<div class="col-md-3">
<div class="card p-3 stat-card">
<div class="stat-label">당일 뽀찌 피크 (ON 전략 합)</div>
<div class="stat-value" id="dash_card_budget"></div>
<small class="text-muted" id="dash_card_budget_sub"></small>
</div>
</div>
<div class="col-md-3">
<div class="card p-3 stat-card">
<div class="stat-label">당일 실현손익 (합)</div>
<div class="stat-value" id="dash_card_pnl"></div>
</div>
</div>
<div class="col-md-3">
<div class="card p-3 stat-card">
<div class="stat-label">총수익률 (실현÷운용한도)</div>
<div class="stat-value" id="dash_card_ret"></div>
<small class="text-muted">백테 bot_pct와 동일 분모</small>
</div>
</div>
</div>
<div class="card p-3">
<h6 class="mb-3">전략별 당일 운영 <small class="text-muted fw-normal">(키움 · LS 두 줄)</small></h6>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0 dash-ops-table" style="font-size:13px">
<thead>
<tr>
<th>전략</th>
<th>소스</th>
<th>ON</th>
<th class="text-end">매수대금</th>
<th class="text-end">매도대금</th>
<th class="text-end">거래대금합</th>
<th class="text-end">청산</th>
<th class="text-end">보유</th>
<th class="text-end">실현손익</th>
<th class="text-end">운용한도</th>
<th class="text-end">당일뽀찌(피크)</th>
<th class="text-end">현재투입</th>
<th class="text-end">사용률</th>
<th class="text-end">수익률</th>
<th></th>
</tr>
</thead>
<tbody id="dash_tbody"></tbody>
<tfoot>
<tr class="fw-bold" style="border-top:2px solid var(--border)">
<td colspan="2">합계 (ON 한도 기준 · 전략당 1회)</td>
<td></td>
<td class="text-end" id="dash_ft_buy"></td>
<td class="text-end" id="dash_ft_sell"></td>
<td class="text-end" id="dash_ft_turn"></td>
<td class="text-end" id="dash_ft_closed"></td>
<td class="text-end" id="dash_ft_open"></td>
<td class="text-end" id="dash_ft_pnl"></td>
<td class="text-end" id="dash_ft_limit"></td>
<td class="text-end" id="dash_ft_used"></td>
<td class="text-end" id="dash_ft_now"></td>
<td class="text-end" id="dash_ft_usage"></td>
<td class="text-end" id="dash_ft_ret"></td>
<td></td>
</tr>
</tfoot>
</table>
</div>
<p class="text-muted mt-2 mb-0" style="font-size:11px" id="dash_notes"></p>
</div>
<!-- 조건검색 이력: 전략별 키움 / LS 두 줄 -->
<div class="card p-3 mt-3">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2">
<h6 class="mb-0">조건검색 이력 (키움 · LS) — 전략별 두 줄</h6>
<small id="dash_univ_meta" class="text-muted"></small>
</div>
<div class="table-responsive dash-univ-wrap">
<table class="table table-sm table-hover mb-0 dash-univ-table" style="font-size:13px">
<thead>
<tr>
<th>전략</th>
<th>소스</th>
<th>실매소스</th>
<th class="text-end">슬롯</th>
<th class="text-end">종목수</th>
<th class="text-end">행수</th>
<th>최초</th>
<th>최근</th>
</tr>
</thead>
<tbody id="dash_univ_tbody"></tbody>
</table>
</div>
<p class="text-muted mt-2 mb-0" style="font-size:11px" id="dash_univ_notes"></p>
</div>
</div>
<!-- ═══ 실거래 분석 탭 ═══════════════════════════════════════════════════ -->
<div id="tab-actual">
<div class="card p-3 mb-3">
<div class="row g-3 align-items-end">
<div class="col-auto">
<label class="form-label param-row" style="color:var(--muted);font-size:12px">전략 선택 (kis_trader 봇)</label><br>
<div class="d-flex flex-wrap gap-2 gap-md-3 mt-1 align-items-center" style="max-width:920px">
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="act_strategy" value="SCALP"> 스캘핑 (SCALP)
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="act_strategy" value="SHORT" checked> 꼬리잡기 (SHORT)
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="act_strategy" value="MOMENTUM"> 모멘텀
</label>
<label class="d-flex align-items-center gap-1 mb-0" title="해외 모멘텀 실거래 (US_MOMENTUM)">
<input type="radio" name="act_strategy" value="US_MOMENTUM"> 해외모멘텀
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="act_strategy" value="UPDOW"> 하락매수 (UPDOW)
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="act_strategy" value="BREAKOUT"> 돌파 (BREAKOUT)
</label>
<label class="d-flex align-items-center gap-1 mb-0" title="holding_bot.py 장기 홀딩">
<input type="radio" name="act_strategy" value="HOLDING"> 홀딩 (HOLDING)
</label>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="act_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="act_end" style="width:150px">
</div>
<div class="col-auto">
<button class="btn btn-primary" onclick="loadActual()">🔍 조회</button>
</div>
</div>
</div>
<!-- 요약 카드 (백테 탭과 동일 레이아웃 + 운용한도 대비 수익률) -->
<div class="row g-3 mb-3" id="act_summary_row">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="a_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="a_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="a_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="a_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="a_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="a_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="a_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="a_daily_avg_pct">-</div>
</div></div>
</div>
<div id="act_filter_note" class="mb-2" style="display:none;font-size:12px;color:var(--muted)"></div>
<!-- 승/패 바 -->
<div class="card p-3 mb-3" id="act_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="a_win_label">-</span>
<span style="color:var(--red)" id="a_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="a_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="a_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3">
<!-- 누적 손익 곡선 -->
<div class="col-12 col-lg-7">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선</div>
<canvas id="a_equity_chart" height="220"></canvas>
</div>
</div>
<!-- 매도 이유 / 상위종목 -->
<div class="col-12 col-lg-5">
<div class="card p-3 mb-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="a_reason_chart" height="180"></canvas>
</div>
<div class="card p-3">
<div class="card-title mb-2">종목별 손익 TOP10</div>
<canvas id="a_code_chart" height="180"></canvas>
</div>
</div>
</div>
<!-- 일별 P&L 바 -->
<div class="card p-3 mt-3">
<div class="card-title mb-2">일별 손익</div>
<canvas id="a_daily_chart" height="150"></canvas>
</div>
<!-- 거래 목록 -->
<div class="section-title">거래 내역 <span id="act_table_hint" style="font-size:11px;color:var(--muted);font-weight:400"></span></div>
<div id="act_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="act_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" id="act_table">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th>
<th>보유(분)</th><th>체결디버그</th><th title="매수 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매수호가</th><th title="매도 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매도호가</th><th>매도사유</th>
</tr></thead>
<tbody id="act_tbody"></tbody>
</table>
</div>
</div>
</div>
<!-- ═══ 운영 설정 (실매 env 실시간 조회·저장) ═════════════════════════════ -->
<div id="tab-liveconfig" style="display:none">
<div class="card p-3 mb-3">
<div class="row g-3 align-items-end">
<div class="col-auto">
<label class="form-label param-row" style="color:var(--muted);font-size:12px">기준일 (손익·익절 상태)</label>
<input type="date" id="lc_date" class="form-control form-control-sm" style="width:160px">
</div>
<div class="col-auto">
<button class="btn btn-sm btn-primary" onclick="lcLoad()">🔄 새로고침</button>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-success" onclick="lcSaveAll()">💾 전체 저장</button>
</div>
<div class="col-auto">
<label class="d-flex align-items-center gap-2 mb-0" style="font-size:12px;color:var(--muted)">
<input type="checkbox" id="lc_auto_refresh" checked> 30초 자동 갱신
</label>
</div>
<div class="col">
<small id="lc_meta" class="text-muted"></small>
</div>
</div>
<div style="font-size:12px;color:var(--muted);line-height:1.6;margin-top:8px">
DB <code>insert_env_snapshot</code> 즉시 저장 → <b>봇 재시작 없이</b> 다음 루프부터 반영.
마스터 키는 <b>env_config</b>, 전략 키는 <b>config_{전략}</b> 테이블로 자동 분리됩니다.
</div>
</div>
<div id="lc_status_cards" class="row g-3 mb-3"></div>
<div id="lc_groups"></div>
<div id="lc_save_result" class="mt-2" style="font-size:13px"></div>
</div>
<!-- ═══ 보유·매도 (DB 동기화) ═══════════════════════════════════════════ -->
<div id="tab-portfolio" style="display:none">
<div class="card p-3 mb-3">
<div style="font-size:12px;color:var(--muted);line-height:1.6">
<b>실거래 분석</b> = 오늘 <b>매도 완료</b> 내역(trade_history). <b>보유·매도</b> = 지금 <b>잔고</b>(HTS 실시간잔고와 동일).
<b>실계좌 대조</b>를 눌러야 삼성전자·삼화전자 등 전 종목이 보입니다. DB에 없는 종목은 <span class="badge-loss">미등록</span> — 봇 매도 버튼 없음(HTS 매도 또는 추후 동기화).
</div>
<div class="row g-3 align-items-end mt-2">
<div class="col-12">
<label class="form-label param-row" style="color:var(--muted);font-size:12px">전략 (실거래 분석 탭과 동일 ID)</label>
<div class="d-flex flex-wrap gap-2 gap-md-3 mt-1 align-items-center">
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="pf_strategy" value="ALL" checked> 전체
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="pf_strategy" value="SCALP"> SCALP
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="pf_strategy" value="SHORT"> SHORT
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="pf_strategy" value="MOMENTUM"> MOMENTUM
</label>
<label class="d-flex align-items-center gap-1 mb-0" title="해외 모멘텀">
<input type="radio" name="pf_strategy" value="US_MOMENTUM"> 해외모멘텀
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="pf_strategy" value="UPDOW"> UPDOW
</label>
<label class="d-flex align-items-center gap-1 mb-0">
<input type="radio" name="pf_strategy" value="BREAKOUT"> BREAKOUT
</label>
</div>
<div class="col-12" style="font-size:11px;color:var(--muted)">
HOLDING(홀딩봇) 종목은 이 탭에 표시하지 않습니다 — 홀딩 전략 탭·실거래(HOLDING)에서만 조회.
현재가·<b>당일%</b>(전일종가 대비)·매수대비%는 <b>보유중만</b> ws_ticks/ws_candles 라이브(표시 전용, 매매 비접촉).
</div>
</div>
<div class="col-auto">
<button class="btn btn-primary" onclick="pfLoad(false)">🔄 새로고침</button>
</div>
<div class="col-auto">
<button class="btn btn-outline-secondary" onclick="pfLoad(true)" title="한투 잔고 API 1회 (수 초)">📡 실계좌 대조</button>
</div>
<div class="col-auto">
<button class="btn btn-outline-success" onclick="pfReconcileOrphans()" title="봇이 매수했지만 active_trades 에 누락된 종목을 DB에 복구(매도 아님). 수동매수·보호종목 제외.">🧩 봇고아 DB복구</button>
</div>
<div class="col-auto">
<button class="btn btn-outline-danger" onclick="pfSellUntrackedAll()" title="active_trades 에 없는(전략 비어있는) 실계좌 보유분만 시장가 일괄매도. 봇 관리분은 건드리지 않음.">🧹 미등록 전량 매도</button>
</div>
<div class="col-auto">
<span class="text-muted" id="pf_meta" style="font-size:12px"></span>
</div>
</div>
<!-- 실계좌 대조 시 계좌 요약 (입금·예수금·평가) -->
<div class="row g-2 mt-2" id="pf_account_row" style="display:none">
<div class="col-6 col-md-3"><div class="card p-2" style="background:rgba(88,166,255,0.06);border-color:var(--accent)">
<div class="card-title" style="font-size:11px">총 입금액</div>
<div class="stat-val" id="pf_total_deposit" style="font-size:16px"></div>
</div></div>
<div class="col-6 col-md-3"><div class="card p-2">
<div class="card-title" style="font-size:11px">예수금</div>
<div class="stat-val" id="pf_cash" style="font-size:16px"></div>
</div></div>
<div class="col-6 col-md-3"><div class="card p-2">
<div class="card-title" style="font-size:11px">주식 평가금</div>
<div class="stat-val" id="pf_holdings_eval" style="font-size:16px"></div>
</div></div>
<div class="col-6 col-md-3"><div class="card p-2">
<div class="card-title" style="font-size:11px">총자산(예수금+평가)</div>
<div class="stat-val" id="pf_total_asset" style="font-size:16px"></div>
</div></div>
</div>
<div class="mt-2" style="font-size:11px;color:var(--muted);line-height:1.5">
<b>동기 배지:</b>
<span class="badge-win">OK</span> DB·실계좌 수량 일치 ·
<span class="badge-loss">주의</span> 수량 불일치(HTS에서 수동 매매했을 수 있음) ·
<span class="badge-loss">봇고아</span> 봇 매수 기록은 있는데 active_trades 없음 →
<b>🧩 봇고아 DB복구</b> ·
<span class="badge-win">홀딩봇</span> HOLDING 관리 종목(여기서 매도 안 함)
</div>
</div>
<div class="trade-sort-bar mb-2" id="pf_sort_bar">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn active" data-sort="pnl_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="pnl_asc">수익률↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="eval_desc">평가금↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="eval_asc">평가금↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="name_asc">종목명</button>
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="untracked_first">미등록먼저</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" id="pf_table">
<thead><tr>
<th>전략</th><th>종목</th><th>매수시각</th><th>DB수량</th><th>실계좌</th><th>동기</th>
<th>DB매수가</th><th>실평단</th><th>현재가</th>
<th title="전일종가 대비 당일 등락">당일%</th>
<th title="매수가(평단) 대비">매수대비%</th>
<th>평가금</th><th>매도</th>
</tr></thead>
<tbody id="pf_tbody"></tbody>
</table>
</div>
<div id="pf_empty" class="text-muted py-3" style="display:none;font-size:13px">
active_trades 에 보유 종목이 없습니다.
</div>
</div>
</div><!-- tab-portfolio end -->
<!-- ═══ 스캘핑 백테스트 탭 ═══════════════════════════════════════════════ -->
<div id="tab-backtest" style="display:none">
<div class="card p-3 mb-3" style="border-left:4px solid var(--accent)">
<div style="font-size:14px;line-height:1.7">
<b>📉 스캘핑 Reversal — 키움 <code>scalp_re</code> 조건검색 + RSI V자 반전</b><br>
<span style="color:var(--muted);font-size:12px">
<b>SCAN</b>: 키움 조건검색 → <code>target_candidates_history</code> (strategy_id=SCALP)<br>
<b>TRIGGER</b>: RSI 과매도 반등 · 낙폭필터 · (선택) MACD 골든크로스 — <code>scalping_engine</code> 라이브와 100% 동일<br>
• 모멘텀 추격은 <b>🌊 모멘텀 백테스트</b> 탭 사용 (SCALP 와 분리)
</span>
</div>
</div>
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end mb-2">
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="bt_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="bt_end" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="종목당 1회 매수 금액">1회투자(원)<span class="d-block text-muted fw-normal" style="font-size:10px">SCALP_SLOT_MONEY</span></label>
<input type="number" class="form-control" id="bt_slot" value="3000000" min="100000" step="100000" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="동시 보유 종목 수">동시보유(종)<span class="d-block text-muted fw-normal" style="font-size:10px">SCALP_MAX_STOCKS</span></label>
<input type="number" class="form-control" id="bt_max_stocks" value="3" min="1" max="50" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="총 운용한도 — 수익률% 분모">총운용한도(원)<span class="d-block text-muted fw-normal" style="font-size:10px">SCALP_TOTAL_BUDGET_KRW</span></label>
<input type="number" class="form-control" id="bt_total_budget" value="9000000" min="0" step="100000" style="width:130px">
</div>
<div class="col-12 mt-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bt_use_univ_history" checked>
<label class="form-check-label" for="bt_use_univ_history" style="font-size:12px;color:var(--muted)">
<b>저장 후보 이력</b> (strategy_id=SCALP) — 체크: DB 슬롯·후보 / 해제: 반전 시뮬 유니버스
</label>
</div>
<div class="mt-1 d-flex align-items-center gap-2 flex-wrap" style="font-size:12px;color:var(--muted)">
<label for="bt_univ_history_source" class="mb-0">이력소스</label>
<select class="form-select form-select-sm" id="bt_univ_history_source" style="width:160px"
title="BACKTEST_UNIVERSE_HISTORY_SOURCE — 키움 target_candidates_history / LS ls_candidates_history">
<option value="kiwoom" selected>키움 (target_candidates)</option>
<option value="ls">LS (ls_candidates)</option>
</select>
<label class="mb-0 ms-2">캔들</label>
<select class="form-select form-select-sm" id="bt_candle_source" style="width:70px" title="기본=실매 LIVE_TICK_PROVIDER 우선 병합">
<option value="" title="실매 LIVE_TICK_PROVIDER 순서 (kiwoom→kis→rest)">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">시세(틱)</label>
<select class="form-select form-select-sm" id="bt_tick_source" style="width:70px">
<option value="">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">호가</label>
<select class="form-select form-select-sm" id="bt_ob_source" style="width:70px">
<option value="">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
</div>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="bt_env_timeline">
<label class="form-check-label" for="bt_env_timeline" style="font-size:12px;color:var(--muted)" title="ON: 봉 시각별 과거 env 스냅샷으로 파람 덮어씀. OFF(기본): 폼 파람 고정">
<b>env 타임라인</b> — 체크: 그 시각 DB설정 재현 / <b>해제(기본)</b>: 폼 파람으로 구간 전체
</label>
</div>
</div>
<!-- 기본 파라미터 -->
<div class="col-4 col-md-1">
<label class="form-label param-row">RSI 기간</label>
<input type="number" class="form-control" id="bt_rsi_period" value="3" min="2" max="14">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">RSI 과매도</label>
<input type="number" class="form-control" id="bt_rsi_oversold" value="18" min="10" max="45" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="이 값 초과 시 고점추격으로 진입 금지">RSI 과열</label>
<input type="number" class="form-control" id="bt_rsi_overbought" value="75" min="50" max="100" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">손절(%)</label>
<input type="number" class="form-control" id="bt_sl" value="1.5" min="0.3" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">익절(%)</label>
<input type="number" class="form-control" id="bt_tp" value="1.5" min="0.3" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="익절 % 상한 — tp_pct가 이보다 크면 목표가는 이 값으로 캡">익절상한%</label>
<input type="number" class="form-control" id="bt_tp_max" value="2.0" min="0.3" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">낙폭필터(%)</label>
<input type="number" class="form-control" id="bt_drop" value="2.0" min="0.5" max="5" step="0.1">
</div>
</div>
<!-- 고급 필터 (2행) -->
<div class="row g-2 align-items-end mt-1">
<div class="col-4 col-md-1">
<label class="form-label param-row" title="손익 후 같은 종목 재진입 금지 시간(분)">쿨다운(분)</label>
<input type="number" class="form-control" id="bt_cooldown" value="10" min="0" max="60" step="5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="현재봉 거래량 > 20봉평균 × N배. 0=비활성">거래량배수(0=끔)</label>
<input type="number" class="form-control" id="bt_vol_mult" value="0" min="0" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="어깨 발동: 진입가 대비 이 % 이상 올라야 고점 추적 시작">어깨발동%</label>
<input type="number" class="form-control" id="bt_smin" value="0.5" min="0" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="어깨 폭: 갱신된 고점 대비 이 % 하락 시 1순위 청산">어깨폭%</label>
<input type="number" class="form-control" id="bt_scut" value="0.3" min="0.1" max="3" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="매수 가능 시작 시각(HHMM)">매수시작</label>
<input type="number" class="form-control" id="bt_time_start" value="830" min="830" max="1500" step="10" style="width:80px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="매수 가능 종료 시각(HHMM)">매수종료</label>
<input type="number" class="form-control" id="bt_time_end" value="1530" min="900" max="1530" step="10" style="width:80px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="종목당 하루 최대 거래횟수">일일최대매수</label>
<input type="number" class="form-control" id="bt_max_daily" value="3" min="1" max="10">
</div>
</div>
<!-- EOD 장마감 청산 -->
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#161b22;border:1px solid #30363d">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:#79c0ff">EOD 장마감 청산</b></span></div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="bt_eod_enabled" checked>
<label class="form-check-label param-row" for="bt_eod_enabled" title="ON=설정 시각 이후 보유 전량 당일청산 (실매 장마감청산)">EOD청산</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="EOD 당일청산 시각 (HH:MM)">EOD시각<span class="d-block text-muted fw-normal" style="font-size:10px">SCALP_EOD_HM</span></label>
<input type="text" class="form-control" id="bt_eod_hm" value="15:25" placeholder="15:25">
</div>
</div>
<!-- TRIGGER (SCAN vs TRIGGER — tail·모멘텀 탭과 동일 패턴) -->
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#0d1117;border:1px solid #21262d">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">TRIGGER 필터</b> — HTS SCAN 통과 후 엔진 검사</span></div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bt_skip_hts_dupes" checked>
<label class="form-check-label" for="bt_skip_hts_dupes" style="font-size:12px" title="SCALP_SKIP_HTS_SCAN_DUPES — 낙폭·RSI·거래량 중복 생략">HTS중복스킵</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bt_require_reversal" checked>
<label class="form-check-label" for="bt_require_reversal" style="font-size:12px" title="SCALP_REQUIRE_REVERSAL_CANDLE">반전캔들필수</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bt_use_defense" checked>
<label class="form-check-label" for="bt_use_defense" style="font-size:12px">진입방어 ON</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bt_use_macd">
<label class="form-check-label" for="bt_use_macd" style="font-size:12px" title="SCALP_USE_MACD_CROSS">MACD골든크로스</label>
</div>
</div>
</div>
<!-- 방어 수치 -->
<div class="row g-2 align-items-end mt-1">
<div class="col-4 col-md-1">
<label class="form-label param-row" title="당일고가 대비 이 비율 이하면 진입 허용">고점추격방지</label>
<input type="number" class="form-control" id="bt_high_chase" value="0.96" min="0.5" max="1" step="0.01">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="당일 등락률 이 값 초과 시 진입 금지(%)">급등주필터(%)</label>
<input type="number" class="form-control" id="bt_max_daily_chg" value="20" min="0" max="100" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="이 가격 미만 종목 진입 금지(원)">최소가격(원)</label>
<input type="number" class="form-control" id="bt_min_price" value="1000" min="0" step="100">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="종목당 1회 최대 손실 한도(원)">1회최대손실(원)</label>
<input type="number" class="form-control" id="bt_max_loss_krw" value="200000" min="0" step="10000">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="본절사수 시 최소 순이익 마진(%)">본절마진(%)</label>
<input type="number" class="form-control" id="bt_min_margin" value="0.2" min="0" max="2" step="0.1">
</div>
<div class="col-12 col-md-auto mt-2 d-flex gap-2 flex-wrap align-items-center">
<button class="btn btn-primary px-4" id="bt_btn_run_bg" onclick="btJobStart('scalp')">🚀 백그라운드 실행</button>
<button class="btn btn-outline-primary px-3" onclick="runBacktest()">동기 실행</button>
<button class="btn btn-outline-danger px-2 py-1" id="bt_btn_stop_bg" onclick="btJobStop()" disabled>중지</button>
<button class="btn btn-success px-3" onclick="saveScalpConfig()">💾 봇에 설정저장</button>
<span class="text-muted" style="font-size:11px">탐색: CLI param_search_scalping.py · 전역 1잡(전략 충돌 방지)</span>
</div>
<div class="col-12">
<div class="optuna-prog-track mb-1" style="height:10px;max-width:480px">
<div class="optuna-prog-fill" id="scalp_bt_tab_fill" style="width:0%"></div>
</div>
<div class="text-muted" style="font-size:11px" id="scalp_bt_tab_status">
백그라운드=CLI 잡 · 탭 이동 OK · 파라미터=DB(+기간/유니버스) · 동기=짧을 때
</div>
</div>
</div>
<div class="mt-3 p-2 rounded" style="background:#0d1117;border:1px solid #21262d;font-size:11px;color:var(--muted)">
<b style="color:var(--accent)">📖 SCAN vs TRIGGER vs 청산</b><br>
SCAN: 키움 <code>scalp_re</code> · TRIGGER: RSI V자 + (skip OFF 시) 낙폭·거래량·반전캔들 · 청산: 어깨→익절→손절→금액손실→EOD (tp_max는 익절 상한) · 진입=신호봉 다음봉 시가 · 탐색: <code>param_search_scalping.py</code>
</div>
</div>
<!-- 파라미터 요약 -->
<div id="bt_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<!-- 요약 카드 (꼬리/모멘텀/돌파와 동일 8칸) -->
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="b_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="b_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="b_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="b_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="b_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="b_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="b_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="b_daily_avg_pct">-</div>
</div></div>
</div>
<!-- Buy & Hold 비교 -->
<!-- 승/패 바 -->
<div class="card p-3 mb-3" id="bt_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="b_win_label">-</span>
<span style="color:var(--red)" id="b_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="b_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="b_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3">
<div class="col-12 col-lg-8">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선 (가상)</div>
<canvas id="b_equity_chart" height="220"></canvas>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card p-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="b_reason_chart" height="200"></canvas>
</div>
</div>
</div>
<div class="card p-3 mt-3">
<div class="card-title mb-2">일별 손익 (가상)</div>
<canvas id="b_daily_chart" height="150"></canvas>
</div>
<!-- 백테스트 거래 목록 -->
<div class="section-title">가상 거래 내역 (최근 200건)</div>
<div id="bt_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="bt_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" id="bt_table">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th><th>보유(분)</th><th title="매수 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매수호가</th><th title="매도 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매도호가</th><th>매도사유</th><th>진입RSI</th>
</tr></thead>
<tbody id="bt_tbody"></tbody>
</table>
</div>
</div>
</div><!-- tab-backtest end -->
<!-- ═══ 꼬리잡기 백테스트 탭 ══════════════════════════════════════════════ -->
<div id="tab-tail" style="display:none">
<div class="card p-3 mb-3">
<!-- 기간 -->
<div class="row g-2 align-items-end mb-2">
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="tl_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="tl_end" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="1회 매수 금액 — 실매 SLOT_MONEY_DEFAULT / resolve_invest_amount_krw">1회투자금(원)</label>
<input type="number" class="form-control" id="tl_slot" value="3000000" min="100000" step="100000" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="동시 보유 매입금 합 상한 — env SHORT_TOTAL_BUDGET_KRW (0=동시보유×1회투자금)">총 운용한도(원)</label>
<input type="number" class="form-control" id="tl_total_budget" value="9000000" min="0" step="100000" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="동시 보유 종목 수 — env SHORT_MAX_STOCKS / MAX_STOCKS">동시보유(종목)</label>
<input type="number" class="form-control" id="tl_max_stocks" value="3" min="1" max="50" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="ws_candles.timeframe — DB에 해당 분봉이 있어야 함 (실매 3분 기본)">분봉(TF)</label>
<select class="form-control" id="tl_tf" style="width:100px">
<option value="3" selected>3분</option>
<option value="5">5분</option>
<option value="15">15분</option>
<option value="60">60분</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row" title="limit_atr=ATR 지정가 대기 / align=다음봉 시가">진입모드</label>
<select class="form-select" id="tl_entry_mode" style="width:130px">
<option value="limit_atr" selected>C limit_atr</option>
<option value="align">A align</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row" title="TAIL_LIMIT_ATR_MULT — anchorATR×배수">지정가×ATR</label>
<input type="number" class="form-control" id="tl_limit_atr_mult" value="1.5" min="0.5" max="5" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="TAIL_LIMIT_ANCHOR">기준가</label>
<select class="form-select" id="tl_limit_anchor" style="width:110px">
<option value="signal_low" selected>신호저점</option>
<option value="signal_close">신호종가</option>
<option value="prev_close">전봉종가</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row" title="TAIL_LIMIT_VALID_BARS — 체결 대기 봉 수(3분봉)">유효봉</label>
<input type="number" class="form-control" id="tl_limit_valid_bars" value="1" min="1" max="5" step="1" style="width:56px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="TAIL_LIMIT_FILL_SLIP_PCT — 백테 체결 보정">체결슬립(%)</label>
<input type="number" class="form-control" id="tl_limit_fill_slip" value="0" min="0" max="1" step="0.01" style="width:72px">
</div>
</div>
<div class="row g-2 align-items-end mb-2">
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_use_univ_history" checked>
<label class="form-check-label" for="tl_use_univ_history" style="font-size:12px;color:var(--muted)">
<b>저장 후보 이력</b> — 체크: DB 슬롯·후보 / 해제: ws_candles 전 종목
</label>
</div>
<div class="mt-1 d-flex align-items-center gap-2 flex-wrap" style="font-size:12px;color:var(--muted)">
<label for="tl_univ_history_source" class="mb-0">이력소스</label>
<select class="form-select form-select-sm" id="tl_univ_history_source" style="width:160px"
title="BACKTEST_UNIVERSE_HISTORY_SOURCE — 키움 / LS">
<option value="kiwoom" selected>키움 (target_candidates)</option>
<option value="ls">LS (ls_candidates)</option>
</select>
<label class="mb-0 ms-2">캔들</label>
<select class="form-select form-select-sm" id="tl_candle_source" style="width:70px" title="기본=실매 LIVE_TICK_PROVIDER 우선 병합">
<option value="" title="실매 LIVE_TICK_PROVIDER 순서 (kiwoom→kis→rest)">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">시세(틱)</label>
<select class="form-select form-select-sm" id="tl_tick_source" style="width:70px">
<option value="">전체</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">호가</label>
<select class="form-select form-select-sm" id="tl_ob_source" style="width:70px">
<option value="">전체</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
</div>
<div class="form-check form-check-inline mt-1">
<input class="form-check-input" type="checkbox" id="tl_use_tick_db" checked>
<label class="form-check-label" for="tl_use_tick_db" style="font-size:12px;color:var(--muted)"
title="TAIL_BACKTEST_USE_TICK_DB — 기본 ON. limit_atr·align 진입가를 ws_ticks로 재생(실매 체결 정합)">
<b>틱 진입</b> (<code>ws_ticks</code>) — 기본 ON
</label>
</div>
<div class="form-check form-check-inline mt-1 bt-ohlc-fallback-danger"
title="절대금지: 틱 모드에서 OHLC 폴백으로 체결·고점·PnL 변조. 엔진은 틱 청산 ON 시 이 체크를 무시함.">
<input class="form-check-input" type="checkbox" id="tl_tick_fallback_ohlc">
<label class="form-check-label" for="tl_tick_fallback_ohlc"
title="TAIL_BACKTEST_TICK_FALLBACK_OHLC — 기본 OFF. ON=정합 파괴(유령거래). 틱 청산 ON이면 엔진 무시.">
⚠ 틱 없으면 <b>OHLC 폴백</b><b>정합 위험 · 기본 OFF · 사용 금지</b>
</label>
<div class="bt-ohlc-fallback-warn">백테·Optuna·파람서치에서 OHLC로 숫자 변조 절대금지 (실매=틱만)</div>
</div>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="tl_env_timeline">
<label class="form-check-label" for="tl_env_timeline" style="font-size:12px;color:var(--muted)" title="ON: 봉 시각별 과거 env. OFF(기본): 폼 파람 고정">
<b>env 타임라인</b> — 체크: 그 시각 DB설정 재현 / <b>해제(기본)</b>: 폼 파람으로 구간 전체
</label>
</div>
</div>
</div>
<!-- 핵심 파라미터 (1행) -->
<div class="row g-2 align-items-end">
<div class="col-4 col-md-1">
<label class="form-label param-row" title="당일 시가→저가 낙폭이 이 값 이상이어야 진입">낙폭필터(%)</label>
<input type="number" class="form-control" id="tl_drop" value="2.0" min="0.5" max="10" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="(현재가-저가)/(고가-저가) 최소 회복 비율(%)">회복률(%)</label>
<input type="number" class="form-control" id="tl_rec" value="45" min="10" max="90" step="5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="꼬리길이/몸통길이 최소 비율 (망치봉 강도)">꼬리/몸통</label>
<input type="number" class="form-control" id="tl_tail" value="1.5" min="0.3" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">손절(%)</label>
<input type="number" class="form-control" id="tl_sl" value="3.0" min="0.5" max="10" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">익절(%)</label>
<input type="number" class="form-control" id="tl_tp" value="5.0" min="0.5" max="15" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="매수가 대비 이 값 이상 오른 뒤 어깨 컷 발동">어깨발동(%)</label>
<input type="number" class="form-control" id="tl_smin" value="0.3" min="0.1" max="2" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="갱신된 max_price 대비 이 % 하락 시 어깨 컷 (1순위 청산)">어깨컷(%)</label>
<input type="number" class="form-control" id="tl_scut" value="0.2" min="0.05" max="2" step="0.05">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="TAIL_TRAIL_PCT — 보조 트레일 하락폭(고점 대비). 0=OFF">보조트레일(%)</label>
<input type="number" class="form-control" id="tl_trail" value="0" min="0" max="5" step="0.1" style="width:80px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="TAIL_TRAIL_ARM_PCT — 이 수익% 도달 후 보조트레일 무장. 0=즉시">트레일무장(%)</label>
<input type="number" class="form-control" id="tl_trail_arm" value="0" min="0" max="5" step="0.1" style="width:80px">
</div>
<div class="col-12 col-md-3">
<label class="form-label param-row" title="래칫 ON 시 단일 어깨 대체. 형식: 수익%:컷%,… (비우면 단일 어깨)">래칫단계 TAIL_RATCHET_TIERS</label>
<select class="form-select form-select-sm mb-1" id="tl_ratchet_preset"
title="파람서치 그리드 프리셋 — 고르면 아래 칸이 채워집니다(직접 수정 가능)"
onchange="btApplyPreset('tl_ratchet', this.value, true)">
<option value="__custom__">프리셋 선택…(직접입력)</option>
<option value="off">off (단일 어깨컷)</option>
<option value="0.5:0.3,1.0:0.25,2.0:0.2">0.5:0.3,1.0:0.25,2.0:0.2 (3단)</option>
<option value="1.0:0.4,2.0:0.3">1.0:0.4,2.0:0.3 (2단)</option>
</select>
<input type="text" class="form-control" id="tl_ratchet" value="" placeholder="0.5:0.3,1.0:0.25,2.0:0.2" style="font-size:12px" oninput="tlSyncRatchetShoulderColors&&tlSyncRatchetShoulderColors()">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="꼬리 길이 최소 비율(%) → TAIL_PCT_MIN">꼬리최소(%)</label>
<input type="number" class="form-control" id="tl_tail_pct" value="0.3" min="0.01" max="2" step="0.05">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="3분봉 회복위치 상한(%) → MAX_RECOVERY_RATIO_3M">3분최대회복(%)</label>
<input type="number" class="form-control" id="tl_max_rec_3m" value="90" min="50" max="100" step="5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="고점 대비 이 비율 이상이면 진입 거부(%) → HIGH_PRICE_CHASE_THRESHOLD">고점추격방지(%)</label>
<input type="number" class="form-control" id="tl_high_chase" value="96" min="90" max="100" step="1">
</div>
</div>
<!-- 당일 누적손익 다단트레일 — SHORT_DAILY_PROFIT_TARGET_ENABLED -->
<div class="row g-2 align-items-end mt-1">
<div class="col-12"><span style="font-size:11px;color:var(--muted)">📅 다단트레일 ON이면 당일 실현손익 고점 대비 되돌릴 때 <b>신규매수만</b> 중단. <b>리스크버짓(B)</b> ON이면 hit 후 보유최악손절합&gt;cushion 이면 전량정리. DB=<code>SHORT_DAILY_PROFIT_*</code>.</span></div>
<div class="col-auto">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="tl_daily_profit_enabled">
<label class="form-check-label param-row" for="tl_daily_profit_enabled" title="SHORT_DAILY_PROFIT_TARGET_ENABLED — 다단트레일 ON/OFF. 로드=DB, 봇저장 시 DB 반영">다단트레일</label>
</div>
</div>
<div class="col-auto">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="tl_daily_risk_budget_enabled">
<label class="form-check-label param-row" for="tl_daily_risk_budget_enabled" title="SHORT_DAILY_PROFIT_RISK_BUDGET_ENABLED — 기본 OFF">리스크버짓(B)</label>
</div>
</div>
<div class="col-12 col-md-4">
<label class="form-label param-row" title="다단 트레일(ratchet식): 수익원:컷%,… — 벌수록 컷% 타이트하게 사수. 비우면 단일 되돌림 사용. 예: 30000:50,100000:35,300000:25">다단규칙(수익원:컷%,…)</label>
<select class="form-select form-select-sm mb-1" id="tl_daily_trail_preset"
title="프리셋 — 고르면 아래 칸이 채워집니다(감시 스위치는 그대로)"
onchange="btApplyPreset('tl_daily_trail_tiers', this.value, false)">
<option value="__custom__">프리셋 선택…(직접입력)</option>
<option value="off">off (다단 숫자 비움)</option>
<option value="20000:40,50000:30,150000:20">보수 20000:40,50000:30,150000:20</option>
<option value="30000:50,100000:35,300000:25">중도 30000:50,100000:35,300000:25</option>
<option value="50000:60,200000:45,500000:30">공격 50000:60,200000:45,500000:30</option>
</select>
<input type="text" class="form-control" id="tl_daily_trail_tiers" value="" placeholder="30000:50,100000:35,300000:25" style="font-size:12px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="다단이 비었을 때만: 당일 실현손익 고점 대비 이 % 되돌리면 중단. 0=미사용">단일되돌림(%)</label>
<input type="number" class="form-control" id="tl_daily_trail_drop" value="0" min="0" max="90" step="5" style="width:110px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="단일 되돌림용: 이 수익(원) 이상 벌어야 감시 시작. 0이면 비활성(과민발동 방지)">발동최소수익(원)</label>
<input type="number" class="form-control" id="tl_daily_trail_arm" value="0" min="0" step="50000" style="width:130px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="trailing=트레일만 / both=고정목표(운영설정)+트레일 먼저 닿는 쪽">방식</label>
<select class="form-select" id="tl_daily_profit_mode" style="width:120px">
<option value="trailing" selected>trailing</option>
<option value="both">both</option>
</select>
</div>
</div>
<!-- V3 방어 파라미터 -->
<div class="row g-2 align-items-end mt-1">
<div class="col-4 col-md-1">
<label class="form-label param-row" title="최소 주가">최소가격(원)</label>
<input type="number" class="form-control" id="tl_min_price" value="1000" min="0" step="500">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="당일 최고/최저 상승폭 제한">최대급등(%)</label>
<input type="number" class="form-control" id="tl_max_daily_change" value="20" min="5" max="30" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="MA20 대비 가격 이격도 허용 범위">MA20이격(%)</label>
<input type="number" class="form-control" id="tl_ma20_above" value="3.0" min="1.0" max="10.0" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="1회 매매 최대 손실 원화 (금액 컷)">최대손실컷(원)</label>
<input type="number" class="form-control" id="tl_max_loss_krw" value="200000" min="10000" step="10000">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="금액손실컷 발동 최소 하락률(%) — 이 미만은 흔들림으로 보고 미발동">손실컷최소하락(%)</label>
<input type="number" class="form-control" id="tl_min_drop_loss_cut" value="1.5" min="0.5" max="5" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="ATR 기준 손절 배수 (변동성 대응)">ATR손절(배)</label>
<input type="number" class="form-control" id="tl_stop_atr" value="1.5" min="0.5" max="10" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="ATR 기준 익절 배수 (2순위 백업)">ATR익절(배)</label>
<input type="number" class="form-control" id="tl_target_atr" value="2.0" min="1.0" max="20" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="ATR 손절 % 하한 (캡)">ATR손절하한%</label>
<input type="number" class="form-control" id="tl_atr_sl_min" value="0.8" min="0.1" max="20" step="0.1" style="width:78px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="ATR 손절 % 상한 (캡)">ATR손절상한%</label>
<input type="number" class="form-control" id="tl_atr_sl_max" value="1.0" min="0.5" max="30" step="0.1" style="width:78px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="ATR 익절 % 하한 (캡)">ATR익절하한%</label>
<input type="number" class="form-control" id="tl_atr_tp_min" value="0.3" min="0.1" max="20" step="0.1" style="width:78px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="ATR 익절 % 상한 (캡)">ATR익절상한%</label>
<input type="number" class="form-control" id="tl_atr_tp_max" value="1.0" min="0.2" max="30" step="0.1" style="width:78px">
</div>
</div>
<!-- 고급 파라미터 (2행) -->
<div class="row g-2 align-items-end mt-1">
<div class="col-4 col-md-1">
<label class="form-label param-row" title="RSI 계산 캔들 수 (실매·파라서치와 동일)">RSI기간</label>
<input type="number" class="form-control" id="tl_rsi_period" value="14" min="3" max="21" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="RSI 이 값 이상이면 과열로 진입 거부">RSI과열기준</label>
<input type="number" class="form-control" id="tl_rsi" value="78" min="50" max="95" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="청산 후 같은 종목 재진입 금지 시간(분)">쿨다운(분)</label>
<input type="number" class="form-control" id="tl_cool" value="30" min="0" max="120" step="5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">매수시작(HHMM)</label>
<input type="number" class="form-control" id="tl_ts" value="830" min="900" max="1500" step="100">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">매수종료(HHMM)</label>
<input type="number" class="form-control" id="tl_te" value="1530" min="900" max="1530" step="100">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="종목당 하루 최대 거래횟수 (안전판)">일일최대매수</label>
<input type="number" class="form-control" id="tl_maxd" value="20" min="1" max="50">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="종목당 당일 실현손익 한도(원, 양수) — 이하면 그 종목만 재진입 금지">종목손실한도(원)</label>
<input type="number" class="form-control" id="tl_symbol_loss_krw" value="30000" min="0" step="5000">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="1회투자금 대비 % — KRW·% 중 먼저 닿는 쪽 적용">종목손실한도(%)</label>
<input type="number" class="form-control" id="tl_symbol_loss_pct" value="1.5" min="0" max="10" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="재진입 허용 최소 당일 누적순익(원, 수수료·세금 감안)">재진입최소(원)</label>
<input type="number" class="form-control" id="tl_reentry_min_edge" value="0" min="0" step="500">
</div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="tl_eod_enabled" checked>
<label class="form-check-label param-row" for="tl_eod_enabled" title="ON=설정 시각 이후 보유 전량 당일청산">EOD청산</label>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row" title="EOD 당일청산 시각 (HH:MM)">EOD시각</label>
<input type="text" class="form-control" id="tl_eod_hm" value="15:25" placeholder="15:25" style="width:72px">
</div>
</div>
<!-- TRIGGER 플래그 (SCAN vs TRIGGER — 실매·백테·저장 동일) -->
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#0d1117;border:1px solid #21262d">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">TRIGGER 필터</b> — 매수 직전 엔진 검사 (HTS tail 조건 통과 후)</span></div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_skip_hts_dupes" checked>
<label class="form-check-label" for="tl_skip_hts_dupes" style="font-size:12px" title="3분봉 직전대비 등락(BAR_CHG) 재검사 생략 — HTS 일봉A/1분G와 축이 다름">봉등락재검스킵</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_use_rsi_filter" checked>
<label class="form-check-label" for="tl_use_rsi_filter" style="font-size:12px">RSI필터</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_use_ma20_filter">
<label class="form-check-label" for="tl_use_ma20_filter" style="font-size:12px">MA20필터</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_use_daily_range" checked>
<label class="form-check-label" for="tl_use_daily_range" style="font-size:12px">당일변동필터</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_use_high_chase_f" checked>
<label class="form-check-label" for="tl_use_high_chase_f" style="font-size:12px">고점추격필터</label>
</div>
</div>
<div class="col-6 col-md-2" title="이 백테 1회에만 적용 (실매 미반영). 저장 시에만 DB 반영">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_ob_filter" checked>
<label class="form-check-label" for="tl_ob_filter" style="font-size:12px">호가필터(백테)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_pg_filter" checked>
<label class="form-check-label" for="tl_pg_filter" style="font-size:12px">프로그램필터(백테)</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="호가 스프레드 상한(%). kiwoom_0d 본체 재계산(6/25~)">스프레드(%)<span class="d-block text-muted fw-normal" style="font-size:10px">MAX_SPREAD</span></label>
<input type="number" step="0.01" class="form-control form-control-sm" id="tl_max_spread_pct" value="0.45">
</div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tl_use_intraday_drop">
<label class="form-check-label" for="tl_use_intraday_drop" style="font-size:12px">당일낙폭필터</label>
</div>
</div>
<div class="col-6 col-md-2">
<label class="form-label param-row" title="0=OFF. 신호봉 거래량 ≥ 직전 N봉평균×배수 (TRIGGER)">거래량배수</label>
<input type="number" class="form-control" id="tl_tail_vol_mult" value="0" min="0" max="10" step="0.1" style="width:78px">
</div>
<div class="col-6 col-md-1">
<label class="form-label param-row" title="거래량 평균 창(봉 수)">거래량창</label>
<input type="number" class="form-control" id="tl_tail_vol_win" value="5" min="1" max="30" step="1" style="width:58px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" style="font-size:11px">봉등락MIN%</label>
<input type="number" class="form-control" id="tl_bar_chg_min" value="-10" min="-30" max="0" step="0.5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" style="font-size:11px">봉등락MAX%</label>
<input type="number" class="form-control" id="tl_bar_chg_max" value="-1.5" min="-30" max="0" step="0.5">
</div>
</div>
<!-- 반전 패턴 OR (TRIGGER — 낙폭·회복 필터 AND 유지) -->
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#0d1117;border:1px solid #21262d">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">반전 패턴</b> — 하나라도 충족 시 진입 (env <code>TAIL_PATTERN_*</code>)</span></div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_hammer" checked>
<label class="form-check-label" for="tl_pat_hammer" style="font-size:12px" title="TAIL_PATTERN_HAMMER">망치</label>
</div>
</div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_pin">
<label class="form-check-label" for="tl_pat_pin" style="font-size:12px" title="TAIL_PATTERN_PIN">핀바</label>
</div>
</div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_engulfing">
<label class="form-check-label" for="tl_pat_engulfing" style="font-size:12px" title="TAIL_PATTERN_ENGULFING">장악</label>
</div>
</div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_piercing">
<label class="form-check-label" for="tl_pat_piercing" style="font-size:12px" title="TAIL_PATTERN_PIERCING">관통</label>
</div>
</div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_harami">
<label class="form-check-label" for="tl_pat_harami" style="font-size:12px" title="TAIL_PATTERN_HARAMI">하라미</label>
</div>
</div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_doji">
<label class="form-check-label" for="tl_pat_doji" style="font-size:12px" title="TAIL_PATTERN_DOJI">도지</label>
</div>
</div>
<div class="col-6 col-md-auto">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="tl_pat_morning_star">
<label class="form-check-label" for="tl_pat_morning_star" style="font-size:12px" title="TAIL_PATTERN_MORNING_STAR">샛별</label>
</div>
</div>
</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12 col-md-auto mt-2 d-flex gap-2 flex-wrap align-items-center">
<button class="btn btn-primary px-4" id="tl_btn_run_bg" onclick="btJobStart('tail')">🚀 백그라운드 실행</button>
<button class="btn btn-outline-primary px-3" onclick="runTailBacktest()">동기 실행</button>
<button class="btn btn-outline-danger px-2 py-1" id="tl_btn_stop_bg" onclick="btJobStop()" disabled>중지</button>
<button class="btn btn-success px-3" onclick="saveTailConfig()">💾 봇에 설정저장</button>
<button class="btn btn-outline-info px-3" onclick="loadTailSearchResults()">📂 탐색결과 불러오기</button>
</div>
<div class="col-12">
<div class="optuna-prog-track mb-1" style="height:10px;max-width:480px">
<div class="optuna-prog-fill" id="tlbt_tab_fill" style="width:0%"></div>
</div>
<div class="text-muted" style="font-size:11px" id="tlbt_tab_status">
백그라운드=CLI 잡(타임아웃 없음) · <b>탭을 옮겨도 계속 실행</b> · 상단 바로 진행률 ·
<b>전역 1잡</b>(스캘핑/돌파/모멘텀과 동시 실행 불가) · 파라미터=DB(+기간/틱) ·
동기 실행=기존 HTTP(짧을 때만)
</div>
</div>
</div>
<!-- 파라미터 설명 -->
<div class="mt-3 p-2 rounded" style="background:#0d1117;border:1px solid #21262d;font-size:11px;color:var(--muted)">
<b style="color:var(--accent)">📖 파라미터 설명 (실매·파라서치·백테 동일 — tail_engine / config_short)</b>
<div class="row g-1 mt-1">
<div class="col-12 col-md-6">
<table style="width:100%;border-collapse:collapse">
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">분봉(TF)</td><td>백테·파라서치에 쓰는 <b>ws_candles.timeframe</b> (3·5·15·60). DB에 해당 분봉 봉이 있어야 함.</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">낙폭필터(%)</td><td>당일 시가→저가 하락폭 → DB: <b>MIN_DROP_RATE</b> (config_short)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">회복률(%)</td><td>당일 저점 대비 회복 하한 → <b>MIN_RECOVERY_RATIO_SHORT</b></td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">3분최대회복(%)</td><td>3분봉 회복 위치 상한 → <b>MAX_RECOVERY_RATIO_3M</b></td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">꼬리/몸통</td><td>망 hammer → <b>TAIL_RATIO_MIN</b> · 패턴 OR → <b>TAIL_PATTERN_*</b></td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">청산순서</td><td><b>1)어깨(max_price)</b> → 2)ATR익절 → 3)ATR손절 → 4)금액손실컷</td></tr>
</table>
</div>
<div class="col-12 col-md-6">
<table style="width:100%;border-collapse:collapse">
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">어깨발동(%)</td><td>진입가 대비 이 수익% 이상이면 max_price 추적 → <b>SHOULDER_MIN_HIGH_PCT</b> (예: 0.3%)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">어깨컷(%)</td><td><b>갱신된 max_price × (1cut)</b><b>SHOULDER_CUT_PCT</b> (예: 0.2%)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">ATR캡</td><td><b>TAIL_ATR_*_MIN/MAX_PCT</b> · 배수 <b>STOP/TARGET_ATR_MULTIPLIER_TAIL</b></td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">1회투자금</td><td>실매 <b>SLOT_MONEY_DEFAULT</b> / SHORT_MAX_BUY_AMOUNT (종목당 상한)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">총 운용한도</td><td>동시 보유 매입금 합 ≤ <b>SHORT_TOTAL_BUDGET_KRW</b> (0=동시보유×1회투자금)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">동시보유</td><td><b>SHORT_MAX_STOCKS</b> / MAX_STOCKS — 시각순 포트폴리오, 1봉 1매수</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">봇저장</td><td><code>insert_env_snapshot</code><b>config_short</b> + env_config 자동 분리</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">일일최대매수</td><td><b>TAIL_MAX_DAILY</b> — 무한루프 안전판(기본 20). 실질 제어는 아래 손실한도·재진입최소.</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">종목손실한도</td><td><b>TAIL_SYMBOL_DAILY_LOSS_LIMIT_KRW/PCT</b>(양수) — 종목 당일 실현손익이 −한도 이하면 그 종목만 재진입 금지. KRW·% 중 <b>먼저 닿는 쪽</b>.</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">재진입최소(원)</td><td><b>TAIL_REENTRY_MIN_EDGE_KRW</b> — 2회째 진입부터 당일 누적순익이 이 값 미만이면 차단(회전매매 방지).</td></tr>
</table>
</div>
</div>
<div class="mt-1">⚡ 진입가 = <b>신호봉(3분봉) 다음 봉 시가</b> | 수수료 0.015%×2 + 거래세 0.18% 자동 차감 | 데이터: ws_candles 3분봉</div>
<div class="mt-1" style="color:var(--muted)">📌 백테는 <b>시각순 포트폴리오</b>(실매 MAX_STOCKS·총한도·1회 slot_money)로 실행됩니다. 웹·파라서치 맞추려면 시작/종료·TF·저장 이력·동시보유·총한도를 동일하게 두세요.</div>
</div>
</div>
<div id="tl_search_result" style="display:none" class="mb-3">
<div class="section-title">🔍 파라미터 탐색 결과 (CLI search_tail_*.json)</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead id="tl_search_thead"><tr><th>-</th></tr></thead>
<tbody id="tl_search_tbody"></tbody>
</table>
</div>
<p id="tl_search_hint" class="text-muted" style="display:none;font-size:11px;margin-top:8px;line-height:1.45;"></p>
</div>
</div>
<!-- 파라미터 요약 바 -->
<div id="tl_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<!-- 요약 카드 -->
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="tl_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="tl_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="tl_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="tl_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="tl_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="tl_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="tl_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="tl_daily_avg_pct">-</div>
</div></div>
</div>
<!-- 승/패 바 -->
<div class="card p-3 mb-3" id="tl_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="tl_win_label">-</span>
<span style="color:var(--red)" id="tl_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="tl_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="tl_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3">
<div class="col-12 col-lg-8">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선 (가상)</div>
<canvas id="tl_equity_chart" height="220"></canvas>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card p-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="tl_reason_chart" height="200"></canvas>
</div>
</div>
</div>
<div class="card p-3 mt-3">
<div class="card-title mb-2">일별 손익 (가상)</div>
<canvas id="tl_daily_chart" height="150"></canvas>
</div>
<!-- 거래 내역 테이블 -->
<div class="section-title">가상 거래 내역 (최근 200건)</div>
<div id="tl_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="tl_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" id="tl_table">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th>
<th>보유(분)</th><th>체결디버그</th><th title="매수 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매수호가</th><th title="매도 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매도호가</th><th>매도사유</th>
</tr></thead>
<tbody id="tl_tbody"></tbody>
</table>
</div>
</div>
</div><!-- tab-tail end -->
<!-- ═══ 더블 볼린저(DBBAND) — 종목별 파라미터 ═══════════════════════════════ -->
<div id="tab-dbband" style="display:none">
<div class="card p-3 mb-3">
<p class="mb-2" style="font-size:12px;color:var(--muted)">
<b>종목 1개씩</b> 파라미터·백테·탐색 (QQQM·379810 등 서로 다른 BB/MA).
백테·파라서치 데이터: <code>holding_min_candles</code> (아래 <b>키움/KIS 분봉 수집</b>으로 DB 저장).
실매 라이브 봉: <code>ws_candles</code> (영구구독 WS) — 백테와 별개.
저장: <code>dbband_stock_config</code> · 그리드 <code>DBBAND_GRID_*</code> env.
</p>
<div class="row g-2 align-items-end mb-2">
<div class="col-auto">
<label class="form-label param-row">종목</label>
<select class="form-control" id="db_code" style="min-width:220px"></select>
</div>
<div class="col-auto">
<label class="form-label param-row">분봉</label>
<select class="form-control" id="db_tf" style="width:100px">
<option value="5">5분</option>
<option value="15" selected>15분</option>
<option value="60">60분</option>
<option value="3">3분</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="db_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="db_end" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="키움/KIS 분봉 수집 시작일 — holding_min_candles">분봉수집 시작</label>
<input type="date" class="form-control" id="db_fetch_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">1회투자(원)</label>
<input type="number" class="form-control" id="db_slot" value="3000000" min="100000" step="100000" style="width:120px">
</div>
</div>
<div class="row g-2 align-items-end mb-2">
<div class="col-auto"><label class="form-label param-row">BB기간</label><input type="number" class="form-control" id="db_period" value="20" style="width:72px"></div>
<div class="col-auto"><label class="form-label param-row">Innerσ</label><input type="number" class="form-control" id="db_inner_std" value="2" step="0.1" style="width:72px"></div>
<div class="col-auto"><label class="form-label param-row">Outerσ</label><input type="number" class="form-control" id="db_outer_std" value="3" step="0.1" style="width:72px"></div>
<div class="col-auto"><label class="form-label param-row">추세MA</label><input type="number" class="form-control" id="db_trend_ma" value="200" style="width:80px"></div>
<div class="col-auto">
<label class="form-label param-row" title="classic=영상원형(반대밴드·신호저점), v4_scalp=단타어깨컷">청산모드</label>
<select class="form-select" id="db_exit_mode" style="width:130px" onchange="dbSyncExitModeUi()">
<option value="classic" selected>영상원형</option>
<option value="v4_scalp">단타V4</option>
</select>
</div>
<div class="col-auto"><label class="form-label param-row">손절%</label><input type="number" class="form-control" id="db_sl" value="2" step="0.5" style="width:72px" title="classic: 신호저점 우선(보조)"></div>
<div class="col-auto"><label class="form-label param-row">익절%</label><input type="number" class="form-control" id="db_tp" value="3" step="0.5" style="width:72px"></div>
<div class="col-auto">
<label class="form-label param-row">익절모드</label>
<select class="form-select" id="db_tp_mode" style="width:120px">
<option value="opposite_band" selected>반대밴드</option>
<option value="pct">고정%</option>
<option value="rr">손익비</option>
</select>
</div>
<div class="col-auto"><label class="form-label param-row">RR</label><input type="number" class="form-control" id="db_rr" value="2" step="0.5" style="width:72px"></div>
<div class="col-auto"><label class="form-label param-row">유효봉</label><input type="number" class="form-control" id="db_valid_bars" value="3" style="width:64px"></div>
<div class="col-auto" id="db_max_hold_wrap"><label class="form-label param-row">최대보유</label><input type="number" class="form-control" id="db_max_hold" value="0" min="0" style="width:64px" title="0=off (영상원형)"></div>
</div>
<div class="row g-2 align-items-end">
<div class="col-auto form-check mt-2">
<input class="form-check-input" type="checkbox" id="db_use_trend" checked>
<label class="form-check-label" for="db_use_trend">추세 MA 필터</label>
</div>
<div class="col-auto form-check mt-2">
<input class="form-check-input" type="checkbox" id="db_env_timeline">
<label class="form-check-label" for="db_env_timeline" style="font-size:12px;color:var(--muted)" title="ON: 봉 시각별 과거 env. OFF(기본): 폼 파람 고정">env 타임라인</label>
</div>
<div class="col-12 col-md-auto mt-2 d-flex gap-1 flex-wrap align-items-center">
<span class="align-self-center me-1" style="font-size:11px;color:var(--muted)">분봉수집</span>
<button type="button" class="btn btn-sm btn-outline-secondary" style="color:#58a6ff;border-color:#58a6ff" onclick="dbFetchMinKiwoom(60)" title="KR=키움 ka10080 / US=KIS 해외분봉 → holding_min_candles">60분</button>
<button type="button" class="btn btn-sm btn-outline-secondary" style="color:#58a6ff;border-color:#58a6ff" onclick="dbFetchMinKiwoom(15)" title="백테 TF와 동일하게 맞출 것">15분</button>
<button type="button" class="btn btn-sm btn-outline-secondary" style="color:#58a6ff;border-color:#58a6ff" onclick="dbFetchMinKiwoom(5)">5분</button>
<button type="button" class="btn btn-sm btn-outline-secondary" style="color:#58a6ff;border-color:#58a6ff" onclick="dbFetchMinKiwoom(3)">3분</button>
<span id="db_min_badge" class="align-self-center" style="font-size:11px;color:var(--muted)">DB봉: —</span>
<span id="db_min_status" style="font-size:11px;color:var(--accent);align-self:center"></span>
</div>
<div class="col-auto mt-2">
<button class="btn btn-primary" onclick="runDbBandBacktest()">▶ 백테</button>
<button class="btn btn-outline-info ms-1" onclick="runDbBandParamSearch()">🔍 파라서치</button>
<button class="btn btn-outline-secondary ms-1" onclick="saveDbBandStockConfig()">💾 종목저장</button>
</div>
<div class="col-auto mt-2"><span id="db_param_source" class="badge badge-secondary" style="font-size:11px"></span></div>
</div>
</div>
<div id="db_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<div id="db_result_area" style="display:none">
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">총 거래</div><div class="stat-val" id="db_total">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">승률</div><div class="stat-val" id="db_winrate">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="db_pnl">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">Profit Factor</div><div class="stat-val" id="db_pf">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="db_mdd">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">평균 보유(분)</div><div class="stat-val" id="db_hold">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="db_bot_pct">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">일평균 수익률</div><div class="stat-val" id="db_daily_avg_pct">-</div></div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3"><div class="card-title">백테 봉수</div><div class="stat-val" id="db_candles">-</div></div></div>
</div>
<div class="card p-3 mb-3" id="db_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="db_win_label">-</span>
<span style="color:var(--red)" id="db_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="db_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="db_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3 mb-3" id="db_bnh_row">
<div class="col-12"><div class="card p-3" style="border-color:var(--accent);background:rgba(88,166,255,0.05)">
<div class="card-title" style="color:var(--accent)">📊 Buy &amp; Hold 벤치마크 (같은 기간·1회투자금)</div>
<div class="row g-3 mt-1">
<div class="col-6 col-md-3"><div class="card-title">봇 수익률</div><div class="stat-val" id="db_bot_pct_bnh">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">B&amp;H 수익률</div><div class="stat-val" id="db_bnh_pct">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">B&amp;H 손익(원)</div><div class="stat-val" id="db_bnh_pnl">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">알파(봇B&amp;H)</div><div class="stat-val" id="db_alpha">-</div></div>
</div>
</div></div>
</div>
<div class="row g-3 mb-3">
<div class="col-12 col-lg-8">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선 (가상)</div>
<canvas id="db_equity_chart" height="220"></canvas>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card p-3">
<div class="card-title mb-2">청산 사유 분포</div>
<canvas id="db_reason_chart" height="200"></canvas>
</div>
</div>
</div>
<div class="card p-3">
<table class="table table-hover"><thead><tr>
<th>방향</th><th>매수</th><th>매도</th><th>진입</th><th>청산</th><th>손익</th><th></th><th>사유</th>
</tr></thead><tbody id="db_tbody"></tbody></table>
</div>
</div><!-- db_result_area -->
<div id="db_search_results" class="card p-3 mt-3" style="display:none">
<div class="card-title mb-2">파라서치 상위</div>
<div class="table-responsive"><table class="table table-sm"><thead><tr>
<th>#</th><th>손익</th><th>승률</th><th>거래</th><th>Inner/Outer</th><th>MA</th><th>적용</th>
</tr></thead><tbody id="db_search_tbody"></tbody></table></div>
</div>
</div><!-- tab-dbband end -->
<!-- ═══ 돌파매매 백테스트 탭 ═════════════════════════════════════════════ -->
<div id="tab-breakout" style="display:none">
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end flex-wrap">
<!-- 기간 (꼬리 탭과 동일 col-auto) -->
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="bo_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="bo_end" style="width:150px">
</div>
<!-- 매수 룰 (키움 'breakout' 조건식 1:1 매핑) -->
<div class="col-auto">
<label class="form-label param-row" title="직전 N봉 최대고가 돌파 검사 (키움: 1봉)">Lookback(분봉)</label>
<input type="number" class="form-control" id="bo_lookback" value="1" min="1" max="60" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="직전 N봉 평균 거래량 윈도우 (키움: 1봉)">VolWin(분봉)</label>
<input type="number" class="form-control" id="bo_vol_win" value="7" min="1" max="60" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="1분 거래량÷유통주식×100 (키움 ka10001 dstr_stk). 1차 거래량 게이트">1분회전율min(%)<span class="d-block text-muted fw-normal" style="font-size:10px">유통주식 대비 · BREAKOUT_MIN_TURNOVER_1M_PCT</span></label>
<input type="number" class="form-control" id="bo_min_turnover" value="0.05" min="0" max="5" step="0.01" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="0=OFF. 켜면 직전 N봉 평균×배수 추가 검사 (HTS 300%=3)">거래량배수(보조)<span class="d-block text-muted fw-normal" style="font-size:10px">0=OFF · BREAKOUT_VOL_MULT</span></label>
<input type="number" class="form-control" id="bo_vol_mult" value="0" min="0" max="10" step="0.5" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="직전봉 등락률 하한">직전봉↑min(%)</label>
<input type="number" class="form-control" id="bo_prev_min" value="0.5" min="0" max="20" step="0.5" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="직전봉 등락률 상한">직전봉↑max(%)</label>
<input type="number" class="form-control" id="bo_prev_max" value="8.0" min="0" max="30" step="0.5" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="intrabar=B(봉내 돌파·HTS E) align=A(다음봉 시가)">진입모드</label>
<select class="form-select" id="bo_entry_mode" style="width:120px">
<option value="intrabar" selected>B intrabar</option>
<option value="align">A align</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row" title="백테 B안 터치가 보정(%)">B슬리피지(%)</label>
<input type="number" class="form-control" id="bo_intrabar_slip" value="0" min="0" max="1" step="0.01" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="1회 매수 금액 — BREAKOUT_SLOT_MONEY">1회투자(원)</label>
<input type="number" class="form-control" id="bo_slot" value="200000" min="100000" step="100000" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="동시 보유 — BREAKOUT_MAX_STOCKS">동시보유(종)</label>
<input type="number" class="form-control" id="bo_max_stocks" value="20" min="1" max="50" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="총 운용한도 — 수익률% 분모">총운용한도(원)</label>
<input type="number" class="form-control" id="bo_total_budget" value="2000000" min="0" step="100000" style="width:130px">
</div>
</div>
<!-- TRIGGER (SCAN vs TRIGGER — 스캘핑·모멘텀 탭과 동일 패턴) -->
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#0d1117;border:1px solid #21262d">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">TRIGGER 필터</b> — HTS breakout SCAN 통과 후 엔진 검사</span></div>
<div class="col-6 col-md-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bo_skip_hts_dupes" checked>
<label class="form-check-label" for="bo_skip_hts_dupes" style="font-size:12px" title="BREAKOUT_SKIP_HTS_SCAN_DUPES — 일봉 돌파·등락·거래량 중복 생략">HTS중복스킵</label>
</div>
</div>
</div>
<!-- 매도/포지션 (2행) -->
<div class="row g-2 align-items-end mt-1 flex-wrap">
<div class="col-auto">
<label class="form-label param-row" title="fixed=고정% 손절 · atr=변동성(ATR) 비례 동적 손절">손절모드<span class="d-block text-muted fw-normal" style="font-size:10px">BREAKOUT_SL_MODE</span></label>
<select class="form-select" id="bo_sl_mode" style="width:96px" onchange="boSyncSlModeColors()">
<option value="fixed" selected>fixed(%)</option>
<option value="atr">atr(동적)</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row" title="sl_mode=fixed 일 때 진입가 대비 이 % 하락 시 손절">손절(%)</label>
<input type="number" class="form-control" id="bo_sl" value="3.0" min="0.5" max="10" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="ATR(RMA) 기간 — sl_mode=atr 일 때 변동성 측정 창">ATR기간<span class="d-block text-muted fw-normal" style="font-size:10px">BREAKOUT_ATR_PERIOD</span></label>
<input type="number" class="form-control" id="bo_atr_period" value="14" min="5" max="60" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="손절폭(%)=ATR×배수/진입가 — sl_mode=atr 일 때">ATR손절배<span class="d-block text-muted fw-normal" style="font-size:10px">BREAKOUT_ATR_SL_MULT</span></label>
<input type="number" class="form-control" id="bo_atr_sl_mult" value="2.0" min="0.5" max="10" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="ATR 손절 % 하한 — 휩쏘 방지(너무 타이트해지는 것 차단)">ATR손절하한%<span class="d-block text-muted fw-normal" style="font-size:10px">MIN_PCT</span></label>
<input type="number" class="form-control" id="bo_atr_sl_min" value="0.8" min="0.1" max="20" step="0.1" style="width:78px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="ATR 손절 % 상한 — 급변동 시 과대 손실 방지">ATR손절상한%<span class="d-block text-muted fw-normal" style="font-size:10px">MAX_PCT</span></label>
<input type="number" class="form-control" id="bo_atr_sl_max" value="6.0" min="0.5" max="30" step="0.1" style="width:78px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="진입가 대비 이 % 상승 시 익절">익절(%)</label>
<input type="number" class="form-control" id="bo_tp" value="10.0" min="0.5" max="20" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="고점 대비 이 % 하락 시 트레일링 청산">트레일(%)</label>
<input type="number" class="form-control" id="bo_trail" value="1.5" min="0.1" max="5" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="고점이 진입가×(1+이%) 도달 후에만 보조 트레일 무장. 0=즉시무장(기존). 진입 직후 본전청산 방지">트레일무장(%)</label>
<input type="number" class="form-control" id="bo_trail_arm" value="0" min="0" max="5" step="0.1" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="익절 미달 시 — 진입가 대비 이 % 이상 올라야 고점 추적(2순위 어깨)">어깨발동(%)</label>
<input type="number" class="form-control" id="bo_shoulder_smin" value="0.5" min="0.05" max="5" step="0.05" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="익절 미달 시 — 고점 대비 이 % 하락 시 2순위 어깨컷">어깨폭(%)</label>
<input type="number" class="form-control" id="bo_shoulder_scut" value="0.2" min="0.05" max="5" step="0.05" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="매수 가능 시작 (HHMM)">매수시작</label>
<input type="number" class="form-control" id="bo_time_start" value="830" min="830" max="1500" step="100" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="매수 가능 종료 (HHMM, 골든타임)">매수종료</label>
<input type="number" class="form-control" id="bo_time_end" value="1030" min="900" max="1530" step="30" style="width:80px">
</div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="bo_eod_enabled" checked>
<label class="form-check-label param-row" for="bo_eod_enabled" title="ON=설정 시각 이후 보유 전량 당일청산">EOD청산</label>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row" title="EOD 당일청산 시각 (HH:MM)">EOD시각</label>
<input type="text" class="form-control" id="bo_eod_hm" value="15:15" placeholder="15:15" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="0=OFF · 진입 후 N분 경과 시 시간컷 청산">최대보유(분)</label>
<input type="number" class="form-control" id="bo_max_hold" value="0" min="0" max="390" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="종목당 일일 최대 진입 횟수">일일최대</label>
<input type="number" class="form-control" id="bo_max_daily" value="100" min="1" max="100" step="1" style="width:64px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="종목당 매도 후 재진입 금지(분)">쿨다운(분)</label>
<input type="number" class="form-control" id="bo_cooldown" value="30" min="0" max="240" step="5" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="당일 시가 대비 이 % 초과 상승이면 진입 금지">급등주(%)</label>
<input type="number" class="form-control" id="bo_max_chg" value="15" min="0" max="50" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="이 가격 미만 종목 진입 금지(원)">최소가격</label>
<input type="number" class="form-control" id="bo_min_price" value="1000" min="0" step="100" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="저항선을 이 % 이상 '확실히' 넘겨야 진입. 선만 살짝 찌르는 가짜돌파(휩쏘) 차단. 0=OFF">돌파확인여유(%)</label>
<input type="number" class="form-control" id="bo_confirm_margin" value="0" min="0" max="5" step="0.05" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="돌파봉 양봉 몸통(종가-시가)/시가 가 이 % 이상이어야 진입. 도지·윗꼬리(찌르고 빠짐) 차단. 0=OFF">양봉몸통최소(%)</label>
<input type="number" class="form-control" id="bo_body_min" value="0" min="0" max="10" step="0.05" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="다단 래칫 — 값 있으면 단일 어깨컷 대체. 형식 수익%:컷%,… (BREAKOUT_RATCHET_TIERS). 비우면 OFF">래칫티어</label>
<input type="text" class="form-control" id="bo_ratchet" value="" placeholder="3:1.5,6:1.0" style="width:160px;font-size:12px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="종목당 1회 최대 손실(원)">1회최대손실</label>
<input type="number" class="form-control" id="bo_max_loss" value="200000" min="0" step="10000" style="width:110px">
</div>
</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-6 col-md-2">
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="bo_use_ema_f">
<label class="form-check-label" for="bo_use_ema_f" style="font-size:12px">EMA추세필터 (TRIGGER)</label>
</div>
</div>
<div class="col-6 col-md-2" title="이 백테 1회에만 적용 (실매 미반영). 저장 시에만 DB 반영">
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="bo_ob_filter" checked>
<label class="form-check-label" for="bo_ob_filter" style="font-size:12px">호가필터(백테)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bo_pg_filter" checked>
<label class="form-check-label" for="bo_pg_filter" style="font-size:12px">프로그램필터(백테)</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="호가 스프레드 상한(%). kiwoom_0d 본체 재계산(6/25~)">스프레드(%)<span class="d-block text-muted fw-normal" style="font-size:10px">MAX_SPREAD</span></label>
<input type="number" step="0.01" class="form-control form-control-sm" id="bo_max_spread_pct" value="0.45">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="EMA 추세 필터 빠른 기간">EMA빠름<span class="d-block text-muted fw-normal" style="font-size:10px">fast · BREAKOUT_EMA_FAST_PERIOD</span></label>
<input type="number" class="form-control" id="bo_ema_fast" value="9" min="2" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="EMA 추세 필터 느린 기간">EMA느림<span class="d-block text-muted fw-normal" style="font-size:10px">slow · BREAKOUT_EMA_SLOW_PERIOD</span></label>
<input type="number" class="form-control" id="bo_ema_slow" value="21" min="3" max="120" step="1">
</div>
</div>
<!-- 당일 누적손익 다단트레일 — BREAKOUT_DAILY_PROFIT_TARGET_ENABLED -->
<div class="row g-2 align-items-end mt-1">
<div class="col-12"><span style="font-size:11px;color:var(--muted)">📅 다단트레일 ON이면 당일 실현손익 고점 대비 되돌릴 때 <b>신규매수만</b> 중단. <b>리스크버짓(B)</b> ON이면 hit 후 보유최악손절합&gt;cushion 이면 전량정리. DB=<code>BREAKOUT_DAILY_PROFIT_*</code>.</span></div>
<div class="col-auto">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="bo_daily_profit_enabled">
<label class="form-check-label param-row" for="bo_daily_profit_enabled" title="BREAKOUT_DAILY_PROFIT_TARGET_ENABLED — 다단트레일 ON/OFF. 로드=DB, 봇저장 시 DB 반영">다단트레일</label>
</div>
</div>
<div class="col-auto">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="bo_daily_risk_budget_enabled">
<label class="form-check-label param-row" for="bo_daily_risk_budget_enabled" title="BREAKOUT_DAILY_PROFIT_RISK_BUDGET_ENABLED — 기본 OFF">리스크버짓(B)</label>
</div>
</div>
<div class="col-12 col-md-4">
<label class="form-label param-row" title="다단 트레일(ratchet식): 수익원:컷%,… — 벌수록 컷% 타이트. 비우면 단일 되돌림 사용. 예: 30000:50,100000:35,300000:25">다단규칙(수익원:컷%,…)</label>
<select class="form-select form-select-sm mb-1" id="bo_daily_trail_preset"
title="프리셋 — 고르면 아래 칸이 채워집니다(감시 스위치는 그대로)"
onchange="btApplyPreset('bo_daily_trail_tiers', this.value, false)">
<option value="__custom__">프리셋 선택…(직접입력)</option>
<option value="off">off (다단 숫자 비움)</option>
<option value="20000:40,50000:30,150000:20">보수 20000:40,50000:30,150000:20</option>
<option value="30000:50,100000:35,300000:25">중도 30000:50,100000:35,300000:25</option>
<option value="50000:60,200000:45,500000:30">공격 50000:60,200000:45,500000:30</option>
</select>
<input type="text" class="form-control" id="bo_daily_trail_tiers" value="" placeholder="30000:50,100000:35,300000:25" style="font-size:12px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="다단이 비었을 때만: 당일 실현손익 고점 대비 이 % 되돌리면 중단. 0=미사용">단일되돌림(%)</label>
<input type="number" class="form-control" id="bo_daily_trail_drop" value="0" min="0" max="90" step="5" style="width:110px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="단일 되돌림용: 이 수익(원) 이상 벌어야 감시 시작. 0이면 비활성(과민발동 방지)">발동최소수익(원)</label>
<input type="number" class="form-control" id="bo_daily_trail_arm" value="0" min="0" step="50000" style="width:130px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="trailing=고점되돌림만 / both=고정목표(운영설정)+트레일 먼저 닿는 쪽">방식</label>
<select class="form-select" id="bo_daily_profit_mode" style="width:120px">
<option value="trailing" selected>trailing</option>
<option value="both">both</option>
</select>
</div>
</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="bo_use_univ_history" checked>
<label class="form-check-label" for="bo_use_univ_history" style="font-size:12px;color:var(--muted)">
<b>저장 후보 이력</b> — 체크: DB 슬롯·후보 / 해제: ws_candles 전 종목
</label>
</div>
<div class="mt-1 d-flex align-items-center gap-2 flex-wrap" style="font-size:12px;color:var(--muted)">
<label for="bo_univ_history_source" class="mb-0">이력소스</label>
<select class="form-select form-select-sm" id="bo_univ_history_source" style="width:160px"
title="BACKTEST_UNIVERSE_HISTORY_SOURCE — 키움 / LS">
<option value="kiwoom" selected>키움 (target_candidates)</option>
<option value="ls">LS (ls_candidates)</option>
</select>
<label class="mb-0 ms-2">캔들</label>
<select class="form-select form-select-sm" id="bo_candle_source" style="width:70px" title="기본=실매 LIVE_TICK_PROVIDER 우선 병합">
<option value="" title="실매 LIVE_TICK_PROVIDER 순서 (kiwoom→kis→rest)">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">시세(틱)</label>
<select class="form-select form-select-sm" id="bo_tick_source" style="width:70px">
<option value="">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">호가</label>
<select class="form-select form-select-sm" id="bo_ob_source" style="width:70px">
<option value="">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
</div>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="bo_env_timeline">
<label class="form-check-label" for="bo_env_timeline" style="font-size:12px;color:var(--muted)" title="ON: 봉 시각별 과거 env. OFF(기본): 폼 파람 고정">
<b>env 타임라인</b> — 체크: 그 시각 DB설정 재현 / <b>해제(기본)</b>: 폼 파람으로 구간 전체
</label>
</div>
</div>
<div class="col-12 col-md-auto mt-2 d-flex gap-2 flex-wrap align-items-center">
<button class="btn btn-primary px-4" id="bo_btn_run_bg" onclick="btJobStart('breakout')">🚀 백그라운드 실행</button>
<button class="btn btn-outline-primary px-3" onclick="runBreakoutBacktest()">동기 실행</button>
<button class="btn btn-outline-danger px-2 py-1" id="bo_btn_stop_bg" onclick="btJobStop()" disabled>중지</button>
<button type="button" class="btn btn-outline-info px-3" onclick="saveBreakoutConfig()" title="현재 입력값을 BREAKOUT_* env 에 저장">💾 봇에 설정저장</button>
<span class="text-muted" style="font-size:11px">탐색: CLI · 전역 1잡</span>
</div>
<div class="col-12">
<div class="optuna-prog-track mb-1" style="height:10px;max-width:480px">
<div class="optuna-prog-fill" id="bo_bt_tab_fill" style="width:0%"></div>
</div>
<div class="text-muted" style="font-size:11px" id="bo_bt_tab_status">백그라운드=CLI 잡 · 탭 이동 OK · DB 파라미터</div>
</div>
</div>
<!-- 파라미터 설명 -->
<div class="mt-3 p-2 rounded" style="background:#0d1117;border:1px solid #21262d;font-size:11px;color:var(--muted)">
<b style="color:var(--accent)">📖 키움 'breakout' 조건식 ↔ 봇 룰 매핑</b>
<div class="row g-1 mt-1">
<div class="col-12 col-md-6">
<table style="width:100%;font-size:11px;border-collapse:collapse">
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">진입모드 B</td><td><b>intrabar</b>=봉 안 저항 돌파·현재가 (실매·HTS E) · <b>align</b>=확정봉 후 다음봉 시가 (구 A안)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">Lookback / VolWin</td><td>둘 다 <b>1</b>이면 키움 'breakout' 조건과 100% 동일 (직전 1봉 기준)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">1분회전율 / 거래량배수</td><td><b>회전율</b>=유통주식 대비 1분 체결%(ka10001) 1차 · <b>거래량배수</b>=직전 N봉 평균×배수(0=OFF, HTS 300%=3)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">직전봉 등락률</td><td>키움 조건은 <b>1~10%</b>. 0.5~15% 범위에서 튜닝 가능.</td></tr>
<tr><td style="color:#d29922;padding:1px 6px;white-space:nowrap">매수시작/종료</td><td>파라서치 fast는 <b>10:30·11:30</b> 종료 탐색. 웹에서 15:30이면 1위 조합과 불일치·수익 악화.</td></tr>
<tr><td style="color:#d29922;padding:1px 6px;white-space:nowrap">운용한도</td><td>총수익률·일평균 % 분모. 파라서치 <code>--total-budget</code> 와 동일해야 비교 가능.</td></tr>
</table>
</div>
<div class="col-12 col-md-6">
<table style="width:100%;font-size:11px;border-collapse:collapse">
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">손절/익절/트레일</td><td>봇 BREAKOUT_STOP_LOSS_PCT=-2% / TAKE_PROFIT=+5% / TRAIL=1.5% 기본</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">트레일무장(%)</td><td>고점이 진입가×(1+무장%) 도달 후에만 보조 트레일 작동. <b>0=즉시</b> · 백테 1.5% 권장(본전청산↓)</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">급등주(%)</td><td>당일 시가 대비 누적 상승률. 이 값 초과 종목은 이격 과열로 진입 금지.</td></tr>
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">일일최대 / 쿨다운</td><td>돌파는 종목당 1번/일 권장. 손절 후 30분 재진입 금지로 휩쏘 회피.</td></tr>
</table>
</div>
</div>
</div>
</div>
<!-- 파라미터 요약 바 (꼬리 탭과 동일) -->
<div id="bo_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<!-- 결과 영역 (첫 백테스트 성공 후 표시) -->
<div id="bo_result_area" style="display:none">
<!-- 요약 카드 — 꼬리 탭과 동일 stat-val 레이아웃 -->
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="bo_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="bo_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="bo_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="bo_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="bo_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="bo_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="bo_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="bo_daily_avg_pct">-</div>
</div></div>
</div>
<!-- 승/패 바 -->
<div class="card p-3 mb-3" id="bo_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="bo_win_label">-</span>
<span style="color:var(--red)" id="bo_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="bo_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="bo_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3">
<div class="col-12 col-lg-8">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선 (가상)</div>
<canvas id="bo_equity_chart" height="220"></canvas>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card p-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="bo_reason_chart" height="200"></canvas>
</div>
</div>
</div>
<div class="card p-3 mt-3">
<div class="card-title mb-2">일별 손익 (가상)</div>
<canvas id="bo_daily_chart" height="150"></canvas>
</div>
<!-- 거래 내역 -->
<div class="section-title">가상 거래 내역 (최근 200건)</div>
<div id="bo_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="bo_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th>
<th>보유(분)</th><th>체결디버그</th><th title="매수 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매수호가</th><th title="매도 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매도호가</th><th>매도사유</th>
</tr></thead>
<tbody id="bo_tbody"></tbody>
</table>
</div>
</div>
</div><!-- bo_result_area -->
</div><!-- tab-breakout end -->
<!-- ═══ 박스권 돌파(RANGE_BREAK) 백테스트 탭 ═══════════════════════════════ -->
<div id="tab-range_break" style="display:none">
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end flex-wrap">
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="rb_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="rb_end" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="박스 형성 lookback(분)">박스Lookback(분)</label>
<input type="number" class="form-control" id="rb_box_lb" value="30" min="10" max="120" step="5" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="박스 고저폭 상한(%)">박스폭max(%)</label>
<input type="number" class="form-control" id="rb_box_max_w" value="2.5" min="0.5" max="8" step="0.1" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="박스 평균거래량 ≤ 기준×배수">횡보거래량×</label>
<input type="number" class="form-control" id="rb_setup_vol" value="0.8" min="0.3" max="1.5" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="박스 구간 최소 음봉 수">음봉min</label>
<input type="number" class="form-control" id="rb_bear_min" value="1" min="0" max="10" step="1" style="width:64px">
</div>
<div class="col-auto">
<label class="form-label param-row">VolWin</label>
<input type="number" class="form-control" id="rb_vol_win" value="7" min="1" max="60" style="width:64px">
</div>
<div class="col-auto">
<label class="form-label param-row">거래량배수</label>
<input type="number" class="form-control" id="rb_vol_mult" value="2.0" min="1" max="10" step="0.5" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">1회투자(원)</label>
<input type="number" class="form-control" id="rb_slot" value="200000" min="100000" step="100000" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row">동시보유(종)</label>
<input type="number" class="form-control" id="rb_max_stocks" value="20" min="1" max="50" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">총운용한도(원)</label>
<input type="number" class="form-control" id="rb_total_budget" value="2000000" min="0" step="100000" style="width:130px">
</div>
</div>
<div class="row g-2 align-items-end mt-1 flex-wrap">
<div class="col-auto">
<label class="form-label param-row">손절(%)</label>
<input type="number" class="form-control" id="rb_sl" value="3.0" min="0.5" max="10" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">익절(%)</label>
<input type="number" class="form-control" id="rb_tp" value="10.0" min="0.5" max="20" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">트레일(%)</label>
<input type="number" class="form-control" id="rb_trail" value="1.5" min="0.1" max="5" step="0.1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">트레일무장(%)</label>
<input type="number" class="form-control" id="rb_trail_arm" value="1.5" min="0" max="5" step="0.1" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row">어깨발동(%)</label>
<input type="number" class="form-control" id="rb_shoulder_smin" value="3.0" min="0.05" max="5" step="0.05" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">어깨폭(%)</label>
<input type="number" class="form-control" id="rb_shoulder_scut" value="0.5" min="0.05" max="5" step="0.05" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">매수시작</label>
<input type="number" class="form-control" id="rb_time_start" value="1030" min="900" max="1500" step="30" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row">매수종료</label>
<input type="number" class="form-control" id="rb_time_end" value="1520" min="1000" max="1530" step="10" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row">일일최대</label>
<input type="number" class="form-control" id="rb_max_daily" value="1" min="1" max="5" style="width:64px">
</div>
<div class="col-auto">
<label class="form-label param-row">쿨다운(분)</label>
<input type="number" class="form-control" id="rb_cooldown" value="30" min="0" max="240" step="5" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">급등주(%)</label>
<input type="number" class="form-control" id="rb_max_chg" value="25" min="0" max="50" step="1" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">최소가격</label>
<input type="number" class="form-control" id="rb_min_price" value="1000" min="0" step="100" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row">1회최대손실</label>
<input type="number" class="form-control" id="rb_max_loss" value="200000" min="0" step="10000" style="width:110px">
</div>
<div class="col-auto">
<div class="form-check mt-4">
<input class="form-check-input" type="checkbox" id="rb_use_high_chase" checked>
<label class="form-check-label" for="rb_use_high_chase" style="font-size:12px">고점추격필터</label>
</div>
</div>
</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="rb_use_univ_history" checked>
<label class="form-check-label" for="rb_use_univ_history" style="font-size:12px;color:var(--muted)">
<b>저장 후보 이력</b> (<code>target_candidates_history</code>, strategy_id=RANGE_BREAK)
</label>
</div>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="rb_env_timeline">
<label class="form-check-label" for="rb_env_timeline" style="font-size:12px;color:var(--muted)" title="ON: 봉 시각별 과거 env. OFF(기본): 폼 파람 고정">
<b>env 타임라인</b> — 체크: 그 시각 DB설정 재현 / <b>해제(기본)</b>: 폼 파람으로 구간 전체
</label>
</div>
</div>
<div class="col-12 col-md-auto mt-2 d-flex gap-2 flex-wrap">
<button class="btn btn-primary px-4" onclick="runRangeBreakBacktest()">🚀 백테스트 실행</button>
<button type="button" class="btn btn-outline-info px-3" onclick="saveRangeBreakConfig()">💾 봇에 설정저장</button>
<span class="text-muted" style="font-size:11px">탐색: CLI param_search_range_break.py</span>
</div>
</div>
<div class="mt-3 p-2 rounded" style="background:#0d1117;border:1px solid #21262d;font-size:11px;color:var(--muted)">
<b style="color:var(--accent)">📖 박스권 돌파 — SCAN vs TRIGGER</b><br>
SCAN: HTS momentum(F·G·J) · TRIGGER: N분 박스(저거래 횡보) → 양봉+거래량 폭발로 상단 돌파 · 청산: 박스실패→익절→어깨→손절→트레일
</div>
</div>
<div id="rb_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<div id="rb_result_area" style="display:none">
<!-- 요약 카드 — 꼬리/스캘핑과 동일 8칸 -->
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="rb_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="rb_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="rb_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="rb_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="rb_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="rb_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="rb_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="rb_daily_avg_pct">-</div>
</div></div>
</div>
<div class="card p-3 mb-3" id="rb_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="rb_win_label">-</span>
<span style="color:var(--red)" id="rb_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="rb_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="rb_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3 mb-3">
<div class="col-md-6"><div class="card p-3"><div class="card-title">누적손익</div><canvas id="rb_equity_chart" height="120"></canvas></div></div>
<div class="col-md-3"><div class="card p-3"><div class="card-title">청산사유</div><canvas id="rb_reason_chart" height="120"></canvas></div></div>
<div class="col-md-3"><div class="card p-3"><div class="card-title">일별손익</div><canvas id="rb_daily_chart" height="120"></canvas></div></div>
</div>
<div id="rb_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="rb_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="card-title mb-2">거래내역</div>
<div class="table-responsive"><table class="table table-sm table-hover">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th><th>보유(분)</th><th>매도사유</th>
</tr></thead>
<tbody id="rb_tbody"></tbody>
</table></div>
</div>
</div>
</div><!-- tab-range_break end -->
<!-- ═══ 모멘텀 백테스트 탭 ═══════════════════════════════════════════════ -->
<!--
[모멘텀 전략 = 키움 'scalp' 조건검색(갭상승+신고가) 추종]
- 봇: STRATEGY_MOMENTUM_ENABLED=true 로 켜면 MomentumStrategy 가독립 쓰레드로 동작.
- 청산: momentum_engine 전용 — 래칫/어깨 → 트레일 → 손절 → 익절상한(tp_max) → 장마감.
- env 키 <code>MOMENTUM_*</code> 전용.
- 백엔드: /api/backtest/momentum → momentum_engine (SCALP reversal 과 분리).
-->
<div id="tab-momentum" style="display:none">
<!-- 헤더 안내 카드 -->
<div class="card p-3 mb-3" style="border-left:4px solid var(--accent)">
<div style="font-size:14px;line-height:1.7">
<b>🌊 모멘텀 전략 = SCALP(reversal)와 분리된 별도 추세추종 전략</b><br>
<span style="color:var(--muted);font-size:12px">
<b>진입</b>: 키움 <code>scalp</code> 조건검색(갭상승+신고가+거래량 폭증) → 봇 자체 RSI 강세/거래량 spike/양봉 검증<br>
<b>청산</b>: <code>momentum_engine</code><b>래칫/어깨·트레일 우선</b>, 익절%는 <b>tp_max 상한(마지막)</b> · 손절/EOD<br>
<b>봇 ON</b>: <code>STRATEGY_MOMENTUM_ENABLED=true</code> + <code>CONDITION_MOMENTUM_NAME/SEQ</code> 설정<br>
• env 키: <code>MOMENTUM_*</code> 전용
</span>
</div>
</div>
<!-- 공통 기간/슬롯 -->
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end">
<div class="col-auto">
<label class="form-label">시작일</label>
<input type="date" class="form-control" id="mom_start">
</div>
<div class="col-auto">
<label class="form-label">종료일</label>
<input type="date" class="form-control" id="mom_end">
</div>
<div class="col-auto">
<label class="form-label param-row" title="종목당 1회 매수 금액 — 백테·파라serch --slot-money 와 동일">1회투자(원)<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_SLOT_MONEY</span></label>
<input type="number" class="form-control" id="mom_slot_money" value="200000" min="100000" step="100000" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="동시 보유 종목 수 — 백테·파라serch --max-stocks">동시보유(종)<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_MAX_STOCKS</span></label>
<input type="number" class="form-control" id="mom_slots" value="20" min="1" max="50" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="총 운용한도 — 수익률% 분모">총운용한도(원)<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_TOTAL_BUDGET_KRW</span></label>
<input type="number" class="form-control" id="mom_total_budget" value="2000000" min="0" step="100000" style="width:130px">
</div>
<div class="col-12" id="mom_portfolio_warn" style="display:none;font-size:12px;color:#f85149"></div>
<div class="col-auto" style="font-size:11px;color:var(--muted)">
<b>1회투자</b>=포트폴리오 매수금(돌파 탭과 동일). <b>1회최대손실÷손절%</b> 자동계산값(천만 등)과 다릅니다.
</div>
<div class="col-12 mt-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="mom_use_univ_history" checked>
<label class="form-check-label" for="mom_use_univ_history" style="font-size:12px;color:var(--muted)">
<b>저장 후보 이력</b> 사용 — <b>체크(기본)</b> = DB 슬롯·후보 재현 (<code>param_search_momentum</code> 기본과 동일).
체크 해제 = 모멘텀 시뮬 유니버스 (<code>--fallback-universe</code>).
</label>
</div>
<div class="mt-1 d-flex align-items-center gap-2 flex-wrap" style="font-size:12px;color:var(--muted)">
<label for="mom_univ_history_source" class="mb-0">이력소스</label>
<select class="form-select form-select-sm" id="mom_univ_history_source" style="width:160px"
title="BACKTEST_UNIVERSE_HISTORY_SOURCE — 키움 / LS">
<option value="kiwoom" selected>키움 (target_candidates)</option>
<option value="ls">LS (ls_candidates)</option>
</select>
<label class="mb-0 ms-2">캔들</label>
<select class="form-select form-select-sm" id="mom_candle_source" style="width:70px" title="기본=실매 LIVE_TICK_PROVIDER 우선 병합">
<option value="" title="실매 LIVE_TICK_PROVIDER 순서 (kiwoom→kis→rest)">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">시세(틱)</label>
<select class="form-select form-select-sm" id="mom_tick_source" style="width:70px">
<option value="">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
<label class="mb-0 ms-1">호가</label>
<select class="form-select form-select-sm" id="mom_ob_source" style="width:70px">
<option value="">기본</option><option value="kis">KIS</option><option value="kiwoom">키움</option>
</select>
</div>
</div>
</div>
</div>
<!-- 모멘텀 TRIGGER V4 — 돌파·눌림재돌파 패턴 OR + V4 어깨청산 (라이브 check_buy_signal_momentum_live 와 1:1) -->
<div class="card p-3 mb-3">
<div class="card-title" style="font-size:13px;color:var(--accent)">📈 모멘텀 TRIGGER V4 (추격 패턴)</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">추격 패턴</b> — 하나라도 충족 시 진입 (env <code>MOMENTUM_PATTERN_*</code>)</span></div>
<div class="col-6 col-md-2">
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="mom_pat_breakout" checked>
<label class="form-check-label" for="mom_pat_breakout" style="font-size:12px" title="MOMENTUM_PATTERN_BREAKOUT">N분 고가 돌파 + 양봉 + 거래량</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="mom_pat_pullback" checked>
<label class="form-check-label" for="mom_pat_pullback" style="font-size:12px" title="MOMENTUM_PATTERN_PULLBACK">스윙고점 → 눌림 → 재돌파</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="돌파 패턴: 직전 N분 고가 돌파 관찰 구간">돌파관찰(분)<span class="d-block text-muted fw-normal" style="font-size:10px">chase lookback · MOMENTUM_CHASE_LOOKBACK_MIN</span></label>
<input type="number" class="form-control" id="mom_chase_lookback" value="10" min="3" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="눌림 패턴: 스윙고점 탐색 구간(분)">눌림관찰(분)<span class="d-block text-muted fw-normal" style="font-size:10px">pullback window · MOMENTUM_PULLBACK_LOOKBACK_MIN</span></label>
<input type="number" class="form-control" id="mom_pullback_lookback" value="15" min="5" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="눌림 최소 깊이(%) — 너무 얕은 눌림 제외">눌림min(%)<span class="d-block text-muted fw-normal" style="font-size:10px">pullback floor · MOMENTUM_PULLBACK_MIN_PCT</span></label>
<input type="number" class="form-control" id="mom_pullback_min" value="0.3" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="눌림 최대 깊이(%) — 너무 깊은 눌림 제외">눌림max(%)<span class="d-block text-muted fw-normal" style="font-size:10px">pullback cap · MOMENTUM_PULLBACK_MAX_PCT</span></label>
<input type="number" class="form-control" id="mom_pullback_max" value="3.0" min="0.5" max="15" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="눌림 구간 평균거래량 ≤ 기준×배수 (V3 setup)">눌림Vol×<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_SETUP_VOL_MAX_MULT</span></label>
<input type="number" class="form-control" id="mom_setup_vol" value="0.8" min="0" max="2" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="눌림 구간 최소 음봉 수 (V3 setup)">눌림음봉min<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_SETUP_BEAR_BARS_MIN</span></label>
<input type="number" class="form-control" id="mom_setup_bear" value="1" min="0" max="10" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="RSI3가 이 값 이상이어야 진입 (약세 제외)">RSI min<span class="d-block text-muted fw-normal" style="font-size:10px">RSI floor · MOMENTUM_RSI_MIN</span></label>
<input type="number" class="form-control" id="mom_rsi_min" value="50" min="30" max="95" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="RSI 상한 필터 ON 시 이 값 초과 진입 금지">RSI max<span class="d-block text-muted fw-normal" style="font-size:10px">RSI cap · MOMENTUM_RSI_MAX</span></label>
<input type="number" class="form-control" id="mom_rsi_max" value="90" min="50" max="100" step="1">
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="mom_use_rsi_max_f">
<label class="form-check-label" for="mom_use_rsi_max_f" style="font-size:12px" title="MOMENTUM_USE_RSI_MAX_FILTER">RSI 상한필터 (기본 OFF)</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="현재봉 거래량 ≥ 직전 N봉 평균 × 이 배수">거래량배수<span class="d-block text-muted fw-normal" style="font-size:10px">vol spike · MOMENTUM_VOL_MULT</span></label>
<input type="number" class="form-control" id="mom_vol_mult" value="1.5" min="0" max="50" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="거래량 평균 계산용 직전 봉 개수">관찰봉수<span class="d-block text-muted fw-normal" style="font-size:10px">vol window · MOMENTUM_VOL_WIN</span></label>
<input type="number" class="form-control" id="mom_vol_win" value="5" min="2" max="30" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="HTS K: 전일 종가 대비 최소 등락(%). 0=종가 초과만. HTS 기본 0.2">전일종가+%(%)<span class="d-block text-muted fw-normal" style="font-size:10px">HTS K · MOMENTUM_E_MIN_CHG_PCT</span></label>
<input type="number" class="form-control" id="mom_e_min_chg" value="0.2" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="매수 종료시각(HHMM)">매수종료<span class="d-block text-muted fw-normal" style="font-size:10px">buy cutoff · MOMENTUM_TIME_END_HM</span></label>
<input type="number" class="form-control" id="mom_time_end_buy" value="1430" min="900" max="1530" step="100">
</div>
<div class="col-12 col-md-5">
<div class="mt-1" style="font-size:11px;color:var(--muted)">
V4 TRIGGER: <b>돌파 OR 눌림재돌파</b> + RSI 하한 + 거래량 + (선택) EMA 추세. 청산은 V4 어깨·트레일·손절 순.
고점추격·시가과열·RSI상한은 <b>기본 OFF</b> — 필요 시 아래 방어 체크박스에서 켜세요.
<br>레거시 시가컷: <code>mom_max_from_open=999</code> 이면 비활성.
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="레거시: 당일 시가 대비 과열 상한(%). 999=비활성">시가+과열(%)<span class="d-block text-muted fw-normal" style="font-size:10px">legacy · MOMENTUM_MAX_FROM_OPEN_PCT</span></label>
<input type="number" class="form-control" id="mom_max_from_open" value="999" min="-50" max="999" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="레거시: 당일 시가 대비 약세 하한(%)">시가+약세(%)<span class="d-block text-muted fw-normal" style="font-size:10px">legacy · MOMENTUM_MIN_FROM_OPEN_PCT</span></label>
<input type="number" class="form-control" id="mom_min_from_open" value="-999" min="-999" max="50" step="1">
</div>
</div>
</div>
<!-- 청산/공통 파라미터 (momentum_engine 전용 — SCALP reversal 과 분리) -->
<div class="card p-3 mb-3">
<div class="card-title" style="font-size:13px;color:var(--accent)">🛑 청산 / 공통 (momentum_engine 전용)</div>
<p class="mb-2" style="font-size:11px;color:var(--muted)">
청산 순서: <b>래칫/어깨 → 트레일 → 손절 → 시간컷 → 금액손실컷 → 익절(tp_max 상한) → 장마감</b>
(실매 MomentumStrategy · param_search 와 동일. SCALP reversal V자 청산과 별도)
</p>
<div class="row g-2 align-items-end mt-1">
<div class="col-4 col-md-1">
<label class="form-label param-row" title="고정 손절률 (%)">손절(%)<span class="d-block text-muted fw-normal" style="font-size:10px">stop-loss % · MOMENTUM_STOP_LOSS_PCT</span></label>
<input type="number" class="form-control" id="mom_sl" value="1.5" min="0.1" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="고정 익절률 (%) — 어깨·트레일 이후 tp_max 상한">익절(%)<span class="d-block text-muted fw-normal" style="font-size:10px">take-profit cap · MOMENTUM_TAKE_PROFIT_PCT</span></label>
<input type="number" class="form-control" id="mom_tp" value="2.5" min="0.1" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="min(tp, tp_max) — 하드 캡, 어깨 미청산 시에만">익절상한%<span class="d-block text-muted fw-normal" style="font-size:10px">tp max cap · MOMENTUM_TP_MAX_PCT</span></label>
<input type="number" class="form-control" id="mom_tp_max" value="2.0" min="0.3" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="어깨 발동: 진입가 대비 이 % 이상 올라야 고점 추적">어깨발동%<span class="d-block text-muted fw-normal" style="font-size:10px">shoulder arm · MOMENTUM_SHOULDER_MIN_HIGH_PCT</span></label>
<input type="number" class="form-control" id="mom_smin" value="0.5" min="0" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="고점 대비 이 % 하락 시 어깨컷 (래칫 미발동 시)">어깨폭%<span class="d-block text-muted fw-normal" style="font-size:10px">shoulder cut · MOMENTUM_SHOULDER_CUT_PCT</span></label>
<input type="number" class="form-control" id="mom_scut" value="0.3" min="0.1" max="3" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="고점 대비 이 % 하락 시 트레일 청산">트레일%<span class="d-block text-muted fw-normal" style="font-size:10px">trail cut · MOMENTUM_TRAIL_PCT</span></label>
<input type="number" class="form-control" id="mom_trail" value="0" min="0" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="트레일 무장: 진입가 대비 이 % 이상 수익 후 추적">트레일무장%<span class="d-block text-muted fw-normal" style="font-size:10px">trail arm · MOMENTUM_TRAIL_ARM_PCT</span></label>
<input type="number" class="form-control" id="mom_trail_arm" value="0" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="최대 보유 1분봉 수 (0=비활성)">최대보유(봉)<span class="d-block text-muted fw-normal" style="font-size:10px">time cut · MOMENTUM_MAX_HOLD_BARS</span></label>
<input type="number" class="form-control" id="mom_max_hold" value="0" min="0" max="120" step="1">
</div>
<div class="col-12 col-md-3">
<label class="form-label param-row" title="수익 구간별 본절 상향 (예: 0.5:0.1,1.0:0.3)">래칫티어<span class="d-block text-muted fw-normal" style="font-size:10px">ratchet tiers · MOMENTUM_RATCHET_TIERS</span></label>
<input type="text" class="form-control" id="mom_ratchet" value="" placeholder="0.5:0.1,1.0:0.3 (빈칸=OFF)">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="손익 후 같은 종목 재진입 금지(분)">쿨다운(분)<span class="d-block text-muted fw-normal" style="font-size:10px">re-entry cooldown · MOMENTUM_COOLDOWN_SEC</span></label>
<input type="number" class="form-control" id="mom_cooldown" value="10" min="0" max="60" step="5">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="매수 시작 시각(HHMM). 모멘텀 탭은 매수종료가 위 '매수종료(추격)' 따로 적용">매수시작<span class="d-block text-muted fw-normal" style="font-size:10px">buy start HHMM · MOMENTUM_TIME_START</span></label>
<input type="number" class="form-control" id="mom_time_start" value="900" min="900" max="1500" step="100">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="종목당 하루 최대 거래 횟수">일일최대매수<span class="d-block text-muted fw-normal" style="font-size:10px">max entries/day · MOMENTUM_MAX_DAILY</span></label>
<input type="number" class="form-control" id="mom_max_daily" value="5" min="1" max="20">
</div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="mom_eod_enabled" checked>
<label class="form-check-label param-row" for="mom_eod_enabled" title="ON=설정 시각 이후 보유 전량 당일청산">EOD청산</label>
</div>
</div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="mom_skip_pre_sub">
<label class="form-check-label param-row" for="mom_skip_pre_sub" title="정합용: 종목 첫 ws_tick 분 이전 진입 제외 (파람 탐색은 OFF 권장)">구독전분제외<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_BACKTEST_SKIP_PRE_SUBSCRIBE</span></label>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row" title="EOD 당일청산 시각 (HH:MM)">EOD시각<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_EOD_HM</span></label>
<input type="text" class="form-control" id="mom_eod_hm" value="15:25" placeholder="15:25" style="width:72px">
</div>
</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12 col-md-2">
<label class="form-label param-row" title="OFF면 진입 방어(낙폭/고점추격/급등/최소가격)를 비활성화하고, 손절/익절/장마감청산은 유지">방어로직<span class="d-block text-muted fw-normal" style="font-size:10px">entry filters · MOMENTUM_USE_DEFENSE_FILTERS</span></label>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="mom_use_defense" checked>
<label class="form-check-label" for="mom_use_defense">진입 방어 ON</label>
</div>
</div>
<div class="col-12 col-md-2">
<label class="form-label param-row" title="이 백테 1회에만 적용 (실매 미반영). 저장 시에만 DB 반영">TRIGGER 필터(백테)<span class="d-block text-muted fw-normal" style="font-size:10px">호가·프로그램 · 끄고/켜고 비교용</span></label>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="mom_ob_filter" checked>
<label class="form-check-label" for="mom_ob_filter">호가필터 ON</label>
</div>
<span id="mom_ob_filter_note" class="d-block text-muted" style="font-size:10px"></span>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="mom_pg_filter" checked>
<label class="form-check-label" for="mom_pg_filter">프로그램필터 ON</label>
</div>
<span id="mom_pg_filter_note" class="d-block text-muted" style="font-size:10px"></span>
</div>
<div class="col-6 col-md-2">
<label class="form-label param-row" title="호가 스프레드 상한(%). 0.45=0.45%. kiwoom_0d 본체 재계산(6/25~). 본체 없는 날은 log 판정 폴백">스프레드상한(%)<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_ORDERBOOK_MAX_SPREAD_PCT</span></label>
<input type="number" step="0.01" class="form-control form-control-sm" id="mom_max_spread_pct" value="0.45">
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="mom_use_high_chase_f">
<label class="form-check-label" for="mom_use_high_chase_f" style="font-size:12px">고점추격필터 (기본 OFF)</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="mom_use_daily_range">
<label class="form-check-label" for="mom_use_daily_range" style="font-size:12px">당일변동필터 (기본 OFF)</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="mom_use_ema_f" checked>
<label class="form-check-label" for="mom_use_ema_f" style="font-size:12px">EMA추세필터 (기본 ON)</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="EMA 추세 필터 빠른 기간">EMA빠름<span class="d-block text-muted fw-normal" style="font-size:10px">fast period · MOMENTUM_EMA_FAST_PERIOD</span></label>
<input type="number" class="form-control" id="mom_ema_fast" value="9" min="2" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="EMA 추세 필터 느린 기간">EMA느림<span class="d-block text-muted fw-normal" style="font-size:10px">slow period · MOMENTUM_EMA_SLOW_PERIOD</span></label>
<input type="number" class="form-control" id="mom_ema_slow" value="21" min="3" max="120" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="당일고가 대비 이 비율 이하면 진입 허용">고점추격방지<span class="d-block text-muted fw-normal" style="font-size:10px">near-high gate · HIGH_CHASE_THR</span></label>
<input type="number" class="form-control" id="mom_high_chase" value="0.96" min="0.5" max="1" step="0.01">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="당일 등락률 이 값 초과 시 진입 금지(%)">급등주필터(%)<span class="d-block text-muted fw-normal" style="font-size:10px">intraday range cap · MAX_DAILY_CHG</span></label>
<input type="number" class="form-control" id="mom_max_daily_chg" value="20" min="0" max="100" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="이 가격 미만 종목 진입 금지(원)">최소가격(원)<span class="d-block text-muted fw-normal" style="font-size:10px">min tick price · MOMENTUM_MIN_PRICE</span></label>
<input type="number" class="form-control" id="mom_min_price" value="1000" min="0" step="100">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="종목당 1회 최대 손실 한도(원)">1회최대손실(원)<span class="d-block text-muted fw-normal" style="font-size:10px">loss cap KRW · MOMENTUM_MAX_LOSS_PER_TRADE_KRW</span></label>
<input type="number" class="form-control" id="mom_max_loss_krw" value="200000" min="0" step="10000">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="본절사수 시 최소 순이익 마진(%)">본절마진(%)<span class="d-block text-muted fw-normal" style="font-size:10px">breakeven buffer · MOMENTUM_MIN_PROFIT_PCT</span></label>
<input type="number" class="form-control" id="mom_min_margin" value="0.2" min="0" max="50" step="0.1">
</div>
<!-- 당일 누적손익 다단트레일 — MOMENTUM_DAILY_PROFIT_TARGET_ENABLED -->
<div class="col-12 mt-1"><span style="font-size:11px;color:var(--muted)">📅 다단트레일 ON이면 당일 실현손익 고점 대비 되돌릴 때 <b>신규매수만</b> 중단. <b>리스크버짓(B)</b> ON이면 hit 후 보유최악손절합&gt;cushion 이면 전량정리. DB=<code>MOMENTUM_DAILY_PROFIT_*</code>.</span></div>
<div class="col-auto">
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="mom_daily_profit_enabled">
<label class="form-check-label param-row" for="mom_daily_profit_enabled" title="MOMENTUM_DAILY_PROFIT_TARGET_ENABLED — 다단트레일 ON/OFF. 로드=DB, 봇저장 시 DB 반영">다단트레일</label>
</div>
</div>
<div class="col-auto">
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="mom_daily_risk_budget_enabled">
<label class="form-check-label param-row" for="mom_daily_risk_budget_enabled" title="MOMENTUM_DAILY_PROFIT_RISK_BUDGET_ENABLED — 기본 OFF">리스크버짓(B)</label>
</div>
</div>
<div class="col-12 col-md-4">
<label class="form-label param-row" title="다단 트레일(ratchet식): 수익원:컷%,… — 벌수록 컷% 타이트. 비우면 단일 되돌림 사용. 예: 30000:50,100000:35,300000:25">다단규칙(수익원:컷%,…)</label>
<select class="form-select form-select-sm mb-1" id="mom_daily_trail_preset"
title="프리셋 — 고르면 아래 칸이 채워집니다(감시 스위치는 그대로)"
onchange="btApplyPreset('mom_daily_trail_tiers', this.value, false)">
<option value="__custom__">프리셋 선택…(직접입력)</option>
<option value="off">off (다단 숫자 비움)</option>
<option value="20000:40,50000:30,150000:20">보수 20000:40,50000:30,150000:20</option>
<option value="30000:50,100000:35,300000:25">중도 30000:50,100000:35,300000:25</option>
<option value="50000:60,200000:45,500000:30">공격 50000:60,200000:45,500000:30</option>
</select>
<input type="text" class="form-control" id="mom_daily_trail_tiers" value="" placeholder="30000:50,100000:35,300000:25" style="font-size:12px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="다단이 비었을 때만: 당일 실현손익 고점 대비 이 % 되돌리면 중단. 0=미사용">단일되돌림(%)</label>
<input type="number" class="form-control" id="mom_daily_trail_drop" value="0" min="0" max="90" step="5" style="width:110px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="단일 되돌림용: 이 수익(원) 이상 벌어야 감시 시작. 0이면 비활성(과민발동 방지)">발동최소수익(원)</label>
<input type="number" class="form-control" id="mom_daily_trail_arm" value="0" min="0" step="50000" style="width:130px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row" title="trailing=트레일만 / both=고정목표(운영설정)+트레일 먼저 닿는 쪽">방식</label>
<select class="form-select" id="mom_daily_profit_mode" style="width:120px">
<option value="trailing" selected>trailing</option>
<option value="both">both</option>
</select>
</div>
<div class="col-12 mt-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="mom_use_univ_history" checked>
<label class="form-check-label" for="mom_use_univ_history" style="font-size:12px;color:var(--muted)">
<b>저장 후보 이력</b> — 체크: DB 슬롯·후보 / 해제: 시뮬 유니버스
(이력소스 셀렉트는 위 포트폴리오 카드)
</label>
</div>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="mom_env_timeline">
<label class="form-check-label" for="mom_env_timeline" style="font-size:12px;color:var(--muted)" title="ON: 봉 시각별 과거 env. OFF(기본): 폼 파람 고정">
<b>env 타임라인</b> — 체크: 그 시각 DB설정 재현 / <b>해제(기본)</b>: 폼 파람으로 구간 전체
</label>
</div>
</div>
<div class="col-12 col-md-auto mt-2 d-flex gap-2 flex-wrap align-items-center">
<button class="btn btn-primary px-4" id="mom_btn_run_bg" onclick="btJobStart('momentum')">🚀 백그라운드 실행</button>
<button class="btn btn-outline-primary px-3" onclick="runMomentumBacktest()">동기 실행</button>
<button class="btn btn-outline-danger px-2 py-1" id="mom_btn_stop_bg" onclick="btJobStop()" disabled>중지</button>
<button type="button" class="btn btn-outline-info px-3" onclick="saveMomentumConfig()" title="현재 입력값을 config_momentum + env_config 에 저장 (실매 MomentumStrategy 동일 소스)">💾 봇에 설정저장</button>
<button class="btn btn-outline-info px-3" onclick="loadMomentumSearchResults()">📂 탐색결과 불러오기</button>
<span class="text-muted" style="font-size:11px">탐색: CLI · 전역 1잡</span>
</div>
<div class="col-12">
<div class="optuna-prog-track mb-1" style="height:10px;max-width:480px">
<div class="optuna-prog-fill" id="mom_bt_tab_fill" style="width:0%"></div>
</div>
<div class="text-muted" style="font-size:11px" id="mom_bt_tab_status">백그라운드=CLI 잡 · 탭 이동 OK · DB 파라미터</div>
</div>
</div>
</div>
<div id="mom_search_result" style="display:none" class="mb-3">
<div class="section-title">🔍 파라미터 탐색 결과 (CLI search_momentum_*.json)</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead id="mom_search_thead"><tr><th>-</th></tr></thead>
<tbody id="mom_search_tbody"></tbody>
</table>
</div>
<p id="mom_search_hint" class="text-muted" style="display:none;font-size:11px;margin-top:8px;line-height:1.45;"></p>
</div>
</div>
<div id="mom_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<!-- 결과 요약 (꼬리잡기 탭과 동일 레이아웃) -->
<div id="mom_result_area" style="display:none">
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="mom_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="mom_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="mom_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="mom_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="mom_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="mom_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="mom_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="mom_daily_avg_pct">-</div>
</div></div>
</div>
<!-- 승/패 바 -->
<div class="card p-3 mb-3" id="mom_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="mom_win_label">-</span>
<span style="color:var(--red)" id="mom_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="mom_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="mom_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3">
<div class="col-12 col-lg-8">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선 (가상)</div>
<canvas id="mom_equity_chart" height="220"></canvas>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card p-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="mom_reason_chart" height="200"></canvas>
</div>
</div>
</div>
<div class="card p-3 mt-3">
<div class="card-title mb-2">일별 손익 (가상)</div>
<canvas id="mom_daily_chart" height="150"></canvas>
</div>
<!-- 거래 내역 (꼬리잡기와 동일 테이블) -->
<div class="section-title">가상 거래 내역 (최근 200건)</div>
<div id="mom_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="mom_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" id="mom_table">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th>
<th>보유(분)</th><th>체결디버그</th><th title="매수 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매수호가</th><th title="매도 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매도호가</th><th>매도사유</th>
</tr></thead>
<tbody id="mom_tbody"></tbody>
</table>
</div>
</div>
</div><!-- mom_result_area -->
<p class="mt-2 mb-0" style="font-size:11px;color:var(--muted)">
파라미터 그리드 탐색은 CLI <code>param_search_momentum.py</code> — 웹은 페이지 로드 시
<code>/api/env/params</code><b>config_momentum</b> + env_config 병합값으로 입력란 자동 채움.
</p>
</div><!-- tab-momentum end -->
<!-- ═══ 해외 모멘텀 (US) — HTS/호가/프로그램 제외 · ws_candles.market=US ═══ -->
<div id="tab-us_momentum" style="display:none">
<div class="card p-3 mb-3" style="border-left:4px solid #58a6ff">
<div style="font-size:14px;line-height:1.7">
<b>🇺🇸 해외 모멘텀</b> = 국내 모멘텀과 <b>엔진 공유</b>, 데이터·유니버스만 US<br>
<span style="color:var(--muted);font-size:12px">
• 봉: <code>ws_candles.market=US</code> · 틱: HDFSCNT0 · 유니버스: 영구구독 US (HTS 없음)<br>
<b>뺀 것</b>: 호가/프로그램 필터 · HTS 후보이력 · 국내 매매세 · KR 장시간(900~1430)<br>
• 세션: KST 자정 넘김 가능 (<code>US_MOMENTUM_TIME_*</code> · 기본 RTH 22:30~05:00)<br>
• 실거래 ID: <code>US_MOMENTUM</code> (국내 <code>MOMENTUM</code> 과 분리) · Optuna: <code>us_momentum</code><br>
• 주문: OrderManager 해외 경로(+MM) · 종목별 파람: <code>us_momentum_stock_config</code> (박스엔진식 행)
</span>
</div>
</div>
<!-- 종목별 설정 (permanent US 행) -->
<div class="card p-3 mb-3">
<div class="d-flex flex-wrap justify-content-between align-items-center mb-2 gap-2">
<div class="card-title mb-0">종목별 파람 (성격 분리)</div>
<div class="d-flex flex-wrap gap-2">
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="usmomLoadStocks(true)">↻ 목록+시드</button>
<button type="button" class="btn btn-sm btn-outline-primary" onclick="usmomSaveStockCfg()">💾 선택종목 저장</button>
<button type="button" class="btn btn-sm btn-outline-warning" onclick="usmomClearStockCfg()">↩ 전역복귀(행삭제)</button>
</div>
</div>
<small class="text-muted d-block mb-2">행 클릭 → 아래 TRIGGER/청산 폼에 로드. 빈칸=전역 <code>US_MOMENTUM_*</code>. ETF/STOCK 그룹으로 구분.</small>
<div class="row g-2 align-items-end mb-2">
<div class="col-auto">
<label class="form-label param-row">종목</label>
<select class="form-select" id="usmom_stock_code" style="width:140px" onchange="usmomOnStockSelect()"></select>
</div>
<div class="col-auto">
<label class="form-label param-row">그룹</label>
<select class="form-select" id="usmom_stock_group" style="width:100px">
<option value="ETF">ETF</option>
<option value="STOCK" selected>STOCK</option>
<option value="OTHER">OTHER</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">거래소</label>
<input type="text" class="form-control" id="usmom_stock_exch" value="NASD" style="width:90px">
</div>
<div class="col-auto" id="usmom_stock_cfg_badge" style="font-size:12px;color:var(--muted)"></div>
</div>
<div class="table-responsive" style="max-height:180px;overflow:auto">
<table class="table table-sm table-hover" style="font-size:12px">
<thead><tr><th>코드</th><th>그룹</th><th>거래소</th><th></th><th>영구구독</th></tr></thead>
<tbody id="usmom_stock_tbody"><tr><td colspan="5" class="text-muted">로딩…</td></tr></tbody>
</table>
</div>
<!-- 종목 cfg Optuna (전역 Optuna 탭과 분리) -->
<div class="border-top pt-2 mt-2">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-1">
<strong style="font-size:13px">🔬 이 종목 Optuna → <code>us_momentum_stock_config</code></strong>
<small class="text-muted">유니버스=선택 1종 · 적용 시 전역 US_MOMENTUM_* 미오염</small>
</div>
<div class="row g-2 align-items-end">
<div class="col-auto">
<label class="form-label param-row">시작</label>
<input type="date" class="form-control form-control-sm" id="usmom_opt_start" style="width:150px"
onchange="usmomOptSyncDatesToMain()">
</div>
<div class="col-auto">
<label class="form-label param-row">종료</label>
<input type="date" class="form-control form-control-sm" id="usmom_opt_end" style="width:150px"
onchange="usmomOptSyncDatesToMain()">
</div>
<div class="col-auto">
<label class="form-label param-row">mode</label>
<input type="text" class="form-control form-control-sm" id="usmom_opt_mode" value="tpe" readonly style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row">trials</label>
<input type="number" class="form-control form-control-sm" id="usmom_opt_trials" value="100" min="1" max="2000" style="width:90px">
</div>
<div class="col-auto">
<button type="button" class="btn btn-sm btn-primary" id="usmom_opt_btn_start" onclick="usmomStockOptunaStart()">이 종목 Optuna</button>
<button type="button" class="btn btn-sm btn-outline-danger" id="usmom_opt_btn_stop" onclick="usmomStockOptunaStop()" disabled>중지</button>
<button type="button" class="btn btn-sm btn-outline-info" id="usmom_opt_btn_fill" onclick="usmomStockOptunaFillForm()" disabled>폼에 넣기</button>
<button type="button" class="btn btn-sm btn-outline-success" id="usmom_opt_btn_apply" onclick="usmomStockOptunaApply()" disabled>종목행에 적용</button>
</div>
<div class="col-12">
<small class="text-muted">완료 후 아래 Top에서 <b>보기</b> → 골라 <b>폼에 넣기</b>/<b>종목행 적용</b>. 상단 버튼=학습1위 단축. 백테=폼. <b>전역 설정 저장</b>≠종목행.</small>
</div>
<div class="col-12">
<div class="optuna-prog-track mb-1" style="height:10px;max-width:480px">
<div class="optuna-prog-fill" id="usmom_opt_fill" style="width:0%"></div>
</div>
<div id="usmom_opt_prog_label" class="small text-muted mb-1">trial —</div>
<div id="usmom_opt_status" class="small text-muted">종목·기간 선택 후 시작</div>
<pre id="usmom_opt_log_tail" class="mt-1 small text-muted p-2 d-none" style="max-height:120px;overflow:auto;background:#0d1117;border:1px solid var(--border);border-radius:6px;white-space:pre-wrap;font-size:11px"></pre>
</div>
<div class="col-12 mt-2" id="usmom_opt_results_box" style="display:none">
<div class="row g-2">
<div class="col-md-6">
<h6 class="mb-1" style="font-size:12px">학습 Top5 <small class="text-muted">results (진행바 best=1위)</small></h6>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" style="font-size:11px">
<thead>
<tr>
<th>#</th><th>trial</th><th class="text-end">거래</th>
<th class="text-end">WR</th><th class="text-end">PF</th><th class="text-end">PnL</th><th></th>
</tr>
</thead>
<tbody id="usmom_opt_top5_learn">
<tr><td colspan="7" class="text-muted">완료 후 표시</td></tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-6">
<h6 class="mb-1" style="font-size:12px">사후합격 Top5 <small class="text-muted">results_gated</small></h6>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" style="font-size:11px">
<thead>
<tr>
<th>#</th><th>trial</th><th class="text-end">거래</th>
<th class="text-end">WR</th><th class="text-end">PF</th><th class="text-end">PnL</th><th></th>
</tr>
</thead>
<tbody id="usmom_opt_top5_gated">
<tr><td colspan="7" class="text-muted">완료 후 표시</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="mt-2 p-2" id="usmom_opt_detail_card" style="background:rgba(56,139,253,0.06);border:1px solid var(--border);border-radius:6px">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-1 mb-1">
<strong style="font-size:12px" id="usmom_opt_detail_title">후보 상세 — Top「보기」선택</strong>
<span class="small text-muted" id="usmom_opt_detail_sel">미선택</span>
</div>
<div id="usmom_opt_detail_metrics" class="small text-muted mb-1">아직 선택 없음</div>
<pre id="usmom_opt_detail_params" class="small p-2 mb-2 d-none" style="max-height:160px;overflow:auto;background:#0d1117;border:1px solid var(--border);border-radius:6px;white-space:pre-wrap;font-size:11px"></pre>
<div class="d-flex flex-wrap gap-1">
<button type="button" class="btn btn-sm btn-outline-info" id="usmom_opt_btn_fill_sel" onclick="usmomStockOptunaFillSelected()" disabled>선택 → 폼에 넣기</button>
<button type="button" class="btn btn-sm btn-outline-success" id="usmom_opt_btn_apply_sel" onclick="usmomStockOptunaApplySelected()" disabled>선택 → 종목행 적용</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end">
<div class="col-auto">
<label class="form-label">시작일</label>
<input type="date" class="form-control" id="usmom_start">
</div>
<div class="col-auto">
<label class="form-label">종료일</label>
<input type="date" class="form-control" id="usmom_end">
</div>
<div class="col-auto">
<label class="form-label param-row" title="비우면 전 종목 · 쉼표 구분 시 해당만 백테">백테 종목</label>
<input type="text" class="form-control" id="usmom_bt_codes" placeholder="TSLA 또는 QQQM,SPYM" style="width:180px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="종목당 1회 매수 금액 (USD)">1회투자($)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_SLOT_MONEY</span></label>
<input type="number" class="form-control" id="usmom_slot_money" value="200000" min="1" step="1" style="width:130px">
</div>
<div class="col-auto">
<label class="form-label param-row">동시보유(종)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MAX_STOCKS</span></label>
<input type="number" class="form-control" id="usmom_slots" value="4" min="1" max="20" style="width:72px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="총 운용한도 (USD)">총운용한도($)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TOTAL_BUDGET</span></label>
<input type="number" class="form-control" id="usmom_total_budget" value="800000" min="0" step="1" style="width:130px">
</div>
<div class="col-auto d-flex align-items-end">
<small id="usmom_fx_hint" class="text-muted" style="font-size:11px;max-width:220px">$↔원 = 표시용(캐시/폴백)</small>
</div>
<div class="col-12" style="font-size:11px;color:var(--muted)">
※ 유니버스=영구구독 US 고정 (HTS/후보이력 없음). 호가·프로그램 필터 없음.
</div>
<div class="col-12 mt-1 d-flex flex-wrap gap-2 align-items-center">
<button type="button" class="btn btn-primary btn-sm" onclick="runUsMomentumBacktest()">▶ 해외 모멘텀 백테</button>
<button type="button" class="btn btn-outline-info btn-sm" onclick="saveUsMomentumConfig()" title="전역 config_us_momentum · US_MOMENTUM_* 만 (종목행 us_momentum_stock_config 아님)">💾 전역 설정 저장</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="usmomGoOptuna()" title="Optuna 탭 · 전역 US_MOMENTUM_*">🔬 전역 Optuna</button>
<small class="text-muted">종목 cfg Optuna는 위 종목 카드 · 전역은 Optuna 탭</small>
</div>
</div>
</div>
<div class="card p-3 mb-3">
<div class="card-title" style="font-size:13px;color:#58a6ff">📈 해외 모멘텀 TRIGGER V4 (추격 패턴)</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:#58a6ff">추격 패턴</b> — 하나라도 충족 시 진입 (<code>US_MOMENTUM_PATTERN_*</code>)</span></div>
<div class="col-6 col-md-2">
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="usmom_pat_breakout" checked>
<label class="form-check-label" for="usmom_pat_breakout" style="font-size:12px">N분 고가 돌파 + 양봉 + 거래량</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="usmom_pat_pullback" checked>
<label class="form-check-label" for="usmom_pat_pullback" style="font-size:12px">스윙고점 → 눌림 → 재돌파</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">돌파관찰(분)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_CHASE_LOOKBACK_MIN</span></label>
<input type="number" class="form-control" id="usmom_chase_lookback" value="10" min="3" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">눌림관찰(분)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_PULLBACK_LOOKBACK_MIN</span></label>
<input type="number" class="form-control" id="usmom_pullback_lookback" value="15" min="5" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">눌림min(%)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_PULLBACK_MIN_PCT</span></label>
<input type="number" class="form-control" id="usmom_pullback_min" value="0.3" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">눌림max(%)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_PULLBACK_MAX_PCT</span></label>
<input type="number" class="form-control" id="usmom_pullback_max" value="3.0" min="0.5" max="15" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">눌림Vol×<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_SETUP_VOL_MAX_MULT</span></label>
<input type="number" class="form-control" id="usmom_setup_vol" value="0.8" min="0" max="2" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">눌림음봉min<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_SETUP_BEAR_BARS_MIN</span></label>
<input type="number" class="form-control" id="usmom_setup_bear" value="1" min="0" max="10" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">RSI min<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_RSI_MIN</span></label>
<input type="number" class="form-control" id="usmom_rsi_min" value="50" min="30" max="95" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">RSI max<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_RSI_MAX</span></label>
<input type="number" class="form-control" id="usmom_rsi_max" value="90" min="50" max="100" step="1">
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="usmom_use_rsi_max_f">
<label class="form-check-label" for="usmom_use_rsi_max_f" style="font-size:12px">RSI 상한필터 (기본 OFF)</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">거래량배수<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_VOL_MULT</span></label>
<input type="number" class="form-control" id="usmom_vol_mult" value="1.5" min="0" max="50" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">관찰봉수<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_VOL_WIN</span></label>
<input type="number" class="form-control" id="usmom_vol_win" value="5" min="2" max="30" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="KST HHMM · 자정 넘김">매수시작<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TIME_START</span></label>
<input type="number" class="form-control" id="usmom_time_start" value="2230" style="width:90px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="KST HHMM · 자정 넘김">매수종료<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TIME_END</span></label>
<input type="number" class="form-control" id="usmom_time_end" value="500" style="width:90px">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">시가+과열(%)<span class="d-block text-muted fw-normal" style="font-size:10px">legacy · US_MOMENTUM_MAX_FROM_OPEN_PCT</span></label>
<input type="number" class="form-control" id="usmom_max_from_open" value="999" min="-50" max="999" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">시가+약세(%)<span class="d-block text-muted fw-normal" style="font-size:10px">legacy · US_MOMENTUM_MIN_FROM_OPEN_PCT</span></label>
<input type="number" class="form-control" id="usmom_min_from_open" value="-999" min="-999" max="50" step="1">
</div>
<div class="col-12 mt-1" style="font-size:11px;color:var(--muted)">
엔진은 국내와 동일(돌파 OR 눌림재돌파 + RSI + 거래량 + EMA). KR-only(호가/프로그램/HTS이력) 제외.
</div>
</div>
</div>
<div class="card p-3 mb-3">
<div class="card-title" style="font-size:13px;color:#58a6ff">🛑 청산 / 공통 (momentum_engine · US_MOMENTUM_*)</div>
<p class="mb-2" style="font-size:11px;color:var(--muted)">
청산 순서: <b>래칫/어깨 → 트레일 → 손절 → 시간컷 → 금액손실컷 → 익절(tp_max) → EOD</b>
</p>
<div class="row g-2 align-items-end mt-1">
<div class="col-4 col-md-1">
<label class="form-label param-row">손절(%)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_STOP_LOSS_PCT</span></label>
<input type="number" class="form-control" id="usmom_sl" value="1.5" min="0.1" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">익절(%)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TAKE_PROFIT_PCT</span></label>
<input type="number" class="form-control" id="usmom_tp" value="2.5" min="0.1" max="20" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">익절상한%<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TP_MAX_PCT</span></label>
<input type="number" class="form-control" id="usmom_tp_max" value="2.0" min="0.3" max="30" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">어깨발동%<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_SHOULDER_MIN_HIGH_PCT</span></label>
<input type="number" class="form-control" id="usmom_smin" value="0.5" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">어깨폭%<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_SHOULDER_CUT_PCT</span></label>
<input type="number" class="form-control" id="usmom_scut" value="0.3" min="0.1" max="5" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">트레일%<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TRAIL_PCT</span></label>
<input type="number" class="form-control" id="usmom_trail" value="0" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">트레일무장%<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_TRAIL_ARM_PCT</span></label>
<input type="number" class="form-control" id="usmom_trail_arm" value="0" min="0" max="10" step="0.1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">최대보유(봉)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MAX_HOLD_BARS</span></label>
<input type="number" class="form-control" id="usmom_max_hold" value="0" min="0" max="500" step="1">
</div>
<div class="col-12 col-md-3">
<label class="form-label param-row">래칫티어<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_RATCHET_TIERS</span></label>
<input type="text" class="form-control" id="usmom_ratchet" value="" placeholder="0.5:0.1,1.0:0.3 (빈칸=OFF)">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">쿨다운(분)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_COOLDOWN_SEC</span></label>
<input type="number" class="form-control" id="usmom_cooldown" value="5" min="0" max="120" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">일일최대매수<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MAX_DAILY</span></label>
<input type="number" class="form-control" id="usmom_max_daily" value="5" min="1" max="50">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row" title="매도 세션 종료 KST HHMM">매도종료<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_SELL_TIME_END</span></label>
<input type="number" class="form-control" id="usmom_sell_time_end" value="630" style="width:90px">
</div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="usmom_eod_enabled">
<label class="form-check-label param-row" for="usmom_eod_enabled">EOD청산</label>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row">EOD시각<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_EOD_HM</span></label>
<input type="text" class="form-control" id="usmom_eod_hm" value="05:00" style="width:80px">
</div>
</div>
<div class="row g-2 align-items-end mt-1">
<div class="col-12 col-md-2">
<label class="form-label param-row">방어로직<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_USE_DEFENSE_FILTERS</span></label>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" id="usmom_use_defense" checked>
<label class="form-check-label" for="usmom_use_defense">진입 방어 ON</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="usmom_use_high_chase_f">
<label class="form-check-label" for="usmom_use_high_chase_f" style="font-size:12px">고점추격필터 (기본 OFF)</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="usmom_use_daily_range">
<label class="form-check-label" for="usmom_use_daily_range" style="font-size:12px">당일변동필터 (기본 OFF)</label>
</div>
</div>
<div class="col-6 col-md-2">
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="usmom_use_ema_f" checked>
<label class="form-check-label" for="usmom_use_ema_f" style="font-size:12px">EMA추세필터 (기본 ON)</label>
</div>
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">EMA빠름<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_EMA_FAST_PERIOD</span></label>
<input type="number" class="form-control" id="usmom_ema_fast" value="9" min="2" max="60" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">EMA느림<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_EMA_SLOW_PERIOD</span></label>
<input type="number" class="form-control" id="usmom_ema_slow" value="21" min="3" max="120" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">고점추격방지<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_HIGH_CHASE_THR</span></label>
<input type="number" class="form-control" id="usmom_high_chase" value="0.96" min="0.5" max="1" step="0.01">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">급등주필터(%)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MAX_DAILY_CHG</span></label>
<input type="number" class="form-control" id="usmom_max_daily_chg" value="20" min="0" max="100" step="1">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">최소가격<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MIN_PRICE</span></label>
<input type="number" class="form-control" id="usmom_min_price" value="1" min="0" step="0.01">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">1회최대손실<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MAX_LOSS_PER_TRADE</span></label>
<input type="number" class="form-control" id="usmom_max_loss" value="0" min="0" step="1000">
</div>
<div class="col-4 col-md-1">
<label class="form-label param-row">본절마진(%)<span class="d-block text-muted fw-normal" style="font-size:10px">US_MOMENTUM_MIN_PROFIT_PCT</span></label>
<input type="number" class="form-control" id="usmom_min_margin" value="0.2" min="0" max="50" step="0.1">
</div>
<div class="col-12 mt-1"><span style="font-size:11px;color:var(--muted)">📅 다단트레일 — 신규매수 중단. <b>리스크버짓(B)</b> — hit 후 보유 최악손절 정리. DB=<code>US_MOMENTUM_DAILY_PROFIT_*</code></span></div>
<div class="col-auto">
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="usmom_daily_profit_enabled">
<label class="form-check-label param-row" for="usmom_daily_profit_enabled">다단트레일</label>
</div>
</div>
<div class="col-auto">
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="usmom_daily_risk_budget_enabled">
<label class="form-check-label param-row" for="usmom_daily_risk_budget_enabled">리스크버짓(B)</label>
</div>
</div>
<div class="col-12 col-md-4">
<label class="form-label param-row">다단규칙(수익원:컷%,…)</label>
<input type="text" class="form-control" id="usmom_daily_trail_tiers" value="" placeholder="30000:50,100000:35" style="font-size:12px">
</div>
<div class="col-4 col-md-2">
<label class="form-label param-row">방식</label>
<select class="form-select" id="usmom_daily_profit_mode" style="width:120px">
<option value="trailing" selected>trailing</option>
<option value="both">both</option>
</select>
</div>
</div>
<div class="mt-3 d-flex flex-wrap gap-2 align-items-center">
<button type="button" class="btn btn-primary" onclick="runUsMomentumBacktest()">▶ 해외 모멘텀 백테</button>
<button type="button" class="btn btn-outline-info" onclick="saveUsMomentumConfig()" title="전역 config_us_momentum · US_MOMENTUM_* 만 (종목행 us_momentum_stock_config 아님)">💾 전역 설정 저장</button>
<button type="button" class="btn btn-outline-secondary" onclick="usmomGoOptuna()">🔬 Optuna 탭으로</button>
<button type="button" class="btn btn-outline-primary" onclick="usmomActGoActualTab()" title="실거래 분석 탭 · 해외모멘텀 선택">📊 실거래 분석</button>
<button type="button" class="btn btn-outline-warning" onclick="usmomFetchCandles(1)">📥 US 1분봉 수집</button>
<span id="usmom_fetch_status" class="text-muted" style="font-size:12px"></span>
</div>
<small class="text-muted d-block mt-1"><b>전역 설정 저장</b>=<code>config_us_momentum</code>(US_MOMENTUM_*) · 종목핀은「선택종목 저장/종목행 적용」. 백테=가상 · 실매=<b>실거래 분석</b>. 3분봉 REST 불필요(1m 롤업).</small>
</div>
<div id="usmom_params_bar" class="text-muted mb-3" style="font-size:12px;display:none"></div>
<div id="usmom_result_area" style="display:none">
<div class="row g-3 mb-3">
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="usmom_total">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="usmom_winrate">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="usmom_pnl">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="usmom_pf">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="usmom_mdd">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="usmom_hold">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="usmom_bot_pct">-</div>
</div></div>
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="usmom_daily_avg_pct">-</div>
</div></div>
</div>
<div class="card p-3 mb-3" id="usmom_winbar_card" style="display:none">
<div class="d-flex justify-content-between mb-1">
<span style="color:var(--green)" id="usmom_win_label">-</span>
<span style="color:var(--red)" id="usmom_loss_label">-</span>
</div>
<div class="ratio-bar">
<span class="ratio-fill-g" id="usmom_ratio_g" style="width:50%"></span>
<span class="ratio-fill-r" id="usmom_ratio_r" style="width:50%"></span>
</div>
</div>
<div class="row g-3">
<div class="col-12 col-lg-8">
<div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선 (가상)</div>
<canvas id="usmom_equity_chart" height="220"></canvas>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card p-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="usmom_reason_chart" height="200"></canvas>
</div>
</div>
</div>
<div class="card p-3 mt-3">
<div class="card-title mb-2">일별 손익 (가상)</div>
<canvas id="usmom_daily_chart" height="150"></canvas>
</div>
<div class="section-title mt-3">가상 거래 내역 (최근 200건)</div>
<div id="usmom_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="usmom_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3 mb-3">
<div class="table-responsive">
<table class="table table-hover" id="usmom_table">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익</th><th>수익률%</th><th>누적손익</th><th>누적%</th>
<th>보유(분)</th><th>체결디버그</th><th title="매수 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매수호가</th><th title="매도 시점 호가 (M:L3잔량비 W:전체잔량비 OR)">매도호가</th><th>매도사유</th>
</tr></thead>
<tbody id="usmom_tbody"></tbody>
</table>
</div>
</div>
</div>
<p class="mt-2 mb-0" style="font-size:11px;color:var(--muted)">
실매 체결·손익은 상단 <b>실거래 분석</b><b>해외모멘텀</b> (국내 모멘텀 탭과 동일 구조 · 이 탭은 백테/설정만).
</p>
</div><!-- tab-us_momentum end -->
<!-- ═══ 홀딩 전략 탭 ═══════════════════════════════════════════════════════ -->
<div id="tab-holding" style="display:none">
<!-- 공통 기간 -->
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end flex-wrap">
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="hd_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="hd_end" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">캔들 수집 시작일</label>
<input type="date" class="form-control" id="hd_fetch_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">탐색 최소거래</label>
<input type="number" class="form-control" id="hd_min_trades" value="1" min="0" max="30" step="1" style="width:88px"
title="TOP에 올릴 최소 완료 거래 수. 0=제한 없음(느림). 1=1회라도 체결된 조합 포함">
</div>
<div class="col-auto mt-auto">
<button class="btn btn-secondary" onclick="hdLoadStocks()">🔄 종목 목록 갱신</button>
</div>
</div>
<div class="mt-2" style="font-size:11px;color:var(--muted)">
⚡ 일봉 기반 전략 | RSI 3단계 분할매수 (35/30/25) | 수익률+익절 / RSI과열 / 손절 | <code>holding_candles</code> DB 사용<br>
📋 <b>종목 목록</b>은 저장소 루트의 <code>long_term_watchlist.json</code> (<code>items[]</code><code>code</code>·<code>name</code>) 에서 불러옵니다. 편집 후 <b>종목 목록 갱신</b>을 누르세요.
</div>
</div>
<!-- 종목 카드 목록 (JS로 동적 생성) -->
<div id="hd_stock_list" class="row g-3"></div>
<!-- 백테스트 결과 영역 (선택한 종목) -->
<div id="hd_result_area" style="display:none" class="mt-4">
<div class="section-title" id="hd_result_title">백테스트 결과</div>
<div id="hd_bt_params_echo" class="text-muted" style="font-size:11px;margin:-4px 0 10px 0;display:none;line-height:1.45"></div>
<div class="row g-3 mb-3">
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">총 거래</div><div class="stat-val" id="hd_total">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">승률</div><div class="stat-val" id="hd_wr">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">순손익(수수료·세금 포함)</div><div class="stat-val" id="hd_pnl">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">Profit Factor</div><div class="stat-val" id="hd_pf">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="hd_mdd">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">평균 보유(일)</div><div class="stat-val" id="hd_hold">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">총 수익률(운용한도 대비)</div><div class="stat-val" id="hd_bot_pct_sum">-</div>
</div></div>
<div class="col-6 col-md-2"><div class="card p-3">
<div class="card-title">일평균 수익률</div><div class="stat-val" id="hd_daily_avg_pct">-</div>
</div></div>
</div>
<!-- Buy & Hold 비교 -->
<div class="row g-3 mb-3" id="hd_bnh_row" style="display:none">
<div class="col-12"><div class="card p-3" style="border-color:var(--accent);background:rgba(88,166,255,0.05)">
<div class="card-title" style="color:var(--accent)">📊 Buy &amp; Hold 벤치마크 비교 <small class="text-muted">("가만히 들고 있었으면?")</small></div>
<div class="text-muted" style="font-size:11px;margin-bottom:6px">전체 구간 = 백테스트 첫 봉 종가 → 마지막 종가 (봇과 기간은 같으나 진입 시점만 다름)</div>
<div class="row g-3 mt-1">
<div class="col-6 col-md-3"><div class="card-title">봇 수익률(투자금 대비)</div><div class="stat-val" id="hd_bot_pct">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">B&amp;H 수익률(전체)</div><div class="stat-val" id="hd_bnh_pct">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">B&amp;H 손익(전체·원)</div><div class="stat-val" id="hd_bnh_pnl">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">알파(봇 전체 B&amp;H)</div><div class="stat-val" id="hd_alpha">-</div></div>
</div>
</div></div>
</div>
<div class="row g-3 mb-3" id="hd_bnh_aligned_row" style="display:none">
<div class="col-12"><div class="card p-3" style="border-color:#58a6ff;background:rgba(88,166,255,0.07)">
<div class="card-title" style="color:#58a6ff">📌 시뮬과 동일 구간 B&amp;H <small class="text-muted">(MA·RSI 준비 완료 봉의 종가 → 마지막 종가)</small></div>
<div class="text-muted" style="font-size:11px;margin-bottom:6px">봇 엔진이 첫 매매 판단을 내리는 봉부터 같은 조건으로 들고 간다고 가정한 벤치마크입니다.</div>
<div class="row g-3 mt-1">
<div class="col-6 col-md-3"><div class="card-title">B&amp;H 수익률(동일구간)</div><div class="stat-val" id="hd_bnh_aligned_pct">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">B&amp;H 손익(동일구간·원)</div><div class="stat-val" id="hd_bnh_aligned_pnl">-</div></div>
<div class="col-6 col-md-3"><div class="card-title">알파(봇 동일구간 B&amp;H)</div><div class="stat-val" id="hd_alpha_aligned">-</div></div>
</div>
</div></div>
</div>
<div id="hd_candle_block" class="mb-3" style="display:none">
<div class="card p-3">
<div class="card-title mb-2">일봉·봉 목록 <small class="text-muted">(최신순 · 전일(직전 봉) 대비)</small></div>
<div class="text-muted" style="font-size:10px;margin-bottom:6px">「전일비」열은 <b>실제 시장 등락</b>입니다. RSI·MA 등 카드 숫자를 바꿔도 여기 %는 바뀌지 않습니다.</div>
<div class="table-responsive" style="max-height:440px;overflow-y:auto">
<table class="table table-sm table-hover" style="font-size:11px">
<thead><tr>
<th>일시</th><th>시가</th><th>고가</th><th>저가</th><th>종가</th>
<th>전일비(원)</th><th>전일비(%)</th>
</tr></thead>
<tbody id="hd_candle_tbody"></tbody>
</table>
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="col-12 col-lg-8"><div class="card p-3">
<div class="card-title mb-2">누적 손익 곡선</div>
<canvas id="hd_equity_chart" height="220"></canvas>
</div></div>
<div class="col-12 col-lg-4"><div class="card p-3">
<div class="card-title mb-2">매도 이유 분포</div>
<canvas id="hd_reason_chart" height="200"></canvas>
</div></div>
</div>
<!-- 파라미터 탐색 결과 -->
<div id="hd_search_result" style="display:none">
<div class="section-title">🔍 파라미터 탐색 결과 (TOP 20)</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead id="hd_search_thead"><tr>
<th>-</th><th>손익(원)</th><th>승률</th><th>거래</th><th>PF</th><th>보유(일)</th><th>적용</th>
</tr></thead>
<tbody id="hd_search_tbody"></tbody>
</table>
</div>
<p id="hd_search_hint" class="text-muted" style="display:none;font-size:11px;margin-top:8px;line-height:1.45;"></p>
</div>
</div>
<!-- 거래 내역 -->
<div class="section-title mt-3">가상 거래 내역 (최근 200건)</div>
<div id="hd_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="hd_trade_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="card p-3">
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead><tr>
<th>종목</th><th>매수일</th><th>매도일</th><th>매수가</th><th>매도가</th>
<th>수량</th><th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th><th>보유(일)</th><th>매도사유</th>
</tr></thead>
<tbody id="hd_trade_tbody"></tbody>
</table>
</div>
</div>
</div>
</div><!-- tab-holding end -->
<!-- ═══ 박스엔진 UPDOWN (kis_trader/engine/updown_box) ═══════════════════════════ -->
<div id="tab-updownbox" style="display:none">
<!-- 안내 -->
<div class="card p-3 mb-3">
<h6 class="mb-1">📦 박스권(횡보) 하단 되돌림 매수 — 신규 엔진</h6>
<div class="text-muted" style="font-size:12px;line-height:1.7">
조건검색 → <b>박스필터(SCAN)</b><code>updown_watchlist</code>(sticky, 최대 30) → 하단 근접 매수 ·
청산 스택 <b>박스이탈 → 패닉(고점-%) → 래칫(어깨컷) → 익절 → 손절</b>.<br>
글로벌 파라미터(<code>UPDOWN_BOX_*</code>)는 <b>운영설정 탭</b>에서 저장 — 여기선 백테/파라서치로 검증 후 1위를 ENV에 적용.
백테=실매 동일 엔진(<code>run_backtest_box</code>). 데이터: <code>holding_min_candles</code>(기본 15분).
</div>
</div>
<!-- watchlist 패널 -->
<div class="card p-3 mb-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<h6 class="mb-0">⭐ 관심종목 (updown_watchlist)
<small class="text-muted" id="ubx_watch_stat">— active 0 / max 0</small></h6>
<div>
<label class="form-check-label me-2" style="font-size:12px">
<input type="checkbox" id="ubx_watch_active_only" onchange="ubxLoadWatch()"> active만</label>
<button class="btn btn-sm btn-secondary" onclick="ubxLoadWatch()">🔄 새로고침</button>
</div>
</div>
<div class="row g-2 align-items-end mb-2">
<div class="col-auto">
<label class="form-label param-row" style="font-size:11px">코드</label>
<input type="text" class="form-control form-control-sm" id="ubx_add_code" placeholder="005930" style="width:110px">
</div>
<div class="col-auto">
<label class="form-label param-row" style="font-size:11px">이름</label>
<input type="text" class="form-control form-control-sm" id="ubx_add_name" placeholder="(선택)" style="width:120px">
</div>
<div class="col-auto">
<label class="form-label param-row" style="font-size:11px" title="박스권 바닥가. 현재가가 이 값×(1이탈여유%) 밑으로 떨어지면 '박스이탈' 손절. 0=캔들에서 자동계산">박스하단</label>
<input type="number" class="form-control form-control-sm" id="ubx_add_low" placeholder="0=자동" style="width:100px">
</div>
<div class="col-auto">
<label class="form-label param-row" style="font-size:11px" title="박스권 천장가. 0=캔들에서 자동계산">박스상단</label>
<input type="number" class="form-control form-control-sm" id="ubx_add_high" placeholder="0=자동" style="width:100px">
</div>
<div class="col-auto">
<button class="btn btn-sm btn-success" onclick="ubxAddWatch()" title="같은 코드면 덮어쓰기(수정). 박스하단/상단 0이면 엔진이 자동 계산"> 추가/수정</button>
</div>
</div>
<div class="text-muted mb-2" style="font-size:11px">
💡 박스하단/상단은 차트의 횡보 바닥·천장 가격. <b>모르면 0</b>으로 두면 엔진이 캔들에서 자동 계산합니다.
같은 코드로 다시 [추가/수정]하면 덮어써집니다(행의 <b>수정</b> 버튼이 값을 폼에 불러옵니다).
</div>
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead><tr>
<th>코드</th><th>이름</th><th>상태</th><th>소스</th><th>박스하단</th><th>박스상단</th>
<th>점수</th><th>추가일</th><th>최근신호</th><th></th>
</tr></thead>
<tbody id="ubx_watch_tbody"><tr><td colspan="10" class="text-muted">로딩…</td></tr></tbody>
</table>
</div>
</div>
<!-- 백테/파라서치 입력 -->
<div class="card p-3 mb-3">
<div class="row g-2 align-items-end flex-wrap">
<div class="col-auto">
<label class="form-label param-row" title="단일 백테용 / 파라서치는 codes(쉼표) 또는 watchlist">종목코드</label>
<input type="text" class="form-control" id="ubx_code" placeholder="005930 (목록에서 선택/직접입력)" style="width:230px"
list="ubx_stock_options" onchange="ubxLoadStockCfg(this.value)" oninput="ubxLoadStockCfg(this.value)">
<datalist id="ubx_stock_options"></datalist>
<div id="ubx_stock_cfg_badge" class="mt-1" style="font-size:11px"></div>
</div>
<div class="col-auto">
<label class="form-label param-row">분봉(TF)</label>
<select class="form-select" id="ubx_tf" style="width:90px">
<option value="15" selected>15분</option>
<option value="60">60분</option>
<option value="5">5분</option>
<option value="3">3분</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">시작일</label>
<input type="date" class="form-control" id="ubx_start" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료일</label>
<input type="date" class="form-control" id="ubx_end" style="width:150px">
</div>
<div class="col-auto">
<button class="btn btn-info" onclick="ubxRunBacktest()">📊 박스 백테</button>
</div>
</div>
<hr class="my-2" style="border-color:#30363d">
<div class="row g-2 align-items-end flex-wrap">
<div class="col-auto">
<label class="form-label param-row" title="박스 lookback (UPDOWN_BOX_LOOKBACK_BARS)">박스봉</label>
<input type="number" class="form-control" id="ubx_lookback_bars" step="1" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="박스 최대 높이% (UPDOWN_BOX_RANGE_MAX_PCT)">범위상한%</label>
<input type="number" class="form-control" id="ubx_range_max_pct" step="0.5" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="밴드폭 상한% (UPDOWN_BOX_BB_BW_MAX)">밴드폭%</label>
<input type="number" class="form-control" id="ubx_bb_bw_max" step="0.5" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="MA 기울기 허용% (UPDOWN_BOX_MA_SLOPE_TOL_PCT)">기울기%</label>
<input type="number" class="form-control" id="ubx_ma_slope_tol_pct" step="0.1" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="하단 근접 진입% (UPDOWN_BOX_NEAR_LOW_PCT)">하단근접%</label>
<input type="number" class="form-control" id="ubx_near_low_pct" step="0.1" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="익절% (UPDOWN_BOX_TP_PCT)">익절%</label>
<input type="number" class="form-control" id="ubx_tp_pct" step="0.5" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="하드손절% (UPDOWN_BOX_STOP_LOSS_PCT)">손절%</label>
<input type="number" class="form-control" id="ubx_stop_loss_pct" step="0.1" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="박스이탈 여유% (UPDOWN_BOX_BREACH_BUFFER_PCT)">이탈여유%</label>
<input type="number" class="form-control" id="ubx_breach_buffer_pct" step="0.1" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="패닉 고점대비% (UPDOWN_PANIC_FROM_HIGH_PCT)">패닉%</label>
<input type="number" class="form-control" id="ubx_panic_from_high_pct" step="0.5" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="래칫 무장+% (UPDOWN_BOX_SHOULDER_MIN_HIGH_PCT)">어깨발동%</label>
<input type="number" class="form-control" id="ubx_shoulder_min_high_pct" step="0.1" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="래칫 컷 고점대비-% (UPDOWN_BOX_SHOULDER_CUT_PCT)">어깨폭%</label>
<input type="number" class="form-control" id="ubx_shoulder_cut_pct" step="0.1" style="width:90px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="다단 래칫 — 값 있으면 단일 어깨컷 대체. 형식 수익%:컷%,… (UPDOWN_BOX_RATCHET_TIERS)">다단래칫(수익%:컷%,…)</label>
<input type="text" class="form-control" id="ubx_ratchet_tiers" placeholder="2:1.5,5:1.0" style="width:160px;font-size:12px"
oninput="ubxSyncRatchetShoulderColors&&ubxSyncRatchetShoulderColors()">
</div>
<div class="col-auto">
<label class="form-label param-row" title="보유한도 봉 (UPDOWN_BOX_MAX_HOLD_BARS)">보유한도</label>
<input type="number" class="form-control" id="ubx_max_hold_bars" step="1" style="width:80px">
</div>
<div class="col-auto">
<label class="form-label param-row" title="ON 이면 박스 상단을 위로 돌파한 뒤엔 익절(tp)을 끄고 래칫(트레일)만으로 추세를 끝까지 추종. 횡보 중엔 평소대로 tp로 짧게. (UPDOWN_BOX_BREAKOUT_FOLLOW)">돌파추종</label>
<select class="form-control" id="ubx_breakout_follow" style="width:90px">
<option value="0">OFF</option>
<option value="1">ON(추종)</option>
</select>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-outline-secondary" onclick="ubxLoadCfg()" title="운영설정 UPDOWN_BOX_* 글로벌 현재값 불러오기">글로벌 불러오기</button>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-outline-primary" onclick="ubxSaveStockCfg()" title="위 [종목코드]의 종목별 파라미터로 현재 입력값을 고정 저장(핀). 실매·백테 모두 이 종목엔 이 값 적용">💾 종목설정 저장</button>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-outline-warning" onclick="ubxClearStockCfg()" title="이 종목의 종목별 핀 해제 → 글로벌로 복귀">↩ 글로벌복귀</button>
</div>
</div>
<hr class="my-2" style="border-color:#30363d">
<div class="row g-2 align-items-end flex-wrap">
<div class="col-auto">
<label class="form-label param-row" title="파라서치 종목 — 쉼표 구분. 비우면 위 종목코드 1개">탐색 종목(codes)</label>
<input type="text" class="form-control" id="ubx_codes" placeholder="005930,000660,005380" style="width:280px">
</div>
<div class="col-auto">
<label class="form-check-label" style="font-size:12px">
<input type="checkbox" id="ubx_from_watchlist"> watchlist active 사용</label>
</div>
<div class="col-auto">
<label class="form-label param-row">모드</label>
<select class="form-select" id="ubx_mode" style="width:100px">
<option value="fast" selected>fast(4축)</option>
<option value="full">full(7축)</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">최소거래</label>
<input type="number" class="form-control" id="ubx_min_trades" value="3" min="0" step="1" style="width:80px">
</div>
<div class="col-auto">
<button class="btn btn-warning" onclick="ubxRunParamSearch()">🔍 파라미터 탐색</button>
</div>
</div>
<div class="mt-1 text-muted" style="font-size:11px" id="ubx_status"></div>
</div>
<!-- 결과: 요약 -->
<div class="card p-3 mb-3" id="ubx_summary_card" style="display:none">
<h6 class="mb-2">백테 요약 <small class="text-muted" id="ubx_summary_sub"></small></h6>
<div id="ubx_summary"></div>
</div>
<!-- 결과: 파라서치 top -->
<div class="card p-3 mb-3" id="ubx_ps_card" style="display:none">
<h6 class="mb-2">파라서치 상위 <small class="text-muted" id="ubx_ps_sub"></small></h6>
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead><tr>
<th>#</th><th>초과수익 α%</th><th>합산손익%</th><th>B&H%</th><th>PF</th><th>승률%</th><th>거래</th><th>파라미터</th><th></th>
</tr></thead>
<tbody id="ubx_ps_tbody"></tbody>
</table>
</div>
</div>
<!-- 결과: 거래 목록 (다른 전략과 동일한 공통 컴포넌트 renderVirtualTrades 사용) -->
<div class="card p-3 mb-3" id="ubx_trades_card" style="display:none">
<h6 class="mb-2">거래 목록 <small class="text-muted" id="ubx_trades_sub"></small></h6>
<div id="ubx_trade_context" class="mb-2 p-2 rounded" style="font-size:12px;background:var(--bg-secondary, #1c2128);color:var(--muted);display:none"></div>
<div class="trade-sort-bar mb-2" data-tbody="ubx_trades_tbody">
<span class="trade-sort-label">정렬</span>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn active" data-sort="exit_desc">매도 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="exit_asc">매도 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_desc">매수 최신</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="buy_asc">매수 오래된순</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_desc">손익↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
</div>
<div class="table-responsive">
<table class="table table-hover" style="font-size:12px">
<thead><tr>
<th>종목</th><th>매수시각</th><th>매도시각</th>
<th>매수가</th><th>매도가</th><th>수량</th>
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th><th>보유(봉)</th><th>청산사유</th>
</tr></thead>
<tbody id="ubx_trades_tbody"></tbody>
</table>
</div>
</div>
</div><!-- tab-updownbox end -->
<!-- ═══ 하락매수 Updow (kis_trader/strategies/updow_buy) ═════════════════════════ -->
<div id="tab-updow" style="display:none">
<!-- ═══ 영구구독 관리 (국내 WS H0STCNT0 + 해외 WS HDFSCNT0) ═══ -->
<div class="card p-3 mb-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<h6 class="mb-0">📡 영구구독 관리 <small class="text-muted">(KR=국내 WS · US=해외 WS · 저장봉=1분→롤업)</small></h6>
<button class="btn btn-sm btn-outline-secondary" type="button" onclick="permLoad()">새로고침</button>
</div>
<div class="row g-2 align-items-end flex-wrap mb-2">
<div class="col-auto">
<label class="form-label param-row">코드</label>
<input class="form-control" id="perm_code" style="width:110px" placeholder="QQQM/005930">
</div>
<div class="col-auto">
<label class="form-label param-row">시장</label>
<select class="form-select" id="perm_market" style="width:90px" onchange="permOnMarket()">
<option value="KR">KR</option>
<option value="US">US</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">거래소</label>
<select class="form-select" id="perm_exch" style="width:100px">
<option value="KRX">KRX</option>
<option value="NASD">NASD</option>
<option value="NYSE">NYSE</option>
<option value="AMEX">AMEX</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">심볼(US)</label>
<input class="form-control" id="perm_symbol" style="width:100px" placeholder="(기본=코드)">
</div>
<div class="col-auto">
<label class="form-label param-row">메모</label>
<input class="form-control" id="perm_note" style="width:160px" placeholder="용도">
</div>
<div class="col-auto">
<button class="btn btn-sm btn-primary" type="button" onclick="permSave()">추가/수정</button>
</div>
</div>
<div class="table-responsive">
<table class="table table-sm table-bordered align-middle mb-0" style="font-size:.85rem">
<thead><tr>
<th>종목</th><th>현재가</th><th>시장</th><th>거래소</th><th>저장봉</th><th>WS키</th><th>ON</th><th>메모</th><th></th>
</tr></thead>
<tbody id="perm_tbody"><tr><td colspan="9" class="text-muted">로딩…</td></tr></tbody>
</table>
</div>
<small class="text-muted">저장봉은 전부 <b>1분</b>(상위 15/60분은 롤업). TF 입력 없음. 현재가=WS 1분봉 DB(틱전수스캔·외부환율 HTTP 없음). US는 <b>$ + 원</b> 병기(표시용 환율). 탭 열면 자동 새로고침.</small>
</div>
</div><!-- tab-updow end -->
<!-- ═══ DART 수주 공시 ═══════════════════════════════════════════════════ -->
<div id="tab-dart" style="display:none">
<div class="card p-3 mb-3">
<h6 class="mb-2">📢 DART 수주/공급계약 <small class="text-muted">(영구구독과 분리 · TTL 워치)</small></h6>
<div class="row g-2 align-items-center mb-2">
<div class="col-auto form-check form-switch">
<input class="form-check-input" type="checkbox" id="dart_scan_en">
<label class="form-check-label" for="dart_scan_en">SCAN</label>
</div>
<div class="col-auto form-check form-switch">
<input class="form-check-input" type="checkbox" id="dart_sub_en">
<label class="form-check-label" for="dart_sub_en">임시구독</label>
</div>
<div class="col-auto form-check form-switch">
<input class="form-check-input" type="checkbox" id="dart_trade_en">
<label class="form-check-label" for="dart_trade_en">매매</label>
</div>
<div class="col-auto form-check form-switch">
<input class="form-check-input" type="checkbox" id="dart_strat_en">
<label class="form-check-label" for="dart_strat_en">전략등록</label>
</div>
<div class="col-auto">
<label class="form-label mb-0 small">워치상한</label>
<input type="number" id="dart_watch_max" class="form-control form-control-sm" style="width:80px" value="15">
</div>
<div class="col-auto">
<label class="form-label mb-0 small">TTL(h)</label>
<input type="number" id="dart_watch_ttl" class="form-control form-control-sm" style="width:80px" value="24">
</div>
<div class="col-auto form-check form-switch">
<input class="form-check-input" type="checkbox" id="dart_quality_en" checked>
<label class="form-check-label" for="dart_quality_en">품질필터</label>
</div>
<div class="col-auto">
<label class="form-label mb-0 small">최소매출%</label>
<input type="number" id="dart_min_sales" class="form-control form-control-sm" style="width:80px" value="5" step="0.1">
</div>
<div class="col-auto form-check form-switch">
<input class="form-check-input" type="checkbox" id="dart_require_theme" checked>
<label class="form-check-label" for="dart_require_theme">테마필수</label>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-primary" onclick="dartSaveConfig()">스위치 저장</button>
<button class="btn btn-sm btn-outline-secondary" onclick="dartLoad()">새로고침</button>
</div>
</div>
<small class="text-muted">매매 OFF 기본. 품질필터=건설·재개발 제외 + 매출대비% + 수출/반도체·방산 테마. 영구구독 탭과 무관.</small>
</div>
<div class="card p-3 mb-3">
<h6>활성 워치</h6>
<div class="table-responsive">
<table class="table table-sm table-dark">
<thead><tr><th>코드</th><th>종목</th><th>공시</th><th>추가</th><th>만료</th></tr></thead>
<tbody id="dart_watch_tbody"><tr><td colspan="5" class="text-muted">로딩…</td></tr></tbody>
</table>
</div>
</div>
<div class="card p-3 mb-3">
<h6>최근 공시 <small class="text-muted">(필터통과/제외 포함)</small></h6>
<div class="table-responsive" style="max-height:360px;overflow:auto">
<table class="table table-sm table-dark">
<thead><tr><th>시각</th><th>코드</th><th>종목</th><th>매출%</th><th>필터</th><th>공시명</th><th>링크</th></tr></thead>
<tbody id="dart_disc_tbody"><tr><td colspan="7" class="text-muted">로딩…</td></tr></tbody>
</table>
</div>
</div>
<div class="card p-3 mb-3">
<h6>백테 (공시 이벤트 × RSI 반등)</h6>
<div class="row g-2 align-items-end">
<div class="col-auto"><label class="small">시작</label><input type="date" id="dart_bt_start" class="form-control form-control-sm"></div>
<div class="col-auto"><label class="small">종료</label><input type="date" id="dart_bt_end" class="form-control form-control-sm"></div>
<div class="col-auto"><button class="btn btn-sm btn-success" onclick="dartRunBacktest()">백테 실행</button></div>
</div>
<pre id="dart_bt_out" class="mt-2 small text-muted" style="white-space:pre-wrap"></pre>
</div>
</div><!-- tab-dart end -->
<!-- ═══ Optuna 파람서치 (잡 시작 + 폴링, HTTP 타임아웃 회피) ═══════════════ -->
<div id="tab-optuna" style="display:none">
<div class="card p-3 mb-3">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-2">
<h6 class="mb-0">🔬 Optuna TPE 탐색</h6>
<small class="text-muted">서버 subprocess · apply-best 없음 · 해외모멘텀=전역만(종목 cfg는 🇺🇸탭)</small>
</div>
<div class="row g-2 align-items-end">
<div class="col-12">
<label class="form-label param-row mb-1">전략 <small class="text-muted">(여러 개면 순차 · 해외는 따로 체크)</small></label>
<div class="d-flex flex-wrap align-items-center gap-2" id="opt_strat_checks">
<label class="form-check form-check-inline mb-0"><input class="form-check-input opt-strat-cb" type="checkbox" value="momentum" checked> 모멘텀</label>
<label class="form-check form-check-inline mb-0" title="전역 US_MOMENTUM_* 만 · 종목 cfg는 🇺🇸탭">
<input class="form-check-input opt-strat-cb" type="checkbox" value="us_momentum"> 해외모멘텀(전역)
</label>
<label class="form-check form-check-inline mb-0"><input class="form-check-input opt-strat-cb" type="checkbox" value="tail"> 꼬리</label>
<label class="form-check form-check-inline mb-0"><input class="form-check-input opt-strat-cb" type="checkbox" value="breakout"> 돌파</label>
<label class="form-check form-check-inline mb-0"><input class="form-check-input opt-strat-cb" type="checkbox" value="scalp"> 스캘핑</label>
<button type="button" class="btn btn-sm btn-outline-secondary py-0" onclick="optunaPickKr4()">국내4</button>
<button type="button" class="btn btn-sm btn-outline-secondary py-0" onclick="optunaPickNone()">해제</button>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row">시작</label>
<input type="date" id="opt_start" class="form-control form-control-sm" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">종료</label>
<input type="date" id="opt_end" class="form-control form-control-sm" style="width:150px">
</div>
<div class="col-auto">
<label class="form-label param-row">trials</label>
<input type="number" id="opt_trials" class="form-control form-control-sm" style="width:90px" value="200" min="1" max="2000">
</div>
<div class="col-auto">
<label class="form-label param-row">mode</label>
<input type="text" id="opt_mode" class="form-control form-control-sm" style="width:80px" value="tpe" readonly>
</div>
<div class="col-auto">
<label class="form-label param-row" title="BACKTEST_UNIVERSE_HISTORY_SOURCE — 키움 target_candidates_history / LS ls_candidates_history">이력소스</label>
<select class="form-select form-select-sm" id="opt_univ_history_source" style="width:160px">
<option value="kiwoom" selected>키움 (target_candidates)</option>
<option value="ls">LS (ls_candidates)</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">캔들소스</label>
<select class="form-select form-select-sm" id="opt_candle_source" style="width:80px" title="기본=실매 LIVE_TICK_PROVIDER 우선 병합">
<option value="" selected title="실매 LIVE_TICK_PROVIDER 순서 (kiwoom→kis→rest)">기본</option>
<option value="kis">KIS</option>
<option value="kiwoom">키움</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">틱소스</label>
<select class="form-select form-select-sm" id="opt_tick_source" style="width:80px">
<option value="" selected>기본</option>
<option value="kis">KIS</option>
<option value="kiwoom">키움</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row">호가소스</label>
<select class="form-select form-select-sm" id="opt_ob_source" style="width:80px">
<option value="" selected>기본</option>
<option value="kis">KIS</option>
<option value="kiwoom">키움</option>
</select>
</div>
<div class="col-auto">
<button class="btn btn-sm btn-primary" id="opt_btn_start" onclick="optunaStart()">시작</button>
<button class="btn btn-sm btn-outline-danger" id="opt_btn_stop" onclick="optunaStop()" disabled>중지</button>
<button class="btn btn-sm btn-outline-secondary" onclick="optunaRefreshJobs()">새로고침</button>
</div>
</div>
<small class="text-muted d-block mt-2">탐색 게이트 WR/PF=0 · 사후=results_gated · 안정=results_stable · DB 자동적용 안 함 · 2개 이상=순차(병렬 아님) · 이력소스=저장 후보 테이블</small>
</div>
<div class="card p-3 mb-3" id="opt_status_card">
<h6>진행</h6>
<div class="optuna-prog-track mb-2" style="height:10px">
<div class="optuna-prog-fill" id="opt_tab_fill" style="width:0%"></div>
</div>
<div class="row g-2" style="font-size:13px">
<div class="col-md-6">
<div><span class="text-muted">상태</span> <b id="opt_st_status"></b></div>
<div><span class="text-muted"></span> <code id="opt_st_job"></code></div>
<div><span class="text-muted">study</span> <code id="opt_st_study" style="font-size:11px"></code></div>
<div><span class="text-muted">trial</span> <span id="opt_st_trials"></span></div>
</div>
<div class="col-md-6">
<div><span class="text-muted">로그</span> <code id="opt_st_log" style="font-size:11px"></code></div>
<div><span class="text-muted">결과 JSON</span> <code id="opt_st_json" style="font-size:11px"></code></div>
<div id="opt_st_top" class="mt-1 text-muted"></div>
</div>
</div>
<pre id="opt_log_tail" class="mt-2 small text-muted p-2" style="max-height:180px;overflow:auto;background:#0d1117;border:1px solid var(--border);border-radius:6px;white-space:pre-wrap"></pre>
<div id="opt_apply_box" class="mt-3 d-none">
<button class="btn btn-sm btn-success" id="opt_btn_apply_gated" onclick="optunaApply('gated',1)">
✅ 사후합격 1위 DB 적용
</button>
<button class="btn btn-sm btn-outline-info" id="opt_btn_apply_stable" onclick="optunaApply('stable',1)">
🛡️ 안정 1위 DB 적용
</button>
<button class="btn btn-sm btn-outline-success" id="opt_btn_apply_mode" onclick="optunaApply('mode',1)">
mode_combo DB 적용
</button>
<small class="text-muted ms-2">완료 후에만 · TIME_* 미변경 · confirm 필수</small>
</div>
</div>
<div class="card p-3 mb-3">
<h6>비교표 <small class="text-muted">학습1위 · gated1위 · stable1위 · mode_combo</small></h6>
<div class="table-responsive">
<table class="table table-sm table-hover mb-1" style="font-size:12px">
<thead>
<tr>
<th>구분</th><th>trial</th><th class="text-end">거래</th>
<th class="text-end">승률%</th><th class="text-end">PF</th><th class="text-end">PnL</th>
<th class="text-end">손실일</th><th class="text-end">최악일</th><th class="text-end">안정점수</th>
</tr>
</thead>
<tbody id="opt_compare_tbody">
<tr><td colspan="9" class="text-muted">완료 후 표시</td></tr>
</tbody>
</table>
</div>
<div id="opt_vs_best" class="small text-muted"></div>
<div id="opt_stable_gates" class="small text-muted mt-1"></div>
<div id="opt_daily_trail_rec" class="mt-2 p-2 small" style="background:rgba(56,139,253,0.08);border:1px solid var(--border);border-radius:6px">
<div class="text-muted mb-1">다단트레일 추천 <span class="text-muted">(탐색 축 아님 · DB 적용 시에만 반영)</span></div>
<div id="opt_daily_trail_rec_body">완료 후 표시</div>
</div>
<div id="opt_postprocess_rec" class="mt-2 p-2 small" style="background:rgba(63,185,80,0.06);border:1px solid var(--border);border-radius:6px">
<div class="text-muted mb-1">후처리 추천 표
<span class="text-muted">(호가 진입+익절 · 휩쏘 · 트레일 · <b>STOP_OB 합의 아직 없음</b>)</span>
</div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" style="font-size:12px">
<thead>
<tr>
<th>구분</th><th>상태</th><th>핵심 수치</th>
<th class="text-end">모수/통계</th><th>비고</th>
</tr>
</thead>
<tbody id="opt_postprocess_tbody">
<tr><td colspan="5" class="text-muted">완료 후 표시</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="card p-3 mb-3">
<h6>사후합격 Top5 <small class="text-muted">results_gated</small></h6>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" style="font-size:12px">
<thead>
<tr>
<th>#</th><th>trial</th><th class="text-end">거래</th>
<th class="text-end">승률</th><th class="text-end">PF</th><th class="text-end">PnL</th><th></th>
</tr>
</thead>
<tbody id="opt_top5_tbody">
<tr><td colspan="7" class="text-muted">완료 후 표시</td></tr>
</tbody>
</table>
</div>
</div>
<div class="card p-3 mb-3">
<h6>안정 Top5 <small class="text-muted">results_stable · 손실일/최악일 게이트 · score=일평균−λ×표준편차</small></h6>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" style="font-size:12px">
<thead>
<tr>
<th>#</th><th>trial</th><th class="text-end">거래</th>
<th class="text-end">승률</th><th class="text-end">PnL</th>
<th class="text-end">손실일</th><th class="text-end">최악일</th><th class="text-end">안정점수</th><th></th>
</tr>
</thead>
<tbody id="opt_top5_stable_tbody">
<tr><td colspan="9" class="text-muted">완료 후 표시 (구 JSON은 재실행 필요)</td></tr>
</tbody>
</table>
</div>
</div>
<div class="card p-3 mb-3" id="opt_detail_card">
<h6>선택 후보 상세 <small class="text-muted" id="opt_detail_title">Top5「보기」또는 비교표 행 선택</small></h6>
<div id="opt_detail_metrics" class="mb-2 small text-muted">아직 선택 없음</div>
<pre id="opt_detail_params" class="small p-2 mb-0" style="max-height:220px;overflow:auto;background:#0d1117;border:1px solid var(--border);border-radius:6px;white-space:pre-wrap;color:var(--text)"></pre>
</div>
<div class="card p-3 mb-3">
<h6>브리핑 미리보기</h6>
<pre id="opt_briefing" class="small" style="max-height:280px;overflow:auto;white-space:pre-wrap;color:var(--text)"></pre>
</div>
<div class="card p-3 mb-3">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-2">
<h6 class="mb-0">최근 잡</h6>
<div class="d-flex align-items-center gap-2">
<label class="small text-muted mb-0" for="opt_jobs_sort">정렬</label>
<select id="opt_jobs_sort" class="form-select form-select-sm" style="width:120px" onchange="optunaRefreshJobs()">
<option value="started" selected>시작↓</option>
<option value="finished">종료↓</option>
</select>
</div>
</div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" style="font-size:12px">
<thead>
<tr>
<th>job_id</th><th>전략</th><th>기간</th><th>상태</th><th>trial</th><th>시작</th><th>종료</th><th></th>
</tr>
</thead>
<tbody id="opt_jobs_tbody"><tr><td colspan="8" class="text-muted">로딩…</td></tr></tbody>
</table>
</div>
</div>
</div><!-- tab-optuna end -->
</div><!-- container end -->
<script src="{{ url_for('static', filename='js/backtest.js') }}"></script>
</body>
</html>