La estrategia Nina EA es un seguidor de tendencias de una posición convertido del experto MetaTrader 4 "NinaEA". El robot original utiliza un indicador personalizado llamado NINA y opera cada vez que la diferencia entre los amortiguadores alcistas y bajistas del indicador cruza por encima o por debajo de cero. En la versión StockSharp, el indicador personalizado se reemplaza con el indicador SuperTrend incorporado, que también publica buffers alcistas y bajistas separados. Un cambio en la dirección de SuperTrend sirve como indicador de cruce por cero: cuando la tendencia se vuelve alcista, la estrategia compra, y cuando se vuelve bajista, vende.
La estrategia siempre mantiene como máximo una posición abierta. Una señal opuesta cierra inmediatamente la posición existente y establece una nueva operación en la nueva dirección. Se puede habilitar un stop-loss opcional expresado en puntos de precio para imitar la entrada original "StopLoss".
Lógica de trading
Suscríbase a la serie de velas configuradas y calcule SuperTrend con el período y el multiplicador ATR suministrados.
Espere hasta que se formen tanto la estrategia como el indicador antes de reaccionar a las señales.
En cada vela completa:
Si se toca un precio stop protector, salga de la posición abierta en el mercado.
Si SuperTrend cambia de bajista a alcista, cierre cualquier exposición corta y compre con el volumen configurado.
Si SuperTrend cambia de alcista a bajista, cierre cualquier exposición larga y venda con el volumen configurado.
Almacene la dirección actual de SuperTrend para detectar el siguiente giro.
La lógica replica el comportamiento del experto MetaTrader, donde nina = Buffer0 - Buffer1 y un cambio de signo impulsan tanto las salidas como las nuevas entradas.
Gestión de posiciones y riesgos
Sólo puede haber una posición activa a la vez; todas las operaciones invierten la dirección en lugar de acumular varias órdenes.
Un stop-loss opcional en puntos de precio se calcula a partir del precio de cumplimiento. Para una operación larga, el stop se coloca debajo de la entrada y para una operación corta, se coloca encima de la entrada. Poner el parámetro a cero desactiva la parada.
Se llama a StartProtection() para que se puedan configurar las protecciones integradas StockSharp si se desea.
Parámetros
Parámetro
Predeterminado
Descripción
Volume
0.1
Volumen de pedidos utilizado para cada nueva entrada.
AtrPeriod
10
periodo ATR pasado al cálculo de SuperTrend (mapa el PeriodWATR original).
AtrMultiplier
1
multiplicador ATR para SuperTrend (asigna el Kwatr original).
StopLossPoints
0
Distancia de stop-loss opcional en puntos de precio. Zero mantiene el stop deshabilitado, idéntico al código MetaTrader que enviaba órdenes de mercado sin precio de stop.
CandleType
TimeFrame(1 minute)
Serie de velas que alimenta el indicador y la lógica comercial.
Notas de conversión
El experto MetaTrader se basó en el indicador personalizado NINA. Sus dos amortiguadores se interpretaron como líneas SuperTrend alcistas/bajistas porque sólo su diferencia y su signo importaban para el trading. SuperTrend expone la misma información a través de su indicador IsUpTrend, lo que lo convierte en un reemplazo de alto nivel adecuado que no requiere manejo manual del búfer.
La lógica de cierre de órdenes refleja el bucle OrdersTotal() del guión original: un cambio de tendencia primero favorece la posición actual y luego abre una operación en la nueva dirección.
Las entradas MetaTrader no utilizadas (highlow, cbars, from, maP, SMAspread, Slippage) se omiten porque no influyen en las reglas comerciales del archivo original.
Consejos de uso
Adjunte la estrategia a un valor y configure el período de vela que coincida con su prueba MetaTrader.
Ajuste el período ATR y el multiplicador para replicar el comportamiento del indicador original.
Aumente StopLossPoints si desea un límite de riesgo estricto; de lo contrario, déjelo en cero para salidas basadas puramente en señales.
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>
/// SuperTrend-based strategy from NinaEA.
/// Trades on SuperTrend direction flips - buy on up trend, sell on down trend.
/// </summary>
public class NinaEaStrategy : Strategy
{
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _atrMultiplier;
private readonly StrategyParam<DataType> _candleType;
private bool? _previousTrendUp;
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public decimal AtrMultiplier { get => _atrMultiplier.Value; set => _atrMultiplier.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public NinaEaStrategy()
{
_atrPeriod = Param(nameof(AtrPeriod), 10)
.SetDisplay("ATR Period", "ATR length for SuperTrend", "Indicators");
_atrMultiplier = Param(nameof(AtrMultiplier), 1m)
.SetDisplay("ATR Multiplier", "SuperTrend multiplier", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousTrendUp = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_previousTrendUp = null;
var superTrend = new SuperTrend
{
Length = AtrPeriod,
Multiplier = AtrMultiplier
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(superTrend, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue superTrendValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!superTrendValue.IsFinal)
return;
var stValue = (SuperTrendIndicatorValue)superTrendValue;
var isUpTrend = stValue.IsUpTrend;
if (_previousTrendUp is bool prevUp)
{
// Trend flipped to up - go long
if (isUpTrend && !prevUp)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
// Trend flipped to down - go short
else if (!isUpTrend && prevUp)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
_previousTrendUp = isUpTrend;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SuperTrend
from StockSharp.Algo.Strategies import Strategy
class nina_ea_strategy(Strategy):
"""SuperTrend-based strategy. Trades on SuperTrend direction flips.
Go long on up trend, go short on down trend."""
def __init__(self):
super(nina_ea_strategy, self).__init__()
self._atr_period = self.Param("AtrPeriod", 10) \
.SetDisplay("ATR Period", "ATR length for SuperTrend", "Indicators")
self._atr_multiplier = self.Param("AtrMultiplier", 1.0) \
.SetDisplay("ATR Multiplier", "SuperTrend multiplier", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._previous_trend_up = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def AtrPeriod(self):
return self._atr_period.Value
@property
def AtrMultiplier(self):
return self._atr_multiplier.Value
def OnReseted(self):
super(nina_ea_strategy, self).OnReseted()
self._previous_trend_up = None
def OnStarted2(self, time):
super(nina_ea_strategy, self).OnStarted2(time)
self._previous_trend_up = None
super_trend = SuperTrend()
super_trend.Length = self.AtrPeriod
super_trend.Multiplier = self.AtrMultiplier
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(super_trend, self._process_candle).Start()
def _process_candle(self, candle, super_trend_value):
if candle.State != CandleStates.Finished:
return
if not super_trend_value.IsFinal:
return
is_up_trend = super_trend_value.IsUpTrend if hasattr(super_trend_value, 'IsUpTrend') else None
if is_up_trend is None:
return
if self._previous_trend_up is not None:
prev_up = self._previous_trend_up
# Trend flipped to up - go long
if is_up_trend and not prev_up:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
# Trend flipped to down - go short
elif not is_up_trend and prev_up:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._previous_trend_up = is_up_trend
def CreateClone(self):
return nina_ea_strategy()