chore: 작업 중 발생한 부수적 변경 사항 및 누락된 파일 전체 커밋
- 프론트엔드 UI 업데이트 (backtest.html, backtest.js) 엔진 라디오 버튼 통합 관련 반영 - Rust 플러그인(kis_rust_core) 및 컴파일 소스코드 추가 - CLI 백테스트 스크립트 수정 및 최신화 - 기타 스크래치 테스트 스크립트, 로그 요약 마크다운(.md) 등 누락 파일 일괄 반영 - 추가적으로 아직 발견되지 않은 엣지 케이스나 렌더링 오류가 포함되어 있을 가능성이 있음
This commit is contained in:
@@ -1,48 +1,81 @@
|
||||
import time
|
||||
import kis_rust_core
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Ensure kis_bot root is in path
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
|
||||
from database import TradeDB
|
||||
from kis_trader.backtest.tail_backtest_common import load_tail_candles_by_code
|
||||
from kis_trader.engine.tail_engine import run_tail_backtest, run_tail_backtest_rust_experimental, get_tail_defaults_from_db
|
||||
|
||||
def test_rust_tail():
|
||||
print(f"Loaded Rust Module: {kis_rust_core}")
|
||||
|
||||
# 1. 파라미터 셋업
|
||||
params = kis_rust_core.TailParams(
|
||||
rsi_limit=45.0,
|
||||
drop_pct_min=3.0,
|
||||
tail_recovery_min=1.5,
|
||||
target_pct=2.0,
|
||||
stop_loss_pct=3.0
|
||||
)
|
||||
print(f"TailParams initialized: {params.rsi_limit}, {params.target_pct}% target")
|
||||
db = TradeDB()
|
||||
try:
|
||||
# Load recent env params
|
||||
engine_params = get_tail_defaults_from_db(db)
|
||||
print(f"Engine params: {engine_params}")
|
||||
|
||||
# Load candles
|
||||
start_date = "2026-08-07"
|
||||
end_date = "2026-08-07"
|
||||
print(f"Loading candles from {start_date} to {end_date}...")
|
||||
candles_by_code, _, _ = load_tail_candles_by_code(db, start_date, end_date, 3)
|
||||
print(f"Loaded {len(candles_by_code)} symbols.")
|
||||
|
||||
# Create Python engine
|
||||
py_trades = run_tail_backtest(
|
||||
candles_by_code=candles_by_code,
|
||||
params=engine_params,
|
||||
)
|
||||
print(f"[Python] Found {len(py_trades)} trades.")
|
||||
|
||||
# Create Rust engine
|
||||
rs_trades = run_tail_backtest_rust_experimental(
|
||||
codes_candles=candles_by_code,
|
||||
params=engine_params,
|
||||
)
|
||||
print(f"[Rust] Found {len(rs_trades)} trades.")
|
||||
|
||||
# Sort both
|
||||
rs_trades.sort(key=lambda x: (x["code"], x["entry_time"]))
|
||||
py_trades.sort(key=lambda x: (x["code"], x["entry_time"]))
|
||||
|
||||
if len(rs_trades) != len(py_trades):
|
||||
print(f"!!! COUNT MISMATCH !!! Rust: {len(rs_trades)}, Python: {len(py_trades)}")
|
||||
|
||||
# Compare first 5
|
||||
print("\n--- Python Trades ---")
|
||||
for i, t in enumerate(py_trades[:5]):
|
||||
print(f"{i}: {t}")
|
||||
|
||||
print("\n--- Rust Trades ---")
|
||||
for i, t in enumerate(rs_trades[:5]):
|
||||
print(f"{i}: {t}")
|
||||
|
||||
# Check diff
|
||||
print("\n--- Differences ---")
|
||||
py_simple = [{"code": t["code"], "entry_time": t["entry_time"], "entry": t["entry"], "exit": t["exit"]} for t in py_trades]
|
||||
rs_simple = [{"code": t["code"], "entry_time": t["entry_time"], "entry": t["entry"], "exit": t["exit"]} for t in rs_trades]
|
||||
|
||||
diff_count = 0
|
||||
for pt in py_simple:
|
||||
if pt not in rs_simple:
|
||||
print(f"Python has trade not in Rust: {pt}")
|
||||
diff_count += 1
|
||||
if diff_count > 10:
|
||||
break
|
||||
for rt in rs_simple:
|
||||
if rt not in py_simple:
|
||||
print(f"Rust has trade not in Python: {rt}")
|
||||
diff_count += 1
|
||||
if diff_count > 20:
|
||||
break
|
||||
|
||||
# 2. 더미 캔들 100만 개 생성 (부하 테스트)
|
||||
print("Generating 1,000,000 dummy candles in Python...")
|
||||
start_time = time.time()
|
||||
candles = []
|
||||
# 단순 패턴: RSI 30, 크게 떨어지고(-4%), 반등(2%)하는 캔들 1개와 나머지 일반 캔들
|
||||
for i in range(1_000_000):
|
||||
if i % 1000 == 0:
|
||||
# 진입 신호 조건 부합하는 캔들
|
||||
c = kis_rust_core.CandleData(f"2026-09-02 {i}", 1000.0, 1050.0, 960.0, 1020.0, 50000.0, 25.0)
|
||||
elif i % 1000 == 5:
|
||||
# 청산(Target) 달성하는 캔들 (고가 1100 -> 10% 상승)
|
||||
c = kis_rust_core.CandleData(f"2026-09-02 {i}", 1020.0, 1100.0, 1010.0, 1080.0, 10000.0, 45.0)
|
||||
else:
|
||||
# 평범한 캔들
|
||||
c = kis_rust_core.CandleData(f"2026-09-02 {i}", 1000.0, 1010.0, 990.0, 1000.0, 1000.0, 50.0)
|
||||
candles.append(c)
|
||||
print(f"Generated 1,000,000 objects in {time.time() - start_time:.3f}s")
|
||||
|
||||
# 3. Rust 엔진으로 던지기
|
||||
print("Running Rust fast tail backtest...")
|
||||
start_time = time.time()
|
||||
pnl = kis_rust_core.run_tail_backtest_fast(params, candles)
|
||||
elapsed = time.time() - start_time
|
||||
|
||||
print(f"=====================================")
|
||||
print(f"🦀 RUST ENGINE RESULT:")
|
||||
print(f"Total PnL: {pnl:.2f} ₩")
|
||||
print(f"Elapsed Time: {elapsed:.4f} seconds for 1M candles!")
|
||||
print(f"=====================================")
|
||||
if diff_count == 0:
|
||||
print("100% Match!")
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_rust_tail()
|
||||
|
||||
Reference in New Issue
Block a user