ホーム
/
戦略のサンプル
GitHub で見る
Plan X戦略
概要
Plan X戦略は、元のMetaTrader 5エキスパートアドバイザーから変換されたブレイクアウトシステムです。各完成したローソク足のクローズを、設定可能なバー数だけシフトした参照ローソク足と比較して評価します。最新のクローズが参照クローズを指定のチャンネル高さだけ超えると、戦略はブレイクアウト方向にポジションを開きます。オプションのシグナル反転により、反対方向のブレイクアウトを取引できます。
実装はStockSharpの高水準APIを使用します。調整可能なストップロス、テイクプロフィット、トレーリングストップロジック、および取引セッションフィルターをサポートします。
動作方法
ローソク足処理 – 戦略は設定されたローソク足タイプを購読し、完成したローソク足のみを処理します。シフトされた参照バーと最新値を比較するために、クローズの短い履歴が維持されます。
ブレイクアウト検出 – 最新のクローズがチャンネル高さ以上で参照クローズを超えると、ロングシグナルが生成されます。同じ量だけ下回ると、ショートシグナルが生成されます。反転フラグが有効な場合、シグナルは反転します。
注文実行 – 戦略はマーケット注文を使用します。反対のポジションから反転する場合、注文ボリュームは自動的に現在のポジションの絶対値を含め、1つの操作でフラット化して再エントリーします。
リスク管理 – ストップロスとテイクプロフィットレベルはエントリー直後に設定されます。価格がトレーリング距離にトレーリングステップを加えた量以上で有利に動いた場合、トレーリングストップが元のストップに取って代わることができます。
タイムフィルター – 取引は開始時間と終了時間に制限できます。開始時間が終了時間より大きい場合、ウィンドウは午前0時をまたがるものとして処理されます。
パラメーター
パラメーター
説明
Stop Loss (pips)
インストゥルメントの価格ステップに基づいて価格単位に変換された、pipでの保護ストップ距離。
Take Profit (pips)
pipでのターゲット距離。
Trailing Stop (pips)
価格とトレーリングストップの間の距離。トレーリングを無効にするにはゼロに設定します。
Trailing Step (pips)
トレーリングストップが進む前に必要な追加利益。トレーリングが有効な場合は正の値でなければなりません。
Channel Height (pips)
pipで表したブレイクアウト閾値。
Candle Shift
最新のクローズと参照ローソク足の間のバー数。
Use Time Control
取引セッションフィルターを有効または無効にします。
Start Hour
取引が許可される最初の時間(0〜23)。
End Hour
取引が許可される最後の時間(0〜23)。
Reverse Signals
ブレイクアウト方向を反転します。
Order Volume
ロット/契約で表したマーケット注文サイズ。
Candle Type
分析に使用するローソク足のデータタイプ。
シグナルロジック
ロングエントリー – 最新のクローズ ≥ 参照クローズ + チャンネル高さ、反転無効。
ショートエントリー – 最新のクローズ ≤ 参照クローズ − チャンネル高さ、反転無効。
反転が有効な場合、ロジックはロングとショートの条件を入れ替えます。
トレーリングストップロジック
トレーリングストップは有利な動きが価格でTrailing Stop + Trailing Stepを超えると有効になります。
ロングポジションでは新しい値が既存のストップより高い場合、ストップはhigh − Trailing Stopに移動されます。
ショートポジションでは新しい値が既存のストップより低い場合、ストップはlow + Trailing Stopに移動されます。
追加の注意事項
pip計算は3桁または5桁の小数点を持つインストゥルメントの価格ステップを10倍にするMQLバージョンを模倣します。
許可されたセッション外での取引は新しいエントリーをスキップしますが、開いているポジションは引き続き管理します。
戦略は起動時に一度StartProtection()を呼び出して組み込みポートフォリオ保護サービスを有効にします。
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class PlanXStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public PlanXStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 plan_x_strategy(Strategy):
def __init__(self):
super(plan_x_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(plan_x_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(plan_x_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return plan_x_strategy()