Открыть на GitHub

Стратегия Follow Line Trend

Описание

Стратегия Follow Line является переносом советника MetaTrader FollowLineEA_v1.0. Она использует связку индикаторов Bollinger Bands, ATR и набора простых скользящих средних, чтобы построить динамическую линию тренда. Линия скользит только в направлении прорыва, поэтому образует ступенчатую структуру и помогает удерживать позицию до завершения импульса.

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

  1. Цепочка индикаторов
    • Полосы Боллинджера с параметрами BollingerPeriod и BollingerDeviations определяют факт выхода цены за диапазон.
    • ATR (AtrPeriod) опционально расширяет линию, если активирован флаг UseAtrFilter.
    • Набор SMA (MovingAveragePeriod) по High, Low, Open, Close и медиане формирует подтверждение сигналов в режимах OpenCloseMedian и HighLowOpenClose.
  2. Обновление линии
    • Закрытие выше верхней полосы поднимает линию под минимум свечи (с учётом ATR), но не позволяет ей опуститься ниже предыдущего значения.
    • Закрытие ниже нижней полосы опускает линию над максимум свечи и тоже не даёт ей подняться выше предыдущего уровня.
    • Знак приращения линии определяет состояние тренда: >0 — бычий, <0 — медвежий.
  3. Сигналы
    • Переключение линии из отрицательного наклона в положительный даёт стрелку на покупку при выполнении фильтра по стрелкам.
    • Переключение из положительного наклона в отрицательный формирует стрелку на продажу.
    • Параметр IndicatorsShift задерживает исполнение сигнала на указанное число свечей, что повторяет обращение к буферу индикатора в MQL.
  4. Фильтры
    • Временной фильтр (UseTimeFilter, TimeStartTrade, TimeEndTrade). Окно может пересекать полуночь.
    • Контроль спреда (MaxSpread) и максимального объёма (MaxOrders).

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

  • Закрытие по встречному сигналу (CloseInSignal).
  • Баскетные ограничения: CloseInProfit, CloseInLoss, UseBasketClose, PipsCloseProfit, PipsCloseLoss — повторяют поведение советника.
  • Стопы: стоп-лосс, тейк-профит, трейлинг и безубыток (UseStopLoss, UseTakeProfit, UseTrailingStop, UseBreakEven). Все расстояния указываются в шагах цены.
  • Лотность: AutoLotSize распределяет долю капитала (RiskFactor), иначе используется фиксированный ManualLotSize. Объём нормируется по шагу и биржевым ограничениям.

Параметры

Сохранены все настройки оригинала: таймфрейм (CandleType), глубина истории (BarsCount), параметры индикаторов, фильтры времени и спреда, блок управления позицией и денежным менеджментом.

Примечания по использованию

  • Стратегия работает по закрытым свечам, поэтому результаты тестов и реальной торговли совпадают при одинаковой компрессии данных.
  • TypeOfArrows = HideArrows полностью отключает торговлю, оставляя только индикацию.
  • Визуализация сделок включена через CreateChartArea() и DrawOwnTrades().

Особенности конвертации

  • Реализация выполнена на высокоуровневом API StockSharp без обращения к индикаторным буферам через GetValue.
  • Управление ордерами повторяет оригинальные вызовы BuyMarket/SellMarket и защитные стопы.
  • Все комментарии в коде на английском языке согласно требованиям репозитория.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Follow Line Trend strategy: EMA + Momentum trend follower.
/// Buys when close > EMA and momentum > 100.
/// Sells when close < EMA and momentum < 100.
/// </summary>
public class FollowLineTrendStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _momPeriod;

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

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public int MomPeriod
	{
		get => _momPeriod.Value;
		set => _momPeriod.Value = value;
	}

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

		_emaPeriod = Param(nameof(EmaPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");

		_momPeriod = Param(nameof(MomPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Momentum", "Momentum period", "Indicators");
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var mom = new Momentum { Length = MomPeriod };

		decimal? prevClose = null;
		decimal? prevEma = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, mom, (candle, emaVal, momVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;

				if (prevClose.HasValue && prevEma.HasValue)
				{
					var crossUp = prevClose.Value <= prevEma.Value && close > emaVal;
					var crossDown = prevClose.Value >= prevEma.Value && close < emaVal;

					if (crossUp && momVal > 100m && Position <= 0)
						BuyMarket();
					else if (crossDown && momVal < 100m && Position >= 0)
						SellMarket();
				}

				prevClose = close;
				prevEma = emaVal;
			})
			.Start();

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