GitHub で見る
CorrTime戦略
CorrTime戦略は、同名のMetaTraderエキスパートアドバイザーを再現する単一シンボルのシステムです。終値とその時系列順序の相関を分析し、モメンタムの加速または反転を検出します。アルゴリズムは確定済みローソク足で動作し、3つの確認層を組み合わせます。
- ボラティリティフィルター: ボリンジャーバンド幅は、許容される活動量の設定範囲内にある必要があります。これにより、横ばい局面と過度に荒い局面を避けます。
- トレンド強度フィルター: 相関シグナル評価前に、Average Directional Index(ADX)がしきい値を上回り続ける必要があります。
- 相関トリガー: Pearson、Spearman、Kendall、Fechnerの相関推定器が、価格が時間とどれだけ密接に進むかを測定します。係数の急変が取引判断を生成します。
元のロボットはH1時間軸のEURUSD向けに設計されていましたが、StockSharp版はすべてのパラメーターを設定可能にしています。既定設定は元に忠実です(1時間足、Fechner相関、逆張りモード)。
取引ワークフロー
- 選択した
CandleTypeを購読し、確定バーを待ちます。
- 新しいローソク足でボリンジャーバンドとADX値を更新します。
- 次の場合、バーを拒否します。
- pipsへ変換したボリンジャースプレッドが
[BollingerSpreadMin, BollingerSpreadMax]の外にある。
- ADXが
AdxLevelを下回る。
- ローソク足が
[EntryHour, EntryHour + OpenHours]取引時間窓の外で始まる(深夜跨ぎ対応)。
- 終値のローリング履歴を構築し、
CorrelationRangeTrendとCorrelationRangeReverseのルックバックで相関係数を計算します。コードは直近3つの相関値を再計算し、元のincludeファイルがバッファーで行っていたのと同様に、制限の実際のクロスを検出します。
- トレンドフォロートリガー(
TradeModeがTrendFollowまたはBothの場合):
- ロング: 相関が
CorrLimitTrendBuyを下回っており、前バーでも下回ったまま、最新バーでしきい値を上抜ける。
- ショート: 相関が
-CorrLimitTrendSellを上回っており、前バーでも上回ったまま、最新バーで-CorrLimitTrendSellを下抜ける。
- 反転トリガー(
TradeModeがReverseまたはBothの場合):
- ロング: 相関が
-CorrLimitReverseBuyを下回っており、前バーでも下回ったまま、最新バーで-CorrLimitReverseBuyを上回る。
- ショート: 相関が
CorrLimitReverseSellを上回っており、前バーでも上回ったまま、最新バーでCorrLimitReverseSellを下回る。
- 両方向が同時に発火した場合、MetaTraderの動作を反映してシグナルは互いに打ち消します。
CloseTradeOnOppositeSignalが有効な場合、新しいポジションを開く前に反対ポジションを即座に閉じます。
- エントリーは
Volumeプロパティでサイズ設定され、MaxOpenOrdersを尊重するため、ネットエクスポージャーはどちらの方向でもVolume * MaxOpenOrdersを超えません。
- リスクは
StartProtectionで制御されます。ストップロスとテイクプロフィットはpipベース距離を使い、トレーリングフラグが有効な場合は同じストップ距離を再利用します。
パラメーター
| パラメーター |
説明 |
CandleType |
ローソク足生成とすべての指標供給に使う時間軸。 |
CloseTradeOnOppositeSignal |
次のシグナルが反対方向を示すとき、オープンポジションを閉じます。 |
EntryHour, OpenHours |
日次取引時間窓を定義します。OpenHours = 0は窓を1時間だけ開いたままにします。 |
BollingerPeriod, BollingerDeviation |
終値に適用する標準ボリンジャーバンド設定。 |
BollingerSpreadMin, BollingerSpreadMax |
ボリンジャーチャンネルに必要な最小/最大幅(pips)。 |
AdxPeriod, AdxLevel |
Average Directional Index設定と必要な最小トレンド強度。 |
TradeMode |
トレンドフォロー、反転、または組み合わせ評価から選択します。 |
CorrelationRangeTrend, CorrelationRangeReverse |
相関計算のルックバック長。 |
CorrelationType |
Pearson、Spearman、Kendall、Fechnerの相関式を選択します。 |
CorrLimitTrendBuy, CorrLimitTrendSell |
有効なトレンドフォローブレイクアウトを定義するしきい値。 |
CorrLimitReverseBuy, CorrLimitReverseSell |
有効な反転ブレイクアウトを定義するしきい値。 |
TakeProfitPips, StopLossPips, TrailingStopPips |
pipsで表し、銘柄pipサイズで価格単位へ変換するリスクパラメーター。 |
MaxOpenOrders |
集約エントリー数の上限(片側上限はVolume * MaxOpenOrders)。 |
実用メモ
- pipサイズは銘柄の小数桁から推定されます(小数5桁または3桁は10倍乗数に対応)。MetaTraderのポイント処理を模倣します。非FX資産ではしきい値を調整してください。
- 相関バッファーはクロスを評価するために少なくとも
lookback + 2本の確定ローソク足を必要とします。ウォームアップ中、戦略は待機します。
- すべてのロジックが確定ローソク足で実行されるため、戦略はバー内ノイズに強く、
iTimeとiCloseスナップショットに依存した元の動作を反映します。
- 複数インスタンスを展開する場合は、ポートフォリオレベルのリスク制御と組み合わせてください。元のロボットもシンボル全体の合計注文数を制限していました。
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// CorrTime strategy: Bollinger Bands mean reversion.
/// Buys when close drops below lower BB.
/// Sells when close rises above upper BB.
/// </summary>
public class CorrTimeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bbWidth;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int BbPeriod
{
get => _bbPeriod.Value;
set => _bbPeriod.Value = value;
}
public decimal BbWidth
{
get => _bbWidth.Value;
set => _bbWidth.Value = value;
}
public CorrTimeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bbWidth = Param(nameof(BbWidth), 2m)
.SetDisplay("BB Width", "Bollinger Bands width", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands { Length = BbPeriod, Width = BbWidth };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bb, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bb);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bbVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var bbv = (BollingerBandsValue)bbVal;
if (bbv.UpBand is not decimal upper ||
bbv.LowBand is not decimal lower)
return;
var close = candle.ClosePrice;
if (close < lower && Position <= 0)
BuyMarket();
else if (close > upper && Position >= 0)
SellMarket();
}
}
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 BollingerBands
from StockSharp.Algo.Strategies import Strategy
class corr_time_strategy(Strategy):
"""
Bollinger Bands mean reversion strategy.
Buys when close drops below lower BB, sells when close rises above upper BB.
"""
def __init__(self):
super(corr_time_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._bb_period = self.Param("BbPeriod", 20) \
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._bb_width = self.Param("BbWidth", 2.0) \
.SetDisplay("BB Width", "Bollinger Bands width", "Indicators")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(corr_time_strategy, self).OnStarted2(time)
bb = BollingerBands()
bb.Length = self._bb_period.Value
bb.Width = self._bb_width.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(bb, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bb)
self.DrawOwnTrades(area)
def on_process(self, candle, bb_val):
if candle.State != CandleStates.Finished:
return
upper = bb_val.UpBand
lower = bb_val.LowBand
if upper is None or lower is None:
return
close = float(candle.ClosePrice)
upper = float(upper)
lower = float(lower)
if close < lower and self.Position <= 0:
self.BuyMarket()
elif close > upper and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return corr_time_strategy()