GitHub で見る

SMA Multi Hedge2 Strategy

This strategy trades a base security while hedging with a correlated instrument. Trend direction is determined by a Simple Moving Average (SMA). When the correlation between the base and hedge symbols exceeds a threshold, both instruments are traded to form a market-neutral pair.

How It Works

  1. Calculate the trend of the base symbol using an SMA of configurable length.
  2. Measure correlation between the base and hedge symbols using the difference between price and its own SMA.
  3. If the correlation reaches the expected level, open positions on both instruments. The hedge direction can follow or oppose the base depending on configuration.
  4. Positions are closed automatically when the combined profit reaches the target value.

Parameters

  • SmaPeriod — period of the SMA used to detect trend. Default is 20.
  • CorrelationPeriod — number of samples used to evaluate correlation. Default is 20.
  • ExpectedCorrelation — minimum absolute correlation required to activate hedging. Default is 0.8.
  • ProfitTarget — overall profit target in money units. Default is 30.
  • CandleType — data type for candle subscription. Default is 1‑minute timeframe.
  • FollowBase — if true, hedge trades in the same direction when correlation is positive.

Indicators

  • SMA
  • Correlation (custom calculation)

Notes

This is a simplified port of the original MQL strategy. Risk and money management should be adjusted before live trading.

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>
/// SMA trend direction strategy.
/// </summary>
public class SmaMultiHedge2Strategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevEma1;
	private decimal _prevEma2;
	private int _count;

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

	public SmaMultiHedge2Strategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend period", "Parameters");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "Parameters");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevEma1 = 0;
		_prevEma2 = 0;
		_count = 0;
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		SubscribeCandles(CandleType)
			.Bind(ema, ProcessCandle)
			.Start();
	}

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

		_count++;
		if (_count < 3)
		{
			_prevEma2 = _prevEma1;
			_prevEma1 = emaVal;
			return;
		}

		var trend = 0;
		if (_prevEma2 < _prevEma1 && _prevEma1 < emaVal)
			trend = 1;
		else if (_prevEma2 > _prevEma1 && _prevEma1 > emaVal)
			trend = -1;

		_prevEma2 = _prevEma1;
		_prevEma1 = emaVal;

		if (trend == 1 && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (trend == -1 && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}
	}
}