GitHub で見る

Linear Regression Channel (Fibo)戦略

概要

この戦略は、MetaTraderエキスパートアドバイザー "linear regression channel" のStockSharp変換版です。加重移動平均、Momentumの読み取り、月次MACDフィルターによって確認された上位時間軸の線形トレンドの方向に取引します。資金管理ルールは、浮動利益目標、累積利益のトレーリング、ブレークイーブン保護、エクイティストップによるオリジナルの動作を再現します。

トレードロジック

  1. 主要時間軸 – 設定可能なキャンドルタイプ(デフォルト15分)。すべてのシグナル計算はこの時間軸で実行されます。
  2. トレンドフィルター – 標準価格で計算された高速LWMAと低速LWMA。ロングシグナルは高速LWMAが低速LWMAを上回ることを必要とし、ショートシグナルはその逆を必要とします。
  3. Momentum確認 – Momentumインジケーターは、オリジナルのMetaTraderマッピングを反映した上位時間軸(M1→M15、M5→M30、M15→H1、M30→H4、H1→D1、H4→W1、D1→MN1)で評価されます。最後の3つのMomentum値はレベル100からの絶対距離に変換されます。ロングセットアップでは3つの距離のいずれかが強気閾値を超える必要があり、ショートセットアップでは3つのいずれかが弱気閾値を超える必要があります。
  4. 月次MACDバイアス – 月次キャンドルがMACD(12,26,9)フィルターを駆動します。MACD主線がシグナル線を上回っている場合のみロングトレードが許可され、ショートトレードは逆の関係を必要とします。
  5. エントリー条件 – すべてのフィルターが揃い取引が許可されると、戦略は対応する方向に成行注文を出します。反対のシグナルが生成されると、現在のポジションが決済・反転されます。

リスクとトレード管理

  • 固定ストップロス / テイクプロフィット – 距離はインストゥルメントポイントで定義され、すべてのエントリーに適用されます。キャンドルの高値/安値がこれらのレベルを突破すると、ポジションが決済されます。
  • トレーリングストップ – オプション;ポジションが設定可能なポイント数を獲得すると有効化され、指定されたオフセットで最良価格を追従します。
  • ブレークイーブン – オプション;価格がトリガー距離を前進した後、利益を確保するためにストップレベルがエントリー価格プラス/マイナスオフセットに移動されます。
  • 浮動利益テイクプロフィット – オプションの金銭的目標。純未実現利益(口座通貨で表示)が閾値を超えると、すべてのポジションが決済されます。
  • パーセントベースのテイクプロフィット – 戦略開始時の初期エクイティに基づくオプション目標。
  • マネートレーリング – 浮動利益がトリガーに達すると、戦略はピーク利益を記録します。利益が指定されたストップ額だけ後退すると、ポジションが決済されます。
  • エクイティストップ – オプションのドローダウン保護。ポジションが損失を出している間、浮動損失が観測されたエクイティピークの一定パーセンテージを超えると、戦略はポジションを清算します。

パラメーター

名称 説明
Candle Type シグナル生成のための主要時間軸。
Fast LWMA / Slow LWMA 高速および低速の線形加重移動平均の期間。
Momentum Length 上位時間軸でのMomentumのルックバック長。
Momentum Buy Threshold / Momentum Sell Threshold 強気/弱気のMomentum確認に必要な100からの最小絶対距離。
Take Profit (points) / Stop Loss (points) インストゥルメントポイントで表された保護距離。
Use Trailing, Trailing Activation, Trailing Offset トレーリングストップの設定。
Use Break-even, Break-even Trigger, Break-even Offset ブレークイーブンロジックパラメーター。
Max Trades 実行中に許可される連続エントリーの最大数。
Order Volume 成行注文のベースボリューム。
Use Money TP, Money Take Profit 浮動金銭的テイクプロフィット。
Use Percent TP, Percent Take Profit 初期エクイティのパーセンテージとして計算されるテイクプロフィット。
Enable Money Trailing, Money Trailing Trigger, Money Trailing Stop 浮動利益のトレーリング。
Use Equity Stop, Equity Risk % エクイティベースのストップロス保護。

注意事項

  • 戦略は単一のネットポジション(ロングまたはショート)のみを保持し、反対のシグナルが届くと反転します。
  • MomentumとMACDのサブスクリプションは、GetWorkingSecurities()を通じてデータフィードに必要な上位時間軸を自動的に追加します。
  • コード内のすべてのコメントはリポジトリガイドラインに従って英語で記述されています。
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;

public class LinearRegressionChannelFibStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public LinearRegressionChannelFibStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}