quantred 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quantred-2.4.0/.dockerignore +23 -0
- quantred-2.4.0/.env.example +27 -0
- quantred-2.4.0/.github/pull_request_template.md +22 -0
- quantred-2.4.0/.github/scripts/require_published_dependency.py +65 -0
- quantred-2.4.0/.github/workflows/ci.yml +102 -0
- quantred-2.4.0/.github/workflows/docs.yml +110 -0
- quantred-2.4.0/.github/workflows/release.yml +98 -0
- quantred-2.4.0/.gitignore +171 -0
- quantred-2.4.0/.gitleaksignore +5 -0
- quantred-2.4.0/.nvmrc +1 -0
- quantred-2.4.0/AGENTS.md +53 -0
- quantred-2.4.0/CLAUDE.md +1 -0
- quantred-2.4.0/CONTRIBUTING.md +75 -0
- quantred-2.4.0/Dockerfile +62 -0
- quantred-2.4.0/LICENSE +21 -0
- quantred-2.4.0/Makefile +213 -0
- quantred-2.4.0/PKG-INFO +632 -0
- quantred-2.4.0/README.md +573 -0
- quantred-2.4.0/conftest.py +14 -0
- quantred-2.4.0/docker-compose.yml +127 -0
- quantred-2.4.0/docs/.nvmrc +1 -0
- quantred-2.4.0/docs/content/changelog.md +1107 -0
- quantred-2.4.0/docs/content/engineering/alphas.md +246 -0
- quantred-2.4.0/docs/content/engineering/architecture.md +93 -0
- quantred-2.4.0/docs/content/engineering/attribution.md +131 -0
- quantred-2.4.0/docs/content/engineering/broker-abstraction.md +163 -0
- quantred-2.4.0/docs/content/engineering/coding-standards.md +71 -0
- quantred-2.4.0/docs/content/engineering/data-flow.md +77 -0
- quantred-2.4.0/docs/content/engineering/data-panel.md +93 -0
- quantred-2.4.0/docs/content/engineering/embedding.md +95 -0
- quantred-2.4.0/docs/content/engineering/engine.md +166 -0
- quantred-2.4.0/docs/content/engineering/evaluation-metrics.md +128 -0
- quantred-2.4.0/docs/content/engineering/extending.md +180 -0
- quantred-2.4.0/docs/content/engineering/indicators.md +55 -0
- quantred-2.4.0/docs/content/engineering/information-analysis.md +108 -0
- quantred-2.4.0/docs/content/engineering/information-horizon.md +94 -0
- quantred-2.4.0/docs/content/engineering/mcp-server.md +324 -0
- quantred-2.4.0/docs/content/engineering/multi-period-trading.md +147 -0
- quantred-2.4.0/docs/content/engineering/multi-signal.md +89 -0
- quantred-2.4.0/docs/content/engineering/optimization.md +123 -0
- quantred-2.4.0/docs/content/engineering/philosophy.md +101 -0
- quantred-2.4.0/docs/content/engineering/portfolio-construction.md +266 -0
- quantred-2.4.0/docs/content/engineering/portfolio.md +75 -0
- quantred-2.4.0/docs/content/engineering/research-agent.md +145 -0
- quantred-2.4.0/docs/content/engineering/risk-model.md +145 -0
- quantred-2.4.0/docs/content/engineering/scanners.md +55 -0
- quantred-2.4.0/docs/content/engineering/separation-of-concerns.md +74 -0
- quantred-2.4.0/docs/content/engineering/strategies.md +140 -0
- quantred-2.4.0/docs/content/engineering/testing.md +89 -0
- quantred-2.4.0/docs/content/engineering/transaction-costs.md +105 -0
- quantred-2.4.0/docs/content/engineering/verdict.md +137 -0
- quantred-2.4.0/docs/content/engineering/walk-forward.md +263 -0
- quantred-2.4.0/docs/content/intro.md +94 -0
- quantred-2.4.0/docs/content/usage/agents.md +241 -0
- quantred-2.4.0/docs/content/usage/alphas.md +157 -0
- quantred-2.4.0/docs/content/usage/backtesting.md +305 -0
- quantred-2.4.0/docs/content/usage/brokers.md +58 -0
- quantred-2.4.0/docs/content/usage/configuration.md +215 -0
- quantred-2.4.0/docs/content/usage/docker.md +123 -0
- quantred-2.4.0/docs/content/usage/extras.md +75 -0
- quantred-2.4.0/docs/content/usage/first-run.md +300 -0
- quantred-2.4.0/docs/content/usage/getting-started.md +223 -0
- quantred-2.4.0/docs/content/usage/horizon.md +71 -0
- quantred-2.4.0/docs/content/usage/html-reports.md +106 -0
- quantred-2.4.0/docs/content/usage/information.md +190 -0
- quantred-2.4.0/docs/content/usage/installation.md +136 -0
- quantred-2.4.0/docs/content/usage/live-trading.md +941 -0
- quantred-2.4.0/docs/content/usage/migrating-to-quantred.md +256 -0
- quantred-2.4.0/docs/content/usage/optimization.md +146 -0
- quantred-2.4.0/docs/content/usage/portfolio.md +202 -0
- quantred-2.4.0/docs/content/usage/private-strategies.md +182 -0
- quantred-2.4.0/docs/content/usage/risk.md +109 -0
- quantred-2.4.0/docs/content/usage/run-configs.md +121 -0
- quantred-2.4.0/docs/content/usage/scanning.md +97 -0
- quantred-2.4.0/docs/content/usage/screening.md +139 -0
- quantred-2.4.0/docs/content/usage/stopping.md +223 -0
- quantred-2.4.0/docs/content/usage/trials.md +632 -0
- quantred-2.4.0/docs/content/usage/validation-diagnostics.md +271 -0
- quantred-2.4.0/docs/content/usage/verdict.md +204 -0
- quantred-2.4.0/docs/content/usage/walk-forward.md +344 -0
- quantred-2.4.0/docs/docusaurus.config.js +77 -0
- quantred-2.4.0/docs/package-lock.json +20967 -0
- quantred-2.4.0/docs/package.json +28 -0
- quantred-2.4.0/docs/sidebars.js +80 -0
- quantred-2.4.0/docs/src/css/custom.css +15 -0
- quantred-2.4.0/docs/static/.gitkeep +0 -0
- quantred-2.4.0/docs/static/img/demo.png +0 -0
- quantred-2.4.0/docs/wrangler.jsonc +14 -0
- quantred-2.4.0/example/.gitignore +8 -0
- quantred-2.4.0/example/README.md +206 -0
- quantred-2.4.0/example/configs/breakout.json +29 -0
- quantred-2.4.0/example/configs/reversion_longshort.json +31 -0
- quantred-2.4.0/example/my_signals/__init__.py +0 -0
- quantred-2.4.0/example/my_signals/scanners/__init__.py +5 -0
- quantred-2.4.0/example/my_signals/scanners/liquidity.py +85 -0
- quantred-2.4.0/example/my_signals/strategies/__init__.py +11 -0
- quantred-2.4.0/example/my_signals/strategies/breakout.py +156 -0
- quantred-2.4.0/example/my_signals/strategies/pairs_reversion.py +133 -0
- quantred-2.4.0/example/pyproject.toml +39 -0
- quantred-2.4.0/main.py +14 -0
- quantred-2.4.0/pyproject.toml +172 -0
- quantred-2.4.0/quantred/__init__.py +24 -0
- quantred-2.4.0/quantred/alphas/__init__.py +53 -0
- quantred-2.4.0/quantred/alphas/base.py +221 -0
- quantred-2.4.0/quantred/alphas/combine.py +260 -0
- quantred-2.4.0/quantred/alphas/horizon.py +153 -0
- quantred-2.4.0/quantred/alphas/refine.py +300 -0
- quantred-2.4.0/quantred/alphas/scorers.py +87 -0
- quantred-2.4.0/quantred/analytics/attribution.py +354 -0
- quantred-2.4.0/quantred/analytics/bootstrap.py +353 -0
- quantred-2.4.0/quantred/analytics/charts.py +393 -0
- quantred-2.4.0/quantred/analytics/excursion.py +185 -0
- quantred-2.4.0/quantred/analytics/execution_quality.py +180 -0
- quantred-2.4.0/quantred/analytics/exposure.py +167 -0
- quantred-2.4.0/quantred/analytics/htmlreport.py +1208 -0
- quantred-2.4.0/quantred/analytics/information.py +197 -0
- quantred-2.4.0/quantred/analytics/metrics.py +502 -0
- quantred-2.4.0/quantred/analytics/performance.py +639 -0
- quantred-2.4.0/quantred/analytics/reporting.py +1672 -0
- quantred-2.4.0/quantred/analytics/screening.py +190 -0
- quantred-2.4.0/quantred/analytics/series_comparison.py +303 -0
- quantred-2.4.0/quantred/analytics/trade_analytics.py +353 -0
- quantred-2.4.0/quantred/brokers/alpaca/broker.py +415 -0
- quantred-2.4.0/quantred/brokers/alpaca/factory.py +33 -0
- quantred-2.4.0/quantred/brokers/alpaca/market_data.py +166 -0
- quantred-2.4.0/quantred/brokers/base.py +220 -0
- quantred-2.4.0/quantred/brokers/dryrun.py +164 -0
- quantred-2.4.0/quantred/brokers/errors.py +70 -0
- quantred-2.4.0/quantred/cli.py +8619 -0
- quantred-2.4.0/quantred/costs/__init__.py +11 -0
- quantred-2.4.0/quantred/costs/base.py +126 -0
- quantred-2.4.0/quantred/costs/parametric.py +131 -0
- quantred-2.4.0/quantred/data/__init__.py +29 -0
- quantred-2.4.0/quantred/data/compute.py +332 -0
- quantred-2.4.0/quantred/data/edges.py +81 -0
- quantred-2.4.0/quantred/data/features.py +120 -0
- quantred-2.4.0/quantred/data/panel.py +61 -0
- quantred-2.4.0/quantred/data/scan.py +85 -0
- quantred-2.4.0/quantred/data/store.py +269 -0
- quantred-2.4.0/quantred/demo/__init__.py +22 -0
- quantred-2.4.0/quantred/demo/scanners.py +104 -0
- quantred-2.4.0/quantred/demo/strategies.py +125 -0
- quantred-2.4.0/quantred/engine/backtest.py +1206 -0
- quantred-2.4.0/quantred/engine/barcheck.py +228 -0
- quantred-2.4.0/quantred/engine/live.py +539 -0
- quantred-2.4.0/quantred/execution/decision.py +192 -0
- quantred-2.4.0/quantred/execution/flatten.py +302 -0
- quantred-2.4.0/quantred/execution/halt.py +165 -0
- quantred-2.4.0/quantred/execution/ledger.py +758 -0
- quantred-2.4.0/quantred/execution/live_trader.py +587 -0
- quantred-2.4.0/quantred/execution/order_id.py +83 -0
- quantred-2.4.0/quantred/execution/sizing.py +114 -0
- quantred-2.4.0/quantred/indicators/indicators.py +158 -0
- quantred-2.4.0/quantred/marketdata/base.py +62 -0
- quantred-2.4.0/quantred/marketdata/client.py +59 -0
- quantred-2.4.0/quantred/marketdata/session.py +112 -0
- quantred-2.4.0/quantred/marketdata/synthetic.py +74 -0
- quantred-2.4.0/quantred/marketdata/timeframe.py +125 -0
- quantred-2.4.0/quantred/mcp/__init__.py +6 -0
- quantred-2.4.0/quantred/mcp/selftest.py +139 -0
- quantred-2.4.0/quantred/mcp/server.py +2419 -0
- quantred-2.4.0/quantred/optimization/causality.py +607 -0
- quantred-2.4.0/quantred/optimization/config_store.py +300 -0
- quantred-2.4.0/quantred/optimization/optimizer.py +431 -0
- quantred-2.4.0/quantred/optimization/parallel.py +345 -0
- quantred-2.4.0/quantred/optimization/param_space.py +309 -0
- quantred-2.4.0/quantred/optimization/walk_forward.py +1254 -0
- quantred-2.4.0/quantred/portfolio/allocator.py +135 -0
- quantred-2.4.0/quantred/portfolio/benchmark.py +109 -0
- quantred-2.4.0/quantred/portfolio/optimizer.py +786 -0
- quantred-2.4.0/quantred/portfolio/policy.py +335 -0
- quantred-2.4.0/quantred/portfolio/posterior.py +208 -0
- quantred-2.4.0/quantred/research/__init__.py +30 -0
- quantred-2.4.0/quantred/research/agent.py +868 -0
- quantred-2.4.0/quantred/research/demo_proposals.py +222 -0
- quantred-2.4.0/quantred/research/llm.py +311 -0
- quantred-2.4.0/quantred/research/proposer.py +234 -0
- quantred-2.4.0/quantred/research/provider_errors.py +242 -0
- quantred-2.4.0/quantred/research/sandbox.py +340 -0
- quantred-2.4.0/quantred/risk/__init__.py +60 -0
- quantred-2.4.0/quantred/risk/base.py +218 -0
- quantred-2.4.0/quantred/risk/conditional.py +474 -0
- quantred-2.4.0/quantred/risk/exposures.py +88 -0
- quantred-2.4.0/quantred/risk/factor.py +119 -0
- quantred-2.4.0/quantred/risk/sample.py +89 -0
- quantred-2.4.0/quantred/risk/streaming.py +214 -0
- quantred-2.4.0/quantred/scanners/base.py +141 -0
- quantred-2.4.0/quantred/scanners/symbol_scanner.py +148 -0
- quantred-2.4.0/quantred/services/__init__.py +51 -0
- quantred-2.4.0/quantred/services/analysis.py +6082 -0
- quantred-2.4.0/quantred/services/audit.py +574 -0
- quantred-2.4.0/quantred/services/campaign.py +381 -0
- quantred-2.4.0/quantred/services/configs.py +282 -0
- quantred-2.4.0/quantred/services/data.py +172 -0
- quantred-2.4.0/quantred/services/dryrun.py +206 -0
- quantred-2.4.0/quantred/services/glossary.py +130 -0
- quantred-2.4.0/quantred/services/maintenance.py +314 -0
- quantred-2.4.0/quantred/services/registry.py +351 -0
- quantred-2.4.0/quantred/services/setup.py +1023 -0
- quantred-2.4.0/quantred/services/sizing.py +150 -0
- quantred-2.4.0/quantred/services/smallreal.py +450 -0
- quantred-2.4.0/quantred/settings.py +571 -0
- quantred-2.4.0/quantred/store/__init__.py +0 -0
- quantred-2.4.0/quantred/store/bars.py +660 -0
- quantred-2.4.0/quantred/store/trials.py +1804 -0
- quantred-2.4.0/quantred/strategies/base.py +643 -0
- quantred-2.4.0/quantred/strategies/signals.py +28 -0
- quantred-2.4.0/quantred/utils/errors.py +48 -0
- quantred-2.4.0/quantred/utils/extras.py +330 -0
- quantred-2.4.0/quantred/utils/logging_config.py +33 -0
- quantred-2.4.0/quantred/utils/numeric.py +46 -0
- quantred-2.4.0/quantred/utils/streaming.py +474 -0
- quantred-2.4.0/quantred/utils/timeutils.py +148 -0
- quantred-2.4.0/scripts/check_links.py +162 -0
- quantred-2.4.0/scripts/compose_smoke.sh +86 -0
- quantred-2.4.0/tests/conftest.py +39 -0
- quantred-2.4.0/tests/fakes.py +500 -0
- quantred-2.4.0/tests/state_leak_guard.py +100 -0
- quantred-2.4.0/tests/test_alphas.py +307 -0
- quantred-2.4.0/tests/test_attribution.py +447 -0
- quantred-2.4.0/tests/test_backtest.py +1209 -0
- quantred-2.4.0/tests/test_backtest_surface_parity.py +148 -0
- quantred-2.4.0/tests/test_bar_cache.py +664 -0
- quantred-2.4.0/tests/test_bar_path_concurrency.py +186 -0
- quantred-2.4.0/tests/test_benchmark_portfolio.py +109 -0
- quantred-2.4.0/tests/test_black_litterman.py +227 -0
- quantred-2.4.0/tests/test_bootstrap_skill.py +262 -0
- quantred-2.4.0/tests/test_broker_errors.py +203 -0
- quantred-2.4.0/tests/test_campaign_material.py +665 -0
- quantred-2.4.0/tests/test_causality_probes.py +365 -0
- quantred-2.4.0/tests/test_cli_dates.py +280 -0
- quantred-2.4.0/tests/test_cli_help.py +95 -0
- quantred-2.4.0/tests/test_cli_hints.py +83 -0
- quantred-2.4.0/tests/test_cli_input_refusals.py +705 -0
- quantred-2.4.0/tests/test_cli_name.py +229 -0
- quantred-2.4.0/tests/test_closing_inventory.py +108 -0
- quantred-2.4.0/tests/test_combine.py +121 -0
- quantred-2.4.0/tests/test_compute.py +464 -0
- quantred-2.4.0/tests/test_conditional_risk.py +345 -0
- quantred-2.4.0/tests/test_conditional_risk_service.py +167 -0
- quantred-2.4.0/tests/test_cost_aware.py +543 -0
- quantred-2.4.0/tests/test_costs.py +143 -0
- quantred-2.4.0/tests/test_data.py +110 -0
- quantred-2.4.0/tests/test_diagnostic_surfaces.py +565 -0
- quantred-2.4.0/tests/test_docs_commands.py +190 -0
- quantred-2.4.0/tests/test_dry_run.py +626 -0
- quantred-2.4.0/tests/test_dst_boundaries.py +151 -0
- quantred-2.4.0/tests/test_example_pack.py +288 -0
- quantred-2.4.0/tests/test_execution_quality.py +413 -0
- quantred-2.4.0/tests/test_extension_registry.py +511 -0
- quantred-2.4.0/tests/test_extras_map.py +478 -0
- quantred-2.4.0/tests/test_forecast_refinement_v2.py +285 -0
- quantred-2.4.0/tests/test_halt.py +631 -0
- quantred-2.4.0/tests/test_holdout_history.py +170 -0
- quantred-2.4.0/tests/test_honest_labels.py +287 -0
- quantred-2.4.0/tests/test_horizon.py +121 -0
- quantred-2.4.0/tests/test_html_report.py +386 -0
- quantred-2.4.0/tests/test_html_report_ux.py +304 -0
- quantred-2.4.0/tests/test_information.py +161 -0
- quantred-2.4.0/tests/test_ledger_fill_accounting.py +725 -0
- quantred-2.4.0/tests/test_links.py +110 -0
- quantred-2.4.0/tests/test_live_hardening.py +1116 -0
- quantred-2.4.0/tests/test_live_portfolio_cli.py +456 -0
- quantred-2.4.0/tests/test_live_trader.py +575 -0
- quantred-2.4.0/tests/test_long_short.py +380 -0
- quantred-2.4.0/tests/test_market_data_feed.py +112 -0
- quantred-2.4.0/tests/test_mcp_bad_input.py +118 -0
- quantred-2.4.0/tests/test_mcp_description_truth.py +538 -0
- quantred-2.4.0/tests/test_mcp_json_safe.py +115 -0
- quantred-2.4.0/tests/test_mcp_keyless.py +125 -0
- quantred-2.4.0/tests/test_mcp_save_config.py +163 -0
- quantred-2.4.0/tests/test_mcp_shutdown.py +277 -0
- quantred-2.4.0/tests/test_mcp_stdio.py +285 -0
- quantred-2.4.0/tests/test_mcp_surface.py +1195 -0
- quantred-2.4.0/tests/test_memoized_backtest.py +205 -0
- quantred-2.4.0/tests/test_min_notional_parity.py +148 -0
- quantred-2.4.0/tests/test_model_probe.py +486 -0
- quantred-2.4.0/tests/test_multi_period_policy.py +437 -0
- quantred-2.4.0/tests/test_net_cap_derivation.py +184 -0
- quantred-2.4.0/tests/test_net_exposure.py +142 -0
- quantred-2.4.0/tests/test_offline.py +112 -0
- quantred-2.4.0/tests/test_optimizer.py +110 -0
- quantred-2.4.0/tests/test_optimizer_book.py +150 -0
- quantred-2.4.0/tests/test_packaging.py +362 -0
- quantred-2.4.0/tests/test_parallel_trials.py +303 -0
- quantred-2.4.0/tests/test_param_constraints.py +220 -0
- quantred-2.4.0/tests/test_portfolio.py +55 -0
- quantred-2.4.0/tests/test_portfolio_excursion.py +276 -0
- quantred-2.4.0/tests/test_portfolio_optimizer.py +351 -0
- quantred-2.4.0/tests/test_promoted_cost.py +128 -0
- quantred-2.4.0/tests/test_release_order.py +70 -0
- quantred-2.4.0/tests/test_research.py +615 -0
- quantred-2.4.0/tests/test_research_cli.py +251 -0
- quantred-2.4.0/tests/test_research_history.py +133 -0
- quantred-2.4.0/tests/test_research_rounds.py +284 -0
- quantred-2.4.0/tests/test_risk.py +228 -0
- quantred-2.4.0/tests/test_risk_streaming.py +215 -0
- quantred-2.4.0/tests/test_run_config.py +956 -0
- quantred-2.4.0/tests/test_run_context.py +549 -0
- quantred-2.4.0/tests/test_saved_config_book.py +343 -0
- quantred-2.4.0/tests/test_scanner.py +245 -0
- quantred-2.4.0/tests/test_screen_command.py +246 -0
- quantred-2.4.0/tests/test_screening.py +180 -0
- quantred-2.4.0/tests/test_series_comparison.py +324 -0
- quantred-2.4.0/tests/test_services.py +1066 -0
- quantred-2.4.0/tests/test_settings.py +102 -0
- quantred-2.4.0/tests/test_setup.py +1149 -0
- quantred-2.4.0/tests/test_shutdown_signals.py +459 -0
- quantred-2.4.0/tests/test_signal_causality.py +255 -0
- quantred-2.4.0/tests/test_small_real_command.py +931 -0
- quantred-2.4.0/tests/test_small_real_contract.py +447 -0
- quantred-2.4.0/tests/test_state_leak_guard.py +346 -0
- quantred-2.4.0/tests/test_state_root.py +417 -0
- quantred-2.4.0/tests/test_store.py +195 -0
- quantred-2.4.0/tests/test_strategy.py +149 -0
- quantred-2.4.0/tests/test_strategy_registry.py +51 -0
- quantred-2.4.0/tests/test_stream.py +97 -0
- quantred-2.4.0/tests/test_stream_close.py +134 -0
- quantred-2.4.0/tests/test_surface_parity.py +1091 -0
- quantred-2.4.0/tests/test_synthetic.py +50 -0
- quantred-2.4.0/tests/test_trade_analytics.py +356 -0
- quantred-2.4.0/tests/test_trade_command_output.py +303 -0
- quantred-2.4.0/tests/test_trade_update_handling.py +340 -0
- quantred-2.4.0/tests/test_transition_package.py +217 -0
- quantred-2.4.0/tests/test_trial_browser.py +788 -0
- quantred-2.4.0/tests/test_trial_history_labels.py +313 -0
- quantred-2.4.0/tests/test_trial_id_prefix.py +135 -0
- quantred-2.4.0/tests/test_trial_store.py +775 -0
- quantred-2.4.0/tests/test_trial_store_maintenance.py +421 -0
- quantred-2.4.0/tests/test_units.py +228 -0
- quantred-2.4.0/tests/test_verdict.py +905 -0
- quantred-2.4.0/tests/test_walk_forward.py +751 -0
- quantred-2.4.0/tests/test_walk_forward_evidence_parity.py +219 -0
- quantred-2.4.0/uv.lock +3027 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# An allowlist, not a denylist: the Dockerfile copies the build context, and a
|
|
2
|
+
# checkout holds things that must never reach an image - `.env` (broker credentials),
|
|
3
|
+
# the gitignored `specs/`, `configs/` and `logs/` (a campaign's private strategy
|
|
4
|
+
# evidence and journal), `cache/`, `.git`, virtual environments and node_modules.
|
|
5
|
+
# A denylist misses the next one somebody adds; this names only what the image runs.
|
|
6
|
+
*
|
|
7
|
+
|
|
8
|
+
!pyproject.toml
|
|
9
|
+
!uv.lock
|
|
10
|
+
!README.md
|
|
11
|
+
!LICENSE
|
|
12
|
+
!main.py
|
|
13
|
+
!quantred/
|
|
14
|
+
!example/
|
|
15
|
+
|
|
16
|
+
# Even inside the allowed trees.
|
|
17
|
+
**/__pycache__
|
|
18
|
+
**/*.pyc
|
|
19
|
+
**/.pytest_cache
|
|
20
|
+
**/.ruff_cache
|
|
21
|
+
**/.DS_Store
|
|
22
|
+
**/.env
|
|
23
|
+
**/.venv
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copy this file to .env and fill in your Alpaca credentials.
|
|
2
|
+
# .env is gitignored, so your keys are never committed.
|
|
3
|
+
#
|
|
4
|
+
# Get free paper-trading keys at https://app.alpaca.markets/
|
|
5
|
+
# -> Paper Account -> API Keys
|
|
6
|
+
#
|
|
7
|
+
# (No keys needed just to explore — run `make demo` for an offline walkthrough.)
|
|
8
|
+
|
|
9
|
+
APCA_API_KEY_ID=<APCA_API_KEY_ID>
|
|
10
|
+
APCA_API_SECRET_KEY=<APCA_API_SECRET_KEY>
|
|
11
|
+
|
|
12
|
+
# Keep this true until you are absolutely sure you want to trade real money.
|
|
13
|
+
PAPER_TRADE=true
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# --- Optional: AI research agent (`python main.py research`) -----------------
|
|
17
|
+
# Only needed if you run the research agent. Set the key for the provider you
|
|
18
|
+
# use (or export it as a normal environment variable — either works). Ollama
|
|
19
|
+
# runs locally and needs no key.
|
|
20
|
+
#
|
|
21
|
+
# --provider anthropic (default): ANTHROPIC_API_KEY (needs the `ai` extra)
|
|
22
|
+
# --provider openai: OPENAI_API_KEY (needs the `openai` extra)
|
|
23
|
+
# --provider ollama (local): no key; optional OLLAMA_BASE_URL
|
|
24
|
+
#
|
|
25
|
+
# ANTHROPIC_API_KEY=sk-ant-...
|
|
26
|
+
# OPENAI_API_KEY=sk-...
|
|
27
|
+
# OLLAMA_BASE_URL=http://localhost:11434
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!-- Keep PRs small and focused on one layer/concern where possible. -->
|
|
2
|
+
|
|
3
|
+
## What & why
|
|
4
|
+
|
|
5
|
+
<!-- What does this change do, and why? Link any issue. -->
|
|
6
|
+
|
|
7
|
+
## How
|
|
8
|
+
|
|
9
|
+
<!-- Notable implementation choices, especially anything affecting a layer boundary. -->
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
|
|
13
|
+
- [ ] `make test` passes (offline; no keys needed)
|
|
14
|
+
- [ ] `uv run ruff check .` and `uv run ruff format --check .` are clean
|
|
15
|
+
- [ ] New/changed behavior is covered by tests
|
|
16
|
+
- [ ] No vendor SDK (`alpaca`, ...) imported above the broker layer
|
|
17
|
+
- [ ] Touches one concern per layer (see [Separation of concerns](../docs/content/engineering/separation-of-concerns.md))
|
|
18
|
+
- [ ] Docs updated if usage or architecture changed (README / `docs/content`)
|
|
19
|
+
|
|
20
|
+
## Screenshots / output
|
|
21
|
+
|
|
22
|
+
<!-- e.g. a backtest report, scan output, or relevant logs. Optional. -->
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Fail unless the engine version the transition package requires is already on PyPI.
|
|
2
|
+
|
|
3
|
+
The transition release of the old distribution name depends on ``quantred``. PyPI never
|
|
4
|
+
lets a version be replaced, so publishing it before a satisfying ``quantred`` exists would
|
|
5
|
+
leave a permanent release whose dependency cannot be installed. The tag order is a human
|
|
6
|
+
convention; this makes it a check.
|
|
7
|
+
|
|
8
|
+
Usage: require_published_dependency.py <pyproject.toml> [<releases.json>]
|
|
9
|
+
Without the second argument the release list is fetched from PyPI.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import sys
|
|
16
|
+
import urllib.error
|
|
17
|
+
import urllib.request
|
|
18
|
+
|
|
19
|
+
import tomllib
|
|
20
|
+
from packaging.requirements import Requirement
|
|
21
|
+
from packaging.version import Version
|
|
22
|
+
|
|
23
|
+
TARGET = "quantred"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def satisfied(pyproject_text: str, releases: dict) -> str:
|
|
27
|
+
"""The newest un-yanked release meeting the dependency, or raise SystemExit."""
|
|
28
|
+
deps = tomllib.loads(pyproject_text)["project"]["dependencies"]
|
|
29
|
+
wanted = [r for r in map(Requirement, deps) if r.name == TARGET]
|
|
30
|
+
if not wanted:
|
|
31
|
+
raise SystemExit(f"the transition package declares no dependency on {TARGET}")
|
|
32
|
+
spec = wanted[0].specifier
|
|
33
|
+
live = [
|
|
34
|
+
version
|
|
35
|
+
for version, files in releases.items()
|
|
36
|
+
if files and not all(f.get("yanked") for f in files) and version in spec
|
|
37
|
+
]
|
|
38
|
+
if not live:
|
|
39
|
+
raise SystemExit(
|
|
40
|
+
f"{TARGET}{spec} is not on PyPI yet; publish it before the transition package "
|
|
41
|
+
"(a published release cannot be replaced)"
|
|
42
|
+
)
|
|
43
|
+
return str(max(map(Version, live)))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def main(argv: list[str]) -> int:
|
|
47
|
+
with open(argv[1], encoding="utf-8") as handle:
|
|
48
|
+
text = handle.read()
|
|
49
|
+
if len(argv) > 2:
|
|
50
|
+
with open(argv[2], encoding="utf-8") as handle:
|
|
51
|
+
data = json.load(handle)
|
|
52
|
+
else:
|
|
53
|
+
try:
|
|
54
|
+
with urllib.request.urlopen(f"https://pypi.org/pypi/{TARGET}/json", timeout=30) as response:
|
|
55
|
+
data = json.load(response)
|
|
56
|
+
except urllib.error.HTTPError as exc:
|
|
57
|
+
if exc.code != 404:
|
|
58
|
+
raise
|
|
59
|
+
data = {"releases": {}} # no such project yet: nothing satisfies the dependency
|
|
60
|
+
print(f"found {TARGET} {satisfied(text, data['releases'])}")
|
|
61
|
+
return 0
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if __name__ == "__main__":
|
|
65
|
+
sys.exit(main(sys.argv))
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# Every branch, not just main: the secret scan below is only useful if it sees a
|
|
5
|
+
# push that has no pull request behind it. The expensive job stays gated to
|
|
6
|
+
# main + PRs via its own `if` — see lint-and-test.
|
|
7
|
+
push:
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
# Cancel superseded runs on the same ref.
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint-and-test:
|
|
17
|
+
# Unchanged behavior: pull requests, and pushes to main. A push to a topic
|
|
18
|
+
# branch with a PR open would otherwise run the whole suite twice.
|
|
19
|
+
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v7
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv sync --extra dev
|
|
31
|
+
|
|
32
|
+
# The example pack registers through the same entry-point groups a user's own
|
|
33
|
+
# pack does. Installing it here is what makes CI exercise that path end to end -
|
|
34
|
+
# real packaging, real discovery, real contract compliance - rather than only the
|
|
35
|
+
# monkeypatched fakes the registry unit tests use.
|
|
36
|
+
- name: Install the example pack (exercises entry-point discovery)
|
|
37
|
+
run: uv pip install --no-deps -e example
|
|
38
|
+
|
|
39
|
+
- name: Lint (ruff)
|
|
40
|
+
run: uv run ruff check .
|
|
41
|
+
|
|
42
|
+
- name: Format check (ruff)
|
|
43
|
+
run: uv run ruff format --check .
|
|
44
|
+
|
|
45
|
+
- name: Docs link check
|
|
46
|
+
# Relative links and heading anchors across the docs site and top-level
|
|
47
|
+
# Markdown, and no tracked link into the gitignored specs/.
|
|
48
|
+
run: uv run python scripts/check_links.py
|
|
49
|
+
|
|
50
|
+
- name: Compose config validates
|
|
51
|
+
# Cheap and daemon-free: catches a malformed compose file on every PR. The
|
|
52
|
+
# behavioral checks (state survives `down`, live never starts, volumes are
|
|
53
|
+
# host-readable) need a daemon and live in scripts/compose_smoke.sh, run
|
|
54
|
+
# locally and recorded in the PR.
|
|
55
|
+
run: docker compose config --quiet
|
|
56
|
+
|
|
57
|
+
- name: Tests (pytest)
|
|
58
|
+
run: uv run pytest -q
|
|
59
|
+
|
|
60
|
+
secret-scan:
|
|
61
|
+
# The repository is public, so a committed key is disclosed the moment it
|
|
62
|
+
# lands. Unlike lint-and-test this runs on *every* branch push, not only main
|
|
63
|
+
# and PRs — a secret pushed to a topic branch is already public whether or not
|
|
64
|
+
# anyone opens a pull request. A branch with a PR open therefore scans twice
|
|
65
|
+
# (push + pull_request); at half a second a run that is not worth avoiding.
|
|
66
|
+
#
|
|
67
|
+
# GitHub's own secret scanning + push protection is enabled on the repo and
|
|
68
|
+
# catches known provider formats before a push lands. This is the second
|
|
69
|
+
# layer — it runs on forks, and it fails the build rather than only alerting
|
|
70
|
+
# the owner.
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v7
|
|
74
|
+
with:
|
|
75
|
+
# Everything reachable from this ref, not just the diff: a secret deleted
|
|
76
|
+
# in a later commit is still readable in the one that added it, and the
|
|
77
|
+
# default shallow clone hides exactly those commits.
|
|
78
|
+
fetch-depth: 0
|
|
79
|
+
|
|
80
|
+
- name: Install gitleaks
|
|
81
|
+
# Pinned to an exact release rather than an action, so a scan is
|
|
82
|
+
# reproducible and no third-party code runs with the workflow token.
|
|
83
|
+
env:
|
|
84
|
+
GITLEAKS_VERSION: 8.30.1
|
|
85
|
+
run: |
|
|
86
|
+
curl -sSfL -o /tmp/gitleaks.tar.gz \
|
|
87
|
+
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
|
|
88
|
+
tar -xzf /tmp/gitleaks.tar.gz -C /usr/local/bin gitleaks
|
|
89
|
+
gitleaks version
|
|
90
|
+
|
|
91
|
+
- name: Scan history for secrets
|
|
92
|
+
# --redact keeps any match out of the public build log; the finding is in
|
|
93
|
+
# the uploaded report. Exits non-zero when anything is found.
|
|
94
|
+
run: gitleaks git --no-banner --redact --report-path gitleaks-report.json .
|
|
95
|
+
|
|
96
|
+
- name: Upload findings
|
|
97
|
+
if: failure()
|
|
98
|
+
uses: actions/upload-artifact@v7
|
|
99
|
+
with:
|
|
100
|
+
name: gitleaks-report
|
|
101
|
+
path: gitleaks-report.json
|
|
102
|
+
if-no-files-found: ignore
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
# Builds the documentation site on every PR (the Docusaurus production build compiles
|
|
4
|
+
# every page and, with onBrokenLinks/onBrokenAnchors set to 'throw', fails on any dead
|
|
5
|
+
# internal link or anchor) — and deploys it on main.
|
|
6
|
+
#
|
|
7
|
+
# The deploy exists because it did not: the site was published by hand, so it silently
|
|
8
|
+
# fell behind the repository. A page could be written, reviewed, merged, and linked
|
|
9
|
+
# from the README while 404ing for every reader.
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [main]
|
|
13
|
+
paths:
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
- '.github/workflows/docs.yml'
|
|
16
|
+
pull_request:
|
|
17
|
+
paths:
|
|
18
|
+
- 'docs/**'
|
|
19
|
+
- '.github/workflows/docs.yml'
|
|
20
|
+
|
|
21
|
+
# Cancel superseded runs on the same ref.
|
|
22
|
+
concurrency:
|
|
23
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
24
|
+
cancel-in-progress: true
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
build-docs:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
defaults:
|
|
30
|
+
run:
|
|
31
|
+
working-directory: docs
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v7
|
|
34
|
+
|
|
35
|
+
- name: Install Node
|
|
36
|
+
uses: actions/setup-node@v7
|
|
37
|
+
with:
|
|
38
|
+
# .nvmrc is the single source: a contributor running `nvm use` and CI build
|
|
39
|
+
# on the same major, and there is no second place to forget to update.
|
|
40
|
+
node-version-file: .nvmrc
|
|
41
|
+
cache: npm
|
|
42
|
+
cache-dependency-path: docs/package-lock.json
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: npm ci
|
|
46
|
+
|
|
47
|
+
- name: Build docs (fails on broken links/anchors)
|
|
48
|
+
run: npm run build
|
|
49
|
+
|
|
50
|
+
- name: Upload the built site
|
|
51
|
+
if: github.ref == 'refs/heads/main'
|
|
52
|
+
uses: actions/upload-artifact@v7
|
|
53
|
+
with:
|
|
54
|
+
name: docs-site
|
|
55
|
+
path: docs/build/
|
|
56
|
+
|
|
57
|
+
deploy:
|
|
58
|
+
name: Deploy to Cloudflare
|
|
59
|
+
# Only from main, and only once the build above has actually succeeded.
|
|
60
|
+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
61
|
+
needs: build-docs
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
defaults:
|
|
64
|
+
run:
|
|
65
|
+
working-directory: docs
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v7
|
|
68
|
+
|
|
69
|
+
- uses: actions/setup-node@v7
|
|
70
|
+
with:
|
|
71
|
+
# .nvmrc is the single source: a contributor running `nvm use` and CI build
|
|
72
|
+
# on the same major, and there is no second place to forget to update.
|
|
73
|
+
node-version-file: .nvmrc
|
|
74
|
+
cache: npm
|
|
75
|
+
cache-dependency-path: docs/package-lock.json
|
|
76
|
+
|
|
77
|
+
- run: npm ci
|
|
78
|
+
|
|
79
|
+
- uses: actions/download-artifact@v8
|
|
80
|
+
with:
|
|
81
|
+
name: docs-site
|
|
82
|
+
path: docs/build/
|
|
83
|
+
|
|
84
|
+
# Fail with an explanation, not a bare exit code. Without this, a missing
|
|
85
|
+
# secret surfaces as `wrangler` exiting 1 with nothing to act on — the reader
|
|
86
|
+
# has to guess that a credential is the problem.
|
|
87
|
+
- name: Check the deploy credentials exist
|
|
88
|
+
env:
|
|
89
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
90
|
+
run: |
|
|
91
|
+
if [ -z "$CLOUDFLARE_API_TOKEN" ]; then
|
|
92
|
+
echo "::error title=Missing deploy credentials::CLOUDFLARE_API_TOKEN is not set."
|
|
93
|
+
echo ""
|
|
94
|
+
echo "The docs site cannot deploy without it, so tradeflow.mk-dir.com will"
|
|
95
|
+
echo "keep serving whatever was last published by hand."
|
|
96
|
+
echo ""
|
|
97
|
+
echo "Add it at: Settings -> Secrets and variables -> Actions"
|
|
98
|
+
echo " CLOUDFLARE_API_TOKEN a token with the Workers Scripts:Edit permission"
|
|
99
|
+
echo " CLOUDFLARE_ACCOUNT_ID optional; only if the account is ambiguous"
|
|
100
|
+
echo ""
|
|
101
|
+
echo "To publish once by hand in the meantime:"
|
|
102
|
+
echo " cd docs && npx wrangler login && npm run deploy"
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
- name: Deploy
|
|
107
|
+
env:
|
|
108
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
109
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
110
|
+
run: npx wrangler deploy
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a version tag is pushed. Two properties matter here:
|
|
4
|
+
#
|
|
5
|
+
# 1. The tests run first, and a failure stops the publish. A release is the one
|
|
6
|
+
# moment a broken build becomes someone else's problem permanently — PyPI
|
|
7
|
+
# versions cannot be replaced, only yanked.
|
|
8
|
+
# 2. No API token is stored anywhere. Publishing uses PyPI's trusted publishing
|
|
9
|
+
# (OIDC), so the only thing that can release is this workflow, from this
|
|
10
|
+
# repository, on a tag. A leaked secret cannot publish because there is no
|
|
11
|
+
# secret.
|
|
12
|
+
#
|
|
13
|
+
# Set up once at https://pypi.org/manage/project/quantred/settings/publishing/ (a new
|
|
14
|
+
# project name needs its own trusted publisher; the one registered for the previous
|
|
15
|
+
# distribution name does not carry over)
|
|
16
|
+
# owner: makedirectory repository: quantred
|
|
17
|
+
# workflow: release.yml environment: pypi
|
|
18
|
+
#
|
|
19
|
+
# A tag `v*` publishes the engine from the repository root. A tag `tradeflow-engine-v*`
|
|
20
|
+
# publishes the final transition release of the old distribution name from
|
|
21
|
+
# packaging/tradeflow-engine instead. That project's trusted publisher must name the
|
|
22
|
+
# repository as it is now called (`quantred`, renamed from the old one) and the same
|
|
23
|
+
# workflow `release.yml` and environment `pypi`.
|
|
24
|
+
|
|
25
|
+
on:
|
|
26
|
+
push:
|
|
27
|
+
tags: ["v*", "tradeflow-engine-v*"]
|
|
28
|
+
workflow_dispatch:
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
verify:
|
|
32
|
+
name: Test before publishing
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v7
|
|
36
|
+
- uses: astral-sh/setup-uv@v7
|
|
37
|
+
with:
|
|
38
|
+
enable-cache: true
|
|
39
|
+
- run: uv sync --extra dev
|
|
40
|
+
- run: uv run ruff check .
|
|
41
|
+
- run: uv run ruff format --check .
|
|
42
|
+
- run: uv run pytest -q
|
|
43
|
+
|
|
44
|
+
build:
|
|
45
|
+
name: Build the distribution
|
|
46
|
+
needs: verify
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v7
|
|
50
|
+
- uses: astral-sh/setup-uv@v7
|
|
51
|
+
- name: Build the engine (tag v*, or a manual run)
|
|
52
|
+
if: ${{ !startsWith(github.ref, 'refs/tags/tradeflow-engine-v') }}
|
|
53
|
+
run: uv build
|
|
54
|
+
- name: Build the transition package (tag tradeflow-engine-v*)
|
|
55
|
+
if: startsWith(github.ref, 'refs/tags/tradeflow-engine-v')
|
|
56
|
+
run: uv build packaging/tradeflow-engine -o dist
|
|
57
|
+
# Catches a malformed README or bad metadata before it is permanent.
|
|
58
|
+
- run: uvx twine check dist/*
|
|
59
|
+
# The tag and the packaged version must agree, or the release notes describe
|
|
60
|
+
# something other than what was published.
|
|
61
|
+
- name: Tag matches the packaged version
|
|
62
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
63
|
+
run: |
|
|
64
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
65
|
+
BUILT=$(ls dist/*.tar.gz | sed -E 's/.*-([0-9][^-]*)\.tar\.gz/\1/')
|
|
66
|
+
echo "tag=$TAG built=$BUILT"
|
|
67
|
+
test "$TAG" = "$BUILT"
|
|
68
|
+
- name: Tag matches the transition package's version
|
|
69
|
+
if: startsWith(github.ref, 'refs/tags/tradeflow-engine-v')
|
|
70
|
+
run: |
|
|
71
|
+
TAG="${GITHUB_REF_NAME#tradeflow-engine-v}"
|
|
72
|
+
BUILT=$(ls dist/tradeflow_engine-*.tar.gz | sed -E 's/.*-([0-9][^-]*)\.tar\.gz/\1/')
|
|
73
|
+
echo "tag=$TAG built=$BUILT"
|
|
74
|
+
test "$TAG" = "$BUILT"
|
|
75
|
+
# PyPI cannot replace a version. Publishing this before the engine release it
|
|
76
|
+
# requires exists would leave a permanent release whose dependency cannot be
|
|
77
|
+
# installed, so the order of the two tags is checked, not remembered.
|
|
78
|
+
- name: The engine release this requires is on PyPI
|
|
79
|
+
if: startsWith(github.ref, 'refs/tags/tradeflow-engine-v')
|
|
80
|
+
run: uv run --no-project --with packaging python .github/scripts/require_published_dependency.py packaging/tradeflow-engine/pyproject.toml
|
|
81
|
+
- uses: actions/upload-artifact@v7
|
|
82
|
+
with:
|
|
83
|
+
name: dist
|
|
84
|
+
path: dist/
|
|
85
|
+
|
|
86
|
+
publish:
|
|
87
|
+
name: Publish to PyPI
|
|
88
|
+
needs: build
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
environment: pypi
|
|
91
|
+
permissions:
|
|
92
|
+
id-token: write # the OIDC token trusted publishing exchanges for an upload
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/download-artifact@v8
|
|
95
|
+
with:
|
|
96
|
+
name: dist
|
|
97
|
+
path: dist/
|
|
98
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Generated artifacts
|
|
2
|
+
optimization_results.csv
|
|
3
|
+
walkforward_results.csv
|
|
4
|
+
|
|
5
|
+
# Saved strategy configs (a human promotes these; never auto-applied).
|
|
6
|
+
# Anchored to the repo root: unanchored, this matched a `configs/` at *any* depth and
|
|
7
|
+
# silently excluded the example pack's own config — so a fresh clone got a pack missing
|
|
8
|
+
# the artefact its README tells you to run.
|
|
9
|
+
/configs/
|
|
10
|
+
|
|
11
|
+
# MCP audit log, research journal, and run artifacts. Anchored for the same reason.
|
|
12
|
+
/logs/
|
|
13
|
+
|
|
14
|
+
# Persistent bar cache - derived from Alpaca, safe to delete. Anchored for the same reason.
|
|
15
|
+
/cache/
|
|
16
|
+
|
|
17
|
+
# Docs site (Docusaurus)
|
|
18
|
+
docs/node_modules/
|
|
19
|
+
docs/build/
|
|
20
|
+
docs/.docusaurus/
|
|
21
|
+
|
|
22
|
+
# Mongo Data
|
|
23
|
+
/data/db
|
|
24
|
+
|
|
25
|
+
# Below is a standard to gitignore file for Python
|
|
26
|
+
# Byte-compiled / optimized / DLL files
|
|
27
|
+
__pycache__/
|
|
28
|
+
*.py[cod]
|
|
29
|
+
*$py.class
|
|
30
|
+
|
|
31
|
+
# C extensions
|
|
32
|
+
*.so
|
|
33
|
+
|
|
34
|
+
# Distribution / packaging
|
|
35
|
+
.Python
|
|
36
|
+
build/
|
|
37
|
+
develop-eggs/
|
|
38
|
+
dist/
|
|
39
|
+
downloads/
|
|
40
|
+
eggs/
|
|
41
|
+
.eggs/
|
|
42
|
+
lib/
|
|
43
|
+
lib64/
|
|
44
|
+
parts/
|
|
45
|
+
sdist/
|
|
46
|
+
var/
|
|
47
|
+
wheels/
|
|
48
|
+
pip-wheel-metadata/
|
|
49
|
+
share/python-wheels/
|
|
50
|
+
*.egg-info/
|
|
51
|
+
.installed.cfg
|
|
52
|
+
*.egg
|
|
53
|
+
MANIFEST
|
|
54
|
+
|
|
55
|
+
# PyInstaller
|
|
56
|
+
# Usually these files are written by a python script from a template
|
|
57
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
58
|
+
*.manifest
|
|
59
|
+
*.spec
|
|
60
|
+
|
|
61
|
+
# Installer logs
|
|
62
|
+
pip-log.txt
|
|
63
|
+
pip-delete-this-directory.txt
|
|
64
|
+
|
|
65
|
+
# Unit test / coverage reports
|
|
66
|
+
htmlcov/
|
|
67
|
+
.tox/
|
|
68
|
+
.nox/
|
|
69
|
+
.coverage
|
|
70
|
+
.coverage.*
|
|
71
|
+
.cache
|
|
72
|
+
nosetests.xml
|
|
73
|
+
coverage.xml
|
|
74
|
+
*.cover
|
|
75
|
+
.hypothesis/
|
|
76
|
+
.pytest_cache/
|
|
77
|
+
|
|
78
|
+
# Translations
|
|
79
|
+
*.mo
|
|
80
|
+
*.pot
|
|
81
|
+
|
|
82
|
+
# Django stuff:
|
|
83
|
+
*.log
|
|
84
|
+
local_settings.py
|
|
85
|
+
db.sqlite3
|
|
86
|
+
db.sqlite3-journal
|
|
87
|
+
|
|
88
|
+
# Flask stuff:
|
|
89
|
+
instance/
|
|
90
|
+
.webassets-cache
|
|
91
|
+
|
|
92
|
+
# Scrapy stuff:
|
|
93
|
+
.scrapy
|
|
94
|
+
|
|
95
|
+
# Sphinx documentation
|
|
96
|
+
docs/_build/
|
|
97
|
+
|
|
98
|
+
# PyBuilder
|
|
99
|
+
target/
|
|
100
|
+
|
|
101
|
+
# Jupyter Notebook
|
|
102
|
+
.ipynb_checkpoints
|
|
103
|
+
|
|
104
|
+
# IPython
|
|
105
|
+
profile_default/
|
|
106
|
+
ipython_config.py
|
|
107
|
+
|
|
108
|
+
# pyenv
|
|
109
|
+
.python-version
|
|
110
|
+
|
|
111
|
+
# pipenv
|
|
112
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
113
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
114
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
115
|
+
# install all needed dependencies.
|
|
116
|
+
#Pipfile.lock
|
|
117
|
+
|
|
118
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
119
|
+
__pypackages__/
|
|
120
|
+
|
|
121
|
+
# Celery stuff
|
|
122
|
+
celerybeat-schedule
|
|
123
|
+
celerybeat.pid
|
|
124
|
+
|
|
125
|
+
# SageMath parsed files
|
|
126
|
+
*.sage.py
|
|
127
|
+
|
|
128
|
+
# Environments
|
|
129
|
+
.env
|
|
130
|
+
.venv
|
|
131
|
+
env/
|
|
132
|
+
venv/
|
|
133
|
+
ENV/
|
|
134
|
+
env.bak/
|
|
135
|
+
venv.bak/
|
|
136
|
+
|
|
137
|
+
# Spyder project settings
|
|
138
|
+
.spyderproject
|
|
139
|
+
.spyproject
|
|
140
|
+
|
|
141
|
+
# Rope project settings
|
|
142
|
+
.ropeproject
|
|
143
|
+
|
|
144
|
+
# mkdocs documentation
|
|
145
|
+
/site
|
|
146
|
+
|
|
147
|
+
# mypy
|
|
148
|
+
.mypy_cache/
|
|
149
|
+
.dmypy.json
|
|
150
|
+
dmypy.json
|
|
151
|
+
|
|
152
|
+
# Pyre type checker
|
|
153
|
+
.pyre/
|
|
154
|
+
|
|
155
|
+
# pytype static type analyzer
|
|
156
|
+
.pytype/
|
|
157
|
+
|
|
158
|
+
# Cython debug symbols
|
|
159
|
+
cython_debug/
|
|
160
|
+
|
|
161
|
+
# macOS
|
|
162
|
+
.DS_Store
|
|
163
|
+
|
|
164
|
+
# VS Code settings
|
|
165
|
+
.vscode/
|
|
166
|
+
|
|
167
|
+
# Ruff
|
|
168
|
+
.ruff_cache/
|
|
169
|
+
|
|
170
|
+
# Specs
|
|
171
|
+
specs/
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Fake API keys in test fixtures, already in history. Each test plants one to check that
|
|
2
|
+
# a key is never printed or written; neither has ever been a real credential. The lines
|
|
3
|
+
# themselves now carry `gitleaks:allow`, which covers them from here on.
|
|
4
|
+
27eb2eebf0dbce4dda8ed77f70f6be45f763dcef:tests/test_setup.py:generic-api-key:640
|
|
5
|
+
c8a28fbac456371971c76681942d2a36c7c9cabf:tests/test_model_probe.py:generic-api-key:18
|
quantred-2.4.0/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24
|
quantred-2.4.0/AGENTS.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Working on QuantRed
|
|
2
|
+
|
|
3
|
+
Topic rules live in `.claude/rules/`; the cycle a change goes through, and the gate it
|
|
4
|
+
has to pass, are in [how a change gets built here](.claude/rules/build-process.md). The
|
|
5
|
+
procedures that cycle names are skills — `review-gate`, `consolidation-pass`,
|
|
6
|
+
`dependency-truth` — and `/ship-check` reports what the definition of done is missing.
|
|
7
|
+
This file is only what is true in every session.
|
|
8
|
+
|
|
9
|
+
## The one invariant
|
|
10
|
+
|
|
11
|
+
**Two clocks.** The research clock (backtest, optimize, walk-forward, analytics, the
|
|
12
|
+
AI agent) is slow, exploratory, and only ever *proposes*. The trade clock
|
|
13
|
+
(`quantred/engine/live.py`, `quantred/execution/`) is deterministic and imports
|
|
14
|
+
**nothing** from `services/`, `analytics/`, `optimization/`, or `research/`.
|
|
15
|
+
Promotion between them is a manual human step.
|
|
16
|
+
|
|
17
|
+
A change that blurs this is wrong regardless of how well it works.
|
|
18
|
+
|
|
19
|
+
## Verify, don't assert
|
|
20
|
+
|
|
21
|
+
The rule that has caught the most real defects here — every one of them looked
|
|
22
|
+
correct in the source:
|
|
23
|
+
|
|
24
|
+
- **Run the thing.** Installing the published package into a clean venv found four
|
|
25
|
+
onboarding dead ends that passed every test. An MCP dependency that every test and
|
|
26
|
+
lockfile agreed was fine shipped broken.
|
|
27
|
+
- **Check the environment, not the config.** Confirm an action tag resolves before
|
|
28
|
+
pushing it, a URL serves before linking it, a dependency's *resolved* version
|
|
29
|
+
rather than what the lockfile pinned.
|
|
30
|
+
- **Say what you actually verified**, and what you did not.
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv run ruff check . && uv run ruff format --check . # exactly what CI runs
|
|
36
|
+
make test # offline, no keys
|
|
37
|
+
make check-links # tracked docs; specs/ never linked
|
|
38
|
+
make release-check # build + install into a clean venv
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Definition of done
|
|
42
|
+
|
|
43
|
+
Per [build-process](.claude/rules/build-process.md), none of it optional: right layer · offline deterministic tests via
|
|
44
|
+
`tests/fakes.py` · every applicable surface wired (CLI, MCP tool, Makefile) · docs
|
|
45
|
+
updated · all four commands above clean.
|
|
46
|
+
|
|
47
|
+
## Git
|
|
48
|
+
|
|
49
|
+
- Branch off `main`; never commit to it directly.
|
|
50
|
+
- **Commit as you go.** Reconstructing per-change commits afterwards is impossible
|
|
51
|
+
once edits to shared files interleave.
|
|
52
|
+
- Messages explain the *why* and any deviation from plan; end with
|
|
53
|
+
`Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>`.
|
quantred-2.4.0/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|