在 GitHub 上查看

Cyberia Trader 策略

该策略是原始 CyberiaTrader.mq5 的 StockSharp 简化版。它结合多个经典技术指标来评估市场方向,并在多数过滤器一致时开仓。

指标

  • MACD – 通过快慢 EMA 与信号线识别动量变化。
  • 简单移动平均线 – 判断主要趋势方向。
  • 商品通道指数 (CCI) – 监测超买和超卖区域。
  • 平均趋向指数 (ADX) – 通过 +DI 和 -DI 组件确认趋势强度。

参数

名称 说明
MacdFast MACD 快速 EMA 周期。
MacdSlow MACD 慢速 EMA 周期。
MacdSignal MACD 信号线周期。
MaPeriod 移动平均线长度。
CciPeriod CCI 周期。
AdxPeriod ADX 周期。
EnableMacd 启用/禁用 MACD 过滤器。
EnableMa 启用/禁用移动平均过滤器。
EnableCci 启用/禁用 CCI 过滤器。
EnableAdx 启用/禁用 ADX 过滤器。
CandleType 输入 K 线的时间框架。

交易逻辑

  1. 每根完成的 K 线都会计算所有已启用指标的数值。
  2. 各过滤器根据规则阻止多头或空头:
    • MACD 高于信号线阻止做空,低于阻止做多。
    • 价格高于均线阻止做空,低于阻止做多。
    • CCI 高于 +100 阻止做多,低于 -100 阻止做空。
    • +DI 大于 -DI 阻止做空,-DI 大于 +DI 阻止做多。
  3. 只有当一侧允许且另一侧被阻止时才开仓。
  4. 使用 2% 止盈与 1% 止损作为基础风险控制。

备注

此移植仅保留原策略的核心方向过滤器,MQL5 版本中复杂的概率分析和辅助模块为简化起见未被包含。

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;

using StockSharp.Algo;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simplified conversion of the CyberiaTrader MQL5 strategy.
/// Combines MACD, MA, CCI, and ADX filters to determine market direction.
/// </summary>
public class CyberiaTraderStrategy : Strategy
{
	private readonly StrategyParam<int> _macdFast;
	private readonly StrategyParam<int> _macdSlow;
	private readonly StrategyParam<int> _macdSignal;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<int> _adxPeriod;
	private readonly StrategyParam<bool> _enableMacd;
	private readonly StrategyParam<bool> _enableMa;
	private readonly StrategyParam<bool> _enableCci;
	private readonly StrategyParam<bool> _enableAdx;
	private readonly StrategyParam<DataType> _candleType;
	
	private MovingAverageConvergenceDivergenceSignal _macd;
	private SimpleMovingAverage _ma;
	private CommodityChannelIndex _cci;
	private AverageDirectionalIndex _adx;
	private int _lastDirection;
	
	/// <summary>
	/// MACD fast EMA period.
	/// </summary>
	public int MacdFast { get => _macdFast.Value; set => _macdFast.Value = value; }
	
	/// <summary>
	/// MACD slow EMA period.
	/// </summary>
	public int MacdSlow { get => _macdSlow.Value; set => _macdSlow.Value = value; }
	
	/// <summary>
	/// MACD signal line period.
	/// </summary>
	public int MacdSignal { get => _macdSignal.Value; set => _macdSignal.Value = value; }
	
	/// <summary>
	/// Moving average length.
	/// </summary>
	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	
	/// <summary>
	/// Commodity Channel Index length.
	/// </summary>
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	
	/// <summary>
	/// ADX calculation length.
	/// </summary>
	public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
	
	/// <summary>
	/// Enable MACD filter.
	/// </summary>
	public bool EnableMacd { get => _enableMacd.Value; set => _enableMacd.Value = value; }
	
	/// <summary>
	/// Enable moving average filter.
	/// </summary>
	public bool EnableMa { get => _enableMa.Value; set => _enableMa.Value = value; }
	
	/// <summary>
	/// Enable CCI filter.
	/// </summary>
	public bool EnableCci { get => _enableCci.Value; set => _enableCci.Value = value; }
	
	/// <summary>
	/// Enable ADX filter.
	/// </summary>
	public bool EnableAdx { get => _enableAdx.Value; set => _enableAdx.Value = value; }
	
	/// <summary>
	/// Candle type used by the strategy.
	/// </summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	
	/// <summary>
	/// Initializes a new instance of <see cref="CyberiaTraderStrategy"/>.
	/// </summary>
	public CyberiaTraderStrategy()
	{
		_macdFast = Param(nameof(MacdFast), 12)
		.SetGreaterThanZero()
		.SetDisplay("MACD Fast Period", "Fast EMA period for MACD", "Indicators");
		
		_macdSlow = Param(nameof(MacdSlow), 26)
		.SetGreaterThanZero()
		.SetDisplay("MACD Slow Period", "Slow EMA period for MACD", "Indicators");
		
		_macdSignal = Param(nameof(MacdSignal), 9)
		.SetGreaterThanZero()
		.SetDisplay("MACD Signal Period", "Signal MA period for MACD", "Indicators");
		
		_maPeriod = Param(nameof(MaPeriod), 20)
		.SetGreaterThanZero()
		.SetDisplay("MA Period", "Length of moving average", "Indicators");
		
		_cciPeriod = Param(nameof(CciPeriod), 14)
		.SetGreaterThanZero()
		.SetDisplay("CCI Period", "Length of CCI", "Indicators");
		
		_adxPeriod = Param(nameof(AdxPeriod), 14)
		.SetGreaterThanZero()
		.SetDisplay("ADX Period", "Length of ADX", "Indicators");
		
		_enableMacd = Param(nameof(EnableMacd), true)
		.SetDisplay("Enable MACD", "Use MACD direction filter", "Logic");
		
		_enableMa = Param(nameof(EnableMa), true)
		.SetDisplay("Enable MA", "Use moving average trend filter", "Logic");
		
		_enableCci = Param(nameof(EnableCci), true)
		.SetDisplay("Enable CCI", "Use CCI overbought/oversold filter", "Logic");
		
		_enableAdx = Param(nameof(EnableAdx), true)
		.SetDisplay("Enable ADX", "Use ADX directional filter", "Logic");
		
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
		.SetDisplay("Candle Type", "Timeframe for strategy", "General");
		
		Volume = 1;
	}
	
	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_lastDirection = 0;
	}
	
	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_lastDirection = 0;
		
		_macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFast },
				LongMa = { Length = MacdSlow },
			},
			SignalMa = { Length = MacdSignal }
		};
		
		_ma = new SMA { Length = MaPeriod };
		_cci = new CommodityChannelIndex { Length = CciPeriod };
		_adx = new AverageDirectionalIndex { Length = AdxPeriod };
		
		var subscription = SubscribeCandles(CandleType);
		subscription
		.BindEx(_macd, _ma, _cci, _adx, ProcessCandle)
		.Start();
		
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, _ma);
			DrawOwnTrades(area);
			
			var indicatorArea = CreateChartArea();
			if (indicatorArea != null)
			{
				DrawIndicator(indicatorArea, _macd);
				DrawIndicator(indicatorArea, _cci);
				DrawIndicator(indicatorArea, _adx);
			}
		}
		
		StartProtection(new Unit(2m, UnitTypes.Percent), new Unit(1m, UnitTypes.Percent));
	}
	
	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdVal, IIndicatorValue maVal, IIndicatorValue cciVal, IIndicatorValue adxVal)
	{
		if (candle.State != CandleStates.Finished)
		return;
		
		if (!IsFormedAndOnlineAndAllowTrading())
		return;
		
		var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
		var adxTyped = (AverageDirectionalIndexValue)adxVal;
		
		var disableBuy = false;
		var disableSell = false;
		
		if (EnableMacd)
		{
			var macd = macdTyped.Macd ?? 0m;
			var signal = macdTyped.Signal ?? 0m;
			if (macd > signal)
			disableSell = true;
			else if (macd < signal)
			disableBuy = true;
		}
		
		if (EnableMa)
		{
			var ma = maVal.ToDecimal();
			if (candle.ClosePrice > ma)
			disableSell = true;
			else if (candle.ClosePrice < ma)
			disableBuy = true;
		}
		
		if (EnableCci)
		{
			var cci = cciVal.ToDecimal();
			if (cci > 100m)
			disableBuy = true;
			else if (cci < -100m)
			disableSell = true;
		}
		
		if (EnableAdx)
		{
			var plus = adxTyped.Dx.Plus ?? 0m;
			var minus = adxTyped.Dx.Minus ?? 0m;
			if (plus > minus)
			disableSell = true;
			else if (minus > plus)
			disableBuy = true;
		}

		var direction = !disableBuy && disableSell ? 1 : !disableSell && disableBuy ? -1 : 0;

		if (direction == 1 && _lastDirection != 1 && Position <= 0)
		{
			BuyMarket();
		}
		else if (direction == -1 && _lastDirection != -1 && Position >= 0)
		{
			SellMarket();
		}

		_lastDirection = direction;
	}
}