Skip to content

Commit 0954b1f

Browse files
committed
REF: Backwards-incompatibly revise lib.SignalStrategy
1 parent 1440701 commit 0954b1f

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

backtesting/lib.py

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
from .backtesting import Strategy
2424
from ._plotting import plot_heatmaps as _plot_heatmaps
25-
from ._util import _Array, _Indicator, _as_str
25+
from ._util import _Array, _as_str
2626

2727
__pdoc__ = {}
2828

@@ -280,36 +280,51 @@ def init(self):
280280

281281
__pdoc__['SignalStrategy.__init__'] = False
282282

283-
def set_signal(self, entry: Sequence[int], exit: Optional[Sequence[bool]] = None,
283+
def set_signal(self, entry_size: Sequence[float],
284+
exit_portion: Sequence[float] = None,
285+
*,
284286
plot: bool = True):
285287
"""
286-
Set entry/exit signal vectors (arrays). An long entry signal is considered
287-
present wherever `entry` is greater than zero. A short entry signal
288-
is considered present wherever `entry` is less than zero. If `exit`
289-
is provided, a nonzero value closes the position, if any; otherwise
290-
the position is held until a reverse signal in `entry`.
288+
Set entry/exit signal vectors (arrays).
289+
290+
A long entry signal is considered present wherever `entry_size`
291+
is greater than zero, and a short signal wherever `entry_size`
292+
is less than zero, following `backtesting.backtesting.Order.size` semantics.
293+
294+
If `exit_portion` is provided, a nonzero value closes portion the position
295+
(see `backtesting.backtesting.Trade.close()`) in the respective direction
296+
(positive values close long trades, negative short).
291297
292298
If `plot` is `True`, the signal entry/exit indicators are plotted when
293299
`backtesting.backtesting.Backtest.plot` is called.
294300
"""
295-
self.__entry_signal = _Indicator(pd.Series(entry, dtype=float).fillna(0),
296-
name='entry', plot=plot, overlay=False)
297-
if exit is not None:
298-
self.__exit_signal = _Indicator(pd.Series(exit, dtype=float).fillna(0),
299-
name='exit', plot=plot, overlay=False)
301+
self.__entry_signal = self.I(
302+
lambda: pd.Series(entry_size, dtype=float).replace(0, np.nan),
303+
name='entry size', plot=plot, overlay=False, scatter=True, color='black')
304+
305+
if exit_portion is not None:
306+
self.__exit_signal = self.I(
307+
lambda: pd.Series(exit_portion, dtype=float).replace(0, np.nan),
308+
name='exit portion', plot=plot, overlay=False, scatter=True, color='black')
300309

301310
def next(self):
302311
super().next()
303312

304-
if self.position and self.__exit_signal[-1]:
305-
self.position.close()
306-
307-
signal = self.__entry_signal[-1]
308-
309-
if signal > 0:
310-
self.buy()
311-
elif signal < 0:
312-
self.sell()
313+
exit_portion = self.__exit_signal[-1]
314+
if exit_portion > 0:
315+
for trade in self.trades:
316+
if trade.is_long:
317+
trade.close(exit_portion)
318+
elif exit_portion < 0:
319+
for trade in self.trades:
320+
if trade.is_short:
321+
trade.close(-exit_portion)
322+
323+
entry_size = self.__entry_signal[-1]
324+
if entry_size > 0:
325+
self.buy(size=entry_size)
326+
elif entry_size < 0:
327+
self.sell(size=-entry_size)
313328

314329

315330
class TrailingStrategy(Strategy):

0 commit comments

Comments
 (0)