Auf GitHub ansehen

Strategie FRASMAv2

Strategie basierend auf dem Fractal Adaptive Simple Moving Average (FRASMAv2).

Diese Strategie berechnet einen fraktal-adaptiven einfachen gleitenden Durchschnitt unter Verwendung des Fractal-Dimension-Indikators. Die Indikatorfarbe ändert sich je nach Steigung: grün für steigend, grau für seitwärts, magenta für fallend. Die Strategie überwacht Farbwechsel bei der letzten abgeschlossenen Kerze:

  • Wenn der Indikator auf dem vorherigen Balken grün war und auf dem letzten Balken nicht grün (grau oder magenta) wird, schließt die Strategie Short-Positionen und eröffnet eine neue Long-Position.
  • Wenn der Indikator magenta war und nicht mehr magenta wird, schließt die Strategie Long-Positionen und eröffnet eine neue Short-Position.

Das Risikomanagement verwendet Stop-Loss- und Take-Profit-Parameter, die in Punkten angegeben werden.

Details

  • Einstiegskriterien: Farbwechsel von FRASMAv2.
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien: Entgegengesetzter Farbwechsel.
  • Stops: Take-Profit und Stop-Loss über das Schutzmodul.
  • Standardwerte:
    • Period = 30
    • TakeProfit = 2000 Punkte
    • StopLoss = 1000 Punkte
    • CandleType = TimeSpan.FromHours(4)
  • Filter:
    • Kategorie: Trendumkehr
    • Richtung: Beide
    • Indikatoren: FractalDimension, FRASMAv2
    • Stops: Ja
    • Komplexität: Mittel
    • Zeitrahmen: 4h
    • 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 Fractal Adaptive Simple Moving Average (FRASMAv2).
/// Computes FRAMA from fractal dimension, trades on color (slope direction) changes.
/// </summary>
public class FrasmaV2Strategy : Strategy
{
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<DataType> _candleType;

	private bool _isFirst;
	private decimal _prevFrama;
	private int _prevColor;

	public int Period { get => _period.Value; set => _period.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FrasmaV2Strategy()
	{
		_period = Param(nameof(Period), 30)
			.SetGreaterThanZero()
			.SetDisplay("Period", "FRAMA calculation period", "Indicator");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_isFirst = true;
		_prevFrama = 0;
		_prevColor = 1;
	}

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

		_isFirst = true;
		_prevFrama = 0;
		_prevColor = 1;

		var fdi = new FractalDimension { Length = Period };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(fdi, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue fdiValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!fdiValue.IsFinal)
			return;

		var fdi = fdiValue.GetValue<decimal>();
		var alpha = (decimal)Math.Exp(-4.6 * ((double)fdi - 1.0));
		alpha = Math.Max(0.01m, Math.Min(1m, alpha));

		var price = candle.ClosePrice;
		var frama = _isFirst ? price : alpha * price + (1 - alpha) * _prevFrama;

		int color;
		if (_isFirst)
		{
			color = 1;
			_isFirst = false;
		}
		else if (frama > _prevFrama)
			color = 0; // Uptrend
		else if (frama < _prevFrama)
			color = 2; // Downtrend
		else
			color = 1; // Flat

		// Uptrend ended (color was 0, now > 0) -> sell signal
		if (_prevColor == 0 && color > 0 && Position >= 0)
			SellMarket();
		// Downtrend ended (color was 2, now < 2) -> buy signal
		else if (_prevColor == 2 && color < 2 && Position <= 0)
			BuyMarket();

		_prevFrama = frama;
		_prevColor = color;
	}
}