@@ -159,6 +159,9 @@ def wealth_ts(
159159 else : # Calendar rebalancing
160160 rebalancing_by_condition_needed = self .abs_deviation or self .rel_deviation
161161 rebalancing_condition = False
162+ # accumulate chunks and concatenate once after the loop
163+ pw_chunks : list [pd .Series ] = []
164+ awi_chunks : list [pd .DataFrame ] = [] if calculate_assets_wealth_indexes else None
162165 for n , x in enumerate (ror .resample (rule = self ._pandas_frequency , convention = "start" )):
163166 df = x [1 ] # select ror part of the grouped data
164167 if n == 0 :
@@ -179,27 +182,24 @@ def wealth_ts(
179182 initial_allocation = end_period_weights * end_period_balance
180183 assets_wealth_indexes_local = initial_allocation * (1 + df ).cumprod ()
181184 if calculate_assets_wealth_indexes :
182- if assets_wealth_indexes .empty :
183- assets_wealth_indexes = assets_wealth_indexes_local .copy ()
184- else :
185- assets_wealth_indexes = pd .concat (
186- [assets_wealth_indexes_local , assets_wealth_indexes ],
187- verify_integrity = True ,
188- sort = False ,
189- )
185+ # collect asset wealth index chunks for later concatenation
186+ awi_chunks .append (assets_wealth_indexes_local .copy ())
190187 wealth_index_local = assets_wealth_indexes_local .sum (axis = 1 )
191- if portfolio_wealth_index .empty :
192- portfolio_wealth_index = wealth_index_local .copy ()
193- else :
194- portfolio_wealth_index = pd .concat ([portfolio_wealth_index , wealth_index_local ], sort = False )
195- end_period_balance = portfolio_wealth_index .iloc [- 1 ]
188+ # collect portfolio wealth index chunks for later concatenation
189+ pw_chunks .append (wealth_index_local .copy ())
190+ # use local last value instead of relying on concatenated series
191+ end_period_balance = wealth_index_local .iloc [- 1 ]
196192 if rebalancing_by_condition_needed :
197193 end_period_weights = assets_wealth_indexes_local .iloc [- 1 ].divide (
198194 wealth_index_local .iloc [- 1 ], axis = 0
199195 )
200196 rebalancing_condition , condition_abs = self ._check_if_rebalancing_required (
201197 assets_wealth_indexes_local , wealth_index_local , target_weights
202198 )
199+ # perform single concatenation outside the loop
200+ portfolio_wealth_index = pd .concat (pw_chunks , sort = False ) if pw_chunks else portfolio_wealth_index
201+ if calculate_assets_wealth_indexes and awi_chunks :
202+ assets_wealth_indexes = pd .concat (awi_chunks , verify_integrity = True , sort = False )
203203 # set value for the first date
204204 portfolio_wealth_index .loc [first_wealth_index_date ] = initial_inv
205205 portfolio_wealth_index .sort_index (ascending = True , inplace = True )
@@ -218,6 +218,7 @@ def _rebalance_by_condition(
218218 assets_wealth_indexes_local = pd .DataFrame (columns = ror .columns , dtype = "float64" )
219219 assets_wealth_indexes = pd .DataFrame (columns = ror .columns , dtype = "float64" )
220220 events_ts = pd .Series (dtype = "float64" )
221+ awi_rows = [] if calculate_assets_wealth_indexes else None
221222 for n , row in enumerate (ror .itertuples ()):
222223 date = row [0 ]
223224 r = pd .Series (row [1 :], index = ror .columns , name = date )
@@ -231,17 +232,17 @@ def _rebalance_by_condition(
231232 assets_wealth_indexes_local *= 1 + r
232233 assets_wealth_indexes_local .rename (date , inplace = True )
233234 if calculate_assets_wealth_indexes :
234- row = pd .DataFrame (assets_wealth_indexes_local ).T
235- if assets_wealth_indexes .empty :
236- assets_wealth_indexes = row .copy ()
237- else :
238- assets_wealth_indexes = pd .concat ([assets_wealth_indexes , row ])
235+ # collect rows for a single concat after the loop
236+ awi_rows .append (pd .DataFrame (assets_wealth_indexes_local ).T )
239237 portfolio_wealth_index_local = assets_wealth_indexes_local .sum ()
240238 portfolio_wealth_index [date ] = portfolio_wealth_index_local
241239 # Check if rebalancing required
242240 rebalancing_condition , condition_abs = self ._check_if_rebalancing_required (
243241 assets_wealth_indexes_local , portfolio_wealth_index_local , target_weights
244242 )
243+ # perform single concatenation outside the loop
244+ if calculate_assets_wealth_indexes and awi_rows :
245+ assets_wealth_indexes = pd .concat (awi_rows , sort = False )
245246 return portfolio_wealth_index , assets_wealth_indexes , events_ts
246247
247248 def _check_if_rebalancing_required (
0 commit comments