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.
66 lines
2.1 KiB
JSON
66 lines
2.1 KiB
JSON
{
|
|
"symbol": "jlpyx",
|
|
"dedup": [
|
|
[
|
|
"2017-12-13",
|
|
4.123
|
|
],
|
|
[
|
|
"2018-12-12",
|
|
4.117
|
|
],
|
|
[
|
|
"2019-12-12",
|
|
1.517
|
|
],
|
|
[
|
|
"2021-12-13",
|
|
6.785
|
|
],
|
|
[
|
|
"2022-12-13",
|
|
4.841
|
|
],
|
|
[
|
|
"2023-12-13",
|
|
1.989
|
|
],
|
|
[
|
|
"2024-12-12",
|
|
1.347
|
|
],
|
|
[
|
|
"2025-12-11",
|
|
0.656
|
|
]
|
|
],
|
|
"note": "Bulk correction from the double-listing scan (scripts/scan_double_listing.py): Yahoo listed this distribution in both the dividend and capitalGains event files (same date, same amount); one copy is spurious. The 'dedup' invariant keeps at most one copy, layout-agnostically. Mechanism verified against official filings for JLPSX/GDEUX/GSOUX/FAEVX/CVSIX/FZAGX; mechanism-inferred for this symbol (no per-fund official check). Revert the entry if a future official cross-check shows both rows were real. adj-close repair: Yahoo dated a distribution on 2020-12-11 (record date) but the price went ex-div on 2020-12-14 (close 30.29 -> 23.40, drop ~6.824); the raw Adj Close column spiked +29.1% on 2020-12-11 and snapped back later. Cells in [2020-12-11, 2020-12-14) rescaled by (1-f) so the adjusted path is smooth; cumulative returns are unchanged. Mechanism: scripts/fix_adj_misalign.py, scan: reports/adj_misalign/scan.md. Distribution date moved 2020-12-11 -> 2020-12-14 (true ex-div date, close 30.10 -> 23.22 for JLPSX / 30.29 -> 23.40 for JLPYX): Yahoo dated the 6.824 capital-gain distribution on the 12-11 record date, but the after-tax model reinvests at the event date's raw close, so the cash flow must sit on the day the price actually dropped. Ops: remove both file copies on 12-11, add the capitalGains copy on 12-14 (kept in capitalGains so it is taxed at the cap-gain rate, matching the 497's CG 6.82 / NII 0.07 split).",
|
|
"history": {
|
|
"2020-12-11": {
|
|
"Adj Close": 11.400895
|
|
}
|
|
},
|
|
"dividends": {
|
|
"remove": [
|
|
[
|
|
"2020-12-11",
|
|
6.824
|
|
]
|
|
]
|
|
},
|
|
"capitalGains": {
|
|
"remove": [
|
|
[
|
|
"2020-12-11",
|
|
6.824
|
|
]
|
|
],
|
|
"add": [
|
|
[
|
|
"2020-12-14",
|
|
6.824
|
|
]
|
|
]
|
|
}
|
|
}
|