Sistema de ruptura diario para GBPUSD que combina una EMA calculada en máximos, filtros RSI, confirmación de momentum MACD y gestión de riesgo basada en ATR. El script reproduce el comportamiento de cuatro tomas de ganancias y punto de equilibrio de la versión MetaTrader original.
Datos Clave
Mercado: GBP/USD spot o CFD
Período: Velas diarias (configurable)
Dirección: Largo y corto
Estilo de posición: Escalado multi-objetivo con stop-loss compartido
Instrumentos Usados: EMA (High), RSI, línea principal MACD, ATR
Configuración de Indicadores
EMA en precios Máximos – longitud predeterminada 6, aproxima el nivel dinámico de ruptura.
RSI – longitud predeterminada 10, define los corredores de sobrecompra/sobreventa usados como filtros de momentum.
Línea principal MACD – rápido 5, lento 21, señal 14. Solo se usa la línea principal para medir la pendiente del momentum.
ATR – longitud 28, proporciona stops y objetivos dependientes de la volatilidad.
Lógica de Entrada
Entradas Largas
La barra diaria anterior abre por debajo de la EMA (High) y cierra por encima de ella (confirmación de cruce ascendente).
El RSI se mantiene entre 60 y 80 – previene trades durante momentum débil y evita rallys sobreextendidos.
La línea principal del MACD satisface una de dos verificaciones de momentum:
El valor hace dos barras es negativo (indicando que la tendencia recientemente se volvió positiva), o
La reducción relativa en MACD absoluto entre las últimas dos barras supera el umbral configurable MacdDiffBuy (predeterminado 0.5).
Si todas las condiciones se cumplen, se colocan cuatro órdenes iguales de compra de mercado (0.1 lotes cada una por defecto). Cualquier exposición corta existente se aplana antes de enviar el nuevo lote.
Entradas Cortas
La barra abre por encima de la EMA (High) y cierra por debajo de ella.
El RSI está entre 25 y 39 – refleja los umbrales del lado largo.
El MACD hace dos barras es positivo o el cambio relativo en el MACD absoluto entre las últimas dos barras está por encima de MacdDiffSell (predeterminado 0.15).
En confirmación, la estrategia aplana los largos existentes, luego envía cuatro ventas iguales de mercado.
Gestión de Trades
Stop Inicial: Stop ATR compartido calculado desde el cierre de entrada. Los largos usan entry - ATR * StopLossMultiplier (predeterminado 1.6). Los cortos usan entry + ATR * StopLossMultiplier.
Objetivos de Ganancia: Cuatro niveles incrementales basados en ATR por dirección: múltiplos 1.0, 1.5, 2.0 y 2.5 escalados por el parámetro TakeProfitMultiplier (predeterminado 1). Cada nivel cierra un cuarto de la posición original a través de una orden de mercado cuando el precio opera a través del nivel.
Comportamiento de Punto de Equilibrio: Después de cada salida parcial el stop protector para la posición restante se mueve al precio objetivo más reciente. Esto imita el EA original que modifica los stop-loss al precio de take-profit ejecutado cada vez que ocurre un trade TP.
Manejo de Stop: Si el precio toca el nivel protector intrabarra (usando máximo/mínimo de vela), la posición restante se cierra inmediatamente a mercado.
Notas de Control de Riesgo
La estrategia no piramida más allá del lote de cuatro entradas. Una nueva señal se ignora mientras la exposición permanece en la misma dirección.
El ATR debe ser positivo; las señales se omiten si el indicador de volatilidad aún no se ha formado.
Los cambios de parámetros en tiempo de ejecución afectan solo órdenes futuras; el volumen por orden se captura en la entrada para el escalado correcto en las salidas.
Parámetros
Nombre
Descripción
Predeterminado
OrderVolume
Volumen por orden individual de mercado en el lote
0.1
EmaPeriod
Longitud de EMA aplicada a máximos de vela
6
RsiPeriod
Período de promedio RSI
10
AtrPeriod
Período de promedio ATR
28
StopLossMultiplier
Múltiplo ATR para el stop protector
1.6
TakeProfitMultiplier
Múltiplo ATR base para objetivos de ganancia
1.0
MacdFastPeriod
Longitud de EMA rápida del MACD
5
MacdSlowPeriod
Longitud de EMA lenta del MACD
21
MacdSignalPeriod
Longitud de EMA de señal del MACD
14
MacdDiffBuyThreshold
Mejora mínima de pendiente MACD para trades largos
0.5
MacdDiffSellThreshold
Mejora mínima de pendiente MACD para trades cortos
0.15
RsiUpperLimit
RSI máximo permitido antes de una entrada larga
80
RsiUpperLevel
RSI mínimo requerido para una entrada larga
60
RsiLowerLevel
RSI máximo permitido para una entrada corta
39
RsiLowerLimit
RSI mínimo requerido antes de cortos
25
CandleType
Marco temporal usado para la suscripción de velas
1 Day
Consejos de Despliegue
Optimizar los umbrales de RSI y MACD juntos; aflojar los corredores RSI sin ajustar los filtros de aceleración MACD puede crear falsas señales.
Dado que las salidas parciales dependen de los extremos de la vela, los datos precisos de valores máximos/mínimos son importantes para backtests realistas.
Siempre operar con capital suficiente para manejar cuatro órdenes simultáneas por señal.
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;
/// <summary>
/// Alexav D1 Profit GBPUSD strategy (simplified). Uses EMA crossover with RSI
/// filter for breakout entries with ATR-based stop/take management.
/// </summary>
public class AlexavD1ProfitGbpUsdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaFastLength;
private readonly StrategyParam<int> _emaSlowLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<decimal> _rsiUpperLevel;
private readonly StrategyParam<decimal> _rsiLowerLevel;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaFastLength
{
get => _emaFastLength.Value;
set => _emaFastLength.Value = value;
}
public int EmaSlowLength
{
get => _emaSlowLength.Value;
set => _emaSlowLength.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public decimal RsiUpperLevel
{
get => _rsiUpperLevel.Value;
set => _rsiUpperLevel.Value = value;
}
public decimal RsiLowerLevel
{
get => _rsiLowerLevel.Value;
set => _rsiLowerLevel.Value = value;
}
public AlexavD1ProfitGbpUsdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_emaFastLength = Param(nameof(EmaFastLength), 6)
.SetGreaterThanZero()
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators");
_emaSlowLength = Param(nameof(EmaSlowLength), 21)
.SetGreaterThanZero()
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators");
_rsiLength = Param(nameof(RsiLength), 10)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
_rsiUpperLevel = Param(nameof(RsiUpperLevel), 65m)
.SetDisplay("RSI Upper", "Max RSI for buy", "Filters");
_rsiLowerLevel = Param(nameof(RsiLowerLevel), 35m)
.SetDisplay("RSI Lower", "Min RSI for sell", "Filters");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaFast = new ExponentialMovingAverage { Length = EmaFastLength };
var emaSlow = new ExponentialMovingAverage { Length = EmaSlowLength };
decimal prevFast = 0, prevSlow = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaFast, emaSlow, (ICandleMessage candle, decimal fastVal, decimal slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastVal;
prevSlow = slowVal;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastVal;
prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
// EMA fast crosses above slow - buy signal
var bullishCross = prevFast <= prevSlow && fastVal > slowVal;
// EMA fast crosses below slow - sell signal
var bearishCross = prevFast >= prevSlow && fastVal < slowVal;
if (bullishCross && Position <= 0)
BuyMarket();
else if (bearishCross && Position >= 0)
SellMarket();
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
DrawOwnTrades(area);
}
}
}
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 alexav_d1_profit_gbp_usd_strategy(Strategy):
def __init__(self):
super(alexav_d1_profit_gbp_usd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ema_fast_length = self.Param("EmaFastLength", 6) \
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators")
self._ema_slow_length = self.Param("EmaSlowLength", 21) \
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaFastLength(self):
return self._ema_fast_length.Value
@property
def EmaSlowLength(self):
return self._ema_slow_length.Value
def OnReseted(self):
super(alexav_d1_profit_gbp_usd_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(alexav_d1_profit_gbp_usd_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
ema_fast = ExponentialMovingAverage()
ema_fast.Length = self.EmaFastLength
ema_slow = ExponentialMovingAverage()
ema_slow.Length = self.EmaSlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema_fast, ema_slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_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 not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return alexav_d1_profit_gbp_usd_strategy()