首页
/
策略示例
在 GitHub 上查看
Plan X 突破策略
Plan X 突破策略复刻了 Peter Ingram 编写的 MetaTrader 智能交易系统“plan x”。策略专注于欧洲上午时段,跟踪 15 分钟 K 线。当会话开始时记录一根参考蜡烛的收盘价,随后等待价格向上或向下突破指定的点数,并只持有一个净头寸。止损与跟踪止损均按点数计算,以控制风险。
交易逻辑
会话锚点
使用 15 分钟蜡烛。
在会话起始小时(默认 11:00)记录该蜡烛的收盘价,作为当天剩余时间的锚点价格。
只有在至少再收出一根蜡烛之后且会话结束之前(默认 15:00)才会寻找信号。
入场条件
做多 :最新一根完成的蜡烛收盘价高于锚点价格 LongTargetPips(默认 25 点)以上,且当前没有持仓。
做空 :最新一根完成的蜡烛收盘价低于锚点价格 ShortTargetPips(默认 20 点)以下,且当前没有持仓。
所有比较都基于按合约最小变动和小数位数推算出的点值。
仓位管理
开仓后立即设置 InitialStopPips(默认 25 点)的固定止损。
当浮动盈利达到 TrailTriggerPips(默认 10 点)时,止损开始跟踪价格。
之后每当价格再前进 TrailTriggerPips,止损就按照 TrailStepPips(默认 5 点)向盈利方向移动。
一旦价格触发止损,立即以市价单平仓。
下单手数
市价单的手数由 TradeVolume(默认 0.1 手)参数决定,可根据交易标的调整。
参数
名称
说明
默认值
TradeVolume
入场与平仓使用的市价单手数。
0.1
LongTargetPips
做多信号相对锚点需要突破的点数。
25
ShortTargetPips
做空信号相对锚点需要突破的点数。
20
InitialStopPips
入场价到保护性止损的距离。
25
TrailTriggerPips
触发或推动跟踪止损所需的盈利点数。
10
TrailStepPips
跟踪止损每次移动的点数。
5
SessionStartHour
会话开始时间,使用十进制小时(例如 11.5 = 11:30)。
11.0
SessionEndHour
会话结束时间,必须大于 SessionStartHour。
15.0
CandleType
用于评估的蜡烛类型,默认 15 分钟。
15 分钟
说明
点值根据标的的 PriceStep 与小数位自动计算(3 或 5 位小数会乘以 10)。
每个交易日都会重新确定锚点价格;若标的存在跳空,请注意价差变化。
StockSharp 使用净持仓模式,因此策略一次只会持有一个方向,与原始策略在未启用对冲时的行为一致。
文件
CS/PlanXBreakoutStrategy.cs – StockSharp 平台上 Plan X 策略的 C# 实现。
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Plan X Breakout strategy using highest high / lowest low channel breakout.
/// Buy when price breaks above the highest high of the lookback period.
/// Sell when price breaks below the lowest low of the lookback period.
/// </summary>
public class PlanXBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _lookback;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PlanXBreakoutStrategy()
{
_lookback = Param(nameof(Lookback), 20)
.SetDisplay("Lookback", "Channel lookback period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0m;
_prevLow = 0m;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var highestHigh = new Highest { Length = Lookback };
var lowestLow = new Lowest { Length = Lookback };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highestHigh, lowestLow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevHigh = highest;
_prevLow = lowest;
_hasPrev = true;
return;
}
// Breakout above previous highest high
if (Position <= 0 && candle.ClosePrice > _prevHigh)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Breakout below previous lowest low
else if (Position >= 0 && candle.ClosePrice < _prevLow)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevHigh = highest;
_prevLow = lowest;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class plan_x_breakout_strategy(Strategy):
"""Plan X Breakout strategy using highest high / lowest low channel breakout.
Buy when price breaks above the highest high of the lookback period.
Sell when price breaks below the lowest low of the lookback period."""
def __init__(self):
super(plan_x_breakout_strategy, self).__init__()
self._lookback = self.Param("Lookback", 20) \
.SetDisplay("Lookback", "Channel lookback period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_high = 0.0
self._prev_low = 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 Lookback(self):
return self._lookback.Value
def OnReseted(self):
super(plan_x_breakout_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(plan_x_breakout_strategy, self).OnStarted2(time)
self._has_prev = False
highest = Highest()
highest.Length = self.Lookback
lowest = Lowest()
lowest.Length = self.Lookback
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._process_candle).Start()
def _process_candle(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
high_val = float(highest)
low_val = float(lowest)
close = float(candle.ClosePrice)
if not self._has_prev:
self._prev_high = high_val
self._prev_low = low_val
self._has_prev = True
return
# Breakout above previous highest high
if self.Position <= 0 and close > self._prev_high:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Breakout below previous lowest low
elif self.Position >= 0 and close < self._prev_low:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_high = high_val
self._prev_low = low_val
def CreateClone(self):
return plan_x_breakout_strategy()