GitHub で見る

VR BUCH 移動平均戦略

概要

VR BUCH 移動平均戦略はMetaTrader エキスパートアドバイザー VR---BUCH の直接ポートです。2つの設定可能な移動平均とキャンドル価格フィルターを使用してトレンド反転を取引します。StockSharpバージョンは元のシグナルフローを維持します:反対のセットアップが現れると戦略はオープンポジションをクローズし、以前のエクスポージャーが完全にクローズされた後にのみ新しいポジションを開きます。

実装はStockSharpの高レベルキャンドルサブスクリプション、ネイティブ移動平均インジケーター、リアルタイム注文ヘルパーに依存しています。すべてのインジケーター値は完成したキャンドルで処理され、戦略はMetaTraderのシフトパラメーターを再現する小さなリングバッファーを除いて手動の履歴バッファーを避けます。

取引ロジック

  1. インジケーター計算
    • 選択したキャンドルタイプで高速移動平均と低速移動平均が計算されます。
    • 各移動平均は異なる価格ソースと平滑化メソッド(単純、指数、平滑、加重)を使用できます。
    • オプションの水平シフトは過去のキャンドルの値を参照してMetaTraderのma_shiftパラメーターを再現します。
  2. シグナル検出
    • シフトした高速MAがシフトした低速MAより上かつ選択した確認価格が高速MAより上のときに買いセットアップが発生します。
    • シフトした高速MAがシフトした低速MAより下かつ確認価格が高速MAより下のときに売りセットアップが発生します。
  3. ポジション管理
    • ポジションが既に開いている場合、反対のシグナルは最初にフラットクローズをトリガーします。新しいエントリーはネットポジションがゼロに戻ったときのみ後続のシグナルで評価されます。
    • ポジションがない場合、戦略はアクティブなシグナルの方向に設定されたボリュームで成行注文を提出します。

デフォルトではストップロスまたはテイクプロフィットレベルは含まれていません。ユーザーは必要に応じてStockSharpの保護ブロック(StartProtection)または外部リスクマネージャーと戦略を組み合わせることができます。

パラメーター

パラメーター 説明
Fast Period 高速移動平均の長さ。
Fast Shift 高速MA値を過去にシフトするために使用されるキャンドルの数。
Fast Price 高速MAに使用されるキャンドル価格コンポーネント(クローズ、オープン、ハイ、ロー、メジアン、典型値、加重)。
Fast Method 高速MAの平滑化メソッド(単純、指数、平滑、加重)。
Slow Period 低速移動平均の長さ。
Slow Shift 低速MA値をシフトするために使用されるキャンドルの数。
Slow Price 低速MAのキャンドル価格コンポーネント。
Slow Method 低速MAの平滑化メソッド。
Signal Price エントリーを確認するために使用されるキャンドル価格(デフォルトはクローズ)。
Candle Type 計算に使用される時間軸またはカスタムキャンドルタイプ。
Volume 新しいトレードの注文ボリューム。

使用上の注意

  • シグナルはバー内のノイズを避けるために完成したキャンドルでのみ評価されます。
  • 戦略は取引コネクターが両方の移動平均とそのシフトバッファーをウォームアップするために十分な履歴データを提供することを期待します。
  • 加重価格はMetaTraderのPRICE_WEIGHTEDオプションに対応する式((High + Low + 2 * Close) / 4)を使用します。
  • クラス名とネームスペースはStockSharpプロジェクトの規約に従い、AlgoTradingソリューション内でシームレスにコンパイルできます。

実行方法

  1. 戦略をStockSharpの戦略コンテナーまたはサンプルランナーに配置します。
  2. 希望の証券、時間軸(Candle Type)、注文ボリュームを設定します。
  3. 必要に応じて移動平均設定を元のMetaTraderテンプレートに合わせて調整します。
  4. 戦略を開始します。キャンドルを購読し、チャートにインジケーターを描画し(利用可能な場合)、説明されたロジックに基づいて成行注文を配置します。

ポートフォリオまたは複数シンボルの使用には、銘柄ごとに戦略インスタンスを複製し、専用の証券を割り当てます。

using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// VR BUCH strategy. Uses Highest/Lowest channel breakout.
/// </summary>
public class VrBuchStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;

	private decimal? _prevHigh;
	private decimal? _prevLow;

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

	public int Period
	{
		get => _period.Value;
		set => _period.Value = value;
	}

	public VrBuchStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_period = Param(nameof(Period), 14)
			.SetGreaterThanZero()
			.SetDisplay("Period", "Channel period", "Indicators");
	}

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

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevHigh = null;
		_prevLow = null;
		var highest = new Highest { Length = Period };
		var lowest = new Lowest { Length = Period };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(highest, lowest, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevHigh = high; _prevLow = low; return; }
		if (_prevHigh == null || _prevLow == null) { _prevHigh = high; _prevLow = low; return; }
		var close = candle.ClosePrice;
		if (close > _prevHigh.Value && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (close < _prevLow.Value && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevHigh = high; _prevLow = low;
	}
}