La estrategia Micro Trend Breakouts es una conversión del asesor experto de MetaTrader "Micro Trend Breakouts" a la API de alto nivel de StockSharp. Detecta patrones de ruptura de corta duración usando medias móviles ponderadas lineales, picos de momentum y alineación MACD. La estrategia abre como máximo una posición a la vez y se basa en los precios de cierre de las velas para activar entradas y salidas.
Indicadores
Medias móviles ponderadas lineales (LWMA) - Las medias rápida y lenta construidas sobre el marco temporal de análisis filtran la dirección dominante del mercado.
Momentum - Las lecturas absolutas de momentum de las tres últimas velas completadas deben superar un umbral configurable para confirmar que el precio acelera en la dirección de la ruptura.
MACD - El histograma MACD clásico se usa como filtro direccional (línea principal por encima de la señal para largos y por debajo de la señal para cortos).
Lógica de entrada
Esperar una vela finalizada del marco temporal configurado.
Exigir que la LWMA rápida esté por encima de la LWMA lenta para largos (por debajo para cortos).
Confirmar una pequeña estructura de ruptura: el mínimo de la vela de hace dos barras debe estar por debajo del máximo de la vela anterior para largos (reflejado para cortos).
Exigir aceleración de momentum: cualquiera de los tres últimos valores absolutos de momentum debe superar el umbral configurado.
Validar la alineación MACD:
Largos: la línea principal MACD debe estar por encima de la línea de señal, independientemente de si está por encima o por debajo de cero.
Cortos: la línea principal MACD debe estar por debajo de la línea de señal, independientemente de la posición de la línea cero.
Cuando todas las comprobaciones coinciden, la estrategia emite una orden de mercado usando el parámetro de volumen predeterminado.
Lógica de salida y gestión de riesgos
Los niveles iniciales de stop-loss y take-profit se expresan en pasos de precio y se calculan al entrar. Establecer un valor en cero desactiva el nivel correspondiente.
Un módulo opcional de breakeven mueve el stop hacia el precio de entrada después de que el precio avance una cantidad configurada de pasos, añadiendo opcionalmente un margen de seguridad.
La protección trailing puede ajustar el stop después de un movimiento rentable. Una vez que la ganancia supera el umbral de activación, el stop se arrastra a la distancia trailing desde el precio de vela más alto (para largos) o más bajo (para cortos) visto desde la entrada.
Las salidas de posición se evalúan en cada vela finalizada. Si el precio alcanza el nivel de stop-loss o take-profit, la estrategia cierra la posición con una orden de mercado y reinicia el estado interno.
Parámetros
Nombre
Descripción
Predeterminado
Order Volume
Volumen de orden de mercado usado para entradas.
1
Candle Type
Marco temporal para el análisis de precio.
15m time frame
Fast LWMA
Período de la media móvil ponderada lineal rápida.
6
Slow LWMA
Período de la media móvil ponderada lineal lenta.
85
Momentum Period
Período retrospectivo del indicador de momentum.
14
Momentum Threshold
Momentum absoluto mínimo requerido durante las tres últimas velas.
0.3
MACD Fast / Slow / Signal
Períodos de media móvil usados por MACD.
12 / 26 / 9
Stop Loss
Distancia del stop en pasos de precio. 0 desactiva el stop.
20
Take Profit
Distancia del objetivo en pasos de precio. 0 desactiva el objetivo.
50
Use Trailing
Habilita la lógica de trailing stop.
true
Trail Activation
Ganancia en pasos requerida antes de que el trailing stop se active.
40
Trail Step
Distancia entre el extremo y el trailing stop en pasos.
40
Use Breakeven
Habilita el ajuste de stop breakeven.
true
Breakeven Trigger
Ganancia en pasos que arma el módulo breakeven.
30
Breakeven Padding
Pasos adicionales añadidos al mover el stop a breakeven.
30
Notas
La estrategia se suscribe a un solo flujo de velas y evita llamadas de API de bajo nivel, manteniéndose dentro de los requisitos del framework de alto nivel.
Las órdenes de protección no se adjuntan directamente a las operaciones; en su lugar, la estrategia usa supervisión basada en velas combinada con StartProtection() para asegurar que la clase base supervise las posiciones abiertas.
Todos los comentarios inline del código C# están escritos en inglés, como exigen las directrices de conversión.
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()