A estratégia Micro Trend Breakouts é uma conversão do expert advisor do MetaTrader "Micro Trend Breakouts" para a API de alto nível do StockSharp. Ela detecta padrões de rompimento de curta duração usando médias móveis ponderadas lineares, picos de momentum e alinhamento MACD. A estratégia abre no máximo uma posição por vez e depende dos preços de fechamento dos candles para acionar entradas e saídas.
Indicadores
Médias móveis ponderadas lineares (LWMA) - Médias rápida e lenta construídas no período de análise filtram a direção dominante do mercado.
Momentum - Leituras absolutas de momentum nos três últimos candles concluídos devem exceder um limite configurável para confirmar que o preço acelera na direção do rompimento.
MACD - O histograma MACD clássico é usado como filtro direcional (linha principal acima do sinal para compradas e abaixo do sinal para vendidas).
Lógica de entrada
Aguarde um candle finalizado do período configurado.
Exija que a LWMA rápida esteja acima da LWMA lenta para compradas (abaixo para vendidas).
Confirme uma pequena estrutura de rompimento: a mínima do candle de duas barras atrás deve estar abaixo da máxima do candle anterior para compradas (espelhado para vendidas).
Exija aceleração de momentum: qualquer um dos três últimos valores absolutos de momentum deve exceder o limite configurado.
Valide o alinhamento MACD:
Compradas: a linha principal MACD deve estar acima da linha de sinal, independentemente de estar acima ou abaixo de zero.
Vendidas: a linha principal MACD deve estar abaixo da linha de sinal, independentemente da posição da linha zero.
Quando todas as verificações concordam, a estratégia emite uma ordem a mercado usando o parâmetro de volume padrão.
Lógica de saída e gestão de risco
Níveis iniciais de stop-loss e take-profit são expressos em passos de preço e calculados na entrada. Definir um valor como zero desabilita o nível correspondente.
Um módulo opcional de breakeven move o stop em direção ao preço de entrada depois que o preço avança uma quantidade configurada de passos, adicionando opcionalmente uma margem de segurança.
A proteção trailing pode apertar o stop depois de um movimento lucrativo. Quando o lucro excede o limite de ativação, o stop é arrastado pela distância de trailing a partir do maior (para compradas) ou menor (para vendidas) preço de candle visto desde a entrada.
Saídas de posição são avaliadas em cada candle finalizado. Se o preço atingir níveis de stop-loss ou take-profit, a estratégia fecha a posição com uma ordem a mercado e redefine o estado interno.
Parâmetros
Nome
Descrição
Padrão
Order Volume
Volume da ordem a mercado usado para entradas.
1
Candle Type
Período para análise de preço.
15m time frame
Fast LWMA
Período da média móvel ponderada linear rápida.
6
Slow LWMA
Período da média móvel ponderada linear lenta.
85
Momentum Period
Retrospectiva do indicador de momentum.
14
Momentum Threshold
Momentum absoluto mínimo exigido nos três últimos candles.
0.3
MACD Fast / Slow / Signal
Períodos de média móvel usados pelo MACD.
12 / 26 / 9
Stop Loss
Distância do stop em passos de preço. 0 desabilita o stop.
20
Take Profit
Distância do alvo em passos de preço. 0 desabilita o alvo.
50
Use Trailing
Habilita a lógica de trailing stop.
true
Trail Activation
Lucro em passos necessário antes de o trailing stop ficar ativo.
40
Trail Step
Distância entre o extremo e o trailing stop em passos.
40
Use Breakeven
Habilita o ajuste de stop breakeven.
true
Breakeven Trigger
Lucro em passos que arma o módulo breakeven.
30
Breakeven Padding
Passos adicionais adicionados ao mover o stop para breakeven.
30
Observações
A estratégia assina um único fluxo de candles e evita chamadas de API de baixo nível, permanecendo dentro dos requisitos do framework de alto nível.
Ordens de proteção não são anexadas diretamente às operações; em vez disso, a estratégia usa monitoramento baseado em candles combinado com StartProtection() para garantir que a classe base supervisione posições abertas.
Todos os comentários inline no código C# são escritos em inglês, conforme exigido pelas diretrizes de conversão.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class MicroTrendBreakoutsStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public MicroTrendBreakoutsStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 micro_trend_breakouts_strategy(Strategy):
def __init__(self):
super(micro_trend_breakouts_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(micro_trend_breakouts_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(micro_trend_breakouts_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return micro_trend_breakouts_strategy()