Esta estratégia é uma conversão StockSharp do especialista MetaTrader Exp_Trend_Intensity_Index. Ela opera em velas finalizadas em um período configurável e usa o Índice de Intensidade de Tendência (TII) para detectar quando o momentum sai de zonas altistas ou baixistas extremas. Quando o indicador faz a transição para fora de uma zona superior, o algoritmo fecha posições vendidas e pode iniciar uma nova posição comprada. Quando o indicador sai de uma zona inferior, o algoritmo fecha posições compradas e pode iniciar uma nova posição vendida.
Como o indicador é construído
Selecionar a fonte de preço (close, open, variantes ponderadas, preços de acompanhamento de tendência, etc.).
Suavizar esse fluxo de preços com uma primeira média móvel (PriceMaMethod, PriceMaLength).
Dividir a diferença entre o preço e o valor suavizado em fluxos positivos e negativos.
Suavizar os fluxos positivos e negativos independentemente com uma segunda média móvel (SmoothingMethod, SmoothingLength).
Calcular o Índice de Intensidade de Tendência: TII = 100 * Positive / (Positive + Negative).
Comparar o resultado com os limites HighLevel e LowLevel para atribuir um estado de cor: zona alta (0), neutro (1) ou zona baixa (2).
A implementação usa médias móveis do StockSharp (simples, exponencial, suavizada, ponderada). Tipos de suavização avançados da biblioteca MQL original não estão disponíveis neste port.
Lógica de trading
Os sinais são processados apenas quando uma vela está completamente fechada (CandleStates.Finished).
O parâmetro SignalBar define qual barra completada é analisada (padrão: uma barra atrás). A estratégia também inspeciona a barra imediatamente anterior, correspondendo à busca de buffer duplo no código MQL.
Quando a barra mais antiga pertence à zona alta (color == 0):
Fechar qualquer posição vendida se EnableSellExits for verdadeiro.
Se a barra mais recente saiu da zona alta e EnableBuyEntries for verdadeiro, abrir ou reverter para uma posição comprada.
Quando a barra mais antiga pertence à zona baixa (color == 2):
Fechar qualquer posição comprada se EnableBuyExits for verdadeiro.
Se a barra mais recente saiu da zona baixa e EnableSellEntries for verdadeiro, abrir ou reverter para uma posição vendida.
As ordens são enviadas com BuyMarket e SellMarket. As reversões de posição usam o volume de posição atual mais a propriedade Volume configurada.
A proteção opcional de stop-loss e take-profit (unidades de preço) é configurada através de StopLossPoints e TakeProfitPoints e implementada com StartProtection.
Parâmetros
Parâmetro
Descrição
CandleType
Período usado para cálculo do indicador e negociação.
PriceMaMethod, PriceMaLength
Tipo e período da média móvel aplicada ao fluxo de preço base.
SmoothingMethod, SmoothingLength
Tipo e período da média móvel aplicada aos fluxos positivos e negativos.
AppliedPrice
Fonte de preço para o indicador (close, open, median, variantes de acompanhamento de tendência, Demark, etc.).
HighLevel, LowLevel
Limites superiores e inferiores que definem zonas altistas e baixistas.
SignalBar
Número de barras completadas para olhar para trás para confirmação de sinal.
EnableBuyEntries, EnableSellEntries
Interruptores que permitem abrir posições compradas/vendidas.
EnableBuyExits, EnableSellExits
Interruptores que permitem saídas automáticas quando o indicador muda.
StopLossPoints, TakeProfitPoints
Distâncias protetoras opcionais expressas em unidades de preço para StartProtection.
Diferenças do especialista MQL original
As opções de gestão monetária (MM, MMMode, Deviation) são substituídas pela propriedade de volume padrão do StockSharp e execução de ordens; o gerenciamento de slippage não é replicado.
Apenas os tipos de média móvel disponíveis no StockSharp (simples, exponencial, suavizada, ponderada) são suportados.
Os parâmetros de fase do indicador MQL são omitidos porque os indicadores do StockSharp não expõem controles equivalentes.
As ordens são executadas imediatamente após a confirmação de um sinal na vela finalizada; não há agendamento explícito para a próxima abertura de barra.
Essas mudanças mantêm a ideia de negociação intacta enquanto seguem as diretrizes de estratégia de alto nível do StockSharp.
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>
/// Trend Intensity Index strategy. Uses EMA crossover for trend following.
/// </summary>
public class ExpTrendIntensityIndexStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
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 ExpTrendIntensityIndexStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
if (!prevAbove && currAbove && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (prevAbove && !currAbove && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class exp_trend_intensity_index_strategy(Strategy):
def __init__(self):
super(exp_trend_intensity_index_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(exp_trend_intensity_index_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(exp_trend_intensity_index_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return exp_trend_intensity_index_strategy()