Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a1b2c3d4",
"metadata": {},
"source": [
"![QuantConnect Logo](https://cdn.quantconnect.com/web/i/icon.png)\n",
"<hr>"
]
},
{
"cell_type": "markdown",
"id": "e5f6a7b8",
"metadata": {},
"source": [
"## CoinGecko Market Cap Research\n",
"\n",
"This notebook studies whether cryptocurrency market cap helps explain future returns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c9d0e1f2",
"metadata": {},
"outputs": [],
"source": [
"qb = QuantBook()\n",
"# Anchor the research clock to the start of 2026 for a reproducible history window.\n",
"qb.set_start_date(2026, 1, 1)\n",
"# Daily bars will have an end_time that matches the following midnight.\n",
"qb.settings.daily_precise_end_time = False\n",
"# Trade crypto in USD on Coinbase.\n",
"qb.set_account_currency(\"USD\")\n",
"market = Market.COINBASE\n",
"# Collect the Coinbase pairs quoted in the account currency.\n",
"market_pairs = [\n",
" x.key.symbol\n",
" for x in qb.symbol_properties_database.get_symbol_properties_list(market)\n",
" if x.value.quote_currency == qb.account_currency\n",
"]"
]
},
{
"cell_type": "markdown",
"id": "a3b4c5d6",
"metadata": {},
"source": [
"### Build a CoinGecko Universe\n",
"\n",
"Select the 10 largest Coinbase USD coins by market cap, then inspect the returned universe history."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e7f8a9b0",
"metadata": {},
"outputs": [],
"source": [
"def select_assets(data: List[CoinGecko]) -> List[Symbol]:\n",
" # Filter coins that are quoted in the account currency and available on the market.\n",
" tradable = [d for d in data if d.coin and (d.coin + qb.account_currency) in market_pairs]\n",
" # Sort by market cap and return the top 10 as tradable Symbols.\n",
" return [f.create_symbol(market, qb.account_currency)\n",
" for f in sorted(tradable, key=lambda f: f.market_cap)[-10:]]\n",
"\n",
"# Add the CoinGecko universe.\n",
"universe = qb.add_universe(CoinGeckoUniverse, \"CoinGeckoUniverse\", Resolution.DAILY, select_assets)\n",
"# Request universe history of the last 90 days.\n",
"universe_history = qb.universe_history(universe, qb.time - timedelta(90), qb.time - timedelta(1), flatten=True).rename_axis(['time', 'symbol']).drop(columns=['time'])\n",
"# Print the returned shape and columns.\n",
"print(f\"Shape: {universe_history.shape}\")\n",
"print(f\"Columns: {list(universe_history.columns)}\")\n",
"universe_history.head()"
]
},
{
"cell_type": "markdown",
"id": "c1d2e3f4",
"metadata": {},
"source": [
"### Universe Diagnostics\n",
"\n",
"Check how many assets pass the filter each day and summarize the factors."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a5b6c7d8",
"metadata": {},
"outputs": [],
"source": [
"# Count selected assets by day.\n",
"universe_size = universe_history.reset_index().groupby(['time', 'symbol']).size().groupby('time').size()\n",
"print(f\"Universe days: {len(universe_size)}\")\n",
"# Store the selected symbol list.\n",
"unique_assets = list(universe_history.index.levels[1].unique())\n",
"print(f\"Mean universe size per day: {universe_size.mean():.1f}\")\n",
"print('')\n",
"print(universe_history.marketcap.describe().map('{:0.3f}'.format))\n",
"universe_size.plot(title='Daily Universe Size', ylabel='Universe Size');"
]
},
{
"cell_type": "markdown",
"id": "e9f0a1b2",
"metadata": {},
"source": [
"### Daily Universe Prices\n",
"\n",
"Fetch daily price history for every symbol that appears in the universe."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c3d4e5f6",
"metadata": {},
"outputs": [],
"source": [
"# Extract unique assets\n",
"symbols = list(universe_history.index.get_level_values(1).unique())\n",
"# Fetch daily historical price metrics using the earliest timestamp available in the index.\n",
"history = qb.history(symbols, universe_history.index[0][0] - timedelta(1), qb.time, Resolution.DAILY)\n",
"history"
]
},
{
"cell_type": "markdown",
"id": "a7b8c9d0",
"metadata": {},
"source": [
"### Align Market Cap And Returns\n",
"\n",
"Build a joined table of market cap and future returns."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3d56c7cd",
"metadata": {},
"outputs": [],
"source": [
"# Align the factor with the return from the next open to the following open.\n",
"dataset = (\n",
" universe_history.reset_index().groupby(['time', 'symbol']).agg(marketcap=('marketcap', 'max'))\n",
" .join(history.open.unstack('symbol').sort_index().pct_change(2, fill_method=None).shift(-2).stack().rename('futurereturn'), how='inner')\n",
")\n",
"\n",
"dataset.head()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Foundation-Py-Default",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.14"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading