Открыть на GitHub

Стратегия BuySell

Стратегия повторяет эксперта BuySell для MetaTrader и объединяет скользящую среднюю с индикатором Average True Range (ATR) для определения разворотов тренда. Когда скользящая средняя начинает расти, рынок считается бычьим; когда она падает – медвежьим. Сделка открывается только если предыдущий бар был в противоположном состоянии, что подтверждает разворот. Стоп‑лосс и тейк‑профит задаются в ценовых пунктах.

Детали

  • Логика входа
    • Покупка: скользящая средняя переходит из снижения в рост и предыдущий бар был медвежьим.
    • Продажа: скользящая средняя переходит из роста в снижение и предыдущий бар был бычьим.
  • Логика выхода
    • Покупка: скользящая средняя разворачивается вниз или срабатывают стоп‑лосс/тейк‑профит.
    • Продажа: скользящая средняя разворачивается вверх или срабатывают стоп‑лосс/тейк‑профит.
  • Индикаторы: простая скользящая средняя (SMA) и ATR.
  • Стопы: присутствуют стоп‑лосс и тейк‑профит в пунктах.
  • Разрешения: отдельные флаги для открытия/закрытия длинных и коротких позиций.
  • Стандартный таймфрейм: свечи H4.

Параметры

Название По умолчанию Описание
MaPeriod 14 Период скользящей средней.
AtrPeriod 60 Период ATR.
StopLoss 1000 Стоп‑лосс в ценовых пунктах.
TakeProfit 2000 Тейк‑профит в ценовых пунктах.
AllowLongEntry true Разрешение на открытие длинных позиций.
AllowShortEntry true Разрешение на открытие коротких позиций.
AllowLongExit true Разрешение на закрытие длинных позиций.
AllowShortExit true Разрешение на закрытие коротких позиций.
CandleType H4 Таймфрейм для расчётов.

Использование

  1. Добавьте стратегию в своё решение StockSharp.
  2. Настройте параметры при необходимости.
  3. Запустите стратегию в режиме реальной торговли или тестирования.

Подход подходит для рынков, где развороты тренда сопровождаются изменением волатильности, отражённым ATR.

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>
/// Buy/Sell strategy based on EMA crossover.
/// </summary>
public class BuySellStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BuySellStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 28)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

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

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}