Estratégia Ultra MFI de Recontagem de Gestão Monetária
Visão geral
A Estratégia Ultra MFI MMRec é um port direto do consultor especialista MetaTrader 5 Exp_UltraMFI_MMRec. Ela combina um oscilador de Índice de Fluxo de Dinheiro (MFI) suavizado em múltiplas etapas com gestão monetária baseada em sequências. Dois contadores internos acumulam quantas camadas de suavização apontam para cima ou para baixo. Cruzamentos entre esses contadores geram sinais de negociação, enquanto os resultados recentes das operações determinam se a próxima posição usa o tamanho de posição normal ou reduzido.
Lógica de trading
Indicador base – um Índice de Fluxo de Dinheiro com comprimento configurável é calculado no tipo de vela selecionado.
Suavização em escada – o valor MFI é passado por uma escada de médias móveis. Cada etapa aumenta o comprimento de suavização em um incremento fixo. Os métodos de suavização suportados são Simple, Exponential, Smoothed, Linear Weighted e médias móveis Jurik (outros modos específicos do MT5 não estão disponíveis no StockSharp).
Contadores direcionais – para cada barra a estratégia compara a saída atual e anterior de cada etapa de suavização. Se a etapa está subindo, o contador de alta aumenta, caso contrário o de baixa aumenta. Ambos os contadores são suavizados novamente por uma média móvel final.
Deslocamento de sinal – as regras de negociação operam em barras terminadas. Um SignalShift configurável informa à estratégia quantas velas fechadas olhar para trás ao comparar os contadores, imitando o comportamento do MT5 ao usar SignalBar=1.
Entradas e saídas –
Se a barra anterior mostrou touros mais fortes (bulls > bears) e a última barra mostra um cruzamento para bulls < bears, a estratégia abre uma posição comprada. A mesma condição também fecha qualquer posição vendida aberta.
Se a barra anterior mostrou ursos mais fortes e a última barra muda para bulls > bears, a estratégia abre uma posição vendida e fecha qualquer posição comprada aberta.
O stop-loss e take-profit opcionais (baseados em porcentagem) podem ser gerenciados através de StartProtection.
Gestão monetária – o próximo tamanho de ordem depende dos últimos resultados de operações por direção. Após fechar cada posição o PnL realizado é inspecionado:
A estratégia armazena as operações de compra mais recentes BuyTotalTrigger e conta quantas foram perdas. Quando a contagem atinge BuyLossTrigger, a próxima ordem de compra usa ReducedVolume, caso contrário usa NormalVolume.
A mesma lógica é aplicada independentemente para operações de venda com SellTotalTrigger e SellLossTrigger.
Parâmetros
CandleType – tipo de dados do instrumento (período) usado para geração de sinais.
MfiPeriod – comprimento do oscilador Índice de Fluxo de Dinheiro.
StepSmoothing / FinalSmoothing – tipo de média móvel para as etapas da escada e os contadores finais.
StartLength / StepSize / StepsTotal – geometria da escada de suavização (primeiro comprimento, incremento, número de etapas).
FinalSmoothingLength – comprimento da etapa de suavização do contador.
SignalShift – número de barras completadas para olhar para trás ao avaliar sinais.
NormalVolume / ReducedVolume – tamanho de operação para condições normais e após uma sequência de perdas.
BuyTotalTrigger / BuyLossTrigger – profundidade do histórico e limiar de perda para mudar a próxima operação comprada para tamanho reduzido.
SellTotalTrigger / SellLossTrigger – configurações análogas para operações vendidas.
AllowLongEntries / AllowShortEntries / AllowLongExits / AllowShortExits – habilitar ou desabilitar entradas e saídas para cada direção.
TakeProfitPercent / StopLossPercent – níveis de proteção opcionais baseados em porcentagem.
Notas de uso
A suavização em escada requer velas históricas suficientes para preencher cada média móvel. Aguarde até que a estratégia esteja totalmente formada antes de confiar nos sinais.
Como o StockSharp não fornece suavizadores específicos do MT5 como JurX, Parabolic, VIDYA ou AMA, as alternativas suportadas mais próximas são utilizadas. A suavização Jurik é um bom padrão que reproduz a sensação original do indicador UltraMFI.
A gestão monetária é baseada no PnL realizado. Certifique-se de que seus backtests incluam a execução de ordens para que o PnL realizado seja atualizado após cada fechamento de posição.
Este port mantém o comportamento de apenas entrar em novas posições quando a posição atual está zerada. Quando um sinal de reversão aparece enquanto a posição oposta é mantida, a estratégia primeiro sai da operação existente e entrará na próxima barra elegível uma vez zerada.
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>
/// Ultra MFI MMRec strategy. Uses EMA crossover as signal generator.
/// </summary>
public class UltraMfiMmRecStrategy : 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 UltraMfiMmRecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.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 ultra_mfi_mm_rec_strategy(Strategy):
def __init__(self):
super(ultra_mfi_mm_rec_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", 8) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow Period", "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(ultra_mfi_mm_rec_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(ultra_mfi_mm_rec_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:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return ultra_mfi_mm_rec_strategy()