Estrategia Expert MACD EURUSD 1 Hora
Descripción general
Esta estrategia es una traducción en C# del asesor experto de MetaTrader 5 Expert MACD EURUSD 1 Hour. Opera en velas de una hora usando el indicador MACD con períodos corto, largo y de señal de 5 / 15 / 3. La estrategia busca un fuerte cambio de momentum donde la línea principal del MACD cruza por encima o por debajo del nivel cero mientras la línea de señal confirma el movimiento. Se usa un trailing stop para proteger las posiciones abiertas, y las operaciones se cierran cuando la pendiente del MACD se vuelve contra la posición actual.
Parámetros
FastLength – período de la EMA rápida para MACD (predeterminado: 5).
SlowLength – período de la EMA lenta para MACD (predeterminado: 15).
SignalLength – período de la línea de señal para MACD (predeterminado: 3).
TrailingPoints – distancia del trailing stop en puntos de precio (predeterminado: 25).
CandleType – marco temporal de las velas (predeterminado: 1 hora).
- La propiedad
Volume de la estrategia controla el tamaño de la orden.
Lógica de negociación
Entrada larga
- Valores de la línea de señal:
mac8 > mac7 > mac6 y mac6 < mac5 (línea de señal subiendo).
- Valores de la línea principal:
mac4 > mac3 < mac2 < mac1 (línea principal subiendo tras una caída).
mac2 < -0.00020, mac4 < 0 y mac1 > 0.00020 – línea principal cruza por encima de cero.
- Si todas las condiciones se cumplen y no hay posición larga abierta, comprar a mercado.
Entrada corta
- Valores de la línea de señal:
mac8 < mac7 < mac6 y mac6 > mac5 (línea de señal bajando).
- Valores de la línea principal:
mac4 < mac3 > mac2 > mac1 (línea principal bajando tras un pico).
mac2 > 0.00020, mac4 > 0 y mac1 < -0.00035 – línea principal cruza por debajo de cero.
- Si todas las condiciones se cumplen y no hay posición corta abierta, vender a mercado.
Reglas de salida
- Cerrar un largo cuando el valor principal actual está por debajo del anterior.
- Cerrar un corto cuando el valor principal actual está por encima del anterior.
- El trailing stop se actualiza en cada vela y sale si el precio cruza el nivel del stop.
Notas
Este ejemplo demuestra el uso de la API de alto nivel de StockSharp con vinculación de indicadores y gestión manual del trailing stop. Está destinado a fines educativos y no incluye gestión de dinero más allá del parámetro fijo Volume.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// MACD based strategy converted from MetaTrader 5 Expert Advisor.
/// Uses MACD indicator with custom pattern checks on recent values and optional trailing stop.
/// </summary>
public class ExpertMacdEurusd1HourStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _signalLength;
private readonly StrategyParam<decimal> _trailingPoints;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _fastEma;
private ExponentialMovingAverage _slowEma;
private ExponentialMovingAverage _signalEma;
private decimal _main0, _main1;
private decimal _signal0, _signal1;
private int _counter;
/// <summary>
/// Fast EMA length for MACD.
/// </summary>
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
/// <summary>
/// Slow EMA length for MACD.
/// </summary>
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
/// <summary>
/// Signal line length for MACD.
/// </summary>
public int SignalLength { get => _signalLength.Value; set => _signalLength.Value = value; }
/// <summary>
/// Trailing stop distance in price points.
/// </summary>
public decimal TrailingPoints { get => _trailingPoints.Value; set => _trailingPoints.Value = value; }
/// <summary>
/// Candle type for analysis.
/// </summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Initialize strategy with default parameters.
/// </summary>
public ExpertMacdEurusd1HourStrategy()
{
_fastLength = Param(nameof(FastLength), 12)
.SetDisplay("Fast Length", "Fast EMA length for MACD", "Parameters")
;
_slowLength = Param(nameof(SlowLength), 26)
.SetDisplay("Slow Length", "Slow EMA length for MACD", "Parameters")
;
_signalLength = Param(nameof(SignalLength), 9)
.SetDisplay("Signal Length", "Signal length for MACD", "Parameters")
;
_trailingPoints = Param(nameof(TrailingPoints), 25m)
.SetDisplay("Trailing Points", "Trailing stop distance in points", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Working timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_main0 = _main1 = 0m;
_signal0 = _signal1 = 0m;
_counter = 0;
_fastEma = null;
_slowEma = null;
_signalEma = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fastEma = new ExponentialMovingAverage { Length = FastLength };
_slowEma = new ExponentialMovingAverage { Length = SlowLength };
_signalEma = new ExponentialMovingAverage { Length = SignalLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
StartProtection(
new Unit(2000m, UnitTypes.Absolute),
new Unit(1000m, UnitTypes.Absolute));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var fast = _fastEma.Process(candle.ClosePrice, candle.CloseTime, true).ToDecimal();
var slow = _slowEma.Process(candle.ClosePrice, candle.CloseTime, true).ToDecimal();
if (!_fastEma.IsFormed || !_slowEma.IsFormed)
return;
var main = fast - slow;
var signal = _signalEma.Process(main, candle.CloseTime, true).ToDecimal();
if (!_signalEma.IsFormed)
return;
// shift stored values
_main1 = _main0;
_main0 = main;
_signal1 = _signal0;
_signal0 = signal;
if (_counter < 3)
{
_counter++;
return;
}
var buySignal = _main1 <= _signal1 && _main0 > _signal0 && _main0 < 0m;
var sellSignal = _main1 >= _signal1 && _main0 < _signal0 && _main0 > 0m;
if (buySignal && Position <= 0)
BuyMarket();
else if (sellSignal && Position >= 0)
SellMarket();
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class expert_macd_eurusd1_hour_strategy(Strategy):
def __init__(self):
super(expert_macd_eurusd1_hour_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 12)
self._slow_length = self.Param("SlowLength", 26)
self._signal_length = self.Param("SignalLength", 9)
self._trailing_points = self.Param("TrailingPoints", 25.0)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._fast_ema = None
self._slow_ema = None
self._signal_ema = None
self._main0 = 0.0
self._main1 = 0.0
self._signal0 = 0.0
self._signal1 = 0.0
self._counter = 0
@property
def FastLength(self):
return self._fast_length.Value
@FastLength.setter
def FastLength(self, value):
self._fast_length.Value = value
@property
def SlowLength(self):
return self._slow_length.Value
@SlowLength.setter
def SlowLength(self, value):
self._slow_length.Value = value
@property
def SignalLength(self):
return self._signal_length.Value
@SignalLength.setter
def SignalLength(self, value):
self._signal_length.Value = value
@property
def TrailingPoints(self):
return self._trailing_points.Value
@TrailingPoints.setter
def TrailingPoints(self, value):
self._trailing_points.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(expert_macd_eurusd1_hour_strategy, self).OnStarted2(time)
self._main0 = 0.0
self._main1 = 0.0
self._signal0 = 0.0
self._signal1 = 0.0
self._counter = 0
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = self.FastLength
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = self.SlowLength
self._signal_ema = ExponentialMovingAverage()
self._signal_ema.Length = self.SignalLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
t = candle.OpenTime
fast_result = process_float(self._fast_ema, candle.ClosePrice, t, True)
slow_result = process_float(self._slow_ema, candle.ClosePrice, t, True)
if not self._fast_ema.IsFormed or not self._slow_ema.IsFormed:
return
fast_val = float(fast_result)
slow_val = float(slow_result)
main = fast_val - slow_val
signal_result = process_float(self._signal_ema, main, t, True)
if not self._signal_ema.IsFormed:
return
signal = float(signal_result)
self._main1 = self._main0
self._main0 = main
self._signal1 = self._signal0
self._signal0 = signal
if self._counter < 3:
self._counter += 1
return
buy_signal = self._main1 <= self._signal1 and self._main0 > self._signal0 and self._main0 < 0.0
sell_signal = self._main1 >= self._signal1 and self._main0 < self._signal0 and self._main0 > 0.0
if buy_signal and self.Position <= 0:
self.BuyMarket()
elif sell_signal and self.Position >= 0:
self.SellMarket()
def OnReseted(self):
super(expert_macd_eurusd1_hour_strategy, self).OnReseted()
self._main0 = 0.0
self._main1 = 0.0
self._signal0 = 0.0
self._signal1 = 0.0
self._counter = 0
self._fast_ema = None
self._slow_ema = None
self._signal_ema = None
def CreateClone(self):
return expert_macd_eurusd1_hour_strategy()