Стратегия является упрощённым портом примера Exp_ColorZerolagX10MA.mq5 из MetaTrader. Используется индикатор zero lag EMA для обнаружения смены наклона. Когда средняя начинает расти после двух свечей снижения, открывается или переворачивается длинная позиция. Если средняя начинает падать после роста, открывается короткая позиция.
Исходный код опирался на сложный индикатор из десяти сглаженных скользящих средних. Здесь он заменён встроенным ZeroLagExponentialMovingAverage из StockSharp. Стратегия работает на выбранном таймфрейме свечей, позволяя включать и отключать отдельные действия (открытие/закрытие длинных и коротких позиций).
Детали
Условия входа:
Long: ZLEMA[t-2] > ZLEMA[t-1] и ZLEMA[t] > ZLEMA[t-1].
Short: ZLEMA[t-2] < ZLEMA[t-1] и ZLEMA[t] < ZLEMA[t-1].
Направление: обе стороны.
Условия выхода:
Long закрывается при появлении сигнала на Short и включённом BuyPosClose.
Short закрывается при появлении сигнала на Long и включённом SellPosClose.
Стопы: не используются, выход по противоположному сигналу.
Значения по умолчанию:
Length = 20.
CandleType = 4-часовой таймфрейм.
Все флаги действий (BuyPosOpen, SellPosOpen, BuyPosClose, SellPosClose) включены.
Фильтры:
Категория: Следование тренду
Направление: Обе
Индикаторы: Один
Стопы: Нет
Сложность: Простая
Таймфрейм: Среднесрочный
Сезонность: Нет
Нейросети: Нет
Дивергенция: Нет
Уровень риска: Средний
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>
/// Trend detection strategy based on the slope of a zero lag moving average.
/// </summary>
public class ColorZerolagX10MaStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<DataType> _candleType;
private decimal _prev1;
private decimal _prev2;
private int _count;
public int Length { get => _length.Value; set => _length.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorZerolagX10MaStrategy()
{
_length = Param(nameof(Length), 20)
.SetDisplay("Length", "MA length", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prev1 = 0;
_prev2 = 0;
_count = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var zlma = new ZeroLagExponentialMovingAverage { Length = Length };
SubscribeCandles(CandleType)
.Bind(zlma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ma)
{
if (candle.State != CandleStates.Finished)
return;
_count++;
if (_count < 3)
{
_prev2 = _prev1;
_prev1 = ma;
return;
}
// Detect trend turn via slope direction change
var trendUp = _prev1 < _prev2 && ma > _prev1;
var trendDown = _prev1 > _prev2 && ma < _prev1;
if (trendUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (trendDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prev2 = _prev1;
_prev1 = ma;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ZeroLagExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_zerolag_x10_ma_strategy(Strategy):
"""
Trend detection strategy based on the slope of a zero lag moving average.
"""
def __init__(self):
super(color_zerolag_x10_ma_strategy, self).__init__()
self._length = self.Param("Length", 20) \
.SetDisplay("Length", "MA length", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev1 = 0.0
self._prev2 = 0.0
self._count = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_zerolag_x10_ma_strategy, self).OnReseted()
self._prev1 = 0.0
self._prev2 = 0.0
self._count = 0
def OnStarted2(self, time):
super(color_zerolag_x10_ma_strategy, self).OnStarted2(time)
zlma = ZeroLagExponentialMovingAverage()
zlma.Length = self._length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(zlma, self.on_process).Start()
def on_process(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
self._count += 1
if self._count < 3:
self._prev2 = self._prev1
self._prev1 = ma_val
return
trend_up = self._prev1 < self._prev2 and ma_val > self._prev1
trend_down = self._prev1 > self._prev2 and ma_val < self._prev1
if trend_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif trend_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev2 = self._prev1
self._prev1 = ma_val
def CreateClone(self):
return color_zerolag_x10_ma_strategy()