GitHub で見る
MA テンプレートの基本戦略
基本的な MA テンプレート戦略 は、リポジトリ エントリ MQL/27964 の MetaTrader 4 エキスパート アドバイザの忠実な StockSharp 移植です。元のロボットは、より高い時間枠の移動平均で単一のシンボルを取引し、前のローソク足が平均を横切るたびにポジションをオープンしました。この C# バージョンは最小限の構造を維持しながら、すべてのコントロールをパラメータとして公開するため、動作を StockSharp 内で直接調整または最適化できます。
テンプレートは完全に完成したローソク足を待ち、その始値と終値をシフトされた移動平均と比較します。バーが平均より上で開き、下で閉じる場合、戦略はショート ポジションをオープンします。逆の場合はロングトレードが始まります。システムは一度に 1 つの市場ポジションのみを許可し、MQL の「アクティブなチケットがありません」チェックを反映します。保護的なストップロスとテイクプロフィットの距離はpipsで定義されます。開始時に、ストラテジーは商品ステップと小数精度を使用してこれらのピップ距離を絶対価格オフセットに変換し、MetaTrader の気配桁に依存するポイントからピップへの変換ロジックを複製します。
取引ロジック
- データ ソース:
CandleType パラメーター (デフォルトは H4) によって決定される単一のローソク足シリーズ。
- インジケーター: 設定可能な移動平均 (
SMA、EMA、SMMA、または LWMA)。 MovingAverageShift パラメータは、MetaTrader iMA 関数とまったく同じようにインジケーターを前方にシフトします。
- エントリールール:
- ロング: ポジションがオープンしていない間、前のローソク足がシフト移動平均の下で始まり、上で閉じました。
- ショート: 前のローソク足がシフト移動平均の上で始まり、下で閉じましたが、オープンなポジションはありません。
- 終了ルール: pip ベースのテイクプロフィットとストップロスの距離を使用して、StockSharp
StartProtection モジュールによって自動的に処理されます。両方のターゲットがゼロの場合でも、この戦略では保護サービスが有効なため、後続または手動での終了が可能です。
- ポジション フィルター: この戦略は、ポジションがアクティブである間は新しいシグナルを無視し、動作を元の
PosSelect() ルーチンと同一に保ちます。
パラメーター
| パラメータ |
説明 |
デフォルト |
CandleType |
シグナルに使用されるローソク足アグリゲーション。 |
H4 (4時間キャンドル) |
MovingAveragePeriod |
移動平均の期間の長さ。 |
49 |
MovingAverageShift |
移動平均バッファに適用される前方シフト。 |
0 |
MovingAverageMethod |
移動平均計算モード (Simple、Exponential、Smoothed、LinearWeighted)。 |
Simple |
TakeProfitPips |
実行時に絶対価格オフセットに変換されたピップ単位の利食い距離。 |
38.5 |
StopLossPips |
実行時に絶対価格オフセットに変換されたピップ単位のストップロス距離。 |
48.5 |
リスク対応
保護サブシステムは、計算された絶対距離を受け取り、それをすべての成行注文に付加します。ピップサイズはシンボルのステップと小数精度(5 桁と 3 桁の引用符はステップを 10 倍します)から導出されるため、ストップレベルは MetaTrader バージョンのブローカーによって強制される最小間隔を尊重します。
変換メモ
- 元の ECN スタイルの 2 ステップの注文発注は、自動保護を備えた StockSharp 成行注文に簡略化されており、約定後の SL/TP の付加がすでに処理されています。
CheckVolumeValue ルーチンと CheckMoneyForTrade ルーチンは省略されています。ポジションのサイジングは、標準の StockSharp リスク設定を通じて構成する必要があります。
- ロギングステートメントはチャート描画フックに置き換えられ、移動平均と実行された取引を戦略チャート領域で直接視覚化できます。
この変換では、慣用的な高レベルの StockSharp API (SubscribeCandles、Bind、および StartProtection) を採用しながら、意思決定モデルを同一に保ちます。より高度な移動平均システムを構築するための軽量の足場として使用します。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Basic MA Template strategy: trades when price crosses a moving average.
/// Opens long when previous candle crosses above MA, short when crosses below.
/// </summary>
public class BasicMaTemplateStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private decimal? _prevOpen;
private decimal? _prevClose;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public BasicMaTemplateStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_maPeriod = Param(nameof(MaPeriod), 49)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevOpen = null;
_prevClose = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevOpen = null;
_prevClose = null;
var sma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sma)
{
if (candle.State != CandleStates.Finished) return;
if (_prevOpen.HasValue && _prevClose.HasValue)
{
if (_prevOpen.Value > sma && _prevClose.Value < sma && Position >= 0)
SellMarket();
else if (_prevOpen.Value < sma && _prevClose.Value > sma && Position <= 0)
BuyMarket();
}
_prevOpen = candle.OpenPrice;
_prevClose = candle.ClosePrice;
}
}
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 basic_ma_template_strategy(Strategy):
def __init__(self):
super(basic_ma_template_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._ma_period = self.Param("MaPeriod", 49) \
.SetDisplay("MA Period", "Moving average period", "Indicators")
self._prev_open = None
self._prev_close = None
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
@property
def ma_period(self):
return self._ma_period.Value
@ma_period.setter
def ma_period(self, value):
self._ma_period.Value = value
def OnReseted(self):
super(basic_ma_template_strategy, self).OnReseted()
self._prev_open = None
self._prev_close = None
def OnStarted2(self, time):
super(basic_ma_template_strategy, self).OnStarted2(time)
self._prev_open = None
self._prev_close = None
sma = SimpleMovingAverage()
sma.Length = self.ma_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
if self._prev_open is not None and self._prev_close is not None:
if self._prev_open > sma_value and self._prev_close < sma_value and self.Position >= 0:
self.SellMarket()
elif self._prev_open < sma_value and self._prev_close > sma_value and self.Position <= 0:
self.BuyMarket()
self._prev_open = float(candle.OpenPrice)
self._prev_close = float(candle.ClosePrice)
def CreateClone(self):
return basic_ma_template_strategy()