Эта стратегия является конвертацией советника MADX-07 с платформы MQL4. Используется таймфрейм H4 и сочетание двух скользящих средних с индикатором ADX для фильтрации.
Логика
Покупка: цена выше медленной MA, быстрая MA выше медленной, цена минимум на MaDifference пунктов выше быстрой MA на двух последних свечах, ADX растёт выше AdxMainLevel, +DI растёт, -DI падает.
Продажа: зеркальные условия.
Позиция закрывается при достижении прибыли CloseProfit пунктов или по лимитной заявке на расстоянии TakeProfit.
Параметры
BigMaPeriod (25) – период медленной MA.
BigMaType – тип медленной MA.
SmallMaPeriod (5) – период быстрой MA.
SmallMaType – тип быстрой MA.
MaDifference (5) – минимальное расстояние от цены до быстрой MA в пунктах.
AdxPeriod (11) – период ADX.
AdxMainLevel (13) – минимальное значение ADX.
AdxPlusLevel (13) – минимальное значение +DI.
AdxMinusLevel (14) – минимальное значение -DI.
TakeProfit (299) – тейк-профит в пунктах.
CloseProfit (13) – прибыль в пунктах для раннего выхода.
Volume (0.1) – объём сделки.
CandleType – таймфрейм свечей (по умолчанию H4).
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>
/// Strategy combining EMA crossover for trend following.
/// </summary>
public class Madx07AdxMaStrategy : Strategy
{
private readonly StrategyParam<int> _bigMaPeriod;
private readonly StrategyParam<int> _smallMaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevSmall;
private decimal _prevBig;
private bool _hasPrev;
public int BigMaPeriod { get => _bigMaPeriod.Value; set => _bigMaPeriod.Value = value; }
public int SmallMaPeriod { get => _smallMaPeriod.Value; set => _smallMaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Madx07AdxMaStrategy()
{
_bigMaPeriod = Param(nameof(BigMaPeriod), 25)
.SetGreaterThanZero()
.SetDisplay("Big MA Period", "Period of the slower MA", "MA");
_smallMaPeriod = Param(nameof(SmallMaPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Small MA Period", "Period of the faster MA", "MA");
_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();
_prevSmall = 0;
_prevBig = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bigMa = new ExponentialMovingAverage { Length = BigMaPeriod };
var smallMa = new ExponentialMovingAverage { Length = SmallMaPeriod };
SubscribeCandles(CandleType)
.Bind(bigMa, smallMa, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal bigMaVal, decimal smallMaVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevSmall = smallMaVal;
_prevBig = bigMaVal;
_hasPrev = true;
return;
}
var crossUp = _prevSmall <= _prevBig && smallMaVal > bigMaVal;
var crossDown = _prevSmall >= _prevBig && smallMaVal < bigMaVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevSmall = smallMaVal;
_prevBig = bigMaVal;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class madx07_adx_ma_strategy(Strategy):
def __init__(self):
super(madx07_adx_ma_strategy, self).__init__()
self._big_ma_period = self.Param("BigMaPeriod", 25) \
.SetDisplay("Big MA Period", "Period of the slower MA", "MA")
self._small_ma_period = self.Param("SmallMaPeriod", 10) \
.SetDisplay("Small MA Period", "Period of the faster MA", "MA")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._prev_small = 0.0
self._prev_big = 0.0
self._has_prev = False
@property
def big_ma_period(self):
return self._big_ma_period.Value
@property
def small_ma_period(self):
return self._small_ma_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(madx07_adx_ma_strategy, self).OnReseted()
self._prev_small = 0.0
self._prev_big = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(madx07_adx_ma_strategy, self).OnStarted2(time)
big_ma = ExponentialMovingAverage()
big_ma.Length = self.big_ma_period
small_ma = ExponentialMovingAverage()
small_ma.Length = self.small_ma_period
self.SubscribeCandles(self.candle_type).Bind(big_ma, small_ma, self.process_candle).Start()
def process_candle(self, candle, big_ma_val, small_ma_val):
if candle.State != CandleStates.Finished:
return
bv = float(big_ma_val)
sv = float(small_ma_val)
if not self._has_prev:
self._prev_small = sv
self._prev_big = bv
self._has_prev = True
return
cross_up = self._prev_small <= self._prev_big and sv > bv
cross_down = self._prev_small >= self._prev_big and sv < bv
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_small = sv
self._prev_big = bv
def CreateClone(self):
return madx07_adx_ma_strategy()