//@version=5 strategy("Pinbar Basic Strategy (1:1 RR)", overlay=true, initial_capital=10000, calc_on_every_tick=false, pyramiding=0) // ===== 参数 ===== pinbarBodyRatio = input.float(0.30, "PinbarBodyRatio", minval=0, maxval=1.0) pinbarShadowRatio = input.float(0.60, "PinbarShadowRatio", minval=0, maxval=1.0) minPinbarLengthPts = input.int(10, "MinPinbarLength(Points)", minval=0) qty = input.float(1.0, "Order Qty", minval=0.0, step=0.1) minVolume = input.float(500, "Min Volume to Trade", minval=0) // ===== 识别上一根K线 Pinbar ===== o1 = open[1] h1 = high[1] l1 = low[1] c1 = close[1] totalLen = h1 - l1 bodySize = math.abs(c1 - o1) isBearish = o1 > c1 upperShadow = isBearish ? (h1 - o1) : (h1 - c1) lowerShadow = isBearish ? (c1 - l1) : (o1 - l1) // 最小长度:点数 * 最小跳动 minLen = minPinbarLengthPts * syminfo.mintick validLen = totalLen > 0 and totalLen >= minLen bodyOk = validLen and (bodySize / totalLen) <= pinbarBodyRatio shadowOk = validLen and (math.max(upperShadow, lowerShadow) / totalLen) >= pinbarShadowRatio isBullPinbar1 = shadowOk and bodyOk and (lowerShadow > upperShadow) isBearPinbar1 = shadowOk and bodyOk and (upperShadow > lowerShadow) isPinbar1 = validLen and bodyOk and shadowOk and (lowerShadow != upperShadow) // ===== 标注(偏移到上一根K线位置) ===== plotshape(isBullPinbar1, title="Bull Pinbar", style=shape.triangleup, color=color.new(color.lime, 0), size=size.tiny, location=location.belowbar, offset=1, text="BP") plotshape(isBearPinbar1, title="Bear Pinbar", style=shape.triangledown, color=color.new(color.red, 0), size=size.tiny, location=location.abovebar, offset=1, text="SP") // ===== 只在新出现的上一根 Pinbar 时触发一次(兼容历史与实时) ===== var int lastPinbarTime = na newSignal = isPinbar1 and (na(lastPinbarTime) or lastPinbarTime != time[1]) volOk = volume > minVolume longSignal = newSignal and isBullPinbar1 and volOk shortSignal = newSignal and isBearPinbar1 and volOk // ===== 1:1 RR 止损/止盈 ===== // 入场使用当前K线的开盘/市价(由策略托管),SL 基于上一根 Pinbar 极点,TP 与入场到 SL 的距离相等 if longSignal // 多:SL = pinbar低点 longSL = l1 // 预估入场价:用当前bar开盘价(更接近实际回测表现) entryPriceLong = open riskLong = math.max(entryPriceLong - longSL, syminfo.mintick) longTP = entryPriceLong + riskLong strategy.entry("Long", strategy.long, qty=qty) strategy.exit("Long-Exit", "Long", stop=longSL, limit=longTP) lastPinbarTime := time[1] if shortSignal // 空:SL = pinbar高点 shortSL = h1 entryPriceShort = open riskShort = math.max(shortSL - entryPriceShort, syminfo.mintick) shortTP = entryPriceShort - riskShort strategy.entry("Short", strategy.short, qty=qty) strategy.exit("Short-Exit", "Short", stop=shortSL, limit=shortTP) lastPinbarTime := time[1]