Стратегия воспроизводит советник MetaTrader Exp_BrainTrend2_AbsolutelyNoLagLwma_MMRec, объединяя два блока сигналов: трендовый блок BrainTrend2 и адаптивный фильтр AbsolutelyNoLagLWMA. Каждый блок может открывать и закрывать позиции в соответствии со своими разрешениями, как в MMRec-шаблоне оригинала. Заявки исполняются рыночными ордерами через высокоуровневый API StockSharp с настраиваемым объёмом.
Логика торговли
Блок BrainTrend2
Формирует плавающий уровень на основе взвешенного истинного диапазона (ATR).
Направление («river») меняется, когда свеча пробивает буфер более чем на 0.7 * ATR.
Бычья свеча внутри восходящего режима открывает лонг (если разрешено) и закрывает шорт.
Медвежья свеча внутри нисходящего режима открывает шорт (если разрешено) и закрывает лонг.
Параметр Brain Signal Shift позволяет сдвигать анализируемую свечу назад на несколько баров.
Блок AbsolutelyNoLagLWMA
Применяет два последовательных линейно взвешенных скользящих средних к выбранному источнику цены.
Цвет линии становится 2 при росте двойной LWMA, 0 при снижении и 1 при нейтральном состоянии.
Переход к цвету 2 даёт сигнал на покупку и (опционально) закрытие шортов; переход к цвету 0 даёт сигнал на продажу и (опционально) закрытие лонгов.
Сдвиг сигналов регулируется параметром Abs Signal Shift.
Управление позицией
Стратегия ведёт одну нетто-позицию. Если оба блока подают сигнал одновременно, команды на закрытие исполняются до новых входов.
Если блок пытается открыть позицию, а противоположная уже активна и её закрытие запрещено, вход пропускается (аналогично невозможности хеджирования при единой нетто-позиции).
Параметры
Группа
Название
Описание
BrainTrend2
Brain Candle
Тип свечей для расчёта BrainTrend2.
BrainTrend2
Brain ATR
Период ATR для внутренней логики BrainTrend2.
BrainTrend2
Brain Signal Shift
Сдвиг сигналов BrainTrend2 по истории.
BrainTrend2
Brain Buy / Sell
Разрешение на открытие лонгов/шортов блоком BrainTrend2.
BrainTrend2
Brain Close Buys / Close Sells
Разрешение блоку BrainTrend2 закрывать существующие позиции.
AbsolutelyNoLag
Abs Candle
Тип свечей для фильтра LWMA.
AbsolutelyNoLag
Abs Length
Период LWMA.
AbsolutelyNoLag
Abs Price
Источник цены (аналог перечисления Applied_price_ в MQL).
AbsolutelyNoLag
Abs Signal Shift
Сдвиг сигналов LWMA по истории.
AbsolutelyNoLag
Abs Buy / Sell
Разрешение на открытие лонгов/шортов блоком LWMA.
AbsolutelyNoLag
Abs Close Buys / Close Sells
Разрешение LWMA закрывать позиции.
AbsolutelyNoLag
Abs Shift
Постоянный сдвиг значения LWMA.
General
Order Volume
Базовый объём рыночных ордеров.
Примечания
Формулы ATR и LWMA перенесены из MQL-версии, включая треугольное взвешивание и полный список источников цены.
В свечах StockSharp нет данных о спреде, поэтому истинный диапазон рассчитывается только по ценам, что эквивалентно нулевому спреду.
Одновременные позиции с разными magic-номерами сведены к одной нетто-позиции, что соответствует модели портфеля в StockSharp.
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>
/// BrainTrend2 AbsolutelyNoLag LWMA MMRec strategy (simplified).
/// Uses RSI + EMA for trend detection with position recovery logic.
/// </summary>
public class BrainTrend2AbsolutelyNoLagLwmaMmrecStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _emaLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public BrainTrend2AbsolutelyNoLagLwmaMmrecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
_emaLength = Param(nameof(EmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ema, (ICandleMessage candle, decimal rsiVal, decimal emaVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
// Bullish: RSI above 55 and close above EMA
if (rsiVal > 55 && close > emaVal && Position <= 0)
BuyMarket();
// Bearish: RSI below 45 and close below EMA
else if (rsiVal < 45 && close < emaVal && Position >= 0)
SellMarket();
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
}
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 RelativeStrengthIndex, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class brain_trend2_absolutely_no_lag_lwma_mmrec_strategy(Strategy):
def __init__(self):
super(brain_trend2_absolutely_no_lag_lwma_mmrec_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "EMA period", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def EmaLength(self):
return self._ema_length.Value
def OnStarted2(self, time):
super(brain_trend2_absolutely_no_lag_lwma_mmrec_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiLength
ema = ExponentialMovingAverage()
ema.Length = self.EmaLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
rv = float(rsi_value)
ev = float(ema_value)
if rv > 55 and close > ev and self.Position <= 0:
self.BuyMarket()
elif rv < 45 and close < ev and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return brain_trend2_absolutely_no_lag_lwma_mmrec_strategy()