John Bob Trading Bot 策略
结合50根K线高低点与公平价值缺口检测的突破策略。开仓五次,使用ATR止损并设定多个获利目标。
详情
- 入场条件:
- 做多:价格上穿50柱最低价或出现看涨FVG
- 做空:价格下穿50柱最高价或出现看跌FVG
- 多空:双向
- 出场条件:
- 价格到达五个TP之一
- 价格触及ATR止损
- 止损:ATR倍数
- 默认值:
AtrMultiplier= 2mCandleType= TimeSpan.FromMinutes(5).TimeFrame()
- 筛选:
- 分类:Breakout
- 方向:双向
- 指标:ATR、Highest、Lowest
- 止损:有
- 复杂度:中等
- 时间框架:日内
- 季节性:否
- 神经网络:否
- 背离:否
- 风险等级:中
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>
/// Breakout strategy with fair value gap detection and ATR-based stop/target.
/// </summary>
public class JohnBobTradingBotStrategy : Strategy
{
private readonly StrategyParam<decimal> _atrMultiplier;
private readonly StrategyParam<int> _maxEntries;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevHigh;
private decimal _prevLow;
private decimal _prev2High;
private decimal _prev2Low;
private decimal _highestHigh;
private decimal _lowestLow;
private int _barCount;
private decimal _entryPrice;
private decimal _stopPrice;
private decimal _targetPrice;
private int _entriesExecuted;
/// <summary>
/// ATR multiplier for stop-loss calculation.
/// </summary>
public decimal AtrMultiplier
{
get => _atrMultiplier.Value;
set => _atrMultiplier.Value = value;
}
/// <summary>
/// Maximum number of entries for one test run.
/// </summary>
public int MaxEntries
{
get => _maxEntries.Value;
set => _maxEntries.Value = value;
}
/// <summary>
/// Candle type for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="JohnBobTradingBotStrategy"/>.
/// </summary>
public JohnBobTradingBotStrategy()
{
_atrMultiplier = Param(nameof(AtrMultiplier), 2m)
.SetDisplay("ATR Mult", "ATR stop multiplier.", "Risk");
_maxEntries = Param(nameof(MaxEntries), 45)
.SetDisplay("Max Entries", "Maximum entries per run.", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles.", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0m;
_prevHigh = 0m;
_prevLow = 0m;
_prev2High = 0m;
_prev2Low = 0m;
_highestHigh = 0m;
_lowestLow = decimal.MaxValue;
_barCount = 0;
_entryPrice = 0m;
_stopPrice = 0m;
_targetPrice = 0m;
_entriesExecuted = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0m;
_prevHigh = 0m;
_prevLow = 0m;
_prev2High = 0m;
_prev2Low = 0m;
_highestHigh = 0m;
_lowestLow = decimal.MaxValue;
_barCount = 0;
_entryPrice = 0m;
_stopPrice = 0m;
_targetPrice = 0m;
_entriesExecuted = 0;
var atr = new AverageTrueRange { Length = 14 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
_barCount++;
if (candle.HighPrice > _highestHigh) _highestHigh = candle.HighPrice;
if (candle.LowPrice < _lowestLow) _lowestLow = candle.LowPrice;
if (_barCount < 50)
{
_prev2High = _prevHigh;
_prev2Low = _prevLow;
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_prevClose = candle.ClosePrice;
return;
}
var close = candle.ClosePrice;
// Fair value gap detection
var fvgUp = _prev2Low > candle.HighPrice;
var fvgDown = _prev2High < candle.LowPrice;
// Breakout detection
var crossUp = _prevClose <= _lowestLow && close > _lowestLow;
var crossDown = _prevClose >= _highestHigh && close < _highestHigh;
var buySignal = crossUp || fvgUp;
var sellSignal = crossDown || fvgDown;
// Exit logic
if (Position > 0 && _stopPrice > 0m && _targetPrice > 0m)
{
if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _targetPrice)
{
SellMarket(Math.Abs(Position));
_stopPrice = 0m;
_targetPrice = 0m;
}
}
else if (Position < 0 && _stopPrice > 0m && _targetPrice > 0m)
{
if (candle.HighPrice >= _stopPrice || candle.LowPrice <= _targetPrice)
{
BuyMarket(Math.Abs(Position));
_stopPrice = 0m;
_targetPrice = 0m;
}
}
// Entry logic
if (Position == 0 && _entriesExecuted < MaxEntries)
{
if (buySignal)
{
BuyMarket();
_entryPrice = close;
_stopPrice = close - atrValue * AtrMultiplier;
_targetPrice = close + atrValue * AtrMultiplier * 2m;
_entriesExecuted++;
}
else if (sellSignal)
{
SellMarket();
_entryPrice = close;
_stopPrice = close + atrValue * AtrMultiplier;
_targetPrice = close - atrValue * AtrMultiplier * 2m;
_entriesExecuted++;
}
}
_prev2High = _prevHigh;
_prev2Low = _prevLow;
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_prevClose = close;
}
}
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 AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class john_bob_trading_bot_strategy(Strategy):
def __init__(self):
super(john_bob_trading_bot_strategy, self).__init__()
self._atr_multiplier = self.Param("AtrMultiplier", 2.0) \
.SetDisplay("ATR Mult", "ATR stop multiplier", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_close = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._prev2_high = 0.0
self._prev2_low = 0.0
self._highest_high = 0.0
self._lowest_low = 999999999.0
self._bar_count = 0
self._entry_price = 0.0
self._stop_price = 0.0
self._target_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(john_bob_trading_bot_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._prev2_high = 0.0
self._prev2_low = 0.0
self._highest_high = 0.0
self._lowest_low = 999999999.0
self._bar_count = 0
self._entry_price = 0.0
self._stop_price = 0.0
self._target_price = 0.0
def OnStarted2(self, time):
super(john_bob_trading_bot_strategy, self).OnStarted2(time)
atr = AverageTrueRange()
atr.Length = 14
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(atr, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def OnProcess(self, candle, atr_val):
if candle.State != CandleStates.Finished:
return
self._bar_count += 1
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
atr_v = float(atr_val)
mult = float(self._atr_multiplier.Value)
if high > self._highest_high:
self._highest_high = high
if low < self._lowest_low:
self._lowest_low = low
if self._bar_count < 50:
self._prev2_high = self._prev_high
self._prev2_low = self._prev_low
self._prev_high = high
self._prev_low = low
self._prev_close = close
return
fvg_up = self._prev2_low > high
fvg_down = self._prev2_high < low
cross_up = self._prev_close <= self._lowest_low and close > self._lowest_low
cross_down = self._prev_close >= self._highest_high and close < self._highest_high
buy_signal = cross_up or fvg_up
sell_signal = cross_down or fvg_down
if self.Position > 0 and self._stop_price > 0 and self._target_price > 0:
if low <= self._stop_price or high >= self._target_price:
self.SellMarket()
self._stop_price = 0.0
self._target_price = 0.0
elif self.Position < 0 and self._stop_price > 0 and self._target_price > 0:
if high >= self._stop_price or low <= self._target_price:
self.BuyMarket()
self._stop_price = 0.0
self._target_price = 0.0
if self.Position == 0:
if buy_signal:
self.BuyMarket()
self._entry_price = close
self._stop_price = close - atr_v * mult
self._target_price = close + atr_v * mult * 2.0
elif sell_signal:
self.SellMarket()
self._entry_price = close
self._stop_price = close + atr_v * mult
self._target_price = close - atr_v * mult * 2.0
self._prev2_high = self._prev_high
self._prev2_low = self._prev_low
self._prev_high = high
self._prev_low = low
self._prev_close = close
def CreateClone(self):
return john_bob_trading_bot_strategy()