Swetten es una estrategia de ruptura impulsada por una red neuronal que se distribuyó originalmente durante MetaTrader 4. Evalúa el diferencial entre un promedio móvil simple de 233 períodos a largo plazo y diez promedios móviles más rápidos calculados en velas de un minuto. Los diferenciales se introducen en una red de base radial que produce un nivel de activación alcista o bajista. Cuando la activación es positiva la estrategia entra en largo, cuando es negativa entra en corto.
Mercado y plazo
Diseñado para los principales pares de divisas (el código original apuntaba al EURUSD).
El análisis utiliza velas de un minuto y las decisiones se toman sólo sobre velas completas.
Las señales se evalúan cada dos horas al final de la hora (00:00, 02:00, …, 22:00 hora de cambio). No se abren operaciones los sábados ni los domingos.
Indicadores y características
Medias móviles simples con períodos: 233 (línea de base), 144, 89, 55, 34, 21, 13, 8, 5, 3, 2.
Las entradas de la red neuronal son las diferencias entre el promedio de 233 períodos y cada promedio más rápido.
Antes de pasar a la red, las entradas se fijan en rangos entrenados, se normalizan y se escalan con los mismos coeficientes utilizados en la DLL original.
La red de base radial se replica exactamente a partir de la función EURUSDn exportada, que consta de 38 características gaussianas cuyas salidas se promedian para obtener la activación final.
Reglas de trading
Espere el cierre de una vela de un minuto que finaliza en una hora par y cae en un día laborable.
Calcule la activación de la red neuronal a partir de los diferenciales de media móvil.
Si la activación > 0 y la posición actual no es larga, envíe una compra de mercado por TradeVolume + abs(current position) lotes.
Si la activación < 0 y la posición actual no es corta, envíe una venta de mercado por TradeVolume + abs(current position) lotes.
Las posiciones están protegidas por:
Una toma de ganancias fija definida en pasos de precio (TakeProfitPoints).
Un stop loss fijo definido en pasos de precio (StopLossPoints).
Cuando se toca cualquiera de los niveles utilizando los extremos alto/bajo de la vela, la posición se cierra mediante una orden de mercado.
Parámetros
Nombre
Descripción
Predeterminado
CandleType
Serie de velas utilizadas para los cálculos.
marco de tiempo de 1 minuto
TradeVolume
Volumen base de pedidos en lotes.
0.1
SlowPeriod
Período de la media móvil simple de referencia.
233
TakeProfitPoints
Distancia objetivo de beneficio en pasos de precio.
150
StopLossPoints
Distancia de stop-loss en pasos de precio.
40
Notas de conversión
La red neuronal basada en DLL de MetaTrader se transfirió completamente a C# traduciendo la función exportada a código administrado.
Las salidas protectoras imitan las condiciones OrderClose originales al comparar los máximos y mínimos de las velas con los umbrales de los escalones de precios.
La gestión de entradas realiza un seguimiento del último precio de cumplimiento a través de OnNewMyTrade para alinear las salidas con los cumplimientos reales.
Todos los comentarios se reescribieron en inglés y el código utiliza API StockSharp de alto nivel (SubscribeCandles, Bind) según lo exigen las pautas de conversión.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Swetten strategy: multi-SMA spread crossover system.
/// Uses fast SMA (5) and slow SMA (50) to generate trend signals.
/// Buys when fast crosses above slow, sells when fast crosses below slow.
/// </summary>
public class SwettenStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _isReady;
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 SwettenStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy", "General");
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 34)
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_isReady = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_isReady = false;
var fast = new SMA { Length = FastPeriod };
var slow = new SMA { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, OnProcess)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void OnProcess(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_isReady)
{
_prevFast = fastVal;
_prevSlow = slowVal;
_isReady = true;
return;
}
// Fast crosses above slow = buy
if (_prevFast <= _prevSlow && fastVal > slowVal)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
// Fast crosses below slow = sell
else if (_prevFast >= _prevSlow && fastVal < slowVal)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}
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
class swetten_strategy(Strategy):
"""Fast/slow SMA crossover (8/34)."""
def __init__(self):
super(swetten_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 8).SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 34).SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle type for strategy", "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(swetten_strategy, self).OnReseted()
self._prev_fast = 0
self._prev_slow = 0
self._is_ready = False
def OnStarted2(self, time):
super(swetten_strategy, self).OnStarted2(time)
self._prev_fast = 0
self._prev_slow = 0
self._is_ready = False
fast = SimpleMovingAverage()
fast.Length = self._fast_period.Value
slow = SimpleMovingAverage()
slow.Length = self._slow_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(fast, slow, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def OnProcess(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if not self._is_ready:
self._prev_fast = fast_val
self._prev_slow = slow_val
self._is_ready = True
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast_val < slow_val:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return swetten_strategy()