GitHub で見る

VR スマートグリッド Lite 平均化戦略

概要

VR スマート グリッド ライト平均化戦略は、オリジナルの MetaTrader 5 エキスパート アドバイザーに準拠したグリッド平均化システムです。このアルゴリズムは、価格がポジションに逆らって動くたびに、最新の強気または弱気のローソク足の方向に成行注文を開き、マーチンゲール スタイルのはしごを構築します。距離、ボリューム、終了ロジックは、元の MQL 実装に一致するように調整できます。

取引ロジック

  • 完了したキャンドルごとに、戦略はその方向をチェックします。
    • 現在の価格が既存の最低購入エントリーより少なくとも Order Step (pips) 低い場合、強気のローソク足で新しい買い注文が可能になります。
    • 弱気のローソク足では、現在の価格が既存の最も高い売りエントリーを少なくとも Order Step (pips) 上回っている場合、新しい売り注文が許可されます。
  • それぞれの側の最初のオーダーでは Start Volume が使用されます。注文を追加するたびに、その側の最も遠い注文の量が 2 倍になりますが、Max Volume によって絶対サイズが制限されます。
  • サイドに 1 つのポジションのみが存在する場合、価格が Take Profit (pips) 距離に達すると取引は終了します。
  • 2 つ以上のポジションの場合、決済ロジックは選択した Close Mode によって異なります。
    • 平均 – 価格が加重平均に Minimal Profit (pips) を加えた値に達すると、最高値と最低値の注文がクローズされます。
    • PartialClose – 価格が混合ターゲットに達したときに、最低注文を完全にクローズし、最高注文を Start Volume だけ減らします。

リスク管理

  • 拒否を避けるために、取引高はブローカーの MinVolumeMaxVolume、および StepVolume に合わせて調整されます。
  • 組み込みの StartProtection() 呼び出しにより、取引前に StockSharp アカウント保護が有効化されます。

パラメーター

名前 説明
Take Profit (pips) 単一のオープンポジションのターゲット距離。
Start Volume 各方向の初期注文のボリューム。
Max Volume 注文ごとに許可される最大量 (0 を使用すると制限が無効になります)。
Close Mode 平均決済か部分決済かを選択します。
Order Step (pips) 新しい注文を追加する前の逆方向の動きを最小限に抑えます。
Minimal Profit (pips) 平均化出口に追加の利益バッファーが追加されました。
Candle Type 信号生成に使用されるキャンドルシリーズ。

注意事項

  • この戦略では成行注文のみを使用します。元の EA からの未決注文は、各ローソク足の条件を評価することによってエミュレートされます。
  • この実装では、部分的なクローズや選択的な終了など、MetaTrader のチケットベースの管理を模倣するために注文ごとの状態が維持されます。
  • 一貫した動作を実現するために、ローソク足のタイプとシンボルのピップ サイズを、MQL スクリプトで使用されるタイムフレームと一致するように設定します。
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// VR Smart Grid Lite Averaging: grid with averaging approach using Bollinger Bands.
/// Buys near lower band, sells near upper band.
/// </summary>
public class VrSmartGridLiteAveragingStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _bbPeriod;

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

	public int BbPeriod
	{
		get => _bbPeriod.Value;
		set => _bbPeriod.Value = value;
	}

	public VrSmartGridLiteAveragingStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_bbPeriod = Param(nameof(BbPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var bb = new BollingerBands { Length = BbPeriod };

		decimal? prevClose = null;
		decimal? prevMid = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(bb, (candle, 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;
				var mid = (upper + lower) / 2m;

				if (prevClose.HasValue && prevMid.HasValue)
				{
					var crossBelow = prevClose.Value >= prevMid.Value && close < mid;
					var crossAbove = prevClose.Value <= prevMid.Value && close > mid;

					if (crossBelow && Position <= 0)
						BuyMarket();
					else if (crossAbove && Position >= 0)
						SellMarket();
				}

				prevClose = close;
				prevMid = mid;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, bb);
			DrawOwnTrades(area);
		}
	}
}