Стратегия воспроизводит логику советника MetaTrader «2 1000 1 0.7% 0.5 500lev st»: позиция открывается в начале каждого нового торгового дня, а направление выбирается по наклону гистограммы MACD. Система рассчитана на часовые свечи и использует фиксированные параметры управления капиталом из исходного MQL файла.
Логика торговли
Стратегия анализирует часовые свечи и определяет первую свечу каждого торгового дня.
Для фильтрации направления используются значения гистограммы MACD на двух последних завершённых свечах предыдущего дня.
Если гистограмма между этими свечами снизилась, в начале нового дня открывается длинная позиция.
Если гистограмма выросла, открывается короткая позиция.
Одновременно может быть открыта только одна позиция. При появлении обратного сигнала текущая позиция закрывается перед открытием новой.
Управление рисками
Первоначальный стоп-лосс: 875 пунктов (переводится в цену умножением на шаг цены инструмента).
Тейк-профит: 510 пунктов.
Трейлинг-стоп: 2172 пункта. Стоп следует за максимумом (для длинных) или минимумом (для коротких) с момента входа и заменяет первоначальный стоп, если становится ближе к цене.
Функция переноса стопа в безубыток в исходной версии отключена и здесь также не используется.
Параметры
Название
Описание
Значение по умолчанию
CandleType
Тип свечей (по умолчанию часовые).
Часовые свечи
MacdFastPeriod
Период быстрой EMA в MACD.
58
MacdSlowPeriod
Период медленной EMA в MACD.
195
MacdSignalPeriod
Период сигнальной линии MACD.
183
StopLossPoints
Дистанция стоп-лосса в пунктах.
875
TakeProfitPoints
Дистанция тейк-профита в пунктах.
510
TrailingStopPoints
Дистанция трейлинг-стопа в пунктах.
2172
Примечания
Используются только закрытые свечи, что соответствует опции «Use previous bar value» в оригинальной реализации и исключает подглядывание в будущее.
Управление стопами и трейлингом выполняется самой стратегией, поэтому дополнительные защитные механизмы портфеля лучше не включать, чтобы избежать дублирования.
Параметры рассчитаны на стандартное определение пункта. При работе с инструментами с другим шагом цены скорректируйте значения.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Day Opening MACD Histogram strategy: MACD histogram direction.
/// Buys when MACD histogram turns positive, sells when turns negative.
/// </summary>
public class DayOpeningMacdHistogramStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _signalPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevHistogram;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public DayOpeningMacdHistogramStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators");
_signalPeriod = Param(nameof(SignalPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Signal Period", "MACD signal period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHistogram = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHistogram = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
SignalMa = { Length = SignalPeriod }
};
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(macd, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished) return;
if (!macdValue.IsFinal) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;
var histogram = macdMain - signal;
if (_hasPrev)
{
if (_prevHistogram <= 0 && histogram > 0 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevHistogram >= 0 && histogram < 0 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevHistogram = histogram;
_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 MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class day_opening_macd_histogram_strategy(Strategy):
def __init__(self):
super(day_opening_macd_histogram_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._fast_period = self.Param("FastPeriod", 12)
self._slow_period = self.Param("SlowPeriod", 26)
self._signal_period = self.Param("SignalPeriod", 9)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_histogram = 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 FastPeriod(self):
return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, value):
self._fast_period.Value = value
@property
def SlowPeriod(self):
return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, value):
self._slow_period.Value = value
@property
def SignalPeriod(self):
return self._signal_period.Value
@SignalPeriod.setter
def SignalPeriod(self, value):
self._signal_period.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(day_opening_macd_histogram_strategy, self).OnReseted()
self._prev_histogram = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
def OnStarted2(self, time):
super(day_opening_macd_histogram_strategy, self).OnStarted2(time)
self._prev_histogram = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self.FastPeriod
macd.Macd.LongMa.Length = self.SlowPeriod
macd.SignalMa.Length = self.SignalPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, self._process_candle).Start()
def _process_candle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFinal:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
if macd_value.Macd is None or macd_value.Signal is None:
return
macd_main = float(macd_value.Macd)
signal = float(macd_value.Signal)
histogram = macd_main - signal
if self._has_prev:
if self._prev_histogram <= 0 and histogram > 0 and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif self._prev_histogram >= 0 and histogram < 0 and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_histogram = histogram
self._has_prev = True
def CreateClone(self):
return day_opening_macd_histogram_strategy()