在 GitHub 上查看

MACD Sample Hedging Grid 策略

概述

该策略是 MetaTrader "MACD Sample Hedging Grid" 智能交易系统的 StockSharp 移植版本。策略将短周期 MACD 金叉/死叉、局部 EMA 斜率过滤以及更高周期的确认信号结合在一起。当多个条件同时满足时,会沿着信号方向建立网格仓位,并按照可配置的指数因子逐步放大手数。

交易逻辑

  • 基础周期: 可配置(默认 5 分钟 K 线)。
  • 趋势过滤: EMA(默认 26 周期)必须上行才允许做多,下行才允许做空。
  • MACD 触发: 基础周期内 MACD 主线需要与信号线交叉,并且绝对值大于指定阈值(以报价最小变动单位计)。
  • 动量确认: 在更高周期上,Momentum 指标与 100 的偏离值需要超过多空各自的阈值。策略检查最近三根高周期 K 线,与原始 EA 的逻辑一致。
  • 长周期确认: 在更长周期(默认近似月线)上计算的 MACD 必须支持当前方向(多头时主线高于信号线,空头则低于信号线)。

当满足条件时,策略会在对应方向开启新的网格或向已有网格加仓,直到达到最大入场次数。

仓位管理

  • 网格加仓: 每次加仓的手数等于初始手数乘以 LotExponent(默认 1.44)。当方向改变或持仓清零时,放大计数会被重置。
  • 风险控制: 可选的止损/止盈距离会转换为 StockSharp 的保护性订单,并以最小报价变动单位表示。
  • 方向切换: 出现反向信号时,会先平掉当前仓位,再按新方向重新建立网格。

参数

名称 说明 默认值
CandleType 计算 MACD 和 EMA 的基础周期。 5 分钟
MomentumCandleType 用于动量确认的高周期。 30 分钟
TrendCandleType 用于趋势 MACD 过滤的长周期。 30 天
FastMaPeriod MACD 快速 EMA 周期。 12
SlowMaPeriod MACD 慢速 EMA 周期。 26
SignalPeriod MACD 信号线周期。 9
TrendMaPeriod 局部趋势 EMA 周期。 26
MomentumPeriod Momentum 指标周期。 14
MacdOpenLevel 入场所需的 MACD 最小绝对值(以最小变动单位计)。 3
MomentumBuyThreshold 做多时 Momentum 偏离 100 的最小值。 0.3
MomentumSellThreshold 做空时 Momentum 偏离 100 的最小值。 0.3
MaxTrades 同方向允许的最大入场次数。 10
LotExponent 每次加仓使用的手数乘数。 1.44
StopLossSteps 止损距离(最小变动单位)。 20
TakeProfitSteps 止盈距离(最小变动单位)。 50

说明

  • 原 EA 中的资金止盈/止损、移动保本等功能依赖账户权益数据和手工订单管理,在本次高层封装中未实现。
  • 策略使用 StockSharp 的高层 API 完成 K 线订阅、指标绑定和交易执行。
  • 运行前请确认所选品种具备所有相关周期的历史数据,否则指标将无法形成有效信号。
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// MACD Sample Hedging Grid: MACD crossover with grid-like position management.
/// </summary>
public class MacdSampleHedgingGridStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public MacdSampleHedgingGridStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var macd = new MovingAverageConvergenceDivergence();

		decimal? prevMacd = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(macd, (candle, macdLine) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevMacd.HasValue)
				{
					if (prevMacd.Value <= 0 && macdLine > 0 && Position <= 0)
						BuyMarket();
					else if (prevMacd.Value >= 0 && macdLine < 0 && Position >= 0)
						SellMarket();
				}

				prevMacd = macdLine;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}
}