Стратегия Cyberia Trader
Упрощённая реализация стратегии CyberiaTrader.mq5 для StockSharp. Стратегия использует комбинацию классических индикаторов для оценки направления рынка и открытия сделок, когда большинство фильтров согласны.
Индикаторы
- MACD – определяет смену импульса через быстрые/медленные EMA и сигнальную линию.
- Простое скользящее среднее – показывает преобладающий тренд.
- Commodity Channel Index – отслеживает зоны перекупленности и перепроданности.
- Average Directional Index – подтверждает силу движения через компоненты +DI и -DI.
Параметры
| Имя | Описание |
|---|---|
MacdFast |
Период быстрой EMA в MACD. |
MacdSlow |
Период медленной EMA в MACD. |
MacdSignal |
Период сигнальной линии MACD. |
MaPeriod |
Длина скользящей средней. |
CciPeriod |
Период CCI. |
AdxPeriod |
Период ADX. |
EnableMacd |
Включить/выключить фильтр MACD. |
EnableMa |
Включить/выключить фильтр скользящей средней. |
EnableCci |
Включить/выключить фильтр CCI. |
EnableAdx |
Включить/выключить фильтр ADX. |
CandleType |
Таймфрейм используемых свечей. |
Логика торговли
- На каждой завершённой свече рассчитываются значения всех включённых индикаторов.
- Каждый фильтр может блокировать покупки или продажи по своим правилам:
- MACD выше сигнальной линии блокирует продажи; ниже – покупки.
- Цена выше скользящей средней блокирует продажи; ниже – покупки.
- CCI выше +100 блокирует покупки; ниже -100 блокирует продажи.
- +DI больше -DI блокирует продажи; -DI больше +DI блокирует покупки.
- Сделка открывается только если одна сторона разрешена, а противоположная заблокирована.
- Используется базовая защита позиции: тейк-профит 2% и стоп-лосс 1%.
Примечания
В данной конверсии сохранены только основные направленные фильтры оригинала. Сложные расчёты вероятностей и вспомогательные модули MQL5-версии опущены для упрощения.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
using StockSharp.Algo;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified conversion of the CyberiaTrader MQL5 strategy.
/// Combines MACD, MA, CCI, and ADX filters to determine market direction.
/// </summary>
public class CyberiaTraderStrategy : Strategy
{
private readonly StrategyParam<int> _macdFast;
private readonly StrategyParam<int> _macdSlow;
private readonly StrategyParam<int> _macdSignal;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _adxPeriod;
private readonly StrategyParam<bool> _enableMacd;
private readonly StrategyParam<bool> _enableMa;
private readonly StrategyParam<bool> _enableCci;
private readonly StrategyParam<bool> _enableAdx;
private readonly StrategyParam<DataType> _candleType;
private MovingAverageConvergenceDivergenceSignal _macd;
private SimpleMovingAverage _ma;
private CommodityChannelIndex _cci;
private AverageDirectionalIndex _adx;
private int _lastDirection;
/// <summary>
/// MACD fast EMA period.
/// </summary>
public int MacdFast { get => _macdFast.Value; set => _macdFast.Value = value; }
/// <summary>
/// MACD slow EMA period.
/// </summary>
public int MacdSlow { get => _macdSlow.Value; set => _macdSlow.Value = value; }
/// <summary>
/// MACD signal line period.
/// </summary>
public int MacdSignal { get => _macdSignal.Value; set => _macdSignal.Value = value; }
/// <summary>
/// Moving average length.
/// </summary>
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
/// <summary>
/// Commodity Channel Index length.
/// </summary>
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
/// <summary>
/// ADX calculation length.
/// </summary>
public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
/// <summary>
/// Enable MACD filter.
/// </summary>
public bool EnableMacd { get => _enableMacd.Value; set => _enableMacd.Value = value; }
/// <summary>
/// Enable moving average filter.
/// </summary>
public bool EnableMa { get => _enableMa.Value; set => _enableMa.Value = value; }
/// <summary>
/// Enable CCI filter.
/// </summary>
public bool EnableCci { get => _enableCci.Value; set => _enableCci.Value = value; }
/// <summary>
/// Enable ADX filter.
/// </summary>
public bool EnableAdx { get => _enableAdx.Value; set => _enableAdx.Value = value; }
/// <summary>
/// Candle type used by the strategy.
/// </summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Initializes a new instance of <see cref="CyberiaTraderStrategy"/>.
/// </summary>
public CyberiaTraderStrategy()
{
_macdFast = Param(nameof(MacdFast), 12)
.SetGreaterThanZero()
.SetDisplay("MACD Fast Period", "Fast EMA period for MACD", "Indicators");
_macdSlow = Param(nameof(MacdSlow), 26)
.SetGreaterThanZero()
.SetDisplay("MACD Slow Period", "Slow EMA period for MACD", "Indicators");
_macdSignal = Param(nameof(MacdSignal), 9)
.SetGreaterThanZero()
.SetDisplay("MACD Signal Period", "Signal MA period for MACD", "Indicators");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Length of moving average", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "Length of CCI", "Indicators");
_adxPeriod = Param(nameof(AdxPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ADX Period", "Length of ADX", "Indicators");
_enableMacd = Param(nameof(EnableMacd), true)
.SetDisplay("Enable MACD", "Use MACD direction filter", "Logic");
_enableMa = Param(nameof(EnableMa), true)
.SetDisplay("Enable MA", "Use moving average trend filter", "Logic");
_enableCci = Param(nameof(EnableCci), true)
.SetDisplay("Enable CCI", "Use CCI overbought/oversold filter", "Logic");
_enableAdx = Param(nameof(EnableAdx), true)
.SetDisplay("Enable ADX", "Use ADX directional filter", "Logic");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for strategy", "General");
Volume = 1;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_lastDirection = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_lastDirection = 0;
_macd = new MovingAverageConvergenceDivergenceSignal
{
Macd =
{
ShortMa = { Length = MacdFast },
LongMa = { Length = MacdSlow },
},
SignalMa = { Length = MacdSignal }
};
_ma = new SMA { Length = MaPeriod };
_cci = new CommodityChannelIndex { Length = CciPeriod };
_adx = new AverageDirectionalIndex { Length = AdxPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(_macd, _ma, _cci, _adx, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ma);
DrawOwnTrades(area);
var indicatorArea = CreateChartArea();
if (indicatorArea != null)
{
DrawIndicator(indicatorArea, _macd);
DrawIndicator(indicatorArea, _cci);
DrawIndicator(indicatorArea, _adx);
}
}
StartProtection(new Unit(2m, UnitTypes.Percent), new Unit(1m, UnitTypes.Percent));
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdVal, IIndicatorValue maVal, IIndicatorValue cciVal, IIndicatorValue adxVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
var adxTyped = (AverageDirectionalIndexValue)adxVal;
var disableBuy = false;
var disableSell = false;
if (EnableMacd)
{
var macd = macdTyped.Macd ?? 0m;
var signal = macdTyped.Signal ?? 0m;
if (macd > signal)
disableSell = true;
else if (macd < signal)
disableBuy = true;
}
if (EnableMa)
{
var ma = maVal.ToDecimal();
if (candle.ClosePrice > ma)
disableSell = true;
else if (candle.ClosePrice < ma)
disableBuy = true;
}
if (EnableCci)
{
var cci = cciVal.ToDecimal();
if (cci > 100m)
disableBuy = true;
else if (cci < -100m)
disableSell = true;
}
if (EnableAdx)
{
var plus = adxTyped.Dx.Plus ?? 0m;
var minus = adxTyped.Dx.Minus ?? 0m;
if (plus > minus)
disableSell = true;
else if (minus > plus)
disableBuy = true;
}
var direction = !disableBuy && disableSell ? 1 : !disableSell && disableBuy ? -1 : 0;
if (direction == 1 && _lastDirection != 1 && Position <= 0)
{
BuyMarket();
}
else if (direction == -1 && _lastDirection != -1 && Position >= 0)
{
SellMarket();
}
_lastDirection = direction;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import (
MovingAverageConvergenceDivergenceSignal,
SimpleMovingAverage as SMA,
CommodityChannelIndex,
AverageDirectionalIndex,
)
from StockSharp.Algo.Strategies import Strategy
class cyberia_trader_strategy(Strategy):
def __init__(self):
super(cyberia_trader_strategy, self).__init__()
self._macd_fast = self.Param("MacdFast", 12)
self._macd_slow = self.Param("MacdSlow", 26)
self._macd_signal = self.Param("MacdSignal", 9)
self._ma_period = self.Param("MaPeriod", 20)
self._cci_period = self.Param("CciPeriod", 14)
self._adx_period = self.Param("AdxPeriod", 14)
self._enable_macd = self.Param("EnableMacd", True)
self._enable_ma = self.Param("EnableMa", True)
self._enable_cci = self.Param("EnableCci", True)
self._enable_adx = self.Param("EnableAdx", True)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._last_direction = 0
self.Volume = 1
@property
def MacdFast(self):
return self._macd_fast.Value
@MacdFast.setter
def MacdFast(self, value):
self._macd_fast.Value = value
@property
def MacdSlow(self):
return self._macd_slow.Value
@MacdSlow.setter
def MacdSlow(self, value):
self._macd_slow.Value = value
@property
def MacdSignal(self):
return self._macd_signal.Value
@MacdSignal.setter
def MacdSignal(self, value):
self._macd_signal.Value = value
@property
def MaPeriod(self):
return self._ma_period.Value
@MaPeriod.setter
def MaPeriod(self, value):
self._ma_period.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def AdxPeriod(self):
return self._adx_period.Value
@AdxPeriod.setter
def AdxPeriod(self, value):
self._adx_period.Value = value
@property
def EnableMacd(self):
return self._enable_macd.Value
@EnableMacd.setter
def EnableMacd(self, value):
self._enable_macd.Value = value
@property
def EnableMa(self):
return self._enable_ma.Value
@EnableMa.setter
def EnableMa(self, value):
self._enable_ma.Value = value
@property
def EnableCci(self):
return self._enable_cci.Value
@EnableCci.setter
def EnableCci(self, value):
self._enable_cci.Value = value
@property
def EnableAdx(self):
return self._enable_adx.Value
@EnableAdx.setter
def EnableAdx(self, value):
self._enable_adx.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(cyberia_trader_strategy, self).OnStarted2(time)
self._last_direction = 0
self._macd = MovingAverageConvergenceDivergenceSignal()
self._macd.Macd.ShortMa.Length = self.MacdFast
self._macd.Macd.LongMa.Length = self.MacdSlow
self._macd.SignalMa.Length = self.MacdSignal
self._ma = SMA()
self._ma.Length = self.MaPeriod
self._cci = CommodityChannelIndex()
self._cci.Length = self.CciPeriod
self._adx = AverageDirectionalIndex()
self._adx.Length = self.AdxPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(self._macd, self._ma, self._cci, self._adx, self.ProcessCandle).Start()
self.StartProtection(Unit(2, UnitTypes.Percent), Unit(1, UnitTypes.Percent))
def ProcessCandle(self, candle, macd_val, ma_val, cci_val, adx_val):
if candle.State != CandleStates.Finished:
return
macd_typed = macd_val
adx_typed = adx_val
disable_buy = False
disable_sell = False
if self.EnableMacd:
macd = float(macd_typed.Macd) if macd_typed.Macd is not None else 0.0
signal = float(macd_typed.Signal) if macd_typed.Signal is not None else 0.0
if macd > signal:
disable_sell = True
elif macd < signal:
disable_buy = True
if self.EnableMa:
ma = float(ma_val)
if float(candle.ClosePrice) > ma:
disable_sell = True
elif float(candle.ClosePrice) < ma:
disable_buy = True
if self.EnableCci:
cci = float(cci_val)
if cci > 100.0:
disable_buy = True
elif cci < -100.0:
disable_sell = True
if self.EnableAdx:
plus_val = float(adx_typed.Dx.Plus) if adx_typed.Dx.Plus is not None else 0.0
minus_val = float(adx_typed.Dx.Minus) if adx_typed.Dx.Minus is not None else 0.0
if plus_val > minus_val:
disable_sell = True
elif minus_val > plus_val:
disable_buy = True
if not disable_buy and disable_sell:
direction = 1
elif not disable_sell and disable_buy:
direction = -1
else:
direction = 0
if direction == 1 and self._last_direction != 1 and self.Position <= 0:
self.BuyMarket()
elif direction == -1 and self._last_direction != -1 and self.Position >= 0:
self.SellMarket()
self._last_direction = direction
def OnReseted(self):
super(cyberia_trader_strategy, self).OnReseted()
self._last_direction = 0
def CreateClone(self):
return cyberia_trader_strategy()