Files
kis_trader/scratch/fix_bloat.py

137 lines
5.6 KiB
Python

import subprocess
import os
ROOT = "/home/hoon/kis_bot"
def run(cmd):
subprocess.run(cmd, shell=True, check=True, cwd=ROOT)
print("Restoring bloated files...")
run("git checkout templates/backtest.html static/js/backtest.js")
print("Done restoring files.")
# Re-apply HTML changes
html_path = f"{ROOT}/templates/backtest.html"
with open(html_path, "r", encoding="utf-8") as f:
html = f.read()
html = html.replace(
"<title>📈 KIS Quant 백테스트 대시보드</title>",
"<title>📈 KIS Quant 백테스트 대시보드</title>\n<link rel=\"icon\" href=\"data:,\">"
)
eod_block = """ </div>
<div class="row g-2 align-items-center mt-2 p-2 rounded" style="background:#161b22;border:1px solid #30363d">
<div class="col-12"><span class="text-muted" style="font-size:11px"><b style="color:#79c0ff">EOD 장마감 청산</b></span></div>
<div class="col-auto d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="bt_eod_enabled" checked>
<label class="form-check-label" for="bt_eod_enabled">적용</label>
</div>
</div>
<div class="col-auto">
<label class="form-label param-row" title="청산 시작 시간 (HH:MM)">시간</label>
<input type="time" class="form-control form-control-sm" id="bt_eod_time" value="15:25">
</div>
<div class="col-auto">
<label class="form-label param-row" title="미체결 주문(지정가 등) 전체 취소 여부">미체결취소</label>
<select class="form-select form-select-sm" id="bt_eod_cancel_open">
<option value="1" selected>Y (전체취소)</option>
<option value="0">N (유지)</option>
</select>
</div>
<div class="col-auto">
<label class="form-label param-row" title="보유 종목 시장가 전량 매도 여부">시장가매도</label>
<select class="form-select form-select-sm" id="bt_eod_sell_holdings">
<option value="1" selected>Y (전량매도)</option>
<option value="0">N (오버나잇)</option>
</select>
</div>"""
html = html.replace(
"""<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>""",
f"""<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>{eod_block}"""
)
with open(html_path, "w", encoding="utf-8") as f:
f.write(html)
print("Applied HTML changes.")
# Re-apply JS changes
js_path = f"{ROOT}/static/js/backtest.js"
with open(js_path, "r", encoding="utf-8") as f:
js = f.read()
js = js.replace(
"cumReturnPct: Number(t.cum_return_pct ?? NaN),",
"cumReturnPct: Number(t.cum_return_pct ?? NaN),\n entryOb: t.entry_ob || null,\n exitOb: t.exit_ob || null,"
)
js = js.replace(
"const nameCell = (r.name || r.code)\n ? `${r.name || r.code}<br><span style=\"color:var(--muted);font-size:11px\">${r.code || ''}</span>`\n : (r.code || '-');",
"const nameCell = (r.name || r.code)\n ? `${r.name || r.code}<br><span style=\"color:var(--muted);font-size:11px\">${r.code || ''}</span>`\n : (r.code || '-');\n const linksHtml = _tradeExtLinksHtml(r);"
)
js = js.replace(
"<td class=\"trade-name-cell\">${causeBadge}${nameCell}</td>",
"<td class=\"trade-name-cell\">${causeBadge}${nameCell}${linksHtml}</td>"
)
js = js.replace(
"if (opts.showDebug) html += `<td style=\"font-size:10px\">${debugHtml}</td>`;",
"if (opts.showDebug) html += `<td style=\"font-size:10px\">${debugHtml}</td>`;\n html += `<td style=\"font-size:10px;line-height:1.35\">${_entryObCellHtml(r.entryOb)}</td>`;\n html += `<td style=\"font-size:10px;line-height:1.35\">${_exitObCellHtml(r.exitOb, r.isOpen)}</td>`;"
)
js = js.replace(
" html += `<td style=\"font-size:11px\">${reasonHtml}</td>`;",
" html += `<td style=\"font-size:11px\">${reasonHtml}</td>`;" # unchanged but kept for context, already handled above
)
helper_funcs = """/** KR 6자리 종목코드 */
function _normKrStockCode(code) {
const d = String(code || '').replace(/\\D/g, '');
if (!d) return '';
return d.length >= 6 ? d.slice(-6) : d.padStart(6, '0');
}
function _tradeExtLinksHtml(r) {
if (r.isUsd || !r.code) return '';
const c = _normKrStockCode(r.code);
return `
<div style="margin-top:2px; display:flex; gap:3px;">
<a href="https://finance.naver.com/item/main.naver?code=${c}" target="_blank" class="btn btn-xs btn-outline-secondary" style="font-size:9px;padding:0 3px">N</a>
<a href="https://m.stock.naver.com/domestic/stock/${c}/total" target="_blank" class="btn btn-xs btn-outline-secondary" style="font-size:9px;padding:0 3px">N(M)</a>
</div>
`;
}
function _entryObCellHtml(ob) {
if (!ob) return '-';
const mr = (ob.mid_ratio || 0).toFixed(1);
const wr = (ob.whale_ratio || 0).toFixed(1);
return `M:${mr}%<br>W:${wr}%`;
}
function _exitObCellHtml(ob, isOpen) {
if (isOpen) return '<span style="color:#2ea043">보유중</span>';
if (!ob) return '-';
const mr = (ob.mid_ratio || 0).toFixed(1);
const wr = (ob.whale_ratio || 0).toFixed(1);
return `M:${mr}%<br>W:${wr}%`;
}
"""
js = js.replace(
"function renderVirtualTrades(tbodyId, trades, opts) {",
helper_funcs + "\nfunction renderVirtualTrades(tbodyId, trades, opts) {"
)
with open(js_path, "w", encoding="utf-8") as f:
f.write(js)
print("Applied JS changes.")