GitHub で見る
Wedge Pattern戦略
概要
Wedge Pattern戦略は、MetaTraderエキスパートアドバイザー Wedge pattern.mq4 をStockSharp高レベルAPIへ変換したものです。Bill Williamsフラクタルから得た対称的なウェッジ型保ち合いを探し、トレンドとモメンタムフィルターが一致したときにブレイクアウトを取引します。
高レベル実装は、元の手動注文管理をStockSharp機能で置き換えつつ、判断ロジックを保持します。
- トレンドフィルター: 典型価格で計算した高速/低速の線形加重移動平均(LWMA)を比較します。
- モメンタムフィルター: 14期間モメンタム指標の中立レベル(100)からの絶対距離を評価します。直近3つのモメンタム値が設定しきい値を超える必要があります。
- MACD確認: ロングではMACDメインラインがシグナルラインを上回ること(ショートでは下回ること)を要求します。
- フラクタルウェッジ検出: 上下のフラクタル点を集めて収束するトレンドラインを構築します。価格がこれらのラインを設定可能な確認バッファー分だけ超えて閉じると、取引シグナルが生成されます。
- リスク管理: 固定ストップロス/テイクプロフィット距離、自動ブレイクイーブン移動、トレーリングストップ調整によりMQL実装を模倣します。
仕組み
CandleTypeパラメーターで定義された単一時間軸を購読します。
- 各確定ローソク足で指標値を更新し、高値/安値のローリングバッファーを維持して新しいフラクタルを検出します。
- 直近2つの高値/安値フラクタルからウェッジのトレンドラインを構築します。収束ウェッジ(高値切り下げと安値切り上げ)のみを有効なセットアップと見なします。
- ロングは次の条件で開かれます。
- 高速LWMA > 低速LWMA。
- MACDライン > シグナルライン。
- 直近3つのモメンタム値のいずれかが設定しきい値を超える。
- 現在のローソク足が、少なくともブレイクアウトバッファー分だけ予測上側トレンドラインの上で閉じる。
- ショートは、ラインとしきい値を反転した条件です。
- エントリー後、戦略はただちにストップロスとテイクプロフィット注文を置きます。その後、ポジションが利益化するとストップをブレイクイーブンへ移動し、トレーリングできます。
パラメーター
| パラメーター |
説明 |
CandleType |
分析と注文に使う時間軸。 |
FastMaPeriod |
高速LWMAフィルターの長さ。 |
SlowMaPeriod |
低速LWMAフィルターの長さ。 |
MomentumPeriod |
モメンタム指標のルックバック期間(既定14)。 |
MomentumThreshold |
市場を衝動的と見なすため、モメンタム指標に必要な100からの最小距離。 |
MacdFastPeriod / MacdSlowPeriod / MacdSignalPeriod |
標準MACD設定。 |
FractalDepth |
フラクタル高値/安値を確認するために各側に必要なバー数。 |
StopLossPips |
初期保護ストップ距離(pips)。 |
TakeProfitPips |
初期利益目標距離(pips)。 |
UseBreakeven, BreakevenTriggerPips, BreakevenOffsetPips |
ブレイクイーブン自動化を有効化し設定します。 |
UseTrailing, TrailingActivationPips, TrailingDistancePips, TrailingStepPips |
トレーリングストップ動作を有効化し設定します。 |
BreakoutBufferPips |
ウェッジブレイクアウト確認に適用する追加バッファー。 |
すべてのpipベース設定は、銘柄のティックサイズを使って価格距離へ変換されます。既定のpip計算は、元のExpert Advisorと同じく小数価格(3桁または5桁)を考慮します。
使用ガイド
- 戦略を希望する銘柄へ接続し、元のセットアップに合うローソク足時間軸(例: 15分足)を選択します。
- 基底
Strategy.Volumeプロパティでポジションサイズを設定します。
- 必要に応じて、対象市場のボラティリティに合わせてフィルターとリスクパラメーターを調整します。
- 戦略を開始します。ローソク足を購読し、チャートデータを描画し、ウェッジブレイクアウトが発生すると自動的に取引します。
MQL版との差異
- StockSharp版は高レベルの
SubscribeCandlesと指標バインディングAPIを使い、手動ティック処理を避けます。
- トレーリングストップとブレイクイーブン管理は
SetStopLoss/SetTakeProfitに依存し、組み込み保護動作と統合されます。
- 一度に1つのポジションのみを維持します。MetaTraderスクリプトは最大取引数までのピラミッディングをサポートしていました。
- アラート、メール、通知機能は省略されています。必要な場合、イベント処理は外部で実装してください。
これらの適応にもかかわらず、中核エントリーロジックと保護ルールは、StockSharpらしいパターンを使いながら元のMetaTraderエキスパートに密接に従っています。
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Wedge Pattern strategy: WMA crossover + Momentum.
/// Buys when fast WMA crosses above slow WMA and momentum > 100.
/// Sells on cross below with momentum < 100.
/// </summary>
public class WedgePatternStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _momPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public int MomPeriod
{
get => _momPeriod.Value;
set => _momPeriod.Value = value;
}
public WedgePatternStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 40)
.SetGreaterThanZero()
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
_momPeriod = Param(nameof(MomPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Momentum", "Momentum period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new WeightedMovingAverage { Length = FastPeriod };
var slow = new WeightedMovingAverage { Length = SlowPeriod };
var mom = new Momentum { Length = MomPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, mom, (candle, fastVal, slowVal, momVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && momVal > 100m && Position <= 0)
BuyMarket();
else if (crossDown && momVal < 100m && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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 WeightedMovingAverage, Momentum
from StockSharp.Algo.Strategies import Strategy
class wedge_pattern_strategy(Strategy):
def __init__(self):
super(wedge_pattern_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 40) \
.SetGreaterThanZero() \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._mom_period = self.Param("MomPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("Momentum", "Momentum period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(wedge_pattern_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(wedge_pattern_strategy, self).OnStarted2(time)
self._fast_ind = WeightedMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = WeightedMovingAverage()
self._slow_ind.Length = self._slow_period.Value
self._mom_ind = Momentum()
self._mom_ind.Length = self._mom_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._mom_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value, mom_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
mom_val = float(mom_value)
if self._prev_fast is not None and self._prev_slow is not None:
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and mom_val > 100.0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and mom_val < 100.0 and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return wedge_pattern_strategy()