Point-in-time valuation

The canonical statement of why historical portfolio values on this chain are usually wrong.

The arithmetic

Valuing a stock token position at block N requires three terms, and the middle one is time-dependent.

value_at(N) = balanceOf(addr, N)              × uiMultiplier_at(N)     ← everyone skips this              × price_at(N)

Why it is skipped

Because raw balances are static across corporate actions, nothing looks wrong. A provider returns balanceOf(addr, N), multiplies by a current price, and produces a number that is confidently, invisibly incorrect for any instrument that has since split or paid a dividend.

After a 4-for-1 split, applying today's multiplier to a pre-split block overstates the position by exactly four times. The error does not decay; it compounds with each subsequent action.

How we do it

Every historical endpoint requires an as_of block or timestamp and applies the multiplier valid at that point. A historical request without as_of returns 400, not a quietly-current answer. Every response carries the multiplier used and the block it became effective, so you can check our arithmetic.

curl -s https://api.robinhoodrpc.io/v1/accounts/0xabc.../positions \  -H "Authorization: Bearer $RHRPC_KEY" \  -G --data-urlencode "as_of_block=4200000" \  | jq '.positions[] | {      token_symbol, balance_raw, balance_ui,      multiplier_applied, multiplier_effective_block    }'

Correctness

Correctness note

This is testable against any provider. Ask for a wallet's position value at a block preceding a corporate action, then check whether the multiplier applied is the one from that block or from today. It reproduces or it does not.

Related