← Log
2026-07-10Thinking

Why CryptoScore weights are a product decision, not an engineering one

ArchitectureProduct4 min read

CryptoScore is our composite token rating — a single number that combines on-chain metrics, market value dynamics, and momentum signals. It sounds like an engineering problem. It's not.

The formula today: OnChain (40%) + Value (30%) + Momentum (30%). When on-chain data is missing for a chain, the remaining two components reweight to 50/50. These weights determine which tokens surface to users, which get flagged as anomalies, and which disappear from the discovery feed. Changing a weight is a product decision that directly affects what users see.

The engineering challenge is less about the math and more about the architecture. compute_crypto_score() is a single function with hardcoded positional float arguments. There's no signal registry — adding a new signal means editing the function signature, adding a parameter, rebalancing all existing weights, and remembering to update both call sites (single-token endpoint AND leaderboard endpoint) independently. They duplicated the branching logic, and nothing enforces that the two stay in sync.

The same pattern applies to on-chain metrics: no plugin system, no base class. Each metric gets its own hand-written Python module with a fetch() function, then gets manually wired into the scheduler pipeline via copy-paste if-blocks. It works — we have 17 chains running — but adding a new chain means editing three separate files in the right order.

The honest fix would be a signal registry with a plugin interface. But the real constraint is that every weight change needs a product conversation first. Until the formula stabilises, the brittle architecture is the right tradeoff — it's easier to change a hardcoded function than a plugin system, and the weights are changing quarterly.

Build something they'll remember.

YS.yogeshsahu.xyz