Стратегия повторяет эксперта 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
Таймфрейм для расчётов.
Использование
Добавьте стратегию в своё решение StockSharp.
Настройте параметры при необходимости.
Запустите стратегию в режиме реальной торговли или тестирования.
Подход подходит для рынков, где развороты тренда сопровождаются изменением волатильности, отражённым 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;
}
}