GitHub で見る

利益を確定する週末戦略

概要

Close Profit End Of Week 戦略 は、MetaTrader スクリプト Closeprofitendofweek.mq5 を自動化します。この戦略は、割り当てられた商品を管理し、設定可能なカットオフ時間後の金曜日に、収益性の高いすべてのポジションを決済します。目標は、週末のギャップリスクが現れる前に変動利益を確保することです。

元の MQL の動作

ソース Expert Advisor は、タイマー ハンドラーを通じてポジションを継続的にポーリングします。サーバー時刻が金曜日と設定された終了時刻に一致するたびに、取引されたシンボルのすべてのオープンポジションをループします。プラスの利益が得られたすべてのポジションは成行注文によって決済されました。暗号通貨シンボルは週末の休みなしで取引されるため、明示的に除外されました。

StockSharpの実装

C# ポートは、StockSharp の高レベルの API を使用している間、同じ保護ロジックを維持します。

  • 定期的な更新を受信するためにのみ、構成可能なキャンドル シリーズを購読します。
  • 終了した各ローソク足をチェックし、それが金曜日の終了時刻がユーザー定義のカットオフを過ぎていることを確認します。
  • 接続されたポートフォリオにアクセスして、戦略シンボルのネット ポジションを評価します。
  • まだオープンしている収益性の高いエクスポージャーごとに、反対方向の成行注文を発行します。
  • 金融商品が暗号資産として分類されている場合、ルーチンを完全にスキップします。

パラメーター

名前 説明 デフォルト
StartTradeTime モニタリング ウィンドウの始まり (MQL 入力と同等のために保持されます)。 00:00
EndTradeTime 利益のあるポジションをクローズしなければならない金曜日の時間帯。 20:00
CloseTradesAtEndTime 自動終了ルーチンを有効または無効にします。 true
CandleType 時間を追跡するために使用されるデータシリーズ (デフォルトは 1 分足のローソク足)。 TimeFrameCandle(1m)

実行フロー

  1. 戦略が開始されると、選択された証券が暗号資産クラスに属しているかどうかが検証されます。暗号商品は、MetaTrader ガード句を反映するために無視されます。
  2. キャンドルのサブスクリプションは、各キャンドルが終了したときに定期的なコールバックを受信するために作成されます。
  3. キャンドルが完成するたびに、スケジュールチェックがトリガーされます。締め切り時間を過ぎて終了した金曜日のみ、さらなる処理が行われます。
  4. この戦略は、接続されたポートフォリオをスキャンし、設定された証券に対応するポジションをフィルターし、その変動利益を読み取ります。
  5. 変動利益がゼロより大きい場合は、エクスポージャーを完全にクローズするために反対方向に成行注文が送信されます。
  6. 新しい注文を送信する前にアクティブな注文を検査することで、重複した決済注文が回避されます。

使用上の注意

  • 監視したいオープンポジションを所有する同じポートフォリオとともに、非暗号商品にストラテジーを添付します。
  • この戦略は新しい取引を開始しません。既存のポジションのみを管理します。
  • StartTradeTime パラメータは、構成パリティと将来の拡張のために存在しますが、現在のロジックでは参照されません。
  • マルチシンボル ポートフォリオの場合、商品ごとに 1 つのインスタンスを実行して、MetaTrader スクリプトの単一シンボル スコープを複製します。

制限事項

  • 利益の検出は、変動損益を報告するブローカーのポートフォリオに依存します。ポートフォリオがリアルタイムで更新されない場合、クロージング コマンドが遅れる可能性があります。
  • 設定された戦略シンボルのポジションのみがクローズされます。他のシンボルで保持されているエクスポージャーはそのまま残ります。
  • チェックはローソク足のクローズイベントで実行されます。より厳しいスケジュールが必要な場合は、適切に短い期間を選択してください。
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Close Profit End Of Week strategy: Momentum + EMA trend following.
/// Buys when momentum positive and close above EMA, sells when momentum negative and close below EMA.
/// </summary>
public class CloseProfitEndOfWeekStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _momPeriod;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _momentumLevel;

	private decimal _prevMom;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int MomPeriod { get => _momPeriod.Value; set => _momPeriod.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal MomentumLevel { get => _momentumLevel.Value; set => _momentumLevel.Value = value; }

	public CloseProfitEndOfWeekStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_momPeriod = Param(nameof(MomPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Momentum Period", "Momentum period", "Indicators");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA filter period", "Indicators");
		_momentumLevel = Param(nameof(MomentumLevel), 101m)
			.SetDisplay("Momentum Level", "Momentum threshold", "Signals");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMom = 0;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevMom = 0;
		_hasPrev = false;
		var mom = new Momentum { Length = MomPeriod };
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(mom, ema, ProcessCandle).Start();
	}

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

		if (_hasPrev)
		{
			if (_prevMom <= MomentumLevel && momValue > MomentumLevel && candle.ClosePrice > emaValue && Position <= 0)
				BuyMarket();
			else if (_prevMom >= 200m - MomentumLevel && momValue < 200m - MomentumLevel && candle.ClosePrice < emaValue && Position >= 0)
				SellMarket();
		}

		_prevMom = momValue;
		_hasPrev = true;
	}
}