Changes: - Introduced new files for strategy definitions and study names. - Enhanced `backtest_web.py` with functions to handle integer display prices and trade data formatting. - Updated backtesting logic to incorporate end-of-day (EOD) parameters for breakout and momentum strategies. - Added EOD configuration options in the database and parameter search files. Impact: - These changes improve the modularity and usability of the backtesting framework, allowing for better integration of EOD strategies and clearer trade data presentation.
2724 lines
179 KiB
HTML
2724 lines
179 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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='css/backtest.css') }}">
|
||
</head>
|
||
<body>
|
||
|
||
<!-- 로딩 오버레이 -->
|
||
<div class="spin-overlay" id="spinner">
|
||
<div class="spinner"></div>
|
||
</div>
|
||
|
||
<nav class="navbar px-4 py-3" style="background:var(--surface); border-bottom:1px solid var(--border)">
|
||
<span class="navbar-brand">📈 KIS Quant Dashboard</span>
|
||
<span class="text-muted" id="lastRefresh" style="font-size:12px"></span>
|
||
</nav>
|
||
|
||
<div class="container-fluid px-4 py-3">
|
||
|
||
<!-- 탭 -->
|
||
<ul class="nav nav-tabs mb-4" id="mainTab">
|
||
<li class="nav-item"><a class="nav-link active" data-tab="actual" href="#">📊 실거래 분석</a></li>
|
||
<li class="nav-item"><a class="nav-link" data-tab="dashboard" href="#">📈 오늘 운영</a></li>
|
||
<li class="nav-item"><a class="nav-link" data-tab="liveconfig" href="#">⚙️ 운영 설정</a></li>
|
||
<li class="nav-item"><a class="nav-link" data-tab="portfolio" href="#">💼 보유·매도</a></li>
|
||
<!-- 숨김 전략(SCALP·DBBAND·RANGE_BREAK) 탭 — 사용자 지정으로 미노출 (HIDDEN_STRATEGY_IDS) -->
|
||
<li class="nav-item" style="display:none"><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="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>
|
||
</ul>
|
||
|
||
<!-- ═══ 오늘 운영 (전략별·합계) ═══════════════════════════════════════════ -->
|
||
<div id="tab-dashboard" style="display:none">
|
||
<div class="card p-3 mb-3">
|
||
<div class="row g-3 align-items-end">
|
||
<div class="col-auto">
|
||
<label class="form-label param-row" style="color:var(--muted);font-size:12px">기준일 (KST)</label>
|
||
<input type="date" id="dash_date" class="form-control form-control-sm" style="width:160px">
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-sm btn-primary" onclick="loadDashboard()">새로고침</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-sm btn-outline-secondary" onclick="dashGoActual()">전략별 상세 → 실거래 분석</button>
|
||
</div>
|
||
<div class="col">
|
||
<small id="dash_meta" class="text-muted"></small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row g-3 mb-3" id="dash_cards">
|
||
<div class="col-md-3">
|
||
<div class="card p-3 stat-card">
|
||
<div class="stat-label">당일 거래대금 (합)</div>
|
||
<div class="stat-value" id="dash_card_turnover">—</div>
|
||
<small class="text-muted" id="dash_card_turnover_sub"></small>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="card p-3 stat-card">
|
||
<div class="stat-label">당일 뽀찌 피크 (ON 전략 합)</div>
|
||
<div class="stat-value" id="dash_card_budget">—</div>
|
||
<small class="text-muted" id="dash_card_budget_sub"></small>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="card p-3 stat-card">
|
||
<div class="stat-label">당일 실현손익 (합)</div>
|
||
<div class="stat-value" id="dash_card_pnl">—</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="card p-3 stat-card">
|
||
<div class="stat-label">총수익률 (실현÷운용한도)</div>
|
||
<div class="stat-value" id="dash_card_ret">—</div>
|
||
<small class="text-muted">백테 bot_pct와 동일 분모</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card p-3">
|
||
<h6 class="mb-3">전략별 당일 운영</h6>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-hover mb-0" 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>합계 (ON 한도 기준)</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>
|
||
</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="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">
|
||
<input type="radio" name="act_strategy" value="UPDOW"> 하락매수 (UPDOW)
|
||
</label>
|
||
<label class="d-flex align-items-center gap-1 mb-0">
|
||
<input type="radio" name="act_strategy" value="BREAKOUT"> 돌파 (BREAKOUT)
|
||
</label>
|
||
<label class="d-flex align-items-center gap-1 mb-0" title="holding_bot.py 장기 홀딩">
|
||
<input type="radio" name="act_strategy" value="HOLDING"> 홀딩 (HOLDING)
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">시작일</label>
|
||
<input type="date" class="form-control" id="act_start" style="width:150px">
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">종료일</label>
|
||
<input type="date" class="form-control" id="act_end" style="width:150px">
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-primary" onclick="loadActual()">🔍 조회</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 요약 카드 -->
|
||
<div class="row g-3 mb-3" id="act_summary_row">
|
||
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
|
||
<div class="card-title">총 거래</div><div class="stat-val" id="a_total">-</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
|
||
<div class="card-title">승률</div><div class="stat-val" id="a_winrate">-</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
|
||
<div class="card-title">순손익</div><div class="stat-val" id="a_pnl">-</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
|
||
<div class="card-title">Profit Factor</div><div class="stat-val" id="a_pf">-</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
|
||
<div class="card-title">최대 낙폭(MDD)</div><div class="stat-val red" id="a_mdd">-</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3 col-lg-2"><div class="card p-3">
|
||
<div class="card-title">평균 보유(분)</div><div class="stat-val" id="a_hold">-</div>
|
||
</div></div>
|
||
</div>
|
||
<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="pnl_desc">손익↑</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="pnl_asc">손익↓</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_desc">수익률↑</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary trade-sort-btn" data-sort="rate_asc">수익률↓</button>
|
||
</div>
|
||
<div class="card p-3">
|
||
<div class="table-responsive">
|
||
<table class="table table-hover" id="act_table">
|
||
<thead><tr>
|
||
<th>종목</th><th>매수시각</th><th>매도시각</th>
|
||
<th>매수가</th><th>매도가</th><th>수량</th>
|
||
<th>손익(원)</th><th>수익률%</th><th>누적손익</th><th>누적%</th>
|
||
<th>보유(분)</th><th>체결디버그</th><th>매도사유</th>
|
||
</tr></thead>
|
||
<tbody id="act_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══ 운영 설정 (실매 env 실시간 조회·저장) ═════════════════════════════ -->
|
||
<div id="tab-liveconfig" style="display:none">
|
||
<div class="card p-3 mb-3">
|
||
<div class="row g-3 align-items-end">
|
||
<div class="col-auto">
|
||
<label class="form-label param-row" style="color:var(--muted);font-size:12px">기준일 (손익·익절 상태)</label>
|
||
<input type="date" id="lc_date" class="form-control form-control-sm" style="width:160px">
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-sm btn-primary" onclick="lcLoad()">🔄 새로고침</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-sm btn-success" onclick="lcSaveAll()">💾 전체 저장</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="d-flex align-items-center gap-2 mb-0" style="font-size:12px;color:var(--muted)">
|
||
<input type="checkbox" id="lc_auto_refresh" checked> 30초 자동 갱신
|
||
</label>
|
||
</div>
|
||
<div class="col">
|
||
<small id="lc_meta" class="text-muted"></small>
|
||
</div>
|
||
</div>
|
||
<div style="font-size:12px;color:var(--muted);line-height:1.6;margin-top:8px">
|
||
DB <code>insert_env_snapshot</code> 즉시 저장 → <b>봇 재시작 없이</b> 다음 루프부터 반영.
|
||
마스터 키는 <b>env_config</b>, 전략 키는 <b>config_{전략}</b> 테이블로 자동 분리됩니다.
|
||
</div>
|
||
</div>
|
||
<div id="lc_status_cards" class="row g-3 mb-3"></div>
|
||
<div id="lc_groups"></div>
|
||
<div id="lc_save_result" class="mt-2" style="font-size:13px"></div>
|
||
</div>
|
||
|
||
<!-- ═══ 보유·매도 (DB 동기화) ═══════════════════════════════════════════ -->
|
||
<div id="tab-portfolio" style="display:none">
|
||
<div class="card p-3 mb-3">
|
||
<div style="font-size:12px;color:var(--muted);line-height:1.6">
|
||
<b>실거래 분석</b> = 오늘 <b>매도 완료</b> 내역(trade_history). <b>보유·매도</b> = 지금 <b>잔고</b>(HTS 실시간잔고와 동일).
|
||
<b>실계좌 대조</b>를 눌러야 삼성전자·삼화전자 등 전 종목이 보입니다. DB에 없는 종목은 <span class="badge-loss">미등록</span> — 봇 매도 버튼 없음(HTS 매도 또는 추후 동기화).
|
||
</div>
|
||
<div class="row g-3 align-items-end mt-2">
|
||
<div class="col-12">
|
||
<label class="form-label param-row" style="color:var(--muted);font-size:12px">전략 (실거래 분석 탭과 동일 ID)</label>
|
||
<div class="d-flex flex-wrap gap-2 gap-md-3 mt-1 align-items-center">
|
||
<label class="d-flex align-items-center gap-1 mb-0">
|
||
<input type="radio" name="pf_strategy" value="ALL" checked> 전체
|
||
</label>
|
||
<label class="d-flex align-items-center gap-1 mb-0">
|
||
<input type="radio" name="pf_strategy" value="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">
|
||
<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)에서만 조회.
|
||
</div>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-primary" onclick="pfLoad(false)">🔄 새로고침</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-outline-secondary" onclick="pfLoad(true)" title="한투 잔고 API 1회 (수 초)">📡 실계좌 대조</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-outline-success" onclick="pfReconcileOrphans()" title="봇이 매수했지만 active_trades 에 누락된 종목을 DB에 복구(매도 아님). 수동매수·보호종목 제외.">🧩 봇고아 DB복구</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button class="btn btn-outline-danger" onclick="pfSellUntrackedAll()" title="active_trades 에 없는(전략 비어있는) 실계좌 보유분만 시장가 일괄매도. 봇 관리분은 건드리지 않음.">🧹 미등록 전량 매도</button>
|
||
</div>
|
||
<div class="col-auto">
|
||
<span class="text-muted" id="pf_meta" style="font-size:12px"></span>
|
||
</div>
|
||
</div>
|
||
<!-- 실계좌 대조 시 계좌 요약 (입금·예수금·평가) -->
|
||
<div class="row g-2 mt-2" id="pf_account_row" style="display:none">
|
||
<div class="col-6 col-md-3"><div class="card p-2" style="background:rgba(88,166,255,0.06);border-color:var(--accent)">
|
||
<div class="card-title" style="font-size:11px">총 입금액</div>
|
||
<div class="stat-val" id="pf_total_deposit" style="font-size:16px">—</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3"><div class="card p-2">
|
||
<div class="card-title" style="font-size:11px">예수금</div>
|
||
<div class="stat-val" id="pf_cash" style="font-size:16px">—</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3"><div class="card p-2">
|
||
<div class="card-title" style="font-size:11px">주식 평가금</div>
|
||
<div class="stat-val" id="pf_holdings_eval" style="font-size:16px">—</div>
|
||
</div></div>
|
||
<div class="col-6 col-md-3"><div class="card p-2">
|
||
<div class="card-title" style="font-size:11px">총자산(예수금+평가)</div>
|
||
<div class="stat-val" id="pf_total_asset" style="font-size:16px">—</div>
|
||
</div></div>
|
||
</div>
|
||
<div class="mt-2" style="font-size:11px;color:var(--muted);line-height:1.5">
|
||
<b>동기 배지:</b>
|
||
<span class="badge-win">OK</span> DB·실계좌 수량 일치 ·
|
||
<span class="badge-loss">주의</span> 수량 불일치(HTS에서 수동 매매했을 수 있음) ·
|
||
<span class="badge-loss">봇고아</span> 봇 매수 기록은 있는데 active_trades 없음 →
|
||
<b>🧩 봇고아 DB복구</b> ·
|
||
<span class="badge-win">홀딩봇</span> HOLDING 관리 종목(여기서 매도 안 함)
|
||
</div>
|
||
</div>
|
||
<div class="trade-sort-bar mb-2" id="pf_sort_bar">
|
||
<span class="trade-sort-label">정렬</span>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn active" data-sort="pnl_desc">수익률↑</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="pnl_asc">수익률↓</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="eval_desc">평가금↑</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="eval_asc">평가금↓</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="name_asc">종목명</button>
|
||
<button type="button" class="btn btn-sm btn-outline-secondary pf-sort-btn" data-sort="untracked_first">미등록먼저</button>
|
||
</div>
|
||
<div class="card p-3">
|
||
<div class="table-responsive">
|
||
<table class="table table-hover" id="pf_table">
|
||
<thead><tr>
|
||
<th>전략</th><th>종목</th><th>매수시각</th><th>DB수량</th><th>실계좌</th><th>동기</th>
|
||
<th>DB매수가</th><th>실평단</th><th>현재가</th><th>수익률</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">
|
||
<div class="row g-2 align-items-end mb-1">
|
||
<div class="col-12" style="font-size:12px;color:var(--muted)">
|
||
📉 <b>반전(Reversal)</b> 전용 — 모멘텀 추격은 <b>🌊 모멘텀 백테스트</b> 탭을 사용하세요.
|
||
</div>
|
||
</div>
|
||
<div class="row g-2 align-items-end">
|
||
<!-- 기간 -->
|
||
<div class="col-6 col-md-2">
|
||
<label class="form-label param-row">시작일</label>
|
||
<input type="date" class="form-control" id="bt_start">
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<label class="form-label param-row">종료일</label>
|
||
<input type="date" class="form-control" id="bt_end">
|
||
</div>
|
||
<div class="col-12 mt-1">
|
||
<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> (<code>target_candidates_history</code>)
|
||
<span id="bt_univ_hint">— 체크: 저장 이력 / 해제: 반전 시뮬 유니버스</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<!-- 기본 파라미터 -->
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">RSI 기간</label>
|
||
<input type="number" class="form-control" id="bt_rsi_period" value="3" min="2" max="14">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">RSI 과매도</label>
|
||
<input type="number" class="form-control" id="bt_rsi_oversold" value="18" min="10" max="45" step="1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="이 값 초과 시 고점추격으로 진입 금지">RSI 과열</label>
|
||
<input type="number" class="form-control" id="bt_rsi_overbought" value="75" min="50" max="100" step="1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">손절(%)</label>
|
||
<input type="number" class="form-control" id="bt_sl" value="1.5" min="0.3" max="5" step="0.1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">익절(%)</label>
|
||
<input type="number" class="form-control" id="bt_tp" value="1.5" min="0.3" max="5" step="0.1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="익절 % 상한 — tp_pct가 이보다 크면 목표가는 이 값으로 캡">익절상한%</label>
|
||
<input type="number" class="form-control" id="bt_tp_max" value="2.0" min="0.3" max="10" step="0.1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">낙폭필터(%)</label>
|
||
<input type="number" class="form-control" id="bt_drop" value="2.0" min="0.5" max="5" step="0.1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row">투자금(원)</label>
|
||
<input type="number" class="form-control" id="bt_slot" value="1000000" min="100000" step="100000">
|
||
</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="900" max="1500" step="100">
|
||
</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="100">
|
||
</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>
|
||
<!-- 방어로직 (스캘핑 전용 env — param_search/엔진과 동일) -->
|
||
<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면 진입 방어(낙폭/고점추격/급등/최소가격)를 비활성화하고, 손절/익절/장마감청산은 유지">방어로직</label>
|
||
<div class="form-check mt-1">
|
||
<input class="form-check-input" type="checkbox" id="bt_use_defense" checked>
|
||
<label class="form-check-label" for="bt_use_defense">진입 방어 ON</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-12 col-md-2">
|
||
<label class="form-label param-row" title="HTS C — MACD+Stoch [12,26,5,3,3] 골든크로스를 TRIGGER에서 검사 (HTS SCAN에서는 C 제거)">진입모드</label>
|
||
<div class="form-check mt-1">
|
||
<input class="form-check-input" type="checkbox" id="bt_use_macd">
|
||
<label class="form-check-label" for="bt_use_macd">MACD 골든크로스 ON</label>
|
||
</div>
|
||
</div>
|
||
<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">
|
||
<button class="btn btn-primary px-4" onclick="runBacktest()">🚀 백테스트 실행</button>
|
||
<button class="btn btn-success px-3" onclick="saveScalpConfig()">💾 봇에 설정저장</button>
|
||
<span class="text-muted" style="font-size:11px">탐색: CLI param_search_scalping.py</span>
|
||
</div>
|
||
</div>
|
||
<!-- 파라미터 설명 — 통합봇 (kis_trader/main.py + ScalpingStrategy + scalping_engine) 기준 -->
|
||
<!--
|
||
⚠️ 옛날 단일파일 봇(kis_scalping_ver1.py) 시절의 잔재 안내문을 통합봇 기준으로 전부 갱신.
|
||
라이브와 백테스트는 동일한 ``scalping_engine.check_buy_signal_live`` /
|
||
``check_sell_signal_live`` 를 호출하므로 모든 입력란이 라이브 봇에도 그대로 적용된다.
|
||
-->
|
||
<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)">📖 파라미터 설명 (실제 봇 <code>kis_trader/main.py</code> = ScalpingStrategy + scalping_engine 기준 — 라이브와 100% 동일 함수 호출)</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">RSI 기간</td><td>RSI 계산 캔들 수 → 라이브 봇 엔진 기본 <b>3</b> (scalping_engine ``rsi_period`` 기본 3, 백테 입력으로 그리드 가능)</td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">RSI 과매도</td><td>이 값 <b>이하</b>일 때 매수 신호 → 봇 DB: <b>SCALP_RSI_OVERSOLD</b> (기본 25)</td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">RSI 과열</td><td>이 값 <b>초과</b>면 진입 금지 (고점 추격 방지) → 봇 DB: <b>SCALP_RSI_OVERBOUGHT</b> (기본 75)</td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">손절(%)</td><td>매수가 대비 하락 시 손절 → 봇 DB: <b>SCALP_STOP_LOSS_PCT</b> (기본 1.5%)</td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">익절(%)</td><td>매수가 대비 상승 시 익절(2순위) → 봇 DB: <b>SCALP_TAKE_PROFIT_PCT</b></td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">익절상한(%)</td><td>목표가 천장 — min(익절, 상한) → DB: <b>SCALP_TP_MAX_PCT</b> (기본 2%, 0=OFF)</td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">낙폭필터(%)</td><td>당일 시가→저가 낙폭이 이 값 이상이어야 진입 → 봇 DB: <b>SCALP_MIN_DROP_RATE</b> (기본 1.5%)</td></tr>
|
||
<tr><td style="color:#58a6ff;padding:1px 6px;white-space:nowrap">투자금(원)</td><td>1회 최대 투자금 → 봇: <b>SCALP_MAX_LOSS_PER_TRADE_KRW ÷ SCALP_STOP_LOSS_PCT</b> 공식 적용 (없으면 MAX_LOSS_PER_TRADE_KRW), 상한은 <b>SCALP_MAX_BUY_AMOUNT</b>(없으면 MAX_BUY_AMOUNT_PER_STOCK)<br><span style="opacity:.7">예) 200,000÷0.015 = 13,333,333원</span></td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<table style="width:100%;border-collapse:collapse">
|
||
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">쿨다운(분)</td><td>청산 후 같은 종목 재진입 금지(분) → 봇 DB: <b>REENTRY_COOLDOWN_SEC</b>(초) ÷60 자동 변환 (scalping_engine.py)</td></tr>
|
||
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">거래량배수</td><td>신호봉 거래량 ≥ 20봉 평균 × N배. 0=비활성 → 봇 DB: <b>VOL_MULTIPLIER</b> (라이브·백테 동일)</td></tr>
|
||
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">어깨발동%</td><td>진입가 대비 이 % 이상 수익 후 max_price 추적 시작 → DB: <b>SCALP_SHOULDER_MIN_HIGH_PCT</b> (없으면 SHOULDER_MIN_HIGH_PCT)</td></tr>
|
||
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">어깨폭%</td><td>고점 대비 이 % 하락 시 <b>1순위 어깨컷</b> → DB: <b>SCALP_SHOULDER_CUT_PCT</b> (꼬리잡기와 동일 로직)</td></tr>
|
||
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">매수시작/종료</td><td>매수 가능 시간대 (HHMM) → 봇 DB: <b>SCALP_TIME_START / SCALP_TIME_END</b> (없으면 글로벌 TIME_START/TIME_END)</td></tr>
|
||
<tr><td style="color:#3fb950;padding:1px 6px;white-space:nowrap">일일최대매수</td><td>종목당 하루 최대 거래횟수 → 봇 DB: <b>SCALP_MAX_DAILY</b> (없으면 엔진 기본 3)</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="mt-1">⚡ 진입가 = <b>신호봉 다음 봉 시가</b> (실제 주문과 동일하게 1봉 지연) | 수수료 0.015%×2 + 거래세 0.18% 자동 차감</div>
|
||
<div class="mt-1" style="color:#3fb950">✅ <b>라이브-백테스트 100% 동일 엔진</b>: 라이브 ScalpingStrategy.check_buy / check_sell_signals 가 모두 ``scalping_engine.check_buy_signal_live`` / ``check_sell_signal_live`` 를 직접 호출합니다.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 파라미터 요약 -->
|
||
<div id="bt_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="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>
|
||
<!-- 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="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>진입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" checked>
|
||
<label class="form-check-label" for="tl_use_univ_history" style="font-size:12px;color:var(--muted)">
|
||
<b>저장 후보 이력</b> (<code>target_candidates_history</code>) — 체크: DB 슬롯·후보 / 해제: ws_candles 전 종목
|
||
</label>
|
||
</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 — 기본 OFF(실매 정합). 저장 틱 ~3초라 실시간 구독 진입과 어긋남. 켜면 limit_atr·align 진입가를 ws_ticks로 재생">
|
||
<b>틱 재생</b> (<code>ws_ticks</code>) — 기본 OFF · 실매는 OHLC 경로 권장
|
||
</label>
|
||
</div>
|
||
<div class="form-check form-check-inline mt-1">
|
||
<input class="form-check-input" type="checkbox" id="tl_tick_fallback_ohlc" checked>
|
||
<label class="form-check-label" for="tl_tick_fallback_ohlc" style="font-size:12px;color:var(--muted)"
|
||
title="TAIL_BACKTEST_TICK_FALLBACK_OHLC — 해당 분 틱 없을 때 3분봉 OHLC 폴백">
|
||
틱 없으면 <b>OHLC 폴백</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>
|
||
<!-- 당일 누적손익 트레일 익절 (포트폴리오·일단위) -->
|
||
<div class="row g-2 align-items-end mt-1">
|
||
<div class="col-12"><span style="font-size:11px;color:var(--muted)">📅 당일 누적손익 트레일 익절 — 그날 실현손익 고점 대비 되돌리면 신규매수 중단 (실매 daily_profit_halt 동일). 다단 입력 시 단일 되돌림은 무시</span></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=OFF">단일되돌림(%)</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="종목당 하루 최대 거래횟수 (실매 MAX_STOCKS)">일일최대매수</label>
|
||
<input type="number" class="form-control" id="tl_maxd" value="3" min="1" max="10">
|
||
</div>
|
||
<div class="col-auto d-flex align-items-end">
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="tl_eod_enabled" checked>
|
||
<label class="form-check-label param-row" for="tl_eod_enabled" title="ON=설정 시각 이후 보유 전량 당일청산">EOD청산</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row" title="EOD 당일청산 시각 (HH:MM)">EOD시각</label>
|
||
<input type="text" class="form-control" id="tl_eod_hm" value="15:25" placeholder="15:25" style="width:72px">
|
||
</div>
|
||
</div>
|
||
<!-- TRIGGER 플래그 (SCAN vs TRIGGER — 실매·백테·저장 동일) -->
|
||
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#0d1117;border:1px solid #21262d">
|
||
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">TRIGGER 필터</b> — 매수 직전 엔진 검사 (HTS tail 조건 통과 후)</span></div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_skip_hts_dupes" checked>
|
||
<label class="form-check-label" for="tl_skip_hts_dupes" style="font-size:12px" title="HTS A조건(낙폭) 재검사 생략 — 이중필터 방지">HTS중복스킵</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_use_rsi_filter" checked>
|
||
<label class="form-check-label" for="tl_use_rsi_filter" style="font-size:12px">RSI필터</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_use_ma20_filter">
|
||
<label class="form-check-label" for="tl_use_ma20_filter" style="font-size:12px">MA20필터</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_use_daily_range" checked>
|
||
<label class="form-check-label" for="tl_use_daily_range" style="font-size:12px">당일변동필터</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_use_high_chase_f" checked>
|
||
<label class="form-check-label" for="tl_use_high_chase_f" style="font-size:12px">고점추격필터</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2" title="이 백테 1회에만 적용 (실매 미반영). 저장 시에만 DB 반영">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_ob_filter" checked>
|
||
<label class="form-check-label" for="tl_ob_filter" style="font-size:12px">호가필터(백테)</label>
|
||
</div>
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_pg_filter" checked>
|
||
<label class="form-check-label" for="tl_pg_filter" style="font-size:12px">프로그램필터(백테)</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="호가 스프레드 상한(%). kiwoom_0d 본체 재계산(6/25~)">스프레드(%)<span class="d-block text-muted fw-normal" style="font-size:10px">MAX_SPREAD</span></label>
|
||
<input type="number" step="0.01" class="form-control form-control-sm" id="tl_max_spread_pct" value="0.45">
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="tl_use_intraday_drop">
|
||
<label class="form-check-label" for="tl_use_intraday_drop" style="font-size:12px">당일낙폭필터</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<label class="form-label param-row" title="0=OFF. 신호봉 거래량 ≥ 직전 N봉평균×배수 (TRIGGER)">거래량배수</label>
|
||
<input type="number" class="form-control" id="tl_tail_vol_mult" value="0" min="0" max="10" step="0.1" style="width:78px">
|
||
</div>
|
||
<div class="col-6 col-md-1">
|
||
<label class="form-label param-row" title="거래량 평균 창(봉 수)">거래량창</label>
|
||
<input type="number" class="form-control" id="tl_tail_vol_win" value="5" min="1" max="30" step="1" style="width:58px">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" style="font-size:11px">봉등락MIN%</label>
|
||
<input type="number" class="form-control" id="tl_bar_chg_min" value="-10" min="-30" max="0" step="0.5">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" style="font-size:11px">봉등락MAX%</label>
|
||
<input type="number" class="form-control" id="tl_bar_chg_max" value="-1.5" min="-30" max="0" step="0.5">
|
||
</div>
|
||
</div>
|
||
<!-- 반전 패턴 OR (TRIGGER — 낙폭·회복 필터 AND 유지) -->
|
||
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#0d1117;border:1px solid #21262d">
|
||
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:var(--accent)">반전 패턴</b> — 하나라도 충족 시 진입 (env <code>TAIL_PATTERN_*</code>)</span></div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_hammer" checked>
|
||
<label class="form-check-label" for="tl_pat_hammer" style="font-size:12px" title="TAIL_PATTERN_HAMMER">망치</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_pin">
|
||
<label class="form-check-label" for="tl_pat_pin" style="font-size:12px" title="TAIL_PATTERN_PIN">핀바</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_engulfing">
|
||
<label class="form-check-label" for="tl_pat_engulfing" style="font-size:12px" title="TAIL_PATTERN_ENGULFING">장악</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_piercing">
|
||
<label class="form-check-label" for="tl_pat_piercing" style="font-size:12px" title="TAIL_PATTERN_PIERCING">관통</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_harami">
|
||
<label class="form-check-label" for="tl_pat_harami" style="font-size:12px" title="TAIL_PATTERN_HARAMI">하라미</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_doji">
|
||
<label class="form-check-label" for="tl_pat_doji" style="font-size:12px" title="TAIL_PATTERN_DOJI">도지</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-auto">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="tl_pat_morning_star">
|
||
<label class="form-check-label" for="tl_pat_morning_star" style="font-size:12px" title="TAIL_PATTERN_MORNING_STAR">샛별</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row g-2 align-items-end mt-1">
|
||
<div class="col-12 col-md-auto mt-2 d-flex gap-2 flex-wrap">
|
||
<button class="btn btn-primary px-4" onclick="runTailBacktest()">🚀 백테스트 실행</button>
|
||
<button class="btn btn-success px-3" onclick="saveTailConfig()">💾 봇에 설정저장</button>
|
||
<button class="btn btn-outline-info px-3" onclick="loadTailSearchResults()">📂 탐색결과 불러오기</button>
|
||
<span class="text-muted" style="font-size:11px">탐색: CLI tail_param_search.py · 표에서 <b>폼반영</b>/<b>DB저장</b></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)">📖 파라미터 설명 (실매·파라서치·백테 동일 — 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">RSI과열기준</td><td><b>RSI_OVERHEAT_THRESHOLD</b> · 쿨다운 <b>REENTRY_COOLDOWN_SEC</b></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="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>매도사유</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-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>
|
||
<!-- 매도/포지션 (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="1" min="1" max="5" 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="종목당 1회 최대 손실(원)">1회최대손실</label>
|
||
<input type="number" class="form-control" id="bo_max_loss" value="200000" min="0" step="10000" style="width:110px">
|
||
</div>
|
||
</div>
|
||
<div class="row g-2 align-items-end mt-1">
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check mt-1">
|
||
<input class="form-check-input" type="checkbox" id="bo_use_ema_f">
|
||
<label class="form-check-label" for="bo_use_ema_f" style="font-size:12px">EMA추세필터 (TRIGGER)</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2" title="이 백테 1회에만 적용 (실매 미반영). 저장 시에만 DB 반영">
|
||
<div class="form-check mt-1">
|
||
<input class="form-check-input" type="checkbox" id="bo_ob_filter" checked>
|
||
<label class="form-check-label" for="bo_ob_filter" style="font-size:12px">호가필터(백테)</label>
|
||
</div>
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="bo_pg_filter" checked>
|
||
<label class="form-check-label" for="bo_pg_filter" style="font-size:12px">프로그램필터(백테)</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="호가 스프레드 상한(%). kiwoom_0d 본체 재계산(6/25~)">스프레드(%)<span class="d-block text-muted fw-normal" style="font-size:10px">MAX_SPREAD</span></label>
|
||
<input type="number" step="0.01" class="form-control form-control-sm" id="bo_max_spread_pct" value="0.45">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="EMA 추세 필터 빠른 기간">EMA빠름<span class="d-block text-muted fw-normal" style="font-size:10px">fast · BREAKOUT_EMA_FAST_PERIOD</span></label>
|
||
<input type="number" class="form-control" id="bo_ema_fast" value="9" min="2" max="60" step="1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="EMA 추세 필터 느린 기간">EMA느림<span class="d-block text-muted fw-normal" style="font-size:10px">slow · BREAKOUT_EMA_SLOW_PERIOD</span></label>
|
||
<input type="number" class="form-control" id="bo_ema_slow" value="21" min="3" max="120" step="1">
|
||
</div>
|
||
</div>
|
||
<!-- 당일 누적손익 트레일 익절 (포트폴리오·일단위) -->
|
||
<div class="row g-2 align-items-end mt-1">
|
||
<div class="col-12"><span style="font-size:11px;color:var(--muted)">📅 당일 누적손익 트레일 익절 — 그날 실현손익 고점 대비 되돌리면 신규매수 중단 (실매 daily_profit_halt 동일). 다단 입력 시 단일 되돌림은 무시</span></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=OFF">단일되돌림(%)</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> (<code>target_candidates_history</code>) — 체크: DB 슬롯·후보 / 해제: ws_candles 전 종목
|
||
</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="runBreakoutBacktest()">🚀 백테스트 실행</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 param_search_breakout.py · 입력 기본값=최신 fast 1위</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)">📖 키움 '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="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>
|
||
</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>
|
||
<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">
|
||
<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">PF</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" 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>
|
||
<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 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>
|
||
</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 키 'MOMENTUM_*' 우선, 없으면 기존 'SCALP_MOM_*' 자동 fallback.
|
||
- 백엔드: /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>
|
||
• <b>호환</b>: 새 키 <code>MOMENTUM_*</code> 미설정 시 기존 <code>SCALP_MOM_*</code> 자동 fallback (운영 데이터 그대로 승계)
|
||
</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> 사용 (<code>target_candidates_history</code>) — <b>체크(기본)</b> = DB 슬롯·후보 재현 (<code>param_search_momentum</code> 기본과 동일).
|
||
체크 해제 = 모멘텀 시뮬 유니버스 (<code>--fallback-universe</code>).
|
||
</label>
|
||
</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="매수 종료시각(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">
|
||
<label class="form-label param-row" title="EOD 당일청산 시각 (HH:MM)">EOD시각<span class="d-block text-muted fw-normal" style="font-size:10px">MOMENTUM_EOD_HM</span></label>
|
||
<input type="text" class="form-control" id="mom_eod_hm" value="15:25" placeholder="15:25" style="width:72px">
|
||
</div>
|
||
</div>
|
||
<div class="row g-2 align-items-end mt-1">
|
||
<div class="col-12 col-md-2">
|
||
<label class="form-label param-row" title="OFF면 진입 방어(낙폭/고점추격/급등/최소가격)를 비활성화하고, 손절/익절/장마감청산은 유지">방어로직<span class="d-block text-muted fw-normal" style="font-size:10px">entry filters · MOMENTUM_USE_DEFENSE_FILTERS</span></label>
|
||
<div class="form-check mt-1">
|
||
<input class="form-check-input" type="checkbox" id="mom_use_defense" checked>
|
||
<label class="form-check-label" for="mom_use_defense">진입 방어 ON</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-12 col-md-2">
|
||
<label class="form-label param-row" title="이 백테 1회에만 적용 (실매 미반영). 저장 시에만 DB 반영">TRIGGER 필터(백테)<span class="d-block text-muted fw-normal" style="font-size:10px">호가·프로그램 · 끄고/켜고 비교용</span></label>
|
||
<div class="form-check mt-1">
|
||
<input class="form-check-input" type="checkbox" id="mom_ob_filter" checked>
|
||
<label class="form-check-label" for="mom_ob_filter">호가필터 ON</label>
|
||
</div>
|
||
<span id="mom_ob_filter_note" class="d-block text-muted" style="font-size:10px"></span>
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="mom_pg_filter" checked>
|
||
<label class="form-check-label" for="mom_pg_filter">프로그램필터 ON</label>
|
||
</div>
|
||
<span id="mom_pg_filter_note" class="d-block text-muted" style="font-size:10px"></span>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<label class="form-label param-row" title="호가 스프레드 상한(%). 0.45=0.45%. kiwoom_0d 본체 재계산(6/25~). 본체 없는 날은 log 판정 폴백">스프레드상한(%)<span class="d-block text-muted fw-normal" style="font-size:10px">ORDERBOOK_MAX_SPREAD_PCT</span></label>
|
||
<input type="number" step="0.01" class="form-control form-control-sm" id="mom_max_spread_pct" value="0.45">
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check mt-3">
|
||
<input class="form-check-input" type="checkbox" id="mom_use_high_chase_f">
|
||
<label class="form-check-label" for="mom_use_high_chase_f" style="font-size:12px">고점추격필터 (기본 OFF)</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check mt-3">
|
||
<input class="form-check-input" type="checkbox" id="mom_use_daily_range">
|
||
<label class="form-check-label" for="mom_use_daily_range" style="font-size:12px">당일변동필터 (기본 OFF)</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-6 col-md-2">
|
||
<div class="form-check mt-3">
|
||
<input class="form-check-input" type="checkbox" id="mom_use_ema_f" checked>
|
||
<label class="form-check-label" for="mom_use_ema_f" style="font-size:12px">EMA추세필터 (기본 ON)</label>
|
||
</div>
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="EMA 추세 필터 빠른 기간">EMA빠름<span class="d-block text-muted fw-normal" style="font-size:10px">fast period · MOMENTUM_EMA_FAST_PERIOD</span></label>
|
||
<input type="number" class="form-control" id="mom_ema_fast" value="9" min="2" max="60" step="1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="EMA 추세 필터 느린 기간">EMA느림<span class="d-block text-muted fw-normal" style="font-size:10px">slow period · MOMENTUM_EMA_SLOW_PERIOD</span></label>
|
||
<input type="number" class="form-control" id="mom_ema_slow" value="21" min="3" max="120" step="1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="당일고가 대비 이 비율 이하면 진입 허용">고점추격방지<span class="d-block text-muted fw-normal" style="font-size:10px">near-high gate · HIGH_CHASE_THR</span></label>
|
||
<input type="number" class="form-control" id="mom_high_chase" value="0.96" min="0.5" max="1" step="0.01">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="당일 등락률 이 값 초과 시 진입 금지(%)">급등주필터(%)<span class="d-block text-muted fw-normal" style="font-size:10px">intraday range cap · MAX_DAILY_CHG</span></label>
|
||
<input type="number" class="form-control" id="mom_max_daily_chg" value="20" min="0" max="100" step="1">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="이 가격 미만 종목 진입 금지(원)">최소가격(원)<span class="d-block text-muted fw-normal" style="font-size:10px">min tick price · MOMENTUM_MIN_PRICE</span></label>
|
||
<input type="number" class="form-control" id="mom_min_price" value="1000" min="0" step="100">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="종목당 1회 최대 손실 한도(원)">1회최대손실(원)<span class="d-block text-muted fw-normal" style="font-size:10px">loss cap KRW · MOMENTUM_MAX_LOSS_PER_TRADE_KRW</span></label>
|
||
<input type="number" class="form-control" id="mom_max_loss_krw" value="200000" min="0" step="10000">
|
||
</div>
|
||
<div class="col-4 col-md-1">
|
||
<label class="form-label param-row" title="본절사수 시 최소 순이익 마진(%)">본절마진(%)<span class="d-block text-muted fw-normal" style="font-size:10px">breakeven buffer · MOMENTUM_MIN_PROFIT_PCT</span></label>
|
||
<input type="number" class="form-control" id="mom_min_margin" value="0.2" min="0" max="50" step="0.1">
|
||
</div>
|
||
<!-- 당일 누적손익 트레일 익절 (포트폴리오·일단위) -->
|
||
<div class="col-12 mt-1"><span style="font-size:11px;color:var(--muted)">📅 당일 누적손익 트레일 익절 — 그날 실현손익 고점 대비 되돌리면 신규매수 중단 (실매 daily_profit_halt 동일). 다단 입력 시 단일 되돌림은 무시</span></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=OFF">단일되돌림(%)</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 col-md-auto mt-2 d-flex gap-2 flex-wrap">
|
||
<button class="btn btn-primary px-4" onclick="runMomentumBacktest()">🚀 백테스트 실행</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 param_search_momentum.py · 표에서 <b>폼반영</b>/<b>DB저장</b> · 저장 후보 이력 체크 시 <b>1~3분</b></span>
|
||
</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="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>매도사유</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 -->
|
||
|
||
<!-- ═══ 홀딩 전략 탭 ═══════════════════════════════════════════════════════ -->
|
||
<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>
|
||
<!-- 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 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="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>
|
||
</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 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="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>
|
||
</tr></thead>
|
||
<tbody id="ubx_trades_tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- tab-updownbox end -->
|
||
|
||
<!-- ═══ 하락매수 Updow (kis_trader/strategies/updow_buy) ═════════════════════════ -->
|
||
<div id="tab-updow" style="display:none">
|
||
<!-- ═══ 영구구독 관리 (국내 WS H0STCNT0 + 해외 WS HDFSCNT0) ═══ -->
|
||
<div class="card p-3 mb-3">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h6 class="mb-0">📡 영구구독 관리 <small class="text-muted">(KR=국내 WS · US=해외 WS)</small></h6>
|
||
<button class="btn btn-sm btn-outline-secondary" type="button" onclick="permLoad()">새로고침</button>
|
||
</div>
|
||
<div class="row g-2 align-items-end flex-wrap mb-2">
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">코드</label>
|
||
<input class="form-control" id="perm_code" style="width:110px" placeholder="QQQM/005930">
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">시장</label>
|
||
<select class="form-select" id="perm_market" style="width:90px" onchange="permOnMarket()">
|
||
<option value="KR">KR</option>
|
||
<option value="US">US</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">거래소</label>
|
||
<select class="form-select" id="perm_exch" style="width:100px">
|
||
<option value="KRX">KRX</option>
|
||
<option value="NASD">NASD</option>
|
||
<option value="NYSE">NYSE</option>
|
||
<option value="AMEX">AMEX</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">심볼</label>
|
||
<input class="form-control" id="perm_symbol" style="width:100px" placeholder="(기본=코드)">
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">TF분</label>
|
||
<input class="form-control" id="perm_tf" type="number" value="15" style="width:70px">
|
||
</div>
|
||
<div class="col-auto">
|
||
<label class="form-label param-row">메모</label>
|
||
<input class="form-control" id="perm_note" style="width:140px" 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>TF</th><th>tr_key</th><th>ON</th><th>메모</th><th></th>
|
||
</tr></thead>
|
||
<tbody id="perm_tbody"><tr><td colspan="9" class="text-muted">로딩…</td></tr></tbody>
|
||
</table>
|
||
</div>
|
||
<small class="text-muted">⚠️ 해외(US) 실시간시세는 KIS '해외 실시간시세' 미신청 시 15분 지연. tr_key=D+거래소(NAS/NYS/AMS)+심볼</small>
|
||
</div>
|
||
|
||
</div><!-- tab-updow end -->
|
||
|
||
</div><!-- container end -->
|
||
|
||
<script src="{{ url_for('static', filename='js/backtest.js') }}"></script>
|
||
</body>
|
||
</html> |