GitHub で見る
戦略 Layered Risk Protector Strategy
概要
階層化リスク プロテクター戦略は、MetaTrader エキスパート アドバイザー「RiskManager」を直接変換したものです。このアルゴリズムはポートフォリオの株式曲線を継続的に追跡し、商品チャネル指数 (CCI)、平均トゥルーレンジ (ATR) の倍数、および階層化されたポジションサイジングモデルを使用して市場エクスポージャーを調整します。リスク指標が設定可能なしきい値を下回ると、戦略は自動的にヘッジ モードに切り替わり、利益またはドローダウン イベントでポジションをクローズし、オプションで損益分岐点でフラット化することもできます。
取引ロジック
- インジケーター条件 – この戦略は、プライマリ ローソク足シリーズ (構成可能な時間枠) をサブスクライブし、以下を計算します。
- CCI using the user-defined period.ロングトレードでは CCI がマイナスのしきい値を下回る必要があり、ショートトレードではプラスのしきい値を上回ることが必要です。
- 開いている各レイヤーのボラティリティ調整済みテイクプロフィット距離とストップロス距離を導出するために、固定期間 14 の ATR を使用します。
- A moving average of candle volumes.取引は、完了した最後の 50 個のローソク足の移動平均が前のローソク足の量を超えた場合にのみ有効になり、元の「アクティブ」フィルターが複製されます。
- 階層化エントリ – 最大露出は、構成可能な数のレイヤーに分散されます。新しい注文ごとに、レイヤーごとのボリューム (
MaxVolume / Layers) が使用されます。相対的なレイヤー使用量 (Orders / Layers * 100) が現在のシステムの健全性を超えると、追加のエントリがブロックされます。
- 注文管理 – 開かれているすべてのレイヤーは、ATR ベースのストップロスおよびテイクプロフィットレベルとともにエントリー価格を保存します。完成した各キャンドルの高低範囲がチェックされ、保護レベルに達したために層を閉じる必要があるかどうかが決定されます。
- ヘッジ モード –
MultiPairTrading が無効になり、計算されたヘルス パーセンテージが HedgeLevel を下回ると、ストラテジーは現在の注文数を記録し、ヘッジ率の要件に達するまで反対側のレイヤーのオープンを開始します。ヘルスがしきい値を超えて回復すると、ヘッジは自動的に無効になります。
- 株式管理 – いくつかの保護は元のエキスパートアドバイザーを反映しています。
RiskLimit (初期資本からリスク制限を引いたもの) によって定義されるハードエクイティストップ。
- 利益目標は、初期資本に対する追加の相殺として表されます。
- すべてのポジションが正常にフラット化されるたびに、現在の残高に
CloseProfitBuffer が追加されるローリング「クローズエクイティ」レベル。
- 株式が保存された損益分岐点資本に達したときにすべての取引を終了するオプションの損益分岐点エグジット。
- 手動の「ハードクローズ」スイッチにより、即座にフラット位置に強制されます。
パラメーター
AllowLong / AllowShort – それぞれ長いエントリまたは短いエントリを有効にします。
MaxVolume – すべてのレイヤーに割り当てられたポジションの合計ボリューム。
Layers – 同時に開くことができるレイヤーの最大数。
CciLength / CciLevel – CCI フィルターの期間としきい値。
StopLossMultiple / TakeProfitMultiple – 各レイヤーの保護レベルを定義する ATR 乗数。
CloseProfitBuffer – ローリング株式至近目標をリサイクルする際に残高に利益が追加されます。 Also used when computing the break-even capital.
ManualCapital – すべてのリスク計算に使用される初期資本を上書きします (開始時にライブ ポートフォリオ残高を使用するには、ゼロに設定します)。
RiskLimit – 初期資本から許容される最大ドローダウン。
ProfitTarget – 到達すると取引を一時停止する追加的な利益目標。
MultiPairTrading – true の場合、ヘルスが制限を下回った場合でもヘッジは無効になります。
HedgeLevel / HedgeRatio – ヘッジを開始するヘルスの割合と、ヘッジモード中に必要な追加レイヤーの比率。
CloseAtBreakEven – Enables the break-even exit logic.
HardClose – true の間、直ちにフラット化を強制し、さらなる取引を一時停止します。
CandleType – インジケーターの評価とトレードの決定に使用されるローソク足シリーズ。
注意事項
- この戦略は市場注文が即座に約定することを前提としています。履歴データで実行する場合、実際の実行モデルは、StockSharp のバックテスト設定によって異なります。
- 株式と残高の情報は、接続されたポートフォリオ (
Portfolio.CurrentValue、Portfolio.CurrentBalance) から取得されます。戦略ポートフォリオが取引される証券と同期していることを確認します。
- ヘッジにより、同じ商品に対して追加の市場ポジションが開かれます。ヘッジが有効な場合、ブローカーまたはシミュレーターが反対のポジションを許可していることを確認します。
- 損益分岐点追跡では、「ClosePL」パラメータで動作した元の MetaTrader バージョンと同様に、
CloseProfitBuffer 値が再利用されます。
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "Risk Manager Layered" MetaTrader expert.
/// Uses CCI crossover for entry with position management. CCI above level -> sell,
/// CCI below negative level -> buy, with volume-based confirmation.
/// </summary>
public class LayeredRiskProtectorStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciLength;
private readonly StrategyParam<decimal> _cciLevel;
private CommodityChannelIndex _cci;
private decimal? _prevCci;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int CciLength
{
get => _cciLength.Value;
set => _cciLength.Value = value;
}
public decimal CciLevel
{
get => _cciLevel.Value;
set => _cciLevel.Value = value;
}
public LayeredRiskProtectorStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Primary candle series", "General");
_cciLength = Param(nameof(CciLength), 100)
.SetGreaterThanZero()
.SetDisplay("CCI Length", "CCI indicator period", "Indicators");
_cciLevel = Param(nameof(CciLevel), 150m)
.SetGreaterThanZero()
.SetDisplay("CCI Level", "CCI threshold for entries", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_cci = new CommodityChannelIndex { Length = CciLength };
_prevCci = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_cci, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _cci);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_cci.IsFormed)
{
_prevCci = cciValue;
return;
}
if (_prevCci is null)
{
_prevCci = cciValue;
return;
}
var volume = Volume;
if (volume <= 0)
volume = 1;
// CCI crosses below -level -> buy
var buyCross = _prevCci.Value >= -CciLevel && cciValue < -CciLevel;
// CCI crosses above +level -> sell
var sellCross = _prevCci.Value <= CciLevel && cciValue > CciLevel;
if (buyCross)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (sellCross)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
_prevCci = cciValue;
}
/// <inheritdoc />
protected override void OnReseted()
{
_cci = null;
_prevCci = null;
base.OnReseted();
}
}
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 CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class layered_risk_protector_strategy(Strategy):
def __init__(self):
super(layered_risk_protector_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._cci_length = self.Param("CciLength", 100)
self._cci_level = self.Param("CciLevel", 150.0)
self._prev_cci = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciLength(self):
return self._cci_length.Value
@CciLength.setter
def CciLength(self, value):
self._cci_length.Value = value
@property
def CciLevel(self):
return self._cci_level.Value
@CciLevel.setter
def CciLevel(self, value):
self._cci_level.Value = value
def OnReseted(self):
super(layered_risk_protector_strategy, self).OnReseted()
self._prev_cci = None
def OnStarted2(self, time):
super(layered_risk_protector_strategy, self).OnStarted2(time)
self._prev_cci = None
cci = CommodityChannelIndex()
cci.Length = self.CciLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(cci, self._process_candle).Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
cci_val = float(cci_value)
if self._prev_cci is None:
self._prev_cci = cci_val
return
cci_level = float(self.CciLevel)
# CCI crosses below -level -> buy
buy_cross = self._prev_cci >= -cci_level and cci_val < -cci_level
# CCI crosses above +level -> sell
sell_cross = self._prev_cci <= cci_level and cci_val > cci_level
if buy_cross:
if self.Position <= 0:
self.BuyMarket()
elif sell_cross:
if self.Position >= 0:
self.SellMarket()
self._prev_cci = cci_val
def CreateClone(self):
return layered_risk_protector_strategy()