Fija vault analysis

  • Run erc-4626-single-vault.ipynb analysis for all Fija

To generate a a HTML report:

jupyter nbconvert --no-input --to html docs/source/tutorials/erc-4626-fija-vaults.ipynb
mv  docs/source/tutorials/erc-4626-fija-vaults.html ~/Downloads

Setup

  • Set up notebook rendering output mode

  • Use static image charts so this notebook is readeable on Github / ReadTheDocs

[17]:
import pandas as pd
from plotly.offline import init_notebook_mode
import plotly.io as pio

from eth_defi.vault.base import VaultSpec
from eth_defi.research.notebook import set_large_plotly_chart_font

pd.options.display.float_format = "{:,.2f}".format
pd.options.display.max_columns = None
pd.options.display.max_rows = None


# Set up Plotly chart output as SVG
image_format = "png"
width = 1400
height = 800

# https://stackoverflow.com/a/52956402/315168
init_notebook_mode()

# https://plotly.com/python/renderers/#overriding-the-default-renderer
pio.renderers.default = image_format

current_renderer = pio.renderers[image_format]
# Have SVGs default pixel with
current_renderer.width = width
current_renderer.height = height

# Set all Plotly charts to use large font sizes for better readability,
# for sharing on mobile
set_large_plotly_chart_font(
    line_width=5,
    legend_font_size=16,
    axis_title_font_size=16,
    font_size=20,
)
pio.templates.default = "custom"

print("Notebook formatting setup done")
Notebook formatting setup done

Read and clean raw scanned vault price data

  • Read the Parquet file produced earlier with price scan

  • Clean the data if necessary

[18]:
import pickle
from pathlib import Path

from eth_defi.vault.vaultdb import VaultDatabase

data_folder = Path("~/.tradingstrategy/vaults").expanduser()
vault_db_path = data_folder / "vault-db.pickle"

vault_db: VaultDatabase = pickle.load(open(vault_db_path, "rb"))

cleaned_data_parquet_file = data_folder / "cleaned-vault-prices-1h.parquet"
prices_df = pd.read_parquet(cleaned_data_parquet_file)

print(f"We have {len(vault_db):,} vaults in the database and {len(prices_df):,} price rows.")
We have 10,357 vaults in the database and 8,393,611 price rows.

Choose vaults to examine

  • We pick Fija vaults by their name

[19]:
from eth_defi.vault.base import VaultSpec
from eth_defi.vault.vaultdb import VaultLead
from eth_defi.research.vault_metrics import format_vault_database

def _lower_name(v: VaultLead):
    name = v["Name"]
    if name:
        return name.lower()
    return ""


# Map out vaults we are going to examine in this notebook
leads = {spec: vault for spec, vault in vault_db.items() if "fija" in _lower_name(vault)}

vault_df = format_vault_database(leads, index=False)
vault_df = vault_df.set_index("Name")
vault_df = vault_df.sort_values("NAV", ascending=False)

vault_df = vault_df[vault_df["Deposit count"] > 40]
display(vault_df)


Symbol Address Denomination NAV Protocol Mgmt fee Perf fee Shares First seen _detection_data _denomination_token _share_token Chain Protocol identified Stablecoin denominated ERC-7540 ERC-7575 Fee detected Deposit count Redeem count Total events Age
Name
fija Strategy USDC GMXv2 sUSDC_GMXv2 0xadbb6ec1d07b0e9708451fd657e7812327ec6501 USDC 1,231,545.17 <unknown ERC-4626> <unknown> <unknown> 1200726.03948 2024-12-12 13:30:29 ERC4262VaultDetection(chain=42161, address='0x... {'name': 'USD Coin', 'symbol': 'USDC', 'total_... {'name': 'fija Strategy USDC GMXv2', 'symbol':... Arbitrum False True False False False 1296 270 1566 224 days 23:00:57.677211
fija Strategy crvUSD CurveConvex scrvUSD_CC 0x6155c331aa73a9872b22871eb6d7516c6fb52a69 crvUSD 1,073,580.29 <unknown ERC-4626> <unknown> <unknown> 939563.649206483304142095 2023-10-19 13:01:47 ERC4262VaultDetection(chain=1, address='0x6155... {'name': 'Curve.Fi USD Stablecoin', 'symbol': ... {'name': 'fija Strategy crvUSD CurveConvex', '... Ethereum False True False False False 41 16 57 644 days 23:29:39.677211
fija USDC GMXv2 RY fUSDC_GMXv2 0xf5b7ac0afbe08ffa7b4bd9bd4e6d678201356658 USDC 223,035.20 <unknown ERC-4626> <unknown> <unknown> 225232.348031 2024-10-30 09:21:01 ERC4262VaultDetection(chain=42161, address='0x... {'name': 'USD Coin', 'symbol': 'USDC', 'total_... {'name': 'fija USDC GMXv2 RY', 'symbol': 'fUSD... Arbitrum False True False False False 755 177 932 268 days 03:10:25.677211
fija USDC GMXv2 FIAX fUSDC 0x4f7f56c6833b7ae211f8cd2563d0728252b2b088 USDC 18,580.67 <unknown ERC-4626> <unknown> <unknown> 18899.453822 2025-05-02 10:20:31 ERC4262VaultDetection(chain=42161, address='0x... {'name': 'USD Coin', 'symbol': 'USDC', 'total_... {'name': 'fija USDC GMXv2 FIAX', 'symbol': 'fU... Arbitrum False True False False False 124 112 236 84 days 02:10:55.677211

Grab the filtered in vault ids for the rest of the notebook.

[20]:
VAULTS = [spec for spec, row in leads.items() if spec.vault_address in vault_df["Address"].values]

print(f"Examining {len(VAULTS):,} vaults.")
Examining 4 vaults.

Calculate reports

  • Calculate vault reports for all vaults

[21]:
from eth_defi.research.vault_metrics import analyse_vault

reports = {}
for vault_spec in VAULTS:

    vault_report = analyse_vault(
        vault_db=vault_db,
        prices_df=prices_df,
        spec=vault_spec,
        chart_frequency="daily",
    )

    if vault_report is not None:
        reports[vault_spec] = vault_report
Examining vault fija USDC GMXv2 RY: 42161-0xf5b7ac0afbe08ffa7b4bd9bd4e6d678201356658, having 5,415 raw returns, 5,414 hourly and 235 daily returns
Share price movement: 1.0090 2024-10-30 09:34:08 -> 0.9901 2025-07-19 14:36:29
Examining vault fija Strategy USDC GMXv2: 42161-0xadbb6ec1d07b0e9708451fd657e7812327ec6501, having 4,967 raw returns, 4,966 hourly and 219 daily returns
Share price movement: 0.9988 2024-12-12 13:32:24 -> 1.0256 2025-07-19 14:36:29
Examining vault fija USDC GMXv2 FIAX: 42161-0x4f7f56c6833b7ae211f8cd2563d0728252b2b088, having 1,172 raw returns, 1,171 hourly and 74 daily returns
Share price movement: 0.9998 2025-05-02 11:19:13 -> 0.9830 2025-07-19 14:36:29
Examining vault fija Strategy crvUSD CurveConvex: 1-0x6155c331aa73a9872b22871eb6d7516c6fb52a69, having 13,110 raw returns, 13,109 hourly and 551 daily returns
Share price movement: 0.9999 2023-10-19 13:54:11 -> 1.1274 2025-05-16 08:37:59

Comparison table for portfolio key metrics

  • Create a comparison matrix of key metrics, each vault being one column

[22]:
from eth_defi.research.vault_metrics import format_vault_header
from eth_defi.research.vault_metrics import format_ffn_performance_stats

columns = []

for spec, report in reports.items():
    vault_row = vault_df[vault_df["Address"] == spec.vault_address].iloc[0]
    vault_row["Name"] = vault_row.name  # Index remaap
    header = format_vault_header(vault_row)
    column_series = format_ffn_performance_stats(report.performance_stats, prefix_series=header)
    columns.append(column_series)

# print(columns)

df = pd.DataFrame(columns).set_index("Name").T
display(df)
Name fija USDC GMXv2 RY fija Strategy USDC GMXv2 fija USDC GMXv2 FIAX fija Strategy crvUSD CurveConvex
Chain Arbitrum Arbitrum Arbitrum Ethereum
Address 0xf5b7ac0afbe08ffa7b4bd9bd4e6d678201356658 0xadbb6ec1d07b0e9708451fd657e7812327ec6501 0x4f7f56c6833b7ae211f8cd2563d0728252b2b088 0x6155c331aa73a9872b22871eb6d7516c6fb52a69
Denomination USDC USDC USDC crvUSD
NAV 223,035.20 1,231,545.17 18,580.67 1,073,580.29
First seen 2024-10-30 09:21:01 2024-12-12 13:30:29 2025-05-02 10:20:31 2023-10-19 13:01:47
Total events 932 1566 236 57
Age 268 days 03:10:25.677211 224 days 23:00:57.677211 84 days 02:10:55.677211 644 days 23:29:39.677211
Start 2024-10-30 2024-12-12 2025-05-02 2023-10-19
End 2025-07-19 2025-07-19 2025-07-19 2025-05-16
Risk-free rate 0.00% 0.00% 0.00% 0.00%
Total Return -1.86% 2.74% -1.68% 12.75%
CAGR -2.59% 4.61% -7.62% 7.92%
Max Drawdown -8.85% -3.16% -1.99% -0.20%
Calmar Ratio -0.29 1.46 -3.84 40.43
MTD -1.35% -1.35% -1.35% 0.41%
3m -1.90% -1.90% - 2.21%
6m -2.44% -0.77% - 4.99%
YTD -1.94% -0.04% -1.68% 3.02%
1Y - - - 8.64%
3Y (ann.) - - - 7.92%
5Y (ann.) - - - -
10Y (ann.) - - - -
Since Incep. (ann.) -2.59% 4.61% -7.62% 7.92%
Daily Sharpe -0.13 0.87 -1.55 2.93
Daily Sortino -0.18 1.47 -2.01 23.05
Daily Mean (ann.) -1.43% 3.17% -5.69% 5.51%
Daily Vol (ann.) 10.88% 3.63% 3.67% 1.88%
Daily Skew -0.79 0.92 -1.30 6.23
Daily Kurt 95.07 10.60 2.78 45.47
Best Day 6.84% 1.49% 0.46% 1.29%
Worst Day -7.24% -0.86% -0.77% -0.10%
Monthly Sharpe -0.82 0.00 -1.74 7.42
Monthly Sortino -1.36 0.00 -2.04 inf
Monthly Mean (ann.) -2.47% 0.00% -6.76% 7.61%
Monthly Vol (ann.) 3.02% 4.17% 3.87% 1.03%
Monthly Skew 0.48 0.47 - 0.34
Monthly Kurt -0.20 -1.25 - 1.13
Best Month 1.36% 1.76% 0.23% 1.32%
Worst Month -1.35% -1.35% -1.35% 0.04%
Yearly Sharpe - - - 1.43
Yearly Sortino - - - inf
Yearly Mean -1.94% -0.04% - 5.96%
Yearly Vol - - - 4.16%
Yearly Skew - - - -
Yearly Kurt - - - -
Best Year -1.94% -0.04% - 8.90%
Worst Year -1.94% -0.04% - 3.02%
Avg. Drawdown -1.96% -0.34% -1.83% -0.04%
Avg. Drawdown Days 37.67 13.07 35.00 5.34
Avg. Up Month 0.76% 1.12% 0.23% 0.63%
Avg. Down Month -0.69% -0.84% -1.35% -
Win Year % 0.00% 0.00% - 100.00%
Win 12m % - - - 100.00%

Vault charts

  • Examine vault metrics and charts

[23]:
from eth_defi.research.vault_metrics import analyse_vault

for spec, vault_report in reports.items():

    # Display returns figur
    returns_chart_fig = vault_report.rolling_returns_chart
    returns_chart_fig.show()

../_images/tutorials_erc-4626-fija-vaults_14_0.png
../_images/tutorials_erc-4626-fija-vaults_14_1.png
../_images/tutorials_erc-4626-fija-vaults_14_2.png
../_images/tutorials_erc-4626-fija-vaults_14_3.png

Returns comparison chart

  • Show rolling returns of all picked vaults

[24]:
from eth_defi.research.rolling_returns import calculate_rolling_returns, visualise_rolling_returns

interesting_vaults = [spec.as_string_id() for spec in VAULTS]

rolling_returns_df = calculate_rolling_returns(
    prices_df,
    interesting_vaults=interesting_vaults,
    clip_up=50,
)

# display(rolling_returns_df.head(3))

fig = visualise_rolling_returns(rolling_returns_df)

fig.show()
../_images/tutorials_erc-4626-fija-vaults_16_0.png