[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81326":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":15,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":9,"pushedAt":9,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":14,"starSnapshotCount":14,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},81326,"binance-smart-money-tracker","0xBennie\u002Fbinance-smart-money-tracker","0xBennie","Production-grade Binance Smart Signal tracker. 17 whale fields incl. longWhalesAvgEntryPrice + profitTraders that public fapi can't give you. 7-layer 418\u002F429 defense.",null,"TypeScript",53,13,43,0,1,10,44.94,"MIT License",false,"main",true,[],"2026-06-12 04:01:32","# binance-smart-money-tracker\n\nProduction-grade scraper for **Binance Smart Signal** (the \"Smart Money\" tab on\nbinance.com Futures) — pulls the full 17-field whale overview that the public\n`fapi` API does **not** expose, with a 7-layer defense against `418 \u002F 429 \u002F 403`\nrate-limit bans.\n\nThis is the URL that `binance.com\u002Fzh-CN\u002Fsmart-money\u002Fsignal\u002F\u003Csymbol>` calls\nbehind the scenes:\n\n```\nhttps:\u002F\u002Fwww.binance.com\u002Fbapi\u002Ffutures\u002Fv1\u002Fpublic\u002Ffuture\u002Fsmart-money\u002Fsignal\u002Foverview?symbol=BTCUSDT\n```\n\nNo API key required. No proxy required (works directly from most VPS regions).\nBut Binance enforces an undocumented per-IP weight budget, and a single careless\nburst can cost you a 4-hour `Retry-After`. This repo solves that.\n\n---\n\n## What you get vs. public fapi\n\n| Field | Public `fapi\u002Fdata` | This repo |\n|---|---|---|\n| `longShortRatio` | ✅ via `topLongShortPositionRatio` | ✅ |\n| Top 20% account\u002Fposition long-short ratios | ✅ | ✅ (bonus: also pulled) |\n| Taker buy\u002Fsell ratio | ✅ | ✅ (bonus: also pulled) |\n| Total Open Interest (USD) + 5m\u002F15m\u002F1h\u002F4h velocity | ✅ | ✅ (bonus: also pulled) |\n| **`longWhalesAvgEntryPrice` \u002F `shortWhalesAvgEntryPrice`** | ❌ | ✅ |\n| **`longProfitTraders` \u002F `shortProfitTraders`** (in-profit count) | ❌ | ✅ |\n| **`longProfitWhales` \u002F `shortProfitWhales`** | ❌ | ✅ |\n| **Smart Money's share of total market OI** (derived) | ❌ | ✅ |\n\nThe four ★ fields are what makes Smart Signal useful — they tell you not just\n*which side has more positions*, but *which side is actually making money right\nnow*, and at what average entry. Public `fapi` can't tell you any of that.\n\n### Example interpretation\n\n```\nSymbol            Long Profit%   Short Profit%   Whale Avg L\u002FS    Verdict\n1000RATSUSDT      5%             92%             0.034 \u002F 0.042    🔴 shorts winning big (price has dropped)\n1000LUNCUSDT      71%            41%             0.085 \u002F 0.092    🟢 longs winning big (price has run)\n```\n\nWhen `Short Whale Avg Entry > Long Whale Avg Entry` by >5%, it usually means\nshorts entered too late and are about to get squeezed.\n\n---\n\n## Architecture\n\n```\n┌─────────────────┐         ┌──────────────────────────────┐\n│ smart-money-tick│ cron 60m├──► binance bapi smart-money  │\n└────────┬────────┘         └──────────────────────────────┘\n         │                                │\n         │ writes ob_smart_money_snapshots│\n         ▼                                ▼\n┌─────────────────────────────────────────────┐\n│           sqlite (data\u002Fsnapshots.db)         │\n│   ob_smart_money_snapshots (21 columns)      │\n│   ob_top_trader_snapshots  (12 columns)      │\n└────────────────────┬─────────────────────────┘\n                     │ read-only\n                     ▼\n            ┌──────────────────┐\n            │ Express dashboard │   http:\u002F\u002Fyour-host:3001\u002F\n            │ + JSON API        │\n            └──────────────────┘\n\n┌─────────────────┐         ┌──────────────────────────────┐\n│ top-trader-tick │ cron 30m├──► binance fapi\u002Ffutures\u002Fdata │\n└─────────────────┘         └──────────────────────────────┘\n```\n\n- **One sqlite file**, two tables, 30-day retention\n- **One Express dashboard** with server-side rendering (no JS framework)\n- **Two cron entry points** (smart-money 60min, top-trader 30min) — staggered\n- **Library mode**: `import { getSmartMoneyOverview } from 'binance-smart-money-tracker'`\n\n---\n\n## 7 layers of 418\u002F429 protection\n\nThe Smart Signal endpoint lives on Binance's web `bapi` gateway, which is more\naggressive than `fapi`. A single uncoordinated burst can earn a **3.85-hour\nRetry-After** (verified empirically). All seven layers below are wired up\nby default:\n\n1. **Real `Retry-After` parsing** — uses the exact seconds Binance returns,\n   not a guess. `parseInt(response.headers['retry-after'])`.\n2. **Weight budget tracker** — reads `X-MBX-USED-WEIGHT-1M` from every fapi\n   response; when utilization > 70%, the next call sleeps to the next minute\n   window before firing.\n3. **Pre-flight ping** — every cron entry pings `\u002Ffapi\u002Fv1\u002Fping` once before\n   the batch; on 418\u002F403 it aborts immediately, no further requests fired.\n4. **Jittered spacing** — smart-money batches use 12s ± 3s, top-trader uses\n   1s ± 200ms. Avoids forming a predictable cadence that WAFs flag.\n5. **Exponential backoff** — consecutive soft hits within 1 hour escalate\n   the cooldown 5min → 15min → 60min.\n6. **Process-wide circuit breaker** — `isBinanceApiBlocked()` short-circuits\n   *all* downstream calls in the same process; `getSmartMoneyOverview()` and\n   `getTopTraderSnapshot()` return cached or null without firing.\n7. **Memory cache** — 10min for smart-money, 5min for top-trader. Repeated\n   calls to the same symbol within the window don't hit Binance at all.\n\nThere is **no retry-on-failure path that ignores `Retry-After`**. That is\nintentional. The single fastest way to escalate a 5-minute soft block into a\nmulti-hour hard block is to retry-loop a 418 — don't.\n\n---\n\n## Quick start\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002F0xBennie\u002Fbinance-smart-money-tracker.git\ncd binance-smart-money-tracker\nnpm install\n\n# 1. One-shot pull (writes to data\u002Fsnapshots.db)\nnpx tsx src\u002Fscripts\u002Fsmart-money-tick.ts\n\n# 2. Start the dashboard (reads from the same db)\nPORT=3001 npx tsx src\u002Fscripts\u002Fsmart-money-dashboard.ts\n# → http:\u002F\u002Flocalhost:3001\u002F\n\n# 3. Optional: also pull top-trader supplement (Taker ratio + 5min LSR)\nnpx tsx src\u002Fscripts\u002Ftop-trader-tick.ts\n```\n\n### Env vars\n\n| Var | Default | What |\n|---|---|---|\n| `SMART_MONEY_POOL_MAX` | `0` | Cap of symbols. **0 = all USDT-PERPETUAL** (~500). Set to e.g. `100` to limit |\n| `SMART_MONEY_SHARD_INDEX` | `0` | 0-based shard index when sharding (see below) |\n| `SMART_MONEY_SHARD_TOTAL` | `1` | Total shards. `1` = no sharding |\n| `TOP_TRADER_POOL_MAX` \u002F `_SHARD_INDEX` \u002F `_SHARD_TOTAL` | same | Same semantics for top-trader cron |\n| `OI_POOL_MAX` \u002F `_SHARD_INDEX` \u002F `_SHARD_TOTAL` | same | Same for open-interest cron |\n| `SMART_MONEY_DASHBOARD_PORT` \u002F `PORT` | `3001` | Dashboard listen port |\n\n### As a library\n\n```ts\nimport {\n  getSmartMoneyOverview,\n  getTopTraderSnapshot,\n  getOpenInterest,\n  smartMoneyNotionalUsd,\n  smartMoneyShareOfOI,\n} from 'binance-smart-money-tracker';\n\nconst sym = 'BTCUSDT';\nconst [sm, tt, oi] = await Promise.all([\n  getSmartMoneyOverview(sym),         \u002F\u002F 17 whale fields\n  getTopTraderSnapshot(sym, '5m'),    \u002F\u002F top-account\u002Fposition LSR + Taker BSR\n  getOpenInterest(sym),               \u002F\u002F total market OI + 5m\u002F15m\u002F1h\u002F4h velocity\n]);\n\nif (sm && oi) {\n  console.log(`${sm.longWhales} long whales @ avg ${sm.longWhalesAvgEntryPrice}`);\n  console.log(`${sm.longProfitTraders}\u002F${sm.longTraders} longs in profit`);\n  console.log(`Total OI: $${(oi.oiNowUsd \u002F 1e6).toFixed(2)}M, 4h chg ${oi.oiChg4h.toFixed(2)}%`);\n\n  \u002F\u002F Smart Money USD notional, derived from qty × avg-entry (NOT from the\n  \u002F\u002F undocumented `totalPositions` field whose unit is inconsistent).\n  const smUsd = smartMoneyNotionalUsd(sm);\n  const share = smartMoneyShareOfOI(sm, oi.oiNowUsd);\n  console.log(`Smart Money notional: $${(smUsd \u002F 1e6).toFixed(2)}M`);\n  console.log(`Smart Money share of total OI: ${share == null ? 'n\u002Fa' : (share * 100).toFixed(1) + '%'}`);\n}\n```\n\n> **Why a helper?** Binance's undocumented `totalPositions` field has\n> inconsistent units across symbols (sometimes base-coin units, sometimes USD).\n> `smartMoneyNotionalUsd(sm)` computes it deterministically from\n> `longTradersQty × longTradersAvgEntryPrice + shortTradersQty × shortTradersAvgEntryPrice`\n> — both fields have known units (base-coin × USD = USD). Don't divide\n> `totalPositions` by anything; use the helper.\n\nThe library re-exports all rate-limit helpers\n(`isBinanceApiBlocked`, `preflightBinanceFapi`, `waitForBinanceWeightHeadroom`)\nso you can integrate the same circuit breaker into your other Binance calls\nand share one weight budget across modules.\n\n---\n\n## Pool sizing & cron cadence\n\nDefault behavior is **all USDT-PERPETUAL symbols** (~500 contracts as of 2026).\nPick a deployment mode that matches your tolerance for data freshness:\n\n| Mode | Symbols | smart-money cron | top-trader cron | OI cron | Sharding |\n|---|---|---|---|---|---|\n| **Light** | 100 cap | `7 * * * *` (1×\u002Fh) | `*\u002F30 * * * *` | `15,45 * * * *` | None |\n| **Standard** | 200 cap | `7 * * * *` (1×\u002Fh) | `*\u002F30 * * * *` | `15,45 * * * *` | None |\n| **Full, 2h refresh** | ~500 all | `0 *\u002F2 * * *` (1×\u002F2h) | `*\u002F30 * * * *` | `15,45 * * * *` | None |\n| **Full, 1h refresh** | ~500 all | `7,37 * * * *` (2×\u002Fh, each does half) | `*\u002F30 * * * *` | `15,45 * * * *` | **2 shards** |\n\nRead \"1h refresh\" as **every symbol gets a fresh snapshot within 1h**, achieved\nby two cron entries at `:07` and `:37` each pulling half (shard 0\u002F2 and 1\u002F2).\n\nThe math: smart-money runs at 12s ± 3s spacing (web bapi is rate-sensitive).\n500 symbols ≈ 100 min, so it cannot finish inside an hour without sharding.\nTop-trader and OI both use fapi\u002Fdata at 1s spacing — 500 symbols ≈ 8 min,\nfits anywhere.\n\n### Sharding\n\nSymbols are split deterministically by `index % SHARD_TOTAL == SHARD_INDEX`,\nso each shard always pulls the same set (good for cache locality, and means\nshards don't collide on the same symbol within a window).\n\n### Data Retention\n\nThe sqlite tables (`ob_smart_money_snapshots`, `ob_top_trader_snapshots`,\n`ob_oi_snapshots`) are pruned to **30 days** by the `storage.cleanup()` call\nthat runs at the end of every `smart-money-tick` execution. If you need\nlonger history, increase `RETENTION_DAYS` in `src\u002Fstorage.ts` and rebuild,\nor back the table up before the daily cron runs.\n\nDisk usage estimate at default cadence (500 symbols, hourly smart-money +\n30min top-trader + 30min OI): roughly **30–80 MB \u002F month** with WAL enabled.\n\n## Production deployment (pm2)\n\n### A. Standard — cap at 200, hourly\n\n```js\n\u002F\u002F ecosystem.config.js\nmodule.exports = {\n  apps: [\n    {\n      name: 'smart-money-tick',\n      script: 'node_modules\u002F.bin\u002Ftsx',\n      args: 'src\u002Fscripts\u002Fsmart-money-tick.ts',\n      cron_restart: '7 * * * *',        \u002F\u002F :07 every hour\n      autorestart: false,\n      env: { SMART_MONEY_POOL_MAX: '200' },\n    },\n    {\n      name: 'top-trader-tick',\n      script: 'node_modules\u002F.bin\u002Ftsx',\n      args: 'src\u002Fscripts\u002Ftop-trader-tick.ts 5m',\n      cron_restart: '*\u002F30 * * * *',\n      autorestart: false,\n    },\n    {\n      name: 'oi-tick',\n      script: 'node_modules\u002F.bin\u002Ftsx',\n      args: 'src\u002Fscripts\u002Foi-tick.ts',\n      cron_restart: '15,45 * * * *',    \u002F\u002F offset from top-trader\n      autorestart: false,\n    },\n    {\n      name: 'smart-money-dashboard',\n      script: 'node_modules\u002F.bin\u002Ftsx',\n      args: 'src\u002Fscripts\u002Fsmart-money-dashboard.ts',\n      autorestart: true,\n      env: { PORT: '3001' },\n    },\n  ],\n};\n```\n\n### B. Full coverage with 1h refresh — 2-way sharding\n\nTwo pm2 entries, each pulls half the symbols at staggered times:\n\n```js\nmodule.exports = {\n  apps: [\n    {\n      name: 'smart-money-tick-a',\n      script: 'node_modules\u002F.bin\u002Ftsx',\n      args: 'src\u002Fscripts\u002Fsmart-money-tick.ts',\n      cron_restart: '7 * * * *',        \u002F\u002F :07\n      autorestart: false,\n      env: { SMART_MONEY_SHARD_INDEX: '0', SMART_MONEY_SHARD_TOTAL: '2' },\n    },\n    {\n      name: 'smart-money-tick-b',\n      script: 'node_modules\u002F.bin\u002Ftsx',\n      args: 'src\u002Fscripts\u002Fsmart-money-tick.ts',\n      cron_restart: '37 * * * *',       \u002F\u002F :37 — 30 min offset from A\n      autorestart: false,\n      env: { SMART_MONEY_SHARD_INDEX: '1', SMART_MONEY_SHARD_TOTAL: '2' },\n    },\n    \u002F\u002F ... top-trader-tick and dashboard same as Mode A\n  ],\n};\n```\n\n### C. Full coverage, slower refresh — 2-hour cron, no sharding\n\nCheapest option if hourly freshness isn't required:\n\n```js\n{\n  name: 'smart-money-tick',\n  args: 'src\u002Fscripts\u002Fsmart-money-tick.ts',\n  cron_restart: '0 *\u002F2 * * *',          \u002F\u002F every 2 hours\n  autorestart: false,\n  \u002F\u002F no env vars needed — defaults to all symbols\n}\n```\n\n### Why staggering matters\n\nThe circuit breaker lives in per-process module state. Two cron processes\nrunning simultaneously cannot share `isBinanceApiBlocked()` state directly,\nbut each one ping-tests via `preflightBinanceFapi()` before issuing any\ndata requests — so if process A just got a 418, process B's preflight will\ncatch it and abort cleanly. Stagger the times anyway to give the IP weight\nwindow time to drain between bursts.\n\n---\n\n## What's *not* in this repo\n\n- ❌ No trading. This is data only.\n- ❌ No proxy. If your IP gets a hard 403 (CloudFront WAF), the only fix is\n  to wait it out or change IP. The whole point of the protection layers is\n  to never get there.\n- ❌ No on-chain data, no order book, no aggregated trades. For that, see\n  the projects in *Credits*.\n\n---\n\n## Credits\n\n- **[andychien555\u002Fbinance-smart-money-tracker](https:\u002F\u002Fgithub.com\u002Fandychien555\u002Fbinance-smart-money-tracker)**\n  — original reverse-engineering of the `bapi\u002Ffutures\u002Fv1\u002Fpublic\u002Ffuture\u002Fsmart-money\u002Fsignal\u002Foverview`\n  endpoint. Their version is built on Cloudflare Workers + R2 with a static SPA\n  frontend; this repo is the Node + sqlite + express version with stronger\n  rate-limit protection. Different architecture, same source insight.\n- **[y18929284608-byte\u002FBNSmartMoneyMonitor](https:\u002F\u002Fgithub.com\u002Fy18929284608-byte\u002FBNSmartMoneyMonitor)**\n  and **[6551Team\u002Fopentrade](https:\u002F\u002Fgithub.com\u002F6551Team\u002Fopentrade)** —\n  parallel implementations that confirmed the endpoint contract.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","该项目是一个生产级的Binance智能信号追踪器，能够获取包括长鲸平均入场价和盈利交易者在内的17个关键字段信息，这些是公共`fapi` API无法提供的。采用TypeScript编写，并具备七层防御机制来应对418\u002F429等限流封禁。特别适合需要深入分析Binance期货市场中大额资金动向及盈利情况的专业投资者或机构使用，无需API密钥或代理服务器即可直接运行。通过提供更全面的数据支持，帮助用户更好地理解当前市场情绪与趋势，从而做出更加明智的投资决策。",2,"2026-06-11 04:04:39","CREATED_QUERY"]