マルチタイムフレーム回帰戦略
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import LinearReg, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class multi_time_frame_regression_strategy(Strategy):
"""
Multi Time Frame Regression: linear regression channel with highest/lowest boundaries.
"""
def __init__(self):
super(multi_time_frame_regression_strategy, self).__init__()
self._regression_length = self.Param("RegressionLength", 20).SetDisplay("Regression", "LinReg period", "Indicators")
self._channel_length = self.Param("ChannelLength", 20).SetDisplay("Channel", "Channel period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candles", "General")
self._prev_lr = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(multi_time_frame_regression_strategy, self).OnReseted()
self._prev_lr = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(multi_time_frame_regression_strategy, self).OnStarted2(time)
lr = LinearReg()
lr.Length = self._regression_length.Value
highest = Highest()
highest.Length = self._channel_length.Value
lowest = Lowest()
lowest.Length = self._channel_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(lr, highest, lowest, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, lr)
self.DrawOwnTrades(area)
def _process_candle(self, candle, lr_val, high_val, low_val):
if candle.State != CandleStates.Finished:
return
lr = float(lr_val)
h = float(high_val)
l = float(low_val)
close = float(candle.ClosePrice)
slope = lr - self._prev_lr if self._has_prev else 0.0
ch_mid = (h + l) / 2.0
ch_width = h - l
if ch_width <= 0:
self._prev_lr = lr
self._has_prev = True
return
upper = ch_mid + ch_width * 0.4
lower = ch_mid - ch_width * 0.4
if self.Position > 0 and (close >= upper or slope < 0):
self.SellMarket()
elif self.Position < 0 and (close <= lower or slope > 0):
self.BuyMarket()
if self.Position == 0:
if close <= lower and slope >= 0:
self.BuyMarket()
elif close >= upper and slope <= 0:
self.SellMarket()
self._prev_lr = lr
self._has_prev = True
def CreateClone(self):
return multi_time_frame_regression_strategy()