GitHub で見る
MAブレイク衝動買い戦略
概要
この戦略は、StockSharp の高レベルの API を使用して「M.A ブレーク mt4 購入」エキスパート アドバイザーを再現します。静かな保ち合いの後に強い強気のブレイクアウトを特定することに重点を置いています。エントリー ロジックは、一連の指数移動平均 (EMA) フィルター、静かな市場フェーズ、そしてブレイクアウト EMA と相互作用する強力な強気インパルス ローソク足を探します。この戦略は ロング ポジションのみをオープンします。
取引ロジック
- EMA トレンド フィルター
- 2 つの EMA ペアは、以前に完了したローソク足 (
shift = 1) で評価されます。
EMA(FirstFastPeriod) は EMA(FirstSlowPeriod) より大きくなければなりません。
EMA(SecondFastPeriod) は EMA(SecondSlowPeriod) より大きくなければなりません。
- インパルスキャンドルの選択
- インパルスローソク足は、最後に完了したバー (シフト 1) です。
- 始値は
TrendMaPeriod EMA を超える必要があります。
- その最低値は、
BreakoutMaPeriod EMA に達するか、それを下回る必要があります。
- ローソク足は強気でなければなりません (
Close > Open)。
- ローソク足の範囲は
CandleMinSize と CandleMaxSize の間にある必要があります (Security.PriceStep を使用してピップから変換)。
- 上部の芯はキャンドル範囲の
UpperWickLimit パーセントを超えてはなりません。下の芯は範囲の少なくとも LowerWickFloor パーセントでなければなりません。
- 静かなバーと衝撃強度
- この戦略は、インパルスローソク足に先行する
QuietBarsCount ローソク足 (シフト ≥ 2) をスキャンし、最大高値と安値の範囲を記録します。
- このクワイエットレンジは、
QuietBarsMinRange (pips → 価格) より大きくなければなりません。
- インパルス キャンドルの本体 (
Close - Open) は少なくとも ImpulseStrength × quietRange でなければなりません。
- ポジション管理
- すべての条件が満たされ、現在オープンなポジションがない場合、成行買い注文が送信されます。
- プロテクティブなストップロス注文とテイクプロフィット注文は、
Security.PriceStep 経由で変換された pip 入力を使用して、StartProtection を通じて管理されます。
パラメーター
| 名前 |
デフォルト |
説明 |
FirstFastPeriod |
20 |
最初のトレンド フィルターで使用される高速 EMA。 |
FirstSlowPeriod |
30 |
最初のトレンド フィルターで使用される遅い EMA。 |
SecondFastPeriod |
30 |
2 番目のトレンド フィルターの高速 EMA。 |
SecondSlowPeriod |
50 |
2 番目のトレンド フィルターでは EMA が遅いです。 |
TrendMaPeriod |
30 |
インパルスローソクのオープンが超える必要がある EMA。 |
BreakoutMaPeriod |
20 |
インパルスローソク足が触れなければならないEMA。 |
QuietBarsCount |
2 |
インパルスが評価される前の穏やかなキャンドルの数。 |
QuietBarsMinRange |
0.0 |
最小静音範囲 (pips)。 |
ImpulseStrength |
1.1 |
インパルスボディのサイズを検証するために静かな範囲に適用される乗数。 |
UpperWickLimit |
100.0 |
ろうそくの範囲のパーセントとしての最大上芯。 |
LowerWickFloor |
0.0 |
キャンドル範囲のパーセントとしての最小下芯。 |
CandleMinSize |
0.0 |
インパルスローソク足の最小許容範囲(ピップ単位)。 |
CandleMaxSize |
100.0 |
インパルスローソク足の最大許容範囲(ピップ単位)。 |
VolumeSize |
0.01 |
BuyMarket で送信された取引量。 VolumeStep を交換するために正規化されました。 |
StopLossPips |
20.0 |
ピップ単位のストップロス距離 (PriceStep で変換)。 |
TakeProfitPips |
20.0 |
利益確定距離 (ピップ単位) (PriceStep で変換)。 |
CandleType |
15分の時間枠 |
コネクタから要求されたキャンドルのデータ型。 |
実装メモ
- この戦略では、StockSharp の高レベルの
Bind サブスクリプションを使用して、インジケーターの計算をローソク足の更新と同期させます。
- すべての計算は完成したキャンドル (
CandleStates.Finished) のみに依存します。
- クワイエットレンジフィルターとローソクサイズフィルターは、
Security.PriceStep を使用して pip 値を価格単位に内部的に変換します。機器が PriceStep をレポートしない場合は、pip 値を乗算する MQL ロジックと一致する、1 のフォールバックが使用されます。
StartProtection は OnStarted 中に 1 回アクティブ化されるため、すべての新しいポジションは設定されたストップロスとテイクプロフィットを受け取ります。
- ローソク足履歴バッファーは、沈黙期間とインパルスローソク足を効率的に評価するために、最後の
QuietBarsCount + 3 エントリのみを保持します。
使用のヒント
- ピップと音量の変換が正確に保たれるように、接続された機器が
PriceStep、VolumeStep、および音量制限を提供していることを確認してください。
- EMA 期間とインパルスパラメータを商品のボラティリティに合わせて調整します。
ImpulseStrength を低くすると小さなブレイクアウトに反応し、値を高くすると最も強力な動きのみがフィルターされます。
- この戦略は、一度に 1 つのオープン ポジションを対象として設計されています。同じ証券に対する外部ポジションにより、新規エントリーが妨げられる場合があります。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MA Break Impulse Buy strategy: EMA crossover with volume surge.
/// Buys on EMA cross up with above-average volume, sells on EMA cross down.
/// </summary>
public class MABreakImpulseBuyStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private decimal _prevClose;
private decimal _prevEma;
private decimal _prevVolume;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public MABreakImpulseBuyStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_prevEma = 0;
_prevVolume = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_prevEma = 0;
_prevVolume = 0;
_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 volumeUp = candle.TotalVolume > _prevVolume;
if (_prevClose <= _prevEma && candle.ClosePrice > emaValue && volumeUp && Position <= 0)
BuyMarket();
else if (_prevClose >= _prevEma && candle.ClosePrice < emaValue && Position >= 0)
SellMarket();
}
_prevClose = candle.ClosePrice;
_prevEma = emaValue;
_prevVolume = candle.TotalVolume;
_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 ma_break_impulse_buy_strategy(Strategy):
def __init__(self):
super(ma_break_impulse_buy_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._prev_close = 0.0
self._prev_ema = 0.0
self._prev_volume = 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(ma_break_impulse_buy_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_ema = 0.0
self._prev_volume = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ma_break_impulse_buy_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_ema = 0.0
self._prev_volume = 0.0
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)
ema_val = float(ema_value)
volume = float(candle.TotalVolume)
if self._has_prev:
volume_up = volume > self._prev_volume
if self._prev_close <= self._prev_ema and close > ema_val and volume_up and self.Position <= 0:
self.BuyMarket()
elif self._prev_close >= self._prev_ema and close < ema_val and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_ema = ema_val
self._prev_volume = volume
self._has_prev = True
def CreateClone(self):
return ma_break_impulse_buy_strategy()