DreamBot es una versión StockSharp del asesor experto MetaTrader 4 "DreamBot". La estrategia monitorea el oscilador del Índice de Fuerza en velas horarias y espera a que el impulso cruce los umbrales alcistas o bajistas. Cuando el Índice de Fuerza cruza por encima del nivel alcista después de estar por debajo de él en la barra anterior, la estrategia abre una posición larga. Cuando el Índice de Fuerza cruza por debajo del nivel bajista después de estar por encima de él, la estrategia abre una posición corta. El comercio se produce sólo cuando no existe una posición, lo que refleja la lógica de posición única del robot original.
Lógica comercial
Suscríbase a velas H1 y calcule un índice de fuerza suavizado (longitud 13 por defecto).
Realice un seguimiento de los dos últimos valores del índice de fuerza completados. Las señales se generan utilizando los valores de barra anteriores, exactamente igual que la implementación MT4 (iForce con turno 1 y 2).
Ingrese en largo cuando el índice de fuerza de la vela anterior esté por encima de BullsThreshold y el valor de dos velas atrás esté por debajo del umbral, siempre que no haya ninguna posición abierta.
Entre en corto cuando el índice de fuerza de la vela anterior esté por debajo de BearsThreshold y el valor dos velas atrás esté por encima del umbral, siempre que no haya ninguna posición abierta.
El trailing stop opcional replica el EA original: una vez que las ganancias superan TrailingStepPoints, se retira un nivel de stop a TrailingStartPoints del precio y sigue nuevos avances.
Gestión de riesgos
StartProtection adjunta órdenes clásicas de stop-loss y take-profit utilizando la distancia de "puntos" de MetaTrader convertida a través del paso del precio del instrumento.
La protección de seguimiento se basa en el mercado: cuando se supera el nivel de seguimiento calculado, la estrategia envía una orden de mercado para cerrar la posición inmediatamente.
El seguimiento de posiciones captura el precio de entrada ponderado por volumen para que la lógica de seguimiento se alinee con los rellenos parciales y las reversiones.
Parámetros
Parámetro
Descripción
ForcePeriod
Período de suavizado del índice de fuerza (predeterminado 13).
TakeProfitPoints
Distancia de obtención de beneficios en MetaTrader puntos.
StopLossPoints
Distancia de stop-loss en MetaTrader puntos.
BullsThreshold
Umbral del índice de fuerza alcista que permite entradas largas.
BearsThreshold
Umbral del índice de fuerza bajista que permite entradas cortas.
EnableTrailing
Habilita la lógica del trailing stop.
TrailingStartPoints
Distancia (en puntos) mantenida entre el precio y el trailing stop una vez activado.
TrailingStepPoints
Beneficio (en puntos) requerido antes de que se active el trailing stop.
CandleType
Marco de tiempo utilizado para los cálculos del índice de fuerza (por defecto, velas H1).
Notas
La validación del parámetro evita que el activador de seguimiento (TrailingStepPoints) supere la distancia de seguimiento (TrailingStartPoints), coincidiendo con la verificación de seguridad MetaTrader.
La aplicación del nivel de parada del EA original (corredor MODE_STOPLEVEL) se aproxima a través de las conversiones de precio-escalón de StockSharp. Dependiendo de las limitaciones del corredor, es posible que se requiera una validación adicional.
Todos los comentarios y registros del código se proporcionan en inglés según lo solicitado por las pautas de conversión.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// DreamBot strategy: Force Index momentum with EMA trend filter.
/// Buys when Force Index positive and close above EMA, sells when negative and below EMA.
/// </summary>
public class DreamBotStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevClose;
private bool _hasPrevClose;
private bool _wasBullish;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public DreamBotStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 100)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0m;
_hasPrevClose = false;
_wasBullish = false;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrevClose = false;
_candlesSinceTrade = SignalCooldownCandles;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
var close = candle.ClosePrice;
var volume = candle.TotalVolume;
if (_hasPrevClose && volume > 0)
{
// Simple force index: (close - prevClose) * volume
var forceIndex = (close - _prevClose) * volume;
var isBullish = forceIndex > 0 && close > emaValue;
if (isBullish && !_wasBullish && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (!isBullish && forceIndex < 0 && close < emaValue && _wasBullish && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
_wasBullish = isBullish;
}
_prevClose = close;
_hasPrevClose = true;
}
}
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 dream_bot_strategy(Strategy):
def __init__(self):
super(dream_bot_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 100)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._prev_close = 0.0
self._has_prev_close = False
self._was_bullish = False
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(dream_bot_strategy, self).OnReseted()
self._prev_close = 0.0
self._has_prev_close = False
self._was_bullish = False
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(dream_bot_strategy, self).OnStarted2(time)
self._has_prev_close = False
self._candles_since_trade = self.SignalCooldownCandles
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
volume = float(candle.TotalVolume)
ema_val = float(ema_value)
if self._has_prev_close and volume > 0:
force_index = (close - self._prev_close) * volume
is_bullish = force_index > 0 and close > ema_val
if is_bullish and not self._was_bullish and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif not is_bullish and force_index < 0 and close < ema_val and self._was_bullish and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._was_bullish = is_bullish
self._prev_close = close
self._has_prev_close = True
def CreateClone(self):
return dream_bot_strategy()