GitHub で見る

会議のライン Stochastic 戦略

概要

ミーティングライン Stochastic 戦略 は、MetaTrader のエキスパート Expert_AML_Stoch の StockSharp の実装です。これは、強気/弱気ミーティングラインのローソク足反転パターンと、Stochastic オシレーターの %D 信号ラインからの確認を組み合わせたものです。この戦略は、追加のモメンタム確認を伴うパターン認識へのルールベースのアプローチを必要とする裁量トレーダー向けに設計されています。高レベルの StockSharp API を使用することで、コードは簡潔かつテスト可能であり、ポートフォリオ管理やさらなる自動化のために簡単に拡張できます。

取引ロジック

  1. ローソク足パターン フィルター

    • この戦略は、最後の 2 つの完了したキャンドルを継続的に評価して、ミーティング ラインのフォーメーションを検出します。
    • 強気のセットアップには、終値が前の終値の 10% 以内にある長い黒のローソク足に続いて長い白のローソク足が必要です。
    • 弱気のセットアップには、同じ10%に近い位置にある長い白いローソク足に続いて長い黒いローソク足が必要です。
    • ローソク足の平均実体サイズは、弱い実体を除外するために、構成可能な単純な移動平均を使用して計算されます。
  2. Stochastic 確認

    • Stochastic オシレーターの %D 信号ラインはローソク足信号を確認する必要があります。
    • 強気のエントリーでは、%D が設定可能な売られすぎしきい値 (デフォルトは 30) を下回っていることが要求されます。
    • 弱気のエントリーでは、%D が設定可能な買われすぎしきい値 (デフォルト 70) を超える必要があります。
  3. 退出ルール

    • %D が下側出口レベル (デフォルト 20) または上側出口レベル (デフォルト 80) のいずれかを上方に通過すると、ショート ポジションがクローズされます。
    • %D が同じレベルを下方にクロスすると、ロング ポジションがクローズされます。
    • 反転注文は、既存のエクスポージャーを自動的にクローズし、反対方向に新しいポジションをオープンします。
  4. ボリュームの処理

    • この戦略は、それが正の場合は基本の Volume プロパティを使用します。それ以外の場合は、MetaTrader の固定ロットの動作との互換性を保つために、デフォルトで単一ロットになります。

パラメーター

名前 説明 デフォルト 注意事項
CandleType 分析に使用される主なローソク足シリーズ。 15分の時間枠 StockSharp でサポートされているあらゆる DataType を受け入れます。
StochasticLength 生の %K 計算のルックバック期間。 3 MetaTrader %K period をミラーリングします。
StochasticSmoothing %K (MetaTrader slowing) に適用される平滑化。 25 オシレーターの内部スムージングの長さを設定します。
StochasticSignal %D 信号線の平滑化期間。 36 MetaTrader %D period をミラーリングします。
BodyAveragePeriod キャンドル本体のサイズを平均するために使用されるキャンドルの数。 3 会議のラインを発見するときにマイナーボディを除外します。
LongEntryLevel 強気のエントリーを可能にする最大 %D 値。 30 売られ過ぎのしきい値に相当します。
ShortEntryLevel 弱気エントリーに必要な最小 %D 値。 70 買われすぎのしきい値に相当します。
ExitLowerLevel 上向きクロスでエグジットをトリガーする下限境界。 20 長期および短期の両方の終了決定に使用されます。
ExitUpperLevel 下向きのクロスでエグジットをトリガーする上限。 80 長期および短期の両方の終了決定に使用されます。

すべてのパラメータは StrategyParam<T> を通じて公開され、StockSharp デザイナーで直接、またはプログラムで最適化できます。

信号の生成

  • ロングエントリー: 強気のミーティングライン + %D が LongEntryLevel を下回っており、既存のロングエクスポージャーはありません (ショートは反転されています)。
  • ショートエントリー: 弱気のミーティングライン + %D が ShortEntryLevel を上回っており、既存のショートエクスポージャーはありません (ロングは反転されています)。
  • ロングイグジット: %D は ExitUpperLevel または ExitLowerLevel を下回ります。
  • ショート終了: %D が ExitLowerLevel または ExitUpperLevel を超えています。

実装メモ

  • インジケーター データは BindEx を介して処理され、手動によるインジケーター収集管理を回避します。
  • ローソク足の実体の平均化では、DecimalIndicatorValue を通じて絶対実体サイズが供給された SimpleMovingAverage を使用し、MetaTrader ヘルパー AvgBody と一致します。
  • コード内のすべてのコメントは英語で書かれており、インデントはプロジェクト ガイドラインに従ってタブ文字に依存しています。
  • この戦略は、チャート領域が利用可能なときにローソク足と確率オシレーターを自動的に描画し、ライブ監視を簡素化します。

使用のヒント

  1. 最適化: 公開されたパラメータをウォークフォワード テストに使用して、取引商品に合わせてしきい値を調整します。
  2. リスク管理: StockSharp に組み込まれた StartProtection または運用環境の導入のための外部のポートフォリオ レベルのリスク制御を使用して戦略を階層化します。
  3. データ品質: ミーティング ライン パターンは、正確な始値/終値の影響を受けます。フィードの調整と非流動性セッションのフィルタリングを保証します。
  4. タイムフレーム: デフォルトは 15 分ですが、CandleType を変更することで日中または日次データを使用できます。

この戦略は、ローソク足のフォーメーションに依存しているが誤検知を減らすためにオシレーターの確認を必要とするトレーダーに規律あるアプローチを提供します。

namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Meeting Lines + Stochastic strategy.
/// Buys on bullish meeting lines with low stochastic, sells on bearish meeting lines with high stochastic.
/// </summary>
public class MeetingLinesStochasticStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _stochPeriod;
	private readonly StrategyParam<decimal> _stochLow;
	private readonly StrategyParam<decimal> _stochHigh;

	private ICandleMessage _prevCandle;
	private ICandleMessage _prevPrevCandle;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int StochPeriod { get => _stochPeriod.Value; set => _stochPeriod.Value = value; }
	public decimal StochLow { get => _stochLow.Value; set => _stochLow.Value = value; }
	public decimal StochHigh { get => _stochHigh.Value; set => _stochHigh.Value = value; }

	public MeetingLinesStochasticStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_stochPeriod = Param(nameof(StochPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Stochastic Period", "Stochastic K period", "Indicators");
		_stochLow = Param(nameof(StochLow), 30m)
			.SetDisplay("Stoch Low", "Stochastic oversold level", "Signals");
		_stochHigh = Param(nameof(StochHigh), 70m)
			.SetDisplay("Stoch High", "Stochastic overbought level", "Signals");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		_prevPrevCandle = null;
		var stoch = new StochasticOscillator { K = { Length = StochPeriod }, D = { Length = 3 } };
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(stoch, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var stochTyped = stochValue as StochasticOscillatorValue;
		if (stochTyped?.K is not decimal kValue) { UpdateState(candle); return; }

		if (_prevCandle != null && _prevPrevCandle != null)
		{
			var avgBody = (Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice) +
						   Math.Abs(_prevPrevCandle.ClosePrice - _prevPrevCandle.OpenPrice)) / 2m;

			if (avgBody > 0)
			{
				// Bullish meeting lines: prev bearish, current bullish, closes near
				var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice &&
								  (_prevCandle.OpenPrice - _prevCandle.ClosePrice) > avgBody * 0.5m;
				var currBullish = candle.ClosePrice > candle.OpenPrice &&
								  (candle.ClosePrice - candle.OpenPrice) > avgBody * 0.5m;
				var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;

				if (prevBearish && currBullish && closesNear && kValue < StochLow && Position <= 0)
					BuyMarket();

				// Bearish meeting lines: prev bullish, current bearish, closes near
				var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice &&
								  (_prevCandle.ClosePrice - _prevCandle.OpenPrice) > avgBody * 0.5m;
				var currBearish = candle.OpenPrice > candle.ClosePrice &&
								  (candle.OpenPrice - candle.ClosePrice) > avgBody * 0.5m;
				var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;

				if (prevBullish && currBearish && closesNear2 && kValue > StochHigh && Position >= 0)
					SellMarket();
			}
		}

		UpdateState(candle);
	}

	private void UpdateState(ICandleMessage candle)
	{
		_prevPrevCandle = _prevCandle;
		_prevCandle = candle;
	}
}