Skip to content

Commit

Permalink
made test for edge case targeted by PR #114 (thanks!)
Browse files Browse the repository at this point in the history
  • Loading branch information
enzbus committed Oct 31, 2023
1 parent 9584c04 commit 3c80d89
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 5 deletions.
9 changes: 4 additions & 5 deletions cvxportfolio/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,11 @@ def _change_universe(self, new_universe):

# if new universe is larger we use it as ordering
# this is the default situation with yfinance data
if self._current_universe.isin(new_universe).all():
# careful (thanks gh PR #114) because we need the
# _current_full_universe, otherwise we drop assets that
# are not traded any more
if self._current_full_universe.isin(new_universe).all():
joined = new_universe
# preprend all all the assets from full that are not in joined
joined = joined.insert(0, sorted(
set(self._current_full_universe[:-1])
- set(joined)))

# otherwise we lose the ordering :(
else:
Expand Down
33 changes: 33 additions & 0 deletions cvxportfolio/tests/test_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,39 @@ def test_simulator_raises(self):
columns=['X', 'USDOLLAR']),
volumes=pd.DataFrame([[0.]]))

def test_backtest_with_ipos_and_delistings(self):
"""Test back-test with assets that both enter and exit."""
rets = pd.DataFrame(self.returns.iloc[:, -10:], copy=True)
volumes = pd.DataFrame(self.volumes.iloc[:, -9:], copy=True)
prices = pd.DataFrame(self.prices.iloc[:, -9:], copy=True)
rets.iloc[14:25, 1:3] = np.nan
rets.iloc[9:17, 3:5] = np.nan
rets.iloc[8:15, 5:7] = np.nan
rets.iloc[16:29, 7:8] = np.nan
print(rets.iloc[10:20])
# raise Exception

modified_market_data = cvx.UserProvidedMarketData(
returns=rets, volumes=volumes, prices=prices,
cash_key='cash',
min_history=pd.Timedelta('0d'))

simulator = cvx.StockMarketSimulator(market_data=modified_market_data)

policy = cvx.SinglePeriodOptimization(
cvx.ReturnsForecast() - 10 * cvx.FullCovariance(),
[cvx.LongOnly(), cvx.LeverageLimit(1)])

bt_result = simulator.backtest(policy, start_time = rets.index[10],
end_time = rets.index[20])

print(bt_result.w)

self.assertTrue(set(bt_result.w.columns) == set(rets.columns))
self.assertTrue(
np.all(bt_result.w.iloc[:-1].isnull() == rets.iloc[
10:20].isnull()))

def test_backtest_with_difficult_universe_changes(self):
"""Test back-test with assets that both enter and exit at same time."""
rets = pd.DataFrame(self.returns.iloc[:, -10:], copy=True)
Expand Down

0 comments on commit 3c80d89

Please sign in to comment.