GitHub で見る
X MAN 戦略
概要
X MAN 戦略は、StockSharp の高レベル API 内に MetaTrader エキスパート アドバイザ X_MAN.mq4 のコア ロジックを再作成します。このシステムは、マルチタイムフレームのモメンタムと毎月の MACD 確認でエントリーをフィルタリングしながら、高速および低速の線形加重移動平均 (LWMA) によって駆動されるブレイクアウトをトレードします。勢いとトレンド構造が一致した場合にのみトリガーされるトレンド継続トレード向けに設計されています。
取引ロジック
- プライマリ トレンド フィルター – 選択したプライマリ タイムフレームで計算された 2 つの LWMA は、少なくとも構成可能な
DistancePoints で区切られている必要があります。長いセットアップでは、高速 LWMA が低速 LWMA よりもそのマージンだけ上にある必要がありますが、短いセットアップでは低速 LWMA が優位になる必要があります。
- モメンタムの確認 – この戦略は、より高いタイムフレームのローソク足シリーズをサブスクライブし、それをモメンタム指標にフィードします。その方向で取引できるようにするには、中立値 (100) からの最後の 3 つのモメンタム測定値の絶対距離が、対応する買いまたは売りのしきい値を少なくとも 1 回超える必要があります。
- MACD フィルター – 毎月のローソク足シリーズは標準 (12、26、9) MACD を駆動します。ロングトレードは、MACD ラインがシグナルラインよりも上にある場合にのみ許可され、ショートトレードではその逆の関係が必要です。
- 注文執行 – すべてのフィルターが一致すると、ストラテジーは成行注文を使用して入力されます。ポジションは、反対のセットアップが表示され、現在のポジションがフラットまたは反対方向にある場合にのみ反転されます。
パラメーター
| パラメータ |
説明 |
CandleType |
LWMA 計算に使用されるプライマリ タイムフレーム。 |
HigherCandleType |
モメンタムフィルターに供給されるより高いタイムフレーム。 |
MacdCandleType |
MACD 確認の期間(デフォルトでは毎月)。 |
FastMaPeriod |
高速 LWMA の長さ。 |
SlowMaPeriod |
低速 LWMA の長さ。 |
MomentumPeriod |
モーメントオシレーターのルックバックウィンドウ。 |
MomentumBuyThreshold |
強気の勢いに必要な 100 からの最小距離。 |
MomentumSellThreshold |
弱気の勢いに必要な 100 からの最小距離。 |
DistancePoints |
価格帯で表される高速 LWMA と低速 LWMA 間の最小限の分離。 |
TakeProfitPoints |
オプションの保護テイクプロフィットディスタンス(ポイント単位)。 |
StopLossPoints |
オプションの保護ストップロス距離 (ポイント単位)。 |
すべてのパラメータは StrategyParam<T> を通じて公開されるため、StockSharp デザイナー内で最適化したり、実行時に構成したりできます。
リスク管理
TakeProfitPoints または StopLossPoints のいずれかがゼロより大きい場合、戦略は市場出口を使用して StockSharp の組み込み保護モジュールを有効にします。元の MQL エキスパートによる追加のトレーリング ロジックや損益分岐点ロジックはまだ実装されていません。
オリジナルエキスパートとの違い
- MetaTrader の実装は、株式ストップ、損益分岐点移動、複雑な資金管理オプションを処理しました。この変換は、コアの指向性フィルターと市場参入に焦点を当てています。ポートフォリオレベルの資金管理は意図的に省略されています。
- 注文のサイジングはホスティング環境に委任されます。元のロット指数ロジックは再現されません。
- アラート、電子メール通知、および手動によるトレーリングストップの変更は含まれません。
これらの変更により、主要な取引概念を維持しながら、戦略が簡潔になり、StockSharp のハイレベルな API が活用されます。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// X-MAN strategy: Stochastic + SMA trend filter.
/// </summary>
public class XManStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaPeriod;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public XManStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var rsi = new RelativeStrengthIndex { Length = 14 };
decimal? prevClose = null;
decimal? prevSma = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, rsi, (candle, smaVal, rsiVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (prevClose.HasValue && prevSma.HasValue)
{
var crossUp = prevClose.Value <= prevSma.Value && close > smaVal;
var crossDown = prevClose.Value >= prevSma.Value && close < smaVal;
if (crossUp && rsiVal < 70 && Position <= 0)
BuyMarket();
else if (crossDown && rsiVal > 30 && Position >= 0)
SellMarket();
}
prevClose = close;
prevSma = smaVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
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 SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class x_man_strategy(Strategy):
def __init__(self):
super(x_man_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA period", "Indicators")
self._sma = None
self._rsi = None
self._prev_close = None
self._prev_sma = None
@property
def sma_period(self):
return self._sma_period.Value
def OnReseted(self):
super(x_man_strategy, self).OnReseted()
self._sma = None
self._rsi = None
self._prev_close = None
self._prev_sma = None
def OnStarted2(self, time):
super(x_man_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = self.sma_period
self._rsi = RelativeStrengthIndex()
self._rsi.Length = 14
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._sma, self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, sma_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed or not self._rsi.IsFormed:
return
close = float(candle.ClosePrice)
sma_val = float(sma_value)
rsi_val = float(rsi_value)
if self._prev_close is not None and self._prev_sma is not None:
cross_up = self._prev_close <= self._prev_sma and close > sma_val
cross_down = self._prev_close >= self._prev_sma and close < sma_val
if cross_up and rsi_val < 70.0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and rsi_val > 30.0 and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_sma = sma_val
def CreateClone(self):
return x_man_strategy()