Открыть на GitHub

Стратегия Ride Alligator

Реализация стратегии Ride Alligator. Используются три скользящие средние, известные как индикатор Alligator. Длинная позиция открывается, когда линия Губ пересекает линию Челюстей снизу и линия Зубов находится ниже Челюстей. Короткая позиция открывается при пересечении Губ сверху вниз при условии, что Зубы выше Челюстей. Открытая позиция защищается стопом по линии Челюстей, который перемещается вслед за ней.

Подробности

  • Условия входа:
    • Лонг: Lips > Jaws && Teeth < Jaws && previous Lips < previous Jaws
    • Шорт: Lips < Jaws && Teeth > Jaws && previous Lips > previous Jaws
  • Лонг/Шорт: Оба направления
  • Условия выхода:
    • Лонг: price <= Jaws
    • Шорт: price >= Jaws
  • Стопы: Подтягивающий стоп по линии Челюстей
  • Значения по умолчанию:
    • AlligatorPeriod = 5
    • MaType = MovingAverageTypeEnum.Weighted
    • CandleType = TimeSpan.FromMinutes(1).TimeFrame()
  • Фильтры:
    • Категория: Следование тренду
    • Направление: Обе стороны
    • Индикаторы: Alligator
    • Стопы: Да
    • Сложность: Базовая
    • Таймфрейм: Внутридневной
    • Сезонность: Нет
    • Нейросети: Нет
    • Дивергенция: Нет
    • Уровень риска: Средний
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>
/// Ride Alligator strategy using SMMA jaw/teeth/lips crossover.
/// </summary>
public class RideAlligatorStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevJaw;
	private decimal _prevLips;
	private bool _hasPrev;

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

	public RideAlligatorStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevJaw = 0;
		_prevLips = 0;
		_hasPrev = false;
	}

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

		var jaw = new SmoothedMovingAverage { Length = 13 };
		var teeth = new SmoothedMovingAverage { Length = 8 };
		var lips = new SmoothedMovingAverage { Length = 5 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(jaw, teeth, lips, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevJaw = jaw;
			_prevLips = lips;
			_hasPrev = true;
			return;
		}

		// Lips crosses above jaw -> buy
		if (_prevLips <= _prevJaw && lips > jaw && teeth < jaw)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Lips crosses below jaw -> sell
		else if (_prevLips >= _prevJaw && lips < jaw && teeth > jaw)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		// Exit on price crossing jaw
		if (Position > 0 && candle.ClosePrice < jaw)
			SellMarket();
		else if (Position < 0 && candle.ClosePrice > jaw)
			BuyMarket();

		_prevJaw = jaw;
		_prevLips = lips;
	}
}