Auto Compound Tracker
Track the performance enhancement of auto-compounding yield strategies by precisely measuring the incremental return difference between simple yield and continuously compounded yield over extended time periods, fully accounting for gas transaction costs and optimal compound frequency analysis.
Auto-Compounding Performance Tracker — Crypto-Native
Category: Crypto-Native | Subcategory: Staking & Yield
What This Notebook Does
Auto-compounding protocols (e.g. Convex, Yearn, Beefy) automatically harvest and reinvest rewards, saving users gas costs and improving yield efficiency.
Key formula:
APY = (1 + APR / n) ^ n - 1
where n = number of compounds per year.
| Compound Frequency | n | APY at 10% APR |
|---|---|---|
| Monthly | 12 | 10.47% |
| Weekly | 52 | 10.51% |
| Daily | 365 | 10.52% |
| Hourly | 8760 | 10.52% |
| Continuous | ∞ | 10.52% |
This notebook:
- Models compound frequency impact on APY across different APR levels
- Calculates gas cost breakeven for manual vs auto compounding
- Tracks auto-compound position value over time
- Compares manual harvest strategies with automated protocols
- Exports compounding performance data
!pip install numpy pandas matplotlib seaborn --quietimport numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
plt.rcParams['figure.figsize'] = (14, 5)
plt.rcParams['axes.spines.top'] = False
plt.rcParams['axes.spines.right'] = False
print('Imports ready.')Imports ready.
Section 1 — Configuration
This section defines the key parameters for our simulation and analysis, including the starting capital, various APR values to evaluate, the gas cost for manual harvesting, and the simulation duration.
CAPITAL = 50_000.0 # starting USD capital
APR_VALUES = [5, 10, 20, 30, 50] # % APR scenarios
GAS_COST_USD = 10.0 # USD cost per manual harvest tx
SIMULATION_YEARS = 3
print('Config ready.')Config ready.
Section 2 — Compound Frequency Analysis
apr_to_apy Function
This helper function converts an Annual Percentage Rate (APR) to an Annual Percentage Yield (APY) based on a specified number of compounding periods per year. It's crucial for understanding the true return on investment given different compounding frequencies.
This section calculates the effective Annual Percentage Yield (APY) for various compounding frequencies (monthly, weekly, daily, hourly) across different Annual Percentage Rate (APR) scenarios. This demonstrates how more frequent compounding can lead to a higher effective yield.
def apr_to_apy(apr: float, n: int) -> float:
"""
Convert APR to APY for a given compounding frequency.
Parameters
----------
apr : float Annual percentage rate (0-100).
n : int Number of compounding periods per year.
Returns
-------
float Effective APY in percent.
"""
return ((1 + apr / 100 / n) ** n - 1) * 100
freqs = {'Monthly (12x)': 12, 'Weekly (52x)': 52,
'Daily (365x)': 365, 'Hourly (8760x)': 8760}
rows = []
for apr in APR_VALUES:
row = {'APR %': apr}
for label, n in freqs.items():
row[label] = round(apr_to_apy(apr, n), 3)
rows.append(row)
compound_table = pd.DataFrame(rows).set_index('APR %')
print('APY vs Compounding Frequency:')
print(compound_table.to_string())APY vs Compounding Frequency:
Monthly (12x) Weekly (52x) Daily (365x) Hourly (8760x)
APR %
5 5.116 5.125 5.127 5.127
10 10.471 10.506 10.516 10.517
20 21.939 22.093 22.134 22.140
30 34.489 34.870 34.969 34.985
50 63.209 64.479 64.816 64.870
Section 3 — Gas Breakeven Analysis
gas_breakeven_harvest_days Function
This function determines the minimum number of days an investor needs to wait between manual harvests for the accumulated rewards to cover the transaction (gas) cost. This helps in deciding the optimal harvest frequency for manual compounding strategies.
This section analyzes the number of days required for accumulated daily rewards to cover the gas cost of a manual harvest. This calculation helps users understand the profitability threshold for performing manual compounding given their capital, APR, and transaction fees.
def gas_breakeven_harvest_days(capital: float, apr: float, gas_usd: float) -> float:
"""
Calculate minimum days between manual harvests to break even on gas.
Harvest only makes sense if daily_reward > gas_cost.
Parameters
----------
capital : float USD capital deployed.
apr : float Annual percentage rate (0-100).
gas_usd : float USD cost of one harvest transaction.
Returns
-------
float Days to wait before manual harvest is profitable.
"""
daily_rate = apr / 100 / 365
daily_income = capital * daily_rate
if daily_income <= 0:
return float('inf')
return gas_usd / daily_income
print(f'Gas breakeven (gas=${GAS_COST_USD}):')
for apr in APR_VALUES:
days = gas_breakeven_harvest_days(CAPITAL, apr, GAS_COST_USD)
print(f' {apr:2d}% APR on ${CAPITAL:,.0f}: harvest every {days:.1f} days to cover gas')Gas breakeven (gas=$10.0): 5% APR on $50,000: harvest every 1.5 days to cover gas 10% APR on $50,000: harvest every 0.7 days to cover gas 20% APR on $50,000: harvest every 0.4 days to cover gas 30% APR on $50,000: harvest every 0.2 days to cover gas 50% APR on $50,000: harvest every 0.1 days to cover gas
Section 4 — Auto-Compound vs Manual Simulation
simulate_compounding Function
This core simulation function compares the growth of an investment under two scenarios over a specified number of years: an auto-compounding strategy (continuous daily compounding) and a manual harvesting strategy (compounding at a set interval, with gas costs deducted). It returns the daily portfolio values for both approaches.
This section simulates the performance of auto-compounding versus a manual harvest strategy over a specified period. It highlights the financial advantage of auto-compounding by comparing the final portfolio values and the total gas fees incurred by manual harvesting.
def simulate_compounding(capital: float, apr: float, years: float,
manual_harvest_days: int, gas_usd: float) -> pd.DataFrame:
"""
Compare auto-compounding vs manual harvest strategies.
Parameters
----------
capital : Initial USD.
apr : Annual rate (%).
years : Simulation length.
manual_harvest_days : How often manual strategy harvests.
gas_usd : Cost per harvest.
Returns
-------
pd.DataFrame Daily portfolio values for each strategy.
"""
n_days = int(years * 365)
daily_rate = apr / 100 / 365
idx = pd.date_range('2023-01-01', periods=n_days, freq='D')
# Auto compound: continuous daily compounding
auto_balance = [capital]
for _ in range(n_days):
auto_balance.append(auto_balance[-1] * (1 + daily_rate))
# Manual harvest: only compounds on harvest days, minus gas cost
manual_capital = capital
manual_pending = 0.0
manual_bal = [capital]
gas_spent = 0.0
for day in range(n_days):
manual_pending += manual_capital * daily_rate
if (day + 1) % manual_harvest_days == 0:
gas_spent += gas_usd
manual_capital += manual_pending - gas_usd
manual_pending = 0
manual_bal.append(manual_capital + manual_pending)
return pd.DataFrame({
'auto_compound': auto_balance[1:],
'manual_harvest': manual_bal[1:],
}, index=idx), gas_spent
BASE_APR = 20
sim_df, gas_total = simulate_compounding(CAPITAL, BASE_APR, SIMULATION_YEARS, 30, GAS_COST_USD)
auto_final = sim_df['auto_compound'].iloc[-1]
manual_final = sim_df['manual_harvest'].iloc[-1]
print(f'APR={BASE_APR}% | Capital=${CAPITAL:,.0f} | {SIMULATION_YEARS} years')
print(f'Auto-compound final: ${auto_final:,.0f} (+{(auto_final/CAPITAL-1)*100:.1f}%)')
print(f'Manual harvest final: ${manual_final:,.0f} (+{(manual_final/CAPITAL-1)*100:.1f}%) | Gas paid: ${gas_total:,.0f}')
print(f'Auto-compound advantage: ${auto_final - manual_final:,.0f}')APR=20% | Capital=$50,000 | 3 years Auto-compound final: $91,091 (+82.2%) Manual harvest final: $90,176 (+80.4%) | Gas paid: $360 Auto-compound advantage: $915
Section 5 — Visualization
This section visualizes the simulation results, illustrating the growth of both auto-compounded and manually harvested portfolios over time. It also presents a comparison of APY across different compounding frequencies and APR levels, making the impact of compounding visually clear.
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
fig.suptitle('Auto-Compounding Performance Analysis', fontsize=13, fontweight='bold')
ax1 = axes[0]
ax1.plot(sim_df.index, sim_df['auto_compound'] / 1000, color='#1976d2', lw=2, label='Auto-compound (daily)')
ax1.plot(sim_df.index, sim_df['manual_harvest'] / 1000, color='#e53935', lw=1.5, ls='--', label='Manual harvest (monthly)')
ax1.axhline(CAPITAL / 1000, color='gray', ls=':', lw=1)
ax1.set_ylabel('Portfolio Value (K USD)')
ax1.legend()
ax1.set_title(f'{BASE_APR}% APR: Auto vs Manual Compounding')
ax2 = axes[1]
compound_table.T.plot(ax=ax2, marker='o')
ax2.set_xlabel('Compounding Frequency')
ax2.set_ylabel('APY (%)')
ax2.set_title('APY vs Compounding Frequency by APR')
ax2.legend(title='APR %', fontsize=8)
plt.tight_layout()
plt.show()Section 6 — Export
This final section exports the simulated data and the APY-vs-frequency table to CSV files. This allows users to further analyze or utilize the generated data in external tools or reports.
sim_df.to_csv('auto_compound_tracker.csv')
compound_table.to_csv('apr_to_apy_table.csv')
print('Saved: auto_compound_tracker.csv, apr_to_apy_table.csv')Saved: auto_compound_tracker.csv, apr_to_apy_table.csv
Conclusion
This notebook demonstrates the significant impact of compounding frequency on the effective yield (APY) and compares the performance of auto-compounding protocols against manual harvesting strategies. Key takeaways include:
- Higher Compounding Frequency, Higher APY: Even small increases in compounding frequency can lead to notable gains in APY over time.
- Auto-compounding Advantage: Auto-compounding consistently outperforms manual harvesting due to the elimination of gas costs and continuous reinvestment.
- Gas Breakeven Analysis: Understanding the gas breakeven point is crucial for manual harvesters to determine profitable harvest intervals.
These insights can help users make informed decisions when choosing between different DeFi investment strategies and protocols.