A estratégia Nina EA é uma seguidora de tendência de uma posição convertida do especialista MetaTrader 4 "NinaEA". O robô original usa um indicador personalizado chamado NINA e negocia sempre que a diferença entre os buffers de alta e de baixa do indicador ultrapassa acima ou abaixo de zero. Na versão StockSharp, o indicador personalizado é substituído pelo indicador integrado SuperTrend, que também publica buffers separados de alta e baixa. Uma mudança na direção da SuperTrend serve como proxy de cruzamento zero: quando a tendência se torna de alta, a estratégia compra, e quando se torna de baixa, ela vende.
A estratégia sempre mantém no máximo uma posição aberta. Um sinal oposto fecha imediatamente a posição existente e estabelece uma nova negociação na nova direção. Um stop-loss opcional expresso em faixas de preço pode ser habilitado para imitar a entrada "StopLoss" original.
Lógica de negociação
Assine a série de velas configurada e calcule o SuperTrend com o período ATR e o multiplicador fornecidos.
Espere até que a estratégia e o indicador sejam formados antes de reagir aos sinais.
Em cada vela concluída:
Se um preço stop protetor for tocado, saia da posição aberta no mercado.
Se o SuperTrend mudar de baixa para alta, feche qualquer exposição curta e compre com o volume configurado.
Se o SuperTrend mudar de alta para baixa, feche qualquer exposição longa e venda com o volume configurado.
Armazene a direção atual do SuperTrend para detectar a próxima virada.
A lógica replica o comportamento do especialista MetaTrader, onde nina = Buffer0 - Buffer1 e uma mudança de sinal acionam saídas e novas entradas.
Gestão de Posição e Risco
Apenas uma única posição pode estar ativa por vez; todas as negociações invertem a direção em vez de empilhar vários pedidos.
Um stop-loss opcional em pontos de preço é calculado a partir do preço de preenchimento. Para uma negociação longa, o stop é colocado abaixo da entrada e, para uma negociação curta, é colocado acima da entrada. Definir o parâmetro como zero desativa a parada.
StartProtection() é chamado para que as proteções StockSharp integradas possam ser configuradas, se desejado.
Parâmetros
Parâmetro
Padrão
Descrição
Volume
0.1
Volume de pedidos usado para cada nova entrada.
AtrPeriod
10
Período ATR passado para o cálculo do SuperTrend (mapeia o PeriodWATR original).
AtrMultiplier
1
Multiplicador ATR para SuperTrend (mapeia o Kwatr original).
StopLossPoints
0
Distância de stop-loss opcional em faixas de preço. Zero mantém o stop desabilitado, idêntico ao código MetaTrader que enviou ordens de mercado sem preço stop.
CandleType
TimeFrame(1 minute)
Série de velas que alimenta o indicador e a lógica de negociação.
Notas de conversão
O especialista MetaTrader confiou no indicador NINA personalizado. Seus dois buffers foram interpretados como linhas SuperTrend de alta/baixa porque apenas sua diferença e sinal importavam para a negociação. SuperTrend expõe as mesmas informações por meio de seu sinalizador IsUpTrend, o que o torna um substituto de alto nível adequado, sem necessidade de manipulação manual de buffer.
A lógica de fechamento da ordem reflete o loop OrdersTotal() do script original: uma mudança de tendência primeiro lisonjeia a posição atual e depois abre uma negociação na nova direção.
As entradas MetaTrader não utilizadas (highlow, cbars, from, maP, SMAspread, Slippage) são omitidas porque não influenciam as regras de negociação no arquivo original.
Dicas de uso
Anexe a estratégia a um título e configure o período de vela que corresponde ao seu teste MetaTrader.
Ajuste o período ATR e o multiplicador para replicar o comportamento do indicador original.
Aumente StopLossPoints se desejar um limite de risco rígido; caso contrário, deixe-o em zero para saídas puramente baseadas em sinal.
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()