1313from abc import ABCMeta , abstractmethod
1414from copy import copy
1515from difflib import get_close_matches
16- from functools import lru_cache , partial
16+ from functools import cached_property , lru_cache , partial
1717from itertools import chain , product , repeat
1818from math import copysign
1919from 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