Auf GitHub ansehen

Trend Continuation Strategy

This strategy identifies continuation of the prevailing trend using a pair of exponential moving averages on price data. A long position is opened when the fast EMA crosses above the slow EMA, signaling upward continuation. A short position is opened when the fast EMA crosses below the slow EMA.

Parameters

  • Fast EMA Length – period for the fast EMA (default: 20).
  • Candle Type – timeframe of candles (default: 4-hour).
  • Stop Loss – protective stop loss applied via StartProtection (default: 1000).
  • Take Profit – profit target applied via StartProtection (default: 2000).

How It Works

  1. On start the strategy subscribes to the selected candle series and creates two EMA indicators.
  2. Each finished candle is processed to detect crossovers between the fast and slow EMAs.
  3. A crossover from below to above opens a long position and closes any short one. The opposite crossover opens a short position and closes any long.
  4. Risk management is handled through the built-in stop loss and take profit parameters.

This example is a simplified conversion of the original MQL Exp_TrendContinuation expert.

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>
/// Trend continuation strategy based on fast and slow EMA cross.
/// Opens long when fast EMA crosses above slow EMA, short on opposite.
/// </summary>
public class TrendContinuationStrategy : Strategy
{
	private readonly StrategyParam<int> _length;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevFast;
	private decimal? _prevSlow;

	public int Length
	{
		get => _length.Value;
		set => _length.Value = value;
	}

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

	public TrendContinuationStrategy()
	{
		_length = Param(nameof(Length), 20)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA Length", "Period for the fast EMA", "Indicators");

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

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

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

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

		_prevFast = _prevSlow = null;

		var fast = new ExponentialMovingAverage { Length = Length };
		var slow = new ExponentialMovingAverage { Length = Length * 2 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (_prevFast.HasValue && _prevSlow.HasValue)
		{
			if (_prevFast < _prevSlow && fast >= slow && Position <= 0)
				BuyMarket();

			if (_prevFast > _prevSlow && fast <= slow && Position >= 0)
				SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}