GitHub で見る

E-フライデーセッション戦略

概要

E フライデー セッション戦略は、金曜日のみ取引する古典的な MetaTrader エキスパート アドバイザーを再現しています。前回の日足のローソク足を観察し、金曜日のセッション開始時に設定された時間にポジションをオープンします。方向は逆張りです。前日の終値が始値 (弱気のローソク足) を下回った場合、戦略は買いです。前日の終値が始値(強気のローソク足)を上回った場合、戦略は売りになります。ポジションは日中に管理され、設定可能な時間の経過後に自動的にクローズするか、保護ストップによってクローズすることができます。

取引ルール

  1. 毎日のローソク足 (デフォルト: 1 日) を収集して、前日の始値と終値を取得します。
  2. 金曜日に、日中のローソク足 (デフォルト: 1 分) を監視して、設定されたエントリー時間を検出します。
  3. 入場時間の最初のローソク足で:
    • 前日が弱気だった場合はロングにします。
    • 前日が強気だった場合はショートする。
    • 前日が童子(始値と終値が等しい)だった場合は取引をスキップします。
  4. オプションで、設定された終了時間に達するとポジションを自動的にクローズします。
  5. 利益のアクティベーションやトレーリング ステップのしきい値を含む、オリジナルの Expert Advisor を模倣するストップロス、テイクプロフィット、およびオプションのトレーリング ストップ ロジックを使用してエグジットを管理します。

実装メモ

  • 毎日のコンテキストと日中のタイミングの両方に、StockSharp の高レベルのキャンドル サブスクリプションを使用します。
  • 証券の価格ステップを使用して、ポイントベースのリスク管理を MQL バージョンから絶対価格オフセットに変換します。
  • コード内でトレーリング ストップを維持し、終了したローソク足ごとにトレーリング ストップを更新し、価格の極端な値を突破したときにポジションを閉じます。
  • 毎日の状態を追跡することで、金曜日に 1 回の取引のみを保証します。
  • ロングエントリーとショートエントリーの両方をサポートし、ストラテジーインスタンスごとに単一のシンボルを取引することで元のマジックナンバーゲーティングを尊重します。

パラメーター

名前 説明 デフォルト
Volume ロット/契約における取引サイズ。 0.1
StopLossPoints 価格ステップのストップロス距離 (0 無効)。 75
TakeProfitPoints 価格ステップでの利食い距離 (0 無効)。 0
HourOpen ポジションをオープンする時刻 (0 ~ 23)。 7
UseClosePositions 終了時間後の自動閉鎖を有効にします。 true
HourClose 有効な場合、ポジションを決済する時刻 (0 ~ 23)。 19
UseTrailing トレーリングストップ調整を有効にします。 true
ProfitTrailing トレーリングがアクティブになる前に、利益がトレーリング距離を超える必要があります。 true
TrailingStopPoints 価格ステップでのトレーリングストップ距離。 60
TrailingStepPoints トレーリングストップを強める前に追加ポイントが必要。 5
IntradayCandleType 日中のタイミングのローソク足タイプ (デフォルトは 1 分ローソク足)。 TimeSpan.FromMinutes(1)
DailyCandleType 毎日のセンチメント検出用のローソクのタイプ (デフォルトは 1 日のローソク)。 TimeSpan.FromDays(1)

使用のヒント

  • 金曜日のエントリー時間が希望する市場の開始時間と一致するように商品の取引セッションを調整します。
  • ストップロスとトレーリングの値を設定するときは、シンボルの価格ステップで使用されるのと同じ「ポイント」で表現して、MetaTrader の動作を再現します。
  • この戦略は金曜日に 1 回の取引を行うように設計されています。複数のシンボルを取引するには、シンボルごとに個別の戦略インスタンスを実行します。

オリジナルの EA との違い

  • 意思決定にはローソク足の終値データが使用されますが、ティックごとの元のポーリング価格が使用されます。
  • プロテクティブ・エグジットは、ローソク足がインターバル内にストップまたはターゲットレベルに触れたことを示したときに、成行注文を通じて実行されます。
  • 戦略パラメータは、StockSharp の StrategyParam システムを通じて公開され、最適化と UI バインディングをサポートします。
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>
/// E-Friday Session strategy - candle body direction with EMA filter.
/// Buys when previous candle was bearish and current closes above EMA (reversal).
/// Sells when previous candle was bullish and current closes below EMA (reversal).
/// </summary>
public class EFridaySessionStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevOpen;
	private decimal _prevClose;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public EFridaySessionStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA trend filter", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevOpen = 0m; _prevClose = 0m; _hasPrev = false; }

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, ProcessCandle)
			.Start();
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevOpen = candle.OpenPrice;
			_prevClose = close;
			_hasPrev = true;
			return;
		}

		var prevBearish = _prevClose < _prevOpen;
		var prevBullish = _prevClose > _prevOpen;

		// Previous bearish + close above EMA = buy reversal
		if (prevBearish && close > ema && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Previous bullish + close below EMA = sell reversal
		else if (prevBullish && close < ema && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevOpen = candle.OpenPrice;
		_prevClose = close;
	}
}