research: 一类反手(step57),六年五币双向全正,PF 2.3~3.0
用户问一类二类的识别是不是错了。查下来是代码没写错、信号该反着用。 先排除一个错误猜测:check_bi_div 只比 MACD 面积、不检查创新极值,等于把 缠论背驰定义丢了一半。看着像致命缺陷,实测 93% 的离开笔本来就创了新极值, 解释不了 PF 0.2。 真正的线索是胜率方向:B1 胜率 18.6%,而 SL2/TP3 随机入场约 40%,远低于 随机说明样本带信息只是指反了。拿相反方向重跑出场(路径依赖,不能取负号), 5m/15m 上 PF 2.35~3.03、t +10~+13。 step57 三关全过:5 币全正、前后半段 2.81/2.81 与 2.55/2.51 几乎不变、 2021~2026 连续六年全正、多空两边都正。余量 15m 33~76bp,B4 只有约 3bp。 机理是滞后把信号变成了相反的交易:信号在 leave_bi.sure_time 发出,中位滞后 8~9 根,此时价格已从低点反弹 1.68 ATR。引擎想说抄底,它给的时间戳对应的却是 反弹已走完——在下跌趋势里于此处做空是标准的顺势回调入场。与 B4 的突破延续 是不同的入场原型,可能互补。 三项验证未做完前不许上实盘:因果性(中枢右边缘已知会重画,需流式回放)、 消融(是不是反弹就做空都赚)、与 B4 的重叠度。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -151,6 +151,15 @@ def collect(sym: str, rows: int, tf: str = "1m") -> pd.DataFrame | None:
|
||||
return None
|
||||
for k in ("g", "r", "c", "b"):
|
||||
r[k] = res[f"{cfg}_{k}"].to_numpy()
|
||||
# 反向对照:胜率远低于随机说明信号带信息但可能指反了。出场是路径依赖的,
|
||||
# 不能把 g 取负号了事,必须拿相反方向重跑一遍
|
||||
flip = pd.DataFrame({"entry_idx": r.i_sure.values,
|
||||
"direction": -r.dir.values})
|
||||
rf = walk_exits(cdf, flip, [SL], [RUNNER], [MAXB], scale_at=SCALE_AT,
|
||||
runners=(RUNNER,), runner_stops=(RSTOP,))
|
||||
if len(rf) == len(r):
|
||||
for k in ("g", "r", "c", "b"):
|
||||
r["f_" + k] = rf[f"{cfg}_{k}"].to_numpy()
|
||||
r["atr_pct"] = atr[r.i_sure.values] / cl[r.i_sure.values]
|
||||
return r
|
||||
except Exception as e:
|
||||
@@ -258,6 +267,31 @@ def profit(d: pd.DataFrame) -> None:
|
||||
print("\n⚠️ B3 是口径校验锚:HANDOFF §4 记的是 PF 0.66 / 胜率 27.4%。"
|
||||
"这里若明显更好,先怀疑接错了再信 B1/B2。")
|
||||
|
||||
if "f_g" not in x.columns:
|
||||
return
|
||||
print("\n" + "=" * 100)
|
||||
print("########## 六、反向对照:信号是「指反了」还是「没有边」 ##########")
|
||||
print("胜率 18.6% 远低于 SL2/TP3 的随机基准约 40%,说明样本带信息。若只是"
|
||||
"方向标反了,\n反手做应显著为正;若反手也不赚,那就是入场时点本身"
|
||||
"已经过期,两边都吃滑点。")
|
||||
y = x.copy()
|
||||
y["fnet"] = y.f_g.values - fee_of(y.f_r.values, y.f_c.values)
|
||||
y["fgR"] = y.f_g.values / (SL * y.atr_pct.values)
|
||||
rows = []
|
||||
for name, g in y.groupby("type"):
|
||||
if len(g) < 40:
|
||||
continue
|
||||
w, o = g.fnet[g.fnet > 0].sum(), -g.fnet[g.fnet <= 0].sum()
|
||||
rows.append({
|
||||
"类型(反手)": name, "笔数": len(g),
|
||||
"胜率": f"{(g.fnet > 0).mean()*100:.1f}%",
|
||||
"毛R": round(g.fgR.mean(), 3),
|
||||
"PF": round(w / o, 2) if o > 0 else np.inf,
|
||||
"t值": round(g.fgR.mean() / (g.fgR.std(ddof=1) / np.sqrt(len(g))),
|
||||
2),
|
||||
})
|
||||
print(pd.DataFrame(rows).to_string(index=False))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser()
|
||||
|
||||
Reference in New Issue
Block a user