Данная стратегия переносит логику MT4-советника «Simple Martingale Template» в инфраструктуру StockSharp. Анализируются завершённые свечи выбранного таймфрейма. Для генерации сигналов используются две простые скользящие средние (SMA) и фильтр пробоя: закрытие предыдущей свечи должно выйти за максимум или минимум свечи двумя барами ранее. Объём позиции управляется по схеме мартингейла — после убыточного цикла объём умножается, после прибыльного цикла возвращается к базовому значению.
Логика торговли
Подписка на свечи таймфрейма CandleType. В расчётах участвуют только закрытые свечи.
Расчёт быстрых и медленных SMA по цене закрытия.
Покупка открывается, если:
закрытие последней свечи выше быстрой SMA,
быстрая SMA выше медленной,
на предыдущей свече быстрая SMA была ниже медленной,
закрытие последней свечи выше максимума свечи двумя барами ранее.
Продажа открывается при зеркально противоположных условиях и закрытии ниже минимума свечи двумя барами ранее.
При появлении сигнала и отсутствии позиции/активных заявок стратегия отправляет рыночный ордер с текущим объёмом мартингейла.
Стоп-лосс и тейк-профит реализованы программно: после входа хранятся целевые цены, и при касании этих уровней по максимуму/минимуму новой свечи позиция закрывается рыночным ордером.
После закрытия позиции анализируется изменение баланса портфеля:
рост баланса приводит к возврату объёма к BaseVolume;
падение баланса умножает предыдущий объём на Multiplier с учётом шага объёма инструмента.
Параметры
Название
Описание
StopLossPoints
Расстояние до защитного стопа в пунктах.
TakeProfitPoints
Расстояние до тейк-профита в пунктах.
BaseVolume
Базовый лот первого шага мартингейла.
Multiplier
Множитель объёма после убыточной сделки.
FastPeriod
Период быстрой SMA.
SlowPeriod
Период медленной SMA.
CandleType
Таймфрейм анализируемых свечей.
Управление капиталом
Изменение объёма происходит только при фиксации результата и отсутствии позиций; мелкие колебания (±0.01 денежной единицы) игнорируются.
Перед постановкой ордеров объём округляется к допустимому шагу, учитываются минимальные и максимальные ограничения инструмента.
Стоп и тейк контролируются по экстремумам свечей, что повторяет механику оригинального советника, использовавшего рыночные выходы.
Рекомендации по использованию
Подбирайте таймфрейм и инструмент так, чтобы SMA успели сформироваться (требуются как минимум два закрытых бара до запуска логики).
Значения StopLossPoints и TakeProfitPoints задаются в пунктах, поэтому их необходимо адаптировать к размеру шага цены выбранного инструмента.
Контролируйте агрессивность мартингейла: при больших множителях капитал требования быстро возрастают.
Стратегия вызывает StartProtection(), поэтому стандартные защитные механизмы StockSharp продолжают работать совместно.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Simple Martingale Template strategy: SMA crossover with momentum confirmation.
/// Buys on fast SMA crossing above slow SMA, sells on crossing below.
/// </summary>
public class SimpleMartingaleTemplateStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
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 SimpleMartingaleTemplateStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
BuyMarket();
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
SellMarket();
}
else
{
if (fastValue > slowValue && Position <= 0)
BuyMarket();
else if (fastValue < slowValue && Position >= 0)
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
}
}