Daily BreakPoint 策略
概述
Daily BreakPoint Strategy 是将 MetaTrader 5 专家顾问 “Daily BreakPoint”(构建号 19498)迁移到 StockSharp 的版本。策略关注当前价格与当日开盘价之间的距离。当价格偏离开盘价超过可配置阈值,并且上一根 K 线的实体满足设定的范围时,系统会按照 CloseBySignal 参数的设置选择顺势建仓或直接反向开仓。
策略同时订阅两类数据:
- 由
CandleType指定的日内 K 线,用于产生交易信号。 - 日线数据,用于跟踪最近一个交易日的开盘价。
交易逻辑
- 每当一根日内 K 线收盘时,策略读取最新的日线开盘价,并使用
BreakPointPips(通过合约最小价位转换为绝对价格)计算上下突破水平。 - 最近收盘的 K 线实体必须位于
[LastBarSizeMinPips, LastBarSizeMaxPips]区间内。 - 看涨条件
- K 线收阳 (
Close > Open)。 - 收盘价至少高于当日开盘价
BreakPointPips。 - 突破价格(开盘价 + BreakPoint)必须落在 K 线实体内部。
CloseBySignal = false时,策略做多;CloseBySignal = true时,先平掉已有多头再开新空头。
- K 线收阳 (
- 看跌条件 对称:收阴 K 线、收盘价至少低于当日开盘价
BreakPointPips,并且突破价落在实体内部。满足条件后,CloseBySignal = false时做空,CloseBySignal = true时先平旧空头再开多头。 - 所有订单均以市价下单,手数为
OrderVolume。仓位是累计的,多次信号可以逐步加仓或反向减仓。
风险控制
- 止损 / 止盈:通过
StopLossPips与TakeProfitPips(单位为点)设置。值为 0 表示关闭该功能。策略使用 K 线最高价和最低价判断是否触发。 - 移动止损:当
TrailingStopPips > 0时启用。当浮动盈利超过TrailingStopPips + TrailingStepPips后,将止损价跟随价格移动,保持TrailingStopPips的距离;TrailingStepPips可避免在震荡行情中过度调整。 - 所有以点为单位的距离都会根据
PriceStep转换为真实价格。对于 3 位或 5 位小数的报价,1 点等于 10 个最小价位,与原始 EA 的处理一致。
参数
| 名称 | 说明 |
|---|---|
OrderVolume |
每次市价单的基础手数。 |
CloseBySignal |
为 true 时出现反向信号会先平仓再开反向单。 |
BreakPointPips |
触发突破所需的开盘价偏离幅度(点)。 |
LastBarSizeMinPips / LastBarSizeMaxPips |
信号 K 线实体允许的最小与最大范围。 |
TrailingStopPips |
移动止损距离,0 表示关闭。 |
TrailingStepPips |
每次移动止损前需要的额外盈利。 |
StopLossPips |
固定止损距离,0 表示不使用。 |
TakeProfitPips |
固定止盈距离,0 表示不使用。 |
CandleType |
用于交易逻辑的日内 K 线类型。 |
使用提示
- 策略会自动订阅日内与日线数据,请确认数据源支持所需的时间框架。
- 仅在 K 线收盘后评估信号,因此订单在信号 K 线收盘时发送。
- 点值换算以外汇品种的常见报价为基准,如用于其它最小价位不同的品种,请重新评估参数默认值。
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Daily breakout strategy that reacts to the distance from the daily open.
/// Converted from the MetaTrader Daily BreakPoint expert advisor.
/// </summary>
public class DailyBreakPointStrategy : Strategy
{
private readonly StrategyParam<decimal> _orderVolume;
private readonly StrategyParam<bool> _closeBySignal;
private readonly StrategyParam<decimal> _breakPointPips;
private readonly StrategyParam<decimal> _lastBarSizeMinPips;
private readonly StrategyParam<decimal> _lastBarSizeMaxPips;
private readonly StrategyParam<decimal> _trailingStopPips;
private readonly StrategyParam<decimal> _trailingStepPips;
private readonly StrategyParam<decimal> _stopLossPips;
private readonly StrategyParam<decimal> _takeProfitPips;
private readonly StrategyParam<DataType> _candleType;
private decimal? _currentDayOpen;
private decimal? _longStopPrice;
private decimal? _longTakePrice;
private decimal? _shortStopPrice;
private decimal? _shortTakePrice;
private decimal? _longEntryPrice;
private decimal? _shortEntryPrice;
private decimal _pipSize;
/// <summary>
/// Order volume.
/// </summary>
public decimal OrderVolume
{
get => _orderVolume.Value;
set => _orderVolume.Value = value;
}
/// <summary>
/// Reverse the position when the opposite signal appears.
/// </summary>
public bool CloseBySignal
{
get => _closeBySignal.Value;
set => _closeBySignal.Value = value;
}
/// <summary>
/// Break distance from the daily open expressed in pips.
/// </summary>
public decimal BreakPointPips
{
get => _breakPointPips.Value;
set => _breakPointPips.Value = value;
}
/// <summary>
/// Minimum size of the previous bar body in pips.
/// </summary>
public decimal LastBarSizeMinPips
{
get => _lastBarSizeMinPips.Value;
set => _lastBarSizeMinPips.Value = value;
}
/// <summary>
/// Maximum size of the previous bar body in pips.
/// </summary>
public decimal LastBarSizeMaxPips
{
get => _lastBarSizeMaxPips.Value;
set => _lastBarSizeMaxPips.Value = value;
}
/// <summary>
/// Trailing stop distance in pips.
/// </summary>
public decimal TrailingStopPips
{
get => _trailingStopPips.Value;
set => _trailingStopPips.Value = value;
}
/// <summary>
/// Trailing stop step in pips.
/// </summary>
public decimal TrailingStepPips
{
get => _trailingStepPips.Value;
set => _trailingStepPips.Value = value;
}
/// <summary>
/// Fixed stop loss in pips.
/// </summary>
public decimal StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Fixed take profit in pips.
/// </summary>
public decimal TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Intraday candle type used for signal calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="DailyBreakPointStrategy"/> class.
/// </summary>
public DailyBreakPointStrategy()
{
_orderVolume = Param(nameof(OrderVolume), 1m)
.SetGreaterThanZero()
.SetDisplay("Volume", "Default order volume", "General");
_closeBySignal = Param(nameof(CloseBySignal), true)
.SetDisplay("Close By Signal", "Reverse existing position on opposite signal", "General");
_breakPointPips = Param(nameof(BreakPointPips), 5m)
.SetGreaterThanZero()
.SetDisplay("Break Point (pips)", "Distance from the daily open", "Signals");
_lastBarSizeMinPips = Param(nameof(LastBarSizeMinPips), 1m)
.SetGreaterThanZero()
.SetDisplay("Last Bar Min (pips)", "Minimum body size of the previous bar", "Signals");
_lastBarSizeMaxPips = Param(nameof(LastBarSizeMaxPips), 5000m)
.SetGreaterThanZero()
.SetDisplay("Last Bar Max (pips)", "Maximum body size of the previous bar", "Signals");
_trailingStopPips = Param(nameof(TrailingStopPips), 2m)
.SetDisplay("Trailing Stop (pips)", "Trailing stop distance", "Risk");
_trailingStepPips = Param(nameof(TrailingStepPips), 2m)
.SetDisplay("Trailing Step (pips)", "Minimum move before trailing", "Risk");
_stopLossPips = Param(nameof(StopLossPips), 0m)
.SetDisplay("Stop Loss (pips)", "Fixed stop loss distance", "Risk");
_takeProfitPips = Param(nameof(TakeProfitPips), 30m)
.SetDisplay("Take Profit (pips)", "Fixed take profit distance", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Intraday candle series", "Data");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType), (Security, TimeSpan.FromMinutes(5).TimeFrame())];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_currentDayOpen = null;
_longStopPrice = null;
_longTakePrice = null;
_shortStopPrice = null;
_shortTakePrice = null;
_longEntryPrice = null;
_shortEntryPrice = null;
_pipSize = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
Volume = OrderVolume;
_pipSize = CalculatePipSize();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var intradaySubscription = SubscribeCandles(CandleType);
intradaySubscription.Bind(ProcessCandle).Start();
var dailySubscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
dailySubscription.Bind(ProcessDailyCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, intradaySubscription);
DrawOwnTrades(area);
}
}
private decimal CalculatePipSize()
{
var step = Security?.PriceStep ?? 0.0001m;
if (step <= 0m)
step = 0.0001m;
var decimals = Security?.Decimals;
if (decimals == 3 || decimals == 5)
return step * 10m;
return step;
}
private decimal NormalizePrice(decimal price)
{
var step = Security?.PriceStep;
if (step is null || step.Value <= 0m)
return price;
var value = price / step.Value;
var rounded = Math.Round(value, 0, MidpointRounding.AwayFromZero);
return rounded * step.Value;
}
private void ProcessDailyCandle(ICandleMessage candle)
{
if (candle.State == CandleStates.Finished || candle.State == CandleStates.Active)
_currentDayOpen = candle.OpenPrice;
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
Volume = OrderVolume;
if (_pipSize <= 0m)
_pipSize = CalculatePipSize();
var dayOpen = _currentDayOpen;
if (dayOpen is null)
return;
var breakOffset = BreakPointPips * _pipSize;
var minBody = LastBarSizeMinPips * _pipSize;
var maxBody = LastBarSizeMaxPips * _pipSize;
var trailingStop = TrailingStopPips * _pipSize;
var trailingStep = TrailingStepPips * _pipSize;
var stopLossOffset = StopLossPips > 0m ? StopLossPips * _pipSize : 0m;
var takeProfitOffset = TakeProfitPips > 0m ? TakeProfitPips * _pipSize : 0m;
UpdateTrailing(candle, trailingStop, trailingStep);
HandleRiskExits(candle);
var bodySize = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var minPrice = Math.Min(candle.OpenPrice, candle.ClosePrice);
var maxPrice = Math.Max(candle.OpenPrice, candle.ClosePrice);
var breakBuy = dayOpen.Value + breakOffset;
var breakSell = dayOpen.Value - breakOffset;
var bullishBody = candle.ClosePrice > candle.OpenPrice;
var bearishBody = candle.ClosePrice < candle.OpenPrice;
var bullishSignal = bullishBody && breakOffset > 0m &&
candle.ClosePrice - dayOpen.Value >= breakOffset &&
bodySize >= minBody &&
(maxBody <= 0m || bodySize <= maxBody);
var bearishSignal = bearishBody && breakOffset > 0m &&
dayOpen.Value - candle.ClosePrice >= breakOffset &&
bodySize >= minBody &&
(maxBody <= 0m || bodySize <= maxBody);
if (bullishSignal)
{
ExecuteBullishSignal(candle.ClosePrice, stopLossOffset, takeProfitOffset);
}
else if (bearishSignal)
{
ExecuteBearishSignal(candle.ClosePrice, stopLossOffset, takeProfitOffset);
}
}
private void UpdateTrailing(ICandleMessage candle, decimal trailingStop, decimal trailingStep)
{
if (trailingStop <= 0m)
return;
if (Position > 0 && _longEntryPrice.HasValue)
{
var profit = candle.ClosePrice - _longEntryPrice.Value;
if (profit > trailingStop + trailingStep)
{
var threshold = candle.ClosePrice - (trailingStop + trailingStep);
if (!_longStopPrice.HasValue || _longStopPrice.Value < threshold)
_longStopPrice = NormalizePrice(candle.ClosePrice - trailingStop);
}
}
else if (Position < 0 && _shortEntryPrice.HasValue)
{
var profit = _shortEntryPrice.Value - candle.ClosePrice;
if (profit > trailingStop + trailingStep)
{
var threshold = candle.ClosePrice + (trailingStop + trailingStep);
if (!_shortStopPrice.HasValue || _shortStopPrice.Value > threshold || _shortStopPrice.Value == 0m)
_shortStopPrice = NormalizePrice(candle.ClosePrice + trailingStop);
}
}
}
private void HandleRiskExits(ICandleMessage candle)
{
if (Position > 0)
{
var volume = Math.Abs(Position);
if (volume > 0m && _longStopPrice.HasValue && candle.LowPrice <= _longStopPrice.Value)
{
SellMarket();
ResetLongState();
return;
}
if (volume > 0m && _longTakePrice.HasValue && candle.HighPrice >= _longTakePrice.Value)
{
SellMarket();
ResetLongState();
}
}
else if (Position < 0)
{
var volume = Math.Abs(Position);
if (volume > 0m && _shortStopPrice.HasValue && candle.HighPrice >= _shortStopPrice.Value)
{
BuyMarket();
ResetShortState();
return;
}
if (volume > 0m && _shortTakePrice.HasValue && candle.LowPrice <= _shortTakePrice.Value)
{
BuyMarket();
ResetShortState();
}
}
else
{
ResetLongState();
ResetShortState();
}
}
private void ExecuteBullishSignal(decimal entryPrice, decimal stopLossOffset, decimal takeProfitOffset)
{
if (CloseBySignal)
{
if (Position > 0)
{
var volume = Math.Abs(Position);
SellMarket();
}
ResetLongState();
SellMarket();
_shortEntryPrice = entryPrice;
_shortStopPrice = stopLossOffset > 0m ? NormalizePrice(entryPrice + stopLossOffset) : null;
_shortTakePrice = takeProfitOffset > 0m ? NormalizePrice(entryPrice - takeProfitOffset) : null;
}
else
{
BuyMarket();
_longEntryPrice = entryPrice;
_longStopPrice = stopLossOffset > 0m ? NormalizePrice(entryPrice - stopLossOffset) : null;
_longTakePrice = takeProfitOffset > 0m ? NormalizePrice(entryPrice + takeProfitOffset) : null;
ResetShortState();
}
}
private void ExecuteBearishSignal(decimal entryPrice, decimal stopLossOffset, decimal takeProfitOffset)
{
if (CloseBySignal)
{
if (Position < 0)
{
var volume = Math.Abs(Position);
BuyMarket();
}
ResetShortState();
BuyMarket();
_longEntryPrice = entryPrice;
_longStopPrice = stopLossOffset > 0m ? NormalizePrice(entryPrice - stopLossOffset) : null;
_longTakePrice = takeProfitOffset > 0m ? NormalizePrice(entryPrice + takeProfitOffset) : null;
}
else
{
SellMarket();
_shortEntryPrice = entryPrice;
_shortStopPrice = stopLossOffset > 0m ? NormalizePrice(entryPrice + stopLossOffset) : null;
_shortTakePrice = takeProfitOffset > 0m ? NormalizePrice(entryPrice - takeProfitOffset) : null;
ResetLongState();
}
}
private void ResetLongState()
{
_longEntryPrice = null;
_longStopPrice = null;
_longTakePrice = null;
}
private void ResetShortState()
{
_shortEntryPrice = null;
_shortStopPrice = null;
_shortTakePrice = null;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class daily_break_point_strategy(Strategy):
"""Daily BreakPoint: daily open breakout with body size filter and trailing stop."""
def __init__(self):
super(daily_break_point_strategy, self).__init__()
self._order_volume = self.Param("OrderVolume", 1.0) \
.SetGreaterThanZero() \
.SetDisplay("Volume", "Default order volume", "General")
self._close_by_signal = self.Param("CloseBySignal", True) \
.SetDisplay("Close By Signal", "Reverse existing position on opposite signal", "General")
self._break_point_pips = self.Param("BreakPointPips", 5.0) \
.SetGreaterThanZero() \
.SetDisplay("Break Point (pips)", "Distance from the daily open", "Signals")
self._last_bar_size_min_pips = self.Param("LastBarSizeMinPips", 1.0) \
.SetGreaterThanZero() \
.SetDisplay("Last Bar Min (pips)", "Minimum body size of the previous bar", "Signals")
self._last_bar_size_max_pips = self.Param("LastBarSizeMaxPips", 5000.0) \
.SetGreaterThanZero() \
.SetDisplay("Last Bar Max (pips)", "Maximum body size of the previous bar", "Signals")
self._trailing_stop_pips = self.Param("TrailingStopPips", 2.0) \
.SetDisplay("Trailing Stop (pips)", "Trailing stop distance", "Risk")
self._trailing_step_pips = self.Param("TrailingStepPips", 2.0) \
.SetDisplay("Trailing Step (pips)", "Minimum move before trailing", "Risk")
self._stop_loss_pips = self.Param("StopLossPips", 0.0) \
.SetDisplay("Stop Loss (pips)", "Fixed stop loss distance", "Risk")
self._take_profit_pips = self.Param("TakeProfitPips", 30.0) \
.SetDisplay("Take Profit (pips)", "Fixed take profit distance", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Intraday candle series", "Data")
self._current_day_open = None
self._long_stop_price = None
self._long_take_price = None
self._short_stop_price = None
self._short_take_price = None
self._long_entry_price = None
self._short_entry_price = None
self._pip_size = 0.0
@property
def OrderVolume(self):
return float(self._order_volume.Value)
@property
def CloseBySignal(self):
return self._close_by_signal.Value
@property
def BreakPointPips(self):
return float(self._break_point_pips.Value)
@property
def LastBarSizeMinPips(self):
return float(self._last_bar_size_min_pips.Value)
@property
def LastBarSizeMaxPips(self):
return float(self._last_bar_size_max_pips.Value)
@property
def TrailingStopPips(self):
return float(self._trailing_stop_pips.Value)
@property
def TrailingStepPips(self):
return float(self._trailing_step_pips.Value)
@property
def StopLossPips(self):
return float(self._stop_loss_pips.Value)
@property
def TakeProfitPips(self):
return float(self._take_profit_pips.Value)
@property
def CandleType(self):
return self._candle_type.Value
def _calc_pip_size(self):
sec = self.Security
if sec is None or sec.PriceStep is None:
return 0.0001
step = float(sec.PriceStep)
if step <= 0:
return 0.0001
decimals = None
if sec.Decimals is not None:
decimals = int(sec.Decimals)
if decimals == 3 or decimals == 5:
return step * 10.0
return step
def _normalize_price(self, price):
sec = self.Security
if sec is None or sec.PriceStep is None:
return price
step = float(sec.PriceStep)
if step <= 0:
return price
return round(price / step) * step
def OnStarted2(self, time):
super(daily_break_point_strategy, self).OnStarted2(time)
self._current_day_open = None
self._long_stop_price = None
self._long_take_price = None
self._short_stop_price = None
self._short_take_price = None
self._long_entry_price = None
self._short_entry_price = None
self._pip_size = self._calc_pip_size()
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(1, UnitTypes.Percent)
)
intraday_subscription = self.SubscribeCandles(self.CandleType)
intraday_subscription.Bind(self.process_candle).Start()
daily_subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
daily_subscription.Bind(self.process_daily_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, intraday_subscription)
self.DrawOwnTrades(area)
def process_daily_candle(self, candle):
if candle.State == CandleStates.Finished or candle.State == CandleStates.Active:
self._current_day_open = float(candle.OpenPrice)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
if self._pip_size <= 0:
self._pip_size = self._calc_pip_size()
day_open = self._current_day_open
if day_open is None:
return
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
h = float(candle.HighPrice)
lo = float(candle.LowPrice)
break_offset = self.BreakPointPips * self._pip_size
min_body = self.LastBarSizeMinPips * self._pip_size
max_body = self.LastBarSizeMaxPips * self._pip_size
trailing_stop = self.TrailingStopPips * self._pip_size
trailing_step = self.TrailingStepPips * self._pip_size
stop_loss_offset = self.StopLossPips * self._pip_size if self.StopLossPips > 0 else 0.0
take_profit_offset = self.TakeProfitPips * self._pip_size if self.TakeProfitPips > 0 else 0.0
self._update_trailing(candle, trailing_stop, trailing_step)
if self._handle_risk_exits(candle):
return
body_size = abs(close - open_p)
bullish_body = close > open_p
bearish_body = close < open_p
bullish_signal = (bullish_body and break_offset > 0 and
close - day_open >= break_offset and
body_size >= min_body and
(max_body <= 0 or body_size <= max_body))
bearish_signal = (bearish_body and break_offset > 0 and
day_open - close >= break_offset and
body_size >= min_body and
(max_body <= 0 or body_size <= max_body))
if bullish_signal:
self._execute_bullish_signal(close, stop_loss_offset, take_profit_offset)
elif bearish_signal:
self._execute_bearish_signal(close, stop_loss_offset, take_profit_offset)
def _update_trailing(self, candle, trailing_stop, trailing_step):
if trailing_stop <= 0:
return
close = float(candle.ClosePrice)
if self.Position > 0 and self._long_entry_price is not None:
profit = close - self._long_entry_price
if profit > trailing_stop + trailing_step:
threshold = close - (trailing_stop + trailing_step)
if self._long_stop_price is None or self._long_stop_price < threshold:
self._long_stop_price = self._normalize_price(close - trailing_stop)
elif self.Position < 0 and self._short_entry_price is not None:
profit = self._short_entry_price - close
if profit > trailing_stop + trailing_step:
threshold = close + trailing_stop + trailing_step
if (self._short_stop_price is None or
self._short_stop_price > threshold or self._short_stop_price == 0):
self._short_stop_price = self._normalize_price(close + trailing_stop)
def _handle_risk_exits(self, candle):
h = float(candle.HighPrice)
lo = float(candle.LowPrice)
if self.Position > 0:
if self._long_stop_price is not None and lo <= self._long_stop_price:
self.SellMarket()
self._reset_long_state()
return True
if self._long_take_price is not None and h >= self._long_take_price:
self.SellMarket()
self._reset_long_state()
return True
elif self.Position < 0:
if self._short_stop_price is not None and h >= self._short_stop_price:
self.BuyMarket()
self._reset_short_state()
return True
if self._short_take_price is not None and lo <= self._short_take_price:
self.BuyMarket()
self._reset_short_state()
return True
else:
self._reset_long_state()
self._reset_short_state()
return False
def _execute_bullish_signal(self, entry_price, stop_loss_offset, take_profit_offset):
if self.CloseBySignal:
if self.Position > 0:
self.SellMarket()
self._reset_long_state()
self.SellMarket()
self._short_entry_price = entry_price
self._short_stop_price = self._normalize_price(entry_price + stop_loss_offset) if stop_loss_offset > 0 else None
self._short_take_price = self._normalize_price(entry_price - take_profit_offset) if take_profit_offset > 0 else None
else:
self.BuyMarket()
self._long_entry_price = entry_price
self._long_stop_price = self._normalize_price(entry_price - stop_loss_offset) if stop_loss_offset > 0 else None
self._long_take_price = self._normalize_price(entry_price + take_profit_offset) if take_profit_offset > 0 else None
self._reset_short_state()
def _execute_bearish_signal(self, entry_price, stop_loss_offset, take_profit_offset):
if self.CloseBySignal:
if self.Position < 0:
self.BuyMarket()
self._reset_short_state()
self.BuyMarket()
self._long_entry_price = entry_price
self._long_stop_price = self._normalize_price(entry_price - stop_loss_offset) if stop_loss_offset > 0 else None
self._long_take_price = self._normalize_price(entry_price + take_profit_offset) if take_profit_offset > 0 else None
else:
self.SellMarket()
self._short_entry_price = entry_price
self._short_stop_price = self._normalize_price(entry_price + stop_loss_offset) if stop_loss_offset > 0 else None
self._short_take_price = self._normalize_price(entry_price - take_profit_offset) if take_profit_offset > 0 else None
self._reset_long_state()
def _reset_long_state(self):
self._long_entry_price = None
self._long_stop_price = None
self._long_take_price = None
def _reset_short_state(self):
self._short_entry_price = None
self._short_stop_price = None
self._short_take_price = None
def OnReseted(self):
super(daily_break_point_strategy, self).OnReseted()
self._current_day_open = None
self._long_stop_price = None
self._long_take_price = None
self._short_stop_price = None
self._short_take_price = None
self._long_entry_price = None
self._short_entry_price = None
self._pip_size = 0.0
def CreateClone(self):
return daily_break_point_strategy()