GitHub で見る

素晴らしいFXトレーダー

This strategy reproduces the MetaTrader setup from MQL/8539, which consists of the custom indicators AwesomeFxTradera.mq4 and t_ma.mq4. The original code paints the Bill Williams Awesome Oscillator histogram in green or red depending on whether the value is rising or falling, and overlays a 34-period linear weighted moving average (LWMA) alongside a smoothed clone of the same curve. StockSharp ポートは同じ計算を維持し、インジケーターの色を取引シグナルに変換します。

元の MQL ロジック

  1. AwesomeFxTradera.mq4 computes two exponential moving averages applied to the open price with periods 8 and 13. Their difference is stored in ExtBuffer0.現在の値が前のバーよりも高い場合はバッファーが緑色にペイントされ、低い場合は赤色でペイントされます。これにより、運動量の符号だけでなく方向も効果的にエンコードされます。
  2. t_ma.mq4 は、始値の 34 期間 LWMA (ExtMapBuffer1) とその LWMA の 6 期間単純移動平均 (ExtMapBuffer2) をプロットします。スムーズでは、トレンド平均が加速するか減速するかを追跡します。

The MetaTrader chart therefore highlights bullish momentum when the oscillator is above zero and keeps increasing while price trades above the smoothed LWMA.弱気の勢いはその逆の構成です。

StockSharp の実装

The AwesomeFxTraderStrategy subscribes to a configurable candle type (default M15) and feeds the indicators with the candle open price to match the MetaTrader buffers.

  1. 高速 EMA と低速 EMA は、完成したローソクごとに再計算されます。それらの差により、振動するヒストグラムが再現されます。
  2. LWMA は 34 バーのトレンドを追跡し、6 バーの SMA がそれを平滑化します。両方の系列を比較すると、トレンド曲線が上昇しているか下降しているかがわかります。
  3. The oscillator colour is rebuilt by comparing the current histogram value with the previous bar, following the bool up logic from the MQL implementation.
  4. エントリールール:
    • オシレーターが正で上昇しており (緑色のバッファー)、LWMA がそのスムーザーを上回っているときにロングを入力します。
    • オシレーターが負で立ち下がり(赤色のバッファー)、LWMA がそのスムーザーを下回っている場合は、ショートを入力します。
  5. 終了/反転ルール: 反対のシグナルによりポジションが反転します。 The order size is automatically increased by the absolute current position so that shorts are closed before a long is established and vice versa.

ソース コードには追加のストップロスまたはテイクプロフィット レベルが定義されていないため、ポートはエグジットのモメンタム フリップのみに依存します。ロギングステートメントには、インジケーターの読み取り値とともに各取引トリガーが記録されます。

パラメーター

名前 デフォルト 説明
FastEmaPeriod 8 発振器レプリカで使用される高速 EMA の長さ。
SlowEmaPeriod 13 低速の EMA の長さ。
TrendLwmaPeriod 34 t_ma.mq4 から取得された LWMA トレンド フィルターの期間。
TrendSmoothingPeriod 6 LWMA 値に適用される SMA のウィンドウ。
CandleType 15分の時間枠 勢いとトレンドの計算の両方に使用されるローソク足のデータ型。

StrategyParam メタデータのおかげで、すべてのパラメータは StockSharp UI を通じて最適化できます。

ファイルマッピング

MetaTrader ファイル StockSharpの相手方 注意事項
MQL/8539/AwesomeFxTradera.mq4 CS/AwesomeFxTraderStrategy.cs EMA-on-open オシレーターとその立ち上がり/立ち下がりカラー ロジックを再作成します。
MQL/8539/t_ma.mq4 CS/AwesomeFxTraderStrategy.cs トレンド検出のために 6 期間の SMA スムーザーを備えた 34 期間 LWMA を実装します。

Python のバージョンは、要求に応じて意図的に省略されています。

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Awesome Fx Trader strategy.
/// Recreates the MetaTrader logic that paints the Awesome Oscillator histogram and trend moving averages.
/// Goes long when the oscillator turns bullish while the linear weighted average stays above its smoother.
/// Opens shorts on the opposite momentum and trend alignment.
/// </summary>
public class AwesomeFxTraderStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<int> _trendLwmaPeriod;
	private readonly StrategyParam<int> _trendSmoothingPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private EMA _fastEma;
	private EMA _slowEma;
	private WeightedMovingAverage _trendLwma;

	private decimal _previousAo;
	private bool _hasPreviousAo;
	private bool _isAoIncreasing;
	private decimal _previousLwma;

	/// <summary>
	/// Period for the fast EMA used in the oscillator.
	/// </summary>
	public int FastEmaPeriod
	{
		get => _fastEmaPeriod.Value;
		set => _fastEmaPeriod.Value = value;
	}

	/// <summary>
	/// Period for the slow EMA used in the oscillator.
	/// </summary>
	public int SlowEmaPeriod
	{
		get => _slowEmaPeriod.Value;
		set => _slowEmaPeriod.Value = value;
	}

	/// <summary>
	/// Length of the trend linear weighted moving average.
	/// </summary>
	public int TrendLwmaPeriod
	{
		get => _trendLwmaPeriod.Value;
		set => _trendLwmaPeriod.Value = value;
	}

	/// <summary>
	/// Length of the smoothing simple moving average applied to the trend LWMA.
	/// </summary>
	public int TrendSmoothingPeriod
	{
		get => _trendSmoothingPeriod.Value;
		set => _trendSmoothingPeriod.Value = value;
	}

	/// <summary>
	/// Type of candles to use for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initialize <see cref="AwesomeFxTraderStrategy"/>.
	/// </summary>
	public AwesomeFxTraderStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Period of the fast EMA driving the oscillator", "Awesome Oscillator")
			
			.SetOptimize(4, 20, 1);

		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 13)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Period of the slow EMA driving the oscillator", "Awesome Oscillator")
			
			.SetOptimize(8, 40, 1);

		_trendLwmaPeriod = Param(nameof(TrendLwmaPeriod), 34)
			.SetGreaterThanZero()
			.SetDisplay("Trend LWMA", "Length of the linear weighted trend average", "Trend Filter")
			
			.SetOptimize(20, 80, 2);

		_trendSmoothingPeriod = Param(nameof(TrendSmoothingPeriod), 6)
			.SetGreaterThanZero()
			.SetDisplay("Trend Smoother", "Length of the SMA applied to the trend LWMA", "Trend Filter")
			
			.SetOptimize(3, 10, 1);

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Time-frame used for calculations", "General");
	}

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

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

		_fastEma = null;
		_slowEma = null;
		_trendLwma = null;
		_previousAo = 0m;
		_hasPreviousAo = false;
		_isAoIncreasing = false;
		_previousLwma = 0m;
	}

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

		_fastEma = new EMA { Length = FastEmaPeriod };
		_slowEma = new EMA { Length = SlowEmaPeriod };
		_trendLwma = new WeightedMovingAverage { Length = TrendLwmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(_fastEma, _slowEma, _trendLwma, ProcessCandle).Start();

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

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

		var ao = fastEma - slowEma;

		if (!_hasPreviousAo)
		{
			_previousAo = ao;
			_hasPreviousAo = true;
			_isAoIncreasing = ao >= 0m;
			_previousLwma = lwma;
			return;
		}

		if (ao > _previousAo)
			_isAoIncreasing = true;
		else if (ao < _previousAo)
			_isAoIncreasing = false;

		var isTrendBullish = lwma > _previousLwma;
		var isTrendBearish = lwma < _previousLwma;
		var bullishSignal = _isAoIncreasing && ao > 0m && isTrendBullish;
		var bearishSignal = !_isAoIncreasing && ao < 0m && isTrendBearish;

		if (bullishSignal && Position <= 0)
		{
			var volume = Volume + Math.Abs(Position);
			if (volume <= 0)
				volume = 1;

			BuyMarket(volume);
		}
		else if (bearishSignal && Position >= 0)
		{
			var volume = Volume + Math.Abs(Position);
			if (volume <= 0)
				volume = 1;

			SellMarket(volume);
		}

		_previousAo = ao;
		_previousLwma = lwma;
	}
}