Стратегия Daily BreakPoint
Обзор
Daily BreakPoint Strategy — это портирование эксперта MetaTrader 5 «Daily BreakPoint» (сборка 19498) в экосистему StockSharp. Алгоритм отслеживает расстояние между текущей ценой и дневным открытием. Когда движение от открытия превышает заданный порог, а тело последней свечи укладывается в допустимый диапазон, стратегия либо открывает позицию по направлению пробоя, либо разворачивает существующую позицию в зависимости от флага CloseBySignal.
Стратегия одновременно использует два типа данных:
- Внутридневные свечи (параметр
CandleType) для генерации торговых сигналов. - Дневные свечи для отслеживания актуального открытия торговой сессии.
Логика торговли
- После закрытия каждой внутридневной свечи стратегия получает цену открытия текущего дня и вычисляет уровни пробоя на основе
BreakPointPips(значение переводится из пунктов в абсолютную цену через шаг цены инструмента). - Размер тела последней свечи должен лежать в диапазоне
[LastBarSizeMinPips, LastBarSizeMaxPips]. - Бычий сценарий
- Свеча закрывается выше открытия (
Close > Open). - Цена закрытия как минимум на
BreakPointPipsвыше дневного открытия. - Уровень пробоя (дневное открытие + порог) находится внутри тела свечи.
- Если
CloseBySignal = false, открывается длинная позиция. ЕслиCloseBySignal = true, текущие лонги закрываются и открывается короткая позиция.
- Свеча закрывается выше открытия (
- Медвежий сценарий симметричен: свеча закрывается ниже открытия, расстояние до дневного открытия больше
BreakPointPips, уровень пробоя лежит внутри тела — в результате открывается шорт (CloseBySignal = false) или происходит разворот в лонг (CloseBySignal = true). - Заявки отправляются по рынку с объемом
OrderVolume. Объём позиции суммируется, поэтому повторные сигналы могут наращивать позицию.
Управление рисками
- Стоп-лосс / тейк-профит: задаются в пунктах (
StopLossPips,TakeProfitPips). Нулевое значение отключает соответствующий уровень. Проверка на срабатывание выполняется по максимумам и минимумам свечей. - Трейлинг-стоп: активируется, если
TrailingStopPips > 0. После того как прибыль превышаетTrailingStopPips + TrailingStepPips, стоп подтягивается на расстояниеTrailingStopPips. Параметр шага предотвращает излишне частые перестановки в боковом рынке. - Все расстояния в пунктах переводятся в абсолютные цены через
PriceStep. Для инструментов с 3 или 5 знаками после запятой размер пункта равен десяти шагам цены — как и в оригинальном советнике.
Параметры
| Параметр | Описание |
|---|---|
OrderVolume |
Базовый объем каждой рыночной заявки. |
CloseBySignal |
При true стратегия закрывает позиции и открывает противоположную при появлении сигнала. |
BreakPointPips |
Расстояние от дневного открытия, необходимое для подтверждения пробоя. |
LastBarSizeMinPips / LastBarSizeMaxPips |
Допустимый диапазон размера тела сигнальной свечи. |
TrailingStopPips |
Дистанция трейлинг-стопа. 0 — отключить. |
TrailingStepPips |
Минимальное дополнительное движение перед каждым смещением стопа. |
StopLossPips |
Фиксированный стоп-лосс. 0 — без стопа. |
TakeProfitPips |
Фиксированный тейк-профит. 0 — без тейка. |
CandleType |
Тип внутридневных свечей для расчетов. |
Примечания по использованию
- Стратегия автоматически подписывается на внутридневные и дневные свечи. Убедитесь, что поставщик данных поддерживает необходимые таймфреймы.
- Сигналы анализируются только после закрытия свечи, поэтому заявки отправляются по цене закрытия сигнального бара.
- Конвертация пунктов рассчитана на форекс-котировки. Для инструментов с нестандартным шагом цены скорректируйте значения параметров.
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()