ホーム
/
戦略のサンプル
GitHub で見る
エンベロープMAショート戦略
概要
Envelope MA Short Strategy は、MetaTrader エキスパート アドバイザー EnvelopeMA.mq4 (ID 9533) の C# ポートです。これは、指数移動平均エンベロープと 2 つの追加 EMA および 3 つの Parabolic SAR フィルターを組み合わせることにより、15 分足のローソク足での元のショートのみのブレイクアウト ロジックを再作成します。この戦略は、価格の下落とエンベロープの下半分への急速な EMA を監視し、エンベロープの下限で保留中の売りストップ注文を準備します。注文が約定すると、固定のストップロスおよびテイクプロフィットレベルとインジケーターベースの決済ルールでショートポジションを管理します。
インジケーターとシグナル
エンベロープベース: ローソク足の高値の指数移動平均 (EnvelopePeriod、デフォルトは 280)。下のバンドはエントリートリガーであり、偏差パーセンテージ (EnvelopeDeviation、デフォルトは 0.08%) で計算されます。
Fast EMA: ショートエントリーを準備する前に勢いを確認するために使用されるローソク足の安値の指数移動平均 (FastMaPeriod、デフォルトは 6)。
スロー EMA (シフト): 1 バー遅延のあるローソク足の指数移動平均 (SlowMaPeriod、デフォルトは 18)。遅延値は、MetaTrader からの iMA シフト パラメータを反映し、エントリの確認と終了の決定の両方に使用されます。
Parabolic SAR トリオ: 異なる加速係数 (0.03/0.5、0.015/0.6、0.02/0.2) を持つ 3 つの Parabolic SAR インスタンスは、戦略がインジケーターベースのエグジットを許可する前に、すべて現在の価格を上回る必要があります。
戦略は完成したキャンドルを待ちます。ファースト EMA、シフト スロー EMA、およびローソク足の終値がエンベロープの境界内 (下限バンドの上と上限バンドの下) に残っている場合、下限エンベロープ バンドで売りストップ注文を送信します。未決注文が約定されないままの場合、約 5 ローソク足間隔の後に期限切れになります。
貿易管理
プロテクションレベル: エントリー時に、ストラテジーは設定されたピップ距離から導出された内部ストップロスおよびテイクプロフィットターゲットを設定します。ローソク足の範囲外の価格変動は、完成した各バーの高値と安値を使用して近似されます。
インジケーターの出口: EMA と終値の両方がエントリー価格を下回り、3 つの SAR の値がすべて価格を上回り、速い EMA が遅延した遅い EMA を上回ったときに、ショート ポジションは早期にクローズされます。これは、MetaTrader の動作を模倣します。
トレーリング調整: 少なくとも 4 バーの後、エントリー以降のローソク足の最高値がエントリー価格より少なくとも 3 価格ステップ下に移動し、終値がエンベロープの下限バンドを下回って取引されている場合、ストップロスはその下限バンドまでタイトになります。
リスク管理
株式保護: LiquidityThreshold パラメーターは、ポートフォリオの株式と開始残高の比率が設定値 (デフォルト 0.58) を下回る場合、オープンショートを閉じ、保留中の売りストップをキャンセルします。
注文の有効期限: 未約定の保留注文は、古いシグナルを避けるために、5 バーの有効期間が経過すると自動的にキャンセルされます。
パラメーター
名前
説明
デフォルト
CandleType
戦略によって処理されるローソク足のタイプ/タイムフレーム。
15分の時間枠
EnvelopePeriod
EMA の長さがエンベロープのベースとして使用されます。
280
EnvelopeDeviation
封筒の幅をパーセントで表します。
0.08
FastMaPeriod
安値で計算された高速の EMA 期間。
6
SlowMaPeriod
EMA 期間が遅い (1 小節の遅延で評価)。
18
StopLossPips
エントリー価格からのストップロス距離 (ピップ単位)。
25
TakeProfitPips
エントリー価格からの利益確定距離 (ピップ単位)。
25
TradeVolume
未決注文と成行注文に使用される数量。
1
LiquidityThreshold
最小資本対残高比率。ショーツは違反されると処分されます。
0.58
変換メモ
MetaTrader の残高、証拠金、またはカウンターピップに基づくロットサイジングは、StockSharp 実行モデルに適合する直接の TradeVolume パラメータに置き換えられました。
StockSharp 注文は MetaTrader と同じ有効期限フィールドを公開しないため、保留中の注文の有効期限タイムスタンプは戦略ループ内で処理されます。
ストップロスとテイクプロフィットのレベルは、ローソク足の高値と安値に対して評価され、バー内トリガーを近似し、完了したバーの価格を監視した MQL エキスパートの行動と一致します。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Envelope MA Short: EMA band reversion with ATR stops.
/// </summary>
public class EnvelopeMaShortStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _bandPercent;
private decimal _entryPrice;
public EnvelopeMaShortStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "EMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
_bandPercent = Param(nameof(BandPercent), 1.0m)
.SetDisplay("Band %", "Band width percent.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
public decimal BandPercent { get => _bandPercent.Value; set => _bandPercent.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
if (atrVal <= 0 || emaVal <= 0) return;
var close = candle.ClosePrice;
var factor = BandPercent / 100m;
var upper = emaVal * (1m + factor);
var lower = emaVal * (1m - factor);
if (Position > 0)
{
if (close >= emaVal || close <= _entryPrice - atrVal * 1.5m) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if (close <= emaVal || close >= _entryPrice + atrVal * 1.5m) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (close < lower) { _entryPrice = close; BuyMarket(); }
else if (close > upper) { _entryPrice = close; 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.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class envelope_ma_short_strategy(Strategy):
def __init__(self):
super(envelope_ma_short_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "EMA period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._band_percent = self.Param("BandPercent", 1.0) \
.SetDisplay("Band %", "Band width percent.", "Indicators")
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
@property
def BandPercent(self):
return self._band_percent.Value
def OnStarted2(self, time):
super(envelope_ma_short_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
ev = float(ema_val)
av = float(atr_val)
if av <= 0 or ev <= 0:
return
close = float(candle.ClosePrice)
factor = float(self.BandPercent) / 100.0
upper = ev * (1.0 + factor)
lower = ev * (1.0 - factor)
if self.Position > 0:
if close >= ev or close <= self._entry_price - av * 1.5:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close <= ev or close >= self._entry_price + av * 1.5:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if close < lower:
self._entry_price = close
self.BuyMarket()
elif close > upper:
self._entry_price = close
self.SellMarket()
def OnReseted(self):
super(envelope_ma_short_strategy, self).OnReseted()
self._entry_price = 0.0
def CreateClone(self):
return envelope_ma_short_strategy()