GitHub で見る

TCPivotStop フロアブレイクアウト戦略

概要

TCPivotStop フロア ブレイクアウト戦略は、MetaTrader エキスパート アドバイザー gpfTCPivotStop の直接移植です。ロジックは以下を中心に展開します 前取引日に実行される古典的なフロアピボット計算。毎日の新しいセッションの開始時の戦略は次のとおりです。

  1. 前日の高値、安値、終値を集計して、ピボットポイントと最初の 3 つのサポート層とレジスタンス層を計算します。
  2. 最新の完了した時間足がピボットを上から横切ったのか下から横切ったのかを確認します。
  3. クロスオーバーの方向に成行注文を開き、同時にストップロスとテイクプロフィットのレベルを反映します。 本来の専門家の行動。

一度にアクティブにできるポジションは 1 つだけです。オプションのセッション管理により、新しい 1 日が始まるときに露出を平坦化することができます。

取引ルール

  • タイムフレーム – 1 時間のローソク足用に設計されています (構成可能)。
  • ピボット計算 – 前日の高値、安値、終値を使用して、PivotR1R2R3S1S2S3 を計算します。
  • エントリー条件
    • 最後に完了したバーがピボットの下で閉じ、前のバーがピボットの上で閉じた場合は、short と入力します。
    • 最後に完了したバーがピボットの上で閉じ、前のバーがピボットの下で閉じた場合は、「long」と入力します。
  • ポジションサイジングOrderVolume パラメータで定義された固定ロットサイズ。
  • 終了条件
    • ストップロスとテイクプロフィットの価格は、古典的なピボットレベルにマッピングされます。
    • CloseAtSessionEnd フラグが有効な場合、戦略は次のセッションが開始する前にオープン取引を清算します。
    • プロテクティブレベルはローソク足の高値/安値で監視され、タッチされたときに成行注文で実行されます。

パラメーター

名前 説明 デフォルト
OrderVolume 市場参入のための取引規模。 0.1
TakeProfitTarget どのピボット層が利益目標として機能するかを選択します (1 = 最も近い、3 = 最も遠い)。 1
CloseAtSessionEnd 新しい日次セッションが開始されたら、オープンポジションをクローズします。 false
CandleType すべての計算に使用される時間枠 (デフォルトでは時間単位)。 H1

注意事項

  • この戦略は、新しいピボット セットが利用可能な場合に 1 日に 1 回だけ注文を実行します。これは、ソース EA がトリガーされるのと同様です。 毎日のセッションの最初のティック。
  • MetaTrader バージョンは、口座証拠金履歴を使用してロットサイズを再計算しました。このポートはポジションサイジングを固定したままにし、 必要に応じて資金管理を他のコンポーネントに委任します。
  • 保護注文は、ローソク足の極値を監視し、しきい値を超えたら成行注文を送信することでエミュレートされます。

ファイル

  • CS/TcpFloorPivotBreakoutStrategy.cs – 取引ロジックの C# 実装。
  • README.md – 英語のドキュメント (このファイル)。
  • README_zh.md – 簡体字中国語翻訳。
  • README_ru.md – ロシア語の翻訳。
using System;

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

namespace StockSharp.Samples.Strategies;

public class TcpFloorPivotBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevMid;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public TcpFloorPivotBreakoutStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 48).SetDisplay("Channel Period", "Channel lookback", "Indicators");
		_cooldownCandles = Param(nameof(CooldownCandles), 150).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();
		_prevClose = default;
		_prevMid = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

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

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(highest, lowest, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		var mid = (highest + lowest) / 2;
		if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevClose = close;
			_prevMid = mid;
			return;
		}

		if (_prevClose <= _prevMid && close > mid && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (_prevClose >= _prevMid && close < mid && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevClose = close;
		_prevMid = mid;
	}
}