Auf GitHub ansehen

ColorJFatl Digit Strategie

Diese Strategie verwendet die Steigungsrichtung eines Jurik Moving Average (JMA), um Trades zu generieren. Der JMA approximiert den "ColorJFatl_Digit"-Indikator aus dem ursprünglichen MQL5-Experten. Eine Long-Position wird eröffnet, wenn der JMA aufwärts dreht, während eine Short-Position eröffnet wird, wenn der JMA abwärts dreht. Entgegengesetzte Positionen werden geschlossen, wenn sich die Steigung umkehrt.

Das System handelt in beide Richtungen und verwendet standardmäßig keine harten Stops. Es eignet sich für Instrumente, bei denen Trendwechsel durch einen glatten adaptiven gleitenden Durchschnitt erfasst werden können.

Details

  • Einstiegskriterien:
    • Long: JMA-Steigung wechselt von negativ zu positiv.
    • Short: JMA-Steigung wechselt von positiv zu negativ.
  • Long/Short: Beide Seiten.
  • Ausstiegskriterien:
    • Long: JMA-Steigung wird negativ.
    • Short: JMA-Steigung wird positiv.
  • Stops: Standardmäßig keine.
  • Standardwerte:
    • JMA Length = 5
    • Timeframe = 4 Stunden
  • Filter:
    • Kategorie: Trendfolge
    • Richtung: Beide
    • Indikatoren: Einzeln
    • Stops: Nein
    • Komplexität: Einfach
    • Zeitrahmen: Mittelfristig
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
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;

/// <summary>
/// Strategy based on the slope changes of Jurik Moving Average (JMA).
/// Opens long when JMA turns up, opens short when JMA turns down.
/// </summary>
public class ColorJFatlDigitStrategy : Strategy
{
	private readonly StrategyParam<int> _jmaLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevJma;
	private decimal? _prevSlope;

	public int JmaLength { get => _jmaLength.Value; set => _jmaLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public ColorJFatlDigitStrategy()
	{
		_jmaLength = Param(nameof(JmaLength), 5)
			.SetGreaterThanZero()
			.SetDisplay("JMA Length", "Period for Jurik Moving Average", "Parameters");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe of indicator", "Parameters");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevJma = null;
		_prevSlope = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevJma = null;
		_prevSlope = null;

		var jma = new JurikMovingAverage { Length = JmaLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(jma, Process)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, jma);
			DrawOwnTrades(area);
		}
	}

	private void Process(ICandleMessage candle, decimal jmaValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var slope = _prevJma is decimal prev ? jmaValue - prev : (decimal?)null;

		if (slope is decimal s && _prevSlope is decimal ps)
		{
			// JMA slope turns positive -> buy
			if (ps <= 0m && s > 0m && Position <= 0)
				BuyMarket();
			// JMA slope turns negative -> sell
			else if (ps >= 0m && s < 0m && Position >= 0)
				SellMarket();
		}

		_prevSlope = slope;
		_prevJma = jmaValue;
	}
}