Skip to content

Commit ed37dcb

Browse files
feat: adds loading bar
1 parent 9da3917 commit ed37dcb

File tree

8 files changed

+349
-235
lines changed

8 files changed

+349
-235
lines changed

src/quant_research_starter/backtest/vectorized.py

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Dict, Optional
44

55
import pandas as pd
6-
6+
from tqdm import tqdm
77

88
class VectorizedBacktest:
99
"""
@@ -74,40 +74,54 @@ def run(self, weight_scheme: str = "rank") -> Dict:
7474

7575
# Compute daily weights from signals (rebalance only on rebalance dates)
7676
weights_list = []
77-
for date in returns_df.index:
78-
if self._should_rebalance(date, prev_rebalance_date):
79-
# Rebalance: compute new target weights
80-
current_weights = self._calculate_weights(
81-
aligned_signals.loc[date], weight_scheme
82-
)
83-
prev_rebalance_date = date
84-
85-
# Append current weights (maintain between rebalances)
86-
weights_list.append(current_weights)
77+
with tqdm(len(returns_df.index),desc="Backtesting", unit="day") as pbar:
78+
for date in returns_df.index:
79+
if self._should_rebalance(date, prev_rebalance_date):
80+
# Rebalance: compute new target weights
81+
current_weights = self._calculate_weights(
82+
aligned_signals.loc[date], weight_scheme
83+
)
84+
prev_rebalance_date = date
85+
pbar.set_postfix(rebalance="✓", refresh=False)
86+
else :
87+
pbar.set_postfix(rebalance=" ", refresh=False)
88+
89+
# Append current weights (maintain between rebalances)
90+
weights_list.append(current_weights)
91+
pbar.update(1)
8792

8893
weights = pd.DataFrame(
8994
weights_list, index=returns_df.index, columns=self.prices.columns
9095
).fillna(0.0)
9196

92-
# Previous day weights for PnL calculation
93-
weights_prev = weights.shift(1).fillna(0.0)
94-
95-
# Turnover for transaction costs (L1 change / 2)
96-
turnover = (weights.fillna(0.0) - weights_prev).abs().sum(axis=1) * 0.5
97-
tc_series = turnover * self.transaction_cost
98-
99-
# Strategy returns
100-
strat_ret = (weights_prev * returns_df).sum(axis=1) - tc_series
101-
102-
# Build portfolio value series
103-
portfolio_value = (1 + strat_ret).cumprod() * self.initial_capital
104-
portfolio_value = pd.concat(
105-
[
106-
pd.Series(self.initial_capital, index=[self.prices.index[0]]),
107-
portfolio_value,
108-
]
109-
)
110-
portfolio_value = portfolio_value.reindex(self.prices.index).ffill()
97+
with tqdm(total=4, desc="Calculating performance") as pbar:
98+
# Previous day weights for PnL calculation
99+
pbar.set_description("Calculating weight shifts")
100+
weights_prev = weights.shift(1).fillna(0.0)
101+
pbar.update(1)
102+
103+
# Turnover for transaction costs (L1 change / 2)
104+
pbar.set_description("Calculating transaction costs")
105+
turnover = (weights.fillna(0.0) - weights_prev).abs().sum(axis=1) * 0.5
106+
tc_series = turnover * self.transaction_cost
107+
pbar.update(1)
108+
109+
# Strategy returns
110+
pbar.set_description("Calculating strategy returns")
111+
strat_ret = (weights_prev * returns_df).sum(axis=1) - tc_series
112+
pbar.update(1)
113+
114+
# Build portfolio value series
115+
pbar.set_description("Building portfolio series")
116+
portfolio_value = (1 + strat_ret).cumprod() * self.initial_capital
117+
portfolio_value = pd.concat(
118+
[
119+
pd.Series(self.initial_capital, index=[self.prices.index[0]]),
120+
portfolio_value,
121+
]
122+
)
123+
portfolio_value = portfolio_value.reindex(self.prices.index).ffill()
124+
pbar.update(1)
111125

112126
# Store results
113127
self.positions = weights # interpret as weights positions

0 commit comments

Comments
 (0)