TradingView PineScript策略订单偶发无法成交问题求助
偶发订单未成交问题排查请求
我开发了一款TradingView策略,核心逻辑如下:
- 等待特定触发信号后发送入场订单
- 订单成交后自动进行交易管理
- 未成交则在1根K线后取消订单(模拟1天订单有效期)
我为每个订单分配了唯一ID,避免Broker Simulator混淆,且pyramiding设置大于1。曾开启bar magnifier,关闭后问题依旧。
多数场景策略运行正常,但存在偶发异常:入场订单已正确创建,下一根K线视觉上已触及入场价位(上布林带,十字光标已定位至该价位),但订单未成交并于1根K线后被取消。尝试改用市价单,仍无法成交。
策略代码
//@version=6 strategy("BB + MACD Trend/Contra Strategy", overlay=true, default_qty_type=strategy.percent_of_equity) // === INPUTS === use_trend = input.bool(true, title="Enable Trend Strategy") use_contra = input.bool(true, title="Enable Contra Strategy") log_enabled = input.bool(true, title="Enable Logging") capital_risk_percent = input.float(1.0, minval=0.1, maxval=10.0, title="Risk % of Equity per Trade") bb_len = input.int(20, title="BB Length") bb_mult = input.float(2.0, title="BB Multiplier") macd_src = input.source(close, title="MACD Source") fast_len = input.int(12, title="MACD Fast Length") slow_len = input.int(26, title="MACD Slow Length") signal_len = input.int(9, title="MACD Signal Length") // === CALCULATIONS === basis = ta.sma(close, bb_len) stddev = ta.stdev(close, bb_len) upper_bb = basis + bb_mult * stddev lower_bb = basis - bb_mult * stddev macd_line = ta.ema(macd_src, fast_len) - ta.ema(macd_src, slow_len) signal_line = ta.ema(macd_line, signal_len) trendUp = macd_line > 0 and macd_line > signal_line trendDown = macd_line < 0 and macd_line < signal_line white_bg = not trendUp and not trendDown first_colored = not (trendUp[1] or trendDown[1]) and (trendUp or trendDown) trend_entry_long = trendUp and close < upper_bb trend_entry_short = trendDown and close > lower_bb valid_contra_bar = white_bg or first_colored bgcolor(trendUp ? color.new(color.green, 90) : trendDown ? color.new(color.red, 90) : na) plot(basis, "BB Basis", color=color.blue) plot(upper_bb, "BB Upper", color=color.red) plot(lower_bb, "BB Lower", color=color.green) // === STATE VARIABLES === var string active_id = na var float entry_price = na var float active_tp = na var float active_sl = na var float active_risk = na var float initial_risk = na var bool active_is_short = false var int barindex_entryorder = na var bool entry_pending = false // === ORDER SETUP === if strategy.opentrades == 0 and not entry_pending capital_at_risk = strategy.equity * capital_risk_percent / 100 if use_contra and valid_contra_bar and close > upper_bb active_id := "Contra Down" entry_price := upper_bb active_tp := basis active_risk := math.abs(entry_price - active_tp) active_sl := entry_price + active_risk active_is_short := true qty = active_risk > 0 ? capital_at_risk / active_risk : 0 strategy.entry(active_id, strategy.short, qty=qty, stop=entry_price) strategy.exit("TP " + active_id, from_entry=active_id, limit=active_tp) strategy.exit("SL " + active_id, from_entry=active_id, stop=active_sl) barindex_entryorder := bar_index entry_pending := true if log_enabled log.info("Order Placed\nID: " + active_id + "\nEntry: " + str.tostring(entry_price, "#.##") + "\nTP: " + str.tostring(active_tp, "#.##") + "\nSL: " + str.tostring(active_sl, "#.##") + "\nRisk: " + str.tostring(active_risk, "#.##") + "\nQty: " + str.tostring(qty, "#.##")) if use_contra and valid_contra_bar and close < lower_bb active_id := "Contra Up" entry_price := lower_bb active_tp := basis active_risk := math.abs(entry_price - active_tp) active_sl := entry_price - active_risk active_is_short := false qty = active_risk > 0 ? capital_at_risk / active_risk : 0 strategy.entry(active_id, strategy.long, qty=qty, stop=entry_price) strategy.exit("TP " + active_id, from_entry=active_id, limit=active_tp) strategy.exit("SL " + active_id, from_entry=active_id, stop=active_sl) barindex_entryorder := bar_index entry_pending := true if log_enabled log.info("Order Placed\nID: " + active_id + "\nEntry: " + str.tostring(entry_price, "#.##") + "\nTP: " + str.tostring(active_tp, "#.##") + "\nSL: " + str.tostring(active_sl, "#.##") + "\nRisk: " + str.tostring(active_risk, "#.##") + "\nQty: " + str.tostring(qty, "#.##")) // === ENTRY-FILL TRACKING === if entry_pending and strategy.opentrades > 0 entry_price := strategy.opentrades.entry_price(0) active_tp := active_is_short ? basis : basis active_risk := math.abs(entry_price - active_tp) active_sl := active_is_short ? entry_price + active_risk : entry_price - active_risk initial_risk := active_risk strategy.exit("TP " + active_id, from_entry=active_id, limit=active_tp) strategy.exit("SL " + active_id, from_entry=active_id, stop=active_sl) entry_pending := false if log_enabled log.info("Order filled\nID: " + active_id + "\nEntry = " + str.tostring(entry_price, "#.##") + "\nSL = " + str.tostring(active_sl, "#.##") + "\nTP = " + str.tostring(active_tp, "#.##")) if entry_pending and bar_index > barindex_entryorder + 1 and strategy.opentrades == 0 entry_pending := false active_id := na entry_price := na active_sl := na active_tp := na active_risk := na barindex_entryorder := na if log_enabled log.info("Order expired – no fill\nBar: " + str.tostring(bar_index)) // === TRADE MANAGEMENT === if strategy.opentrades > 0 and not na(entry_price) if active_id == "Contra Up" or active_id == "Contra Down" new_tp = basis new_risk = math.abs(entry_price - new_tp) new_sl = active_is_short ? entry_price + new_risk : entry_price - new_risk if new_risk < active_risk active_tp := new_tp active_sl := new_sl active_risk := new_risk strategy.exit("TP " + active_id, from_entry=active_id, limit=active_tp) strategy.exit("SL " + active_id, from_entry=active_id, stop=active_sl) if log_enabled log.info("Trade Mgmt\nID: " + active_id + "\nTP: " + str.tostring(active_tp, "#.##") + "\nSL: " + str.tostring(active_sl, "#.##") + "\nRisk: " + str.tostring(active_risk, "#.##")) if (active_is_short and active_tp >= entry_price) or (not active_is_short and active_tp <= entry_price) strategy.close(active_id) if log_enabled log.info("Closed by Basis\nID: " + active_id + "\nReason: Basis >= Entry") active_id := na entry_price := na active_tp := na active_sl := na active_risk := na initial_risk := na // === EXIT LABEL === if strategy.opentrades == 0 and not na(active_id) entry = strategy.closedtrades.entry_price(strategy.closedtrades - 1) exit = strategy.closedtrades.exit_price(strategy.closedtrades - 1) r = math.abs(entry - initial_risk > 0 ? initial_risk : 1) r_mult = (exit - entry) / r * (active_is_short ? -1 : 1) label_color = r_mult >= 0 ? color.green : color.red label_text = (r_mult >= 0 ? "TP" : "SL") + " " + active_id + " " + str.tostring(r_mult, format.percent) label.new(strategy.closedtrades.exit_bar_index(strategy.closedtrades - 1), exit, label_text, style=label.style_label_left, color=label_color, textcolor=color.white, size=size.normal) if log_enabled log.info("Trade Closed\nID: " + active_id + "\nR: " + str.tostring(r_mult, "#.##") + "\nEntry: " + str.tostring(entry, "#.##") + "\nExit: " + str.tostring(exit, "#.##") + "\nRisk: " + str.tostring(r, "#.##")) active_id := na entry_price := na active_sl := na active_tp := na active_risk := na initial_risk := na barindex_entryorder := na // === PLOT MARKERS === plotshape(active_id == "Contra Down" and strategy.opentrades > 0 and use_contra ? active_sl : na, title="SL Contra Down", style=shape.triangleup, location=location.absolute, color=color.red, size=size.tiny) plotshape(active_id == "Contra Down" and strategy.opentrades > 0 and use_contra ? active_tp : na, title="TP Contra Down", style=shape.triangledown, location=location.absolute, color=color.green, size=size.tiny) plotshape(active_id == "Contra Up" and strategy.opentrades > 0 and use_contra ? active_sl : na, title="SL Contra Up", style=shape.triangleup, location=location.absolute, color=color.red, size=size.tiny) plotshape(active_id == "Contra Up" and strategy.opentrades > 0 and use_contra ? active_tp : na, title="TP Contra Up", style=shape.triangledown, location=location.absolute, color=color.green, size=size.tiny)
相关场景说明
- 异常场景:EUR/USD 10月23日,收盘价上穿布林带触发入场,订单已创建但未成交
- 配置截图:展示当前策略的参数设置界面
可能的问题原因及排查方向
- 订单触发逻辑的价格跳空:TradingView止损单触发条件是下一根K线价格触及或穿过止损价,若下一根K线开盘价直接跳过止损价(比如做空单的止损价是上布林带,开盘价高于该价位),订单不会触发。需检查异常场景下K线的开盘价与止损价的关系。
- 布林带计算的周期匹配问题:当前用
close计算布林带,若回测时K线周期与预期的“1天”不匹配(比如实际用1小时K线,订单过期逻辑是2小时而非1天),会导致视觉与实际逻辑不符。需确认K线周期设置。 - 市价单的成交限制:策略模拟器中市价单以下一根K线开盘价成交,若滑点、手续费设置过高,或开盘价导致权益不足以开仓,会导致订单无法成交。需检查策略设置中的滑点、手续费参数。
- 状态变量重置不彻底:
entry_pending等状态变量在订单过期后是否正确重置?若某些场景下变量未重置,会导致后续订单逻辑异常。可在日志中增加状态变量打印,确认重置情况。 - 订单ID与exit命名冲突:虽用
active_id区分订单,但strategy.exit的命名是否唯一?若重复会导致订单被覆盖。可检查日志中的订单ID与exit名称是否对应。
内容的提问来源于stack exchange,提问作者user30449074
相关产品推荐
相关产品推荐

