feat(vol_breakout): 15m 현물 롱 라이브·모니터·cron 운영 추가

vol_breakout 멀티종목 tick, vol_live HTML 모니터, 마감 봉만 저장하는 캔들 다운로드,
텔레그램 체결 알림, cron/watch 감시 스크립트 및 테스트를 포함한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dsyoon
2026-06-29 08:31:14 +09:00
parent 8413bbd536
commit 72de8d534e
58 changed files with 6008 additions and 1286 deletions

View File

@@ -0,0 +1,46 @@
"""vol_breakout 현물 롱 단위 테스트."""
from __future__ import annotations
import pandas as pd
from bithumb.operations.multi_portfolio import count_empty_buy_slots, empty_multi_portfolio
from bithumb.simulation.vol_breakout import (
baseline_15m_signal_at,
spot_long_action,
)
def test_spot_long_action_buy_only_when_flat() -> None:
assert spot_long_action(1, False) == "buy"
assert spot_long_action(1, True) is None
def test_spot_long_action_sell_only_when_long() -> None:
assert spot_long_action(-1, True) == "sell"
assert spot_long_action(-1, False) is None
def test_baseline_signal_breakout() -> None:
n = 30
closes = [100.0] * n
closes[-1] = 120.0
df = pd.DataFrame({
"datetime": pd.date_range("2026-01-01", periods=n, freq="15min"),
"open": closes,
"high": [c + 1 for c in closes],
"low": [c - 1 for c in closes],
"close": closes,
"volume": [1.0] * n,
})
sig = baseline_15m_signal_at(df, n - 1, lookback=5, atr_mult=0.01)
assert sig == 1
def test_empty_buy_slots_dynamic_split() -> None:
pf = empty_multi_portfolio(["TRX", "NEAR", "WLD"], cash_krw=900_000)
assert count_empty_buy_slots(pf, ["TRX", "NEAR", "WLD"]) == 3
pf["positions"]["TRX"]["coin_qty"] = 100.0
assert count_empty_buy_slots(pf, ["TRX", "NEAR", "WLD"]) == 2
pf["positions"]["NEAR"]["coin_qty"] = 10.0
assert count_empty_buy_slots(pf, ["TRX", "NEAR", "WLD"]) == 1