-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrolling.py
More file actions
63 lines (52 loc) · 1.93 KB
/
Copy pathrolling.py
File metadata and controls
63 lines (52 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
"""Rolling multi-date rebalance through the PortfolioSequence API.
One fixed factor structure, ten dates of new expected returns anchored on the
previous date's weights. The sequence keeps the equilibration and the reduced
factorizations cached across dates and chains warm starts internally, so each
date only pays iteration cost.
"""
import numpy as np
from ledge import PortfolioProblem
def main() -> None:
rng = np.random.default_rng(42)
assets, factors, dates = 60, 6, 10
exposures = rng.normal(0.0, 0.25, size=(assets, factors))
omega = np.diag(rng.uniform(0.04, 0.16, size=factors))
specific = rng.uniform(0.05, 0.12, size=assets)
expected = rng.normal(0.08, 0.025, size=assets)
anchor = np.full(assets, 1.0 / assets)
problem = PortfolioProblem(
exposures,
omega,
specific,
expected,
risk_aversion=8.0,
lower_bounds=np.zeros(assets),
upper_bounds=np.full(assets, 0.05),
previous_weights=anchor,
turnover_penalty=0.5,
)
sequence = problem.sequence()
print("date | status | iterations | factorizations | one-way turnover")
previous_weights = None
for date in range(dates):
if date == 0:
result = sequence.solve_next()
else:
result = sequence.solve_next(
expected_returns=expected + rng.normal(0.0, 0.01, size=assets),
previous_weights=previous_weights,
)
turnover = (
0.0
if previous_weights is None
else 0.5 * float(np.abs(result.weights - previous_weights).sum())
)
print(
f"{date} | {result.status} | {result.iterations} | "
f"{sequence.factorizations} | {turnover:.6f}"
)
previous_weights = result.weights
print(f"total reduced factorizations across {dates} dates: "
f"{sequence.factorizations}")
if __name__ == "__main__":
main()