Auf GitHub ansehen

Fibo Gleitender Durchschnitt Kreuzungs-Strategie

Übersicht

Diese Strategie konvertiert den MetaTrader Expert Advisor EA_Fibo_Avg_001a in das StockSharp-Framework. Sie verwendet zwei geglättete gleitende Durchschnitte. Die Länge des langsamen Durchschnitts ist die Summe des Basiszeitraums und eines Fibonacci-basierten Versatzes. Eine Long-Position wird eröffnet, wenn der schnelle Durchschnitt den langsamen nach oben kreuzt, während eine Short-Position bei der entgegengesetzten Kreuzung eröffnet wird. Positionen werden mit Stop-Loss, Take-Profit und einem Trailing Stop verwaltet. Optionales Money Management kann das Ordervolumen aus der Portfoliogröße berechnen.

Parameter

  • CandleType – Kerzen-Datentyp.
  • FiboNumPeriod – zusätzliche Länge, die zum langsamen gleitenden Durchschnitt addiert wird.
  • MaPeriod – Basiszeitraum der gleitenden Durchschnitte.
  • TrailingStop – Trailing-Abstand in Preisschritten.
  • TakeProfit – Take-Profit-Abstand in Preisschritten.
  • StopLoss – Stop-Loss-Abstand in Preisschritten.
  • UseMoneyManagement – einfaches Money Management aktivieren.
  • PercentMm – Portfolioprozentsatz bei aktiviertem Money Management.
  • LotSize – Standard-Ordervolumen bei deaktiviertem Money Management.

Logik

  1. Kerzen abonnieren und zwei geglättete gleitende Durchschnitte berechnen.
  2. Wenn der schnelle Durchschnitt den langsamen nach oben kreuzt, kaufen. Wenn er nach unten kreuzt, verkaufen.
  3. Nach dem Einstieg in eine Position Stop-Loss-, Take-Profit- und Trailing-Levels setzen.
  4. Trailing Stop aktualisieren, wenn sich der Preis zugunsten der Position bewegt, und Positionen schließen, wenn Schutzlevels erreicht werden oder die entgegengesetzte Kreuzung auftritt.
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 crossover of two smoothed moving averages with Fibonacci offset.
/// </summary>
public class FiboAvg001aStrategy : Strategy
{
	private readonly StrategyParam<int> _fiboNumPeriod;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FiboNumPeriod { get => _fiboNumPeriod.Value; set => _fiboNumPeriod.Value = value; }
	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FiboAvg001aStrategy()
	{
		_fiboNumPeriod = Param(nameof(FiboNumPeriod), 11)
			.SetGreaterThanZero()
			.SetDisplay("Fibo Period", "Additional length for slow MA", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Base moving average period", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var fastMa = new SmoothedMovingAverage { Length = MaPeriod };
		var slowMa = new SmoothedMovingAverage { Length = MaPeriod + FiboNumPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastMa, slowMa, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		// Fast crosses above slow -> buy
		if (_prevFast <= _prevSlow && fast > slow)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Fast crosses below slow -> sell
		else if (_prevFast >= _prevSlow && fast < slow)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}