在 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);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergence
from StockSharp.Algo.Strategies import Strategy
class macd_sample_hedging_grid_strategy(Strategy):
def __init__(self):
super(macd_sample_hedging_grid_strategy, self).__init__()
self._macd = None
self._prev_macd = None
def OnReseted(self):
super(macd_sample_hedging_grid_strategy, self).OnReseted()
self._macd = None
self._prev_macd = None
def OnStarted2(self, time):
super(macd_sample_hedging_grid_strategy, self).OnStarted2(time)
self._macd = MovingAverageConvergenceDivergence()
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._macd, self._process_candle)
subscription.Start()
def _process_candle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
if not self._macd.IsFormed:
return
macd_line = float(macd_value)
if self._prev_macd is not None:
if self._prev_macd <= 0.0 and macd_line > 0.0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_macd >= 0.0 and macd_line < 0.0 and self.Position >= 0:
self.SellMarket()
self._prev_macd = macd_line
def CreateClone(self):
return macd_sample_hedging_grid_strategy()