La estrategia Eugene traslada el MetaTrader 4 asesor experto original "Eugene" al StockSharp alto nivel API. El algoritmo monitorea las velas horarias de forma predeterminada y busca rupturas de velas internas que se confirman mediante un retroceso a un tercio de la vela anterior. Una vez que se confirma una ruptura, la estrategia entra en la dirección de la ruptura y puede revertir las posiciones existentes cuando aparece una configuración opuesta.
Lógica de trading
Detección de vela interior: la vela anterior debe estar completamente dentro del rango de la vela anterior. Su dirección de cierre determina si se clasifica como insider negro (bajista) o blanco (alcista).
Filtros de pájaros: una vela interior confirmada por otra vela del mismo color detrás de ella está marcada como "pájaro". Los pájaros negros bloquean las operaciones largas, los pájaros blancos bloquean las operaciones cortas. Esto refleja el filtro protector de la versión MQL.
Niveles de confirmación en zigzag: se calculan dos precios de confirmación en un tercio del cuerpo o mecha de la vela anterior:
El nivel de confirmación largo está un tercio por debajo del cierre anterior (cuerpo para velas alcistas, mecha para velas bajistas).
El nivel de confirmación corta está un tercio por encima del cierre anterior (cuerpo para velas bajistas, mecha para velas alcistas).
Filtro de sesión: si la vela actual se abre a las 08:00 o más tarde, las confirmaciones se consideran satisfechas incluso sin un retroceso.
Condición de ruptura: una señal de compra requiere que la vela actual alcance un máximo más alto que la vela anterior mientras mantiene un mínimo más alto y se superpone al rango de la vela dos barras atrás. Una señal de venta utiliza condiciones simétricas con mínimos y máximos más bajos.
Gestión de posiciones: antes de abrir una nueva operación, la estrategia cierra cualquier exposición opuesta. Solo se puede emitir una entrada larga y una corta por vela, replicando las restricciones Counter_buy y Counter_sell del asesor experto original.
Parámetros
Nombre
Descripción
Predeterminado
Trade Volume
Tamaño de la orden para órdenes de mercado.
0.1
Candle Type
Marco temporal de la serie de velas procesadas.
1 hour
Trazar
Cuando hay un área del gráfico disponible, la estrategia traza las velas procesadas junto con las operaciones ejecutadas, lo que ayuda a visualizar el comportamiento de ruptura.
Notas
La versión StockSharp mantiene el filtro de sesión por hora del experto MQL. Ajuste el tipo de vela cuando opere en otros mercados o zonas horarias.
La gestión de stop-loss y take-profit no está incluida en el archivo fuente MQL. Por lo tanto, el puerto deja la gestión de riesgos al entorno de alojamiento.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class EugeneStrategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevSma;
private bool _hasPrev;
private int _cooldownRemaining;
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public EugeneStrategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 50).SetDisplay("SMA Period", "SMA lookback", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14).SetDisplay("RSI Period", "RSI lookback", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 200).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevSma = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_prevSma = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sma, decimal rsi)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev) { _prevClose = close; _prevSma = sma; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevClose = close;
_prevSma = sma;
return;
}
if (_prevClose <= _prevSma && close > sma && rsi < 70 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevClose >= _prevSma && close < sma && rsi > 30 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevClose = close;
_prevSma = sma;
}
}
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 SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class eugene_strategy(Strategy):
def __init__(self):
super(eugene_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 50) \
.SetDisplay("SMA Period", "SMA lookback", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI lookback", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 200) \
.SetDisplay("Cooldown", "Candles between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_sma = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@property
def sma_period(self):
return self._sma_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def cooldown_candles(self):
return self._cooldown_candles.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(eugene_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_sma = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(eugene_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_sma = 0.0
self._has_prev = False
self._cooldown_remaining = 0
sma = SimpleMovingAverage()
sma.Length = self.sma_period
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, rsi, self.process_candle).Start()
def process_candle(self, candle, sma, rsi):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
sma_val = float(sma)
rsi_val = float(rsi)
if not self._has_prev:
self._prev_close = close
self._prev_sma = sma_val
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_close = close
self._prev_sma = sma_val
return
if self._prev_close <= self._prev_sma and close > sma_val and rsi_val < 70 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_candles
elif self._prev_close >= self._prev_sma and close < sma_val and rsi_val > 30 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_candles
self._prev_close = close
self._prev_sma = sma_val
def CreateClone(self):
return eugene_strategy()