在 GitHub 上查看

Three Soldiers Stochastic 策略

该策略复刻 MetaTrader 专家 Expert_ABC_WS_Stoch.mq5,将经典的三根蜡烛反转形态与随机指标结合使用。当出现多头的“三个白兵”形态并且随机指标信号线位于超卖区时开多;当出现空头的“三只乌鸦”形态并且信号线位于超买区时开空。平仓逻辑基于信号线穿越可配置的阈值带。

交易逻辑

  1. 形态识别
    • 监控最近三根已完成的蜡烛。
    • Three White Soldiers:三根蜡烛全部收阳,且每根收盘价高于上一根。
    • Three Black Crows:三根蜡烛全部收阴,且每根收盘价低于上一根。
  2. 随机指标确认
    • 计算随机指标,参数 %K = 47%D = 9Slowing = 13(默认值与原始脚本一致)。
    • 使用信号线(%D)作为确认条件:
      • 当上一根信号线低于超卖阈值(默认 30)时确认买入。
      • 当上一根信号线高于超买阈值(默认 70)时确认卖出。
  3. 离场条件
    • 当信号线从下向上穿越下限或上限阈值(默认 2080)时平掉多单。
    • 当信号线从上向下穿越这些阈值时平掉空单。
    • 通过比较上一根与上上一根信号线数值来判断是否真正穿越。

参数

参数 默认值 说明
CandleType 1 小时 订阅蜡烛的时间周期。
StochKPeriod 47 %K 的回溯周期。
StochDPeriod 9 信号线的平滑周期。
StochSlowing 13 %K 的额外平滑系数。
OversoldLevel 30 确认多头的超卖阈值。
OverboughtLevel 70 确认空头的超买阈值。
ExitLowerLevel 20 平多使用的下限阈值。
ExitUpperLevel 80 平空使用的上限阈值。

所有数值参数都提供优化范围,可在 Strategy Designer 中直接调优。

订单管理

  • 出现反向信号时通过增加当前仓位的绝对值来实现反向开仓。
  • 调用 StartProtection() 激活平台的风险控制,默认不设置固定止损或止盈。

可视化

在 Strategy Designer 中运行时将绘制:

  • 指定品种及时间框架的蜡烛图;
  • 配置好的随机指标;
  • 入场与离场的成交标记。

使用建议

  • 确保行情历史充足,以便随机指标有足够的数据进行计算。
  • 实盘部署时可叠加波动率、交易时段等额外过滤条件。
  • 阈值参数全部外部化,便于快速试验不同的确认区间。
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Three Soldiers Stochastic strategy: detects three consecutive bullish/bearish candles
/// confirmed by RSI levels.
/// </summary>
public class ThreeSoldiersStochasticStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private int _bullCount;
	private int _bearCount;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public ThreeSoldiersStochasticStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period for confirmation", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_bullCount = 0;
		_bearCount = 0;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_bullCount = 0;
		_bearCount = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsi)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (candle.ClosePrice > candle.OpenPrice)
		{
			_bullCount++;
			_bearCount = 0;
		}
		else if (candle.ClosePrice < candle.OpenPrice)
		{
			_bearCount++;
			_bullCount = 0;
		}
		else
		{
			_bullCount = 0;
			_bearCount = 0;
		}

		if (_bullCount >= 3 && rsi < 65 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			BuyMarket();
			_bullCount = 0;
			_candlesSinceTrade = 0;
		}
		else if (_bearCount >= 3 && rsi > 35 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			SellMarket();
			_bearCount = 0;
			_candlesSinceTrade = 0;
		}
	}
}