GitHub で見る

OHLC Stochastic戦略

OHLCローソク足でクラシックな%K/%D Stochasticオシレーターを使用するモメンタムフォロー戦略。 アルゴリズムは売られ過ぎ/買われ過ぎゾーンでのクロスオーバーに反応し、価格ステップで測定された設定可能なトレーリングストップでオープントレードを保護します。

詳細

  • コアアイデア: Stochastic %Kが極端なレベルで%Dをクロスするときのモメンタムの転換を活用する。
  • エントリー条件:
    • ロング:
      • %Kが%Dを上方クロスし、少なくとも1つのラインがLevelDownしきい値を下回る。
      • ショートポジションが存在する場合、クローズしてロングに反転。
    • ショート:
      • %Kが%Dを下方クロスし、少なくとも1つのラインがLevelUpしきい値を上回る。
      • ロングポジションが存在する場合、クローズしてショートに反転。
  • エグジット条件:
    • トレーリングストップがヒットする(TrailingStopSteps距離とTrailingStepSteps改善要件に基づく)。
    • 反対のエントリーシグナルが現れ、リバーサルをトリガーする。
  • トレーリングロジック:
    • 距離とステップはpips/ステップを絶対価格に変換するためにインストゥルメントのPriceStepで乗算されます。
    • ストップはエントリー価格からTrailingStopSteps + TrailingStepStepsを超えてトレードが移動した後にのみ前進します。
    • ロングとショートサイドのトレーリングロジックを分離。
  • インジケーター:
  • ロング/ショート: 両方。
  • ストップ: トレーリングストップのみ(固定SL/TP注文なし)。
  • ポジションサイジング: 戦略のVolumeパラメータを使用;リバーサルは方向を変えるためにVolume + |Position|を送信。
  • デフォルト値:
    • CandleType = TimeSpan.FromHours(12).TimeFrame()
    • KPeriod = 5
    • DPeriod = 3
    • Slowing = 3
    • LevelUp = 70
    • LevelDown = 30
    • TrailingStopSteps = 5 (価格ステップ)
    • TrailingStepSteps = 2 (価格ステップ)
  • 可視化:
    • チャートが利用可能な場合、OHLCローソク足、Stochasticインジケーター、トレードマーカーを描画します。

使用上の注意事項

  1. 戦略を開始する前に基礎となるインストゥルメントと時間軸を設定してください。
  2. 実際のpip距離を反映するためにインストゥルメントのティックサイズに応じてTrailingStopStepsを調整してください。
  3. 戦略はStartProtection()を呼び出し、追加のリスクルールを外部でアタッチできます。
  4. Stochasticのリバーサルが価格をリードするトレンドレジームで最もよく機能します。
  5. イントラデイ商品では、早期エグジットを避けるために低い時間軸でトレーリング距離を縮小する必要がある場合があります。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

public class OhlcStochasticStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private decimal? _prevRsi;

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

	public OhlcStochasticStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero().SetDisplay("RSI Period", "RSI lookback", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = null;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevRsi = rsiVal; return; }
		if (_prevRsi == null) { _prevRsi = rsiVal; return; }
		if (_prevRsi.Value < 30m && rsiVal >= 30m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevRsi.Value > 70m && rsiVal <= 70m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevRsi = rsiVal;
	}
}