GitHub で見る

マルチタイムフレーム回帰戦略

M1、M5、および H1 ローソク足の線形回帰チャネルを組み合わせたマルチタイムフレーム戦略。 H1 チャネルからの回帰勾配は支配的なトレンドを定義し、M5 および M1 チャネルはサポートとレジスタンス付近の正確なエントリー位置を提供します。

取引ロジック

  • データ フィード: 標準ローソク足の 9 つのタイムフレーム (M1、M5、M15、M30、H1、H4、D1、W1、MN1)。
  • インジケーター: 各フィードは、構成可能な長さの線形回帰チャネルによって処理されます。このチャネルは、最近の終値の最大偏差に基づいて中心線と対称の上部/下部バンドを提供します。
  • トレンド フィルター: この戦略では、H1 チャネルの傾きが負の場合はショート取引のみが考慮され、正の場合はロング取引が考慮されます。
  • エントリ:
    • ショート – 最新の M5 高値と M1 高値は両方とも、上部チャネル バンドを突き抜けていますが、H1 の傾きは負です。
    • ロング – 最新の M5 安値と M1 安値は両方とも、H1 の傾きが正である間に、より低いチャネル バンドに到達します。
  • 注文処理: エントリは、設定された数量を使用して成行注文で実行されます。ストップロスとテイクプロフィットのターゲットは、それぞれ M5 チャネルの半幅とセンターラインから導出されます。
  • 終了: 価格が保護ストップまたはセンターラインターゲットに達すると、M1 ローソク足のポジションは閉じられます。
  • ポジション管理: いつでもオープンできる市場ポジションは最大 1 つです。

パラメーター

名前 説明
EnableTrading 有効にすると、ストラテジーで注文を行うことができます。
BarsToCount すべての回帰チャネルで使用されるバーの数 (デフォルトは 50)。
Volume ロット単位の成行注文量。

注意事項

  • 回帰ウィンドウが長くなると、チャネルの傾きは滑らかになりますが、反応は遅くなります。
  • マルチタイムフレームのスロープ表示は、H1 スロープ ゲート エントリのみであっても、より高い間隔にわたるアラインメントを監視するのに役立ちます。
  • 保護レベルは、新しい M5 キャンドルが形成されるたびに再計算されます。頻繁に再調整することで、リスクが現在のチャネル形状と密接に結びついた状態に保たれます。
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Linear regression channel strategy.
/// Uses LinearReg as the center line with Highest/Lowest to form a channel.
/// Sells at upper channel, buys at lower channel, with trend filter from regression slope.
/// </summary>
public class MultiTimeFrameRegressionStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _regressionLength;
	private readonly StrategyParam<int> _channelLength;

	private decimal _prevLrValue;
	private bool _hasPrev;

	public MultiTimeFrameRegressionStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for analysis.", "General");

		_regressionLength = Param(nameof(RegressionLength), 20)
			.SetDisplay("Regression Length", "Period for linear regression.", "Indicators");

		_channelLength = Param(nameof(ChannelLength), 20)
			.SetDisplay("Channel Length", "Period for highest/lowest channel.", "Indicators");
	}

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

	public int RegressionLength
	{
		get => _regressionLength.Value;
		set => _regressionLength.Value = value;
	}

	public int ChannelLength
	{
		get => _channelLength.Value;
		set => _channelLength.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevLrValue = 0;
		_hasPrev = false;
	}

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

		_prevLrValue = 0;
		_hasPrev = false;

		var lr = new LinearReg { Length = RegressionLength };
		var highest = new Highest { Length = ChannelLength };
		var lowest = new Lowest { Length = ChannelLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(lr, highest, lowest, ProcessCandle)
			.Start();

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

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

		var close = candle.ClosePrice;

		// Determine slope direction from regression
		var slope = _hasPrev ? lrValue - _prevLrValue : 0m;

		// Channel boundaries
		var channelMid = (highestValue + lowestValue) / 2m;
		var channelWidth = highestValue - lowestValue;

		if (channelWidth <= 0)
		{
			_prevLrValue = lrValue;
			_hasPrev = true;
			return;
		}

		// Upper/lower thresholds
		var upperThreshold = channelMid + channelWidth * 0.4m;
		var lowerThreshold = channelMid - channelWidth * 0.4m;

		// Exit conditions
		if (Position > 0 && (close >= upperThreshold || slope < 0))
		{
			SellMarket();
		}
		else if (Position < 0 && (close <= lowerThreshold || slope > 0))
		{
			BuyMarket();
		}

		// Entry conditions
		if (Position == 0)
		{
			if (close <= lowerThreshold && slope >= 0)
			{
				// Price near lower channel with flat/rising regression
				BuyMarket();
			}
			else if (close >= upperThreshold && slope <= 0)
			{
				// Price near upper channel with flat/falling regression
				SellMarket();
			}
		}

		_prevLrValue = lrValue;
		_hasPrev = true;
	}
}