Neuro Nirvaman EA 2 — это переработанная под StockSharp версия одноимённого советника из MetaTrader 5. Стратегия строится на трёхслойной системе перцептронов, которая объединяет четыре Laguerre-фильтра +DI и два детектора SilverTrend. Каждый завершённый бар пересчитывает выходы перцептронов, после чего модуль supervisor принимает решение об открытии позиции согласно выбранному режиму Pass. Сделки допускаются только внутри заданного торгового окна, по его завершении позиции принудительно закрываются.
Индикаторы и сигналы
Laguerre +DI — каждый блок получает линию +DI индикатора ADX и сглаживает её фильтром Laguerre с γ = 0.764. Значение колеблется в диапазоне [0;1] и сравнивается с центральным уровнем 0.5 и пользовательским отступом.
SilverTrend — два канала SilverTrend рассчитывают динамические уровни поддержки/сопротивления по последним девяти барам. Параметр риска изменяет ширину коридора (K = 33 - risk). Изменение направления канала формирует сигнал ±1, поступающий на вход перцептронов.
Торговая логика
Перцептрон №1: сочетает «напряжение» от Laguerre #1 и breakout-сигнал SilverTrend #1. Веса X11 и X12 уменьшаются на 100 — как и в оригинальном коде.
Перцептрон №2: аналог первой модели, но использует Laguerre #2 и SilverTrend #2 с весами X21 и X22.
Перцептрон №3: суммирует напряжения Laguerre #3 и Laguerre #4 с весами X31 и X32.
Supervisor (Pass):
1 — торгует только сигнал перцептрона №1 (значение < 0 — короткая позиция, иначе — длинная).
2 — торгует по перцептрону №2 (значение > 0 — покупка, иначе — продажа).
3 — открывает лонг при положительных значениях перцептронов №3 и №2; открывает шорт, если перцептрон №3 ≤ 0 и перцептрон №1 < 0.
4 — режим защиты: сделки не совершаются (соответствует стандартной настройке советника).
При входе стратегия отправляет рыночную заявку фиксированного объёма и запоминает уровни стоп-лосса и тейк-профита в шагах цены. На каждом завершённом баре проверяется, достиг ли максимум/минимум этих уровней; при срабатывании позиция закрывается. Выход за границы торгового окна также приводит к закрытию.
Параметры
Параметр
Описание
Risk1, Risk2
Риск-параметры SilverTrend: чем выше значение, тем уже канал и чаще сигналы.
LaguerreXPeriod
Длина ADX, из которого берётся линия +DI для соответствующего фильтра Laguerre.
LaguerreXDistance
Процентный отступ от центра 0.5, определяющий границы зоны перекупленности/перепроданности.
X11, X12, X21, X22, X31, X32
Веса перцептронов (внутри формулы из значения вычитается 100).
TakeProfit1, StopLoss1, TakeProfit2, StopLoss2
Размеры тейк-профита и стоп-лосса в шагах цены для соответствующих сигналов.
Pass
Режим supervisor (1–4).
TradeVolume
Базовый объём заявки.
StartHour, StartMinute, EndHour, EndMinute
Границы торговой сессии; вне окна сделки не открываются, позиции закрываются.
CandleType
Тип свечей, по которым работает стратегия.
Управление рисками
Используются только фиксированные стоп-лосс и тейк-профит; усреднение и наращивание позиции отсутствуют. Одновременно может быть открыта лишь одна позиция. При выходе цены за уровни защиты или при окончании торговой сессии сделка закрывается.
Примечания
Значение γ для фильтра Laguerre зафиксировано на 0.764, как в исходном индикаторе.
Режим Pass = 4 полностью блокирует торговлю и служит защитной настройкой по умолчанию.
Расчёт SilverTrend выполнен через стандартные индикаторы Highest/Lowest/SMA, что соответствует требованиям StockSharp и избавляет от ручного управления буферами.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// NeuroNirvaman EA 2 strategy. Uses DEMA crossover (10/30).
/// </summary>
public class NeuroNirvamanEa2Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
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 NeuroNirvamanEa2Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10).SetGreaterThanZero().SetDisplay("Fast DEMA", "Fast DEMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30).SetGreaterThanZero().SetDisplay("Slow DEMA", "Slow DEMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new DoubleExponentialMovingAverage { Length = FastPeriod };
var slow = new DoubleExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
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 DoubleExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class neuro_nirvaman_ea2_strategy(Strategy):
def __init__(self):
super(neuro_nirvaman_ea2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast DEMA", "Fast DEMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow DEMA", "Slow DEMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(neuro_nirvaman_ea2_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(neuro_nirvaman_ea2_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = DoubleExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = DoubleExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return neuro_nirvaman_ea2_strategy()