GitHub で見る

XDPOローソク足戦略

この戦略はオリジナルのMQL5エキスパートアドバイザー Exp_XDPOCandle の変換版です。始値と終値に2つの連続した指数移動平均を適用して合成ローソク足を構築します。結果として得られるローソク足の色(強気、弱気、または中立)がトレードの意思決定を導きます。

戦略ロジック

  1. 各受信市場ローソク足は2回平滑化されます:
    • 最初の平滑化は長さ FastLength のEMAを使用します。
    • 2回目の平滑化は最初の結果に長さ SlowLength の別のEMAを適用します。
  2. 平滑化された終値が平滑化された始値を上回る場合、ローソク足は強気とみなされます。
  3. 平滑化された終値が平滑化された始値を下回る場合、ローソク足は弱気とみなされます。
  4. 非強気ローソク足の後に強気ローソク足が現れるとロングポジションが建てられます。非弱気ローソク足の後に弱気ローソク足が現れるとショートポジションが建てられます。
  5. 既存の反対ポジションは成行注文を通じたリバーサルによって自動的にクローズされます。

パラメーター

名前 説明
FastLength 価格に適用される最初のEMAの長さ。
SlowLength 最初のEMA結果に適用される2番目のEMAの長さ。
CandleType 計算に使用する時間軸とローソク足の種類。

使用方法

  1. StockSharp環境内で戦略を銘柄に接続します。
  2. 必要に応じてパラメーターを設定します。デフォルト値はオリジナルのエキスパート設定に合わせて調整されています。
  3. 戦略を開始します。指定されたローソク足の種類を購読し、平滑化ローソク足の色の変化に応じて取引します。

注意事項

  • リスク管理はデフォルト設定の StartProtection() によって処理されます。必要に応じて Volume および保護パラメーターを外部で調整してください。
  • このリポジトリには現在C#版のみが含まれています。Pythonポートは提供されていません。
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;



/// <summary>
/// XDPO candle strategy that trades on color changes of double smoothed candles.
/// </summary>
public class XdpoCandleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _emaOpen1;
	private decimal? _emaOpen2;
	private decimal? _emaClose1;
	private decimal? _emaClose2;
	private int? _previousColor;

	/// <summary>
	/// Length of the first exponential moving average.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Length of the second exponential moving average.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Candle type used for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="XdpoCandleStrategy"/>.
	/// </summary>
	public XdpoCandleStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Length of the first EMA", "Parameters")
			;

		_slowLength = Param(nameof(SlowLength), 5)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Length of the second EMA", "Parameters")
			;

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return new[] { (Security, CandleType) };
	}

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

		_emaOpen1 = _emaOpen2 = _emaClose1 = _emaClose2 = null;
		_previousColor = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var warmup = new StockSharp.Algo.Indicators.ExponentialMovingAverage { Length = FastLength };
		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(warmup, ProcessCandle)
			.Start();

	}

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

		var open1 = CalcEma(candle.OpenPrice, ref _emaOpen1, FastLength);
		var open2 = CalcEma(open1, ref _emaOpen2, SlowLength);
		var close1 = CalcEma(candle.ClosePrice, ref _emaClose1, FastLength);
		var close2 = CalcEma(close1, ref _emaClose2, SlowLength);

		var color = open2 < close2 ? 2 : open2 > close2 ? 0 : 1;
		var goLong = color == 2 && _previousColor != 2;
		var goShort = color == 0 && _previousColor != 0;

		if (IsFormedAndOnlineAndAllowTrading())
		{
			if (goLong && Position <= 0)
				BuyMarket();
			else if (goShort && Position >= 0)
				SellMarket();
		}

		_previousColor = color;
	}

	private static decimal CalcEma(decimal price, ref decimal? prev, int length)
	{
		var k = 2m / (length + 1m);
		var result = prev.HasValue ? price * k + prev.Value * (1m - k) : price;
		prev = result;
		return result;
	}
}