GitHub で見る

Avalanche AV ストラテジー

Avalanche AV は等しい確率でロングとショートのエントリーを交互に行うランダム化されたマーティンゲールストラテジーです。設定可能な数の完成したローソク足の後にのみ取引が開かれ、各ポジションは pip で定義された固定のストップロスとテイクプロフィットのレベルを継承します。取引が損失でクローズすると、回復を追求するためにポジションサイズにマーティンゲール係数を掛け、利益を上げた取引はアカウント残高が新しい資産の高値を記録すると初期ボリュームにサイズをリセットします。ストラテジーはまたアカウント残高のパーセンテージとして最大フローティングドローダウンを実施し、この閾値を超えるポジションをクローズします。

元の MQL バージョンはティックで取引を開いていました。StockSharp のポートは同じ確率的な動作を維持しますが、ローソク足の更新で動作し、バーデータでのバックテストとライブトレーディングの両方に適しています。

トレーディングルール

  • 決定間隔: 新しいシグナルを評価する前に、指定された数の完成したローソク足を待ちます。ポジションがまだ開いている場合、間隔はカウントを続けますが、新しい取引は行いません。
  • エントリー方向: 乱数を生成します。16384 より大きい値はロングエントリーをトリガーし、そうでなければショートエントリーになります。ポジションはアクティブな取引がない場合にのみ開かれます。
  • 注文サイズ: InitialVolume から始めます。各負け取引の後、次の注文サイズは PreviousVolume * MartingaleMultiplier(インストゥルメントのボリュームステップに正規化)になります。実現残高が新しい高値を記録すると勝ち取引はサイズを InitialVolume にリセットします。そうでなければマーティンゲールの拡張が続きます。
  • ストップとターゲット: ストップロスとテイクプロフィットはエントリー価格から pip で計算されます。1 pip はインストゥルメントの価格ステップに等しい。
  • フローティングドローダウン: ポジションがアクティブな間、ストラテジーは未実現 PnL を監視します。損失が実現アカウント残高(初期残高 + 実現 PnL)の MaxDrawdownPercent を超えると、ポジションは即座にクローズされます。

パラメーター

パラメーター デフォルト 説明
InitialVolume 0.1 初期取引ボリューム。
StopLossPips 15 pip でのストップ距離(0 でストップを無効化)。
TakeProfitPips 30 pip でのテイクプロフィット距離(0 でターゲットを無効化)。
MaxDrawdownPercent 75 残高のパーセントとして許容される最大フローティング損失。
MartingaleMultiplier 1.6 損失後に適用されるボリューム乗数。
DecisionInterval 9 新しい取引決定の間の完成したローソク足の数。
CandleType 1分足の時間軸 ストラテジーを駆動するローソク足タイプ。

注意事項

  • ボリュームはインストゥルメントの VolumeStepMinVolumeMaxVolume の制限に自動的に正規化されます。正規化が失敗した場合、サイズは初期ボリュームにリセットされます。
  • ストップロスとテイクプロフィットのレベルはインストゥルメントの PriceStep を 1 pip として依存します。エキゾチックなシンボルのステップを確認してください。
  • ドローダウン保護は PriceStepStepPrice の両方が定義されている必要があります。そうでなければ、セーフティチェックはスキップされます。
  • ストラテジーはランダム性に依存するため、乱数シードが外部で制御されない限り、同一の市場データでも実行間で結果が異なります。
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>
/// Avalanche strategy using channel breakout with Highest/Lowest.
/// </summary>
public class AvalancheAvStrategy : 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 AvalancheAvStrategy()
	{
		_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);
			DrawIndicator(area, highest);
			DrawIndicator(area, lowest);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevHigh = high;
			_prevLow = low;
			return;
		}

		var close = candle.ClosePrice;

		if (_prevHigh == null || _prevLow == null)
		{
			_prevHigh = high;
			_prevLow = low;
			return;
		}

		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;
	}
}