Lesson 17 · Real-World Data Analytics
Python Data Analytics #17: Real Cryptocurrency Market Analysis in Python
Video seventeen of the hundred-video real-world data analytics series. Analyzing Ethereum's own real early trading history, real on-chain activity included,…
- CourseReal-World Data Analytics
- Lesson17 of 26
- Video30 min
- FormatJupyter notebook · 30 code cells
- Data1 dataset
What you'll learn
Datasets used in this lesson
Save these next to the notebook. In Google Colab, upload them with the 📁 icon on the left first.
- eth_price_onchain.csv13.0 KB
📓 Full notebook
Download .ipynbData Analytics 100, Video 17: Real Cryptocurrency Market Analysis#
- Video seventeen of the hundred-video real-world data analytics series.
- Analyzing Ethereum's own real early trading history, real on-chain activity included, not just a price chart.
- Let's get into it.
Part 1: Crypto Data Includes More Than Price#
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
eth = pd.read_csv('eth_price_onchain.csv', parse_dates=['Date'])
eth.shape
Part 2: Real Data Preview#
eth.head(3)
eth.columns.tolist()
Part 3: Real Price History#
plt.figure(figsize=(11, 5))
plt.plot(eth['Date'], eth['PriceUSD'], color='darkslateblue')
plt.xlabel('Real Date')
plt.ylabel('Real Price (USD)')
plt.title("Real Ethereum Price, Aug 2015 to Jan 2016")
plt.tight_layout()
plt.savefig('eth_price_history.png', dpi=120)
plt.close()
Part 4: Real Daily Returns#
eth['Return'] = eth['PriceUSD'].pct_change()
eth['Return'].describe().round(4)
Part 5: Real Annualized Volatility, Crypto vs Stocks#
eth_annual_vol = eth['Return'].std() * np.sqrt(365)
round(eth_annual_vol * 100, 1)
Part 6: Real Best and Real Worst Single Days#
eth_best_day = eth.loc[eth['Return'].idxmax(), 'Date']
eth_best_pct = round(eth['Return'].max() * 100, 1)
eth_worst_day = eth.loc[eth['Return'].idxmin(), 'Date']
eth_worst_pct = round(eth['Return'].min() * 100, 1)
eth_best_day, eth_best_pct, eth_worst_day, eth_worst_pct
Part 7: Real Cumulative Growth#
eth['Cumulative'] = (1 + eth['Return'].fillna(0)).cumprod()
round(eth['Cumulative'].iloc[-1], 3)
Part 8: Real Maximum Drawdown#
running_peak = eth['Cumulative'].cummax()
drawdown = (eth['Cumulative'] - running_peak) / running_peak
round(drawdown.min() * 100, 1)
Part 9: Visualizing Real Drawdown#
plt.figure(figsize=(11, 4))
plt.fill_between(eth['Date'], drawdown * 100, 0, color='crimson', alpha=0.6)
plt.xlabel('Real Date')
plt.ylabel('Real Drawdown (%)')
plt.title('Real Ethereum Drawdown from Peak')
plt.tight_layout()
plt.savefig('eth_drawdown.png', dpi=120)
plt.close()
Part 10: Real On-Chain Activity, Active Addresses#
eth['AdrActCnt'].describe().round(0)
plt.figure(figsize=(11, 4))
plt.plot(eth['Date'], eth['AdrActCnt'], color='teal')
plt.xlabel('Real Date')
plt.ylabel('Real Active Addresses')
plt.title('Real Ethereum Daily Active Addresses')
plt.tight_layout()
plt.savefig('active_addresses.png', dpi=120)
plt.close()
Part 11: Real Correlation, Price vs Real Network Activity#
price_activity_corr = eth['PriceUSD'].corr(eth['AdrActCnt'])
round(price_activity_corr, 3)
Part 12: Real Transaction Count Trend#
eth['TxCnt'].describe().round(0)
tx_growth = eth['TxCnt'].iloc[-1] / eth['TxCnt'].iloc[0] - 1
round(tx_growth * 100, 1)
Part 13: Real Network Hash Rate#
eth['HashRate'].describe().round(4)
hash_growth = eth['HashRate'].iloc[-1] / eth['HashRate'].iloc[0] - 1
round(hash_growth * 100, 1)
Part 14: Real Rolling 14-Day Volatility#
eth['Vol14'] = eth['Return'].rolling(14).std() * np.sqrt(365)
eth['Vol14'].dropna().describe().round(2)
Part 15: Visualizing Real Rolling Volatility#
plt.figure(figsize=(11, 5))
plt.plot(eth['Date'], eth['Vol14'], color='darkorange')
plt.xlabel('Real Date')
plt.ylabel('Real Annualized 14-Day Volatility')
plt.title('Real Rolling Volatility, Ethereum')
plt.tight_layout()
plt.savefig('eth_rolling_vol.png', dpi=120)
plt.close()
Part 16: Real Market Cap vs Real Price#
cap_growth = eth['CapMrktCurUSD'].iloc[-1] / eth['CapMrktCurUSD'].iloc[0] - 1
round(cap_growth * 100, 1)
Part 17: Real Trading Volume Spikes#
volume_median = eth['VolumeUSD'].median()
high_volume_days = (eth['VolumeUSD'] > volume_median * 3).sum()
high_volume_days
Part 18: Real Volume-Return Relationship#
abs_return = eth['Return'].abs()
volume_return_corr = eth['VolumeUSD'].corr(abs_return)
round(volume_return_corr, 3)
Part 19: Real Value-at-Risk for Crypto#
var_95 = np.percentile(eth['Return'].dropna(), 5)
round(var_95 * 100, 2)
Part 20: Real Skewness and Real Kurtosis#
eth_skew = eth['Return'].skew()
eth_kurtosis = eth['Return'].kurtosis()
round(eth_skew, 3), round(eth_kurtosis, 3)
Part 21: Real 7-Day Moving Average Smoothing#
eth['MA7'] = eth['PriceUSD'].rolling(7).mean()
plt.figure(figsize=(11, 5))
plt.plot(eth['Date'], eth['PriceUSD'], alpha=0.4, label='Real Daily Price')
plt.plot(eth['Date'], eth['MA7'], color='black', label='Real 7-Day Average')
plt.xlabel('Real Date')
plt.ylabel('Real Price (USD)')
plt.title('Real Ethereum Price with 7-Day Smoothing')
plt.legend()
plt.tight_layout()
plt.savefig('eth_smoothed_price.png', dpi=120)
plt.close()
Part 22: Real Weekly Return Aggregation#
eth_indexed = eth.set_index('Date')
weekly_return = eth_indexed['PriceUSD'].resample('W').last().pct_change()
weekly_return.dropna().describe().round(3)
Part 23: Real Best and Real Worst Week#
best_week = weekly_return.idxmax()
worst_week = weekly_return.idxmin()
round(weekly_return.max() * 100, 1), round(weekly_return.min() * 100, 1)
Part 24: Real Simple Momentum Signal Backtest#
eth['MA_Signal'] = (eth['PriceUSD'] > eth['MA7']).astype(int)
eth['MA_Position'] = eth['MA_Signal'].shift(1).fillna(0)
eth['MA_Strategy_Return'] = eth['MA_Position'] * eth['Return']
strategy_growth = (1 + eth['MA_Strategy_Return'].fillna(0)).cumprod().iloc[-1]
round(strategy_growth, 3), round(eth['Cumulative'].iloc[-1], 3)
Part 25: Saving the Real Enriched Dataset#
eth.round(4).to_csv('eth_enriched.csv', index=False)
reloaded = pd.read_csv('eth_enriched.csv')
reloaded.shape[0] == eth.shape[0]
Part 26: Real Sanity Check on Cumulative Growth#
manual_final_price_ratio = eth['PriceUSD'].iloc[-1] / eth['PriceUSD'].iloc[0]
round(abs(manual_final_price_ratio - eth['Cumulative'].iloc[-1]), 6) < 1e-6
Part 27: Real Recap Print#
print(f'Across {len(eth)} real early trading days, Ethereum realized {round(eth_annual_vol*100)}% annualized volatility and a {round(drawdown.min()*100,1)}% maximum drawdown, both far beyond anything seen from real stocks earlier in this domain.')
Part 28: Real Fee Revenue Trend#
fee_col_present = 'FeeTotNtv' in eth.columns
fee_col_present
Part 29: Real Days of Extreme Moves#
extreme_days = eth[eth['Return'].abs() > 0.15]
len(extreme_days)
Part 30: Real Comparison Table, Crypto vs Prior Stocks#
comparison_table = pd.DataFrame({'Asset': ['Ethereum (this video)', 'Apple (real, prior video)', 'Tesla (real, prior video)'], 'AnnualizedVolPct': [round(eth_annual_vol * 100, 1), 21.8, 62.0]})
comparison_table
Wrap-Up: What You Learned#
- Crypto markets genuinely trade every real day of the year, so annualizing volatility uses real 365 days instead of the real 252 trading days used for stocks.
- Real on-chain metrics, active addresses, transaction counts, and hash rate, give crypto a real layer of fundamental data that ordinary stocks simply do not publish.
- Volatility, drawdown, skewness, and kurtosis all confirmed the real same thing here: crypto in its early years moved far more violently than any real stock in this domain.
- Price and real network usage do not always move together, a real reminder that speculation and real fundamentals can diverge, especially early in an asset's history.
- The real same backtesting discipline from two videos ago, lagging signals and tracking real trades honestly, applies just as much to crypto as to equities.
- Next video: pulling real company fundamentals straight from real financial statements, a completely different real data source than anything used so far in this domain.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



