CleanedVaultPriceRow

Documentation for eth_defi.research.wrangle_vault_prices.CleanedVaultPriceRow Python class.

class CleanedVaultPriceRow

Bases: TypedDict

Schema for a single row in the cleaned vault price DataFrame.

This is the enriched format produced by the cleaning pipeline in this module and consumed by calculate_lifetime_metrics().

It extends RawVaultPriceRow with denormalised metadata columns (id, name, event_count, protocol) and computed columns (returns_1h). The DataFrame uses a DatetimeIndex built from the timestamp column.

Columns are grouped by availability:

  • General columns are present for all vault protocols.

  • ERC-4626 only columns come from on-chain ERC-4626 calls and are NaN / empty for native protocols.

  • Lending only columns are populated for lending protocol vaults (IPOR, Euler, Morpho, Gearbox, etc.) and NaN for others.

  • Hypercore only columns come from the Hyperliquid native vault API and are NaN for all other protocols.

  • Native protocol flow columns are populated for native protocols that provide daily deposit/withdrawal data (Hypercore, GRVT, Lighter, Hibachi) and NaN for ERC-4626 vaults.

Attributes summary

chain

EVM chain id (e.g.

address

Vault contract address, lowercase.

block_number

Block number of the on-chain read.

timestamp

Naive UTC timestamp (also used as the DatetimeIndex).

share_price

Share price in denomination token units.

total_assets

Total assets under management (TVL) in denomination token units.

total_supply

Total supply of vault share tokens.

performance_fee

Performance fee at time of read (e.g.

management_fee

Management fee at time of read (e.g.

errors

Comma-separated RPC error messages, or empty string if no errors.

vault_poll_frequency

Dynamic poll frequency used when taking this sample.

id

Vault identifier string: "<chain_id>-<address>".

name

Human-readable vault name (unique within the dataset).

event_count

Total deposit + redeem events observed for this vault.

protocol

Protocol name (e.g.

returns_1h

Hourly return as pct_change() of share_price within each vault group.

max_deposit

Maximum deposit amount allowed (ERC-4626 maxDeposit).

max_redeem

Maximum redeem amount allowed (ERC-4626 maxRedeem).

deposits_open

Whether deposits were open: "true", "false", or "".

redemption_open

Whether redemptions were open: "true", "false", or "".

trading

Whether the vault was actively trading: "true", "false", or "".

available_liquidity

Available liquidity for immediate withdrawal in denomination token units.

utilisation

Utilisation ratio (0.0–1.0) for lending vaults.

deposit_closed_reason

Unified reason why deposits are closed (e.g.

written_at

When this price row was actually written/fetched (naive UTC).

vault_settlement_at

Latest asynchronous vault settlement timestamp in the interval ending at this price row.

leader_fraction

Fraction of vault assets controlled by the leader (0.0–1.0).

leader_commission

Commission rate charged by the vault leader (0.0–1.0).

follower_count

Number of followers in the vault.

account_pnl

Cumulative PnL of the vault leader account in USD.

cumulative_volume

Cumulative trading volume of the vault in USD.

hypercore_source

Hypercore scanner source: "daily" or "hf".

epoch_reset

The row starts a new performance epoch after a complete wipe-out.

hypercore_repair_status

Provenance of the cleaned Hypercore PnL/NAV approximation.

daily_deposit_count

Number of deposit events in the latest day.

daily_withdrawal_count

Number of withdrawal events in the latest day.

daily_deposit_usd

Total USD deposited in the latest day.

daily_withdrawal_usd

Total USD withdrawn in the latest day.

Methods summary

__init__(*args, **kwargs)

clear()

Remove all items from the dict.

copy()

Return a shallow copy of the dict.

fromkeys([value])

Create a new dictionary with keys from iterable and values set to value.

get(key[, default])

Return the value for key if key is in the dictionary, else default.

items()

Return a set-like object providing a view on the dict's items.

keys()

Return a set-like object providing a view on the dict's keys.

pop(k[,d])

If the key is not found, return the default if given; otherwise, raise a KeyError.

popitem()

Remove and return a (key, value) pair as a 2-tuple.

setdefault(key[, default])

Insert key with a value of default if key is not in the dictionary.

update([E, ]**F)

If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values()

Return an object providing a view on the dict's values.

chain: int

EVM chain id (e.g. 1 for Ethereum, 8453 for Base).

Native (non-EVM) protocols use synthetic in-house chain ids:

The full mapping lives in CHAIN_NAMES.

General — present for all protocols.

address: str

Vault contract address, lowercase.

Address formats vary by protocol:

  • EVM vaults: 0x-prefixed hex (e.g. "0xabcd...")

  • Hypercore: 0x-prefixed hex (Hyperliquid vault addresses)

  • GRVT: platform-specific id (e.g. "vlt:xxx")

  • Lighter: synthetic id (e.g. "lighter-pool-281474976710654")

  • Hibachi: synthetic id (e.g. "hibachi-vault-2")

See is_good_multichain_address() for the validation function that accepts all these formats.

General — present for all protocols.

block_number: int

Block number of the on-chain read. For native protocols without blocks this is a synthetic sequence number.

General — present for all protocols.

timestamp: pandas.Timestamp

Naive UTC timestamp (also used as the DatetimeIndex).

General — present for all protocols.

share_price: float

Share price in denomination token units.

For ERC-4626 vaults this is read directly from the contract (convertToAssets(1e decimals)). GRVT, Lighter, and Hibachi provide native share prices from their respective APIs. Hypercore (native Hyperliquid vaults) does not expose a historical share price or supply. Its cleaned value is a PnL/NAV economic-performance index starting at 1.0 for each retained capital epoch. The scanner’s synthetic input remains available in raw_share_price.

General — present for all protocols.

total_assets: float

Total assets under management (TVL) in denomination token units.

General — present for all protocols.

total_supply: float

Total supply of vault share tokens. Hypercore has no exposed historical token supply; its value is synthetic index units calculated as total_assets / share_price and must not be interpreted as an on-chain share count.

General — present for all protocols.

performance_fee: float

Performance fee at time of read (e.g. 0.20 = 20%). NaN if unknown.

General — present for all protocols.

management_fee: float

Management fee at time of read (e.g. 0.02 = 2%). NaN if unknown.

General — present for all protocols.

errors: str

Comma-separated RPC error messages, or empty string if no errors.

Example values: "total_supply call failed", "total_assets zero: 0", "total_supply call missing". Always empty for native protocols.

General — present for all protocols (always empty for native protocols).

vault_poll_frequency: str

Dynamic poll frequency used when taking this sample. Empty string if not set.

Example values: "1h", "4h", "24h". The scanner adjusts frequency based on vault TVL and activity; low-TVL vaults may be polled less frequently.

General — present for all protocols (may be empty for native protocols).

id: str

Vault identifier string: "<chain_id>-<address>".

General — present for all protocols.

name: str

Human-readable vault name (unique within the dataset).

General — present for all protocols.

event_count: int

Total deposit + redeem events observed for this vault.

Zero if the protocol does not support on-chain deposit/redeem event tracking (e.g. native vaults like GRVT, Lighter, Hibachi).

General — present for all protocols.

protocol: str

Protocol name (e.g. "Morpho", "Yearn", "Hyperliquid").

General — present for all protocols.

returns_1h: float

Hourly return as pct_change() of share_price within each vault group. Despite the name, for native protocols (Hypercore, GRVT, Lighter) the interval may be daily or irregular — the column name is kept for backward compatibility.

General — present for all protocols.

max_deposit: float

Maximum deposit amount allowed (ERC-4626 maxDeposit). NaN if unknown.

ERC-4626 only — NaN for native protocols.

max_redeem: float

Maximum redeem amount allowed (ERC-4626 maxRedeem). NaN if unknown.

ERC-4626 only — NaN for native protocols.

deposits_open: str

Whether deposits were open: "true", "false", or "".

ERC-4626 only — empty for native protocols.

redemption_open: str

Whether redemptions were open: "true", "false", or "".

ERC-4626 only — empty for native protocols.

trading: str

Whether the vault was actively trading: "true", "false", or "". Currently only supported for D2 Finance vaults.

Protocol-specific — empty for most protocols.

available_liquidity: float

Available liquidity for immediate withdrawal in denomination token units. NaN if not applicable.

Lending only — IPOR, Euler, Morpho, Gearbox, etc. NaN for other protocols.

utilisation: float

Utilisation ratio (0.0–1.0) for lending vaults. NaN if not applicable.

Warning

This metric measures capital deployment efficiency (how much of the vault’s AUM is lent out), not redeemable liquidity. For single-market vaults (Euler EVK, Gearbox, Silo) high utilisation does mean low available liquidity. For multi-market aggregators (Morpho, Euler Earn, IPOR) a vault can show 95% utilisation yet have substantial instantly redeemable liquidity in low-utilisation underlying markets. See README-vault-redeemable.md and README-utilisation.md in eth_defi.erc_4626.vault_protocol for details.

Lending only — IPOR, Euler, Morpho, Gearbox, etc. NaN for other protocols.

deposit_closed_reason: str

Unified reason why deposits are closed (e.g. "Vault deposits disabled"). Empty string if deposits are open. Derived from deposits_open for ERC-4626 vaults or set directly by native protocol exporters.

General — present for all protocols (empty when deposits are open).

written_at: pandas.Timestamp

When this price row was actually written/fetched (naive UTC). NaT for old data.

General — present for all protocols.

vault_settlement_at: pandas.Timestamp

Latest asynchronous vault settlement timestamp in the interval ending at this price row.

General — populated by merging vault-settlements.duckdb after cleaning. NaT means no known settlement occurred since the previous cleaned price row.

leader_fraction: float

Fraction of vault assets controlled by the leader (0.0–1.0).

Hypercore only — NaN for all other protocols.

leader_commission: float

Commission rate charged by the vault leader (0.0–1.0).

Hypercore only — NaN for all other protocols.

follower_count: float

Number of followers in the vault.

Hypercore only — NaN for all other protocols.

account_pnl: float

Cumulative PnL of the vault leader account in USD.

Hypercore only — NaN for all other protocols.

cumulative_volume: float

Cumulative trading volume of the vault in USD.

Hypercore only — NaN for all other protocols.

hypercore_source: str

Hypercore scanner source: "daily" or "hf".

Used during wrangling to reconcile overlapping synthetic share prices. Hypercore only — NaN for all other protocols.

epoch_reset: bool

The row starts a new performance epoch after a complete wipe-out.

Hypercore only — false for ordinary observations.

hypercore_repair_status: str

Provenance of the cleaned Hypercore PnL/NAV approximation.

approximated_pnl_nav marks a four-hour economic checkpoint, approximated_pnl_nav_clipped a positive checkpoint capped at 100%, approximated_pnl_nav_lag_repaired a gain whose NAV confirmation arrived within the bounded confirmation window, approximated_pnl_nav_wipe_out a terminal NAV-corroborated loss, and approximated_pnl_nav_carried a row that adds no performance, either because it is not the selected checkpoint for its four-hour UTC bucket, because its PnL awaits NAV confirmation, or because the epoch is already at zero after a terminal loss. A later NAV confirmation can revise the recent provisional PnL-only checkpoint and subsequently compounded prices. deferred_pnl_nav means inputs were missing and deferred_pnl_nav_outlier means an uncorroborated negative PnL step was not allowed to zero a funded vault. Hypercore only — empty for ordinary observations and other protocols.

daily_deposit_count: float

Number of deposit events in the latest day.

Native protocol flow — Hypercore, GRVT, Lighter, Hibachi. NaN for ERC-4626 vaults.

daily_withdrawal_count: float

Number of withdrawal events in the latest day.

Native protocol flow — Hypercore, GRVT, Lighter, Hibachi. NaN for ERC-4626 vaults.

daily_deposit_usd: float

Total USD deposited in the latest day.

Native protocol flow — Hypercore, GRVT, Lighter, Hibachi. NaN for ERC-4626 vaults.

daily_withdrawal_usd: float

Total USD withdrawn in the latest day.

Native protocol flow — Hypercore, GRVT, Lighter, Hibachi. NaN for ERC-4626 vaults.

__init__(*args, **kwargs)
__new__(**kwargs)
clear()

Remove all items from the dict.

copy()

Return a shallow copy of the dict.

fromkeys(value=None, /)

Create a new dictionary with keys from iterable and values set to value.

get(key, default=None, /)

Return the value for key if key is in the dictionary, else default.

items()

Return a set-like object providing a view on the dict’s items.

keys()

Return a set-like object providing a view on the dict’s keys.

pop(k[, d]) v, remove specified key and return the corresponding value.

If the key is not found, return the default if given; otherwise, raise a KeyError.

popitem()

Remove and return a (key, value) pair as a 2-tuple.

Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.

setdefault(key, default=None, /)

Insert key with a value of default if key is not in the dictionary.

Return the value for key if key is in the dictionary, else default.

update([E, ]**F) None.  Update D from mapping/iterable E and F.

If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

values()

Return an object providing a view on the dict’s values.