ls증권 히스토리 구독 넣음
This commit is contained in:
@@ -177,21 +177,34 @@ def _build_scan_time_keys(
|
||||
scan_sec: int,
|
||||
time_start_hm: int,
|
||||
time_end_hm: int,
|
||||
*,
|
||||
wrap_midnight: bool = False,
|
||||
) -> List[str]:
|
||||
"""장중 분봉이 있는 구간만 N초 간격 스캔 시각(YYYYMMDDHHMMSS) 생성."""
|
||||
"""장중 분봉이 있는 구간만 N초 간격 스캔 시각(YYYYMMDDHHMMSS) 생성.
|
||||
|
||||
wrap_midnight=True: 해외 US 등 자정 넘김 세션 (예: 2230~0500).
|
||||
"""
|
||||
if not minute_set or scan_sec < 1:
|
||||
return []
|
||||
start_min = _hm_to_minutes(time_start_hm)
|
||||
end_min = _hm_to_minutes(time_end_hm)
|
||||
from kis_trader.utils.session_hm import hm_in_trading_window
|
||||
|
||||
days = sorted({m[:8] for m in minute_set})
|
||||
out: List[str] = []
|
||||
for day in days:
|
||||
day_minutes = sorted(m for m in minute_set if m.startswith(day))
|
||||
for minute_key in day_minutes:
|
||||
hm = int(minute_key[8:12])
|
||||
bar_min = _hm_to_minutes(hm)
|
||||
if bar_min < start_min or bar_min >= end_min:
|
||||
continue
|
||||
if wrap_midnight:
|
||||
if not hm_in_trading_window(
|
||||
hm, time_start_hm, time_end_hm, wrap_midnight=True,
|
||||
):
|
||||
continue
|
||||
else:
|
||||
start_min = _hm_to_minutes(time_start_hm)
|
||||
end_min = _hm_to_minutes(time_end_hm)
|
||||
bar_min = _hm_to_minutes(hm)
|
||||
if bar_min < start_min or bar_min >= end_min:
|
||||
continue
|
||||
base = datetime.strptime(minute_key, "%Y%m%d%H%M")
|
||||
sec = 0
|
||||
while sec < 60:
|
||||
@@ -540,6 +553,17 @@ def _collect_buy_candidates(
|
||||
)
|
||||
if reject or not sig:
|
||||
continue
|
||||
from kis_trader.engine.mid_enroll_entry_gate import bt_should_defer_mid_enroll
|
||||
if bt_should_defer_mid_enroll(
|
||||
str(entry_bar_time or ""),
|
||||
code,
|
||||
bar_t,
|
||||
tf_min=1,
|
||||
universe_timeline=params.get("_universe_timeline"),
|
||||
universe_by_slot=universe_by_slot,
|
||||
params=params,
|
||||
):
|
||||
continue
|
||||
entry_price, entry_time_key, entry_src = align_momentum_entry_from_ticks(
|
||||
ticks_by_code, code, entry_bar_time, entry_open, params,
|
||||
min_tick_time=min_tick_time,
|
||||
@@ -548,6 +572,7 @@ def _collect_buy_candidates(
|
||||
"entry_time": entry_time_key,
|
||||
"entry_price": entry_price,
|
||||
"entry_source": entry_src,
|
||||
"entry_bar_key": str(entry_bar_time or "")[:12],
|
||||
"stop": entry_price * (1 - sl_pct),
|
||||
"target": entry_price * (1 + tp_pct),
|
||||
"rsi": sig.get("rsi"),
|
||||
@@ -581,6 +606,8 @@ def run_momentum_backtest_portfolio(
|
||||
invest_cap = _resolve_invest_cap_krw(params, slot_money)
|
||||
fee_rate = float(params.get("fee_rate", 0.00015))
|
||||
sell_tax = float(params.get("sell_tax", 0.0018))
|
||||
fx_fee_rate = float(params.get("fx_fee_rate", 0.0) or 0.0)
|
||||
is_us_mkt = str(params.get("market") or "").strip().upper() == "US"
|
||||
|
||||
skipped_micro_buys = 0
|
||||
tick_exit_count = 0
|
||||
@@ -638,7 +665,11 @@ def run_momentum_backtest_portfolio(
|
||||
|
||||
if live_scan_queue and live_align:
|
||||
time_start_hm, time_end_hm = _time_bounds_hm(params)
|
||||
scan_keys = _build_scan_time_keys(all_times_set, scan_sec, time_start_hm, time_end_hm)
|
||||
_wrap = bool(params.get("_session_wrap_midnight"))
|
||||
scan_keys = _build_scan_time_keys(
|
||||
all_times_set, scan_sec, time_start_hm, time_end_hm,
|
||||
wrap_midnight=_wrap,
|
||||
)
|
||||
for scan_key in scan_keys:
|
||||
scan_events += 1
|
||||
bar_t = scan_key[:12]
|
||||
@@ -892,6 +923,8 @@ def run_momentum_backtest_portfolio(
|
||||
attach_scalp_trade_pnl(
|
||||
all_trades, fee_rate=fee_rate, sell_tax=sell_tax,
|
||||
slip_pct=backtest_slip_pct(params),
|
||||
fx_fee_rate=fx_fee_rate,
|
||||
pnl_decimals=4 if (is_us_mkt or fx_fee_rate > 0) else 0,
|
||||
)
|
||||
all_trades.sort(key=lambda x: x["sell_time"])
|
||||
return all_trades
|
||||
|
||||
Reference in New Issue
Block a user