GitHub で見る

価格で買う戦略

概要

  • MetaTrader エキスパート アドバイザー BuySellonYourPrice.mq5 (id 35391) を StockSharp の高レベルの API に変換します。
  • 開始時に 1 つの注文だけを送信し、アクティブな注文やポジションを必要としない元のロジックに一致します。
  • 絶対価格で表されるオプションのストップロスおよびテイクプロフィットレベルを使用して、マーケット、リミット、ストップエントリーをサポートします。
  • 有効なストップロス/テイクプロフィット距離が指定された価格レベルから導出できる場合、StockSharp 保護注文を自動的に構成します。

パラメーター

名前 説明 デフォルト
Mode 送信する注文タイプ (なし、買い、売り、買い指値、売り指値、買いストップ、売りストップ)。 None
OrderVolume 生成された注文のボリューム。 1
EntryPrice 未決注文に使用される価格。成行注文の場合は無視されます。 0
StopLossPrice ストップロスの絶対的な価格レベル。 0
TakeProfitPrice 利食いの絶対的な価格レベル。 0

取引ロジック

  1. 戦略が開始されると、次のことがチェックされます。
    • None とは異なる有効な Mode が選択されています。
    • OrderVolume は陽性です。
    • 現在のポジションやアクティブな注文はありません。どちらかが存在する場合、注文は送信されません(MQL の OrdersTotal()==0 および PositionsTotal()==0 チェックと同じです)。
  2. エントリー価格は次のように決定されます。
    • マーケット モードは最良の買値/売値を使用し、市場データがまだ利用できない場合は最後の価格または EntryPrice に戻ります。
    • 保留モードには EntryPrice > 0 が必要です。
  3. 保護距離は、指定されたストップロスおよびテイクプロフィットレベルから導出されます。 EA パラメータをエミュレートするために、有効な正の距離のみが StartProtection に渡されます。
  4. 選択した注文タイプ (BuyMarketSellLimitBuyStop など) が 1 回だけ送信され、アクションを反映する情報ログが生成されます。

オリジナルの EA との違い

  • ロギングは、Print ではなく AddInfoLog を通じて実行されます。
  • エントリー価格とストップロス/テイクプロフィットの両方で正の距離を計算できる場合、保護注文は StartProtection 経由で登録されます。
  • 市場価格の解決には現在のレベル 1 データ (BestBidBestAskLastPrice) が使用され、見積りがまだ利用できない場合は注文の送信が延期されます。

使用上の注意

  • 戦略を開始する前に必要なセキュリティを割り当て、レベル 1 データが成行注文に利用できることを確認します。
  • 未決注文を使用する場合は、EntryPriceStopLossPrice、および TakeProfitPrice を絶対条件で設定します。
  • 環境から戦略を削除せずに取引を無効にするには、ModeNone のままにします。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Buy Sell On Your Price strategy: Keltner Channel breakout.
/// Buys when close breaks above upper Keltner band, sells when close breaks below lower band.
/// </summary>
public class BuySellOnYourPriceStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

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

	public BuySellOnYourPriceStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for trend", "Indicators");
	}

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

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

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

		if (_hasPrev)
		{
			if (_prevClose <= _prevEma && candle.ClosePrice > emaValue && Position <= 0)
				BuyMarket();
			else if (_prevClose >= _prevEma && candle.ClosePrice < emaValue && Position >= 0)
				SellMarket();
		}

		_prevClose = candle.ClosePrice;
		_prevEma = emaValue;
		_hasPrev = true;
	}
}