//@version=6 strategy(title="EMA+MACD 趋势跟踪策略", shorttitle="EMA+MACD策略", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10, initial_capital=100000, commission_type=strategy.commission.percent, commission_value=0.1, pyramiding=0, calc_on_every_tick=false) // ========================= 策略参数 ========================= // 交易方向 trade_direction = input.string("双向交易", "交易方向", options=["只做多", "只做空", "双向交易"], group="策略设置") // 止损止盈 use_sl = input.bool(true, "启用止损", group="风控设置") sl_pct = input.float(3.0, "止损比例(%)", minval=0.5, maxval=20, step=0.5, group="风控设置") use_tp = input.bool(true, "启用止盈", group="风控设置") tp_pct = input.float(6.0, "止盈比例(%)", minval=1, maxval=50, step=0.5, group="风控设置") // 平仓逻辑:趋势结束即平仓 // 移动止损 use_trailing = input.bool(false, "启用移动止损", group="风控设置") trail_pct = input.float(2.0, "移动止损比例(%)", minval=0.5, maxval=10, step=0.5, group="风控设置") // ========================= EMA 参数 ========================= ema1_len = input.int(9, "EMA1 快线周期", minval=1, group="EMA设置") ema2_len = input.int(21, "EMA2 中线周期", minval=1, group="EMA设置") ema3_len = input.int(55, "EMA3 慢线周期", minval=1, group="EMA设置") ema4_len = input.int(200, "EMA4 超慢线周期", minval=1, group="EMA设置") use_ema4 = input.bool(true, "启用第4条均线(EMA200)", group="EMA设置") // ========================= MACD 参数 ========================= macd_fast = input.int(12, "MACD快线周期", minval=1, group="MACD设置") macd_slow = input.int(26, "MACD慢线周期", minval=1, group="MACD设置") macd_signal = input.int(9, "MACD信号线周期", minval=1, group="MACD设置") // ========================= 趋势判断参数 ========================= ema_spread_thresh = input.float(0.3, "EMA收束阈值(%)", minval=0.1, maxval=2.0, step=0.1, group="趋势判断") / 100 macd_zero_zone = input.float(0.1, "MACD零轴区域(%)", minval=0.01, maxval=0.5, step=0.01, group="趋势判断") / 100 confirm_bars = input.int(2, "趋势确认周期", minval=1, maxval=5, group="趋势判断") // ========================= 显示设置 ========================= show_ema = input.bool(true, "显示EMA线", group="显示设置") show_background = input.bool(true, "背景着色", group="显示设置") show_signals = input.bool(true, "显示趋势笔", group="显示设置") // ========================= 颜色设置 ========================= col_uptrend = color.new(color.teal, 80) col_downtrend = color.new(color.red, 80) col_consolidation = color.new(color.gray, 85) // ========================= 指标计算 ========================= // EMA计算 ema1 = ta.ema(close, ema1_len) ema2 = ta.ema(close, ema2_len) ema3 = ta.ema(close, ema3_len) ema4 = use_ema4 ? ta.ema(close, ema4_len) : na // MACD计算 [macdLine, signalLine, histLine] = ta.macd(close, macd_fast, macd_slow, macd_signal) macd_normalized = macdLine / close // ========================= EMA排列判断 ========================= bull_alignment_3 = ema1 > ema2 and ema2 > ema3 bull_alignment = use_ema4 ? (bull_alignment_3 and ema3 > ema4) : bull_alignment_3 bear_alignment_3 = ema1 < ema2 and ema2 < ema3 bear_alignment = use_ema4 ? (bear_alignment_3 and ema3 < ema4) : bear_alignment_3 // EMA方向 ema1_rising = ema1 > ema1[1] ema2_rising = ema2 > ema2[1] ema3_rising = ema3 > ema3[1] ema4_rising = use_ema4 ? ema4 > ema4[1] : true ema1_falling = ema1 < ema1[1] ema2_falling = ema2 < ema2[1] ema3_falling = ema3 < ema3[1] ema4_falling = use_ema4 ? ema4 < ema4[1] : true all_rising = ema1_rising and ema2_rising and ema3_rising and (not use_ema4 or ema4_rising) all_falling = ema1_falling and ema2_falling and ema3_falling and (not use_ema4 or ema4_falling) // EMA收束 max_ema = math.max(math.max(ema1, ema2), ema3) min_ema = math.min(math.min(ema1, ema2), ema3) ema_spread = (max_ema - min_ema) / close emas_converged = ema_spread < ema_spread_thresh // ========================= MACD状态判断 ========================= macd_bullish = macdLine > signalLine macd_bearish = macdLine < signalLine macd_above_zero = macdLine > 0 macd_below_zero = macdLine < 0 macd_near_zero = math.abs(macd_normalized) < macd_zero_zone hist_shrinking = math.abs(histLine) < math.abs(histLine[1]) // MACD评分 macd_score = 0 macd_score := macd_bullish ? macd_score + 1 : macd_score - 1 macd_score := macd_above_zero ? macd_score + 1 : macd_below_zero ? macd_score - 1 : macd_score // ========================= 综合趋势判断 ========================= price_above_emas = close > ema1 and close > ema2 and close > ema3 uptrend_ema = bull_alignment or (all_rising and price_above_emas) uptrend_macd = macd_score >= 1 or (macd_bullish and not macd_near_zero) uptrend_raw = uptrend_ema and uptrend_macd price_below_emas = close < ema1 and close < ema2 and close < ema3 downtrend_ema = bear_alignment or (all_falling and price_below_emas) downtrend_macd = macd_score <= -1 or (macd_bearish and not macd_near_zero) downtrend_raw = downtrend_ema and downtrend_macd consolidation_ema = emas_converged or (not bull_alignment and not bear_alignment) consolidation_macd = macd_near_zero or hist_shrinking consolidation_raw = (consolidation_ema and consolidation_macd) or (not uptrend_raw and not downtrend_raw) // ========================= 连续确认计数 ========================= var int uptrend_count = 0 var int downtrend_count = 0 var int consolidation_count = 0 uptrend_count := uptrend_raw ? uptrend_count + 1 : 0 downtrend_count := downtrend_raw ? downtrend_count + 1 : 0 consolidation_count := consolidation_raw ? consolidation_count + 1 : 0 uptrend_confirmed = uptrend_count >= confirm_bars downtrend_confirmed = downtrend_count >= confirm_bars consolidation_confirmed = consolidation_count >= confirm_bars // ========================= 状态机 ========================= var int trend_state = 0 prev_state = nz(trend_state[1], 0) int new_state = prev_state if prev_state == 0 if uptrend_confirmed new_state := 1 else if downtrend_confirmed new_state := -1 else if prev_state == 1 if downtrend_confirmed new_state := -1 else if consolidation_confirmed and not uptrend_raw new_state := 0 else if prev_state == -1 if uptrend_confirmed new_state := 1 else if consolidation_confirmed and not downtrend_raw new_state := 0 trend_state := barstate.isconfirmed ? new_state : prev_state // 状态切换信号 entered_up = barstate.isconfirmed and trend_state == 1 and prev_state != 1 entered_down = barstate.isconfirmed and trend_state == -1 and prev_state != -1 entered_consolidation = barstate.isconfirmed and trend_state == 0 and prev_state != 0 exit_up = barstate.isconfirmed and prev_state == 1 and trend_state != 1 exit_down = barstate.isconfirmed and prev_state == -1 and trend_state != -1 // ========================= 交易逻辑 ========================= // 做多条件 can_long = trade_direction == "只做多" or trade_direction == "双向交易" can_short = trade_direction == "只做空" or trade_direction == "双向交易" // 开仓信号 long_signal = entered_up and can_long short_signal = entered_down and can_short // 平仓信号:趋势结束即平仓 close_long_signal = exit_up // 上涨趋势结束 → 平多仓 close_short_signal = exit_down // 下跌趋势结束 → 平空仓 // 止损止盈价格 long_sl = use_sl ? strategy.position_avg_price * (1 - sl_pct / 100) : na long_tp = use_tp ? strategy.position_avg_price * (1 + tp_pct / 100) : na short_sl = use_sl ? strategy.position_avg_price * (1 + sl_pct / 100) : na short_tp = use_tp ? strategy.position_avg_price * (1 - tp_pct / 100) : na // 执行交易 if long_signal strategy.entry("做多", strategy.long) if short_signal strategy.entry("做空", strategy.short) // 平仓 if close_long_signal and strategy.position_size > 0 strategy.close("做多", comment="趋势结束") if close_short_signal and strategy.position_size < 0 strategy.close("做空", comment="趋势结束") // 止损止盈 if strategy.position_size > 0 if use_trailing strategy.exit("多头止损止盈", "做多", stop=long_sl, limit=long_tp, trail_points=close * trail_pct / 100 / syminfo.mintick, trail_offset=close * trail_pct / 100 / syminfo.mintick) else strategy.exit("多头止损止盈", "做多", stop=long_sl, limit=long_tp) if strategy.position_size < 0 if use_trailing strategy.exit("空头止损止盈", "做空", stop=short_sl, limit=short_tp, trail_points=close * trail_pct / 100 / syminfo.mintick, trail_offset=close * trail_pct / 100 / syminfo.mintick) else strategy.exit("空头止损止盈", "做空", stop=short_sl, limit=short_tp) // ========================= 可视化 ========================= // 绘制EMA线 plot(show_ema ? ema1 : na, "EMA1 快线", color=color.new(color.red, 30), linewidth=1) plot(show_ema ? ema2 : na, "EMA2 中线", color=color.new(color.orange, 30), linewidth=1) plot(show_ema ? ema3 : na, "EMA3 慢线", color=color.new(color.blue, 30), linewidth=2) plot(show_ema and use_ema4 ? ema4 : na, "EMA4 超慢线", color=color.new(color.purple, 30), linewidth=2) // 背景着色 bg_color = trend_state == 1 ? col_uptrend : trend_state == -1 ? col_downtrend : col_consolidation bgcolor(show_background ? bg_color : na, title="趋势背景") // ========================= 类缠论笔的绘制 ========================= trend_line_width = input.int(2, "趋势笔宽度", minval=1, maxval=5, group="显示设置") var int up_start_bar = na var float up_start_price = na var int down_start_bar = na var float down_start_price = na // 上涨趋势开始 - 记录起点 if entered_up up_start_bar := bar_index up_start_price := low // 上涨趋势结束 - 画笔(终点 = 结束时的K线) if exit_up and show_signals and not na(up_start_bar) line.new(up_start_bar, up_start_price, bar_index, close, color=color.teal, width=trend_line_width, style=line.style_solid) // 下跌趋势开始 - 记录起点 if entered_down down_start_bar := bar_index down_start_price := high // 下跌趋势结束 - 画笔(终点 = 结束时的K线) if exit_down and show_signals and not na(down_start_bar) line.new(down_start_bar, down_start_price, bar_index, close, color=color.red, width=trend_line_width, style=line.style_solid) // 当前进行中的笔(实时显示) var line current_up_line = na var line current_down_line = na if show_signals if not na(current_up_line) line.delete(current_up_line) if not na(current_down_line) line.delete(current_down_line) // 上涨中 - 画到当前K线 if trend_state == 1 and not na(up_start_bar) current_up_line := line.new(up_start_bar, up_start_price, bar_index, close, color=color.new(color.teal, 40), width=trend_line_width, style=line.style_dotted) // 下跌中 - 画到当前K线 if trend_state == -1 and not na(down_start_bar) current_down_line := line.new(down_start_bar, down_start_price, bar_index, close, color=color.new(color.red, 40), width=trend_line_width, style=line.style_dotted) // ========================= 信息面板 ========================= var table info_table = table.new(position.top_right, 2, 8, bgcolor=color.new(color.black, 80), border_width=1) if barstate.islast table.cell(info_table, 0, 0, "EMA+MACD策略", text_color=color.white, bgcolor=color.new(color.gray, 60), text_size=size.small) table.cell(info_table, 1, 0, "", bgcolor=color.new(color.gray, 60)) state_text = trend_state == 1 ? "📈 上涨" : trend_state == -1 ? "📉 下跌" : "📊 盘整" state_color = trend_state == 1 ? color.teal : trend_state == -1 ? color.red : color.gray table.cell(info_table, 0, 1, "趋势状态", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 1, state_text, text_color=state_color, text_size=size.small) pos_text = strategy.position_size > 0 ? "多头持仓" : strategy.position_size < 0 ? "空头持仓" : "空仓" pos_color = strategy.position_size > 0 ? color.teal : strategy.position_size < 0 ? color.red : color.gray table.cell(info_table, 0, 2, "持仓状态", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 2, pos_text, text_color=pos_color, text_size=size.small) if strategy.position_size != 0 table.cell(info_table, 0, 3, "入场价", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 3, str.tostring(strategy.position_avg_price, "#.##"), text_color=color.white, text_size=size.small) pnl_pct = (close - strategy.position_avg_price) / strategy.position_avg_price * 100 * (strategy.position_size > 0 ? 1 : -1) pnl_color = pnl_pct > 0 ? color.teal : color.red table.cell(info_table, 0, 4, "浮动盈亏", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 4, str.tostring(pnl_pct, "#.##") + "%", text_color=pnl_color, text_size=size.small) if use_sl sl_price = strategy.position_size > 0 ? long_sl : short_sl table.cell(info_table, 0, 5, "止损价", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 5, str.tostring(sl_price, "#.##"), text_color=color.red, text_size=size.small) if use_tp tp_price = strategy.position_size > 0 ? long_tp : short_tp table.cell(info_table, 0, 6, "止盈价", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 6, str.tostring(tp_price, "#.##"), text_color=color.teal, text_size=size.small) table.cell(info_table, 0, 7, "总交易次数", text_color=color.white, text_size=size.small) table.cell(info_table, 1, 7, str.tostring(strategy.closedtrades), text_color=color.white, text_size=size.small) // ========================= 策略说明 ========================= // 【EMA+MACD 趋势跟踪策略】 // // 交易逻辑: // 1. 上涨趋势确认时 → 开多仓 // 2. 下跌趋势确认时 → 开空仓(或平多仓) // 3. 进入盘整时 → 根据设置决定是否平仓 // // 风控设置: // - 止损:默认3%,可自定义 // - 止盈:默认6%,可自定义 // - 移动止损:可选开启 // // 交易方向: // - 只做多:仅在上涨趋势开仓 // - 只做空:仅在下跌趋势开仓 // - 双向交易:趋势转换时反向开仓