Главная
/
Примеры стратегий
Открыть на GitHub
Стратегия Simplest DeMarker
Обзор
Стратегия Simplest DeMarker повторяет логику исходного советника MetaTrader. Она отслеживает осциллятор DeMarker, чтобы определить моменты выхода цены из зон перекупленности и перепроданности. Когда индикатор возвращается в нейтральную область, стратегия открывает позицию в направлении ожидаемого разворота и управляет рисками с помощью настраиваемых уровней стоп-лосса и тейк-профита.
Основная логика
Подписаться на свечи выбранного таймфрейма и рассчитать индикатор DeMarker с заданным периодом.
Помечать состояние рынка как перекупленное , если предыдущее значение DeMarker выше порога перекупленности, и как перепроданное , если оно ниже порога перепроданности.
Формировать сигналы при возврате индикатора в нейтральную зону:
Продажа, если текущий DeMarker опускается ниже уровня перекупленности после нахождения выше него.
Покупка, если текущий DeMarker поднимается выше уровня перепроданности после нахождения ниже него.
Одновременно открывается только одна позиция. При включенном параметре Trade On Bar Open заявка отправляется на открытии следующей свечи, иначе вход выполняется сразу после закрытия текущей свечи.
Стоп-лосс и тейк-профит выставляются через сервис StartProtection, что соответствует фиксированным дистанциям из версии на MQL.
Параметры
Volume – объем сделки в лотах/контрактах.
DeMarker Period – период расчета индикатора DeMarker.
Overbought Level – верхний порог, определяющий зону перекупленности.
Oversold Level – нижний порог, определяющий зону перепроданности.
Trade On Bar Open – при включении вход выполняется на открытии следующей свечи.
Stop Loss Points – расстояние стоп-лосса в ценовых пунктах.
Take Profit Points – расстояние тейк-профита в ценовых пунктах.
Candle Type – тип свечей (таймфрейм), используемый для расчетов.
Управление рисками
Защита позиции активируется автоматически через StartProtection, дистанции переводятся в ценовые пункты.
В один момент времени удерживается не более одной позиции; новые сигналы игнорируются при открытой позиции.
Элементы графика
Свечи по выбранному типу данных.
Линия индикатора DeMarker.
Маркеры собственных сделок для визуальной проверки входов и выходов.
Примечания
Рекомендуется использовать инструменты с достаточной ликвидностью для корректного исполнения стопов и тейк-профитов.
Параметр Trade On Bar Open приближенно повторяет поведение оригинального советника, ожидающего формирования новой свечи перед отправкой заявки.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Simplest DeMarker strategy: DeMarker oscillator crossover.
/// Buys when DeMarker crosses above oversold, sells when crosses below overbought.
/// </summary>
public class SimplestDeMarkerStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _demarkerPeriod;
private readonly StrategyParam<decimal> _oversold;
private readonly StrategyParam<decimal> _overbought;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevValue;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int DemarkerPeriod { get => _demarkerPeriod.Value; set => _demarkerPeriod.Value = value; }
public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public SimplestDeMarkerStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_demarkerPeriod = Param(nameof(DemarkerPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("DeMarker Period", "DeMarker period", "Indicators");
_oversold = Param(nameof(Oversold), 0.2m)
.SetDisplay("Oversold", "DeMarker oversold level", "Signals");
_overbought = Param(nameof(Overbought), 0.8m)
.SetDisplay("Overbought", "DeMarker overbought level", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevValue = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevValue = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var demarker = new DeMarker { Length = DemarkerPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(demarker, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal demarkerValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev)
{
if (_prevValue < Oversold && demarkerValue >= Oversold && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevValue > Overbought && demarkerValue <= Overbought && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevValue = demarkerValue;
_hasPrev = true;
}
}
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 DeMarker
from StockSharp.Algo.Strategies import Strategy
class simplest_de_marker_strategy(Strategy):
def __init__(self):
super(simplest_de_marker_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._demarker_period = self.Param("DemarkerPeriod", 14)
self._oversold = self.Param("Oversold", 0.2)
self._overbought = self.Param("Overbought", 0.8)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_value = 0.0
self._candles_since_trade = 4
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def DemarkerPeriod(self):
return self._demarker_period.Value
@DemarkerPeriod.setter
def DemarkerPeriod(self, value):
self._demarker_period.Value = value
@property
def Oversold(self):
return self._oversold.Value
@Oversold.setter
def Oversold(self, value):
self._oversold.Value = value
@property
def Overbought(self):
return self._overbought.Value
@Overbought.setter
def Overbought(self, value):
self._overbought.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(simplest_de_marker_strategy, self).OnReseted()
self._prev_value = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
def OnStarted2(self, time):
super(simplest_de_marker_strategy, self).OnStarted2(time)
self._prev_value = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
demarker = DeMarker()
demarker.Length = self.DemarkerPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(demarker, self._process_candle).Start()
def _process_candle(self, candle, demarker_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
dm_val = float(demarker_value)
if self._has_prev:
if self._prev_value < self.Oversold and dm_val >= self.Oversold and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif self._prev_value > self.Overbought and dm_val <= self.Overbought and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_value = dm_val
self._has_prev = True
def CreateClone(self):
return simplest_de_marker_strategy()