GitHub で見る
シンプルな巻き込み戦略
概要
Simple Engulfing Strategy は、MetaTrader 4 人の専門家「simple engulf mt4 buy」と「simple engulf mt4 sell」の動作を再現します。どちらの専門家も、ローソク足の巻き込みパターンを検出し、一方向に取引を開始します。 StockSharp ポートは両方のアドバイザーを 1 つの構成可能な戦略に統合するため、トレーダーは元の買いのみ、売りのみ、または組み合わせた動作を StockSharp フレームワーク内で再現できます。
このストラテジーは完了したローソク足のみをリッスンし、MetaTrader バージョンで使用されるバークローズ実行スタイルと一致します。すべての注文では、StockSharp コーディング ガイドラインに準拠するために、高レベルの StockSharp API (SubscribeCandles、Bind、BuyMarket、SellMarket、および StartProtection) が使用されます。
取引ロジック
- 構成された
CandleType に基づいてキャンドルを作成します。
- 現在のキャンドルが終了するまで待ち、以前に完了したキャンドルをメモリに保持します。
- 現在のローソク体のサイズをピップ単位で計算します。
MinBodyPips 未満または MaxBodyPips を超える場合、パターンを拒否します (最大フィルターが正の値で有効になっている場合)。
- 次の場合に 強気の巻き込み パターンを検出します。
- 前のローソク足は弱気です(始値を下回る終値)。
- 現在のローソク足は強気です(終値が始値を上回っている)。
- 現在の始値は前回の終値以下です。
- 現在の終値は前回の始値以上です。
- ミラー条件を使用して 弱気の巻き込み パターンを検出します。
- 有効なパターンが表示されたら、自動取引が許可されていること (
IsFormedAndOnlineAndAllowTrading()) と、設定された方向で取引が許可されていることを確認してください。
BuyOnly は「simple engulf mt4 buy」ロボットを複製します。
SellOnly は、「simple engulf mt4 sell」ロボットを複製します。
Both により、双方向取引が可能になります。
- すべてのエントリに構成済みの
TradeVolume を使用します。ストラテジーが現在反対側に位置している場合、ポジションをクローズし、絶対ポジション サイズをエントリー注文に追加することで反転し、ショートからロングに切り替えるときの MetaTrader の動作と一致します (またはその逆)。
- オプションのストップロスとテイクプロフィットのレベルは、価格ベースの単位を使用して
StartProtection を通じて適用されます。彼らは、StockSharp が元の専門家と同じ方法で保護注文を管理できるように、ピップ距離を商品価格の増分に変換します。
パラメーター
| 名前 |
デフォルト |
説明 |
CandleType |
TimeFrame(15 minutes) |
パターンの検出に使用されるローソクのタイプと集計間隔。 |
TradeVolume |
0.01 |
エントリごとの注文量は、MetaTrader の専門家と同じです。 |
StopLossPips |
20 |
ピップスで表されるストップロス距離。保護命令を無効にするには、0 に設定します。 |
TakeProfitPips |
20 |
ピップスで表されるテイクプロフィット距離。保護命令を無効にするには、0 に設定します。 |
MinBodyPips |
0 |
有効な飲み込みパターンに必要な最小キャンドル本体 (ピップ単位)。 |
MaxBodyPips |
50 |
有効な飲み込みパターンで許可されるローソク足の最大値 (ピップ単位)。 0 を使用して上部フィルターを取り外します。 |
Direction |
BuyOnly |
元のアドバイザーのどちら側を実行するかを定義します (BuyOnly、SellOnly、または Both)。 |
実用上の注意
- ピップサイズは、商品の
PriceStep と小数点以下の桁数を分析することにより、取引される商品に自動的に適応します。これにより、pip フィルターと保護注文が 4 桁と 5 桁の両方の外国為替記号の MetaTrader 入力と同様に動作することが保証されます。
- 保護命令は、
StopLossPips または TakeProfitPips が陽性の場合にのみ送信されます。それ以外の場合、戦略は出口を裁量管理または他の自動化モジュールに任せます。
- この戦略はローソク足が完全に終了するまで待機するため、各バーの終了時にシグナルが生成され、バー内の再描画が回避されます。
- 高レベルの API 呼び出しは実装を簡潔に保ち、手動の注文処理よりも既製の StockSharp コンポーネントを優先するというプロジェクト ガイドラインに従います。
オリジナルとの違い
- 両方の MetaTrader アドバイザーは、2 つの個別のファイルではなく、
Direction パラメータを使用して 1 つの戦略に結合されます。
- StockSharp のロギングおよびチャート ヘルパー (オプションのローソク足およびトレード プロット) が追加され、StockSharp ターミナル内で実行する際の視認性が向上しました。
- リスク管理は、StockSharp の
StartProtection ヘルパーを使用します。これは、StockSharp エンジンを介してストップロス注文とテイクプロフィット注文を内部で管理します。結果として生じる動作は、MetaTrader でハード ストップを使用した場合と同等です。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Simple Engulfing strategy: engulfing candlestick pattern with EMA filter.
/// Buys on bullish engulfing above EMA, sells on bearish engulfing below EMA.
/// </summary>
public class SimpleEngulfingStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private decimal _prevOpen;
private decimal _prevClose;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public SimpleEngulfingStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevOpen = 0;
_prevClose = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
var prevBearish = _prevClose < _prevOpen;
var currBullish = candle.ClosePrice > candle.OpenPrice;
var bullishEngulf = prevBearish && currBullish
&& candle.OpenPrice <= _prevClose && candle.ClosePrice >= _prevOpen;
var prevBullish = _prevClose > _prevOpen;
var currBearish = candle.ClosePrice < candle.OpenPrice;
var bearishEngulf = prevBullish && currBearish
&& candle.OpenPrice >= _prevClose && candle.ClosePrice <= _prevOpen;
if (bullishEngulf && candle.ClosePrice > emaValue && Position <= 0)
BuyMarket();
else if (bearishEngulf && candle.ClosePrice < emaValue && Position >= 0)
SellMarket();
}
_prevOpen = candle.OpenPrice;
_prevClose = candle.ClosePrice;
_hasPrev = true;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class simple_engulfing_strategy(Strategy):
def __init__(self):
super(simple_engulfing_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._ema_period = self.Param("EmaPeriod", 50)
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
def OnReseted(self):
super(simple_engulfing_strategy, self).OnReseted()
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(simple_engulfing_strategy, self).OnStarted2(time)
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
ema_val = float(ema_value)
if self._has_prev:
prev_bearish = self._prev_close < self._prev_open
curr_bullish = close > open_price
bullish_engulf = (prev_bearish and curr_bullish and
open_price <= self._prev_close and close >= self._prev_open)
prev_bullish = self._prev_close > self._prev_open
curr_bearish = close < open_price
bearish_engulf = (prev_bullish and curr_bearish and
open_price >= self._prev_close and close <= self._prev_open)
if bullish_engulf and close > ema_val and self.Position <= 0:
self.BuyMarket()
elif bearish_engulf and close < ema_val and self.Position >= 0:
self.SellMarket()
self._prev_open = open_price
self._prev_close = close
self._has_prev = True
def CreateClone(self):
return simple_engulfing_strategy()