63a829cc46
主要内容: - Phase 8 PROMOTE: finalist #1 (trial #324) registry 条目,自动生成 - Optuna objective warmup bug 修复 (shared/optimizer/objective.py) - studies/ 目录按用途重组为 optuna/ + finalists/ + features/ 三层 - reports/ 加入 Optuna 中文 dashboard (5 主图 + 18 slice + 15 contour) - 新增 PROJECT_GUIDE.md 项目说明文档 - 新增 build_registry_entry.py / build_optuna_dashboard.py / build_feature_datasets.py - .gitignore: 允许提交 studies/*.db (Optuna DB) 和 reports/*.html (MT5 + dashboard)
73 lines
3.1 KiB
Python
73 lines
3.1 KiB
Python
"""Check indicator values + signal conditions at 2025-01-02 01:50 vs 15:45.
|
|
|
|
MT5 first trade fired 2025.01.02 01:55 LONG @ 2624.05
|
|
→ signal bar 01:50 close=2623.84, fill at 01:55 open=2623.84
|
|
Python first trade fired 2025-01-02 15:50 LONG @ 2642.57
|
|
→ signal bar 15:45 close=2642.54, fill at 15:50 open=2642.54
|
|
|
|
Both engines should fire same signals on same bars. Why do they differ?
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
PROJECT = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(PROJECT))
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
from shared.indicators.base import atr, ema, rsi
|
|
from shared.data.loaders import load_bars
|
|
from strategies.gold_scalper_pro.search_space import FROZEN_BASELINE
|
|
import optuna
|
|
|
|
# Load finalist #1 params
|
|
db = PROJECT / "studies" / "optuna" / "gold_scalper_pro_is2025.db"
|
|
study = optuna.load_study(
|
|
study_name="gold_scalper_pro_is2025",
|
|
storage=f"sqlite:///{db}",
|
|
)
|
|
from shared.optimizer.selector import select_diverse_topn
|
|
from strategies.gold_scalper_pro.search_space import SEARCH_SPACE
|
|
finalists = select_diverse_topn(study, n=3, ranges=SEARCH_SPACE)
|
|
params = {**FROZEN_BASELINE, **finalists[0].params}
|
|
|
|
print(f"InpFastEmaPeriod={params['InpFastEmaPeriod']}, "
|
|
f"InpSlowEmaPeriod={params['InpSlowEmaPeriod']}, "
|
|
f"InpRsiPeriod={params['InpRsiPeriod']}, "
|
|
f"InpAtrPeriod={params['InpAtrPeriod']}")
|
|
print(f"InpRsiBuyLevel={params['InpRsiBuyLevel']}, "
|
|
f"InpPullbackAtrMult={params['InpPullbackAtrMult']}")
|
|
|
|
m5 = load_bars(PROJECT / "data" / "XAUUSD_M5_2024-06-26_2026-06-26.parquet")
|
|
window = m5[(m5["timestamp"] >= "2024-12-01 00:00:00") & (m5["timestamp"] < "2025-01-03 00:00:00")].reset_index(drop=True)
|
|
|
|
close = window["close"].to_numpy(dtype=float)
|
|
high = window["high"].to_numpy(dtype=float)
|
|
low = window["low"].to_numpy(dtype=float)
|
|
|
|
fast = ema(close, int(params["InpFastEmaPeriod"]))
|
|
slow = ema(close, int(params["InpSlowEmaPeriod"]))
|
|
rsi_arr = rsi(close, int(params["InpRsiPeriod"]))
|
|
atr_arr = atr(high, low, close, int(params["InpAtrPeriod"]))
|
|
|
|
# Find rows on 2025-01-02 around 01:50 and 15:45
|
|
window["fast"] = fast
|
|
window["slow"] = slow
|
|
window["rsi"] = rsi_arr
|
|
window["atr"] = atr_arr
|
|
window["trend_up"] = (fast > slow) & (close > slow)
|
|
window["near_fast"] = np.abs(close - fast) <= (params["InpPullbackAtrMult"] * atr_arr)
|
|
window["rsi_prev"] = np.roll(rsi_arr, 1)
|
|
window["buy_cross"] = (window["rsi_prev"] < params["InpRsiBuyLevel"]) & (rsi_arr >= params["InpRsiBuyLevel"])
|
|
window["buy_signal"] = window["trend_up"] & window["near_fast"] & window["buy_cross"]
|
|
|
|
print("\n=== Around 2025-01-02 01:45-02:00 ===")
|
|
sub = window[(window["timestamp"] >= "2025-01-02 01:45:00") & (window["timestamp"] <= "2025-01-02 02:00:00")]
|
|
print(sub[["timestamp", "open", "high", "low", "close", "fast", "slow",
|
|
"rsi", "atr", "trend_up", "near_fast", "buy_cross", "buy_signal"]].to_string())
|
|
|
|
print("\n=== Around 2025-01-02 15:40-15:55 ===")
|
|
sub = window[(window["timestamp"] >= "2025-01-02 15:40:00") & (window["timestamp"] <= "2025-01-02 15:55:00")]
|
|
print(sub[["timestamp", "open", "high", "low", "close", "fast", "slow",
|
|
"rsi", "atr", "trend_up", "near_fast", "buy_cross", "buy_signal"]].to_string())
|