MelBar Take325 — порт стратегии "MelBar™Take325%™ 5.5Y NZD-USD" из Expert Advisor Studio. Она торгует парой NZD/USD в обе стороны, используя всплеск тикового объёма, разворот простого скользящего среднего с периодом 12 и выход по RSI с периодом 14. В версии для StockSharp сохранены исходные рисковые параметры: стоп-лосс 16 пунктов и тейк-профит 45 пунктов, измеряемые в пунктах от цены входа.
Сначала стратегия ждёт прорыва тикового объёма выше заданного уровня. Как только объём расширяется, проверяется, сформировала ли простая скользящая средняя локальный разворот двумя барами ранее. Локальный максимум SMA даёт сигнал на покупку, локальный минимум — на продажу. При одновременных сигналах позиция не открывается, чтобы избежать последовательных разворотов в ту же свечу.
Открытые позиции постоянно контролируются. На каждом закрытии свечи проверяются уровни стоп-лосса и тейк-профита — так же, как в MetaTrader. Дополнительно используется RSI: длинные позиции закрываются, когда RSI пересекает вниз заданный уровень (по умолчанию 80), короткие — когда RSI пересекает вверх симметричный уровень (по умолчанию 20). Для фиксации стопов и целей сравниваются максимум и минимум обработанной свечи с ценой входа.
Детали
Условия входа:
Фильтр объёма: объём два бара назад ниже порога, предыдущий бар превышает порог.
Покупка: SMA (период 12) формирует локальный максимум (SMA[t-3] < SMA[t-2] и SMA[t-2] > SMA[t-1]).
Продажа: SMA формирует локальный минимум (SMA[t-3] > SMA[t-2] и SMA[t-2] < SMA[t-1]).
Условия выхода:
Стоп-лосс: 16 пунктов от входа, проверяется на закрытии свечи.
Тейк-профит: 45 пунктов от входа, проверяется на закрытии свечи.
Выход по RSI для покупок: RSI пересекает уровень 80 сверху вниз (RSI[t-3] > 80 и RSI[t-2] < 80).
Выход по RSI для продаж: RSI пересекает уровень 20 снизу вверх (RSI[t-3] < 20 и RSI[t-2] > 20).
Параметры по умолчанию:
Объём входа = 0.1 лота.
Порог объёма = 1000 тиков.
Период SMA = 12.
Период RSI = 14.
Уровень RSI = 80 (для коротких используется 100 - уровень).
Таймфрейм свечей = 30 минут.
Рынок: рассчитана на NZD/USD, но может применяться к другим валютным парам.
Стиль: пробой импульса с выходами против тренда.
Стопы: фиксированные стоп-лосс и тейк-профит, без трейлинга.
Сложность: средняя — несколько фильтров, но без наращивания позиции.
Риск: средний, стоп-лосс меньше тейк-профита, но оба фиксированы.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MelBar Take325 strategy: SMA reversal with RSI exit filter.
/// Enters on SMA direction change, exits when RSI reaches extreme levels.
/// </summary>
public class MelBarTake325Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiExitLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevSma;
private decimal _prevPrevSma;
private bool _hasPrev2;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiExitLevel { get => _rsiExitLevel.Value; set => _rsiExitLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public MelBarTake325Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_smaPeriod = Param(nameof(SmaPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_rsiExitLevel = Param(nameof(RsiExitLevel), 75m)
.SetDisplay("RSI Exit Level", "RSI level to close long; 100-level closes short", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 8)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevSma = 0m;
_prevPrevSma = 0m;
_hasPrev2 = false;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev2 = false;
_candlesSinceTrade = SignalCooldownCandles;
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sma, decimal rsi)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev2)
{
// Exit on RSI extremes
if (Position > 0 && rsi > RsiExitLevel)
{
SellMarket();
_candlesSinceTrade = 0;
}
else if (Position < 0 && rsi < (100 - RsiExitLevel))
{
BuyMarket();
_candlesSinceTrade = 0;
}
// Entry on SMA reversal (peak/trough)
if (Position == 0 && _candlesSinceTrade >= SignalCooldownCandles && _prevPrevSma > _prevSma && _prevSma < sma)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (Position == 0 && _candlesSinceTrade >= SignalCooldownCandles && _prevPrevSma < _prevSma && _prevSma > sma)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevPrevSma = _prevSma;
_prevSma = sma;
_hasPrev2 = true;
}
}