The sweep harness and ci_activate.py read the tier with the public
mbt.license_info(), and the parity-only check uses the published
Community limit of 256 combinations per sweep. Checked locally: a
licensed run times the grid, an unlicensed one is skipped, and
parity-only still runs below the limit and is skipped above it.
plotly 7.0.0 landed on PyPI and removed the mapbox trace types that
vectorbt 0.28.4's template still references, so 'import vectorbt' died
before a single bar ran. plotly was the one transitive dependency the
lock did not cover; it does now, on 6.9.0, the last 6.x line. The
version printout includes it so the results stay comparable.
The root testpaths points at python/tests, so nothing collected
benchmarks/vs_vectorbt/test_report.py, which arrived with #13. A light
job (pytest alone, no wheel) runs them on every push and pull request.
Authored upstream; the release sync will keep carrying this copy.
A documented point whose timing was never published appears nowhere in
the report, so a measured size for it would be an explanation with
nothing to explain. Fails against the parent of the previous commit.
render() fed `documented` to _divergence_note, so a documented row
without a published timing would have got a measured-size bullet under
a table it does not appear in. The note explains the timings published
above it, so it takes `timed`. Follow-up to #13, which made the note
per-row and left the population as it found it.
README.md publishes a documented verdict as "the timing, in an annex, with
the cause and its measured size". render() printed the size for the first
documented row and broke out of the loop, so the run at 93ad928 published
three bracket_sl_tp timings under one measured line.
The line that printed is the 100,000-bar point, where raptorbt sits 0.92% of
capital from the reference. The two without one are 1,000,000 bars, where it
sits 10.07% away and crosses from below the reference to above it, and
10,000,000 bars, where the round-trip delta is 93,295.
_divergence_note now takes the rows rather than a row, and states the cause
once underneath them. The lines become bullets: three consecutive lines are
one paragraph in CommonMark, and every other multi-fact block in this file
is already a list.
Names which paths are maintained on this mirror and which are
overwritten by the release sync, and states that contributions are
accepted under Apache 2.0 without the Commons Clause.
The other two tests in the file run plain backtests on daily data and
still measure the leak on a Community wheel; only the detect_lookahead
call is Pro-gated, so the guard is per-test.
This CI runs the mirrored suite against the PyPI wheel without a licence.
Twelve tests exercised paths Community gates: walk-forward optimization
raises LicenseError before any geometry is read, and the look-ahead
detector both needs Pro and counts sub-daily bars that the Community
daily floor reduces to four. Same module-level guard the sweep tests
already carry, with the reason named.
Seven badges on one wrapped line buried the only one meant to be clicked. Discord
now sits alone above the rest, in the large style, and the second line keeps four
informational ones: PyPI, Python, Rust, benchmarks. Dropped the licence badge,
which repeated the LICENSE link already in the footer.
The pyversions badge was rendering "missing" in red, and it was right to. Every
published wheel carries NO `Programming Language :: Python :: 3.x` classifier:
crates/bt-python/pyproject.toml, the file maturin actually builds from, has no
`classifiers` field at all. The public pyproject.toml has one, but it does not
build anything, so its list never reached PyPI. `requires-python = ">=3.9"` is a
separate field and does not populate classifiers.
Replaced with a static "python 3.9+" badge, since PyPI cannot answer the question
for 0.18.0 whatever we ask it. The engine-side fix travels separately; once a
wheel ships with classifiers, PyPI's sidebar will list the versions too and this
can go back to being dynamic.
The performance table was still quoting run #11 (manifoldbt 0.17.3), while the
site publishes run #13 (0.18.0) from the same workflow. Same shape, different
numbers, and the headline claim disagreed with the site by a few percent:
10M bars with the metric suite is 329 ms against 102.38 s, a factor of 311,
not 317 ms / 97.46 s / 308. Every row now comes from run 32469701489, the one
data/benchmark.json is synced from.
Added the stop-loss/take-profit bracket row, where raptorbt is level with us
(x1.0). It belongs next to the five-asset row for the same reason that one is
there: deciding which of the stop and the target triggers first is a sequential
intra-bar walk in both engines, so there is nothing left to vectorise. Publishing
only the workloads we win looks better and reads worse.
Qualified the backtrader figure. It is measured on a developer machine with a
different script, not on the CI runner, so quoting it beside a CI table implied a
comparability it does not have. It also no longer appears in the headline bullet:
the site makes no numeric backtrader claim, and the two engines are not doing the
same work.
Documented the two additions that were reachable but undocumented:
- tf("1h").apply(expr) evaluates on that timeframe's own grid, so periods count
in ITS bars. The note warns about sma(tf("1h").close, 20), which looks
equivalent and is not: it counts simulation bars over a step-held series, so
on a 1m run it is a 20-minute smoothing of an hourly staircase.
- choice(name, {branch: expr}) makes a selector a grid axis.
Every snippet in these two sections was executed verbatim against the 0.19.0rc1
wheel before committing, including the warning, which was checked to actually
differ rather than asserted.
Header badges: PyPI version and Python versions (both live), Rust core, CUDA,
benchmarks-in-CI linking the workflow, and the licence.