Auf GitHub ansehen

JS Signal Baes-Strategie

Übersicht

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:

  1. Schnelle MA > Langsame MA.
  2. MACD-Hauptlinie > MACD-Signallinie.
  3. RSI > 50.
  4. CCI > 0.
  5. Stochastik %K > 40.

Ein Zeitrahmen gilt als bärisch, wenn:

  1. Schnelle MA < Langsame MA.
  2. MACD-Hauptlinie < MACD-Signallinie.
  3. RSI < 50.
  4. CCI < 0.
  5. 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;
	}
}