Открыть на GitHub

Стратегия Fractals Martingale

В данной папке находится порт советника MetaTrader «Fractals Martingale», реализованный на высокоуровневом API StockSharp. Алгоритм объединяет фракталы Билла Вильямса, трендовый фильтр на основе индикатора Ишимоку и подтверждение по месячному MACD. Размер позиции регулируется по принципу мартингейла: после убыточных сделок объем следующей заявки умножается на коэффициент, а защитная пауза предотвращает бесконтрольный рост экспозиции.

Логика торговли

  1. Поиск фракталов на рабочем таймфрейме. Стратегия хранит историю завершенных свечей и ищет локальные экстремумы, окруженные минимум FractalDepth барами. Если следующая свеча открывается выше верхнего фрактала, формируется бычий сигнал; если ниже нижнего фрактала – медвежий. Найденные уровни остаются актуальными в течение FractalLookback обработанных свечей.
  2. Фильтр Ишимоку. Сигнал учитывается только тогда, когда на старшем таймфрейме (IchimokuCandleType) линия Tenkan расположена выше Kijun для покупок и ниже Kijun для продаж.
  3. Подтверждение MACD. Как и в исходном советнике, применяется месячный MACD (серия MacdCandleType, по умолчанию 30-дневные свечи). Длинные позиции открываются, только если линия MACD находится выше сигнальной, а короткие – если ниже.
  4. Фильтр торговой сессии. Заявки размещаются лишь в диапазоне часов от StartHour (включительно) до EndHour (не включая). Поддерживается режим с переходом через полночь.
  5. Мартингейл. Базовый объем задается параметром TradeVolume. После убыточной серии следующий объем умножается на Multiplier и приводится к шагу объема инструмента. При прибыли цепочка сбрасывается. При превышении MaxConsecutiveLosses торговля приостанавливается на PauseMinutes минут и затем возобновляется с базовым объемом.
  6. Переворот позиции. Перед открытием нового ордера стратегия закрывает встречный объем, чтобы в портфеле не оставалось разнонаправленных позиций.

Управление рисками

  • StopLossPips и TakeProfitPips переводятся в абсолютное изменение цены с учетом шага пункта и передаются в StartProtection. Это повторяет настройки исходного советника, где стопы задавались в пунктах.
  • Денежный трейлинг-стоп оригинала заменен на встроенный защитный механизм StockSharp, поскольку работа с валютой счета зависит от брокера.

Параметры

Параметр Описание
TradeVolume Базовый объем первой заявки в серии.
Multiplier Во сколько раз увеличить объем после убыточной сделки.
StopLossPips, TakeProfitPips Расстояние до стоп-лосса и тейк-профита в пунктах.
FractalDepth Количество баров по обе стороны при определении фрактала.
FractalLookback Сколько обработанных свечей хранить фрактал в качестве актуального уровня.
StartHour, EndHour Торговые часы (по времени площадки). Равные значения отключают фильтр.
MaxConsecutiveLosses Допустимое число подряд идущих убыточных сделок перед паузой.
PauseMinutes Длительность защитной паузы в минутах.
TenkanPeriod, KijunPeriod, SenkouPeriod Периоды линий Ишимоку на старшем таймфрейме.
MacdFastPeriod, MacdSlowPeriod, MacdSignalPeriod Периоды EMA для фильтра MACD.
CandleType Основная серия свечей для сигналов и сделок.
IchimokuCandleType Таймфрейм для расчета Ишимоку.
MacdCandleType Таймфрейм для MACD (по умолчанию приблизительный месяц).

Рекомендации по использованию

  1. Расчет пункта. Значение пункта берется из Security.PriceStep; для пятизначных форекс-котировок производится умножение на 10, чтобы соответствовать логике MetaTrader.
  2. Множественные подписки. Стратегии требуются до трех разных серий свечей. Убедитесь, что поставщик данных поддерживает необходимые таймфреймы.
  3. Контроль мартингейла. Умножение объема резко увеличивает риски. Используйте параметры Multiplier, MaxConsecutiveLosses и PauseMinutes, чтобы адаптировать стратегию к капиталу.
  4. Отличия от версии MT4. В переводе отсутствуют почтовые и push-уведомления, денежные трейлинг-стопы и явные проверки маржи – эти функции реализованы средствами StockSharp. Логика входа/выхода и наращивания позиции сохранена.

Содержимое

  • CS/FractalsMartingaleStrategy.cs – реализация стратегии на C#.
  • README.md – документация на английском языке.
  • README_zh.md – описание на китайском языке.
  • README_ru.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;

public class FractalsMartingaleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public FractalsMartingaleStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}