S7 Up Bot 策略
基于突破的系统,寻找相近的高点或低点后出现的快速价格移动。
当连续两个低点几乎相等且价格上升 Span Price 时开多单。
当连续两个高点几乎相等且价格下降 Span Price 时做空。
仓位可通过止盈、止损、跟踪止损及提前退出进行保护。
细节
- 入场条件:
- 做多: 当前低点与前一个低点差值小于
HL Divergence,且价格高于低点Span Price。 - 做空: 当前高点与前一个高点差值小于
HL Divergence,且价格低于高点Span Price。
- 做多: 当前低点与前一个低点差值小于
- 多空方向: 双向。
- 出场条件:
- 止盈或止损。
- 跟踪止损或移动到保本位。
- 当价格突破前高/前低(
Exit At Extremum)或靠近反向水平(Exit At Reversal)时提前退出。
- 止损机制: 绝对止盈和止损,可选跟踪。
- 过滤器: 无。
参数
Take Profit– 以价格单位表示的止盈。Stop Loss– 以价格单位表示的止损,0 表示自动计算。HL Divergence– 连续高/低点允许的最大差值。Span Price– 从极值到价格的距离要求。Max Trades– 同时允许的最大交易数。Use Trailing Stop– 启用跟踪止损。Trail Stop– 跟踪止损距离。Zero Trailing– 当出现盈利时移动止损。Step Trailing– 调整保本止损的最小步长。Exit At Extremum– 当价格突破前高或前低时退出。Exit At Reversal– 当价格接近反向水平时退出。Span To Revers– 触发反向退出的距离。Candle Type– 分析所用的时间框架。Order Volume– 每笔交易的数量。
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;
/// <summary>
/// S7 Up Bot breakout strategy.
/// Opens long after double bottom and short after double top.
/// </summary>
public class S7UpBotStrategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _hlDivergence;
private readonly StrategyParam<decimal> _spanPrice;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevLow;
private decimal _prevHigh;
private decimal _entryPrice;
private decimal _stopPrice;
private decimal _takeProfitPrice;
private bool _isLong;
private bool _inPosition;
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal HlDivergence { get => _hlDivergence.Value; set => _hlDivergence.Value = value; }
public decimal SpanPrice { get => _spanPrice.Value; set => _spanPrice.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public S7UpBotStrategy()
{
_takeProfit = Param(nameof(TakeProfit), 500m)
.SetDisplay("Take Profit", "Absolute take profit", "Risk");
_stopLoss = Param(nameof(StopLoss), 300m)
.SetDisplay("Stop Loss", "Absolute stop loss", "Risk");
_hlDivergence = Param(nameof(HlDivergence), 100m)
.SetGreaterThanZero()
.SetDisplay("HL Divergence", "Max difference between highs or lows", "General");
_spanPrice = Param(nameof(SpanPrice), 50m)
.SetGreaterThanZero()
.SetDisplay("Span Price", "Distance from extreme to price", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Time frame for analysis", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevLow = 0m;
_prevHigh = 0m;
_entryPrice = 0m;
_stopPrice = 0m;
_takeProfitPrice = 0m;
_isLong = false;
_inPosition = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevLow = 0m;
_prevHigh = 0m;
_inPosition = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var price = candle.ClosePrice;
if (_inPosition)
ManagePosition(candle, price);
if (!_inPosition && _prevLow != 0m && _prevHigh != 0m)
CheckEntry(candle, price);
_prevLow = candle.LowPrice;
_prevHigh = candle.HighPrice;
}
private void CheckEntry(ICandleMessage candle, decimal price)
{
// Double bottom: consecutive similar lows + bounce
if (Math.Abs(candle.LowPrice - _prevLow) < HlDivergence &&
price - candle.LowPrice > SpanPrice)
{
if (Position <= 0)
BuyMarket();
_inPosition = true;
_isLong = true;
_entryPrice = price;
_stopPrice = price - StopLoss;
_takeProfitPrice = price + TakeProfit;
}
// Double top: consecutive similar highs + drop
else if (Math.Abs(candle.HighPrice - _prevHigh) < HlDivergence &&
candle.HighPrice - price > SpanPrice)
{
if (Position >= 0)
SellMarket();
_inPosition = true;
_isLong = false;
_entryPrice = price;
_stopPrice = price + StopLoss;
_takeProfitPrice = price - TakeProfit;
}
}
private void ManagePosition(ICandleMessage candle, decimal price)
{
if (_isLong)
{
if (candle.HighPrice >= _takeProfitPrice || candle.LowPrice <= _stopPrice)
{
SellMarket();
_inPosition = false;
}
}
else
{
if (candle.LowPrice <= _takeProfitPrice || candle.HighPrice >= _stopPrice)
{
BuyMarket();
_inPosition = false;
}
}
}
}
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.Strategies import Strategy
class s7_up_bot_strategy(Strategy):
def __init__(self):
super(s7_up_bot_strategy, self).__init__()
self._take_profit = self.Param("TakeProfit", 500.0) \
.SetDisplay("Take Profit", "Absolute take profit", "Risk")
self._stop_loss = self.Param("StopLoss", 300.0) \
.SetDisplay("Stop Loss", "Absolute stop loss", "Risk")
self._hl_divergence = self.Param("HlDivergence", 100.0) \
.SetDisplay("HL Divergence", "Max difference between highs or lows", "General")
self._span_price = self.Param("SpanPrice", 50.0) \
.SetDisplay("Span Price", "Distance from extreme to price", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Time frame for analysis", "General")
self._prev_low = 0.0
self._prev_high = 0.0
self._entry_price = 0.0
self._stop_price = 0.0
self._take_profit_price = 0.0
self._is_long = False
self._in_position = False
@property
def take_profit(self):
return self._take_profit.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def hl_divergence(self):
return self._hl_divergence.Value
@property
def span_price(self):
return self._span_price.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(s7_up_bot_strategy, self).OnReseted()
self._prev_low = 0.0
self._prev_high = 0.0
self._entry_price = 0.0
self._stop_price = 0.0
self._take_profit_price = 0.0
self._is_long = False
self._in_position = False
def OnStarted2(self, time):
super(s7_up_bot_strategy, self).OnStarted2(time)
self._prev_low = 0.0
self._prev_high = 0.0
self._in_position = False
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
if self._in_position:
self._manage_position(candle, price)
if not self._in_position and self._prev_low != 0.0 and self._prev_high != 0.0:
self._check_entry(candle, price, high, low)
self._prev_low = low
self._prev_high = high
def _check_entry(self, candle, price, high, low):
hl_div = float(self.hl_divergence)
span = float(self.span_price)
tp = float(self.take_profit)
sl = float(self.stop_loss)
# Double bottom
if abs(low - self._prev_low) < hl_div and price - low > span:
if self.Position <= 0:
self.BuyMarket()
self._in_position = True
self._is_long = True
self._entry_price = price
self._stop_price = price - sl
self._take_profit_price = price + tp
# Double top
elif abs(high - self._prev_high) < hl_div and high - price > span:
if self.Position >= 0:
self.SellMarket()
self._in_position = True
self._is_long = False
self._entry_price = price
self._stop_price = price + sl
self._take_profit_price = price - tp
def _manage_position(self, candle, price):
high = float(candle.HighPrice)
low = float(candle.LowPrice)
if self._is_long:
if high >= self._take_profit_price or low <= self._stop_price:
self.SellMarket()
self._in_position = False
else:
if low <= self._take_profit_price or high >= self._stop_price:
self.BuyMarket()
self._in_position = False
def CreateClone(self):
return s7_up_bot_strategy()