CoinGecko
Crypto Market Cap
Introduction
The Crypto Market Cap dataset by CoinGecko tracks the market cap of cryptocurrencies. The data covers 620 cryptocurrencies that are supported by QuantConnect, starts in 28 April 2013, and is delivered on a daily frequency. This dataset is created by scraping CoinGecko's Market Chart.
For more information about the Crypto Market Cap dataset, including CLI commands and pricing, see the dataset listing.
About the Provider
CoinGecko was founded in 2014 by TM Lee (CEO) and Bobby Ong (COO) with the mission to democratize the access of crypto data and empower users with actionable insights. We also deep dive into the crypto space to deliver valuable insights to our users through our cryptocurrency reports, as well as our publications, newsletter, and more.
Getting Started
The following snippet demonstrates how to request data from the CoinGecko Crypto Market Cap dataset:
self.btc = self.add_data(CoinGecko, "BTC").symbol self._universe = self.add_universe(CoinGeckoUniverse, self.universe_selection)
_symbol = AddData<CoinGecko>("BTC").Symbol;
_universe = AddUniverse(CoinGeckoUniverse, UniverseSelection)
Requesting Data
To add CoinGecko Crypto Market Cap data to your algorithm, call the AddDataadd_data method. Save a reference to the dataset Symbol so you can access the data later in your algorithm.
from AlgorithmImports import *
class CoinGeckoMarketCapDataAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2019, 1, 1)
self.set_end_date(2020, 6, 1)
self.set_cash(100000)
self.btcusd = self.add_crypto("BTCUSD", Resolution.DAILY).symbol
self.dataset_symbol = self.add_data(CoinGecko, "BTC").symbol public class CoinGeckoMarketCapDataAlgorithm: QCAlgorithm
{
private Symbol _symbol, _datasetSymbol;
public override void Initialize()
{
SetStartDate(2019, 1, 1);
SetEndDate(2020, 6, 1);
SetCash(100000);
_symbol = AddCrypto("BTCUSD", Resolution.Daily).Symbol;
_datasetSymbol = AddData<CoinGecko>("BTC").Symbol;
}
}
Accessing Data
To get the current Crypto Market Cap data, index the current Slice with the dataset Symbol. Slice objects deliver unique events to your algorithm as they happen, but the Slice may not contain data for your dataset at every time step. To avoid issues, check if the Slice contains the data you want before you index it.
def on_data(self, slice: Slice) -> None:
if slice.contains_key(self.dataset_symbol):
data_point = slice[self.dataset_symbol]
self.log(f"{self.dataset_symbol} market cap::volume at {slice.time}: {data_point.market_cap}::{data_point.volume}") public override void OnData(Slice slice)
{
if (slice.ContainsKey(_datasetSymbol))
{
var dataPoint = slice[_datasetSymbol];
Log($"{_datasetSymbol} market cap::volume at {slice.Time}: {dataPoint.MarketCap}::{dataPoint.Volume}");
}
}
To iterate through all of the dataset objects in the current Slice, call the Getget method.
def on_data(self, slice: Slice) -> None:
for dataset_symbol, data_point in slice.get(CoinGecko).items():
self.log(f"{dataset_symbol} market cap::volume at {slice.time}: {data_point.market_cap}::{data_point.volume}")
public override void OnData(Slice slice)
{
foreach (var kvp in slice.Get<CoinGecko>())
{
var datasetSymbol = kvp.Key;
var dataPoint = kvp.Value;
Log($"{datasetSymbol} market cap::volume at {slice.Time}: {dataPoint.MarketCap}::{dataPoint.Volume}");
}
}
Historical Data
To get historical CoinGecko Crypto Market Cap data, call the Historyhistory method with the dataset Symbol. If there is no data in the period you request, the history result is empty.
# DataFrame history_df = self.history(self.dataset_symbol, 100, Resolution.DAILY) # Dataset objects history_bars = self.history[CoinGecko](self.dataset_symbol, 100, Resolution.DAILY)
var history = History<CoinGecko>(_datasetSymbol, 100, Resolution.Daily);
For more information about historical data, see History Requests.
Universe Selection
To select a dynamic universe of Cryptos based on CoinGecko Crypto Market Cap data, call the AddUniverseadd_universe method with the CoinGeckoUniverse class and a selection function. Note that the filtered output is a list of names of the coins. If corresponding tradable crypto pairs are preferred, call CreateSymbol(market, quoteCurrency)create_symbol(market, quoteCurrency) method for each output item.
class CryptoMarketCapUniverseAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_account_currency("USD")
self._market = Market.COINBASE
self._market_pairs = [
x.key.symbol
for x in self.symbol_properties_database.get_symbol_properties_list(self._market)
if x.value.quote_currency == self.account_currency
]
self._universe = self.add_universe(CoinGeckoUniverse, 'CoinGeckoUniverse', Resolution.DAILY, self._select_assets)
def _select_assets(self, data: List[CoinGecko]) -> List[Symbol]:
for datum in data:
self.debug(f'{datum.coin},{datum.market_cap},{datum.price}')
# Select the coins that our brokerage supports and have a quote currency that matches
# our account currency.
tradable_coins = [d for d in data if d.coin + self.account_currency in self._market_pairs]
# Select the largest coins and create their Symbol objects.
return [
c.create_symbol(self._market, self.account_currency)
for c in sorted(tradable_coins, key=lambda x: x.market_cap)[-10:]
] public class CryptoMarketCapUniverseAlgorithm : QCAlgorithm
{
private Universe _universe;
public override void Initialize()
{
SetAccountCurrency("USD");
var market = Market.Coinbase;
var marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(market)
.Where(x => x.Value.QuoteCurrency == AccountCurrency)
.Select(x => x.Key.Symbol)
.ToList();
_universe = AddUniverse<CoinGecko>(data =>
{
foreach (var datum in data.OfType<CoinGecko>())
{
Debug($"{datum.Coin},{datum.MarketCap},{datum.Price}");
}
return data
.Select(c => c as CoinGecko)
// Select the coins that the brokerage supports and have a quote currency that
// matches our account currency.
.Where(c => marketPairs.Contains(c.Coin + AccountCurrency))
// Select the 10 largest coins.
.OrderByDescending(c => c.MarketCap)
.Take(10)
// Create the Symbol objects of the selected coins.
.Select(c => c.CreateSymbol(market, AccountCurrency));
});
}
}
For more information about dynamic universes, see Universes.
Universe History
You can get historical universe data in an algorithm and in the Research Environment.
Historical Universe Data in Algorithms
To get historical universe data in an algorithm, call the Historyhistory method with the Universe object and the lookback period. If there is no data in the period you request, the history result is empty.
var universeHistory = History(_universe, 30, Resolution.Daily);
foreach (var coins in universeHistory)
{
foreach (CoinGecko coin in coins)
{
Log($"{coin.Symbol.Value} market cap at {coin.EndTime}: {coin.MarketCap}");
}
} # DataFrame example where the columns are the CoinGeckoUniverse attributes:
history_df = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
# Series example where the values are lists of CoinGeckoUniverse objects:
universe_history = self.history(self._universe, 30, Resolution.DAILY)
for (_, time), coins in universe_history.items():
for coin in coins:
self.log(f"{coin.symbol.value} market cap at {coin.end_time}: {coin.market_cap}")
Historical Universe Data in Research
To get historical universe data in research, call the UniverseHistoryuniverse_history method with the Universe object, a start date, and an end date. This method returns the filtered universe. If there is no data in the period you request, the history result is empty.
var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
foreach (var coins in universeHistory)
{
foreach (CoinGecko coin in coins)
{
Console.WriteLine($"{coin.Symbol.Value} market cap at {coin.EndTime}: {coin.MarketCap}");
}
} # DataFrame example where the columns are the CoinGeckoUniverse attributes:
history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
# Series example where the values are lists of CoinGeckoUniverse objects:
universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
for (_, time), coins in universe_history.items():
for coin in coins:
print(f"{coin.symbol.value} market cap at {coin.end_time}: {coin.market_cap}")
You can call the Historyhistory method in Research.
Example Applications
The CoinGecko Crypto Market Cap dataset provides information on the size of the crypto coin and can be used to compare the size of one coin to another. Examples include the following strategies:
- Construct a major crypto index fund.
- Invest in the cryptos with the fastest growth in market size.
- Red flag stop when there might be a crypto bank run.
Classic Algorithm Example
The following example algorithm buy BTCUSD when the market cap of BTC is rising, while sell it when the market cap of BTC is dropping.
from AlgorithmImports import *
class CoinGeckoAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
# Request BTCUSD crypto data for trading
self.crypto_symbol = self.add_crypto("BTCUSD").symbol
# Request CoinGecko Market Cap data of BTC for trade signal generation
self.custom_data_symbol = self.add_data(CoinGecko, "BTC").symbol
# Use RollingWindow to save the last 2 market cap data for capital flow analysis
self.window = RollingWindow(2)
def on_data(self, slice: Slice) -> None:
# Trade based on updated market cap data
data = slice.get(CoinGecko)
if data and self.custom_data_symbol in data:
# Update RollingWindow for updated comparison
self.window.add(data[self.custom_data_symbol])
if not self.window.is_ready:
return
# Buy BTCUSD if the market cap of BTC is increasing, which suggests the capital flow towards BTC market and drive up the demand
if self.window[0].market_cap > self.window[1].market_cap:
self.set_holdings(self.crypto_symbol, 1)
# Sell otherwise, since the capital is flowing out and the demand of BTC lowered
else:
self.set_holdings(self.crypto_symbol, -0.5)
def on_order_event(self, orderEvent: OrderEvent) -> None:
if orderEvent.status == OrderStatus.FILLED:
self.debug(f'Purchased Crypto: {orderEvent.symbol}') public class CoinGeckoAlgorithm : QCAlgorithm
{
private Symbol _cryptoSymbol, _customDataSymbol;
private RollingWindow<CoinGecko> _window;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
// Request BTCUSD crypto data for trading
_cryptoSymbol = AddCrypto("BTCUSD").Symbol;
// Request CoinGecko Market Cap data of BTC for trade signal generation
_customDataSymbol = AddData<CoinGecko>("BTC").Symbol;
// Use RollingWindow to save the last 2 market cap data for capital flow analysis
_window = new RollingWindow<CoinGecko>(2);
}
public override void OnData(Slice slice)
{
// Trade based on updated market cap data
var data = slice.Get<CoinGecko>();
if (!data.IsNullOrEmpty() && data.ContainsKey(_customDataSymbol))
{
// Update RollingWindow for updated comparison
_window.Add(data[_customDataSymbol]);
if (!_window.IsReady)
{
return;
}
// Buy BTCUSD if the market cap of BTC is increasing, which suggests the capital flow towards BTC market and drive up the demand
if (_window[0].MarketCap > _window[1].MarketCap)
{
SetHoldings(_cryptoSymbol, 1);
}
// Sell otherwise, since the capital is flowing out and the demand of BTC lowered
else
{
SetHoldings(_cryptoSymbol, -0.5m);
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status.IsFill())
{
Debug($"Purchased Crypto: {orderEvent.Symbol}");
}
}
}
Framework Algorithm Example
The following example algorithm buy BTCUSD when the market cap of BTC is rising, while sell it when the market cap of BTC is dropping with framework implementation.
from AlgorithmImports import *
class CoinGeckoAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
# Request CoinGecko Market Cap data of BTC for trade signal generation
symbol = self.add_data(CoinGecko, "BTC").symbol
# Request BTCUSD crypto data for trading
crypto = self.add_crypto("BTCUSD", market=Market.COINBASE).symbol
symbol_dict = {symbol: crypto}
# Use RollingWindow to save the last 2 market cap data for capital flow analysis
window = {symbol: RollingWindow[CoinGecko](2)}
# Custom alpha model that emit insights based on updated market cap data
self.add_alpha(CoinGeckoAlphaModel(symbol_dict, window))
# Equal invest to evenly dissipate capital concentration risk from non-systematic individual risky event
self.set_portfolio_construction(InsightWeightingPortfolioConstructionModel())
class CoinGeckoAlphaModel(AlphaModel):
def __init__(self, symbol_dict: Dict[Symbol, Symbol], window: Dict[Symbol, RollingWindow[CoinGecko]]) -> None:
self.symbol_dict = symbol_dict
self.window = window
def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
insights = []
# Trade based on updated market cap data
data = slice.Get(CoinGecko)
for dataset_symbol, crypto_symbol in self.symbol_dict.items():
if not data.contains_key(dataset_symbol):
continue
# Update RollingWindow for updated comparison
self.window[dataset_symbol].add(data[dataset_symbol])
# Can only compare market cap if the RollingWindow is ready
window = self.window[dataset_symbol]
if not window.is_ready:
continue
# Buy BTCUSD if the market cap of BTC is increasing, which suggests the capital flow towards BTC market and drive up the demand
if window[0].market_cap > window[1].market_cap:
insight = Insight.price(crypto_symbol, timedelta(1), InsightDirection.UP, weight=1)
insights.append(insight)
# Sell otherwise, since the capital is flowing out and the demand of BTC lowered
else:
insight = Insight.price(crypto_symbol, timedelta(1), InsightDirection.DOWN, weight=0.25)
insights.append(insight)
return insights public class CoinGeckoAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
// Request CoinGecko Market Cap data of BTC for trade signal generation
var symbol = AddData<CoinGecko>("BTC").Symbol;
// Request BTCUSD crypto data for trading
var crypto = AddCrypto("BTCUSD", market: Market.Coinbase).Symbol;
var symbolDict = new Dictionary<Symbol, Symbol> { {symbol, crypto} };
// Use RollingWindow to save the last 2 market cap data for capital flow analysis
var window = new Dictionary<Symbol, RollingWindow<CoinGecko>>{ {symbol, new RollingWindow<CoinGecko>(2)} };
// Custom alpha model that emit insights based on updated market cap data
AddAlpha(new CoinGeckoAlphaModel(symbolDict, window));
// Equal invest to evenly dissipate capital concentration risk from non-systematic individual risky event
SetPortfolioConstruction(new InsightWeightingPortfolioConstructionModel());
}
}
public class CoinGeckoAlphaModel : AlphaModel
{
private Dictionary<Symbol, Symbol> _symbolDict = new();
private Dictionary<Symbol, RollingWindow<CoinGecko>> _window = new();
public CoinGeckoAlphaModel(Dictionary<Symbol, Symbol> symbolDict, Dictionary<Symbol, RollingWindow<CoinGecko>> window)
{
_symbolDict = symbolDict;
_window = window;
}
public override List<Insight> Update(QCAlgorithm algorithm, Slice slice)
{
var insights = new List<Insight>();
// Trade based on updated market cap data
var data = slice.Get<CoinGecko>();
foreach (var kvp in _symbolDict)
{
var datasetSymbol = kvp.Key;
var cryptoSymbol = kvp.Value;
if (!data.ContainsKey(kvp.Key)) continue;
// Update RollingWindow for updated comparison
_window[datasetSymbol].Add(data[datasetSymbol]);
// Can only compare market cap if the RollingWindow is ready
var window = _window[datasetSymbol];
if (!window.IsReady) continue;
// Buy BTCUSD if the market cap of BTC is increasing, which suggests the capital flow towards BTC market and drive up the demand
if (window[0].MarketCap > window[1].MarketCap)
{
var insight = Insight.Price(cryptoSymbol, TimeSpan.FromDays(1), InsightDirection.Up, weight: 1d);
insights.Add(insight);
}
// Sell otherwise, since the capital is flowing out and the demand of BTC lowered
else
{
var insight = Insight.Price(cryptoSymbol, TimeSpan.FromDays(1), InsightDirection.Down, weight: 0.25d);
insights.Add(insight);
}
}
return insights;
}
}
Research Example
The following example lists US Equities having the highest 7-day sentiment.
#r "../QuantConnect.DataSource.CoinGecko.dll"
using QuantConnect.DataSource;
var qb = new QuantBook();
// Requesting Data
var symbol = qb.AddData<CoinGecko>("BTC").Symbol;
// Historical data
var history = qb.History<CoinGecko>(symbol, 30, Resolution.Daily);
foreach (CoinGecko coin in history)
{
Console.WriteLine($"{coin} at {coin.EndTime}");
}
// Add Universe Selection
IEnumerable<Symbol> UniverseSelection(IEnumerable<BaseData> altCoarse)
{
return (from d in altCoarse.OfType<CoinGecko>()
orderby d.MarketCap descending select d.Symbol).Take(10);
}
var universe = qb.AddUniverse<CoinGeckoUniverse<(UniverseSelection);
// Historical Universe data
var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-5), qb.Time);
foreach (var coins in universeHistory)
{
foreach (CoinGecko coin in coins)
{
Console.WriteLine($"{coin.Symbol.Value} market cap at {coin.EndTime}: {coin.MarketCap}");
}
} qb = QuantBook()
# Requesting Data
symbol = qb.add_data(CoinGecko, "BTC").symbol
# Historical data
history = qb.history(CoinGecko, symbol, 30, Resolution.DAILY)
for (symbol, time), row in history.iterrows():
print(f"{symbol} sentiment at {time}: {row['marketcap']}")
# Add Universe Selection
def universe_selection(alt_coarse: List[CoinGeckoUniverse]) -> List[Symbol]:
return [d.symbol for d in sorted([x for x in alt_coarse if x.market_cap],
key=lambda x: x.market_cap, reverse=True)[:10]]
universe = qb.add_universe(CoinGeckoUniverse, universe_selection)
# Historical Universe data
universe_history = qb.universe_history(universe, qb.time-timedelta(10), qb.time)
for (_, time), coins in universe_history.items():
for coin in coins:
print(f"{coin.symbol.value} market cap at {coin.end_time}: {coin.market_cap}")