Открыть на GitHub

Стратегия Alligator Volatility

Стратегия Alligator Volatility — это порт оригинального советника MetaTrader "Alligator vol 1.1" на платформу StockSharp. Она использует индикатор Билла Вильямса Alligator, опциональный фильтр по фракталам, сетку усредняющих ордеров в стиле мартингейл и гибкое управление рисками.

Общая логика

  • Подписывается на выбранный тип свечей и рассчитывает три сглаженных скользящих средних (челюсти, зубы, губы) — компоненты индикатора Alligator.
  • Фиксирует бычью фазу, когда губы находятся выше челюстей минимум на EntryGap и при этом не опускаются ниже зубов (ExitGap). Медвежья фаза требует, чтобы челюсти доминировали над губами и оставались выше зубов.
  • В пределах последних FractalBars завершённых свечей ищет фракталы по модели пяти свечей. Фильтр (опционально) требует пробоя свежего верхнего фрактала для покупок и нижнего — для продаж.
  • При появлении нового состояния Alligator отправляет рыночный ордер. Если включён мартингейл, дополнительно размещает серию лимитных ордеров с шагом, равным расстоянию до стоп-лосса.
  • Управляет выходом из позиции через стоп-лосс, тейк-профит, при необходимости — трейлинг-стоп и закрытие по сигналу разворота Alligator.

Правила входа

  1. Обрабатываются только полностью сформированные свечи (CandleStates.Finished).
  2. Условия для длинных позиций:
    • При активном флаге UseAlligatorEntry стратегия ждёт, пока бычье состояние сменит медвежье, и (если требуется) пока верхний фрактал будет минимум на FractalDistancePips пунктов выше текущей цены.
    • Если UseAlligatorEntry выключен, то (при необходимости) проверяется лишь условие по фракталам.
  3. Короткие позиции формируются зеркально относительно длинных.
  4. Параметр ManualMode позволяет полностью отключить автоматические сделки и управлять ордерами вручную.
  5. При OnlyOnePosition = true стратегия не открывает новые сделки, если есть активная позиция.

Правила выхода

  • После увеличения позиции рассчитываются исходные уровни стоп-лосса и тейк-профита на основании StopLossPips и TakeProfitPips, переводимых в цену через шаг котировки.
  • При включённом EnableTrailing трейлинг-стоп активируется, когда прибыль достигает TrailingActivationPips пунктов. Для лонгов стоп подтягивается под максимум свечей, для шортов — над минимум.
  • Если UseAlligatorExit = true, позиция закрывается сразу после исчезновения соответствующего состояния Alligator (например, бычьего сигнала для лонга).
  • Срабатывание стопа или тейка автоматически закрывает позицию и отменяет лимитные ордера усреднения.

Мартингейл-сетка

  • Параметр EnableMartingale включает постановку серии лимитных ордеров после входа в сделку.
  • Объём каждого последующего ордера равен объёму предыдущей сделки, умноженному на 2 * MartingaleMultiplier, но не превышает MaxVolume.
  • Цены ордеров сдвигаются на расстояние стоп-лосса (StopLossPips) и корректируются на GridSpreadPips для учёта спрэда.
  • Все неисполненные лимитные ордера снимаются при смене сигнала, закрытии позиции или ручном вмешательстве.

Управление капиталом

  • Объём сделки рассчитывается по формуле equity / 1000 * RiskPerThousand. При отсутствии данных об эквити используется MinVolume.
  • MaxVolume ограничивает размер как рыночного ордера, так и усредняющих заявок.
  • Перед отправкой заявок цены округляются к ближайшему шагу цены инструмента.

Параметры

Параметр Описание Значение по умолчанию
CandleType Тип свечей для расчётов. Таймфрейм 15 минут
ManualMode Отключает автоматические входы. false
UseAlligatorEntry Требовать сигнала расширения Alligator. true
UseFractalFilter Фильтр по пробою фракталов. false
UseAlligatorExit Закрывать позицию при сворачивании Alligator. false
OnlyOnePosition Разрешать только одну позицию. true
EnableMartingale Включить сетку усреднения. true
EnableTrailing Активировать трейлинг-стоп. true
RiskPerThousand Коэффициент объёма на каждые 1000 ед. капитала. 0.04
MaxVolume Максимальный объём ордера. 0.5
MinVolume Минимальный объём ордера. 0.01
StopLossPips / TakeProfitPips Расстояние до стопа и тейка в пунктах. 80
TrailingStopPips Расстояние трейлинг-стопа. 30
TrailingActivationPips Прибыль для включения трейлинга. 20
EntryGap Минимальный зазор между губами и челюстью (в цене). 0.0005
ExitGap Минимальный зазор относительно зубов (в цене). 0.0001
JawPeriod / TeethPeriod / LipsPeriod Периоды сглаженных средних. 13 / 8 / 5
JawShift / TeethShift / LipsShift Сдвиг линий при расчёте сигналов. 8 / 5 / 3
FractalBars Количество свечей для поиска фракталов. 10
FractalDistancePips Минимальная дистанция между ценой и фракталом. 30
MartingaleDepth Число ордеров усреднения. 10
MartingaleMultiplier Дополнительный множитель к объёму. 1.3
GridSpreadPips Поправка на спред в сетке. 10

Дополнительные замечания

  • Индикатор Alligator рассчитывается по медиане свечей и использует задержку в одну свечу, чтобы исключить незавершённые значения.
  • EntryGap и ExitGap задаются в абсолютных ценовых величинах — подберите их с учётом шага цены инструмента.
  • Фильтр по фракталам повторяет стандартную пятисвечную структуру; при включении фильтра требуется накопить достаточный объём истории.
  • Стратегия управляет выходами внутренне и не размещает биржевые стоп-ордеры или тейк-профиты.
  • Любые ручные изменения ордеров отслеживаются: сетка автоматически очищается после исполнения, отмены или ошибки заявки.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Alligator volatility strategy using three smoothed moving averages (Jaw, Teeth, Lips).
/// Enters long when Lips > Teeth > Jaw (uptrend expansion), short when Lips &lt; Teeth &lt; Jaw.
/// Exits when the lines converge (Alligator sleeps).
/// </summary>
public class AlligatorVolatilityStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _jawPeriod;
	private readonly StrategyParam<int> _teethPeriod;
	private readonly StrategyParam<int> _lipsPeriod;

	private int _candleCount;

	public AlligatorVolatilityStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for analysis.", "General");

		_jawPeriod = Param(nameof(JawPeriod), 13)
			.SetDisplay("Jaw Period", "Alligator jaw smoothing length.", "Indicators");

		_teethPeriod = Param(nameof(TeethPeriod), 8)
			.SetDisplay("Teeth Period", "Alligator teeth smoothing length.", "Indicators");

		_lipsPeriod = Param(nameof(LipsPeriod), 5)
			.SetDisplay("Lips Period", "Alligator lips smoothing length.", "Indicators");
	}

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

	public int JawPeriod
	{
		get => _jawPeriod.Value;
		set => _jawPeriod.Value = value;
	}

	public int TeethPeriod
	{
		get => _teethPeriod.Value;
		set => _teethPeriod.Value = value;
	}

	public int LipsPeriod
	{
		get => _lipsPeriod.Value;
		set => _lipsPeriod.Value = value;
	}

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

		_candleCount = 0;
	}

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

		_candleCount = 0;

		// Use SimpleMovingAverage for Jaw/Teeth/Lips lines
		var jaw = new SimpleMovingAverage { Length = JawPeriod };
		var teeth = new SimpleMovingAverage { Length = TeethPeriod };
		var lips = new SimpleMovingAverage { Length = LipsPeriod };

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

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

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

		_candleCount++;
		if (_candleCount < JawPeriod + 2)
			return;

		var close = candle.ClosePrice;

		// Alligator expansion: lips > teeth > jaw = uptrend
		var bullish = lipsValue > teethValue && teethValue > jawValue;
		// Alligator expansion: lips < teeth < jaw = downtrend
		var bearish = lipsValue < teethValue && teethValue < jawValue;

		// Exit conditions: lines converge (no longer in order)
		if (Position > 0 && !bullish)
		{
			SellMarket();
		}
		else if (Position < 0 && !bearish)
		{
			BuyMarket();
		}

		// Entry conditions
		if (Position == 0)
		{
			if (bullish && close > lipsValue)
			{
				BuyMarket();
			}
			else if (bearish && close < lipsValue)
			{
				SellMarket();
			}
		}
	}
}