Skip to content

Commit 0fc7741

Browse files
Working backtester with comparison to equally-weighted portfolio.
1 parent ae02ccc commit 0fc7741

File tree

5 files changed

+35
-11
lines changed

5 files changed

+35
-11
lines changed

backtest.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
# -*- coding: utf-8 -*-
22
import time
3+
4+
import numpy as np
35
import pandas as pd
46

7+
from matplotlib import pyplot as plt
8+
59
from tests.test_config import TEST_YAHOO_STOCK_UNIVERSE_16, TEST_YAHOO_STOCK_UNIVERSE_8, TEST_YAHOO_STOCK_UNIVERSE_4
610
from src.abacus.utils.portfolio import Portfolio
711
from src.abacus.utils.universe import Universe
@@ -12,7 +16,8 @@
1216
# Backtesting setup.
1317
instrument_specification = {}
1418
inital_weights = {}
15-
wealth = []
19+
wealth = [100]
20+
wealth_n = [100]
1621
number_of_start_assets = 5
1722
for i, ticker in enumerate(sorted(TEST_YAHOO_STOCK_UNIVERSE_8)):
1823
file = f"tests/data/{ticker}.csv"
@@ -24,7 +29,7 @@
2429

2530
# Date range for backtesting.
2631
start_date = "2020-01-02"
27-
end_date = "2020-01-05" # "2023-05-31"
32+
end_date = "2020-05-02" # "2023-05-31"
2833
date_range = pd.date_range(start=start_date, end=end_date, freq='B')
2934
solutions = {"2020-01-01": inital_weights}
3035
times = {}
@@ -34,15 +39,32 @@
3439
universe.date_today = date
3540
simulator = Simulator(universe)
3641
simulator.calibrate()
37-
simulator.run_simulation(time_steps=10, number_of_simulations=1_000)
38-
optimizer = MPCMaximumReturn(universe, portfolio, simulator.return_tensor, gamma=2, l1_penalty=0, l2_penalty=0.15,
42+
simulator.run_simulation(time_steps=5, number_of_simulations=1000)
43+
optimizer = MPCMaximumReturn(universe, portfolio, simulator.return_tensor, gamma=2, l1_penalty=0, l2_penalty=0.02,
3944
covariance_matrix=simulator.covariance_matrix)
4045
optimizer.solve()
4146
solution = optimizer.solution
4247
times[date] = time.time() - t1
4348
portfolio.weights = solution
4449
solutions[date] = solution
4550

51+
universe_returns = universe.todays_returns
52+
portfolio_weights = np.array(list(solution.values()))
53+
equal_weights = (1/8) * np.ones(8)
54+
portfolio_return = np.dot(universe_returns, portfolio_weights)
55+
equal_return = np.dot(universe_returns, equal_weights)
56+
wealth.append(wealth[-1] * (1 + portfolio_return))
57+
wealth_n.append(wealth_n[-1] * (1 + equal_return))
58+
59+
dates = ["2024-01-01"]
60+
for date in date_range:
61+
dates.append(str(date)[0:10])
62+
63+
np.savetxt('data.csv', np.array(wealth), delimiter=',')
64+
65+
plt.plot(dates, wealth)
66+
plt.plot(dates, wealth_n)
67+
plt.show()
4668

4769
print('\n' * 10)
4870
for date, solution in solutions.items():

src/abacus/legacy/leg_main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
from utils.stock_factory import StockFactory
99
from utils.data_handler import YahooDataHandler
1010
from utils.portfolio import Portfolio
11-
from utils.risk_assessor import RiskAssessor
11+
from abacus.assessor.risk_assessor import RiskAssessor
1212
from simulator.simulator import Simulator
13-
from optimizer.optimizer import Optimizer
13+
from abacus.optimizer.leg_optimizer import Optimizer
1414
from optimizer.enums import OptimizationModels
1515

1616

src/abacus/optimizer/leg_optimizer.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,7 @@ def _set_ampl_data(self):
5656
tensor_size = price_tensor.shape
5757
number_of_assets = tensor_size[0]
5858
number_of_scenarios = tensor_size[1]
59-
60-
price_dict = {(j+1, asset.identifier): price_tensor[asset.id][j] for asset in assets
61-
for j in range(number_of_scenarios)}
62-
59+
price_dict = {(j+1, asset.identifier): price_tensor[asset.id][j] for asset in assets for j in range(number_of_scenarios)}
6360
self._ampl.get_set("assets").set_values(asset_identifiers)
6461
self._ampl.param["gamma"] = -24
6562
self._ampl.param["risk_free_rate"] = 0.04

src/abacus/utils/instrument.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def log_returns(self) -> pd.DataFrame:
2626

2727
@property
2828
def art_returns(self) -> pd.DataFrame:
29-
return self.price_history.pct_change()[1:]
29+
return np.array(self.price_history.pct_change())[1:]
3030

3131
@property
3232
def log_returns_tensor(self) -> torch.Tensor:

src/abacus/utils/universe.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
import numpy as np
23

34
from pandas import DataFrame
45
from datetime import date
@@ -38,6 +39,10 @@ def instruments(self) -> list[Instrument]:
3839
built_instruments.append(ins)
3940
return built_instruments
4041

42+
@property
43+
def todays_returns(self):
44+
return np.array([instrument.art_returns[-1] for instrument in self.instruments]).flatten()
45+
4146
def has_updated_cache(self) -> bool:
4247
has_cache = self._instruments is not None
4348
has_last_build = self._instrument_build_date is not None

0 commit comments

Comments
 (0)