Стратегия переносит советник MetaTrader 5 Exp_XDeMarker_Histogram_Vol_Direct на инфраструктуру StockSharp. Она умножает
осциллятор DeMarker на выбранный поток объёма, сглаживает и сам осциллятор, и объём одним и тем же методом усреднения, после чего
сравнивает результат с динамическими уровнями. Сделки совершаются, когда направление сглаженной гистограммы меняется между
последовательными барами.
Логика индикатора
Рассчитывается классический DeMarker на заданном таймфрейме.
Значение DeMarker домножается на тиковый либо реальный объём каждой закрытой свечи.
Гистограмма и объём сглаживаются выбранным типом скользящей средней.
Сглаженный объём умножается на четыре коэффициента, образуя верхние и нижние уровни.
По направлению (рост/падение) гистограммы определяется, требуется ли смена позиции. При смене направления открывается сделка в
новом направлении и закрывается противоположная.
Варианты сглаживания включают простую, экспоненциальную, сглаженную (RMA/SMMA) и линейно-взвешенную средние. Экзотические фильтры
из оригинальной библиотеки (JJMA, JurX, ParMA, T3, VIDYA, AMA) в этой реализации отсутствуют.
Торговые правила
Вход в лонг — возможен при Разрешить вход в лонг = true. Если позапрошлый бар имел направление «вверх», а последний переключился
на «вниз», стратегия выставляет целевую длинную позицию объёмом Volume.
Вход в шорт — доступен при Разрешить вход в шорт = true. Условие зеркальное: предыдущий бар «вниз», текущий «вверх».
Выход из лонга — при Разрешить выход из лонга = true позиция закрывается, если направление предыдущего бара «вниз» и нет
одновременного сигнала на открытие шорта.
Выход из шорта — аналогично, при Разрешить выход из шорта = true позиция закрывается, если предыдущий бар «вверх» и нет
сигнала на открытие лонга.
Расчёт сигналов выполняется один раз для каждой завершённой свечи. Сохранена оригинальная задержка в один бар — параметр Signal Bar
оставлен для совместимости, но значения, отличные от 1, игнорируются с предупреждением.
Параметры
Параметр
Описание
Candle Type
Таймфрейм свечей для расчёта индикатора.
DeMarker Period
Длина базового осциллятора DeMarker.
Volume Source
Источник объёма: число тиков или фактический объём.
High Level 2 / High Level 1
Множители для построения верхних динамических уровней.
Low Level 1 / Low Level 2
Множители для нижних уровней.
Smoothing Method
Тип скользящей средней для сглаживания гистограммы и объёма.
Smoothing Length
Длина окна сглаживания.
Smoothing Phase
Заглушка для совместимости, в расчётах не используется.
Signal Bar
Смещение по истории (жёстко равно 1).
Allow Long/Short Entry
Разрешения на открытие длинных и коротких позиций.
Allow Long/Short Exit
Разрешения на автоматическое закрытие позиций.
Особенности реализации
Класс XDeMarkerHistogramVolDirectIndicator воспроизводит буферы индикатора MT5 и отдаёт сглаженную гистограмму, уровни и
направление через комплексное значение индикатора.
При необходимости изменить целевую позицию стратегия отправляет единственный рыночный ордер, приводящий позицию к значениям
Volume, -Volume или 0. Это повторяет последовательность «закрыть+открыть» из MQL5 без дублирования заявок.
При наличии области графика автоматически отображаются свечи, индикатор и совершённые сделки.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class XDeMarkerHistogramVolDirectStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private decimal? _prevDm;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Period { get => _period.Value; set => _period.Value = value; }
public XDeMarkerHistogramVolDirectStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_period = Param(nameof(Period), 14).SetGreaterThanZero().SetDisplay("DeMarker Period", "DeMarker lookback", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevDm = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevDm = null;
var dm = new DeMarker { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(dm, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal dmVal)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevDm = dmVal; return; }
if (_prevDm == null) { _prevDm = dmVal; return; }
if (_prevDm.Value < 0.45m && dmVal >= 0.55m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (_prevDm.Value > 0.55m && dmVal <= 0.45m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevDm = dmVal;
}
}
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 x_de_marker_histogram_vol_direct_strategy(Strategy):
def __init__(self):
super(x_de_marker_histogram_vol_direct_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._period = self.Param("Period", 14) \
.SetDisplay("DeMarker Period", "DeMarker lookback", "Indicators")
self._prev_dm = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def Period(self):
return self._period.Value
def OnReseted(self):
super(x_de_marker_histogram_vol_direct_strategy, self).OnReseted()
self._prev_dm = None
def OnStarted2(self, time):
super(x_de_marker_histogram_vol_direct_strategy, self).OnStarted2(time)
self._prev_dm = None
dm = DeMarker()
dm.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(dm, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle, dm_value):
if candle.State != CandleStates.Finished:
return
dv = float(dm_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_dm = dv
return
if self._prev_dm is None:
self._prev_dm = dv
return
if self._prev_dm < 0.45 and dv >= 0.55 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_dm > 0.55 and dv <= 0.45 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_dm = dv
def CreateClone(self):
return x_de_marker_histogram_vol_direct_strategy()