La estrategia Suffic369 es un sistema de ruptura que sigue tendencias y combina dos promedios móviles cortos con bandas Bollinger anchas. El asesor experto ingresa en posiciones largas cuando el promedio móvil simple rápido (SMA) de los precios de cierre cruza por encima del SMA de máximos recientes mientras el mercado cotiza cerca de la banda inferior Bollinger. Las posiciones cortas se abren cuando el SMA rápido cruza por debajo del SMA de los mínimos recientes mientras el precio presiona contra la banda superior. La versión convertida StockSharp mantiene la lógica original MQL pero la expresa con suscripciones de velas de alto nivel y enlaces de indicadores.
Indicadores
Rápido SMA (Cierre, longitud = 3) – mide la dirección a corto plazo del precio de cierre.
Máximo SMA (Máximo, longitud = 5) – promedia los máximos recientes y actúa como referencia de resistencia alcista.
Mínimo SMA (Mínimo, longitud = 5) – promedia los mínimos recientes y proporciona la referencia de soporte bajista.
Bollinger Bandas (longitud = 156, desviación = 1): identifica los precios extremos en relación con la volatilidad.
Todos los indicadores se actualizan con las velas completadas. Los valores anteriores se almacenan en caché para reproducir el desplazamiento de una barra utilizado en el programa MetaTrader original.
Reglas de trading
Entrada larga
El rápido anterior SMA (cierre) está por debajo del máximo anterior SMA.
El rápido actual SMA (cerrado) cruza por encima del máximo actual SMA.
El precio de cierre de la vela está por debajo de la banda inferior Bollinger.
Entrada corta
El rápido anterior SMA (cierre) está por encima del mínimo anterior SMA.
El SMA rápido actual (cerrado) cruza por debajo del mínimo actual SMA.
El precio de cierre de la vela está por encima de la banda superior Bollinger.
Salir de la lógica
Señal opuesta: Una posición larga se cierra cuando aparece una nueva señal de entrada corta, y viceversa.
Stop-Loss: Stop opcional basado en pasos de precio que protege la posición una vez activada.
Take-Profit: Objetivo opcional basado en pasos de precio que refleja el parámetro TakeProfit original.
Trailing Stop: Trailing stop opcional que se ajusta detrás de las operaciones rentables exactamente como la lógica MQL (utiliza el cierre actual para mover el stop solo cuando las ganancias exceden la distancia configurada).
La estrategia mantiene como máximo una posición a la vez. Después de que una señal de parada, objetivo u opuesta cierra la operación, no se evalúa ninguna nueva entrada hasta la siguiente vela terminada.
Parámetros
Nombre
Predeterminado
Descripción
FastMaLength
3
Duración del rápido SMA basado en precios de cierre.
HighMaLength
5
Longitud del SMA calculada sobre los máximos de las velas.
LowMaLength
5
Longitud del SMA calculada sobre los mínimos de las velas.
BollingerLength
156
Tamaño de ventana de las Bollinger Bandas.
BollingerDeviation
1
Multiplicador de desviación estándar para las bandas.
UseStopLoss
cierto
Habilita el bloque stop-loss.
StopLossPoints
30
Distancia de parada en pasos del precio del instrumento.
UseTakeProfit
cierto
Habilita el bloque de toma de ganancias.
TakeProfitPoints
60
Distancia objetivo de beneficio en pasos de precio.
UseTrailingStop
cierto
Permite la gestión de trailing stop.
TrailingStopPoints
30
Compensación final en los incrementos de precios.
CandleType
plazo de 15 minutos
Tipo de vela utilizada para los cálculos.
Todos los parámetros numéricos están expuestos como instancias StrategyParam<T> para que puedan optimizarse directamente dentro de StockSharp.
Gestión del riesgo
Los stop-loss, take-profit y trailing stop utilizan el paso del precio del instrumento (Security.PriceStep) para convertir distancias de puntos en precios absolutos.
Los trailingstops siguen movimientos rentables sólo cuando el precio ha avanzado más que la distancia configurada, replicando la lógica original de modificación de órdenes.
StartProtection() se invoca al inicio para habilitar las funciones de protección integradas de StockSharp.
Notas de uso
Suscríbase la estrategia a un instrumento que admita el tipo de vela seleccionado.
Asegúrese de que la propiedad Volume esté configurada en el tamaño comercial deseado antes de comenzar la estrategia.
La estrategia espera a que los valores de los indicadores estén completamente formados antes de emitir cualquier orden; Las velas iniciales se utilizan para generar el historial del indicador.
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>
/// Suffic369 breakout strategy based on fast/slow SMA crossover.
/// Buy when fast SMA crosses above slow SMA, sell when fast crosses below slow.
/// </summary>
public class Suffic369Strategy : Strategy
{
private readonly StrategyParam<int> _fastMaLength;
private readonly StrategyParam<int> _slowMaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
/// <summary>
/// Fast SMA length.
/// </summary>
public int FastMaLength
{
get => _fastMaLength.Value;
set => _fastMaLength.Value = value;
}
/// <summary>
/// Slow SMA length.
/// </summary>
public int SlowMaLength
{
get => _slowMaLength.Value;
set => _slowMaLength.Value = value;
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Suffic369Strategy"/> class.
/// </summary>
public Suffic369Strategy()
{
_fastMaLength = Param(nameof(FastMaLength), 3)
.SetDisplay("Fast SMA Length", "Fast moving average period", "Indicators");
_slowMaLength = Param(nameof(SlowMaLength), 6)
.SetDisplay("Slow SMA Length", "Slow moving average period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Primary candle source", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0m;
_prevSlow = 0m;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fastSma = new SimpleMovingAverage { Length = FastMaLength };
var slowSma = new SimpleMovingAverage { Length = SlowMaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastSma, slowSma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
// Buy signal: fast SMA crosses above slow SMA
var longSignal = _prevFast <= _prevSlow && fast > slow;
// Sell signal: fast SMA crosses below slow SMA
var shortSignal = _prevFast >= _prevSlow && fast < slow;
if (Position > 0 && shortSignal)
{
SellMarket();
}
else if (Position < 0 && longSignal)
{
BuyMarket();
}
else if (Position == 0)
{
if (longSignal)
BuyMarket();
else if (shortSignal)
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class suffic369_strategy(Strategy):
"""Fast/slow SMA crossover (3/6)."""
def __init__(self):
super(suffic369_strategy, self).__init__()
self._fast_ma_length = self.Param("FastMaLength", 3).SetDisplay("Fast SMA Length", "Fast moving average period", "Indicators")
self._slow_ma_length = self.Param("SlowMaLength", 6).SetDisplay("Slow SMA Length", "Slow moving average period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Primary candle source", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(suffic369_strategy, self).OnReseted()
self._prev_fast = 0
self._prev_slow = 0
self._has_prev = False
def OnStarted2(self, time):
super(suffic369_strategy, self).OnStarted2(time)
self._prev_fast = 0
self._prev_slow = 0
self._has_prev = False
fast_sma = SimpleMovingAverage()
fast_sma.Length = self._fast_ma_length.Value
slow_sma = SimpleMovingAverage()
slow_sma.Length = self._slow_ma_length.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(fast_sma, slow_sma, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, fast_sma)
self.DrawIndicator(area, slow_sma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
long_signal = self._prev_fast <= self._prev_slow and fast > slow
short_signal = self._prev_fast >= self._prev_slow and fast < slow
if self.Position > 0 and short_signal:
self.SellMarket()
elif self.Position < 0 and long_signal:
self.BuyMarket()
elif self.Position == 0:
if long_signal:
self.BuyMarket()
elif short_signal:
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return suffic369_strategy()