{"id":50811753,"url":"https://github.com/hu553in/polybot","last_synced_at":"2026-06-13T05:06:09.058Z","repository":{"id":355922571,"uuid":"1230230399","full_name":"hu553in/polybot","owner":"hu553in","description":"Chainlink-aligned Polymarket BTC/ETH 5m trading bot with executable CLOB quotes.","archived":false,"fork":false,"pushed_at":"2026-05-21T06:04:20.000Z","size":609,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T12:54:17.946Z","etag":null,"topics":["algorithmic-trading","backtesting","binance","bitcoin","btc","chainlink","clob","crypto-trading","eth","ethereum","paper-trading","polymarket","prediction-markets","python","risk-management","trading-bot"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hu553in.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-05T19:58:17.000Z","updated_at":"2026-05-21T06:04:22.000Z","dependencies_parsed_at":"2026-05-21T08:03:05.529Z","dependency_job_id":null,"html_url":"https://github.com/hu553in/polybot","commit_stats":null,"previous_names":["hu553in/polybot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hu553in/polybot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hu553in%2Fpolybot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hu553in%2Fpolybot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hu553in%2Fpolybot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hu553in%2Fpolybot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hu553in","download_url":"https://codeload.github.com/hu553in/polybot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hu553in%2Fpolybot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34272673,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithmic-trading","backtesting","binance","bitcoin","btc","chainlink","clob","crypto-trading","eth","ethereum","paper-trading","polymarket","prediction-markets","python","risk-management","trading-bot"],"created_at":"2026-06-13T05:06:08.156Z","updated_at":"2026-06-13T05:06:09.051Z","avatar_url":"https://github.com/hu553in.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Polybot\n\n[![CI](https://github.com/hu553in/polybot/actions/workflows/ci.yml/badge.svg)](https://github.com/hu553in/polybot/actions/workflows/ci.yml)\n\nPolymarket BTC/ETH Up/Down 5m trading bot with Chainlink-aligned price analysis, executable\nCLOB quotes, paper/live modes, risk limits, SQLite history, and Telegram notifications.\n\nThe bot is built for short-window binary markets where the settlement line is the window open\nprice. It chooses a direction from the current move, estimates whether the market price is\nmispriced after fees, and enters only when signal, execution quality, timing, and risk gates all\npass.\n\n## ⚠️ Financial warning\n\n**This bot does not guarantee profit. It can lose money, including all allocated capital. Do not\ntrade live with money you cannot afford to lose.**\n\n## What it does\n\n- Tracks BTC and ETH 5-minute Up/Down markets on Polymarket.\n- Uses Gamma for market metadata and CLOB token winners for official settlement data.\n- Uses a fresh CLOB WebSocket order-book cache first, with REST order-book fallback for executable\n  buy VWAP.\n- Uses Chainlink RTDS for runtime open/current/close prices and Binance spot/futures as context data.\n- Scores the move with delta, ATR, micro-momentum, volume heat, multi-timeframe confirmation,\n  higher-timeframe trend, funding bias, market regime, and BTC/ETH correlation.\n- Applies price, edge, quote-age, liquidity, spread, depth, push-risk, timing, and risk guards\n  before entry.\n- Supports paper and live modes.\n- Stores snapshots, decisions, trades, and settlements in SQLite when storage is enabled.\n- Sends Telegram alerts for startup, entries, execution blocks/failures, risk blocks, settlements, and summaries.\n- Adds Telegram `/summary` and `/wallet` commands when Telegram is configured.\n- Keeps Telegram notifications event-based; ordinary console logs and debug noise are not mirrored to chat.\n\n## Components\n\n- **cli**: Typer commands: `run`, `doctor`, `healthcheck`, `show-config`, and `export`\n- **bot**: market loop, entry window handling, decisions, execution, settlement\n- **analysis**: price sourcing, delta direction, ATR, momentum, volume, higher timeframes, funding\n- **probability**: transparent heuristic probability model\n- **calibration**: rolling isotonic probability calibration from settled trades\n- **strategy**: dynamic delta skip, required edge, and position sizing helpers\n- **polymarket**: Gamma market lookup, CLOB official resolution lookup, CLOB WS/REST order-book quotes\n- **executor**: live CLOB buy execution and live order checks\n- **risk**: run/day/notional/consecutive-loss, drawdown, VaR, and expected shortfall limits\n- **storage**: SQLite persistence and migrations\n- **logging**: plain/Rich or structured JSON console logs, Telegram notifications, and run summary\n\n## Architecture\n\n```mermaid\nflowchart LR\n    G[\"Gamma markets\"] --\u003e B[\"Bot loop\"]\n    CL[\"Chainlink RTDS\"] --\u003e A[\"Analysis\"]\n    BN[\"Binance candles and funding\"] --\u003e A\n    CLOB[\"CLOB WebSocket and REST order book\"] --\u003e Q[\"Executable quote\"]\n    B --\u003e A\n    B --\u003e Q\n    A --\u003e D[\"Decision gates\"]\n    Q --\u003e D\n    D --\u003e R[\"Risk limits\"]\n    R --\u003e X[\"Paper or live buy\"]\n    X --\u003e S[\"SQLite, logs, Telegram\"]\n    G --\u003e O[\"Official settlement\"]\n    O --\u003e S\n```\n\n## Trading lifecycle\n\n1. Compute the next 5-minute close and the corresponding market slug.\n2. Capture the Chainlink window open when possible. Missing or stale Chainlink data pauses entries.\n   The default open/price freshness windows allow normal RTDS publication lag, while still rejecting\n   genuinely old ticks. At a close boundary, the next window open is captured before settling the\n   just-closed window, so settlement latency cannot make the next market miss its price-to-beat.\n3. Wake shortly before close and poll only inside the configured entry window.\n4. Fetch BTC and ETH market state in parallel.\n5. Analyze each market against the settlement line and apply the BTC/ETH correlation filter.\n6. Build a decision from signal quality, execution quote, timing, edge, and risk limits.\n7. Optionally wait for a better edge until the forced-decision cutoff.\n8. Enter once per market slug when every gate passes.\n9. After market close, fetch official settlement and update realized result metrics. If the\n   official result and a fresh Chainlink close tick are both unavailable, keep traded slugs pending\n   and retry instead of finalizing an `UNKNOWN` result.\n\n## Strategy\n\n### Direction and base signal\n\nThe settlement line is the window open price. If the current price is above it, the considered side\nis `Up`; if below it, the side is `Down`. The absolute move from the open is the main signal.\n\nVery small moves are skipped through `POLYBOT_DELTA_SKIP`. That threshold is dynamic:\n\n- late in the window it is multiplied by `POLYBOT_DELTA_SKIP_LATE_MULTIPLIER`\n- as ATR ratio rises, it is discounted by `POLYBOT_DELTA_SKIP_ATR_DISCOUNT_*`\n- in high-volatility candles it is multiplied by `POLYBOT_DELTA_SKIP_HIGH_VOL_MULTIPLIER`\n\nThis keeps noise out early in the window while still allowing stronger late moves to pass.\n\nLate relaxed entries have one extra guard: if the move is still below\n`POLYBOT_LATE_WEAK_SIGNAL_DELTA_MAX`, the bot requires at least\n`POLYBOT_LATE_WEAK_SIGNAL_MIN_MOMENTUM_SCORE` unless volume is strongly aligned. This blocks fragile\nlast-seconds near-line trades where a small reversal can flip the result.\n\n### Probability model\n\nThe model is a transparent heuristic, not a trained model. It starts from an interpolated probability\nbased on delta strength:\n\n- `POLYBOT_DELTA_SKIP` to `POLYBOT_DELTA_WEAK`\n- `POLYBOT_DELTA_WEAK` to `POLYBOT_DELTA_STRONG`\n- `POLYBOT_DELTA_STRONG` to `POLYBOT_DELTA_VERY_STRONG`\n\nThen it adjusts probability with context:\n\n- **source quality**: stale Chainlink source age is penalized\n- **ATR**: overheated candles and high ATR ratios reduce confidence\n- **micro-momentum**: recent 1-minute candles are volume-weighted; acceleration can add confidence\n- **volume heat**: unusually high aligned Binance volume can add confidence\n- **multi-timeframe confirmation**: the live 5-minute candle can add confidence or penalize a counter-signal\n- **higher timeframes**: 15-minute and 1-hour candles can confirm or penalize the 5-minute impulse\n- **funding bias**: Binance futures funding is treated as a directional crowding signal\n- **regime**: trending and strong-trending regimes add confidence; high-volatility regimes penalize confidence\n- **correlation**: BTC/ETH disagreement or a weak peer move dynamically penalizes the weaker signal\n\nWhen SQLite contains enough settled trades, the final probability is passed through a rolling\nisotonic calibration curve. This does not make the model predictive by itself; it only shrinks\nrepeated overconfidence or underconfidence observed in the bot's own settled history. Calibration\nis mode-specific, so live execution is not tuned from paper fills. The bot refreshes that\ncalibrator after settled trades, so a long-running process can adapt without a restart.\n\n### Edge and price gates\n\nThe entry price is the executable buy VWAP from CLOB asks. Gamma prices are metadata only and are\nnever used as entry quotes.\n\nFor each candidate, the bot computes:\n\n```text\nbreakeven = fee-adjusted entry price\nedge = probability - breakeven\n```\n\nThe trade must pass:\n\n- `POLYBOT_MIN_CONFIDENCE`\n- dynamic required confidence after late-entry and ATR discounts\n- dynamic required edge from `POLYBOT_MIN_EDGE`\n- `POLYBOT_MIN_EDGE_FLOOR` after late-entry and ATR discounts\n- per-asset `POLYBOT_BTC_ENTRY_PRICE_MIN` / `POLYBOT_ETH_ENTRY_PRICE_MIN`\n- `POLYBOT_ENTRY_PRICE_MAX`\n\nThe bot also estimates near-line push risk. A tiny move can pass the late dynamic delta threshold,\nbut still be rejected if the configured push-risk estimate is too high.\n\nWeak moves just above the dynamic delta threshold are probability-capped before edge math. This\nprevents momentum/volume bonuses from turning a barely-off-the-line setup into a falsely strong\n95%+ signal. Expensive entries also pay a small high-price premium: near the top of the binary\nprice range, the required edge and confidence are slightly higher because one tick of slippage or\none small reversal matters more.\n\nIf dynamic entry is enabled, a barely valid early trade can be delayed until either edge or\nearly-window delta is clearly stronger, or until the forced-decision cutoff is reached.\n\n### Execution quality guards\n\nBefore entry, the bot checks that the market is tradable enough for the configured amount:\n\n- minimum market liquidity\n- known bid/ask spread\n- max spread\n- minimum book depth in shares\n- maximum order book levels consumed\n- maximum VWAP slippage versus best ask\n- fresh CLOB quote age\n- side-collapse guard when the considered side quote suddenly drops\n- top-of-book bid/ask depth imbalance as a probability bonus or penalty\n- one trade attempt per slug by default\n\nLive mode repeats the edge check against the actual live order price before submitting the order.\nIt can also use a stricter live-only VWAP slippage cap through `POLYBOT_LIVE_MAX_VWAP_TO_BEST_ASK_BPS`.\nTransient live order submit failures can be retried with a small exponential backoff; rejected or\nambiguous orders are not blindly retried. The live taker FAK/FOK BUY flow uses the CLOB\nmarket-order API and sends the pUSD amount, matching Polymarket's UI-style cash sizing.\n\n### Position sizing\n\nPosition size starts from `POLYBOT_AMOUNT` and changes with edge quality:\n\n- low edge near the threshold uses `POLYBOT_POSITION_SIZE_MIN_MULTIPLIER`\n- strong edge can scale toward `POLYBOT_POSITION_SIZE_MAX_MULTIPLIER`\n- strong-trending regime can scale size up, within the cap\n- high ATR or high-volatility regime reduces size\n- near-line distance reduces size when the move barely cleared the dynamic delta threshold\n- late-window entries can slightly increase size\n- fractional Kelly can cap the computed size using configured bankroll and fraction\n- correlated same-window BTC/ETH exposure can reduce the second same-direction trade\n\nAll sizing is still bounded by the risk limits below.\n\n## Risk controls\n\n- `POLYBOT_MAX_TRADES`: max trades per process run\n- `POLYBOT_MAX_TRADES_PER_DAY`: max trades per UTC day\n- `POLYBOT_MAX_DAILY_NOTIONAL`: max daily pUSD notional\n- `POLYBOT_MAX_CONSECUTIVE_LOSSES`: stop after a configured losing streak\n- `POLYBOT_MAX_DRAWDOWN_PCT`: pause entries after realized drawdown exceeds the configured budget\n- `POLYBOT_VAR_*`: block entries when historical tail loss exceeds the configured VaR threshold\n- `POLYBOT_EXPECTED_SHORTFALL_MAX_LOSS`: block entries when average tail loss is too large\n- `POLYBOT_MAX_CORRELATED_EXPOSURE`: cap same-window, same-direction BTC/ETH exposure\n- `POLYBOT_LIVE_PRIVATE_KEY` and `POLYBOT_LIVE_WALLET`: required only for live execution\n\nThe current live strategy is entry-and-settle. It does not actively sell positions before market\nresolution.\n\n## Quick start\n\nInstall dependencies, create a local config, inspect it, check external services, and start the bot.\nWith no explicit mode set, `run` uses paper mode.\n\n```bash\nmake install-deps\ncp .env.example .env\nuv run polybot show-config\nuv run polybot doctor\nuv run polybot run\n```\n\n## Modes\n\nThe two modes are mutually exclusive. With nothing set, the bot defaults to **paper** so a\nforgotten env var cannot accidentally place real orders.\n\n| Behavior                                                    | paper      | live        |\n| ----------------------------------------------------------- | ---------- | ----------- |\n| Calls real CLOB execution                                   | no         | yes         |\n| Records `TradeRecord` to storage                            | yes        | yes         |\n| Writes `Snapshot` / `Decision` rows                         | yes        | yes         |\n| Entry price                                                 | quote VWAP | taker limit |\n| Requires `POLYBOT_LIVE_PRIVATE_KEY` + `POLYBOT_LIVE_WALLET` | no         | yes         |\n\nWhen to pick which:\n\n- **paper**: realistic strategy simulation against live market data; default for research.\n- **live**: actually submits orders. Repeats the edge check against the live order price before\n  posting and can use a stricter live-only VWAP slippage cap.\n\n## CLI commands\n\n```bash\nuv run polybot run           # start the trading loop in the configured mode\nuv run polybot doctor        # health check: gamma, clob, clob-ws, RTDS, storage, live env, telegram\nuv run polybot healthcheck   # Docker-safe local heartbeat check; exits 0 when fresh, 1 otherwise\nuv run polybot show-config   # print every effective setting with its env name (secrets masked)\nuv run polybot export        # export all stored trades as CSV to stdout\n```\n\n`doctor` exits non-zero if any check fails, so it is safe to use as a pre-flight gate in CI or\ndeploy scripts. Run it before switching to live mode.\n\n`healthcheck` is intentionally smaller than `doctor`: it only reads the local heartbeat file that\nthe running bot updates in `POLYBOT_STORAGE_DATA_DIR`, including the last local CLOB WebSocket\nstate. It does not call Polymarket, Binance, Chainlink, or Telegram, so transient third-party\noutages do not restart the container.\n\n## Operational notes\n\n- **Live rollout**: keep live mode off until paper metrics look stable.\n- **Storage data directory**: `POLYBOT_STORAGE_DATA_DIR` is created automatically when the parent\n  path is writable. The bot stores `polybot.sqlite3` and `polybot.health.json` inside it, so Docker\n  deployments should mount a writable volume and set `POLYBOT_STORAGE_DATA_DIR` to that mount path.\n- **Live wallet setup**: new Polymarket accounts commonly use the `POLY_1271` / deposit-wallet\n  flow. In live mode, `POLYBOT_LIVE_WALLET` must be the CLOB funder wallet for the configured private\n  key, and `POLYBOT_LIVE_SIGNATURE_TYPE` must match that wallet type. For the current deposit-wallet\n  flow this is usually `POLYBOT_LIVE_SIGNATURE_TYPE=3`.\n- **pUSD balance and allowances**: `doctor` checks CLOB-reported pUSD balance and spender\n  allowances. If it reports `clob-live: balance/allowance insufficient`, the bot cannot trade from\n  the configured wallet yet. Fix the private-key/wallet/signature-type combination first, then\n  approve/sync pUSD allowances before running live.\n- **CLOB API key creation warning**: the client may print `Could not create api key` while deriving\n  an existing key. If subsequent CLOB calls work and `doctor` passes, that line is not a blocker.\n- **Probability calibration warm-up**: until SQLite has at least\n  `POLYBOT_PROBABILITY_CALIBRATION_MIN_SAMPLES` settled trades (default 30), the calibrator is a\n  no-op and probabilities come straight from the heuristic. Expect win rate to be noisy for the\n  first ~30 settled trades in the current mode.\n- **Chainlink RTDS session recycle**: the Polymarket RTDS websocket forces a disconnect after about\n  120 minutes. The bot pre-emptively recycles the connection at\n  `POLYBOT_CHAINLINK_MAX_SESSION_SECONDS` (default 105 min), but only at a moment at least\n  `POLYBOT_CHAINLINK_RECONNECT_SAFE_DISTANCE_SECONDS` (default 30 s) away from any 5-minute close,\n  so the recycle never lands on a settlement boundary. If RTDS ticks become stale, the bot logs the\n  stale/recovery cycle and reconnects the websocket. Telegram is only notified when the stale\n  episode lasts at least\n  `POLYBOT_CHAINLINK_TELEGRAM_STALE_SECONDS` (default 120 s; `0` disables RTDS Telegram alerts).\n  Entries also pause for a short recovery cooldown after a stale episode so the first fresh tick\n  after reconnect is not treated as an immediately stable feed.\n- **CLOB WebSocket cache**: the hot path uses the public market-channel websocket for active token\n  books. If the cache is empty or stale, the bot falls back to REST when enabled; stale quotes never\n  become tradable entries. `doctor` and `healthcheck` report whether the stream is started,\n  connected, subscribed, and receiving fresh book messages.\n- **Settlement source**: the bot prefers Polymarket's official result and uses its own close tick\n  if the official one is not available yet. If neither is usable at close, settlement remains\n  pending and is retried on later cycles. Stored trades carry the `settlement_source` and\n  settlement-line context so you can tell which path resolved each trade.\n- **State retention**: in-memory caches and slug sets are pruned to the last\n  `POLYBOT_STATE_RETENTION_WINDOWS` windows, so a long-running process does not grow forever.\n  SQLite history is unbounded.\n- **Migrations and backup**: storage applies migrations on startup via `yoyo`. By default a\n  timestamped `*.bak-...` is created next to the SQLite file before any migration is applied;\n  disable with `POLYBOT_STORAGE_BACKUP_BEFORE_MIGRATION=false`.\n- **Stop and resume**: `Ctrl-C` requests a graceful stop, finishes the current cycle, prints the\n  run summary, and exits with code 130. Restarting the process re-reads recent trades from SQLite\n  to reseed risk drawdown and calibration from the current mode.\n- **Telegram visibility**: when Telegram is configured, the bot sends startup, entries, results,\n  actionable runtime alerts, and a periodic run summary. Short RTDS stale/recovered cycles stay in\n  logs by default. Set `POLYBOT_TELEGRAM_SUMMARY_INTERVAL_SECONDS=0` to disable the periodic\n  summary.\n\n### Snapshot one-line log key\n\nEach in-window iteration prints a compact line per market. Reading it left to right:\n\n```text\nETH 47s Down@0.515 U:0.020 D:0.515 px:cl:2313.29 beat:2315.20 o:cl q:ws d:0.0824% p:93.2% be:53.3% e:+39.9% age:120ms qage:80ms s:0.42 skip: ...\n```\n\n| Token             | Meaning                                                         |\n| ----------------- | --------------------------------------------------------------- |\n| `ETH 47s`         | asset and seconds left in the close window                      |\n| `Down@0.515`      | Polymarket side considered and its current quote                |\n| `U:0.020 D:0.515` | Up/Down market quotes side by side                              |\n| `px:`             | current price source: `cl` chainlink, `--` none                 |\n| `beat:`           | settlement line (window open price)                             |\n| `o:`              | window-open source: `cl` chainlink, `--` missing                |\n| `q:`              | execution quote source: `ws`, `clob`, or `--` none              |\n| `d:`              | absolute move from window open in percent                       |\n| `p:`              | model probability                                               |\n| `be:`             | fee-adjusted breakeven probability                              |\n| `e:`              | edge = probability - breakeven                                  |\n| `age:`            | current-price source age in milliseconds                        |\n| `qage:`           | execution quote age or REST quote latency in milliseconds       |\n| `s:`              | compact signal-strength score for logging and sizing context    |\n| trailing tag      | `enter`, `waiting-entry`, `monitor/no-dir: ...`, or `skip: ...` |\n\nSet `POLYBOT_LOG_FORMAT=json` to emit one JSON object per log event instead of Rich text. The same\nsnapshot data is kept as structured fields, for example `crypto`, `seconds_left`, `pm_side`,\n`pm_price`, `up_price`, `down_price`, `current_price`, `window_open`, `quote_source`,\n`delta_pct`, `confidence`, `breakeven`, `edge`, `source_age_ms`, `quote_age_ms`, and\n`signal_strength`. Log source and severity are structured as `component` and `level`; plain mode\nrenders them as readable prefixes. Telegram still receives only event notifications, not\ndebug/snapshot noise.\n\n## Configuration\n\nAll runtime settings are environment variables with the `POLYBOT_` prefix. `.env` is loaded\nautomatically, and `.env.example` contains every available setting with its default or effective\ndefault value.\n\nUse `uv run polybot show-config` to see the parsed values. Non-empty secrets are masked.\n\nTrade export is intentionally CLI-only instead of env-driven:\n\n```bash\nuv run polybot export\nuv run polybot export --output-file exports/polybot-trades.csv\nuv run polybot export --since 2026-05-08T00:00:00Z\nuv run polybot export --current-run\nuv run polybot export --format summary\n```\n\n`export` reads SQLite in read-only mode and never applies migrations or creates the database. CSV\nrows include the executable quote context used at entry (`quote_source`, `quote_age_ms`, best\nbid/ask, book imbalance, and levels used). Missing, damaged, and incompatible databases fail with\nexplicit errors.\n\n## Development\n\n```bash\nmake install-deps\nmake lint\nmake check-types\nmake test\nmake check\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhu553in%2Fpolybot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhu553in%2Fpolybot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhu553in%2Fpolybot/lists"}