Auf GitHub ansehen

MACFibo Strategy

This strategy implements the MACFibo trading system. It waits for a crossover between the 5-period EMA and the 20-period SMA. After the cross, the algorithm measures the swing from the close of the cross bar (point A) to the most recent extreme (point B) and builds Fibonacci expansion levels. Positions are opened at market price with take profit and stop loss derived from these levels. An optional exit closes losing trades when the fast EMA crosses the mid SMA in the opposite direction.

Details

  • Entry Conditions:
    • Long: 5 EMA crosses above 20 SMA. Point B is the lowest low since the downward move started.
    • Short: 5 EMA crosses below 20 SMA. Point B is the highest high since the upward move started.
  • Exit Conditions:
    • Take profit at the 161.8% Fibonacci level or the minimum take profit distance.
    • Stop loss at the 38.2% Fibonacci level or the maximum stop loss distance.
    • Optional close if 5 EMA crosses 8 SMA against the position and the trade is losing.
  • Filters:
    • Trades only between configured start and end hours.
    • Trading on Monday or Friday can be disabled.
  • Parameters:
    • FastLength – fast EMA length.
    • MidLength – middle SMA length for protective exit.
    • SlowLength – slow SMA length for trend detection.
    • MinTakeProfit – minimum take profit in price units.
    • MaxStopLoss – maximum stop loss in price units.
    • StartHour / EndHour – allowed trading time window.
    • FridayTrade / MondayTrade – enable trading on these days.
    • CloseAtFastMid – close losing trades on fast-mid cross.
    • CandleType – candle type for calculations.
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>
/// EMA crossover strategy with Fibonacci-inspired targets.
/// </summary>
public class MacfiboStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public MacfiboStrategy()
	{
		_fastLength = Param(nameof(FastLength), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA 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 fast = new ExponentialMovingAverage { Length = FastLength };
		var slow = new ExponentialMovingAverage { Length = SlowLength };

		SubscribeCandles(CandleType).Bind(fast, slow, ProcessCandle).Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastValue > slowValue;
		var crossDown = _prevFast >= _prevSlow && fastValue < slowValue;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}