Skip to content

Commit f4bc7c0

Browse files
ChadThackraykernc
authored andcommitted
Replace hand-rolled cache with @cached_property
1 parent e8d780a commit f4bc7c0

1 file changed

Lines changed: 19 additions & 25 deletions

File tree

backtesting/backtesting.py

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from abc import ABCMeta, abstractmethod
1414
from copy import copy
1515
from difflib import get_close_matches
16-
from functools import lru_cache, partial
16+
from functools import cached_property, lru_cache, partial
1717
from itertools import chain, product, repeat
1818
from math import copysign
1919
from numbers import Number
@@ -344,8 +344,6 @@ def __bool__(self):
344344
@property
345345
def size(self) -> float:
346346
"""Position size in units of asset. Negative if position is short."""
347-
if self.__broker._trade_sums_dirty:
348-
self.__broker._recalculate_trade_sums()
349347
return self.__broker._open_trade_size_sum
350348

351349
@property
@@ -356,8 +354,6 @@ def pl(self) -> float:
356354
@property
357355
def pl_pct(self) -> float:
358356
"""Profit (positive) or loss (negative) of the current position in percent."""
359-
if self.__broker._trade_sums_dirty:
360-
self.__broker._recalculate_trade_sums()
361357
total_invested = self.__broker._open_trade_entry_abs_value_sum
362358
return (self.pl / total_invested) * 100 if total_invested else 0
363359

@@ -758,10 +754,6 @@ def __init__(self, *, data, cash, spread, commission, margin,
758754
self.trades: List[Trade] = []
759755
self.position = Position(self)
760756
self.closed_trades: List[Trade] = []
761-
self._trade_sums_dirty = True
762-
self._open_trade_size_sum = 0
763-
self._open_trade_entry_value_sum = 0.0
764-
self._open_trade_entry_abs_value_sum = 0.0
765757

766758
def _commission_func(self, order_size, price):
767759
return self._commission_fixed + abs(order_size) * price * self._commission_relative
@@ -819,23 +811,25 @@ def new_order(self,
819811

820812
return order
821813

822-
def _mark_trade_sums_dirty(self) -> None:
823-
self._trade_sums_dirty = True
814+
@cached_property
815+
def _open_trade_size_sum(self) -> int:
816+
return sum(int(trade.size) for trade in self.trades)
824817

825-
def _recalculate_trade_sums(self) -> None:
826-
self._open_trade_size_sum = sum(int(trade.size) for trade in self.trades)
827-
self._open_trade_entry_value_sum = sum(
828-
trade.size * trade.entry_price for trade in self.trades
829-
)
830-
self._open_trade_entry_abs_value_sum = sum(
831-
abs(trade.size) * trade.entry_price for trade in self.trades
832-
)
833-
self._trade_sums_dirty = False
818+
@cached_property
819+
def _open_trade_entry_value_sum(self) -> float:
820+
return sum(trade.size * trade.entry_price for trade in self.trades)
821+
822+
@cached_property
823+
def _open_trade_entry_abs_value_sum(self) -> float:
824+
return sum(abs(trade.size) * trade.entry_price for trade in self.trades)
825+
826+
def _clear_trade_caches(self) -> None:
827+
self.__dict__.pop('_open_trade_size_sum', None)
828+
self.__dict__.pop('_open_trade_entry_value_sum', None)
829+
self.__dict__.pop('_open_trade_entry_abs_value_sum', None)
834830

835831
@property
836832
def unrealized_pl(self) -> float:
837-
if self._trade_sums_dirty:
838-
self._recalculate_trade_sums()
839833
if not self.trades:
840834
return 0.0
841835
current_price = float(self._data._current_value("Close"))
@@ -1086,7 +1080,7 @@ def _process_orders(self):
10861080
def _reduce_trade(self, trade: Trade, price: float, size: float, time_index: int):
10871081
assert trade.size * size < 0
10881082
assert abs(trade.size) >= abs(size)
1089-
self._mark_trade_sums_dirty()
1083+
self._clear_trade_caches()
10901084

10911085
size_left = trade.size + size
10921086
assert size_left * trade.size >= 0
@@ -1107,7 +1101,7 @@ def _reduce_trade(self, trade: Trade, price: float, size: float, time_index: int
11071101
self._close_trade(close_trade, price, time_index)
11081102

11091103
def _close_trade(self, trade: Trade, price: float, time_index: int):
1110-
self._mark_trade_sums_dirty()
1104+
self._clear_trade_caches()
11111105
self.trades.remove(trade)
11121106
if trade._sl_order:
11131107
self.orders.remove(trade._sl_order)
@@ -1131,7 +1125,7 @@ def _open_trade(self, price: float, size: int,
11311125
self.trades.append(trade)
11321126
# Apply broker commission at trade open
11331127
self._cash -= self._commission(size, price)
1134-
self._mark_trade_sums_dirty()
1128+
self._clear_trade_caches()
11351129
# Create SL/TP (bracket) orders.
11361130
if tp:
11371131
trade.tp = tp

0 commit comments

Comments
 (0)