racinglines 1.0.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.
- racinglines-1.0.0/LICENSE +21 -0
- racinglines-1.0.0/PKG-INFO +273 -0
- racinglines-1.0.0/README.md +239 -0
- racinglines-1.0.0/exchanges/og.toml +188 -0
- racinglines-1.0.0/markets/kinds.toml +567 -0
- racinglines-1.0.0/migrations/env.py +38 -0
- racinglines-1.0.0/migrations/script.py.mako +24 -0
- racinglines-1.0.0/migrations/versions/20260926_0e47bb766d0b_house_markets_and_bets.py +68 -0
- racinglines-1.0.0/migrations/versions/20260926_1983462a0695_initial_schema.py +258 -0
- racinglines-1.0.0/migrations/versions/20260926_3f94d44a125e_market_trades_and_book_snapshots.py +57 -0
- racinglines-1.0.0/migrations/versions/20260926_50a176ca2955_market_price_history.py +33 -0
- racinglines-1.0.0/migrations/versions/20260926_66d4b92ba307_market_links_and_orders.py +79 -0
- racinglines-1.0.0/migrations/versions/20260926_81022900a936_jobs.py +45 -0
- racinglines-1.0.0/migrations/versions/20260926_8c46493d7cda_house_market_uniqueness_per_mirrored_.py +30 -0
- racinglines-1.0.0/migrations/versions/20260926_8d64d59a2940_users_roles_activity_log.py +80 -0
- racinglines-1.0.0/migrations/versions/20260926_d84cd5aa7ce4_polymarket_alignment.py +83 -0
- racinglines-1.0.0/migrations/versions/20260926_f3e017071b76_laps_track_profiles_round_extra.py +64 -0
- racinglines-1.0.0/migrations/versions/20260927_5b1e0c7d2a41_user_prefs.py +24 -0
- racinglines-1.0.0/migrations/versions/20260927_9c4d2e8f1a63_market_first_seen.py +23 -0
- racinglines-1.0.0/migrations/versions/20260927_c7a1f4e2b9d0_strategy_signals.py +79 -0
- racinglines-1.0.0/migrations/versions/20260927_d2b8e5a1c3f7_replay_taker_account.py +35 -0
- racinglines-1.0.0/migrations/versions/20260927_e4c1a9b7d205_paper_position_venue.py +23 -0
- racinglines-1.0.0/migrations/versions/20260929_a3f5c8d1e7b2_live_events.py +40 -0
- racinglines-1.0.0/migrations/versions/20260929_b7d2e4f1a9c3_data_changes.py +33 -0
- racinglines-1.0.0/migrations/versions/20260929_c8e3f6a2d4b1_market_disagreements.py +55 -0
- racinglines-1.0.0/migrations/versions/20261002_d9f2a7e5c1b3_user_email_prefs.py +40 -0
- racinglines-1.0.0/migrations/versions/20261002_d9f4b1c7e5a2_user_mcp_tokens.py +24 -0
- racinglines-1.0.0/migrations/versions/20261003_f8a2c4e7b5d1_fastf1_snapshots.py +59 -0
- racinglines-1.0.0/migrations/versions/20261005_a7e3c1f9b4d2_kalshi_candlestick_bid_ask.py +34 -0
- racinglines-1.0.0/pyproject.toml +31 -0
- racinglines-1.0.0/racinglines/__init__.py +10 -0
- racinglines-1.0.0/racinglines/__main__.py +5 -0
- racinglines-1.0.0/racinglines/attribution.py +137 -0
- racinglines-1.0.0/racinglines/books/__init__.py +3 -0
- racinglines-1.0.0/racinglines/books/ledger.py +138 -0
- racinglines-1.0.0/racinglines/books/picks.py +132 -0
- racinglines-1.0.0/racinglines/books/render.css +85 -0
- racinglines-1.0.0/racinglines/books/render.py +650 -0
- racinglines-1.0.0/racinglines/books/schema.py +394 -0
- racinglines-1.0.0/racinglines/books/slips.py +561 -0
- racinglines-1.0.0/racinglines/cli/__init__.py +120 -0
- racinglines-1.0.0/racinglines/cli/backtest.py +197 -0
- racinglines-1.0.0/racinglines/cli/book.py +432 -0
- racinglines-1.0.0/racinglines/cli/check.py +44 -0
- racinglines-1.0.0/racinglines/cli/config.py +57 -0
- racinglines-1.0.0/racinglines/cli/db.py +204 -0
- racinglines-1.0.0/racinglines/cli/f1.py +1302 -0
- racinglines-1.0.0/racinglines/cli/live.py +555 -0
- racinglines-1.0.0/racinglines/cli/markets.py +337 -0
- racinglines-1.0.0/racinglines/cli/mtb_dh.py +502 -0
- racinglines-1.0.0/racinglines/cli/replay_cmd.py +405 -0
- racinglines-1.0.0/racinglines/cli/rich_view.py +130 -0
- racinglines-1.0.0/racinglines/cli/source.py +274 -0
- racinglines-1.0.0/racinglines/cli/tty.py +115 -0
- racinglines-1.0.0/racinglines/cli/users.py +141 -0
- racinglines-1.0.0/racinglines/cli/verbs.py +217 -0
- racinglines-1.0.0/racinglines/cli/web.py +34 -0
- racinglines-1.0.0/racinglines/core/__init__.py +1 -0
- racinglines-1.0.0/racinglines/core/calibration.py +60 -0
- racinglines-1.0.0/racinglines/core/stages.py +54 -0
- racinglines-1.0.0/racinglines/core/stats.py +34 -0
- racinglines-1.0.0/racinglines/core/walk_forward.py +103 -0
- racinglines-1.0.0/racinglines/db/__init__.py +0 -0
- racinglines-1.0.0/racinglines/db/changes.py +51 -0
- racinglines-1.0.0/racinglines/db/config.py +33 -0
- racinglines-1.0.0/racinglines/db/ingest.py +194 -0
- racinglines-1.0.0/racinglines/db/mirror.py +433 -0
- racinglines-1.0.0/racinglines/db/models.py +654 -0
- racinglines-1.0.0/racinglines/db/pull.py +336 -0
- racinglines-1.0.0/racinglines/db/queries.py +183 -0
- racinglines-1.0.0/racinglines/db/reads.py +335 -0
- racinglines-1.0.0/racinglines/db/records.py +61 -0
- racinglines-1.0.0/racinglines/db/registry.py +41 -0
- racinglines-1.0.0/racinglines/db/schedule.py +142 -0
- racinglines-1.0.0/racinglines/db/snapshot.py +71 -0
- racinglines-1.0.0/racinglines/demo/__init__.py +0 -0
- racinglines-1.0.0/racinglines/demo/mk_demo/__init__.py +2 -0
- racinglines-1.0.0/racinglines/demo/mk_demo/generate.py +513 -0
- racinglines-1.0.0/racinglines/demo/packs/kart/book.toml +147 -0
- racinglines-1.0.0/racinglines/demo/packs/kart/files/live/f1/demo-2026-09.toml +35 -0
- racinglines-1.0.0/racinglines/demo/packs/kart/pack.toml +72 -0
- racinglines-1.0.0/racinglines/demo/packs/kart/world.toml +336 -0
- racinglines-1.0.0/racinglines/demo/store.py +279 -0
- racinglines-1.0.0/racinglines/exchanges.py +78 -0
- racinglines-1.0.0/racinglines/fantasy/__init__.py +8 -0
- racinglines-1.0.0/racinglines/fantasy/exchange.py +653 -0
- racinglines-1.0.0/racinglines/fantasy/follow.py +287 -0
- racinglines-1.0.0/racinglines/fantasy/ledger.py +313 -0
- racinglines-1.0.0/racinglines/fantasy/sizing.py +110 -0
- racinglines-1.0.0/racinglines/frames/__init__.py +55 -0
- racinglines-1.0.0/racinglines/frames/_util.py +34 -0
- racinglines-1.0.0/racinglines/frames/f1.py +123 -0
- racinglines-1.0.0/racinglines/frames/mtb_dh.py +156 -0
- racinglines-1.0.0/racinglines/frames/schema.py +255 -0
- racinglines-1.0.0/racinglines/markets/__init__.py +0 -0
- racinglines-1.0.0/racinglines/markets/alerts.py +219 -0
- racinglines-1.0.0/racinglines/markets/combos.py +260 -0
- racinglines-1.0.0/racinglines/markets/crowd.py +249 -0
- racinglines-1.0.0/racinglines/markets/disagree.py +442 -0
- racinglines-1.0.0/racinglines/markets/exchange_driver.py +733 -0
- racinglines-1.0.0/racinglines/markets/identity.py +54 -0
- racinglines-1.0.0/racinglines/markets/kalshi/__init__.py +0 -0
- racinglines-1.0.0/racinglines/markets/kalshi/client.py +113 -0
- racinglines-1.0.0/racinglines/markets/kalshi/sync.py +565 -0
- racinglines-1.0.0/racinglines/markets/kalshi/trade.py +110 -0
- racinglines-1.0.0/racinglines/markets/kinds.py +312 -0
- racinglines-1.0.0/racinglines/markets/payoffs.py +502 -0
- racinglines-1.0.0/racinglines/markets/polymarket/__init__.py +0 -0
- racinglines-1.0.0/racinglines/markets/polymarket/links.py +107 -0
- racinglines-1.0.0/racinglines/markets/polymarket/sync.py +611 -0
- racinglines-1.0.0/racinglines/markets/polymarket/trade.py +240 -0
- racinglines-1.0.0/racinglines/markets/private_book.py +438 -0
- racinglines-1.0.0/racinglines/markets/probalytics.py +390 -0
- racinglines-1.0.0/racinglines/markets/quoting.py +76 -0
- racinglines-1.0.0/racinglines/markets/settle_check.py +136 -0
- racinglines-1.0.0/racinglines/markets/settlement_rules.py +184 -0
- racinglines-1.0.0/racinglines/markets/store.py +407 -0
- racinglines-1.0.0/racinglines/markets/strategies/__init__.py +0 -0
- racinglines-1.0.0/racinglines/markets/strategies/buy_everything.py +107 -0
- racinglines-1.0.0/racinglines/markets/strategies/maker_replay.py +691 -0
- racinglines-1.0.0/racinglines/markets/strategies/replay_json.py +51 -0
- racinglines-1.0.0/racinglines/markets/strategies/season.py +162 -0
- racinglines-1.0.0/racinglines/markets/strategies/sizing.py +30 -0
- racinglines-1.0.0/racinglines/markets/strategies/taker_weekend.py +312 -0
- racinglines-1.0.0/racinglines/markets/venue_replay.py +454 -0
- racinglines-1.0.0/racinglines/markets/venues.py +654 -0
- racinglines-1.0.0/racinglines/models/__init__.py +0 -0
- racinglines-1.0.0/racinglines/models/calibration.py +173 -0
- racinglines-1.0.0/racinglines/models/combo_job.py +212 -0
- racinglines-1.0.0/racinglines/models/dnf_check.py +123 -0
- racinglines-1.0.0/racinglines/models/evaluate.py +267 -0
- racinglines-1.0.0/racinglines/models/inputs/__init__.py +107 -0
- racinglines-1.0.0/racinglines/models/inputs/grid.py +138 -0
- racinglines-1.0.0/racinglines/models/inputs/laps.py +864 -0
- racinglines-1.0.0/racinglines/models/inputs/laps_core.py +82 -0
- racinglines-1.0.0/racinglines/models/inputs/laps_pricing.py +730 -0
- racinglines-1.0.0/racinglines/models/inputs/practice.py +246 -0
- racinglines-1.0.0/racinglines/models/inputs/results.py +454 -0
- racinglines-1.0.0/racinglines/models/inputs/run_times/__init__.py +6 -0
- racinglines-1.0.0/racinglines/models/inputs/run_times/core.py +107 -0
- racinglines-1.0.0/racinglines/models/inputs/run_times/model.py +296 -0
- racinglines-1.0.0/racinglines/models/inputs/run_times/points.py +183 -0
- racinglines-1.0.0/racinglines/models/inputs/run_times/season.py +271 -0
- racinglines-1.0.0/racinglines/models/inputs/run_times/settings.py +61 -0
- racinglines-1.0.0/racinglines/models/inrace.py +46 -0
- racinglines-1.0.0/racinglines/models/model_global.py +70 -0
- racinglines-1.0.0/racinglines/models/outcomes.py +224 -0
- racinglines-1.0.0/racinglines/models/position_sim/__init__.py +27 -0
- racinglines-1.0.0/racinglines/models/props.py +394 -0
- racinglines-1.0.0/racinglines/models/race_model.py +95 -0
- racinglines-1.0.0/racinglines/models/sprint_check.py +114 -0
- racinglines-1.0.0/racinglines/models/timed_runs/__init__.py +15 -0
- racinglines-1.0.0/racinglines/models/variants.py +84 -0
- racinglines-1.0.0/racinglines/paths.py +62 -0
- racinglines-1.0.0/racinglines/pipelines/__init__.py +0 -0
- racinglines-1.0.0/racinglines/pipelines/clv.py +470 -0
- racinglines-1.0.0/racinglines/pipelines/coverage.py +199 -0
- racinglines-1.0.0/racinglines/pipelines/demo_history.py +91 -0
- racinglines-1.0.0/racinglines/pipelines/live.py +341 -0
- racinglines-1.0.0/racinglines/pipelines/live_dh.py +983 -0
- racinglines-1.0.0/racinglines/pipelines/live_f1.py +897 -0
- racinglines-1.0.0/racinglines/pipelines/live_report.py +280 -0
- racinglines-1.0.0/racinglines/pipelines/model_vs_market.py +128 -0
- racinglines-1.0.0/racinglines/pipelines/position_replay.py +636 -0
- racinglines-1.0.0/racinglines/pipelines/profiles.py +418 -0
- racinglines-1.0.0/racinglines/pipelines/reconcile.py +483 -0
- racinglines-1.0.0/racinglines/pipelines/scorecard.py +302 -0
- racinglines-1.0.0/racinglines/pipelines/search.py +580 -0
- racinglines-1.0.0/racinglines/pipelines/search_plan.py +108 -0
- racinglines-1.0.0/racinglines/pipelines/search_report.py +404 -0
- racinglines-1.0.0/racinglines/pipelines/season_checkpoints.py +174 -0
- racinglines-1.0.0/racinglines/pipelines/season_replay.py +362 -0
- racinglines-1.0.0/racinglines/pipelines/season_strategy.py +369 -0
- racinglines-1.0.0/racinglines/pipelines/season_sweep.py +498 -0
- racinglines-1.0.0/racinglines/pipelines/signals.py +933 -0
- racinglines-1.0.0/racinglines/pipelines/sport_forecast.py +201 -0
- racinglines-1.0.0/racinglines/pipelines/sport_paper.py +302 -0
- racinglines-1.0.0/racinglines/pipelines/sport_signals.py +331 -0
- racinglines-1.0.0/racinglines/pipelines/story.py +345 -0
- racinglines-1.0.0/racinglines/pipelines/sweep_settings.py +379 -0
- racinglines-1.0.0/racinglines/pipelines/weekend_sweep.py +680 -0
- racinglines-1.0.0/racinglines/progress.py +110 -0
- racinglines-1.0.0/racinglines/reporting/__init__.py +1 -0
- racinglines-1.0.0/racinglines/reporting/markdown_html.py +55 -0
- racinglines-1.0.0/racinglines/reporting/metrics.py +19 -0
- racinglines-1.0.0/racinglines/reporting/search_analyze.py +231 -0
- racinglines-1.0.0/racinglines/reporting/search_noise.py +59 -0
- racinglines-1.0.0/racinglines/reporting/search_plot.py +157 -0
- racinglines-1.0.0/racinglines/sources/__init__.py +0 -0
- racinglines-1.0.0/racinglines/sources/chronorace/__init__.py +0 -0
- racinglines-1.0.0/racinglines/sources/chronorace/download.py +488 -0
- racinglines-1.0.0/racinglines/sources/chronorace/ingest.py +131 -0
- racinglines-1.0.0/racinglines/sources/chronorace/parse.py +736 -0
- racinglines-1.0.0/racinglines/sources/chronorace/pdf.py +198 -0
- racinglines-1.0.0/racinglines/sources/fastf1/__init__.py +0 -0
- racinglines-1.0.0/racinglines/sources/fastf1/fetch.py +219 -0
- racinglines-1.0.0/racinglines/sources/fastf1/ingest.py +350 -0
- racinglines-1.0.0/racinglines/sources/http.py +108 -0
- racinglines-1.0.0/racinglines/sports.py +233 -0
- racinglines-1.0.0/racinglines/testing/__init__.py +0 -0
- racinglines-1.0.0/racinglines/testing/checks.py +273 -0
- racinglines-1.0.0/racinglines/testing/synthetic.py +265 -0
- racinglines-1.0.0/racinglines/weather/__init__.py +21 -0
- racinglines-1.0.0/racinglines/weather/open_meteo.py +269 -0
- racinglines-1.0.0/racinglines/weather/schema.py +173 -0
- racinglines-1.0.0/racinglines/weather/venues.toml +278 -0
- racinglines-1.0.0/racinglines/weather/wet.py +274 -0
- racinglines-1.0.0/racinglines/weather/wunderground.py +230 -0
- racinglines-1.0.0/racinglines/web/__init__.py +1 -0
- racinglines-1.0.0/racinglines/web/accounts.py +170 -0
- racinglines-1.0.0/racinglines/web/admin.py +508 -0
- racinglines-1.0.0/racinglines/web/api.py +80 -0
- racinglines-1.0.0/racinglines/web/app.py +912 -0
- racinglines-1.0.0/racinglines/web/audience.py +47 -0
- racinglines-1.0.0/racinglines/web/board.py +342 -0
- racinglines-1.0.0/racinglines/web/book_routes.py +318 -0
- racinglines-1.0.0/racinglines/web/demo.py +83 -0
- racinglines-1.0.0/racinglines/web/diag.py +314 -0
- racinglines-1.0.0/racinglines/web/diag_routes.py +89 -0
- racinglines-1.0.0/racinglines/web/edge.py +453 -0
- racinglines-1.0.0/racinglines/web/exchange_routes.py +207 -0
- racinglines-1.0.0/racinglines/web/f1_live.py +191 -0
- racinglines-1.0.0/racinglines/web/f1_ws.py +283 -0
- racinglines-1.0.0/racinglines/web/fantasy_routes.py +211 -0
- racinglines-1.0.0/racinglines/web/formats.py +87 -0
- racinglines-1.0.0/racinglines/web/info_routes.py +154 -0
- racinglines-1.0.0/racinglines/web/jobs.py +517 -0
- racinglines-1.0.0/racinglines/web/layout.py +52 -0
- racinglines-1.0.0/racinglines/web/legacy.py +38 -0
- racinglines-1.0.0/racinglines/web/mybets.py +28 -0
- racinglines-1.0.0/racinglines/web/order_routes.py +186 -0
- racinglines-1.0.0/racinglines/web/prefs.py +45 -0
- racinglines-1.0.0/racinglines/web/ranges.py +43 -0
- racinglines-1.0.0/racinglines/web/roles.py +192 -0
- racinglines-1.0.0/racinglines/web/sport_status.py +227 -0
- racinglines-1.0.0/racinglines/web/static/app.js +700 -0
- racinglines-1.0.0/racinglines/web/static/brand/logo.svg +8 -0
- racinglines-1.0.0/racinglines/web/static/f1_stream.js +58 -0
- racinglines-1.0.0/racinglines/web/static/htmx.min.js +1 -0
- racinglines-1.0.0/racinglines/web/static/replay.js +115 -0
- racinglines-1.0.0/racinglines/web/static/replay.wasm +0 -0
- racinglines-1.0.0/racinglines/web/static/style.css +643 -0
- racinglines-1.0.0/racinglines/web/strategy_pick.py +208 -0
- racinglines-1.0.0/racinglines/web/templates/_admin_nav.html +9 -0
- racinglines-1.0.0/racinglines/web/templates/_board_recent.html +9 -0
- racinglines-1.0.0/racinglines/web/templates/_board_sport.html +66 -0
- racinglines-1.0.0/racinglines/web/templates/_lab_nav.html +8 -0
- racinglines-1.0.0/racinglines/web/templates/_macros.html +77 -0
- racinglines-1.0.0/racinglines/web/templates/_recorders.html +11 -0
- racinglines-1.0.0/racinglines/web/templates/_site_notice.html +28 -0
- racinglines-1.0.0/racinglines/web/templates/_sport_status.html +14 -0
- racinglines-1.0.0/racinglines/web/templates/_storage_status.html +60 -0
- racinglines-1.0.0/racinglines/web/templates/admin.html +19 -0
- racinglines-1.0.0/racinglines/web/templates/admin_activity.html +17 -0
- racinglines-1.0.0/racinglines/web/templates/admin_db.html +11 -0
- racinglines-1.0.0/racinglines/web/templates/admin_mcp.html +25 -0
- racinglines-1.0.0/racinglines/web/templates/admin_monitors.html +25 -0
- racinglines-1.0.0/racinglines/web/templates/admin_row.html +17 -0
- racinglines-1.0.0/racinglines/web/templates/admin_sql.html +19 -0
- racinglines-1.0.0/racinglines/web/templates/admin_table.html +17 -0
- racinglines-1.0.0/racinglines/web/templates/admin_user.html +29 -0
- racinglines-1.0.0/racinglines/web/templates/admin_users.html +47 -0
- racinglines-1.0.0/racinglines/web/templates/athlete.html +11 -0
- racinglines-1.0.0/racinglines/web/templates/base.html +37 -0
- racinglines-1.0.0/racinglines/web/templates/base_public.html +8 -0
- racinglines-1.0.0/racinglines/web/templates/bet.html +43 -0
- racinglines-1.0.0/racinglines/web/templates/board.html +61 -0
- racinglines-1.0.0/racinglines/web/templates/book.html +32 -0
- racinglines-1.0.0/racinglines/web/templates/diag.html +123 -0
- racinglines-1.0.0/racinglines/web/templates/error.html +7 -0
- racinglines-1.0.0/racinglines/web/templates/event.html +15 -0
- racinglines-1.0.0/racinglines/web/templates/exchange.html +44 -0
- racinglines-1.0.0/racinglines/web/templates/fantasy_trade.html +53 -0
- racinglines-1.0.0/racinglines/web/templates/forgot.html +26 -0
- racinglines-1.0.0/racinglines/web/templates/history.html +90 -0
- racinglines-1.0.0/racinglines/web/templates/house.html +51 -0
- racinglines-1.0.0/racinglines/web/templates/house_market.html +47 -0
- racinglines-1.0.0/racinglines/web/templates/house_sheet.html +15 -0
- racinglines-1.0.0/racinglines/web/templates/lab.html +26 -0
- racinglines-1.0.0/racinglines/web/templates/lab_backtests.html +9 -0
- racinglines-1.0.0/racinglines/web/templates/lab_diagnostics.html +12 -0
- racinglines-1.0.0/racinglines/web/templates/lab_edge.html +134 -0
- racinglines-1.0.0/racinglines/web/templates/lab_jobs.html +12 -0
- racinglines-1.0.0/racinglines/web/templates/lab_models.html +9 -0
- racinglines-1.0.0/racinglines/web/templates/lab_run.html +39 -0
- racinglines-1.0.0/racinglines/web/templates/lab_runs.html +6 -0
- racinglines-1.0.0/racinglines/web/templates/lab_scenarios.html +11 -0
- racinglines-1.0.0/racinglines/web/templates/lab_sport_sweep_form.html +25 -0
- racinglines-1.0.0/racinglines/web/templates/lab_sweep_form.html +40 -0
- racinglines-1.0.0/racinglines/web/templates/live.html +52 -0
- racinglines-1.0.0/racinglines/web/templates/live_f1.html +97 -0
- racinglines-1.0.0/racinglines/web/templates/live_f1_stream.html +690 -0
- racinglines-1.0.0/racinglines/web/templates/live_mtb_dh.html +95 -0
- racinglines-1.0.0/racinglines/web/templates/live_partial.html +1 -0
- racinglines-1.0.0/racinglines/web/templates/live_picks.html +17 -0
- racinglines-1.0.0/racinglines/web/templates/market.html +31 -0
- racinglines-1.0.0/racinglines/web/templates/market_lookup.html +37 -0
- racinglines-1.0.0/racinglines/web/templates/markets.html +18 -0
- racinglines-1.0.0/racinglines/web/templates/mcp_authorize.html +21 -0
- racinglines-1.0.0/racinglines/web/templates/order_preview.html +21 -0
- racinglines-1.0.0/racinglines/web/templates/orders.html +20 -0
- racinglines-1.0.0/racinglines/web/templates/positions.html +144 -0
- racinglines-1.0.0/racinglines/web/templates/positions_backtests.html +26 -0
- racinglines-1.0.0/racinglines/web/templates/race.html +119 -0
- racinglines-1.0.0/racinglines/web/templates/racinglines101.html +389 -0
- racinglines-1.0.0/racinglines/web/templates/run.html +17 -0
- racinglines-1.0.0/racinglines/web/templates/settings.html +111 -0
- racinglines-1.0.0/racinglines/web/templates/signin.html +19 -0
- racinglines-1.0.0/racinglines/web/templates/signup.html +31 -0
- racinglines-1.0.0/racinglines/web/templates/strategy.html +137 -0
- racinglines-1.0.0/racinglines/web/templates/strategy_pick.html +51 -0
- racinglines-1.0.0/racinglines/web/templates/strategy_pick_alpha.html +56 -0
- racinglines-1.0.0/racinglines/web/templates/tapes.html +25 -0
- racinglines-1.0.0/racinglines/web/templates/term.html +51 -0
- racinglines-1.0.0/racinglines/web/term/demos.toml +16 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-10.ansi +21 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-10.html +23 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-2.ansi +7 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-2.html +9 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-4.ansi +21 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-4.html +23 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-6.ansi +21 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-6.html +23 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-8.ansi +21 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore-8.html +23 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore.json +48 -0
- racinglines-1.0.0/racinglines/web/term/f1-singapore.toml +84 -0
- racinglines-1.0.0/racinglines/web/term/quickstart.json +37 -0
- racinglines-1.0.0/racinglines/web/term/step-1.html +0 -0
- racinglines-1.0.0/racinglines/web/term/step-2.ansi +37 -0
- racinglines-1.0.0/racinglines/web/term/step-2.html +39 -0
- racinglines-1.0.0/racinglines/web/term/step-3.ansi +52 -0
- racinglines-1.0.0/racinglines/web/term/step-3.html +54 -0
- racinglines-1.0.0/racinglines/web/term/step-4.ansi +60 -0
- racinglines-1.0.0/racinglines/web/term/step-4.html +62 -0
- racinglines-1.0.0/racinglines/web/term/step-5.ansi +146 -0
- racinglines-1.0.0/racinglines/web/term/step-5.html +148 -0
- racinglines-1.0.0/racinglines/web/term_routes.py +72 -0
- racinglines-1.0.0/racinglines/web/users.py +130 -0
- racinglines-1.0.0/racinglines/web/views.py +1117 -0
- racinglines-1.0.0/racinglines/web/viz.py +183 -0
- racinglines-1.0.0/racinglines.egg-info/PKG-INFO +273 -0
- racinglines-1.0.0/racinglines.egg-info/SOURCES.txt +354 -0
- racinglines-1.0.0/racinglines.egg-info/dependency_links.txt +1 -0
- racinglines-1.0.0/racinglines.egg-info/entry_points.txt +2 -0
- racinglines-1.0.0/racinglines.egg-info/requires.txt +22 -0
- racinglines-1.0.0/racinglines.egg-info/top_level.txt +1 -0
- racinglines-1.0.0/setup.cfg +4 -0
- racinglines-1.0.0/setup.py +26 -0
- racinglines-1.0.0/sports/f1/calibration.toml +241 -0
- racinglines-1.0.0/sports/f1/fastest_lap.toml +72 -0
- racinglines-1.0.0/sports/f1/grid_penalties.toml +24 -0
- racinglines-1.0.0/sports/f1.toml +228 -0
- racinglines-1.0.0/sports/mtb_dh.toml +161 -0
- racinglines-1.0.0/sports/points/uci_dhi_wc.toml +57 -0
- racinglines-1.0.0/tests/test_packaging.py +62 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kevin Lalli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: racinglines
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Fair prices for Formula 1 prediction markets, and the tools to test trading strategies against them
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://racinglines.bet
|
|
7
|
+
Project-URL: Documentation, https://racinglines.bet/docs
|
|
8
|
+
Project-URL: Quickstart, https://racinglines.bet/term
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: rich>=13
|
|
13
|
+
Requires-Dist: numpy>=2
|
|
14
|
+
Requires-Dist: pandas>=2.2
|
|
15
|
+
Requires-Dist: scikit-learn>=1.5
|
|
16
|
+
Requires-Dist: SQLAlchemy>=2
|
|
17
|
+
Provides-Extra: web
|
|
18
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == "web"
|
|
19
|
+
Requires-Dist: alembic>=1.13; extra == "web"
|
|
20
|
+
Requires-Dist: fastapi>=0.115; extra == "web"
|
|
21
|
+
Requires-Dist: uvicorn[standard]>=0.30; extra == "web"
|
|
22
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "web"
|
|
23
|
+
Requires-Dist: Jinja2>=3.1; extra == "web"
|
|
24
|
+
Requires-Dist: httpx>=0.27; extra == "web"
|
|
25
|
+
Requires-Dist: pyarrow>=16; extra == "web"
|
|
26
|
+
Requires-Dist: Markdown>=3.6; extra == "web"
|
|
27
|
+
Requires-Dist: matplotlib>=3.8; extra == "web"
|
|
28
|
+
Requires-Dist: fastf1>=3.4; extra == "web"
|
|
29
|
+
Requires-Dist: pandas<3; extra == "web"
|
|
30
|
+
Requires-Dist: requests>=2.31; extra == "web"
|
|
31
|
+
Requires-Dist: beautifulsoup4>=4.12; extra == "web"
|
|
32
|
+
Requires-Dist: lxml>=5; extra == "web"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# racinglines
|
|
36
|
+
|
|
37
|
+
[](https://pypi.org/project/racinglines/)
|
|
38
|
+
[](https://opensource.org/licenses/MIT)
|
|
39
|
+
|
|
40
|
+
Fair prices for Formula 1 prediction markets. racinglines turns official timing into win, podium, head-to-head and
|
|
41
|
+
championship odds, priced strictly as of any moment (a price never sees data from after its own time), and gives you
|
|
42
|
+
the tools to test trading strategies against those prices: backtests, season forecasts, a live private book that
|
|
43
|
+
reprices after every session and trades against simulated bettors, and a web app with fantasy trading and a live
|
|
44
|
+
viewer. The same engine runs a UCI downhill mountain-bike sim: season forecasts, backtests and a live final.
|
|
45
|
+
|
|
46
|
+
You can try all of it on your own machine with no account, no API key and no real money. The **kart demo** is a
|
|
47
|
+
synthetic F1 season with a Mario Kart grid (Mario, Luigi, Peach, Bowser and friends, racing on Rainbow Road and
|
|
48
|
+
Bowser's Castle). Every lap, result and price in it is invented, and the commands are the same ones that run on real
|
|
49
|
+
F1 data.
|
|
50
|
+
|
|
51
|
+
## How releases work
|
|
52
|
+
|
|
53
|
+
- **What you install is what you can read.** Every version on PyPI is built from a tagged commit in the public source repository, so `pip install racinglines==X` matches tag `vX` line for line.
|
|
54
|
+
- **Releases come now and then, not every day.** Day-to-day development happens elsewhere, and the public repository is updated in occasional releases. Each one lands as a reviewed pull request that follows the same contribution guidelines we ask of everyone.
|
|
55
|
+
- **Contributions are welcome.** Open a pull request against the public repository. Accepted changes are carried into the next release.
|
|
56
|
+
- **Docs:** while the `racinglines[docs]` install is in the works, the documentation is live at https://racinglines.bet/docs.
|
|
57
|
+
- **Quickstart:** watch the demo below run in your browser at https://racinglines.bet/term.
|
|
58
|
+
|
|
59
|
+
## Two ways in
|
|
60
|
+
|
|
61
|
+
| | What you get | What you need |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| **Quick check** (2 minutes) | The engine and the command line, run on synthetic data | Python 3.11+ |
|
|
64
|
+
| **Everything** (about 15 minutes) | A local database, the kart demo, backtests, forecasts, a live private book, the web app with fantasy trading and its live viewer, the downhill sim | Python 3.11+, Docker |
|
|
65
|
+
|
|
66
|
+
### Quick check: `pip install racinglines`
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python3 --version # 3.11 or newer; on an older Python pip says "no matching distribution"
|
|
70
|
+
python3 -m venv ~/rl-try && source ~/rl-try/bin/activate
|
|
71
|
+
pip install racinglines
|
|
72
|
+
racinglines --version
|
|
73
|
+
racinglines check --sport f1 --offline --no-db # the pipelines on synthetic data: no network, no database
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The last command should end with `9/9 checks passed`. That install is the engine and the command line only. For
|
|
77
|
+
the database, the demo, the live book and the web app, install `racinglines[web]` as below.
|
|
78
|
+
|
|
79
|
+
## Everything: database, demo and live viewer
|
|
80
|
+
|
|
81
|
+
Run these in order, one block at a time; each says what you should see. Steps 2 and 4 to 9 were run end to end from
|
|
82
|
+
the built package in a fresh virtualenv, with an empty home folder, against a PostgreSQL like the one step 3 starts.
|
|
83
|
+
|
|
84
|
+
### 1. What you need
|
|
85
|
+
|
|
86
|
+
- **Python 3.11 or newer.** Check with `python3 --version`. On a Mac the built-in `/usr/bin/python3` is too old;
|
|
87
|
+
install a newer one from [python.org](https://www.python.org/downloads/) or with `brew install python@3.12`.
|
|
88
|
+
- **Docker** (Docker Desktop on a Mac or Windows) for the database. Any PostgreSQL 16+ server works instead; see
|
|
89
|
+
step 3.
|
|
90
|
+
|
|
91
|
+
### 2. Install
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
python3 -m venv ~/rl && source ~/rl/bin/activate
|
|
95
|
+
pip install "racinglines[web]"
|
|
96
|
+
racinglines --version
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The quotes matter in zsh (the Mac's shell). `[web]` adds the database, web and timing packages; nothing else needs
|
|
100
|
+
installing. Keep this terminal open: every later step runs with the virtualenv active (`source ~/rl/bin/activate`
|
|
101
|
+
again in a new terminal).
|
|
102
|
+
|
|
103
|
+
### 3. Start the database
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
docker run -d --name racinglines-db -p 5433:5432 -e POSTGRES_USER=racinglines -e POSTGRES_PASSWORD=racinglines \
|
|
107
|
+
-e POSTGRES_DB=racinglines -v racinglines-pgdata:/var/lib/postgresql/data postgres:17
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
That starts PostgreSQL on `localhost:5433` (port 5433 so it doesn't clash with a Postgres you may already run on
|
|
111
|
+
5432), with its data kept in the Docker volume `racinglines-pgdata`. Give it a few seconds, then tell racinglines to
|
|
112
|
+
use it and create its tables:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
racinglines book config source local
|
|
116
|
+
racinglines db init
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`db init` ends with `Reference data seeded.` No Docker? Point `DATABASE_URL` at your own server instead, for example
|
|
120
|
+
`export DATABASE_URL=postgresql+psycopg://USER:PASSWORD@localhost:5432/racinglines`. The user needs the right to
|
|
121
|
+
create databases, because the demo makes its own next to it. The server must use UTF-8 encoding.
|
|
122
|
+
|
|
123
|
+
### 4. Check the install
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
racinglines check --offline
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
It runs the F1 and downhill pipelines on synthetic data and checks the database, in about 5 seconds. It should end
|
|
130
|
+
with `14/14 checks passed`.
|
|
131
|
+
|
|
132
|
+
### 5. Build the kart demo and look at it
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
racinglines db stats --demo
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`--demo` on any command runs that same command on the **demo store**: a separate database (`racinglines_demo_kart`)
|
|
139
|
+
and data folder (`~/.racinglines/data/demo/kart/`) filled with the kart world. The first `--demo` command builds it, with a progress
|
|
140
|
+
bar (under a minute here). Then it prints what's stored: events, sessions, results and market links per season.
|
|
141
|
+
Later commands reuse it.
|
|
142
|
+
|
|
143
|
+
### 6. Backtest the model and forecast the season
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
racinglines model backtest kart --demo
|
|
147
|
+
racinglines model forecast kart --demo --save
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The backtest prices every past race as of before the weekend, before qualifying and before the race, then scores
|
|
151
|
+
those prices against what happened (about 30 seconds). It ends with a best call and the biggest upset, and saves the
|
|
152
|
+
per-race rows as a CSV. The forecast prices the races still to come and both championships, and `--save` stores it
|
|
153
|
+
for the web app (`Saved forecast run ...`).
|
|
154
|
+
|
|
155
|
+
### 7. Run a live private book
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
racinglines live run kart/demo-2026-09 --demo --simulate --no-fetch
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
This replays one race weekend, the Bowser's Castle Grand Prix, on a simulated clock (about 30 seconds). A market maker
|
|
162
|
+
opens a book before practice, reprices it after every session from the model, and 100 simulated bettors trade against
|
|
163
|
+
it until the book closes at lights out. Then it settles from the results. It ends with a summary box: the fills, the
|
|
164
|
+
money traded, and how many bettors finished up or down.
|
|
165
|
+
|
|
166
|
+
Afterwards:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
racinglines live status --demo
|
|
170
|
+
racinglines live report kart/demo-2026-09 --demo
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`live status` lists the event as `settled`. `live report` writes the event report (Markdown and charts) under
|
|
174
|
+
`~/.racinglines/data/demo/kart/runs/live/demo-2026-09/report/`.
|
|
175
|
+
|
|
176
|
+
### 8. Price a sportsbook's lines
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
racinglines book price --demo
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The demo carries a sample sportsbook's lines on two upcoming races. This prints each leg with the model's fair price,
|
|
183
|
+
the exchange price, the book's implied probability and the expected value against each.
|
|
184
|
+
|
|
185
|
+
### 9. Open the web app and the live viewer
|
|
186
|
+
|
|
187
|
+
> **Read this first.** This runs your own copy of the racinglines web app on your machine. It is not
|
|
188
|
+
> [racinglines.bet](https://racinglines.bet), and accounts here have nothing to do with that site. The code is
|
|
189
|
+
> MIT-licensed ([LICENSE](LICENSE)): use it, change it, host it. The racinglines name and branding (the logo in
|
|
190
|
+
> `racinglines/web/static/brand/`, the wordmark on the sign-in page, the page titles and the top bar) are
|
|
191
|
+
> © 2026 Kevin Lalli and not covered by that licence: replace them before you put this app on any public link.
|
|
192
|
+
> `racinglines web` prints the same notice when it starts.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
RACINGLINES_FANTASY=1 ADMIN_PASSWORD=choose-one racinglines web --demo
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Pick your own password in place of `choose-one`. The app runs at <http://127.0.0.1:8000> on your machine only; stop
|
|
199
|
+
it with Ctrl+C. With `--demo` it sets up the accounts and fantasy-trading tables on first start and creates the demo
|
|
200
|
+
accounts, so nothing else is needed before you sign in.
|
|
201
|
+
|
|
202
|
+
1. Open <http://127.0.0.1:8000> and click **Try the demo** (the demo account, `maker`, a pro). Or sign in as `admin`
|
|
203
|
+
with the password you chose; a box then asks for an email so you don't get locked out: click **Skip for now**,
|
|
204
|
+
nothing leaves your machine.
|
|
205
|
+
2. Click **Live** in the top bar. That's the live viewer for the race you ran in step 7: the winner, the maker's
|
|
206
|
+
settled P&L, the crowd's fills and volume, and a **Replay** bar to step or play through the weekend's seven
|
|
207
|
+
updates as they were seen live.
|
|
208
|
+
3. **Markets** shows the forecast you saved in step 6, and **Lab** has the backtests and strategy tools.
|
|
209
|
+
4. **Trade** and **History** are fantasy trading with F$ 1,000 of play money (`RACINGLINES_FANTASY=1` turns them
|
|
210
|
+
on). Trade lists exchange markets with a book recorded in the last day; the demo's recorded books are older, so
|
|
211
|
+
in the demo it opens with no markets.
|
|
212
|
+
|
|
213
|
+
To add more accounts, by role, stop the app (Ctrl+C) and run, for each one:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
racinglines users add alice --role basic --demo
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`--role` is `admin` (everything, plus user management and the database explorer), `pro` (fair prices, quotes,
|
|
220
|
+
every strategy and the Lab) or `basic` (open markets, a few taker strategies, their own bets). Each prints a one-time
|
|
221
|
+
password; `racinglines users list --demo` shows who exists. Then start the app again as above.
|
|
222
|
+
|
|
223
|
+
### 10. The downhill sim
|
|
224
|
+
|
|
225
|
+
`racinglines check` in step 4 already ran the downhill model, forecast and backtest on synthetic data. On real UCI
|
|
226
|
+
World Cup results it needs the network: `racinglines mtb_dh -h` lists its commands (download, parse, ingest,
|
|
227
|
+
forecast, backtest, points, live), and `racinglines data download mtb_dh -h` explains how results are found on
|
|
228
|
+
ChronoRace. No results ship with the package.
|
|
229
|
+
|
|
230
|
+
### Where things are, and starting over
|
|
231
|
+
|
|
232
|
+
| What | Where |
|
|
233
|
+
|---|---|
|
|
234
|
+
| The main database | `racinglines` on `localhost:5433` (the Docker volume `racinglines-pgdata`) |
|
|
235
|
+
| The demo database | `racinglines_demo_kart`, on the same server |
|
|
236
|
+
| The demo's files, runs and reports | `~/.racinglines/data/demo/kart/` |
|
|
237
|
+
| Your settings | `~/.config/racinglines/cli.toml` |
|
|
238
|
+
|
|
239
|
+
To rebuild the demo from scratch, delete `~/.racinglines/data/demo/kart/demo-store.json` and run any `--demo` command
|
|
240
|
+
again. To remove everything: `docker rm -f racinglines-db && docker volume rm racinglines-pgdata`, then delete
|
|
241
|
+
`~/.racinglines` and the virtualenv `~/rl`.
|
|
242
|
+
|
|
243
|
+
### If something goes wrong
|
|
244
|
+
|
|
245
|
+
| What you see | What it means |
|
|
246
|
+
|---|---|
|
|
247
|
+
| `No matching distribution found` during `pip install` | Your Python is too old. Check `python3 --version`, then make the virtualenv with a newer one (step 1) |
|
|
248
|
+
| `Requirement already satisfied` with an old version | `pip` belongs to another environment (conda, for example). Activate this virtualenv first, or run `~/rl/bin/pip` |
|
|
249
|
+
| `zsh: no matches found: racinglines[web]` | Quote it: `pip install "racinglines[web]"` |
|
|
250
|
+
| `command not found: racinglines` | The virtualenv isn't active in this terminal: `source ~/rl/bin/activate` |
|
|
251
|
+
| `needs psycopg, which the core install leaves out` (or another package) | The plain install is missing the extra: `pip install "racinglines[web]"` |
|
|
252
|
+
| `racinglines needs a database, and none is configured` | Step 3 was skipped: run `racinglines book config source local` |
|
|
253
|
+
| `demo: no Postgres server for ...` | The database isn't running: `docker start racinglines-db`, then `docker ps` should list it |
|
|
254
|
+
| `check` fails on `alembic_version` | The tables don't exist yet: `racinglines db init` |
|
|
255
|
+
|
|
256
|
+
### From source (contributors)
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
git clone https://github.com/racinglines/racinglines.git && cd racinglines
|
|
260
|
+
python3 -m venv .venv-rl && source .venv-rl/bin/activate
|
|
261
|
+
pip install -r requirements.txt && pip install -e . # Python 3.12+ for the pinned versions
|
|
262
|
+
docker compose up -d # the same database as step 3
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Then steps 3 (`book config` and `db init`) to 10 as above; the demo's files go under `data/demo/kart/` in the checkout.
|
|
266
|
+
|
|
267
|
+
## More
|
|
268
|
+
|
|
269
|
+
- Documentation: https://racinglines.bet/docs (the quickstart, the model, market making, the CLI reference)
|
|
270
|
+
- The same demo, recorded, in your browser: https://racinglines.bet/term
|
|
271
|
+
- `racinglines <group> -h` lists any command group's commands and options.
|
|
272
|
+
|
|
273
|
+
MIT licensed.
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# racinglines
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/racinglines/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Fair prices for Formula 1 prediction markets. racinglines turns official timing into win, podium, head-to-head and
|
|
7
|
+
championship odds, priced strictly as of any moment (a price never sees data from after its own time), and gives you
|
|
8
|
+
the tools to test trading strategies against those prices: backtests, season forecasts, a live private book that
|
|
9
|
+
reprices after every session and trades against simulated bettors, and a web app with fantasy trading and a live
|
|
10
|
+
viewer. The same engine runs a UCI downhill mountain-bike sim: season forecasts, backtests and a live final.
|
|
11
|
+
|
|
12
|
+
You can try all of it on your own machine with no account, no API key and no real money. The **kart demo** is a
|
|
13
|
+
synthetic F1 season with a Mario Kart grid (Mario, Luigi, Peach, Bowser and friends, racing on Rainbow Road and
|
|
14
|
+
Bowser's Castle). Every lap, result and price in it is invented, and the commands are the same ones that run on real
|
|
15
|
+
F1 data.
|
|
16
|
+
|
|
17
|
+
## How releases work
|
|
18
|
+
|
|
19
|
+
- **What you install is what you can read.** Every version on PyPI is built from a tagged commit in the public source repository, so `pip install racinglines==X` matches tag `vX` line for line.
|
|
20
|
+
- **Releases come now and then, not every day.** Day-to-day development happens elsewhere, and the public repository is updated in occasional releases. Each one lands as a reviewed pull request that follows the same contribution guidelines we ask of everyone.
|
|
21
|
+
- **Contributions are welcome.** Open a pull request against the public repository. Accepted changes are carried into the next release.
|
|
22
|
+
- **Docs:** while the `racinglines[docs]` install is in the works, the documentation is live at https://racinglines.bet/docs.
|
|
23
|
+
- **Quickstart:** watch the demo below run in your browser at https://racinglines.bet/term.
|
|
24
|
+
|
|
25
|
+
## Two ways in
|
|
26
|
+
|
|
27
|
+
| | What you get | What you need |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| **Quick check** (2 minutes) | The engine and the command line, run on synthetic data | Python 3.11+ |
|
|
30
|
+
| **Everything** (about 15 minutes) | A local database, the kart demo, backtests, forecasts, a live private book, the web app with fantasy trading and its live viewer, the downhill sim | Python 3.11+, Docker |
|
|
31
|
+
|
|
32
|
+
### Quick check: `pip install racinglines`
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
python3 --version # 3.11 or newer; on an older Python pip says "no matching distribution"
|
|
36
|
+
python3 -m venv ~/rl-try && source ~/rl-try/bin/activate
|
|
37
|
+
pip install racinglines
|
|
38
|
+
racinglines --version
|
|
39
|
+
racinglines check --sport f1 --offline --no-db # the pipelines on synthetic data: no network, no database
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The last command should end with `9/9 checks passed`. That install is the engine and the command line only. For
|
|
43
|
+
the database, the demo, the live book and the web app, install `racinglines[web]` as below.
|
|
44
|
+
|
|
45
|
+
## Everything: database, demo and live viewer
|
|
46
|
+
|
|
47
|
+
Run these in order, one block at a time; each says what you should see. Steps 2 and 4 to 9 were run end to end from
|
|
48
|
+
the built package in a fresh virtualenv, with an empty home folder, against a PostgreSQL like the one step 3 starts.
|
|
49
|
+
|
|
50
|
+
### 1. What you need
|
|
51
|
+
|
|
52
|
+
- **Python 3.11 or newer.** Check with `python3 --version`. On a Mac the built-in `/usr/bin/python3` is too old;
|
|
53
|
+
install a newer one from [python.org](https://www.python.org/downloads/) or with `brew install python@3.12`.
|
|
54
|
+
- **Docker** (Docker Desktop on a Mac or Windows) for the database. Any PostgreSQL 16+ server works instead; see
|
|
55
|
+
step 3.
|
|
56
|
+
|
|
57
|
+
### 2. Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python3 -m venv ~/rl && source ~/rl/bin/activate
|
|
61
|
+
pip install "racinglines[web]"
|
|
62
|
+
racinglines --version
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The quotes matter in zsh (the Mac's shell). `[web]` adds the database, web and timing packages; nothing else needs
|
|
66
|
+
installing. Keep this terminal open: every later step runs with the virtualenv active (`source ~/rl/bin/activate`
|
|
67
|
+
again in a new terminal).
|
|
68
|
+
|
|
69
|
+
### 3. Start the database
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
docker run -d --name racinglines-db -p 5433:5432 -e POSTGRES_USER=racinglines -e POSTGRES_PASSWORD=racinglines \
|
|
73
|
+
-e POSTGRES_DB=racinglines -v racinglines-pgdata:/var/lib/postgresql/data postgres:17
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
That starts PostgreSQL on `localhost:5433` (port 5433 so it doesn't clash with a Postgres you may already run on
|
|
77
|
+
5432), with its data kept in the Docker volume `racinglines-pgdata`. Give it a few seconds, then tell racinglines to
|
|
78
|
+
use it and create its tables:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
racinglines book config source local
|
|
82
|
+
racinglines db init
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`db init` ends with `Reference data seeded.` No Docker? Point `DATABASE_URL` at your own server instead, for example
|
|
86
|
+
`export DATABASE_URL=postgresql+psycopg://USER:PASSWORD@localhost:5432/racinglines`. The user needs the right to
|
|
87
|
+
create databases, because the demo makes its own next to it. The server must use UTF-8 encoding.
|
|
88
|
+
|
|
89
|
+
### 4. Check the install
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
racinglines check --offline
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
It runs the F1 and downhill pipelines on synthetic data and checks the database, in about 5 seconds. It should end
|
|
96
|
+
with `14/14 checks passed`.
|
|
97
|
+
|
|
98
|
+
### 5. Build the kart demo and look at it
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
racinglines db stats --demo
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`--demo` on any command runs that same command on the **demo store**: a separate database (`racinglines_demo_kart`)
|
|
105
|
+
and data folder (`~/.racinglines/data/demo/kart/`) filled with the kart world. The first `--demo` command builds it, with a progress
|
|
106
|
+
bar (under a minute here). Then it prints what's stored: events, sessions, results and market links per season.
|
|
107
|
+
Later commands reuse it.
|
|
108
|
+
|
|
109
|
+
### 6. Backtest the model and forecast the season
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
racinglines model backtest kart --demo
|
|
113
|
+
racinglines model forecast kart --demo --save
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The backtest prices every past race as of before the weekend, before qualifying and before the race, then scores
|
|
117
|
+
those prices against what happened (about 30 seconds). It ends with a best call and the biggest upset, and saves the
|
|
118
|
+
per-race rows as a CSV. The forecast prices the races still to come and both championships, and `--save` stores it
|
|
119
|
+
for the web app (`Saved forecast run ...`).
|
|
120
|
+
|
|
121
|
+
### 7. Run a live private book
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
racinglines live run kart/demo-2026-09 --demo --simulate --no-fetch
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This replays one race weekend, the Bowser's Castle Grand Prix, on a simulated clock (about 30 seconds). A market maker
|
|
128
|
+
opens a book before practice, reprices it after every session from the model, and 100 simulated bettors trade against
|
|
129
|
+
it until the book closes at lights out. Then it settles from the results. It ends with a summary box: the fills, the
|
|
130
|
+
money traded, and how many bettors finished up or down.
|
|
131
|
+
|
|
132
|
+
Afterwards:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
racinglines live status --demo
|
|
136
|
+
racinglines live report kart/demo-2026-09 --demo
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`live status` lists the event as `settled`. `live report` writes the event report (Markdown and charts) under
|
|
140
|
+
`~/.racinglines/data/demo/kart/runs/live/demo-2026-09/report/`.
|
|
141
|
+
|
|
142
|
+
### 8. Price a sportsbook's lines
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
racinglines book price --demo
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The demo carries a sample sportsbook's lines on two upcoming races. This prints each leg with the model's fair price,
|
|
149
|
+
the exchange price, the book's implied probability and the expected value against each.
|
|
150
|
+
|
|
151
|
+
### 9. Open the web app and the live viewer
|
|
152
|
+
|
|
153
|
+
> **Read this first.** This runs your own copy of the racinglines web app on your machine. It is not
|
|
154
|
+
> [racinglines.bet](https://racinglines.bet), and accounts here have nothing to do with that site. The code is
|
|
155
|
+
> MIT-licensed ([LICENSE](LICENSE)): use it, change it, host it. The racinglines name and branding (the logo in
|
|
156
|
+
> `racinglines/web/static/brand/`, the wordmark on the sign-in page, the page titles and the top bar) are
|
|
157
|
+
> © 2026 Kevin Lalli and not covered by that licence: replace them before you put this app on any public link.
|
|
158
|
+
> `racinglines web` prints the same notice when it starts.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
RACINGLINES_FANTASY=1 ADMIN_PASSWORD=choose-one racinglines web --demo
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Pick your own password in place of `choose-one`. The app runs at <http://127.0.0.1:8000> on your machine only; stop
|
|
165
|
+
it with Ctrl+C. With `--demo` it sets up the accounts and fantasy-trading tables on first start and creates the demo
|
|
166
|
+
accounts, so nothing else is needed before you sign in.
|
|
167
|
+
|
|
168
|
+
1. Open <http://127.0.0.1:8000> and click **Try the demo** (the demo account, `maker`, a pro). Or sign in as `admin`
|
|
169
|
+
with the password you chose; a box then asks for an email so you don't get locked out: click **Skip for now**,
|
|
170
|
+
nothing leaves your machine.
|
|
171
|
+
2. Click **Live** in the top bar. That's the live viewer for the race you ran in step 7: the winner, the maker's
|
|
172
|
+
settled P&L, the crowd's fills and volume, and a **Replay** bar to step or play through the weekend's seven
|
|
173
|
+
updates as they were seen live.
|
|
174
|
+
3. **Markets** shows the forecast you saved in step 6, and **Lab** has the backtests and strategy tools.
|
|
175
|
+
4. **Trade** and **History** are fantasy trading with F$ 1,000 of play money (`RACINGLINES_FANTASY=1` turns them
|
|
176
|
+
on). Trade lists exchange markets with a book recorded in the last day; the demo's recorded books are older, so
|
|
177
|
+
in the demo it opens with no markets.
|
|
178
|
+
|
|
179
|
+
To add more accounts, by role, stop the app (Ctrl+C) and run, for each one:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
racinglines users add alice --role basic --demo
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`--role` is `admin` (everything, plus user management and the database explorer), `pro` (fair prices, quotes,
|
|
186
|
+
every strategy and the Lab) or `basic` (open markets, a few taker strategies, their own bets). Each prints a one-time
|
|
187
|
+
password; `racinglines users list --demo` shows who exists. Then start the app again as above.
|
|
188
|
+
|
|
189
|
+
### 10. The downhill sim
|
|
190
|
+
|
|
191
|
+
`racinglines check` in step 4 already ran the downhill model, forecast and backtest on synthetic data. On real UCI
|
|
192
|
+
World Cup results it needs the network: `racinglines mtb_dh -h` lists its commands (download, parse, ingest,
|
|
193
|
+
forecast, backtest, points, live), and `racinglines data download mtb_dh -h` explains how results are found on
|
|
194
|
+
ChronoRace. No results ship with the package.
|
|
195
|
+
|
|
196
|
+
### Where things are, and starting over
|
|
197
|
+
|
|
198
|
+
| What | Where |
|
|
199
|
+
|---|---|
|
|
200
|
+
| The main database | `racinglines` on `localhost:5433` (the Docker volume `racinglines-pgdata`) |
|
|
201
|
+
| The demo database | `racinglines_demo_kart`, on the same server |
|
|
202
|
+
| The demo's files, runs and reports | `~/.racinglines/data/demo/kart/` |
|
|
203
|
+
| Your settings | `~/.config/racinglines/cli.toml` |
|
|
204
|
+
|
|
205
|
+
To rebuild the demo from scratch, delete `~/.racinglines/data/demo/kart/demo-store.json` and run any `--demo` command
|
|
206
|
+
again. To remove everything: `docker rm -f racinglines-db && docker volume rm racinglines-pgdata`, then delete
|
|
207
|
+
`~/.racinglines` and the virtualenv `~/rl`.
|
|
208
|
+
|
|
209
|
+
### If something goes wrong
|
|
210
|
+
|
|
211
|
+
| What you see | What it means |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `No matching distribution found` during `pip install` | Your Python is too old. Check `python3 --version`, then make the virtualenv with a newer one (step 1) |
|
|
214
|
+
| `Requirement already satisfied` with an old version | `pip` belongs to another environment (conda, for example). Activate this virtualenv first, or run `~/rl/bin/pip` |
|
|
215
|
+
| `zsh: no matches found: racinglines[web]` | Quote it: `pip install "racinglines[web]"` |
|
|
216
|
+
| `command not found: racinglines` | The virtualenv isn't active in this terminal: `source ~/rl/bin/activate` |
|
|
217
|
+
| `needs psycopg, which the core install leaves out` (or another package) | The plain install is missing the extra: `pip install "racinglines[web]"` |
|
|
218
|
+
| `racinglines needs a database, and none is configured` | Step 3 was skipped: run `racinglines book config source local` |
|
|
219
|
+
| `demo: no Postgres server for ...` | The database isn't running: `docker start racinglines-db`, then `docker ps` should list it |
|
|
220
|
+
| `check` fails on `alembic_version` | The tables don't exist yet: `racinglines db init` |
|
|
221
|
+
|
|
222
|
+
### From source (contributors)
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git clone https://github.com/racinglines/racinglines.git && cd racinglines
|
|
226
|
+
python3 -m venv .venv-rl && source .venv-rl/bin/activate
|
|
227
|
+
pip install -r requirements.txt && pip install -e . # Python 3.12+ for the pinned versions
|
|
228
|
+
docker compose up -d # the same database as step 3
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Then steps 3 (`book config` and `db init`) to 10 as above; the demo's files go under `data/demo/kart/` in the checkout.
|
|
232
|
+
|
|
233
|
+
## More
|
|
234
|
+
|
|
235
|
+
- Documentation: https://racinglines.bet/docs (the quickstart, the model, market making, the CLI reference)
|
|
236
|
+
- The same demo, recorded, in your browser: https://racinglines.bet/term
|
|
237
|
+
- `racinglines <group> -h` lists any command group's commands and options.
|
|
238
|
+
|
|
239
|
+
MIT licensed.
|