La Estrategia de Three Timeframes replica el experto de MetaTrader Three timeframes.mq5 usando la API de alto nivel de StockSharp. El sistema combina filtros de momentum y tendencia tomados de diferentes marcos temporales:
MACD (M5) detecta reversiones de momentum recientes en el marco temporal de trading.
Alligator (H4) verifica que la estructura del marco temporal superior esté alineada con la dirección de operación prevista.
RSI (H1) confirma que el momentum en el marco temporal intermedio apoya la ruptura.
Filtrado de sesión opcional bloquea las operaciones fuera de las horas de trabajo configuradas.
La estrategia usa gestión de riesgo basada en pips. Los niveles iniciales de stop-loss y take-profit se adjuntan a cada nueva posición. Cuando el precio avanza, un trailing stop opcional ajusta el stop protector después de que el mercado cubra tanto la distancia de trailing como el paso de trailing.
Lógica de señales
Los precios se procesan en tres suscripciones diferentes: velas de trading, velas de marco temporal superior para el Alligator y velas intermedias para el RSI.
Una configuración larga requiere:
La línea principal del MACD cruzando por debajo de la línea de señal en la barra anterior mientras que la barra anterior a esa estaba por encima de la línea de señal, reproduciendo la regla de MetaTrader "azul cruza rojo hacia abajo".
RSI en el feed H1 por encima de 50.
Alligator jaw > teeth > lips en la vela H4 completada anterior, indicando una estructura alcista.
Una configuración corta replica las reglas: la línea principal del MACD cruza por encima de la línea de señal, el RSI está por debajo de 50 y lips > teeth > jaw en el Alligator para confirmar una estructura bajista.
Si existe una posición opuesta, la estrategia la cierra enviando una orden de mercado por el tamaño neto, igual que el EA original antes de abrir una nueva operación.
Después de la entrada, la estrategia aplica las distancias iniciales de stop-loss/take-profit y continúa siguiendo el stop una vez que el precio se mueve TrailingStopPips + TrailingStepPips desde la entrada.
El filtro de sesión de trading refleja la implementación de MetaTrader. Cuando la hora de inicio es menor que la hora de fin, el trading solo se permite dentro del intervalo. Cuando la hora de inicio es mayor que la hora de fin, la ventana activa cruza la medianoche.
Gestión de riesgo
Stop Loss / Take Profit – las distancias se expresan en pips. La estrategia los convierte a unidades de precio usando el paso de precio del símbolo y ajusta para cotizaciones FX de 3 o 5 dígitos.
Trailing Stop – se activa una vez que la operación cubre tanto la distancia de trailing como el paso de trailing. El stop se mueve entonces a price - trailing distance para largos y price + trailing distance para cortos.
Volumen de trading – especifica el tamaño base del lote para nuevas órdenes de mercado. La exposición opuesta se aplana automáticamente antes de revertir.
Diferencias respecto a la versión de MetaTrader
El modelo de órdenes asíncronas de StockSharp elimina la necesidad de flags explícitos de seguimiento de transacciones (m_waiting_transaction). Las órdenes se ejecutan usando BuyMarket/SellMarket, que ya esperan confirmaciones internamente.
Las configuraciones de deslizamiento, política de llenado y modo de margen de la versión MQL están abstraídas por StockSharp. Estos controles específicos de plataforma no son necesarios para la implementación .NET.
El indicador Alligator se reconstruye desde medias móviles suavizadas preservando los períodos y desplazamientos originales. Los valores del indicador se almacenan en buffers deslizantes para reproducir el comportamiento de desplazamiento del Alligator integrado de MetaTrader.
Parámetros
Nombre
Descripción
Predeterminado
TradeVolume
Tamaño de la orden de mercado en lotes/contratos.
1
StopLossPips
Distancia inicial de stop-loss en pips.
50
TakeProfitPips
Distancia inicial de take-profit en pips.
140
TrailingStopPips
Distancia del trailing stop en pips.
5
TrailingStepPips
Movimiento de pips adicional requerido antes de mover el trailing stop.
5
MacdFastPeriod
Longitud de EMA rápida para MACD.
13
MacdSlowPeriod
Longitud de EMA lenta para MACD.
26
MacdSignalPeriod
Período de suavizado de señal para MACD.
10
JawPeriod, TeethPeriod, LipsPeriod
Períodos SMMA del Alligator para jaw/teeth/lips.
13, 8, 5
JawShift, TeethShift, LipsShift
Desplazamientos hacia adelante para las líneas del Alligator.
8, 5, 3
RsiPeriod
Longitud de promediación RSI en el marco temporal intermedio.
14
CandleType
Marco temporal de trading (predeterminado velas de 5 minutos).
M5
AlligatorCandleType
Marco temporal superior para el cálculo del Alligator (predeterminado velas de 4 horas).
H4
RsiCandleType
Marco temporal intermedio para confirmación RSI (predeterminado velas de 1 hora).
H1
UseTimeFilter
Habilita el filtro de sesión.
true
StartHour
Hora de inicio de sesión (inclusiva).
10
EndHour
Hora de fin de sesión (exclusiva).
15
Notas de uso
Asegúrese de que el instrumento seleccionado proporcione los tres flujos de velas configurados (M5, H1, H4 por defecto). StockSharp solicitará automáticamente todas las suscripciones necesarias a través de GetWorkingSecurities().
La conversión de pips depende de Security.PriceStep. Los instrumentos con tamaños de tick inusuales pueden necesitar ajuste manual de los parámetros de stop/take.
Los trailing stops requieren que tanto TrailingStopPips como TrailingStepPips sean mayores que cero. Establecer cualquiera de los parámetros en cero deshabilita la lógica de trailing, de forma consistente con el experto MQL.
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 ThreeTimeframesStrategy : 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 ThreeTimeframesStrategy()
{
_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 three_timeframes_strategy(Strategy):
def __init__(self):
super(three_timeframes_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(three_timeframes_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(three_timeframes_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 three_timeframes_strategy()