4602 lines
306 KiB
HTML
4602 lines
306 KiB
HTML
<!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/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||
<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 class="optuna-prog-track mt-1 d-none" id="optuna_nav_post_track" style="height:4px">
|
||
<div class="optuna-prog-fill is-post" id="optuna_nav_post_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 id="nav_sys_perf" class="badge bg-secondary ms-2" style="font-size:11px; cursor:pointer;" title="오늘 평균 매수 체결 슬리피지. (수집통계 탭 진단 정보)" onclick="switchTab('feed_tab')">
|
||
⚡ Slippage: -
|
||
</span>
|
||
<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 id="bt_engine_nav" class="d-flex align-items-center gap-2 ms-3" title="모든 백테스트/옵투나에 적용될 엔진.">
|
||
<span class="text-muted" style="font-size:11px;white-space:nowrap">엔진</span>
|
||
<div class="btn-group btn-group-sm" role="group" aria-label="BT_ENGINE">
|
||
<input type="radio" class="btn-check" name="bt_engine_radio" id="bt_engine_python" value="python" checked>
|
||
<label class="btn btn-outline-secondary" for="bt_engine_python">Python</label>
|
||
<input type="radio" class="btn-check" name="bt_engine_radio" id="bt_engine_rust" value="rust">
|
||
<label class="btn btn-outline-secondary" for="bt_engine_rust">Rust</label>
|
||
</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="feedstats" 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="envhist" href="#">🧾 env변경</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">
|
||
<label class="form-label param-row" style="color:var(--muted);font-size:12px" title="trade_history/active_trades.is_mock">계좌</label>
|
||
<select id="dash_account" class="form-control form-control-sm" style="width:130px" onchange="loadDashboard()" title="모의=1 · 실전=0 · 미상(NULL)은 전체에서만">
|
||
<option value="">현재(KIS_MOCK)</option>
|
||
<option value="mock">모의만</option>
|
||
<option value="live">실전만</option>
|
||
<option value="all">전체(+미상)</option>
|
||
</select>
|
||
</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">(증권사별 — 키움 · 한투)</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>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>
|
||
|
||
<!-- 조건검색 이력: 키움 target_candidates_history 원툴 -->
|
||
<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">조건검색 이력 (키움)</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 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">
|
||
<label class="form-label param-row" title="trade_history.is_mock · 모의/실전 구분">계좌</label>
|
||
<select id="act_account" class="form-control" style="width:140px" title="기본=현재 KIS_MOCK. 미상(NULL)은 「전체」에서만">
|
||
<option value="">현재(KIS_MOCK)</option>
|
||
<option value="mock">모의만</option>
|
||
<option value="live">실전만</option>
|
||
<option value="all">전체(+미상)</option>
|
||
</select>
|
||
</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" title="목표가 vs 실제 체결가 평균 괴리율">평균 슬리피지</div><div class="stat-val" id="a_slippage">-</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 title="is_mock: 1=모의 · 0=실전 · NULL=미상">계좌</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><th title="【살 때】 녹=괜찮음 · 노랑=숫자만/기록없음 · 빨강=간격큼/살힘약함/팔대기많음. 가격간격=낮을수록 좋음, 살힘=높을수록 좋음(1≈균형).">매수호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th title="【팔 때】 녹=수급OK · 노랑=숫자만 · 빨강=수급약함/간격큼. OR=총사겠음÷총팔겠음. 매수칸과 시각이 다름.">매도호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th>매도사유</th>
|
||
</tr></thead>
|
||
<tbody id="act_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══ 수집통계 (일자별 틱·호가 벤더) ═══════════════════════════════════ -->
|
||
<div id="tab-feedstats" 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="fs_date" class="form-control form-control-sm" style="width:160px">
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-sm btn-primary" onclick="fsLoad(false)">🔄 조회</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-sm btn-outline-secondary" onclick="fsLoad(true)" title="호가0종목 교집합·filter_eval 합격/거부 (느림)">⏱ 상세 집계</button>
|
||
</div>
|
||
<div class="col">
|
||
<small id="fs_meta" class="text-muted"></small>
|
||
</div>
|
||
</div>
|
||
<div style="font-size:12px;color:var(--muted);line-height:1.55;margin-top:8px">
|
||
<b>메인 표</b> = 증권사별 틱 vs 호가 대비 (MODE=tick → 호가행 ≤ 틱행이 정상).
|
||
LS 틱=`ls_ws_ticks` · LS 호가=`ls_ws_orderbook`. filter_eval 은 진입스냅(별도).
|
||
최근 N일 표는 제거(전수 GROUP BY 폭주). 폴백나이는 기본 조회에 포함 · 호가0종목 교집합은 「상세 집계」.
|
||
</div>
|
||
</div>
|
||
<div id="fs_env" class="mb-2" style="font-size:12px"></div>
|
||
<div id="fs_notes" class="mb-3" style="font-size:13px"></div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<div class="fw-semibold mb-2" style="font-size:14px">당일 · 증권사별 틱 / 호가 대비</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-bordered mb-0" style="font-size:13px">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>증권사</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" title="호가행÷틱행">호가/틱</th>
|
||
<th class="text-end">호가/틱%</th>
|
||
<th>비고</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="fs_vendor_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
<div id="fs_vendor_foot" class="mt-2" style="font-size:12px;color:var(--muted)"></div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<div class="fw-semibold mb-2" style="font-size:14px">폴백나이(3초컷) 합격 · 옵투나 usable · 간택</div>
|
||
<div style="font-size:12px;color:var(--muted);margin-bottom:8px" id="fs_age_note"></div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-bordered mb-0" style="font-size:12px">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>채널</th>
|
||
<th>source</th>
|
||
<th class="text-end">총행</th>
|
||
<th class="text-end" title="lag≤나이">합격</th>
|
||
<th class="text-end" title="lag>나이">탈락</th>
|
||
<th class="text-end" title="lag 미상=유지">미상</th>
|
||
<th class="text-end" title="합격+미상">usable</th>
|
||
<th class="text-end" title="자사 총행 대비 usable — 벤더 합≠100">자사%</th>
|
||
<th class="text-end" title="같은 채널 usable 건수 분배 — 합≈100">분배%</th>
|
||
<th class="text-end" title="종목×초 · LIVE_*_PROVIDER 체인 1순위 usable 간택">간택</th>
|
||
<th class="text-end" title="간택 슬롯 대비 %">간택%</th>
|
||
<th class="text-end">탈락%</th>
|
||
<th class="text-end" title="그 분 틱이 전부 탈락">전량탈락분</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="fs_age_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<div class="fw-semibold mb-2" style="font-size:14px">끊김 · 종목별 recv_ts 공백 (연결 축)</div>
|
||
<div style="font-size:12px;color:var(--muted);margin-bottom:8px" id="fs_gap_note"></div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-bordered mb-0" style="font-size:12px">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>벤더</th>
|
||
<th class="text-end" title="연속 틱 쌍 수(장중)">틱쌍</th>
|
||
<th class="text-end" title="간격≥소프트초">끊김(소프트)</th>
|
||
<th class="text-end">소프트%</th>
|
||
<th class="text-end" title="간격≥하드초">끊김(하드)</th>
|
||
<th class="text-end">하드%</th>
|
||
<th class="text-end" title="소프트 이상만 평균">평균끊김(초)</th>
|
||
<th class="text-end">최대공백(초)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="fs_gap_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<div class="fw-semibold mb-2" style="font-size:14px">틱↔호가 공백 · 동기율 (종목 단위)</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-hover mb-0" style="font-size:12px">
|
||
<thead>
|
||
<tr>
|
||
<th>벤더</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" title="틱은 있는데 호가행이 한 줄도 없는 종목">호가0종목</th>
|
||
<th class="text-end">호가0%</th>
|
||
<th class="text-end">호가/틱행%</th>
|
||
<th class="text-end">공백행%</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="fs_cov_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
<div id="fs_overlap" class="mt-2" style="font-size:12px;color:var(--muted)"></div>
|
||
</div>
|
||
|
||
<details class="mb-3">
|
||
<summary style="cursor:pointer;font-size:13px;color:var(--muted)">세부 source / filter_eval / LS 테이블 (접기)</summary>
|
||
<div class="row g-3 mt-1">
|
||
<div class="col-md-6">
|
||
<div class="card p-3">
|
||
<div class="fw-semibold mb-2" style="font-size:13px">틱 by source (<code>ws_ticks</code>)</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm mb-0" style="font-size:12px">
|
||
<thead><tr><th>source</th><th class="text-end">행</th><th class="text-end">종목</th></tr></thead>
|
||
<tbody id="fs_ticks_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="card p-3">
|
||
<div class="fw-semibold mb-2" style="font-size:13px">호가 by source (<code>ws_orderbook</code>)</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm mb-0" style="font-size:12px">
|
||
<thead><tr><th>source</th><th class="text-end">행</th><th class="text-end">종목</th></tr></thead>
|
||
<tbody id="fs_ob_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6 mt-2">
|
||
<div class="card p-3">
|
||
<div class="fw-semibold mb-2" style="font-size:13px">filter_eval by 전략</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm mb-0" style="font-size:12px">
|
||
<thead><tr><th>strategy</th><th class="text-end">행</th><th class="text-end">종목</th></tr></thead>
|
||
<tbody id="fs_fe_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6 mt-2">
|
||
<div class="card p-3">
|
||
<div class="fw-semibold mb-2" style="font-size:13px">LS·전용 테이블</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm mb-0" style="font-size:12px">
|
||
<thead><tr><th>테이블</th><th class="text-end">행</th><th class="text-end">종목</th></tr></thead>
|
||
<tbody id="fs_ls_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
</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">
|
||
<label class="form-label param-row" style="color:var(--muted);font-size:12px" title="손익 집계 is_mock 필터">계좌</label>
|
||
<select id="lc_account" class="form-control form-control-sm" style="width:130px" onchange="lcLoad()" title="당일 실현손익·익절상태 집계용">
|
||
<option value="">현재(KIS_MOCK)</option>
|
||
<option value="mock">모의만</option>
|
||
<option value="live">실전만</option>
|
||
<option value="all">전체(+미상)</option>
|
||
</select>
|
||
</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_strategy_top" class="mb-3"></div>
|
||
<div id="lc_status_cards" class="lc-status-row 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.65">
|
||
<b>진실은 한투 실잔고</b>입니다. RAM·DB는 봇이 기억한 메모일 뿐.
|
||
재시작해도 RAM은 사라지고, 봇은 <code>active_trades</code>만 다시 읽습니다.
|
||
<b>HTS에서 팔지 마세요</b> — 실잔고만 비우고 DB는 남아 <b>유령</b>이 됩니다.
|
||
</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">
|
||
<label class="form-label param-row" style="color:var(--muted);font-size:12px" title="active_trades.is_mock">계좌</label>
|
||
<select id="pf_account" class="form-control" style="width:140px" onchange="pfLoad(false)" title="기본=현재 KIS_MOCK">
|
||
<option value="">현재(KIS_MOCK)</option>
|
||
<option value="mock">모의만</option>
|
||
<option value="live">실전만</option>
|
||
<option value="all">전체(+미상)</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-primary" onclick="pfLoad(false)" title="active_trades 만 다시 읽음. 한투 REST 없음.">1. 🔄 DB 새로고침</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-outline-secondary" onclick="pfLoad(true)" title="한투 잔고 1회 조회 후 DB와 나란히 표시. 고치지는 않음.">2. 📡 실계좌 대조</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-outline-success" onclick="pfReconcileOrphans()" title="매도 없음. 실잔고 기준으로 고아→DB복구 · 유령행 삭제 · 수량/평단 맞춤. 봇 기동 시에도 자동 1회.">3. 🧩 잔고=DB 맞추기</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<span class="text-muted" id="pf_meta" style="font-size:12px"></span>
|
||
</div>
|
||
</div>
|
||
<div class="mt-2 p-2" style="font-size:11px;color:var(--muted);line-height:1.65;background:rgba(88,166,255,0.06);border-radius:6px">
|
||
<b>쓰는 순서</b> (수동매매 안 할 때)<br>
|
||
<b>1 DB 새로고침</b> — 봇이 기억하는 보유만 봄 (빠름).<br>
|
||
<b>2 실계좌 대조</b> — 한투에 있는데 DB에 없으면 봇고아, DB만 있고 한투 0주면 유령.<br>
|
||
<b>3 잔고=DB 맞추기</b> — <u>주문 안 냄</u>. 고아는 DB에 넣고, 유령 행은 지움. 봇 기동 시 자동 1회. 장중 꼬이면 이 버튼.
|
||
</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> 수량은 다른데 둘 다 있음 (3번으로 맞춤) ·
|
||
<span class="badge-loss">봇고아</span> 실잔고 O · DB X · 봇 BUY 있음 → <b>3번</b> ·
|
||
<span class="badge-win">홀딩봇</span> HOLDING 관리(여기서 매도 안 함) ·
|
||
행의 <b>DB없음</b> = 매도 버튼 없음(active_trades 없음). 유령(DB O · 실잔고 0)은 버튼이 있음 → 3번이 행을 지움.
|
||
</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 title="is_mock">계좌</th>
|
||
<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="기본=실매 메인 WS, 구멍=키움 REST">
|
||
<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" readonly tabindex="-1" title="DB·Optuna 적용값 · 수정은 Optuna「적용」" style="background:#0d1117;color:#f0a060">
|
||
</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" readonly tabindex="-1" title="DB·Optuna 적용값 · 수정은 Optuna「적용」" style="background:#0d1117;color:#f0a060">
|
||
</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" readonly tabindex="-1" title="DB·Optuna 적용값 · 수정은 Optuna「적용」" style="background:#0d1117;color:#f0a060">
|
||
</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>
|
||
|
||
<!-- 호가·익절·손절·휩쏘 (DB 읽기전용) — Optuna 적용값 확인. 입력 불가 -->
|
||
<div class="row g-2 align-items-end mt-2 p-2 rounded" style="background:#161b22;border:1px solid #3d2a1a" id="bt_ob_whip_ro_box">
|
||
<div class="col-12">
|
||
<span class="text-muted" style="font-size:11px">
|
||
<b style="color:#f0a060">호가·익절·손절·휩쏘 (DB · 읽기전용)</b>
|
||
— Optuna「적용」후 여기로 확인. 수정 불가 · 백테는 DB값 사용
|
||
</span>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_STOP_LOSS_PCT">손절%<span class="d-block text-muted fw-normal" style="font-size:10px">SL</span></label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_sl_ro" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_TAKE_PROFIT_PCT">익절%<span class="d-block text-muted fw-normal" style="font-size:10px">TP</span></label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_tp_ro" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_TP_MAX_PCT">익절상한%<span class="d-block text-muted fw-normal" style="font-size:10px">TP_MAX</span></label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_tp_max_ro" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-auto">
|
||
<div class="form-check mt-3">
|
||
<input class="form-check-input" type="checkbox" id="bt_ob_ro_on" disabled>
|
||
<label class="form-check-label" for="bt_ob_ro_on" style="font-size:12px">호가필터</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_ORDERBOOK_MAX_SPREAD_PCT">스프레드%<span class="d-block text-muted fw-normal" style="font-size:10px">MAX_SPREAD</span></label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_ob_ro_spread" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_ORDERBOOK_MIN_BID_ASK_RATIO">잔량비≥<span class="d-block text-muted fw-normal" style="font-size:10px">MIN_RATIO</span></label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_ob_ro_ratio" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_ORDERBOOK_ENTRY_ASK_MAX_MULT">ask×≤<span class="d-block text-muted fw-normal" style="font-size:10px">ASK_MAX</span></label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_ob_ro_ask" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-auto">
|
||
<div class="form-check mt-3">
|
||
<input class="form-check-input" type="checkbox" id="bt_whip_ro_on" disabled>
|
||
<label class="form-check-label" for="bt_whip_ro_on" style="font-size:12px">휩쏘</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_WHIPSAW_SUBBAR_SEC">sub초</label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_whip_ro_sub" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_WHIPSAW_LOOKBACK_SEC">lb초</label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_whip_ro_lb" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="SCALP_WHIPSAW_DIP_PCT">dip</label>
|
||
<input type="number" class="form-control form-control-sm" id="bt_whip_ro_dip" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-12">
|
||
<span id="bt_ob_whip_ro_note" class="text-muted" style="font-size:10px"></span>
|
||
</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="【살 때】 녹=괜찮음 · 노랑=숫자만/기록없음 · 빨강=간격큼/살힘약함/팔대기많음. 가격간격=낮을수록 좋음, 살힘=높을수록 좋음(1≈균형).">매수호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th title="【팔 때】 녹=수급OK · 노랑=숫자만 · 빨강=수급약함/간격큼. OR=총사겠음÷총팔겠음. 매수칸과 시각이 다름.">매도호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></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 — anchor−ATR×배수">지정가×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">
|
||
<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="기본=실매 메인 WS, 구멍=키움 REST">
|
||
<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">
|
||
<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">
|
||
<input class="form-check-input" type="checkbox" id="tl_use_spill_fallback">
|
||
<label class="form-check-label" for="tl_use_spill_fallback" style="font-size:12px;color:var(--muted)"
|
||
title="TAIL_BACKTEST_USE_SPILL_FALLBACK — 기본 ON. 3사 틱 병합 시 3초 컷 지연 스필(Spill) 시뮬레이션 적용">
|
||
<b>스필 3사 폴백</b> (<code>3초컷 간택</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 후 보유최악손절합>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">
|
||
<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">
|
||
<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">
|
||
<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">
|
||
<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">
|
||
<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">
|
||
<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">
|
||
<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" title="3분 신호봉 직전대비 등락 하한(%). TPE -25~-3 · 실매 -10">봉등락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" title="3분 신호봉 직전대비 등락 상한(%). TPE -2~+10 · 실매 -0.5. 양수=반등봉 허용">봉등락MAX%</label>
|
||
<input type="number" class="form-control" id="tl_bar_chg_max" value="-1.5" min="-30" max="15" 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">
|
||
<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>
|
||
<!-- 호가·휩쏘 (DB 읽기전용) -->
|
||
<div class="row g-2 align-items-end mt-2 p-2 rounded" style="background:#161b22;border:1px solid #3d2a1a" id="tl_ob_whip_ro_box">
|
||
<div class="col-12">
|
||
<span class="text-muted" style="font-size:11px">
|
||
<b style="color:#f0a060">호가·휩쏘 (DB · 읽기전용)</b>
|
||
— Optuna「적용」후 여기로 확인. 백테는 이 DB값을 사용
|
||
</span>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">휩쏘(1=ON)</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_whipsaw_filter" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">sub초</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_whipsaw_sub" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">lb초</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_whipsaw_lb" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">dip%</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_whipsaw_dip" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">tol%</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_whipsaw_tol" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="MIN_BID_ASK_RATIO">잔량비(ratio)</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_min_bid_ask_ratio" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="ENTRY_ASK_MAX_MULT">ask×(mult)</label>
|
||
<input type="text" class="form-control form-control-sm" id="tl_h_ob_ask_max_mult" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</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 id="tl_optuna_ob_whip_banner" class="small text-info d-none mb-1"></div>
|
||
<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>(스캘핑/돌파/모멘텀과 동시 실행 불가) ·
|
||
<b>파라미터=현재 폼(+Optuna hidden 호가/휩쏘)</b> · 동기 실행=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 × (1−cut)</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="【살 때】 녹=괜찮음 · 노랑=숫자만/기록없음 · 빨강=간격큼/살힘약함/팔대기많음. 가격간격=낮을수록 좋음, 살힘=높을수록 좋음(1≈균형).">매수호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th title="【팔 때】 녹=수급OK · 노랑=숫자만 · 빨강=수급약함/간격큼. OR=총사겠음÷총팔겠음. 매수칸과 시각이 다름.">매도호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></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 & 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&H 수익률</div><div class="stat-val" id="db_bnh_pct">-</div></div>
|
||
<div class="col-6 col-md-3"><div class="card-title">B&H 손익(원)</div><div class="stat-val" id="db_bnh_pnl">-</div></div>
|
||
<div class="col-6 col-md-3"><div class="card-title">알파(봇−B&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">
|
||
<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">
|
||
<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 후 보유최악손절합>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="기본=실매 메인 WS, 구멍=키움 REST">
|
||
<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="【살 때】 녹=괜찮음 · 노랑=숫자만/기록없음 · 빨강=간격큼/살힘약함/팔대기많음. 가격간격=낮을수록 좋음, 살힘=높을수록 좋음(1≈균형).">매수호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th title="【팔 때】 녹=수급OK · 노랑=숫자만 · 빨강=수급약함/간격큼. OR=총사겠음÷총팔겠음. 매수칸과 시각이 다름.">매도호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></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="기본=실매 메인 WS, 구멍=키움 REST">
|
||
<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" disabled>
|
||
<label class="form-check-label" for="mom_ob_filter" id="mom_ob_filter_lbl">호가필터 (DB·읽기전용)</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">
|
||
<label class="form-check-label" for="mom_pg_filter" id="mom_pg_filter_lbl">프로그램필터</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%. DB 읽기전용(Optuna 적용값). 수정 불가">스프레드상한(%)<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" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="DB 읽기전용">잔량비≥</label>
|
||
<input type="number" class="form-control form-control-sm" id="mom_ob_ro_ratio" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="DB 읽기전용">ask×≤</label>
|
||
<input type="number" class="form-control form-control-sm" id="mom_ob_ro_ask" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-auto">
|
||
<div class="form-check mt-3">
|
||
<input class="form-check-input" type="checkbox" id="mom_whip_ro_on" disabled>
|
||
<label class="form-check-label" for="mom_whip_ro_on" style="font-size:12px">휩쏘</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">sub초</label>
|
||
<input type="number" class="form-control form-control-sm" id="mom_whip_ro_sub" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">lb초</label>
|
||
<input type="number" class="form-control form-control-sm" id="mom_whip_ro_lb" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">dip</label>
|
||
<input type="number" class="form-control form-control-sm" id="mom_whip_ro_dip" readonly tabindex="-1" style="background:#0d1117;color:#f0a060">
|
||
</div>
|
||
<div class="col-12"><span id="mom_ob_whip_ro_note" class="text-muted" style="font-size:10px"></span></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">
|
||
<label class="form-check-label" for="mom_use_ema_f" style="font-size:12px">EMA추세필터 (DB)</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 후 보유최악손절합>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="【살 때】 녹=괜찮음 · 노랑=숫자만/기록없음 · 빨강=간격큼/살힘약함/팔대기많음. 가격간격=낮을수록 좋음, 살힘=높을수록 좋음(1≈균형).">매수호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th title="【팔 때】 녹=수급OK · 노랑=숫자만 · 빨강=수급약함/간격큼. OR=총사겠음÷총팔겠음. 매수칸과 시각이 다름.">매도호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></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">
|
||
<label class="form-label param-row" title="이 study 완료 목표. 비우면 이번 trials">스터디 총 횟수</label>
|
||
<input type="number" class="form-control form-control-sm" id="usmom_opt_study_trials" min="0" max="5000" placeholder="비움" 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">학습 Top10 <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">사후합격 Top10 <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="【살 때】 녹=괜찮음 · 노랑=숫자만/기록없음 · 빨강=간격큼/살힘약함/팔대기많음. 가격간격=낮을수록 좋음, 살힘=높을수록 좋음(1≈균형).">매수호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></th><th title="【팔 때】 녹=수급OK · 노랑=숫자만 · 빨강=수급약함/간격큼. OR=총사겠음÷총팔겠음. 매수칸과 시각이 다름.">매도호가<br><span style="font-size:9px;font-weight:400;opacity:.7">녹OK · 노랑참고 · 빨강나쁨</span></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 & 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&H 수익률(전체)</div><div class="stat-val" id="hd_bnh_pct">-</div></div>
|
||
<div class="col-6 col-md-3"><div class="card-title">B&H 손익(전체·원)</div><div class="stat-val" id="hd_bnh_pnl">-</div></div>
|
||
<div class="col-6 col-md-3"><div class="card-title">알파(봇 − 전체 B&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&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&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&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&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 flex-wrap gap-2">
|
||
<h6 class="mb-0">📡 영구구독 관리 <small class="text-muted">(KR=LS WS · US=해외 WS · 저장봉=1분→롤업)</small></h6>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<div class="form-check form-switch mb-0">
|
||
<input class="form-check-input" type="checkbox" id="perm_master_en" checked onchange="permSaveMaster()">
|
||
<label class="form-check-label" for="perm_master_en">구독 마스터</label>
|
||
</div>
|
||
<button class="btn btn-sm btn-outline-primary" type="button" onclick="permFillCandles('')">KR 확정봉 가져오기</button>
|
||
<button class="btn btn-sm btn-outline-secondary" type="button" onclick="permLoad()">새로고침</button>
|
||
</div>
|
||
</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>저장봉</th><th>WS키</th><th>ON</th><th>메모</th><th></th>
|
||
</tr></thead>
|
||
<tbody id="perm_tbody"><tr><td colspan="10" class="text-muted">로딩…</td></tr></tbody>
|
||
</table>
|
||
</div>
|
||
<small class="text-muted">저장봉은 전부 <b>1분</b>(상위 15/60분은 롤업). TF 입력 없음. KR 현재가=<b>ls_ws_candles</b>. US 현재가=<b>해외 WS→ws_candles</b>(OVERSEAS_WS 필요). 「확정봉 가져오기」=키움 ka10080 → <b>ls_ws_candles 구멍만</b>. 목표가=도달 시 MM alias <code>permanent</code>. 발화 후 「재무장」. 탭 열면 자동 새로고침.</small>
|
||
</div>
|
||
|
||
</div><!-- tab-updow end -->
|
||
|
||
<!-- ═══ 전략별 env 변경 이력 ═══════════════════════════════════════════ -->
|
||
<div id="tab-envhist" style="display:none">
|
||
<div class="card p-3 mb-3">
|
||
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-2">
|
||
<h6 class="mb-0">🧾 전략별 env 변경내역 <small class="text-muted">(최근 3스냅샷 · 직전값과 다르면 빨강)</small></h6>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<div class="form-check mb-0">
|
||
<input class="form-check-input" type="checkbox" id="envhist_changed_only" checked onchange="envHistRender()">
|
||
<label class="form-check-label" for="envhist_changed_only">변경키만</label>
|
||
</div>
|
||
<button class="btn btn-sm btn-outline-secondary" type="button" onclick="envHistLoad()">새로고침</button>
|
||
</div>
|
||
</div>
|
||
<p class="small text-muted mb-2">임계값이 많아 기본은 <b>바뀐 키만</b> 보입니다. 체크 해제 시 해당 전략 스냅샷에 있는 키 전부(시크릿 제외). 열=오래된→최신.</p>
|
||
<div id="envhist_root"><div class="text-muted">로딩…</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══ 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">최근 잡 <small class="text-muted fw-normal">(최대 40 · 순차 스터디가 잘리지 않게)</small></h6>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<button class="btn btn-sm btn-outline-info" onclick="compareSelectedJobs()">선택 비교</button>
|
||
<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 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"> 모멘텀</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>
|
||
<span class="d-inline-flex flex-wrap align-items-center gap-1 px-2 py-1" style="border:1px solid var(--border);border-radius:6px" title="꼬리=전략. align/limit_atr는 진입모드(한 스터디에 섞지 않음). 둘 다 켜면 순차 2회. 둘 다 끄면 꼬리 미실행.">
|
||
<span class="text-muted" style="font-size:12px">꼬리 진입</span>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input opt-tail-em" type="checkbox" id="opt_tail_em_align" value="align"> align
|
||
<small class="text-muted">다음봉시가</small>
|
||
</label>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input opt-tail-em" type="checkbox" id="opt_tail_em_limit" value="limit_atr"> limit_atr
|
||
<small class="text-muted">지정가</small>
|
||
</label>
|
||
</span>
|
||
<span class="d-inline-flex flex-wrap align-items-center gap-1 px-2 py-1" style="border:1px solid var(--border);border-radius:6px" title="돌파=전략. fixed/atr는 손절모드(한 스터디에 섞지 않음). 둘 다 켜면 순차 2회. 둘 다 끄면 돌파 미실행.">
|
||
<span class="text-muted" style="font-size:12px">돌파 손절</span>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input opt-bo-sl" type="checkbox" id="opt_bo_sl_fixed" value="fixed"> fixed
|
||
<small class="text-muted">고정%</small>
|
||
</label>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input opt-bo-sl" type="checkbox" id="opt_bo_sl_atr" value="atr"> atr
|
||
<small class="text-muted">ATR배수</small>
|
||
</label>
|
||
</span>
|
||
<span class="d-inline-flex flex-wrap align-items-center gap-1 px-2 py-1" style="border:1px solid var(--border);border-radius:6px" title="돌파 호가=스터디 스위치(trial 축 아님). off/on 각각 별도 스터디. 손절×호가 최대 4순차.">
|
||
<span class="text-muted" style="font-size:12px">돌파 호가</span>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input opt-bo-ob" type="checkbox" id="opt_bo_ob_off" value="off"> off
|
||
<small class="text-muted">필터OFF</small>
|
||
</label>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input opt-bo-ob" type="checkbox" id="opt_bo_ob_on" value="on"> on
|
||
<small class="text-muted">필터ON</small>
|
||
</label>
|
||
</span>
|
||
<label class="form-check form-check-inline mb-0"><input class="form-check-input opt-strat-cb" type="checkbox" value="scalp"> 스캘핑</label>
|
||
<span class="d-inline-flex flex-wrap align-items-center gap-1 px-2 py-1" style="border:1px solid var(--border);border-radius:6px" title="TAIL_BACKTEST_USE_SPILL_FALLBACK: 백테 틱 3사(KIS,키움,LS) 3초 컷 지연 스필 시뮬레이션">
|
||
<span class="text-muted" style="font-size:12px">스필(Spill) 3사 폴백</span>
|
||
<label class="form-check form-check-inline mb-0">
|
||
<input class="form-check-input" type="checkbox" id="opt_use_spill_fallback"> 3초 간택 (ON/OFF)
|
||
</label>
|
||
</span>
|
||
<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" title="이 study 완료 목표. 비우면 이번 trials 와 같음. 미달이면 후처리 안 함">스터디 총 횟수</label>
|
||
<input type="number" id="opt_study_trials" class="form-control form-control-sm" style="width:90px" min="0" max="5000" placeholder="비움=이번">
|
||
</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="Optuna가 1등으로 올리는 기준">승리식</label>
|
||
<select class="form-select form-select-sm" id="opt_sort_by" style="width:170px">
|
||
<option value="score" selected>수익·낙폭·표본</option>
|
||
<option value="score_legacy">(구) PnL/MDD하한</option>
|
||
<option value="daily_avg">일평균</option>
|
||
<option value="pnl">총손익</option>
|
||
</select>
|
||
</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="기본=실매 메인 WS, 구멍=키움 REST">
|
||
<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">전략 1개만=1·2차 연쇄 · 2개 이상·꼬리2모드·돌파多=순차(조합마다 1·2차) · 승리식=수익·낙폭·표본 · min_trades: 꼬리=1 · 그 외=거래일×2 · WR/PF=0 · DB 미적용</small>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3" id="opt_status_card">
|
||
<h6>진행</h6>
|
||
<div id="opt_period_banner" class="opt-period-banner d-none mb-2 p-2 rounded small"></div>
|
||
<div class="small text-muted mb-1">학습 trial</div>
|
||
<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="small text-muted mb-1">후처리 (호가·휩쏘 · 끝나면 「상세」)</div>
|
||
<div class="optuna-prog-track mb-2" style="height:10px">
|
||
<div class="optuna-prog-fill is-post" id="opt_post_fill" style="width:0%"></div>
|
||
</div>
|
||
<div id="opt_st_post" class="small text-muted mb-2">후처리 — trial 끝난 뒤 시작</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" style="cursor:pointer" title="클릭하면 다른 PC 실행 명령">—</b>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary py-0 ms-1" onclick="optunaOpenJoinCmd()">명령</button>
|
||
</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 id="opt_st_refine_wrap" class="d-none"><span class="text-muted">1·2차</span> <span id="opt_st_refine" class="small" style="font-size:11px">—</span></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>
|
||
<span id="opt_overfit_badge_gated" class="small ms-1" title="과적합%=이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정). AI 아님.">—</span>
|
||
<button class="btn btn-sm btn-outline-info" id="opt_btn_apply_stable" onclick="optunaApply('stable',1)">
|
||
🛡️ 안정 1위 DB 적용
|
||
</button>
|
||
<span id="opt_overfit_badge_stable" class="small ms-1" title="과적합%=이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정). AI 아님.">—</span>
|
||
<button class="btn btn-sm btn-outline-success" id="opt_btn_apply_mode" onclick="optunaApply('mode',1)">
|
||
mode_combo DB 적용
|
||
</button>
|
||
<span id="opt_overfit_badge_mode" class="small ms-1" title="과적합%=이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정). AI 아님.">—</span>
|
||
<small class="text-muted ms-2">완료 후에만 · TIME_* 미변경 · 위 버튼=타점만 · 트레일/호가는 아래 표 · confirm 필수 · mode_combo=TopN 최빈값 조합(표에서 뺌)</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3" id="opt_gated_top3_card">
|
||
<h6 id="opt_gated_top3_title">사후합격 Top5 <small class="text-muted">DB 적용 후보 · 일평균(원/%) · 익절/손절 비교</small></h6>
|
||
<div id="opt_gated_top3_body" class="small text-muted">완료 후 표시</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3" id="opt_param_dist_card">
|
||
<h6>사후합격 pool 파라미터 분포 <small class="text-muted">분포 참고용 · DB 적용 1순위 아님</small></h6>
|
||
<div id="opt_param_dist_legend" class="small mb-2 p-2 rounded" style="background:rgba(56,139,253,0.06);border:1px solid var(--border);font-size:11px;line-height:1.6">
|
||
<div class="fw-semibold mb-1">범례 (막대 1줄 = 파라미터 1개)</div>
|
||
<div class="d-flex flex-wrap gap-3 align-items-center">
|
||
<span><span style="display:inline-block;width:28px;height:10px;background:rgba(56,139,253,0.45);border-radius:2px;vertical-align:middle"></span>
|
||
<b class="ms-1">파란 띠</b> = p25~p75 · 사후합격 후보들의 <b>중간 50% 구간</b> (너무 극단값 제외한 흔한 범위)</span>
|
||
<span><span style="display:inline-block;width:2px;height:12px;background:#3fb950;vertical-align:middle"></span>
|
||
<b class="ms-1">녹색 세로줄</b> = median · <b>중앙값</b> (위·아래 절반이 이 값 기준)</span>
|
||
<span><span style="display:inline-block;width:8px;height:8px;background:#f0883e;border-radius:50%;vertical-align:middle"></span>
|
||
<b class="ms-1">주황 동그라미</b> = mode · <b>최빈값</b> (후보 중 가장 많이 나온 숫자 · 괄호 %는 비율)</span>
|
||
</div>
|
||
<div class="text-muted mt-1">아래 숫자(p25·med·p75)는 막대와 동일. 익절·손절이 Top5마다 다르게 보이면 이 밴드가 넓다는 뜻입니다.</div>
|
||
</div>
|
||
<div id="opt_param_dist_chart" class="small text-muted">완료 후 표시</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<div id="opt_overfit_box" class="p-2 small" style="background:rgba(248,81,73,0.06);border:1px solid var(--border);border-radius:6px">
|
||
<div class="d-flex flex-wrap justify-content-between gap-2 mb-1">
|
||
<div class="text-muted">스터디 과적합 요약 <span class="text-muted">(휴리스틱 · 교차검증 아님 · 적용은 아래 각 행 과적합% 보세요)</span></div>
|
||
<div id="opt_overfit_score" class="fw-semibold">완료 후 표시</div>
|
||
</div>
|
||
<div class="table-responsive mb-1">
|
||
<table class="table table-sm table-hover mb-0" style="font-size:12px">
|
||
<thead>
|
||
<tr>
|
||
<th>요인</th><th class="text-end">가점</th><th>설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_overfit_factors_tbody">
|
||
<tr><td colspan="3" class="text-muted">완료 후 표시</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<details class="text-muted">
|
||
<summary style="cursor:pointer">임계값 분포 (참고 · 적용 판단용 아님)</summary>
|
||
<div class="mt-1" id="opt_thresh_pool"></div>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-hover mb-0" style="font-size:12px">
|
||
<thead>
|
||
<tr>
|
||
<th>파라미터</th>
|
||
<th class="text-end">median</th>
|
||
<th class="text-end">p25</th>
|
||
<th class="text-end">p75</th>
|
||
<th>mode</th>
|
||
<th class="text-end">mode%</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_thresh_dist_tbody">
|
||
<tr><td colspan="6" class="text-muted">완료 후 표시</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</details>
|
||
<div id="opt_overfit_note" class="text-muted mt-1" style="font-size:11px">—</div>
|
||
</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_vs_best" class="d-none">—</div>
|
||
<div id="opt_compare_tbody" class="d-none"></div>
|
||
</div>
|
||
|
||
<div id="opt_tpe_ob_banner" class="small mb-2 text-muted">—</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<h6>학습 Top10 <small class="text-muted">results · Optuna 목적함수 1위 풀 · 진행바 best=여기 1위 · OPTUNA_POST_TOP_N</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 class="text-end" title="총손익 ÷ 기간 한국거래일수. 짧은/긴 구간 비교용.">일평균(원)</th>
|
||
<th class="text-end" title="총수익률(운용한도) ÷ 기간 거래일수">일평균%</th>
|
||
<th title="본 TPE: 호가ON/OFF·spr/r/ask · 익절%/상한 · 손절% · 휩쏘ON/OFF·수치 (사후8방 아님)">호가·익절·손절·휩쏘</th>
|
||
<th class="text-end">손실일</th><th class="text-end">최악일</th>
|
||
<th class="text-end" title="높을수록 좋음. 만점 없음. 일평균PnL − λ×일표준편차(원).">안정점수 ↑</th>
|
||
<th class="text-end" title="높을수록 위험. 0~100. 이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정).">과적합% ↓</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_top5_learn_tbody">
|
||
<tr><td colspan="14" class="text-muted">완료 후 표시</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<h6>사후합격 Top10 <small class="text-muted">results_gated · 「호가·익절·손절·휩쏘」열=본TPE 수치 · 사후8방은 TPE호가포함 시 비는 게 정상</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 class="text-end" title="총손익 ÷ 기간 한국거래일수. 짧은/긴 구간 비교용.">일평균(원)</th>
|
||
<th class="text-end" title="총수익률(운용한도) ÷ 기간 거래일수">일평균%</th>
|
||
<th title="본 TPE: 호가ON/OFF·spr/r/ask · 익절%/상한 · 손절% · 휩쏘ON/OFF·수치 (사후8방 아님)">호가·익절·손절·휩쏘</th>
|
||
<th class="text-end">손실일</th><th class="text-end">최악일</th>
|
||
<th class="text-end" title="높을수록 좋음. 만점 없음. 일평균PnL − λ×일표준편차(원).">안정점수 ↑</th>
|
||
<th class="text-end" title="높을수록 위험. 0~100. 이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정).">과적합% ↓</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_top5_tbody">
|
||
<tr><td colspan="14" class="text-muted">완료 후 표시</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<h6>mode_combo <small class="text-muted">축별 최빈 조립 · PnL 양수 pool · trial 번호 없음 · 2차 완료 후 표시</small></h6>
|
||
<div id="opt_mode_combo_body" class="small mb-2">완료 후 표시</div>
|
||
<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 class="text-end" title="총손익 ÷ 기간 한국거래일수. 짧은/긴 구간 비교용.">일평균(원)</th>
|
||
<th class="text-end" title="총수익률(운용한도) ÷ 기간 거래일수">일평균%</th>
|
||
<th title="본 TPE: 호가ON/OFF·spr/r/ask · 익절%/상한 · 손절% · 휩쏘ON/OFF·수치 (사후8방 아님)">호가·익절·손절·휩쏘</th>
|
||
<th class="text-end">손실일</th><th class="text-end">최악일</th>
|
||
<th class="text-end" title="높을수록 좋음. 만점 없음. 일평균PnL − λ×일표준편차(원).">안정점수 ↑</th>
|
||
<th class="text-end" title="높을수록 위험. 0~100. 이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정).">과적합% ↓</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_top5_mode_tbody">
|
||
<tr><td colspan="14" class="text-muted">완료 후 표시 (mode 실측 1행 · 사후합격과 같은 열)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<h6>mode Top10 <small class="text-muted">results_mode · PnL 양수 pool p25~p75 밴드 <b>근접도</b> ↑ · trial 있음 · <b>적용 1순위 아님</b></small></h6>
|
||
<div id="opt_mode_band_top3" class="small mb-2 text-muted">—</div>
|
||
<div id="opt_mode_top_meta" class="small text-muted mb-1">—</div>
|
||
<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" title="Top-N pool 축별 p25~p75 밴드 안/근접 — 100에 가까울수록 흔한 구간">근접% ↑</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" title="총손익 ÷ 기간 한국거래일수">일평균(원)</th>
|
||
<th class="text-end" title="총수익률(운용한도) ÷ 기간 거래일수">일평균%</th>
|
||
<th title="본 TPE trial 호가·익절·손절·휩쏘">호가·익절·손절·휩쏘</th>
|
||
<th class="text-end">손실일</th><th class="text-end">최악일</th>
|
||
<th class="text-end" title="일평균PnL − λ×일표준편차">안정점수 ↑</th>
|
||
<th class="text-end" title="과적합 추정 0~100">과적합% ↓</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_top5_mode_top_tbody">
|
||
<tr><td colspan="15" class="text-muted">완료 후 표시 (mode Top10 · 구 JSON은 웹에서 즉시 재계산)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card p-3 mb-3">
|
||
<h6>안정 Top10 <small class="text-muted">results_stable · gated/플러스와 독립 · 게이트0이면 안정점수순 폴백</small></h6>
|
||
<div id="opt_stable_gates" class="small text-muted mb-1">—</div>
|
||
<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 class="text-end" title="총손익 ÷ 기간 한국거래일수. 짧은/긴 구간 비교용.">일평균(원)</th>
|
||
<th class="text-end" title="총수익률(운용한도) ÷ 기간 거래일수">일평균%</th>
|
||
<th title="본 TPE: 호가ON/OFF·spr/r/ask · 익절%/상한 · 손절% · 휩쏘ON/OFF·수치 (사후8방 아님)">호가·익절·손절·휩쏘</th>
|
||
<th class="text-end">손실일</th><th class="text-end">최악일</th>
|
||
<th class="text-end" title="높을수록 좋음. 만점 없음. 일평균PnL − λ×일표준편차(원).">안정점수 ↑</th>
|
||
<th class="text-end" title="높을수록 위험. 0~100. 이 숫자만 믿으면 내일 틀릴 수 있는 정도(추정).">과적합% ↓</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="opt_top5_stable_tbody">
|
||
<tr><td colspan="14" 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><!-- tab-optuna end -->
|
||
|
||
</div><!-- container end -->
|
||
|
||
<div id="opt_join_overlay" class="opt-join-overlay" onclick="if(event.target===this)optunaCloseJoinCmd()">
|
||
<div class="opt-join-panel" role="dialog" aria-labelledby="opt_join_title">
|
||
<div class="d-flex justify-content-between align-items-center gap-2 mb-2">
|
||
<h6 class="mb-0" id="opt_join_title">다른 PC 병렬 · study 이어 붙이기</h6>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary py-0" onclick="optunaCloseJoinCmd()">닫기</button>
|
||
</div>
|
||
<p id="opt_join_hint" class="small text-muted mb-2" style="white-space:pre-wrap"></p>
|
||
<div id="opt_join_refine" class="mb-3"></div>
|
||
<div class="small text-muted">지금 study (trial 추가용)</div>
|
||
<code id="opt_join_study" style="font-size:11px">—</code>
|
||
<div class="d-flex justify-content-between align-items-center mt-2 mb-1">
|
||
<span class="small text-muted">Linux / VM (bash) — 같은 study trial 추가</span>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary py-0" onclick="optunaCopyJoin('join')">복사</button>
|
||
</div>
|
||
<pre id="opt_join_cmd" class="opt-join-pre mb-2">—</pre>
|
||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||
<span class="small text-muted">Windows PowerShell — trial 추가</span>
|
||
<button type="button" class="btn btn-sm btn-primary py-0" onclick="optunaCopyJoin('ps')">복사</button>
|
||
</div>
|
||
<pre id="opt_join_cmd_ps" class="opt-join-pre mb-2">—</pre>
|
||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||
<span class="small text-muted">순차 전체 (env 포함 bash · 이 VM과 동일)</span>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary py-0" onclick="optunaCopyJoin('web_full')">복사</button>
|
||
</div>
|
||
<pre id="opt_web_cmd_full" class="opt-join-pre mb-2">—</pre>
|
||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||
<span class="small text-muted">웹 실행 요약 (참고)</span>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary py-0" onclick="optunaCopyJoin('web')">복사</button>
|
||
</div>
|
||
<pre id="opt_web_cmd" class="opt-join-pre mb-2">—</pre>
|
||
<div id="opt_join_all" class="small"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 선택 비교 모달 -->
|
||
<div class="modal fade" id="optCmpModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
|
||
<div class="modal-content bg-dark text-light" style="border:1px solid #444;">
|
||
<div class="modal-header border-bottom border-secondary py-2">
|
||
<h5 class="modal-title fs-6">🏆 선택 항목 Top 10 비교</h5>
|
||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body p-2" style="background:#1e1e1e;">
|
||
<div id="optCmpLoading" class="text-center py-4 d-none">
|
||
<div class="spinner-border text-info" role="status"></div>
|
||
<div class="mt-2 text-muted" style="font-size:12px;">상세 데이터를 불러오는 중...</div>
|
||
</div>
|
||
<div class="table-responsive" id="optCmpTableWrap">
|
||
<!-- 비교 테이블 렌더링 영역 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 🐛 DB 디버거 플로팅 패널 -->
|
||
<div id="btDbDebuggerBtn" onclick="toggleDbDebugger()" style="position:fixed; right:20px; top:70px; z-index:9999; background:var(--accent, #58a6ff); color:#fff; border-radius:50%; width:44px; height:44px; display:flex; align-items:center; justify-content:center; cursor:pointer; box-shadow:0 4px 12px rgba(0,0,0,0.5); transition:transform 0.2s;">
|
||
<span style="font-size:20px;" title="DB 디버거 열기">🕵️</span>
|
||
</div>
|
||
|
||
<div id="btDbDebuggerPanel" style="display:none; position:fixed; right:20px; top:120px; width:360px; max-height:calc(100vh - 140px); background:#1e1e1e; border:1px solid #444; border-radius:8px; z-index:9998; box-shadow:0 8px 24px rgba(0,0,0,0.7); display:flex; flex-direction:column; overflow:hidden;">
|
||
<div style="background:#2a2a2a; padding:10px 15px; border-bottom:1px solid #444; display:flex; justify-content:space-between; align-items:center;">
|
||
<h6 style="margin:0; font-size:14px; color:#c9d1d9;">🕵️ DB 파라미터 대조 <span id="btDbDebugStrategy" style="color:var(--accent, #58a6ff); font-weight:bold; margin-left:8px;"></span></h6>
|
||
<div>
|
||
<button class="btn btn-sm btn-outline-info py-0 px-2" style="font-size:11px;" onclick="refreshDbDebugger()">새로고침</button>
|
||
<button class="btn btn-sm btn-outline-secondary py-0 px-2 ms-1" style="font-size:11px;" onclick="toggleDbDebugger()">닫기</button>
|
||
</div>
|
||
</div>
|
||
<div style="padding:10px; flex:1; overflow-y:auto;">
|
||
<p style="font-size:11px; color:#8b949e; margin-bottom:8px;">
|
||
현재 DB값과 폼 값이 다르면 <strong>붉은색</strong>으로 표시됩니다.
|
||
</p>
|
||
<div id="btDbDebuggerList" style="display:flex; flex-direction:column; gap:8px;">
|
||
<div class="text-center text-muted py-3" style="font-size:11px;">새로고침을 눌러 데이터를 불러오세요.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="{{ url_for('static', filename='js/backtest.js') }}?v=20260901opt_bg_pctfix"></script>
|
||
</body>
|
||
</html> |