GitHub で見る

ワンMA チャネルブレイクアウト戦略

概要

ワンMAチャネルブレイクアウト戦略は、StockSharpの高レベル戦略APIを使用してMetaTrader 5エキスパートアドバイザーOne MA EAを複製します。システムはシフトされた移動平均を描画し、設定可能なpipベースのチャネルで囲みます。価格が同じバー内でチャネルを試した後にチャネルの外でオープンすると、戦略はブレイクアウト方向にポジションを開き、オプションのストップロスとテイクプロフィット保護がリスクを自動的に管理します。

主な特徴:

  • 複数の移動平均計算方法(SMA、EMA、SMMA、LWMA)をサポート。
  • 移動平均に入力するローソク足価格(終値、始値、高値、安値、中央値、典型値、加重値)を選択可能。
  • 移動平均値とシグナル評価に使用されるローソク足に独立したシフトを適用し、元のEAのCurrent Barコントロールと一致。
  • インストゥルメントのPriceStepと小数点精度を使用してpip距離を絶対価格増分に変換(3/5小数インストゥルメントは自動的に従来のFX pipsにマッピング)。

トレードロジック

  1. インジケーター準備

    • サブスクライブされたローソク足シリーズ(CandleType)から、期間MaPeriod、方法MaMethodParam、シフトMaShift、適用価格AppliedPriceTypeで移動平均が計算されます。
    • チャネルオフセットはpipsから価格増分に変換されます:シフトされた移動平均の上にChannelHighPips、下にChannelLowPips
    • 履歴バッファーは、MQLバージョンと全く同様に、以前のバーの参照を許可します(MAシリーズにはMaBarShift、OHLCデータにはPriceBarShift)。
  2. シグナル生成

    • 強気ブレイクアウト:検査されたローソク足の安値がMAベースラインと上部チャネルの間に留まり、始値が上部チャネルを超えて印刷されます。ロングエクスポージャーがない場合(Position <= 0)、戦略は買います。
    • 弱気ブレイクアウト:検査されたローソク足の高値がMAベースラインと下部チャネルの間に留まり、始値が下部チャネルを下回って現れます。ショートエクスポージャーがない場合(Position >= 0)、戦略は売ります。
    • 注文ボリュームは設定されたTradeVolumeに加えて反対ポジションを解消するために必要な量に等しく、ソースエキスパートのhedge-to-net動作を反映します。
  3. リスク管理

    • StopLossPipsTakeProfitPipsは絶対価格距離に変換され、StartProtectionに渡され、各ポジションの自動エグジット注文が有効になります。
    • ゼロ値の場合、それぞれの保護注文は無効になります。

追加のエグジットロジックは適用されません;ポジションは保護モジュールを通じて、または反対シグナルへの逆転によってのみクローズします。

パラメーター

パラメーター 説明
MaPeriod 移動平均の長さ。> 0でなければなりません。
MaShift バーでの移動平均の水平シフト。正の値はMAを右に変位させます。
MaMethodParam 移動平均計算タイプ(SmaEmaSmmaLwma)。
AppliedPriceType MAに入力されるローソク足価格(CloseOpenHighLowMedianTypicalWeighted)。
MaBarShift 使用する過去のMA値(0 = 現在処理中のバー)。
PriceBarShift OHLC値のために検査する過去のローソク足。
ChannelHighPips MAから上部チャネル境界までの距離(pips)。
ChannelLowPips MAから下部チャネル境界までの距離(pips)。
StopLossPips pipsでの保護ストップ距離。ゼロはストップを無効にします。
TakeProfitPips pipsでの利益目標距離。ゼロはターゲットを無効にします。
TradeVolume 戦略ボリューム単位での注文サイズ(Strategy.Volumeにマッピング)。
CandleType 計算とシグナルに使用されるローソク足データシリーズ。

実装ノート

  • Pipから価格への変換はPriceStepDecimalsを使用します。3または5小数点のシンボルの場合、pip値はPriceStep * 10に等しく、それ以外の場合はPriceStepに等しくなります。
  • 履歴バッファーは固定サイズのスライディングウィンドウで実装され、戦略はインジケーターGetValue呼び出しに依存せずにインデックスでバーにアクセスでき、プロジェクトガイドラインに準拠します。
  • 戦略は完成したローソク足のみに依存します;未完成のローソク足は早期シグナルを避けるために無視されます。
  • オプションのチャートレンダリングは、ホストアプリケーションにチャート領域が利用可能な場合、価格ローソク足と実行されたトレードを描画します。

使用上のヒント

  • サブスクライブされた銘柄が有効なPriceStep/Decimalsデータを公開していることを確認します;そうでない場合は、pipベースのパラメーターを手動で調整します。
  • 特定の市場やタイムフレームにブレイクアウト動作を適応させるために、MaPeriod、チャネル距離、バーシフトを最適化します。
  • 戦略は常にインストゥルメントごとに1つのネットポジションを持つため、ライブ展開時はポートフォリオレベルのリスク管理と組み合わせます。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// One MA channel breakout strategy.
/// Places an SMA channel around price with configurable offset, trades breakouts.
/// </summary>
public class OneMaChannelBreakoutStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<decimal> _channelOffset;

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

	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	public decimal ChannelOffset
	{
		get => _channelOffset.Value;
		set => _channelOffset.Value = value;
	}

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

		_maPeriod = Param(nameof(MaPeriod), 44)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Moving average length", "Indicators");

		_channelOffset = Param(nameof(ChannelOffset), 0.005m)
			.SetGreaterThanZero()
			.SetDisplay("Channel Offset", "Percentage offset for channel", "Indicators");
	}

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var sma = new SimpleMovingAverage { Length = MaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var upper = maValue * (1 + ChannelOffset);
		var lower = maValue * (1 - ChannelOffset);
		var close = candle.ClosePrice;

		// Bullish breakout above upper channel
		if (close > upper && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Bearish breakdown below lower channel
		else if (close < lower && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}