GitHub で見る

ランダムT戦略

概要

この戦略は、MetaTrader 4 エキスパート アドバイザー「RandomT」の StockSharp 移植です。元の EA は、確認されたフラクタルと一致する ZigZag スイングを待ってから、MACD 比較でエントリをフィルタリングします。 StockSharp バージョンは同じ決定プロセスを維持します。設定可能な数のローソク足 (BarWatch) を監視し、5 足のフラクタルが最新のスイングの極値をマークしていることを確認し、MACD のメインラインが同じ履歴足のシグナルラインの上または下にある場合にのみ取引します。

取引ロジック

  • ローリングローソク足バッファを構築し、選択した時間枠 (CandleType) の終了した各バーで MACD シグナルを計算します。
  • 過去の Shift バーを調べて、そのバーが上向きまたは下向きのフラクタル (両側に 2 本のローソク足) を形成しているかどうかを確認します。
  • 周囲の価格アクションに対してフラクタルを検証します。BarWatch ルックバック ウィンドウ内の高値が最大値、または安値が最小値である必要があります。これは、MetaTrader バージョンで使用される ZigZag スイング確認を反映しています。
  • 短いセットアップの場合、MACD のメイン値はシフトされたバーの信号値より大きくなければなりません。長いセットアップの場合は、逆の比較が真である必要があります。
  • シグナルが表示されると、この戦略は単一の成行注文を使用し、新しい取引を開始する前にそのボリュームで反対のポジションを無効にします。

トレーリングストップ管理

  • トレーリングブロックは、UseTrailingProfit が有効で、変動利益 (PriceStep および StepPrice を通じて換算) が MinProfit を超える場合にのみアクティブになります。
  • トレーリング距離は価格ポイントで測定されます。 AutoStopLeveltrue の場合、エンジンは StartStopLevelPoints を使用します。それ以外の場合は、StopLevelPoints が使用されます。
  • ロングポジションの場合、ストップは ClosePrice - distance を追跡し、ショートポジションの場合、ストップは ClosePrice + distance を追跡します。ローソク足がストップレベルを突き抜けた場合、戦略は成行注文で取引を終了します。

パラメーター

パラメータ 説明
TradeVolume すべてのエントリーに使用されるロット単位の基本取引サイズ。
BarWatch フラクタルがジグザグ スイングの極値でもあることを検証するために使用されるバーの数。
Shift シグナルが評価された履歴内のバーの数。古典的なフラクタルの場合は 2 のままにする必要があります。
UseTrailingProfit トレーリングストップロジックを有効にします。
AutoStopLevel 後続距離を StartStopLevelPoints に切り替えます。
StartStopLevelPoints 代替後続距離 (ポイント)。
StopLevelPoints 主な後続距離 (ポイント)。
MinProfit トレーリングが適用される前に必要な最小変動利益 (アカウント通貨)。
CandleType ローソク足とインジケーターの計算に使用される時間枠。
MacdFastLength MACD フィルタの高速な EMA 期間。
MacdSlowLength MACD フィルタの EMA 期間が遅い。
MacdSignalLength MACD フィルタの EMA 期間を通知します。

注意事項

  • この戦略は内部でフラクタル (各辺に 2 つのバー) を計算し、その結果を ZigZag 検証に再利用して、MQL コードでアクセスされるバッファーと厳密に一致させます。
  • ZigZag の確認は、完全な MetaTrader インジケーターを再実行するのではなく、周囲の BarWatch ローソク足をチェックすることによって近似され、これにより、StockSharp 内の動作が確定的に保たれます。
  • トレーリングストップの利益は、商品の PriceStepStepPrice から得られます。ストラテジーを実行する前に、お使いの商品のこれらの値を確認してください。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RandomT: EMA crossover with RSI filter and ATR stops.
/// </summary>
public class RandomTStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

	public RandomTStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_fastEmaLength = Param(nameof(FastEmaLength), 12)
			.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators");
		_slowEmaLength = Param(nameof(SlowEmaLength), 26)
			.SetDisplay("Slow EMA Length", "Slow EMA period.", "Indicators");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
	public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

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

		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
		var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, rsi, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fastEma); DrawIndicator(area, slowEma); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0) { _prevFast = fastVal; _prevSlow = slowVal; return; }
		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
			else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _entryPrice = close; SellMarket(); }
		}
		_prevFast = fastVal; _prevSlow = slowVal;
	}
}