Reproducible market research toolkit for weekly modeling, walk-forward evaluation, and baseline-plus-ML experiments.
Project description
MarketLab
MarketLab is a package-first research toolkit for reproducible market experiments over a fixed ETF universe. The current implementation includes a working baseline-plus-ML workflow: weekly supervised modeling rows, walk-forward folds, trained models, rank-based ML strategies, shared out-of-sample experiments, and reviewable artifact summaries.
See ARCHITECTURE.md for the system map, data contracts, execution flow, and extension rules.
Current Commands
python scripts/run_marketlab.py prepare-data --config configs/experiment.weekly_rank.yaml
python scripts/run_marketlab.py backtest --config configs/experiment.weekly_rank.yaml
python scripts/run_marketlab.py train-models --config configs/experiment.weekly_rank.yaml
python scripts/run_marketlab.py run-experiment --config configs/experiment.weekly_rank.yaml
python scripts/run_marketlab.py ... is the canonical local invocation path because it always resolves to the source tree under src/.
What Each Command Does
prepare-data: build or reuse the cached prepared panel.backtest: run the rule baselines only (buy_holdandsma) and write performance, analytics summaries, report, and plots.train-models: fit the configured models across walk-forward folds and write raw training artifacts plus fold/model summary CSVs.run-experiment: run baselines and ML strategies together on the shared out-of-sample window and write the experiment outputs, analytics summaries, and ML summary CSVs.
Artifact Outputs
train-models
Writes a timestamped folder under artifacts/runs/<experiment_name>/ containing:
folds.csvmodel_manifest.csvmodel_metrics.csvpredictions.csvmodel_summary.csvfold_summary.csv- per-fold model pickles under
models/
backtest
Writes a timestamped folder under artifacts/runs/<experiment_name>/ containing:
metrics.csvperformance.csvstrategy_summary.csvmonthly_returns.csvturnover_costs.csvreport.mdcumulative_returns.pngdrawdown.pngturnover.png
run-experiment
Writes a timestamped folder under artifacts/runs/<experiment_name>/ containing:
metrics.csvperformance.csvstrategy_summary.csvmonthly_returns.csvturnover_costs.csvreport.mdcumulative_returns.pngdrawdown.pngturnover.pngmodel_summary.csvfold_summary.csv- optional per-fold model pickles under
models/
Environment
- Python 3.12+
- Installed packages:
pandasPyYAMLmatplotlibyfinancescikit-learn
Quickstart
python -m pip install -e .[dev]
python scripts/run_marketlab.py run-experiment --config configs/experiment.weekly_rank.yaml
If artifacts/data/panel.csv already exists, the pipeline uses it and does not attempt a network download.
Installed Package Quickstart
If you install MarketLab from PyPI or a built wheel, use the packaged CLI bootstrap flow instead of the repo launcher:
marketlab --version
marketlab list-configs
marketlab write-config --name weekly_rank --output weekly_rank.yaml
marketlab run-experiment --config weekly_rank.yaml
list-configs shows the bundled example templates, and write-config exports one of those templates into your working directory. That keeps the installed package self-contained without requiring a checkout of this repository.
Local Validation
python -m pytest -q --basetemp .pytest_tmp
powershell -ExecutionPolicy Bypass -File scripts/run-e2e.ps1
Local CI Entry Points
python -m uv sync --group dev
python -m uv run tox -e lint
python -m uv run tox -e docs
python -m uv run tox -e package
python -m uv run tox -e py312
python -m tox -e integration
python -m tox -e preflight
Use python -m tox -e preflight as the canonical local pre-push gate. It runs the same lint, docs, packaging, unit-test, and offline integration checks that Phase 3 CI expects through one local entrypoint after the dev dependencies are installed.
The MkDocs site renders the current root Markdown docs through mkdocs-include-markdown-plugin, so the documentation build stays aligned with README.md, ARCHITECTURE.md, Phase2-results.md, and PLAN.md.
Contribution Workflow
- Branch from a refreshed
masterinstead of working directly on the default branch. - Keep changes in small intentional commits so review scope stays clear.
- Run
python -m tox -e preflightbefore pushing. - Open a pull request for review instead of pushing directly to
master. - Treat the
Docker Runnerworkflow as an optional manual smoke path, not as a required pre-push step. - Keep Codex skills and other personal automation assets in the user-local Codex home rather than in the public repository or package surface.
- Expect
masterto move ahead of the last public release between monthly release batches.
Dockerized CLI
docker build -t marketlab-cli .
docker run --rm marketlab-cli --help
docker run --rm marketlab-cli backtest --config configs/experiment.weekly_rank.smoke.yaml
The container uses the installed marketlab console script as its entrypoint. Keep using python scripts/run_marketlab.py ... for local source-tree development; the Docker image exists to validate the installed package path and to support manual GitHub Actions runs.
Manual Docker Runner Workflow
GitHub Actions now includes a manual workflow named Docker Runner with these inputs:
command:backtest,train-models, orrun-experimentconfig_path: repo-relative config path inside the image, defaulting toconfigs/experiment.weekly_rank.smoke.yaml
The workflow defaults to backtest, builds the Docker image, runs the selected command inside the container, writes the resolved run directory into the job summary, and uploads the copied artifacts/ tree as an Actions artifact.
This workflow is not part of the required PR CI checks. It is a manual historical real-data smoke runner around the checked-in smoke config, not a rolling weekly market automation job.
Release Automation
GitHub Actions now includes a release workflow at .github/workflows/release.yml.
- Normal feature PRs still merge to
masterin sequence. - Each merge to
masterupdates the open Release PR managed by release-please. - The Release PR accumulates the unreleased monthly or feature batch over time.
- Nothing is tagged or published when a normal feature PR lands on
master. - The actual Git tag, GitHub Release, and PyPI publish path run only when you merge the Release PR.
This means master can intentionally contain unreleased work while you continue merging feature PRs. The Release PR is the public-release gate.
Manual Prerequisites
Before the first automated public release:
- verify that the
marketlabpackage name is available on PyPI - configure PyPI Trusted Publishing for this repository and the
pypienvironment - create the GitHub Actions environment named
pypi
The first automated public release target remains v0.1.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file marketlab-0.1.0.tar.gz.
File metadata
- Download URL: marketlab-0.1.0.tar.gz
- Upload date:
- Size: 30.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
536962f24d3f10b72f493833cc47b005317b6361077c24722dddbd8df5a29d0c
|
|
| MD5 |
5d8483b71209076ca09a409c217d9acf
|
|
| BLAKE2b-256 |
073ba92214ce55722000250155789bf7b93c016af3104e21ee6d83a7f4ee4093
|
Provenance
The following attestation bundles were made for marketlab-0.1.0.tar.gz:
Publisher:
release.yml on ricardogr07/market-lab
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marketlab-0.1.0.tar.gz -
Subject digest:
536962f24d3f10b72f493833cc47b005317b6361077c24722dddbd8df5a29d0c - Sigstore transparency entry: 1191980460
- Sigstore integration time:
-
Permalink:
ricardogr07/market-lab@233f8bfb4f5c453b63f3e481e845519003c5b0e4 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/ricardogr07
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@233f8bfb4f5c453b63f3e481e845519003c5b0e4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file marketlab-0.1.0-py3-none-any.whl.
File metadata
- Download URL: marketlab-0.1.0-py3-none-any.whl
- Upload date:
- Size: 37.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53211ba0d01464767455b56dafa7cd2ee00d6345b2f8a3e31bd96775a277a200
|
|
| MD5 |
23b1e4f9a3470e6946d25465c9ab8c45
|
|
| BLAKE2b-256 |
f4105aeb7931babba6a915b2a3b6466eae466836d17278a06708336abeccc615
|
Provenance
The following attestation bundles were made for marketlab-0.1.0-py3-none-any.whl:
Publisher:
release.yml on ricardogr07/market-lab
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marketlab-0.1.0-py3-none-any.whl -
Subject digest:
53211ba0d01464767455b56dafa7cd2ee00d6345b2f8a3e31bd96775a277a200 - Sigstore transparency entry: 1191980463
- Sigstore integration time:
-
Permalink:
ricardogr07/market-lab@233f8bfb4f5c453b63f3e481e845519003c5b0e4 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/ricardogr07
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@233f8bfb4f5c453b63f3e481e845519003c5b0e4 -
Trigger Event:
push
-
Statement type: