SUPERMACBOT by The Guardian Forex TV 策略
概览
SUPERMACBOT by The Guardian Forex TV 策略 通过将 MACD 振荡器、双重简单移动平均线趋势过滤器以及跟踪移动平均线结合在一起,复刻了原始 MetaTrader 智能交易系统的思路。转换后的 StockSharp 版本基于已完成的 K 线进行决策,并在多重多空共振出现时发出市价委托。策略完全基于高级 API:使用蜡烛订阅、指标绑定以及参数化配置,便于跨品种、跨周期复用。
交易逻辑
- 数据源:订阅可配置的蜡烛类型(周期),仅在蜡烛收盘后运行逻辑。
- 指标计算:每根蜡烛重新计算 MACD(包含快线、慢线、信号线参数)以及两条简单均线,并额外维护一条用于出场确认的跟踪均线。
- 开仓条件:
- 多头:MACD 柱线向上穿越阈值、快均线在慢均线上方且收盘价位于跟踪均线上方,同时当前无多头仓位;
- 空头:MACD 柱线向下穿越负阈值、快均线在慢均线下方且收盘价位于跟踪均线下方,同时当前无空头仓位。
- 平仓条件:
- 多头:MACD 柱线跌破零值、快均线下穿慢均线或收盘价跌破跟踪均线;
- 空头:MACD 柱线上穿零值、快均线上穿慢均线或收盘价上穿跟踪均线。
- 风控:策略仅维持单向净头寸,不加仓不锁仓;如需止损或仓位控制,可在 StockSharp 中叠加其他风险规则。
参数
| 名称 | 说明 | 默认值 |
|---|---|---|
CandleType |
处理的蜡烛类型(时间框架)。 | 1 分钟 |
FastMaPeriod |
快速简单均线周期。 | 12 |
SlowMaPeriod |
慢速简单均线周期。 | 26 |
MacdFastPeriod |
MACD 快速 EMA 周期。 | 12 |
MacdSlowPeriod |
MACD 慢速 EMA 周期。 | 24 |
MacdSignalPeriod |
MACD 信号 EMA 周期。 | 9 |
HistogramThreshold |
开仓所需的 MACD 柱线最小绝对值。 | 0.0 |
TrailingPeriod |
跟踪简单均线周期。 | 12 |
所有参数均通过 StrategyParam<T> 暴露,可在 StockSharp Designer 中直接调优。
使用提示
- 在加载策略前准备足够的历史数据,确保指标形成后再开始交易;
- 策略基于净头寸运作,可安全地在多品种组合中复用;
- 可结合 StockSharp 风险管理与资金管理组件实现更复杂的止损、止盈与分批处理。
与原版 EA 的差异
- StockSharp 版本采用收盘价驱动的确定性逻辑,而不是 MQL EA 的事件驱动模型;
- 原 EA 中的资金管理与追踪止损逻辑被简化为基于跟踪均线的平仓规则;
- 信号阈值通过 MACD 柱线阈值参数体现,用户可根据需要模拟 MQL 中的权重评分系统。
免责声明
量化交易存在风险。请务必在真实资金投入前充分回测与模拟交易。
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// SUPERMACBOT strategy converted from the MQL expert by The Guardian Forex TV.
/// </summary>
public class SupermacbotByTheGuardianForexTvStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastMaPeriod;
private readonly StrategyParam<int> _slowMaPeriod;
private readonly StrategyParam<int> _macdFastPeriod;
private readonly StrategyParam<int> _macdSlowPeriod;
private readonly StrategyParam<int> _macdSignalPeriod;
private readonly StrategyParam<decimal> _histogramThreshold;
private readonly StrategyParam<int> _trailingPeriod;
/// <summary>
/// Candle type to process.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Fast simple moving average period.
/// </summary>
public int FastMaPeriod
{
get => _fastMaPeriod.Value;
set => _fastMaPeriod.Value = value;
}
/// <summary>
/// Slow simple moving average period.
/// </summary>
public int SlowMaPeriod
{
get => _slowMaPeriod.Value;
set => _slowMaPeriod.Value = value;
}
/// <summary>
/// Fast EMA period for MACD.
/// </summary>
public int MacdFastPeriod
{
get => _macdFastPeriod.Value;
set => _macdFastPeriod.Value = value;
}
/// <summary>
/// Slow EMA period for MACD.
/// </summary>
public int MacdSlowPeriod
{
get => _macdSlowPeriod.Value;
set => _macdSlowPeriod.Value = value;
}
/// <summary>
/// Signal EMA period for MACD.
/// </summary>
public int MacdSignalPeriod
{
get => _macdSignalPeriod.Value;
set => _macdSignalPeriod.Value = value;
}
/// <summary>
/// Minimal absolute histogram value required for new entries.
/// </summary>
public decimal HistogramThreshold
{
get => _histogramThreshold.Value;
set => _histogramThreshold.Value = value;
}
/// <summary>
/// Trailing simple moving average period.
/// </summary>
public int TrailingPeriod
{
get => _trailingPeriod.Value;
set => _trailingPeriod.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="SupermacbotByTheGuardianForexTvStrategy"/>.
/// </summary>
public SupermacbotByTheGuardianForexTvStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to process", "General");
_fastMaPeriod = Param(nameof(FastMaPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
.SetOptimize(5, 30, 1);
_slowMaPeriod = Param(nameof(SlowMaPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
.SetOptimize(10, 60, 1);
_macdFastPeriod = Param(nameof(MacdFastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators")
.SetOptimize(5, 20, 1);
_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 24)
.SetGreaterThanZero()
.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators")
.SetOptimize(18, 40, 1);
_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("MACD Signal", "MACD signal EMA period", "Indicators")
.SetOptimize(3, 15, 1);
_histogramThreshold = Param(nameof(HistogramThreshold), 0m)
.SetDisplay("Histogram Threshold", "Required MACD histogram magnitude", "Logic");
_trailingPeriod = Param(nameof(TrailingPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Trailing SMA", "Trailing SMA period", "Logic")
.SetOptimize(6, 30, 1);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastMa = new SimpleMovingAverage { Length = FastMaPeriod };
var slowMa = new SimpleMovingAverage { Length = SlowMaPeriod };
var trailingMa = new SimpleMovingAverage { Length = TrailingPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, slowMa, trailingMa, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, slowMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastMa, decimal slowMa, decimal trailingMa)
{
if (candle.State != CandleStates.Finished)
return;
if (Position != 0)
return;
var bullishTrend = fastMa > slowMa;
var bearishTrend = fastMa < slowMa;
var price = candle.ClosePrice;
if (bullishTrend && price > trailingMa)
BuyMarket();
else if (bearishTrend && price < trailingMa)
SellMarket();
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class supermacbot_by_the_guardian_forex_tv_strategy(Strategy):
def __init__(self):
super(supermacbot_by_the_guardian_forex_tv_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles to process", "General")
self._fast_ma_period = self.Param("FastMaPeriod", 12) \
.SetGreaterThanZero() \
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_ma_period = self.Param("SlowMaPeriod", 26) \
.SetGreaterThanZero() \
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._macd_fast_period = self.Param("MacdFastPeriod", 12) \
.SetGreaterThanZero() \
.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators")
self._macd_slow_period = self.Param("MacdSlowPeriod", 24) \
.SetGreaterThanZero() \
.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators")
self._macd_signal_period = self.Param("MacdSignalPeriod", 9) \
.SetGreaterThanZero() \
.SetDisplay("MACD Signal", "MACD signal EMA period", "Indicators")
self._histogram_threshold = self.Param("HistogramThreshold", 0.0) \
.SetDisplay("Histogram Threshold", "Required MACD histogram magnitude", "Logic")
self._trailing_period = self.Param("TrailingPeriod", 12) \
.SetGreaterThanZero() \
.SetDisplay("Trailing SMA", "Trailing SMA period", "Logic")
self._is_histogram_initialized = False
self._prev_histogram = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def FastMaPeriod(self):
return self._fast_ma_period.Value
@FastMaPeriod.setter
def FastMaPeriod(self, value):
self._fast_ma_period.Value = value
@property
def SlowMaPeriod(self):
return self._slow_ma_period.Value
@SlowMaPeriod.setter
def SlowMaPeriod(self, value):
self._slow_ma_period.Value = value
@property
def TrailingPeriod(self):
return self._trailing_period.Value
@TrailingPeriod.setter
def TrailingPeriod(self, value):
self._trailing_period.Value = value
def OnReseted(self):
super(supermacbot_by_the_guardian_forex_tv_strategy, self).OnReseted()
self._is_histogram_initialized = False
self._prev_histogram = 0.0
def OnStarted2(self, time):
super(supermacbot_by_the_guardian_forex_tv_strategy, self).OnStarted2(time)
fast_ma = SimpleMovingAverage()
fast_ma.Length = self.FastMaPeriod
slow_ma = SimpleMovingAverage()
slow_ma.Length = self.SlowMaPeriod
trailing_ma = SimpleMovingAverage()
trailing_ma.Length = self.TrailingPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ma, slow_ma, trailing_ma, self._process_candle).Start()
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(1, UnitTypes.Percent))
def _process_candle(self, candle, fast_ma, slow_ma, trailing_ma):
if candle.State != CandleStates.Finished:
return
if self.Position != 0:
return
fma = float(fast_ma)
sma_val = float(slow_ma)
tma = float(trailing_ma)
price = float(candle.ClosePrice)
bullish_trend = fma > sma_val
bearish_trend = fma < sma_val
if bullish_trend and price > tma:
self.BuyMarket()
elif bearish_trend and price < tma:
self.SellMarket()
def CreateClone(self):
return supermacbot_by_the_guardian_forex_tv_strategy()