ホーム
/
戦略のサンプル
GitHub で見る
ワンMA チャネルブレイクアウト戦略
概要
ワンMAチャネルブレイクアウト戦略 は、StockSharpの高レベル戦略APIを使用してMetaTrader 5エキスパートアドバイザーOne MA EA を複製します。システムはシフトされた移動平均を描画し、設定可能なpipベースのチャネルで囲みます。価格が同じバー内でチャネルを試した後にチャネルの外でオープンすると、戦略はブレイクアウト方向にポジションを開き、オプションのストップロスとテイクプロフィット保護がリスクを自動的に管理します。
主な特徴:
複数の移動平均計算方法(SMA、EMA、SMMA、LWMA)をサポート。
移動平均に入力するローソク足価格(終値、始値、高値、安値、中央値、典型値、加重値)を選択可能。
移動平均値とシグナル評価に使用されるローソク足に独立したシフトを適用し、元のEAのCurrent Barコントロールと一致。
インストゥルメントのPriceStepと小数点精度を使用してpip距離を絶対価格増分に変換(3/5小数インストゥルメントは自動的に従来のFX pipsにマッピング)。
トレードロジック
インジケーター準備
サブスクライブされたローソク足シリーズ(CandleType)から、期間MaPeriod、方法MaMethodParam、シフトMaShift、適用価格AppliedPriceTypeで移動平均が計算されます。
チャネルオフセットはpipsから価格増分に変換されます:シフトされた移動平均の上にChannelHighPips、下にChannelLowPips。
履歴バッファーは、MQLバージョンと全く同様に、以前のバーの参照を許可します(MAシリーズにはMaBarShift、OHLCデータにはPriceBarShift)。
シグナル生成
強気ブレイクアウト :検査されたローソク足の安値がMAベースラインと上部チャネルの間に留まり、始値が上部チャネルを超えて印刷されます。ロングエクスポージャーがない場合(Position <= 0)、戦略は買います。
弱気ブレイクアウト :検査されたローソク足の高値がMAベースラインと下部チャネルの間に留まり、始値が下部チャネルを下回って現れます。ショートエクスポージャーがない場合(Position >= 0)、戦略は売ります。
注文ボリュームは設定されたTradeVolumeに加えて反対ポジションを解消するために必要な量に等しく、ソースエキスパートのhedge-to-net動作を反映します。
リスク管理
StopLossPipsとTakeProfitPipsは絶対価格距離に変換され、StartProtectionに渡され、各ポジションの自動エグジット注文が有効になります。
ゼロ値の場合、それぞれの保護注文は無効になります。
追加のエグジットロジックは適用されません;ポジションは保護モジュールを通じて、または反対シグナルへの逆転によってのみクローズします。
パラメーター
パラメーター
説明
MaPeriod
移動平均の長さ。> 0でなければなりません。
MaShift
バーでの移動平均の水平シフト。正の値はMAを右に変位させます。
MaMethodParam
移動平均計算タイプ(Sma、Ema、Smma、Lwma)。
AppliedPriceType
MAに入力されるローソク足価格(Close、Open、High、Low、Median、Typical、Weighted)。
MaBarShift
使用する過去のMA値(0 = 現在処理中のバー)。
PriceBarShift
OHLC値のために検査する過去のローソク足。
ChannelHighPips
MAから上部チャネル境界までの距離(pips)。
ChannelLowPips
MAから下部チャネル境界までの距離(pips)。
StopLossPips
pipsでの保護ストップ距離。ゼロはストップを無効にします。
TakeProfitPips
pipsでの利益目標距離。ゼロはターゲットを無効にします。
TradeVolume
戦略ボリューム単位での注文サイズ(Strategy.Volumeにマッピング)。
CandleType
計算とシグナルに使用されるローソク足データシリーズ。
実装ノート
Pipから価格への変換はPriceStepとDecimalsを使用します。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();
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class one_ma_channel_breakout_strategy(Strategy):
def __init__(self):
super(one_ma_channel_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._ma_period = self.Param("MaPeriod", 44) \
.SetDisplay("MA Period", "Moving average length", "Indicators")
self._channel_offset = self.Param("ChannelOffset", 0.005) \
.SetDisplay("Channel Offset", "Percentage offset for channel", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def MaPeriod(self):
return self._ma_period.Value
@property
def ChannelOffset(self):
return self._channel_offset.Value
def OnStarted2(self, time):
super(one_ma_channel_breakout_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.MaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(sma, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _on_process(self, candle, ma_value):
if candle.State != CandleStates.Finished:
return
mv = float(ma_value)
offset = float(self.ChannelOffset)
upper = mv * (1.0 + offset)
lower = mv * (1.0 - offset)
close = float(candle.ClosePrice)
# Bullish breakout above upper channel
if close > upper and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Bearish breakdown below lower channel
elif close < lower and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return one_ma_channel_breakout_strategy()