f/run_tests.sh
Greg Pomerantz 576d9fba97 Fix after-tax model: raw prices + reinvestment (was 2.7x over-taxing)
The old model valued holdings in ADJ (total-return index) units but
computed distribution flows as raw per-share dollars — so every
distribution, and its tax, was overstated by the raw/adj ratio
(JLPSX: 30.10/11.25 = 2.7x; the Dec-2020 cap-gain tax showed as 12.1%
of the account instead of the true 4.5%). The wiggle in the after-tax
curve was this bug, not a convention issue.

tax.py now:
- values holdings in RAW share units on close prices (bundle.close);
- receives the per-share distribution on its event date, pays the tax
  (recorded in TaxResult.taxes), and reinvests the after-tax remainder
  at the same day's raw close — the tax's effect lives in the (smaller)
  reinvested units and is NOT also deducted from cash (double-count
  caught and fixed in review);
- recomputes market value after the reinvestment so equity[t] is the
  post-event liquidation value.

With the fix, the 'as-if-liquidated' equity on JLPSX's ex-div day drops
by exactly the true tax cost (4.72% vs 12.1% before); the -22.9% price
drop is offset by the distribution kept.

Also:
- app.py passes bundle.close to the after-tax model (pre-tax
  portfolio_returns still uses adj);
- JLPSX/JLPYX: the 2020-12-11 6.824 capital-gain distribution is moved
  to the true ex-div date 2020-12-14 (remove/add correction ops), so
  the reinvestment prices at the post-drop close;
- tests/test_tax.py: 8 synthetic regression tests (tax magnitude,
  reinvestment MV, no double-count, ex-div equity step, per-component
  rates); run_tests.sh now runs it.
2026-08-31 23:58:15 -04:00

34 lines
978 B
Bash
Executable File

#!/usr/bin/env bash
# Full test suite: app-level (Streamlit AppTest) + real-browser e2e (Playwright).
#
# Usage: ./run_tests.sh
# The browser e2e part needs the server running (./run.sh, port 8599);
# it is skipped automatically if the server is down.
set -uo pipefail
cd "$(dirname "$0")"
fail=0
echo "=== 1/4 data cache tests (incremental refresh) ==="
.venv/bin/python tests/test_data.py || fail=1
echo
echo "=== 2/4 after-tax model tests (synthetic) ==="
.venv/bin/python tests/test_tax.py || fail=1
echo
echo "=== 3/4 app tests (AppTest, no browser) ==="
.venv/bin/python tests/test_app.py || fail=1
echo
echo "=== 4/4 browser e2e (Playwright, needs the server) ==="
if curl -s -m 3 -o /dev/null http://localhost:8599/healthz; then
.venv/bin/python tests/test_e2e_browser.py || fail=1
else
echo "server not reachable on :8599 — skipping e2e (start it with ./run.sh)"
fi
echo
[ $fail -eq 0 ] && echo "ALL TESTS PASSED" || echo "TESTS FAILED"
exit $fail