在 GitHub 上查看

Expert Alligator 策略

Expert Alligator 策略 是 MetaTrader 5 内置专家顾问 Expert_Alligator.mq5 的 StockSharp 复刻版。原始 EA 使用比尔·威廉姆斯 (Bill Williams) 的 Alligator 指标:三条平滑移动平均线(颚线、齿线、唇线)按经典长度计算,并向未来平移数根 K 线。EA 通过观察这些线条的收敛和发散来捕捉新的交叉点,并在“鳄鱼之口”重新张开之前禁止再次入场。此 C# 实现完全按照该流程构建,使用 StockSharp 的高级策略 API 与指标库复现原始逻辑。

交易逻辑

  1. 指标准备

    • 对每根完成的 K 线计算中位价 (最高价 + 最低价) / 2,分别输入到长度为 13、8、5 的平滑移动平均 (SMMA) 中。
    • 按照 Alligator 的设定将颚线、齿线、唇线分别向前平移 8、5、3 根 K 线,并维护足够的历史缓冲以重现 EA 中 LipsTeethDiff(-2) 这类未来索引。
  2. 入场条件

    • 多头:当唇线-齿线和齿线-颚线的差值在连续三个平移位置上逐步缩小且保持在零以上时触发,代表绿色唇线向下穿过红色齿线,预示上行张口。
    • 空头:完全对称,只是差值在零以下逐步增大,表示唇线向上穿过齿线与颚线。
    • 成交后会设置内部的 crossed 标志,在三条线的间距重新扩大到不少于 Cross Measure(以 MetaTrader 点数计)之前禁止再次开仓。
  3. 离场条件

    • 多头平仓:当最近的平移值上唇线-齿线差值跌破零,而更早的两个平移值仍保持正数(对应原始 EA 的 -101 索引)。
    • 空头平仓:当差值序列出现相反的符号变换时平掉空单。

参数

名称 说明 默认值
Order Volume 市价单的交易数量(手数或合约数)。 0.1
Candle Type 订阅的 K 线周期。 1 小时
Jaw Period 颚线的 SMMA 长度。 13
Jaw Shift 颚线向前平移的根数。 8
Teeth Period 齿线的 SMMA 长度。 8
Teeth Shift 齿线向前平移的根数。 5
Lips Period 唇线的 SMMA 长度。 5
Lips Shift 唇线向前平移的根数。 3
Cross Measure 交叉后重新允许入场所需的最小张口距离(以 MetaTrader 点数衡量)。 5

实现细节

  • 所有计算都基于收盘状态的 K 线;在蜡烛未完成之前不会执行任何交易决策。
  • 指标历史通过固定长度数组维护,既可访问过去的数值,也可在 Alligator 向前平移后访问“未来”索引,以匹配 MQL5 的 CiAlligator 行为。
  • MetaTrader 的 _Point 值使用品种的 PriceStep(报价步长)近似;若不可用,则回退到 10^-Decimals 或默认 0.0001
  • 策略会在图表面板上绘制 K 线与三条 Alligator 线,方便快速验证移植是否正确。

使用方法

  1. 将策略附加到具备所需行情数据的 Connector,并确保可提供设定周期的 K 线(默认 1 小时)。
  2. 等待数据订阅完成后调用 Start() 启动策略。
  3. 如需优化,可调整 Alligator 的长度、平移量或 Cross Measure 阈值。
  4. 通过 StockSharp 的标准界面监控持仓与绩效。

原始专家顾问仅使用固定手数和 Alligator 的几何关系管理仓位,因此本移植版未增加其他资金管理或跟踪止损模块。

using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Expert Alligator strategy: Triple SMA (Alligator concept).
/// Buys when lips > teeth > jaw (bullish alignment).
/// Sells when lips < teeth < jaw (bearish alignment).
/// </summary>
public class ExpertAlligatorStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;

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

	public ExpertAlligatorStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

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

		// Alligator: Jaw=13, Teeth=8, Lips=5
		var lips = new SimpleMovingAverage { Length = 5 };
		var teeth = new SimpleMovingAverage { Length = 8 };
		var jaw = new SimpleMovingAverage { Length = 13 };

		decimal? prevLips = null;
		decimal? prevTeeth = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(lips, teeth, jaw, (candle, lipsVal, teethVal, jawVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevLips.HasValue && prevTeeth.HasValue)
				{
					var lipsCrossUp = prevLips.Value <= prevTeeth.Value && lipsVal > teethVal;
					var lipsCrossDown = prevLips.Value >= prevTeeth.Value && lipsVal < teethVal;

					if (lipsCrossUp && teethVal > jawVal && Position <= 0)
						BuyMarket();
					else if (lipsCrossDown && teethVal < jawVal && Position >= 0)
						SellMarket();
				}

				prevLips = lipsVal;
				prevTeeth = teethVal;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, lips);
			DrawIndicator(area, teeth);
			DrawIndicator(area, jaw);
			DrawOwnTrades(area);
		}
	}
}