GitHub で見る

トレンドを取得する Stochastic 戦略

この戦略は、MetaTrader 4 エキスパート アドバイザー Get Trend.mq4 の StockSharp の高レベル ポートです。 M15 チャートを評価します。 エントリを入力し、上半期のより広範なトレンドを検証し、2 つの平滑化移動平均と 2 つの確率的移動平均に依存します。 長期トレンド近くの平均回帰ブレイクアウトを検出するオシレーター。実装は元の資金管理を維持します 価格ポイントで表される固定のテイクプロフィット、ストップロス、トレーリングストップの距離に基づくルール。

取引ロジック

  1. 指標とデータ
    • M15 ローソク足は、期間 M15MaPeriod と 2 つの確率オシレーターを持つ平滑化移動平均 (SMMA、中央価格) を供給します。
    • H1 ローソク足は、期間 H1MaPeriod の別の SMMA (中央価格) をフィードします。
    • 高速確率論 (FastStochasticPeriod, 3, 3) は、%K ラインとその前の値を提供します。低速確率論 (SlowStochasticPeriod, 3, 3) は %D 信号ラインを供給します。
  2. 長いセットアップ
    • 現在の M15 の終値は SMMA を下回っており、H1 の終値は SMMA を下回っています。
    • M15 SMMA と終値の間の距離は ThresholdPoints の価格ステップ以内です。
    • 両方の確率線は 20 を下回っています。最後のローソク足の間に、速い線が遅い線の上を横切ります (fast > slow、前の速い値は slow を下回っていました)。
    • ショート ポジションが存在する場合、この戦略はまずそれをフラットにするのに十分な量を購入し、次に TradeVolume で新しいロングをオープンします。
  3. 短いセットアップ は、長いロジックを反映しています。
    • どちらの終値も SMMA の上にあり、距離は ThresholdPoints 以内、確率値は 80 を超え、速い ラインがスローラインを下回ります。この戦略は売り、必要に応じて既存のロングを決済します。
  4. リスク管理
    • すべてのエントリーの後、保護注文は StopLossPointsTakeProfitPoints (絶対価格に換算) で発注されます。 距離は商品の価格ステップを使用します)。
    • トレーリングストップは、トレードが少なくとも TrailingStopPoints ポイントを獲得すると、ストップロス注文を再調整します。新しい停留所は、 現在の終値からロング/ショートのトレーリング距離を引いた/プラスした位置に位置します。
    • ポジションがフラットに戻ると、すべての保護命令が解除されます。

オリジナルの EA との違い

  • MetaTrader の SMMA は 8 バーのインジケーター シフトを使用します。 StockSharp インジケーターは直接シフト設定を公開しません。港 代わりに、最新の終了値を評価します。これにより、追加のカスタム バッファーを回避しながら、クロスオーバーのタイミングが維持されます。
  • 元の EA は、トレーリングに MQL の買値/売値を使用していました。ポートは、トレーリングをトリガーした完成したローソク足のクローズを使用します。 これは、高レベルの API で利用可能な最も近い類似物です。
  • 資金管理は、代わりに StockSharp の注文登録ヘルパー (BuyMarketSellMarketSellStop など) に依存します。 OrderSendOrderModify

パラメーター

グループ 名前 説明 デフォルト
データ M15 Candle Type 主な計算に使用されるローソク足の種類/時間枠。 M15 の時間枠
データ H1 Candle Type 確認に使用されるローソクの種類/時間枠。 下半期の時間枠
指標 M15 SMMA Period M15 シリーズの平滑化移動平均の長さ。 200
指標 H1 SMMA Period H1 シリーズの平滑化移動平均の長さ。 200
指標 Slow Stochastic Period %D ラインを提供する低速確率オシレーターの %K の長さ。 14
指標 Fast Stochastic Period メインの %K ラインを提供する高速確率発振器の %K の長さ。 14
信号 Threshold (points) エントリーを許可する M15 SMMA と現在の近くの間の最大距離。 50
リスク Take Profit (points) 価格ステップで表される利食い距離。 570
リスク Stop Loss (points) 価格ステップで表されるストップロス距離。 30
リスク Trailing Stop (points) トレーリングストップの距離を価格ステップで表します。 200
取引 Trade Volume 各成行注文で送信されるボリューム。 0.1

使用上の注意

  • 取引された証券が PriceStep を公開していることを確認します。それ以外の場合、ポイントベースの距離は 1 に戻り、大きな問題が発生する可能性があります。 小数単位で見積もられた金融商品に対する保護命令。
  • この戦略は、より良いトレーリングレベルが検出されるとすぐに、ストップ注文をキャンセルして再作成します。頻繁な取引を禁止するブローカー 変更にはスロットルが必要になる場合があります。
  • ポートは完成したローソク足でのみ動作するため、システムはバックテストとバーの終わりの実行向けに設計されています。実行する ライブティックデータは、端末と StockSharp の間のローソク足の構築設定を一致させる必要があります。
using System;

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

namespace StockSharp.Samples.Strategies;

public class GetTrendStochasticStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _oversold;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevRsi;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
	public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GetTrendStochasticStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14).SetDisplay("RSI Period", "RSI lookback", "Indicators");
		_emaPeriod = Param(nameof(EmaPeriod), 20).SetDisplay("EMA Period", "EMA filter", "Indicators");
		_oversold = Param(nameof(Oversold), 35m).SetDisplay("Oversold", "RSI oversold level", "Levels");
		_overbought = Param(nameof(Overbought), 65m).SetDisplay("Overbought", "RSI overbought level", "Levels");
		_cooldownCandles = Param(nameof(CooldownCandles), 30).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal ema)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (!_hasPrev) { _prevRsi = rsi; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevRsi = rsi;
			return;
		}

		if (_prevRsi <= Oversold && rsi > Oversold && close > ema && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (_prevRsi >= Overbought && rsi < Overbought && close < ema && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevRsi = rsi;
	}
}