Files
Chan/research/step16_fast_bsp3_nested.py
jackyu66gitandCursor 7f393b93ed refactor: 精简仓库为 chanlun 核心与 web 分析,移除威科夫与遗留模块
删除根目录旧 Chan 模块、策略、配置、文档及 wyckoff 相关代码;更新缠论 pipeline 与笔中枢计算;补充 research 研究与 web 测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-27 01:05:12 +08:00

123 lines
4.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Step 16:快速三买 + 大级别分型定位。
Step 15 证明两件事:
- 大级别分型定位有判别力(同向 PF 0.55 vs 反向 0.29
- 但引擎三买基线太差(PF 0.50),因为要等回拉笔确认,滞后 9~10 根
本步把三买的确认从「等笔确认」换成「回抽当根实时判定」,
在同样的区间套结构下重测。
"""
from __future__ import annotations
import argparse
import sys
import warnings
from pathlib import Path
import numpy as np
import pandas as pd
warnings.filterwarnings("ignore")
sys.path.insert(0, str(Path(__file__).resolve().parent))
from lib.breakout import run_trades, summarize_trades
from lib.data import fetch_ohlcv
from lib.fast_bsp3 import find_fast_bsp3
from lib.fx_signal import extract_fx_signals, signals_to_frame
from lib.nested_bsp import attach_htf_context, htf_fx_timeline
from lib.nested_level import build_htf_zones
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from chanlun import TF_DF
pd.set_option("display.width", 260)
def show(rows: list[dict]) -> None:
rows = [r for r in rows if r.get("笔数", 0) > 0]
print(pd.DataFrame(rows).to_string(index=False) if rows else " (样本不足)")
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("--symbol", default="BTC/USDT:USDT")
ap.add_argument("--ltf", default="15m")
ap.add_argument("--htf1", default="1h")
ap.add_argument("--htf2", default="4h")
ap.add_argument("--sl", type=float, default=1.5)
ap.add_argument("--tp", type=float, default=3.0)
ap.add_argument("--max-bars", type=int, default=48)
args = ap.parse_args()
df_l = fetch_ohlcv(args.symbol, args.ltf, 10**9)
chan_l = TF_DF(df_l, 1, args.ltf)
cdf_l = chan_l.dataframe
zones = build_htf_zones(df_l, args.ltf)
sig = find_fast_bsp3(cdf_l, zones)
print(f"[小级别 {args.ltf}] {len(cdf_l)} 根K线 中枢 {len(zones)} "
f"快速三类信号 {len(sig)}")
if sig.empty:
print("无信号")
return
print(f" 方向:三买 {(sig.direction == 1).sum()} / 三卖 {(sig.direction == -1).sum()}")
print(f" 突破到入场滞后:中位 {sig['lag'].median():.0f} 根 "
f"均值 {sig['lag'].mean():.1f} 根 —— 对照引擎三买 9~10 根")
ctx = sig
for tf, pref in ((args.htf1, "h1"), (args.htf2, "h2")):
df_h = fetch_ohlcv(args.symbol, tf, 10**9)
chan_h = TF_DF(df_h, 1, tf)
sig_h = signals_to_frame(extract_fx_signals(chan_h, chan_h.dataframe))
ctx = attach_htf_context(ctx, cdf_l, htf_fx_timeline(sig_h, chan_h.dataframe), pref)
a1 = ctx["h1_agree"] == 1
a2 = ctx["h2_agree"] == 1
print(f"\n[方向一致率] {args.htf1} {a1.mean() * 100:.0f}% "
f"{args.htf2} {a2.mean() * 100:.0f}% 两者同时 {(a1 & a2).mean() * 100:.0f}%")
E = lambda g: list(zip(g["entry_idx"].astype(int), g["direction"].astype(int)))
T = lambda g, nm: summarize_trades(
run_trades(cdf_l, E(g), args.sl, args.tp, args.max_bars), nm)
print("\n########## 逐层过滤 ##########")
rows = [
T(ctx, "A 全部快速三类"),
T(ctx[a1], f"B +{args.htf1}同向"),
T(ctx[a2], f"C +{args.htf2}同向"),
T(ctx[a1 & a2], "D 双大级别同向"),
T(ctx[~a1], f"F {args.htf1}反向(对照)"),
]
show(rows)
print("\n########## 回抽深度分层(越大表示回抽越浅、未插入中枢)##########")
rows = []
q = ctx["depth"].quantile([0.33, 0.66]).to_numpy()
for lo, hi, nm in [(-9, q[0], "深回抽"), (q[0], q[1], "中等"), (q[1], 9, "浅回抽")]:
g = ctx[(ctx.depth >= lo) & (ctx.depth < hi)]
if len(g) >= 20:
rows.append(T(g, nm))
show(rows)
print("\n########## 多空拆分(双大级别同向)##########")
both = ctx[a1 & a2]
rows = [T(both[both.direction == d], nm)
for d, nm in ((1, "三买做多"), (-1, "三卖做空"))
if len(both[both.direction == d]) >= 10]
show(rows)
print("\n########## 与 Step 15 引擎三买的直接对照 ##########")
print(f" 引擎三买(等笔确认,滞后 9~10 根):675 笔 PF 0.50 t -7.87")
a = T(ctx, "快速三买(实时判定)")
print(f" 快速三买(回抽当根,滞后 {sig['lag'].median():.0f} 根):"
f"{a['笔数']} 笔 PF {a['盈亏比PF']} t {a['t值']}")
out = Path(__file__).parent / "out" / f"step16_fast_{args.symbol.split('/')[0]}_{args.ltf}.csv"
out.parent.mkdir(exist_ok=True)
ctx.to_csv(out, index=False)
print(f"\n明细已写入 {out}")
if __name__ == "__main__":
main()