//@version=6 strategy(“Brooks_Final_V53_ThreeState_Logic”, overlay=true, initial_capital=100000, process_orders_on_close=true)
// — 1. 参数设置 — t0_enabled = input.bool(false, “开启T+0日内交易”) qty_per_hand = input.int(1, “每手股数”) risk_reward_ratio = input.float(1.0, “P1盈亏比”) slope_threshold = input.float(0.01, “趋势判定斜率阈值”, step=0.01)
// — 2. 全局变量 — var float dynamic_res = 0.0 var float dynamic_sup = 0.0 var int range_test_count = 0 var int state = 1 // 1=区间, 2=上涨趋势, 3=下跌趋势 var int bull_count = 0 var float stop_level = 0.0 var float tp_p1 = 0.0 var int last_entry_date = 0
// — 3. 指标 — ema50 = ta.ema(close, 50) atr = ta.atr(14) h20 = ta.highest(high, 20) l20 = ta.lowest(low, 20)
// — 4. 动态边界 — if bar_index == 0 dynamic_res := h20 dynamic_sup := l20
if bar_index % 50 == 0 dynamic_res := h20 dynamic_sup := l20 else if close > dynamic_res dynamic_res := close if close < dynamic_sup dynamic_sup := close
// — 5. 状态机 (三态模式:1=区间, 2=上涨趋势, 3=下跌趋势) — is_bull = close > open is_bear = close < open
// 计算斜率:当前阻力/支撑 vs 20根K线前 float res_slope = dynamic_res - dynamic_res[20] float sup_slope = dynamic_sup - dynamic_sup[20]
// 状态转移逻辑 if (res_slope > slope_threshold) state := 2 // 上涨趋势 else if (sup_slope < -slope_threshold) state := 3 // 下跌趋势 else state := 1 // 回归区间
// 仅在上涨趋势下进行趋势回调计数 bull_count := (state == 2 and is_bear) ? bull_count + 1 : (is_bull ? 0 : bull_count)
// — 6. 进场决策 — // 1. 获取昨日收盘价 (确保在盘中可以正确获取日级别数据) float close_prev = request.security(syminfo.tickerid, “D”, close[1], barmerge.gaps_off, barmerge.lookahead_on) float daily_pct = (close - close_prev) / close_prev * 100 bool is_daily_runup_too_high = daily_pct > 7.0
// 2. K线强度与涨幅逻辑 float kline_change_pct = (close - open) / open * 100 // 实体占比 > 40% 且涨幅在 1% 到 7% 之间 bool is_strong_bar = (close > open) and (math.abs(close - open) / (math.max(high - low, 0.0001)) > 0.4) bool is_valid_growth = (kline_change_pct > 1.01 and kline_change_pct < 6.99)
bool is_breakout = (high > high[1])
// 3. 整合进场条件 // 共同限制:形态必须强、日内涨幅不能过高、且突破前高 bool common_entry_filters = is_strong_bar and is_valid_growth and not is_daily_runup_too_high and is_breakout
// 关键改动:增加初始突破入场逻辑 bool is_strong_bull_bar = (close > open) and (math.abs(close - open) / (math.max(high - low, 0.0001)) > 0.4) // 实体占比 > 40% bool initial_breakout_entry = (state == 1) and is_strong_bull_bar and is_valid_growth and not is_daily_runup_too_high and (high > dynamic_res)
// 区间入场 // 关键改动:给区间入场增加一个不需要严格回调序列的“强力反转线”条件 bool is_ultra_strong_bar = (close > open) and (math.abs(close - open) / (math.max(high - low, 0.0001)) > 0.9) // 实体占比 > 90% // 要求该阳线不仅踩在支撑上,且具备决定性力度 bool climax_support_test = (state == 1 and is_ultra_strong_bar and is_breakout and common_entry_filters)
// 1. 计算上下影线长度 float lower_shadow = math.min(open, close) - low float upper_shadow = high - math.max(open, close) float body_size = math.abs(close - open)
// 2. 锤线/反转线判定逻辑 // A. 下影线至少是实体的 2 倍 // B. 下影线必须比上影线长 // C. 必须要刺破过支撑线 (low <= dynamic_sup) bool is_hammer_bar = (lower_shadow > body_size * 2) and (lower_shadow > upper_shadow) and (low <= dynamic_sup)
// 原有的区间入场(需严格回调序列) bool range_h1 = (state == 1 and range_test_count[1] == 1 and is_bull and common_entry_filters) bool range_h2 = (state == 1 and range_test_count[1] >= 2 and is_bull and common_entry_filters)
// 整合区间逻辑:满足其一即可 bool is_range_entry = (range_h1 or range_h2 or climax_support_test or is_hammer_bar)
// 趋势入场 bool h1_signal = (state == 2 and bull_count[1] == 1 and is_bull and common_entry_filters ) bool h2_signal = (state == 2 and bull_count[1] >= 2 and is_bull and common_entry_filters ) bool is_trend_entry = (h1_signal or h2_signal)
// 最终入场逻辑 go_long = (state != 3) and (initial_breakout_entry or is_range_entry or is_trend_entry)
// — 7. 订单 — if strategy.position_size == 0 and go_long strategy.entry(“Long_P1”, strategy.long, qty=qty_per_hand, comment=is_range_entry ? “R” : “T”) strategy.entry(“Long_P2”, strategy.long, qty=qty_per_hand, comment=is_range_entry ? “R” : “T”) stop_level := low - atr * 1 tp_p1 := close + (close - stop_level) * risk_reward_ratio last_entry_date := year * 10000 + month * 100 + dayofmonth
// — 8. 离场 — if strategy.position_size > 0 stop_level := math.max(stop_level, low - atr) is_today = (year * 10000 + month * 100 + dayofmonth == last_entry_date) can_exit = t0_enabled or not is_today
if can_exit
if close >= tp_p1
strategy.close("Long_P1", "P1_TP")
if close <= stop_level or close < dynamic_sup
strategy.close_all("Exit_Stop")
// — 9. 画图 — // 绿色=上涨(2), 红色=下跌(3), 灰色=区间(1) color bg_color = state == 2 ? color.new(color.green, 90) : (state == 3 ? color.new(color.red, 90) : color.new(color.gray, 95)) bgcolor(bg_color)
plot(dynamic_res, color=color.blue, title=”Dynamic Resistance”, linewidth=2) plot(dynamic_sup, color=color.red, title=”Dynamic Support”, linewidth=2) plot(strategy.position_size > 0 ? stop_level : na, color=color.orange, linewidth=2, style=plot.style_linebr, title=”Trail Stop”) plot(strategy.position_size > 0 ? tp_p1 : na, color=color.green, linewidth=2, style=plot.style_linebr, title=”P1 TP”)
plotshape(go_long and strategy.position_size == 0, style=shape.triangleup, location=location.belowbar, color=is_range_entry ? color.red : color.green, size=size.small, title=”Entry Marker”)