Diese Strategie ist ein StockSharp-Port des MetaTrader Expert Advisors „JS Signal Baes". Sie bewertet gleichzeitig sechs verschiedene Zeitrahmen (standardmäßig M1, M5, M15, M30, H1, H4) und wartet, bis alle überwachten Indikatoren in derselben Marktrichtung übereinstimmen, bevor eine Position eröffnet wird. Signale können über den Reverse-Parameter invertiert werden für Benutzer, die entgegen dem erkannten Trend handeln möchten.
Indikatoren und Bestätigungen
Folgende Indikatoren werden auf jedem der sechs Zeitrahmen berechnet:
Zwei Moving Averages mit der ausgewählten Glättungsmethode (einfach, exponentiell, geglättet oder linear gewichtet).
MACD (Moving Average Convergence Divergence) mit konfigurierbaren schnellen, langsamen und Signal-Längen.
RSI (Relative Strength Index) mit einem dedizierten Periodenparameter.
CCI (Commodity Channel Index) mit eigener Lookback-Länge.
Stochastic Oszillator definiert durch K-, D- und Glättungsperioden.
Ein Zeitrahmen gilt als bullisch, wenn:
Schnelle MA > Langsame MA.
MACD-Hauptlinie > MACD-Signallinie.
RSI > 50.
CCI > 0.
Stochastik %K > 40.
Ein Zeitrahmen gilt als bärisch, wenn:
Schnelle MA < Langsame MA.
MACD-Hauptlinie < MACD-Signallinie.
RSI < 50.
CCI < 0.
Stochastik %K < 60.
Handelsregeln
Eine neue netto-Position wird nur eröffnet, wenn der primäre Zeitrahmen (Standard M1) schließt und alle sechs Zeitrahmen gleichzeitig bullisch oder bärisch sind:
Long-Einstieg: jeder Zeitrahmen ist bullisch. Wenn Reverse aktiviert ist, wird das Signal zu einem Short-Einstieg.
Short-Einstieg: jeder Zeitrahmen ist bärisch. Wenn Reverse aktiviert ist, wird das Signal zu einem Long-Einstieg.
Positionen werden nicht pyramidisiert. Die Strategie wartet, bis die bestehende Position extern geschlossen wird, bevor sie auf ein neues Signal reagiert. Es gibt keine automatischen Ausstiege über die entgegengesetzte Signallogik des Original Expert Advisors hinaus.
Parameter
Parameter
Standard
Beschreibung
CciPeriod
13
Lookback-Länge für den Commodity Channel Index.
FastMaPeriod
5
Länge des schnellen Moving Average.
SlowMaPeriod
9
Länge des langsamen Moving Average.
MaMethod
LinearWeighted
Moving-Average-Glättungstyp für beide Durchschnitte.
MacdFastPeriod
8
Schnelle EMA-Länge für MACD.
MacdSlowPeriod
17
Langsame EMA-Länge für MACD.
MacdSignalPeriod
9
Signallinienlänge für MACD.
StochasticKPeriod
5
K-Periode für den stochastischen Oszillator.
StochasticDPeriod
3
D-Periode für den stochastischen Oszillator.
StochasticSmoothing
3
Glättungsfaktor für den stochastischen Oszillator.
RsiPeriod
9
RSI-Lookback-Länge.
ReverseSignals
false
Richtung jedes Handelssignals invertieren.
TimeFrame1..6
M1, M5, M15, M30, H1, H4
Kerzenserien für jeden Zeitrahmen.
Hinweise
Die Standardparameter replizieren die in der MetaTrader-Version eingebettete Konfiguration.
Geldverwaltung, Stop-Loss, Take-Profit und Trailing-Logik aus dem Originalcode werden nicht reproduziert; Portfolio-Level-Risikokontrollen verwenden falls erforderlich.
Stellen Sie sicher, dass historische Daten für jeden ausgewählten Zeitrahmen verfügbar sind, damit die Indikatoren sich aufwärmen können, bevor gehandelt wird.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class JsSignalBaesStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public JsSignalBaesStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 js_signal_baes_strategy(Strategy):
def __init__(self):
super(js_signal_baes_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(js_signal_baes_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(js_signal_baes_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return js_signal_baes_strategy()