在 GitHub 上查看

Deep Drawdown MA 策略

概述

Deep Drawdown MA 策略是将 MetaTrader 5 专家顾问“Deep Drawdown MA (barabashkakvn's edition)”直接移植到 StockSharp 高阶 API 的结果。策略利用两条可配置的移动平均线寻找趋势交叉,同时在出现深度回撤时触发保本机制。所有关键参数(移动平均期数、价格类型、历史偏移、持仓上限以及亏损处理方式)均按照原始脚本实现。

交易逻辑

  • 指标:两条移动平均线拥有独立的周期、价格来源与历史偏移,共享同一平滑方法(SMA、EMA、SMMA 或 LWMA)。
  • 开仓条件
    • 做多:当带有偏移的快线向上穿越慢线,且上一笔开仓不是多单并且未超过最大仓位限制时,按设定手数买入,同时自动平掉现有空单。
    • 做空:当带有偏移的快线向下穿越慢线,且上一笔开仓不是空单并且仍有仓位额度时,按设定手数卖出,并在需要时先平掉多头。
  • 平仓条件
    • 多单:当快线重新跌破慢线,若 CloseLosses = true 则立即平仓;否则记录保本标记,等待后续 K 线收盘价回到平均开仓价时再退出。
    • 空单:逻辑对称——当快线重新站上慢线时立即平仓或进入保本等待,直到价格回落至平均开仓价。
  • 持仓跟踪:策略根据自身成交实时重构平均开仓价以及最近的入场方向,确保在 StockSharp 的净头寸模型下复刻 MT5 的行为。

参数

参数 说明 默认值
OrderVolume 每次市价下单的数量。 0.1
MaxPositions 单一方向允许的累计净头寸(以手数计)。 5
CloseLosses 信号反转时是否立即平掉亏损头寸。 false
FastMaPeriod / SlowMaPeriod 快速/慢速移动平均的周期。 10 / 30
FastMaShift / SlowMaShift 对应移动平均的历史偏移量(等价于 MT5 的 shift 参数)。 3 / 0
FastPriceType / SlowPriceType 计算所用的价格类型(收盘、开盘、最高、最低、中值、典型价、加权价)。 Close
MaMethod 两条移动平均共用的平滑方式。 SMA
CandleType 进行计算的蜡烛类型。 15 分钟蜡烛

转换说明

  • 原 MT5 顾问支持同时持有对冲方向的订单,StockSharp 策略以净头寸运行,因此移植版本通过限制累积仓位来模拟原始参数。
  • 保本逻辑通过内部标记完成,不再修改订单属性。策略在每根蜡烛收盘时检测价格是否回到平均开仓价并自动平仓。
  • 移动平均的 “shift” 功能通过维护最近指标值的队列实现,避免直接访问指标缓冲区,完全符合仓库约定的高阶 API 规范。

使用步骤

  1. 选择目标证券后配置 OrderVolumeCandleType 及两条移动平均线的参数,使之符合预期的市场和周期。
  2. 启动策略并确认蜡烛订阅已经建立且允许自动交易。
  3. 观察日志输出:当触发保本逻辑时,策略会在价格回到平均入场价附近自动平仓。

风险控制

  • 若希望在信号反转时迅速止损,可将 CloseLosses 设为 true
  • 调整 MaxPositions 以限制在交替信号下的最大净头寸。
  • 建议结合 StockSharp 提供的 StartProtection 等账户级风控组件使用,以获得额外保护。

文件结构

  • CS/DeepDrawdownMaStrategy.cs:基于 StockSharp 高阶 API 的 C# 实现。
  • README.mdREADME_ru.mdREADME_zh.md:提供英文、俄文与中文的详细文档说明。
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Deep drawdown MA crossover strategy (simplified).
/// Uses fast/slow EMA crossover with position management.
/// </summary>
public class DeepDrawdownMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public DeepDrawdownMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA", "Indicators");
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		decimal prevFast = 0, prevSlow = 0;
		bool hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					return;
				}

				if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
					BuyMarket();
				else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
					SellMarket();

				prevFast = fastValue;
				prevSlow = slowValue;
			})
			.Start();

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