GitHub で見る

平均変化ローソク足戦略

MetaTraderのエキスパートExp_AverageChangeCandleから変換された戦略です。ダイナミックなベースライン移動平均に対するローソク足の比率を平滑化し、強気/弱気の色遷移に反応することで、StockSharp内のオリジナルロジックを再現します。

コアアイデア

  1. 選択した適用価格に対してベースライン移動平均(MaMethod1Length1)を計算します。
  2. 現在のローソク足の始値と終値をベースラインに対する比率として表し、それらをPower乗します。
  3. 変換された始値と終値の値を二次移動平均(MaMethod2Length2)で平滑化します。
  4. ローソク足の色を分類します:平滑化された終値 > 平滑化された始値なら強気、平滑化された終値 < 平滑化された始値なら弱気。
  5. 設定されたSignalBar遅延後に色が変化したときにトレードシグナルを生成します。

完成したローソク足のみが処理されます。戦略は新しい色の方向にマーケットポジションを開き、オプションで反対側を閉じます。

パラメーター

パラメーター デフォルト値 説明
OrderVolume 1 新しいポジションを開く際に使用するボリューム。
MaMethod1 Lwma ベースライン比率に適用される平滑化(SMA/EMA/SMMA/LWMA/JJMA/AMAのサブセット)。非対応タイプはEMAにフォールバック。
Length1 12 ベースライン移動平均の期間。
Phase1 15 ベースラインのJurikフェーズパラメーター(互換性のため保持)。
PriceSource Median ベースラインを計算する前に使用される適用価格。
MaMethod2 Jjma 変換された比率に適用される平滑化。
Length2 5 シグナル移動平均の期間。
Phase2 100 シグナル平滑化のJurikフェーズパラメーター。
Power 5 始値/終値の比率を上げる際に使用される指数。
SignalBar 1 色変化に反応する前に待つ閉じたバーの数。
BuyOpenEnabled true ロングポジションを開くことを許可。
SellOpenEnabled true ショートポジションを開くことを許可。
BuyCloseEnabled true 弱気シグナルが現れたときにロングを閉じる。
SellCloseEnabled true 強気シグナルが現れたときにショートを閉じる。
StopLossPoints 0 絶対ストップロス距離。0でストップを無効化。
TakeProfitPoints 0 絶対テイクプロフィット距離。0で目標を無効化。
CandleType H4タイムフレーム 戦略が処理するローソク足シリーズ。

トレードルール

  • 強気の遷移colorが2に変化):アクティブなショートを閉じ(許可されている場合)、Position <= 0かつBuyOpenEnabledが真のときにロングポジションを開きます。
  • 弱気の遷移colorが0に変化):アクティブなロングを閉じ(許可されている場合)、Position >= 0かつSellOpenEnabledが真のときにショートポジションを開きます。
  • 色1(中立)はトレードをトリガーしません。
  • オリジナルのMetaTraderタイミングを模倣するため、シグナルは最近完了したローソク足からSignalBarステップ後ろにある棒を使って評価されます。

リスク管理

StopLossPointsTakeProfitPointsは絶対距離でStartProtectionを設定します。いずれかの値がゼロの場合、対応する保護が無効化されます。

注記

  • StockSharpで利用可能な平滑化方法のみが直接実装されています。オリジナルコードのJurX、ParMA、T3、VIDYAは機能的なフォールバックとしてEMAにマッピングされます。
  • フェーズパラメーターは互換性のために保持されますが、Jurik/Kaufmanベースの平均のみに影響します。
  • 戦略はオリジナルのエキスパートアドバイザーと同様に成行注文を使用します。MQLバージョンのスリッページ管理は、StockSharpがコネクタを介して実行を処理するため、再現されません。
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Average Change Candle strategy (simplified).
/// Compares smoothed open vs close ratios to detect bullish/bearish candle patterns.
/// Uses EMA of open and close to determine trend direction.
/// </summary>
public class AverageChangeCandleStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _prevSmoothedOpen;
	private decimal _prevSmoothedClose;
	private bool _initialized;

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

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

	public AverageChangeCandleStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Source candles", "General");

		_emaPeriod = Param(nameof(EmaPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA smoothing period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevSmoothedOpen = 0m;
		_prevSmoothedClose = 0m;
		_initialized = false;
	}

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

		_prevSmoothedOpen = 0;
		_prevSmoothedClose = 0;
		_initialized = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, (ICandleMessage candle, decimal emaValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				// Simple exponential smoothing of open and close
				var alpha = 2m / (EmaPeriod + 1m);

				if (!_initialized)
				{
					_prevSmoothedOpen = candle.OpenPrice;
					_prevSmoothedClose = candle.ClosePrice;
					_initialized = true;
					return;
				}

				var smoothedOpen = alpha * candle.OpenPrice + (1m - alpha) * _prevSmoothedOpen;
				var smoothedClose = alpha * candle.ClosePrice + (1m - alpha) * _prevSmoothedClose;

				var prevBullish = _prevSmoothedClose > _prevSmoothedOpen;
				var currBullish = smoothedClose > smoothedOpen;

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					_prevSmoothedOpen = smoothedOpen;
					_prevSmoothedClose = smoothedClose;
					return;
				}

				// Buy on transition to bullish smoothed candle
				if (currBullish && !prevBullish && candle.ClosePrice > emaValue && Position <= 0)
				{
					BuyMarket();
				}
				// Sell on transition to bearish smoothed candle
				else if (!currBullish && prevBullish && candle.ClosePrice < emaValue && Position >= 0)
				{
					SellMarket();
				}

				_prevSmoothedOpen = smoothedOpen;
				_prevSmoothedClose = smoothedClose;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, ema);
			DrawOwnTrades(area);
		}
	}
}