Esta estrategia porta el asesor experto MetaTrader "1H EUR_USD" a la API de alto nivel de StockSharp. Opera el par EUR/USD en velas horarias usando medias móviles duales y detección de oscilaciones MACD. Las entradas requieren tanto un filtro de tendencia (MA rápida por encima/por debajo de la MA lenta) como un patrón de doble fondo/doble techo MACD combinado con una ruptura de máximos o mínimos recientes. El riesgo se controla con stop loss, take profit basados en pips y un trailing stop incremental que refleja la lógica del EA original.
Detalles
Mercado: Diseñado para EUR/USD en el marco temporal de 1 hora, pero puede aplicarse a cualquier instrumento que produzca velas estándar.
Criterios de entrada:
Largo:
La MA rápida está por encima de la MA lenta (tipo seleccionable entre SMA, EMA, SMMA, LWMA).
La línea principal MACD forma cualquiera de las siguientes oscilaciones alcistas completamente por debajo de la línea cero:
MACD[-1] > MACD[-2] < MACD[-3] con MACD[-2] < 0 y el cierre actual rompe el máximo de la vela anterior.
MACD[-2] > MACD[-3] < MACD[-4] con MACD[-3] < 0 y el cierre actual rompe el máximo de hace dos velas.
Corto:
La MA rápida está por debajo de la MA lenta.
La línea principal MACD forma las oscilaciones bajistas reflejadas completamente por encima de la línea cero y el precio cierra por debajo del mínimo previo relevante.
Criterios de salida:
El take profit y el stop loss basados en pips se adjuntan inmediatamente después de la entrada.
El trailing stop se activa solo después de que el precio se mueva a favor por TrailingStop + TrailingStep pips y luego sigue el precio a una distancia de TrailingStop pips, siguiendo la lógica de modificación gradual del EA.
Las órdenes de protección se activan en el máximo/mínimo intraperiodo de la vela.
Gestión de posición:
Usa el volumen de operación configurado; revertir posiciones cierra el lado opuesto antes de abrir el nuevo.
Las operaciones largas y cortas comparten los mismos cálculos de pip (el tamaño de pip se adapta automáticamente a cotizaciones de 4/5 dígitos).
Indicadores:
Medias móviles rápida y lenta con tipo seleccionable (Simple, Exponencial, Suavizado, Ponderado Lineal) y desplazamiento horizontal opcional.
MACD clásico (longitudes de EMA rápida/lenta/señal).
Parámetros:
TradeVolume – tamaño de lote base enviado con cada orden.
StopLossPips, TakeProfitPips – distancias de protección en pips (establezca en cero para deshabilitar).
TrailingStopPips, TrailingStepPips – configuración de seguimiento; el paso de seguimiento debe permanecer positivo cuando el seguimiento está activo.
FastMaLength, FastMaShift, FastMaType – configuración de la MA rápida.
SlowMaLength, SlowMaShift, SlowMaType – configuración de la MA lenta.
CandleType – marco temporal para procesamiento (predeterminado a 1 hora).
LookbackPeriod – preservado por compatibilidad con las entradas MQL; no altera la lógica porque el EA original también lo dejó sin usar.
Notas
El comportamiento del trailing stop refleja la versión MQL: no ocurre ningún ajuste hasta que tanto la distancia de seguimiento como el paso de seguimiento son superados por la ganancia no realizada.
La estrategia asume que el paso de precio es igual al punto de cotización; si el instrumento tiene 3 o 5 dígitos decimales, el código escala automáticamente el tamaño del pip por 10.
Los comentarios dentro del fuente C# explican cada bloque clave en inglés para facilitar el mantenimiento y la extensión.
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>
/// 1H EUR/USD style strategy using EMA with RSI confirmation.
/// </summary>
public class OneHourEurUsdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private decimal? _prevRsi;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaPeriod
{
get => _emaPeriod.Value;
set => _emaPeriod.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public OneHourEurUsdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "Trend EMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = null;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal rsiVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevRsi = rsiVal;
return;
}
if (_prevRsi == null)
{
_prevRsi = rsiVal;
return;
}
var close = candle.ClosePrice;
// Price above EMA + RSI crosses 50 up
if (close > emaVal && _prevRsi.Value <= 50 && rsiVal > 50 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Price below EMA + RSI crosses 50 down
else if (close < emaVal && _prevRsi.Value >= 50 && rsiVal < 50 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevRsi = rsiVal;
}
}
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, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class one_hour_eur_usd_strategy(Strategy):
def __init__(self):
super(one_hour_eur_usd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "Trend EMA period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._prev_rsi = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaPeriod(self):
return self._ema_period.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
def OnReseted(self):
super(one_hour_eur_usd_strategy, self).OnReseted()
self._prev_rsi = None
def OnStarted2(self, time):
super(one_hour_eur_usd_strategy, self).OnStarted2(time)
self._prev_rsi = None
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, rsi, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, ema_value, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self._prev_rsi is None:
self._prev_rsi = rv
return
close = float(candle.ClosePrice)
ev = float(ema_value)
# Price above EMA + RSI crosses 50 up
if close > ev and self._prev_rsi <= 50 and rv > 50 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Price below EMA + RSI crosses 50 down
elif close < ev and self._prev_rsi >= 50 and rv < 50 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_rsi = rv
def CreateClone(self):
return one_hour_eur_usd_strategy()