DreamBot ist eine StockSharp-Portierung des MetaTrader 4-Expertenberaters „DreamBot“. Die Strategie überwacht den Force-Index-Oszillator auf stündlichen Kerzen und wartet darauf, dass das Momentum bullische oder bärische Schwellenwerte überschreitet. Wenn der Force-Index das bullische Niveau überschreitet, nachdem er beim vorherigen Balken darunter lag, eröffnet die Strategie eine Long-Position. Wenn der Force-Index das rückläufige Niveau unterschreitet, nachdem er darüber gelegen hat, eröffnet die Strategie eine Short-Position. Der Handel erfolgt nur, wenn keine Position vorhanden ist, was die Einzelpositionslogik des ursprünglichen Roboters widerspiegelt.
Handelslogik
Abonnieren Sie H1-Kerzen und berechnen Sie einen geglätteten Kraftindex (standardmäßig Länge 13).
Verfolgen Sie die letzten beiden abgeschlossenen Force-Index-Werte. Signale werden unter Verwendung der vorherigen Balkenwerte generiert, genau wie bei der MT4-Implementierung (iForce mit Verschiebung 1 und 2).
Geben Sie Long ein, wenn der Force Index der vorherigen Kerze über BullsThreshold liegt und der Wert zwei Kerzen zurück unter dem Schwellenwert lag, vorausgesetzt, es ist keine Position offen.
Geben Sie Short ein, wenn der Force Index der vorherigen Kerze unter BearsThreshold liegt und der Wert zwei Kerzen zurück über dem Schwellenwert lag, vorausgesetzt, es ist keine Position offen.
Der optionale Trailing-Stop reproduziert den ursprünglichen EA: Sobald der Gewinn TrailingStepPoints übersteigt, wird ein Stop-Level auf TrailingStartPoints vom Preis weg gezogen und folgt weiteren Anstiegen.
Risikomanagement
StartProtection fügt klassische Stop-Loss- und Take-Profit-Orders unter Verwendung der durch die Preisstufe des Instruments umgerechneten Distanz von MetaTrader „Punkten“ hinzu.
Der Trailing-Schutz ist marktbasiert: Wenn das berechnete Trailing-Level durchbrochen wird, sendet die Strategie einen Marktauftrag, um die Position sofort zu schließen.
Die Positionsverfolgung erfasst den volumengewichteten Einstiegspreis, sodass die abschließende Logik auf Teilfüllungen und Umkehrungen ausgerichtet ist.
Parameter
Parameter
Beschreibung
ForcePeriod
Glättungszeitraum des Force-Index (Standard 13).
TakeProfitPoints
Take-Profit-Distanz in MetaTrader Punkten.
StopLossPoints
Stop-Loss-Distanz in MetaTrader Punkten.
BullsThreshold
Schwellenwert des Bullish Force Index, der Long-Einstiege ermöglicht.
BearsThreshold
Schwellenwert des Bearish Force Index, der Short-Einstiege ermöglicht.
EnableTrailing
Aktiviert die Trailing-Stop-Logik.
TrailingStartPoints
Abstand (in Punkten), der nach der Aktivierung zwischen Preis und Trailing Stop beibehalten wird.
TrailingStepPoints
Erforderlicher Gewinn (in Punkten), bevor der Trailing Stop aktiviert wird.
CandleType
Für die Force-Index-Berechnungen verwendeter Zeitrahmen (standardmäßig H1-Kerzen).
Notizen
Die Parametervalidierung verhindert, dass der Trailing-Trigger (TrailingStepPoints) die Trailing-Distanz (TrailingStartPoints) überschreitet, was der Sicherheitsprüfung MetaTrader entspricht.
Die Stop-Level-Durchsetzung des ursprünglichen EA (Broker MODE_STOPLEVEL) wird durch die Preisstufenumrechnungen von StockSharp angenähert. Abhängig von den Einschränkungen des Brokers kann eine zusätzliche Validierung erforderlich sein.
Alle Codekommentare und Protokolle werden gemäß den Konvertierungsrichtlinien auf Englisch bereitgestellt.
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()