research.vault_metrics
Documentation for eth_defi.research.vault_metrics Python module.
Vault metrics calculations.
Calculate various performance reports and charts for vaults.
Functions
|
Create charts and tables to analyse a vault performance. |
|
Check for broken vaults by detecting abnormal metric values. |
|
Blacklist Morpho vaults missing from Morpho API. |
|
Takes a returns series and calculates cumulative returns. |
Calculate daily returns for each vault in isolation |
|
Calculate hourly returns for each vault in isolation |
|
|
Calculate lifetime metrics for each vault in the provided DataFrame. |
|
Calculate profit after external fees have been reduced from the share price change. |
|
Convert a cumulative gross return series to a cumulative net return series after fees. |
|
Convert a share price series to net return series after fees. |
Calculate performance metrics for each vault. |
|
|
Calculate metrics for one period. |
|
Calculate returns from resampled share price series. |
|
Calculate annualized Sharpe ratio from hourly returns. |
|
Calculate rankings for all periods inside PeriodMetrics objects. |
|
Process a single vault metadata + prices to calculate its full data. |
|
Clean lifetime data so we have only valid vaults. |
|
Create combined net / (gross) returns column for display. |
|
Create 2% / 20% style labels to display variosu kinds of vault fees. |
|
Check that VaultDatabase has metadata for all price_df vaults and vice versa. |
Render a formatted lifetime table as compact HTML in a Jupyter notebook. |
|
|
Render a chart and tearsheet for a single vault. |
|
Export lifetime metrics row to a fully JSON-serializable dict. |
Display fees to .1 accuracy if there are .1 fractions, otherwise as int. |
|
|
Format FFN report for human readable output. |
Format FFN report as logically grouped sections. |
|
|
Format table for human readable output. |
|
Format vault database for human readable output. |
|
Format vault header for human readable output. |
|
Get PeriodMetrics for a specific period from the results list. |
|
Check if a vault is a special vault that may not have deposit/redeem event data. |
|
Calculate returns from resampled returns series. |
|
Create a slug from protocol name for URLs. |
|
Create a slug from vault metadata for URLs. |
|
Create slugs for a set of vaults. |
|
Replace values with abs(x) < eps by 0. |
Classes
Provenance metadata for the vault metrics JSON export. |
|
Git version stamp of the exporter Docker image. |
|
Deposit and withdrawal flow metrics for a time period. |
|
Tearsheet metrics for one period. |
|
Top-level structure of the vault metrics JSON export. |
|
Per-vault record in the JSON export. |
|
One vault data analysed |
- class ExportMetadata
Bases:
TypedDictProvenance metadata for the vault metrics JSON export.
Identifies which exporter build produced the file so stale deployments are diagnosable from the JSON alone.
- __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.
- class ExportVersionMetadata
Bases:
TypedDictGit version stamp of the exporter Docker image.
Produced by
eth_defi.version_info.VersionInfo.as_dict(). All fields areNonewhen the exporter runs outside a stamped Docker image, e.g. from a source checkout. Individual fields can also beNoneinside a stamped image when the corresponding build ARG was not passed.- __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.
- class NetflowMetrics
Bases:
objectDeposit and withdrawal flow metrics for a time period.
Aggregates daily deposit/withdrawal event counts and USD values over a given period (e.g.
"1d","7d","30d").Only available for chains that support vault flow tracking (currently Hyperliquid). For other chains this will be
Nonein the vault record.
- class PeriodMetrics
Bases:
objectTearsheet metrics for one period.
- __init__(period, error_reason=None, period_start_at=None, period_end_at=None, share_price_start=None, share_price_end=None, raw_samples=0, samples_start_at=None, samples_end_at=None, daily_samples=0, returns_gross=None, returns_net=None, cagr_gross=None, cagr_net=None, volatility=None, sharpe=None, max_drawdown=None, tvl_start=None, tvl_end=None, tvl_low=None, tvl_high=None, ranking_overall=None, ranking_chain=None, ranking_protocol=None, avg_utilisation=None)
- Parameters
period (Literal['1W', '1M', '3M', '6M', '1Y', 'lifetime']) –
period_start_at (Optional[pandas.Timestamp]) –
period_end_at (Optional[pandas.Timestamp]) –
raw_samples (int) –
samples_start_at (Optional[pandas.Timestamp]) –
samples_end_at (Optional[pandas.Timestamp]) –
daily_samples (int) –
- Return type
None
- class VaultMetricsExport
Bases:
TypedDictTop-level structure of the vault metrics JSON export.
Describes the shape of
top_vaults_by_chain.jsonuploaded to R2.- __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.
- class VaultMetricsRecord
Bases:
TypedDictPer-vault record in the JSON export.
Uses
total=Falseso that only the most critical fields are typed explicitly — remaining fields are still present but not enforced by the type checker. This is an incremental approach; more fields can be promoted to required as the schema stabilises.- __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.
- class VaultReport
Bases:
objectOne vault data analysed
- __init__(vault_metadata, rolling_returns_chart, performance_stats, daily_returns, hourly_returns, hourly_df)
- Parameters
vault_metadata (dict) –
rolling_returns_chart (plotly.graph_objs._figure.Figure) –
performance_stats (ffn.core.PerformanceStats) –
daily_returns (pandas.Series) –
hourly_returns (pandas.Series) –
hourly_df (pandas.DataFrame) –
- Return type
None
- analyse_vault(vault_db, prices_df, spec, returns_col='returns_1h', logger=<built-in function print>, chart_frequency='daily')
Create charts and tables to analyse a vault performance.
We plot our annualised 1 month rolling returns on the chart, to see how vaults move in the direction of the markets, or what kind of outliers there are
- Parameters
vault_db (eth_defi.vault.vaultdb.VaultDatabase) – Database of all vault metadata
price_df –
Cleaned price and returns data for all vaults.
Can be be in any time frame.
id – Vault chain + address to analyse, e.g. “1-0x1234567890abcdef1234567890abcdef12345678”
chart_frequency (Literal['hourly', 'daily']) –
Do we plot based on daily or hourly datapoints.
Hourly data has too many points, chocking Plotly.
prices_df (pandas.DataFrame) –
spec (eth_defi.vault.base.VaultSpec) –
returns_col (str) –
- Returns
Analysis report to display.
None if the vault does not have price data.
- Return type
- apply_abnormal_value_checks(risk, notes, flags, current_nav=None, current_share_price=None, three_months_volatility=None)
Check for broken vaults by detecting abnormal metric values.
Automatically blacklists vaults with unrealistic TVL, share price, or volatility. These thresholds catch broken smart contracts and low-TVL vaults that produce meaningless metrics.
Called multiple times as more metrics become available (first with NAV/price, then again after 3M volatility is computed).
- Parameters
risk (eth_defi.vault.risk.VaultTechnicalRisk) – Current risk classification.
notes (str) – Current notes string.
flags (set[eth_defi.vault.flag.VaultFlag]) – Current vault flags set.
current_nav (Optional[float]) – Current TVL in USD. Checked against
MAX_VALID_NAV.current_share_price (Optional[float]) – Current share price. Checked against
MAX_VALID_SHARE_PRICE.three_months_volatility (Optional[float]) – 3-month annualised volatility. Checked against
MAX_VALID_VOLATILITY. Catches low-TVL Hyperliquid vaults with one or few trades that produce extreme volatility numbers.
- Returns
Updated (risk, notes, flags) tuple.
- Return type
tuple[eth_defi.vault.risk.VaultTechnicalRisk, str, set[eth_defi.vault.flag.VaultFlag]]
- apply_morpho_not_in_api_check(risk, notes, flags)
Blacklist Morpho vaults missing from Morpho API.
Dynamic scan flags are not visible to
get_vault_risk(), because that helper only reads the static manual flag table. This helper handles the Morpho-specific dynamic blacklist flag before metrics export.- Parameters
risk (Optional[eth_defi.vault.risk.VaultTechnicalRisk]) – Current risk classification.
notes (Optional[str]) – Current note, if any. Existing notes have priority.
flags (set[eth_defi.vault.flag.VaultFlag]) – Dynamic flags collected during vault scan.
- Returns
Updated risk, notes, and flags.
- Return type
tuple[eth_defi.vault.risk.VaultTechnicalRisk | None, str | None, set[eth_defi.vault.flag.VaultFlag]]
- calculate_cumulative_returns(cleaned_returns, freq='D')
Takes a returns series and calculates cumulative returns.
The cleaned returns series is created by
eth_defi.research.wrangle_vault_prices.
- Parameters
cleaned_returns (pandas.Series) –
- calculate_daily_returns_for_all_vaults(df_work)
Calculate daily returns for each vault in isolation
- Parameters
df_work (pandas.DataFrame) –
- Return type
- calculate_hourly_returns_for_all_vaults(df_work)
Calculate hourly returns for each vault in isolation
- Parameters
df_work (pandas.DataFrame) –
- Return type
- calculate_lifetime_metrics(df, vault_db, returns_column='returns_1h', core3_protocols=None)
Calculate lifetime metrics for each vault in the provided DataFrame.
All-time returns
3M returns, latest
1M returns, latest
Volatility (3M)
Lookback based on the last entry.
- Parameters
df (pandas.DataFrame) – Cleaned price DataFrame conforming to
CleanedVaultPriceRow. Must have aDatetimeIndex.vault_db (Union[eth_defi.vault.vaultdb.VaultDatabase, dict[eth_defi.vault.base.VaultSpec, eth_defi.vault.vaultdb.VaultRow]]) – Pass all vaults or subset of vaults as VaultRows, or full VaultDatabase
core3_protocols (Optional[dict[str, eth_defi.core3.vault_protocol.Core3ExportRecord]]) – Optional Core3 risk records keyed by our protocol slug, as returned by
eth_defi.core3.vault_protocol.build_core3_protocols_for_export(). Threaded through tocalculate_vault_record()to attach a per-vaultcore3summary.Noneto skip Core3 enrichment.returns_column (str) –
- Returns
DataFrame, one row per vault.
- Return type
- calculate_net_profit(start, end, share_price_start, share_price_end, management_fee_annual, performance_fee, deposit_fee, withdrawal_fee, seconds_in_year=31557600.0, sample_count=None)
Calculate profit after external fees have been reduced from the share price change.
- Parameters
start (datetime.datetime) – Start datetime of the investment period.
end (datetime.datetime) – End datetime of the investment period.
share_price_start (float) – Share price at the start of the investment period.
share_price_end (float) – Share price at the end of the investment period.
management_fee_annual (float) – Annual management fee as a percent (0.02 = 2% per year).
performance_fee (float) – Performance fee as a percent (0.20 = 20% of profits).
deposit_fee (Optional[float]) – Deposit fee as a percent (0.01 = 1% fee), or None if no fee.
withdrawal_fee (Optional[float]) – Withdrawal fee as a percent (0.01 = 1% fee), or None if no fee.
sample_count (Optional[int]) – If we have not enough returns data, do not try to calculate profit.
- Returns
Net profit as a floating point (0.10 = 10% profit).
- Return type
- calculate_net_returns_from_gross(name, cumulative_returns, management_fee_annual, performance_fee, deposit_fee, withdrawal_fee, seconds_in_year=31557600.0)
Convert a cumulative gross return series to a cumulative net return series after fees.
This function correctly models a High-Water Mark (HWM) for performance fees, which requires an iterative calculation (a loop). This loop operates on Numpy arrays for maximum speed.
Management fees are accrued based on the time delta of each period.
Performance fees are charged only on profits above the highest net value.
Deposit fees are applied once at the start (t=0).
Withdrawal fees are applied once at the end (t=T).
- Parameters
name (str) – Name for the returned pandas Series.
cumulative_returns (pandas.Series) – A pandas Series with a DatetimeIndex representing the cumulative gross return index (e.g., 1.0, 1.02, 1.05) OR cumulative gross profit (e.g., 0.0, 0.02, 0.05).
management_fee_annual (Optional[float]) – Annual management fee as a decimal (e.g., 0.02 for 2%).
performance_fee (Optional[float]) – Performance fee as a decimal (e.g., 0.20 for 20% of profits above the High-Water Mark).
deposit_fee (Optional[float]) – Fee applied to the initial deposit as a decimal (e.g., 0.01 for 1%).
withdrawal_fee (Optional[float]) – Fee applied to the final withdrawal as a decimal (e.g., 0.01 for 1%).
seconds_in_year – The number of seconds in a year for precise management fee accrual.
- Returns
A pandas Series of the cumulative net profit (e.g., 0.10 for 10%).
- Return type
- calculate_net_returns_from_price(name, share_price, management_fee_annual, performance_fee, deposit_fee, withdrawal_fee, seconds_in_year=31557600.0, zero_epsilon=0.001, freq='h')
Convert a share price series to net return series after fees.
- Parameters
name (str) – For debugging
share_price (pandas.Series) – Share price series with datetime index.
management_fee_annual (Optional[float]) – Annual management fee as a percent (0.02 = 2% per year).
performance_fee (Optional[float]) – Performance fee as a percent (0.20 = 20% of profits).
deposit_fee (Optional[float]) – Deposit fee as a percent (0.01 = 1% fee), or None if no fee.
withdrawal_fee (Optional[float]) – Withdrawal fee as a percent (0.01 = 1% fee), or None if no fee.
freq – The time series frequency (hourly, daily, etc) for management fee calculation.
- Returns
Cumulative net profit as a floating point (0.10 = 10% profit).
- Return type
- calculate_performance_metrics_for_all_vaults(vault_db, prices_df, logger=<built-in function print>, lifetime_min_nav_threshold=100.0, broken_max_nav_value=99000000000, cagr_too_high=10000, min_events=25)
Calculate performance metrics for each vault.
Only applicable to stablecoin vaults as cleaning units are in USD
Clean up idle vaults that have never seen enough events to be considered active
Calculate lifetime returns, CAGR, NAV, etc.
Filter out results with abnormal values
- Returns
DataFrame with lifetime metrics for each vault, indexed by vault name.
- Parameters
vault_db (eth_defi.vault.vaultdb.VaultDatabase) –
prices_df (pandas.DataFrame) –
- Return type
- calculate_period_metrics(period, gross_fee_data, net_fee_data, share_price_hourly, share_price_daily, tvl, now_, utilisation=None)
Calculate metrics for one period.
- Parameters
period (Literal['1W', '1M', '3M', '6M', '1Y', 'lifetime']) – Period identifier (1W, 1M, 3M, 6M, 1Y, lifetime)
gross_fee_data (eth_defi.vault.fee.FeeData) – Fee data before fee mode adjustments
net_fee_data (eth_defi.vault.fee.FeeData) – Fee data after fee mode adjustments (for net return calculations)
share_price_hourly (pandas.Series) – Hourly share price series with DatetimeIndex
share_price_daily (pandas.Series) – Daily share price series with DatetimeIndex
tvl (pandas.Series) – Total value locked series with DatetimeIndex
now – The reference timestamp (usually the last timestamp in the data)
utilisation (Optional[pandas.Series]) – Optional utilisation series (lending vaults only, values 0.0–1.0). When provided,
avg_utilisationis computed for the period window.now_ (pandas.Timestamp) –
- Returns
PeriodMetrics dataclass with calculated metrics
- Return type
- calculate_returns(share_price, freq='D')
Calculate returns from resampled share price series.
- Parameters
share_price (pandas.Series) –
- Return type
- calculate_sharpe_ratio_from_returns(hourly_returns, risk_free_rate=0.0, year_multiplier=365)
Calculate annualized Sharpe ratio from hourly returns.
- Parameters
hourly_returns (pandas.Series) – Pandas Series of hourly percentage returns.
risk_free_rate (float) – Annualized risk-free rate (default 2%).
year_multiplier (float) –
- Returns
Sharpe ratio as a float.
- Return type
- calculate_vault_rankings(results_df, min_tvl_chain_protocol=10000, min_tvl_overall=50000)
Calculate rankings for all periods inside PeriodMetrics objects.
Updates PeriodMetrics objects in-place within the period_results lists. Rankings are calculated for all 6 periods (1W, 1M, 3M, 6M, 1Y, lifetime).
Vaults are excluded from rankings if: - They have no CAGR data (zero or NaN) - They have an error_reason set - They are blacklisted (risk == VaultTechnicalRisk.blacklisted) - Their period TVL is below the threshold
- Parameters
results_df (pandas.DataFrame) – DataFrame from calculate_lifetime_metrics()
min_tvl_chain_protocol (float) – Minimum TVL required for chain and protocol rankings (default: $10,000)
min_tvl_overall (float) – Minimum TVL required for overall rankings (default: $50,000)
- Returns
DataFrame with rankings updated in PeriodMetrics objects
- Return type
- calculate_vault_record(prices_df, vault_metadata_rows, month_ago, three_months_ago, vault_id=None, core3_protocols=None)
Process a single vault metadata + prices to calculate its full data.
Exported to frontend, everything
- Parameters
prices_df (pandas.DataFrame) – Price DataFrame for a single vault, conforming to
CleanedVaultPriceRowvault_metadata_rows (dict[eth_defi.vault.base.VaultSpec, eth_defi.vault.vaultdb.VaultRow]) – Dictionary of vault metadata keyed by VaultSpec
month_ago (pandas.Timestamp) – Timestamp for 1-month lookback
three_months_ago (pandas.Timestamp) – Timestamp for 3-month lookback
vault_id (Optional[str]) – Vault ID string. If not provided, extracted from prices_df[“id”].
core3_protocols (Optional[dict[str, eth_defi.core3.vault_protocol.Core3ExportRecord]]) – Optional Core3 risk records keyed by our protocol slug, as returned by
eth_defi.core3.vault_protocol.build_core3_protocols_for_export(). When given, a compact per-vaultcore3summary (Core3VaultSection) is attached to the record for the vault’s protocol, orNoneif the protocol has no Core3 data.
- Returns
Series with calculated metrics
- Return type
- clean_lifetime_metrics(lifetime_data_df, broken_max_nav_value=99000000000, lifetime_min_nav_threshold=100.0, max_annualised_return=3.0, min_events=25, logger=<built-in function print>)
Clean lifetime data so we have only valid vaults.
Filter out vaults that have broken records or never saw daylight
- Returns
Cleaned lifetime dataframe
- Parameters
lifetime_data_df (pandas.DataFrame) –
- Return type
- combine_return_columns(gross, net, new_line=' ', mode='percent', profit_presentation='split')
Create combined net / (gross) returns column for display.
E.g. 8.3% (10.5%)
- Parameters
gross (pandas.Series) – Gross returns series
net (pandas.Series) – Net returns series
mode (Literal['percent', 'usd']) –
profit_presentation (Literal['split', 'net_only']) –
- Returns
Combined string series
- create_fee_label(fee_data)
Create 2% / 20% style labels to display variosu kinds of vault fees.
Order is: management / performance / deposit / withdrawal fees.
- Parameters
fee_data (eth_defi.vault.fee.FeeData) –
- cross_check_data(vault_db, prices_df, printer=<built-in function print>)
Check that VaultDatabase has metadata for all price_df vaults and vice versa.
- Returns
Number of problem entries.
Should be zero.
- Parameters
vault_db (eth_defi.vault.vaultdb.VaultDatabase) –
prices_df (pandas.DataFrame) –
- Return type
- display_lifetime_table(df)
Render a formatted lifetime table as compact HTML in a Jupyter notebook.
Produces an HTML table with minimal cell padding and renders
<a>links created byformat_lifetime_table()withhtml_links=True.Example:
formatted = format_lifetime_table(df, html_links=True) display_lifetime_table(formatted)
- Parameters
df (pandas.DataFrame) – DataFrame returned by
format_lifetime_table().
- display_vault_chart_and_tearsheet(vault_spec, vault_db, prices_df, render=True)
Render a chart and tearsheet for a single vault.
Use in notebooks
- :param render;
Disable rendering in tests
- Parameters
vault_spec (eth_defi.vault.base.VaultSpec) –
vault_db (eth_defi.vault.vaultdb.VaultDatabase) –
prices_df (pandas.DataFrame) –
- export_lifetime_row(row)
Export lifetime metrics row to a fully JSON-serializable dict.
Recursively handles nested dicts, lists, tuples, sets, and dataclasses.
Normalizes pandas, numpy, datetime, and custom types.
Preserves legacy fee field names.
- Parameters
row (pandas.Series) –
- Return type
- fmt_one_decimal_or_int(x)
Display fees to .1 accuracy if there are .1 fractions, otherwise as int.
- format_ffn_performance_stats(report, prefix_series=None)
Format FFN report for human readable output.
Return a Series with formatted performance metrics
Multiple series can be combined to a comparison table
- Parameters
prefix_data – Extra header data to insert.
report (ffn.core.PerformanceStats) – FFN performance report to format
prefix_series (Optional[pandas.Series]) –
- Returns
DataFrame with formatted performance metrics
- Return type
- format_ffn_performance_stats_grouped(report, prefix_series=None)
Format FFN report as logically grouped sections.
Returns a list of
(heading, series)tuples where each tuple represents a group of related metrics. The groups correspond to theNoneseparators in FFN’sPerformanceStats._stats().- Parameters
report (ffn.core.PerformanceStats) – FFN performance report to format.
prefix_series (Optional[pandas.Series]) – Extra header data to prepend to the first group.
- Returns
List of
(heading, series)tuples for each logical group.- Return type
- format_lifetime_table(df, add_index=False, add_address=False, add_share_token=False, drop_blacklisted=True, profit_presentation='split', html_links=False)
Format table for human readable output.
See
calculate_lifetime_metrics()- Parameters
add_index – Add 1, 2, 3… index column
add_address –
Add address as a separate column.
For vault address list copy-pasted.
drop_blacklisted – Remove vaults we have manually flagged as troublesome.
html_links –
Wrap Name, Chain, and Protocol values in
<a>tags linking to tradingstrategy.ai. Usedisplay_lifetime_table()to render the result with compact styling in a Jupyter notebook.Example:
from eth_defi.research.vault_metrics import ( format_lifetime_table, display_lifetime_table, ) formatted = format_lifetime_table(df, html_links=True) display_lifetime_table(formatted)df (pandas.DataFrame) –
profit_presentation (Literal['split', 'net_only']) –
- Returns
Human readable data frame
- Return type
- format_vault_database(vault_db, index=True)
Format vault database for human readable output.
- Parameters
vault_db (eth_defi.vault.vaultdb.VaultDatabase) – Vault database to format
- Returns
DataFrame with vault metadata, with human readable columns
- Return type
- format_vault_header(vault_row)
Format vault header for human readable output.
- Returns
DataFrame with formatted performance metrics
- Parameters
vault_row (pandas.Series) –
- Return type
- get_period_metrics(period_results, period)
Get PeriodMetrics for a specific period from the results list.
- Parameters
period_results (list[eth_defi.research.vault_metrics.PeriodMetrics]) – List of PeriodMetrics objects from a vault record
period (Literal['1W', '1M', '3M', '6M', '1Y', 'lifetime']) – The period to find (e.g., “1W”, “1M”, “3M”, “6M”, “1Y”, “lifetime”)
- Returns
The matching PeriodMetrics or None if not found
- Return type
- is_special_vault(protocol_slug, vault_address)
Check if a vault is a special vault that may not have deposit/redeem event data.
GRVT and Hyperliquid vaults get data from off-chain APIs
Hardcoded protocol vaults may lack standard ERC-4626 deposit/redeem events
- resample_returns(returns_1h, freq='D')
Calculate returns from resampled returns series.
- Parameters
returns_1h (pandas.Series) – The original returns series.
- Return type
- slugify_protocol(protocol)
Create a slug from protocol name for URLs.
- slugify_vault(name, symbol, address, existing_slugs)
Create a slug from vault metadata for URLs.
- slugify_vaults(vaults)
Create slugs for a set of vaults.
Always give the primary slug to the vault that was created first.
Mutates VaultRow data in-place
- Parameters
vaults (dict[eth_defi.vault.base.VaultSpec, eth_defi.vault.vaultdb.VaultRow]) – The vault metadata entries.
- Return type
- zero_out_near_zero_prices(s, eps=1e-09, clip_negatives=True)
Replace values with abs(x) < eps by 0. Optionally clip negatives to 0.
Keeps NaN as-is, turns +/- inf into NaN.
- Parameters
s (pandas.Series) –
eps (float) –
clip_negatives (bool) –
- Return type