GitHub で見る

ラヴィアオ戦略 (StockSharp)

概要

RAVIiAO 戦略 は、StockSharp の高レベル API 内で MetaTrader 4 エキスパート アドバイザー「RAVIiAO」を再現します。システム 新しいローソク足が閉じるのを待ち、ビル Williams の加速/減速 (AC) とともに RAVI オシレーターの傾きを評価します。 オシレーターを使用し、両方の指標がトレンドの方向に一致した場合、市場で即座にポジションをオープンします。ポートは オリジナルのパラメータセット - 移動平均期間、しきい値、ストップロス/テイクプロフィット距離、注文量 - トレーダーが利用できるようにする 手動による調整を行わずに従来の動作を再現します。

コアワークフロー

  1. ローソク足のサブスクリプション – この戦略は、構成可能な時間枠 (デフォルトでは 30 分のローソク足) をサブスクライブします。
  2. インジケーターの更新 – 完成したローソク足ごとに、RAVI オシレーターとフィードを構築するために 2 つの単純な移動平均を更新します。 同じローソク足を Awesome Oscillator + 5 期間平滑化ペアに変換して、AC 値を取得します。
  3. シグナル準備 – 最後に完成したローソク足は「バー 1」として保存され、以前の値は「バー 2」となり、 MetaTrader からの iCustom(...,1)iCustom(...,2) の呼び出し。
  4. エントリーの決定 – AC と RAVI の両方が以前の値を上回って増加し、 強気の環境 (AC[1] > AC[2] > 0RAVI[1] > RAVI[2] > Threshold)。ショートトレードではミラー条件を使用します。
  5. リスク管理 – 注文が実行されるとすぐに、戦略により静的なストップロスとテイクプロフィットのレベルが記録されます。 インストゥルメントポイント(つまり、StopLossPoints * PriceStep)。ローソク足は、高値/安値を使用してバー内突破が監視されます。
  6. 状態リセット – 保護レベルに達すると、ポジションは成行注文でクローズされ、内部バッファーがリセットされます。 次の機会のために。

取引ルール

  • 長いエントリ
    • 以前の AC 値が以前の AC 値より大きく、両方とも 0 より大きい。
    • 以前の RAVI 測定値がしきい値と以前の RAVI 値の両方を上回っています。
    • 信号の時点ではアクティブな位置はありません。
  • 短いエントリー
    • 以前の AC 値が以前の AC 値より小さく、両方ともゼロより小さい。
    • 以前の RAVI 測定値が負のしきい値を下回っており、以前の RAVI 値を下回っている。
    • 信号が発信されたときにアクティブな位置はありません。
  • ポジションエグジット
    • 静的なストップロスとテイクプロフィットのレベルは生のポイントで表され、商品 PriceStep を介して価格オフセットに変換されます。
    • 違反はローソク足の極端な値(ロングストップの場合は安値、ショートストップの場合は高値など)で検出され、市場を通じて即座にクローズされます。 MetaTraderの保護命令に倣う命令。

パラメーター

名前 説明
CandleType キャンドルのサブスクリプションに使用される時間枠 (デフォルトは 30 分)。
FastLength RAVI オシレーターで使用される高速移動平均の長さ。
SlowLength RAVI オシレーターで使用される低速移動平均の長さ。
Threshold トレンドの継続を検証するための最小絶対 RAVI パーセンテージ。
StopLossPoints インスツルメントポイントでのストップロス距離 (PriceStep を乗算)。
TakeProfitPoints 商品ポイントでのテイクプロフィット距離。
TradeVolume 各エントリーの成行注文量。

変換メモ

  • StockSharp ポートは、ローソク足 n での決定で AC[1] と 2 つの最新のインジケーター値を再利用するように保存します。 MetaTrader の RAVI[1] 値(つまり、前のバーの結果)。EA の「新しいバー」実行スタイルが維持されます。
  • AC は、Awesome Oscillator とその 5 期間の単純移動平均の差を通じて再構築され、MT4 と一致します。 計算チェーン。
  • ストップとターゲットは、保留中の保護注文を発行するのではなく、ローソク足の極値に対して評価されます。これはその効果を反映しています StockSharp の慣用的な実装を維持しながら、MetaTrader の組み込み SL/TP 処理を強化します。

使用のヒント

  • 選択した機器が正しい PriceStep を公開していることを確認してください。そうしないと、保護距離が MT4 のバージョンと一致しなくなります。
  • 戦略をさまざまな市場に適応させる場合は、ThresholdFastLength、および SlowLength パラメータを最適化します。 ボラティリティ特性。
  • この戦略と StockSharp のポートフォリオ レベルまたはコネクタ レベルの保護を組み合わせて、ライブ取引中の安全性をさらに高めます。
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Port of the MetaTrader 4 expert advisor "RAVIiAO" that combines the RAVI oscillator and the Acceleration/Deceleration oscillator.
/// </summary>
public class RaviIaoStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _threshold;
	private readonly StrategyParam<decimal> _stopLossPoints;
	private readonly StrategyParam<decimal> _takeProfitPoints;

	private SMA _aoAverage;

	private decimal? _prevRavi;
	private decimal? _prevPrevRavi;
	private decimal? _prevAc;
	private decimal? _prevPrevAc;

	/// <summary>
	/// Type of candles used for indicator calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Fast moving average length for the RAVI oscillator.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Slow moving average length for the RAVI oscillator.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Threshold for bullish or bearish confirmation of the RAVI oscillator (percentage value).
	/// </summary>
	public decimal Threshold
	{
		get => _threshold.Value;
		set => _threshold.Value = value;
	}

	/// <summary>
	/// Stop-loss distance in absolute price units.
	/// </summary>
	public decimal StopLossPoints
	{
		get => _stopLossPoints.Value;
		set => _stopLossPoints.Value = value;
	}

	/// <summary>
	/// Take-profit distance in absolute price units.
	/// </summary>
	public decimal TakeProfitPoints
	{
		get => _takeProfitPoints.Value;
		set => _takeProfitPoints.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="RaviIaoStrategy"/>.
	/// </summary>
	public RaviIaoStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(10).TimeFrame())
			.SetDisplay("Candle Type", "Time-frame for analysis", "General");

		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Fast SMA period inside RAVI", "RAVI");

		_slowLength = Param(nameof(SlowLength), 72)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow SMA period inside RAVI", "RAVI");

		_threshold = Param(nameof(Threshold), 0.3m)
			.SetDisplay("RAVI Threshold", "Minimum absolute RAVI value to confirm the trend", "Signals");

		_stopLossPoints = Param(nameof(StopLossPoints), 500m)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop-loss distance in price units", "Risk");

		_takeProfitPoints = Param(nameof(TakeProfitPoints), 500m)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take-profit distance in price units", "Risk");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevRavi = null;
		_prevPrevRavi = null;
		_prevAc = null;
		_prevPrevAc = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		var fastMa = new SMA { Length = FastLength };
		var slowMa = new SMA { Length = SlowLength };
		var ao = new AwesomeOscillator();
		_aoAverage = new SMA { Length = 5 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(new IIndicator[] { fastMa, slowMa, ao }, ProcessCandle)
			.Start();

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

		// Use StartProtection for SL/TP
		var tp = TakeProfitPoints > 0 ? new Unit(TakeProfitPoints, UnitTypes.Absolute) : null;
		var sl = StopLossPoints > 0 ? new Unit(StopLossPoints, UnitTypes.Absolute) : null;
		StartProtection(tp, sl);

		base.OnStarted2(time);
	}

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

		var fastVal = values[0];
		var slowVal = values[1];
		var aoVal = values[2];

		if (fastVal.IsEmpty || slowVal.IsEmpty || aoVal.IsEmpty)
			return;

		var fastValue = fastVal.ToDecimal();
		var slowValue = slowVal.ToDecimal();
		var aoValue = aoVal.ToDecimal();

		// Compute AC = AO - SMA(AO)
		var aoAvgResult = _aoAverage.Process(aoVal);
		if (aoAvgResult.IsEmpty)
			return;

		var aoAvgValue = aoAvgResult.ToDecimal();
		var ac = aoValue - aoAvgValue;

		if (slowValue == 0m)
		{
			UpdateHistory(null, ac);
			return;
		}

		var ravi = 100m * (fastValue - slowValue) / slowValue;

		if (_prevRavi is decimal prevRavi &&
			_prevPrevRavi is decimal prevPrevRavi &&
			_prevAc is decimal prevAc &&
			_prevPrevAc is decimal prevPrevAc &&
			Position == 0 &&
			IsFormedAndOnlineAndAllowTrading())
		{
			var bullish = prevAc > prevPrevAc && prevPrevAc > 0m && prevRavi > prevPrevRavi && prevRavi > Threshold;
			var bearish = prevAc < prevPrevAc && prevPrevAc < 0m && prevRavi < prevPrevRavi && prevRavi < -Threshold;

			if (bullish)
			{
				BuyMarket(Volume);
			}
			else if (bearish)
			{
				SellMarket(Volume);
			}
		}

		UpdateHistory(ravi, ac);
	}

	private void UpdateHistory(decimal? ravi, decimal ac)
	{
		_prevPrevRavi = _prevRavi;
		_prevRavi = ravi;
		_prevPrevAc = _prevAc;
		_prevAc = ac;
	}
}