book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

CoinAPI

Binance Crypto Price Data

Introduction

The Binance Crypto Price Data by CoinAPI is for Cryptocurrency price and volume data points. The data covers 2,684 Cryptocurrency pairs, starts in July 2017, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Binance.

For more information about the Binance Crypto Price Data dataset, including CLI commands and pricing, see the dataset listing.

About the Provider

CoinAPI was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications.

Getting Started

The following snippet demonstrates how to request data from the Binance Crypto Price dataset:

# Binance accepts both Cash and Margin account types only.
self.set_brokerage_model(BrokerageName.BINANCE, AccountType.CASH)
self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)

self.btcbusd = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE).symbol

self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
// Binance accepts both Cash and Margin account types only.
SetBrokerageModel(BrokerageName.Binance, AccountType.Cash);
SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);

_symbol = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance).Symbol;

_universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));

Data Summary

The following table describes the dataset properties:

PropertyValue
Start DateJuly 2017
Asset Coverage2,684 Currency Pairs
Data DensityDense
ResolutionTick, Second, Minute, Hourly, & Daily
TimezoneUTC
Market HoursAlways Open

Requesting Data

To add Binance Crypto Price data to your algorithm, call the AddCryptoadd_crypto method. Save a reference to the Crypto Symbol so you can access the data later in your algorithm.

class CoinAPIDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2020, 6, 1)
        self.set_end_date(2021, 6, 1)

        # Set Account Currency to Binance Stable Coin for USD
        self.set_account_currency("BUSD")
        self.set_cash(100000)

        # Binance accepts both Cash and Margin account types.
        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
        
        self.btcbusd = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE).symbol
namespace QuantConnect
{
    public class CoinAPIDataAlgorithm : QCAlgorithm
    {
        private Symbol _symbol;
        
        public override void Initialize()
        {
            SetStartDate(2020, 6, 1);
            SetEndDate(2021, 6, 1);

            // Set Account Currency to Binance Stable Coin for USD
            SetAccountCurrency("BUSD");
            SetCash(100000);

            // Binance accepts both Cash and Margin account types.
            SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
            
            _symbol = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance).Symbol;
        }
    }
}

For more information about creating Crypto subscriptions, see Requesting Data.

Accessing Data

To get the current Binance Crypto Price data, index the Barsbars, QuoteBarsquote_bars, or Ticksticks properties of the current Slice with the Crypto Symbol. Slice objects deliver unique events to your algorithm as they happen, but the Slice may not contain data for your security 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 self.btcbusd in slice.bars:
        trade_bar = slice.bars[self.btcbusd]
        self.log(f"{self.btcbusd} close at {slice.time}: {trade_bar.close}")

    if self.btcbusd in slice.quote_bars:
        quote_bar = slice.quote_bars[self.btcbusd]
        self.log(f"{self.btcbusd} bid at {slice.time}: {quote_bar.bid.close}")

    if self.btcbusd in slice.ticks:
        ticks = slice.ticks[self.btcbusd]
        for tick in ticks:
            self.log(f"{self.btcbusd} price at {slice.time}: {tick.price}")
public override void OnData(Slice slice)
{
    if (slice.Bars.ContainsKey(_symbol))
    {
        var tradeBar = slice.Bars[_symbol];
        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    }

    if (slice.QuoteBars.ContainsKey(_symbol))
    {
        var quoteBar = slice.QuoteBars[_symbol];
        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    }

    if (slice.Ticks.ContainsKey(_symbol))
    {
        var ticks = slice.Ticks[_symbol];
        foreach (var tick in ticks)
        {
            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
        }
    }
}

You can also iterate through all of the data objects in the current Slice.

def on_data(self, slice: Slice) -> None:
    for symbol, trade_bar in slice.bars.items():
        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")

    for symbol, quote_bar in slice.quote_bars.items():
        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")

    for symbol, ticks in slice.ticks.items():
        for tick in ticks:
            self.log(f"{symbol} price at {slice.time}: {tick.price}")
public override void OnData(Slice slice)
{
    foreach (var kvp in slice.Bars)
    {
        var symbol = kvp.Key;
        var tradeBar = kvp.Value;
        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    }

    foreach (var kvp in slice.QuoteBars)
    {
        var symbol = kvp.Key;
        var quoteBar = kvp.Value;
        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    }

    foreach (var kvp in slice.Ticks)
    {
        var symbol = kvp.Key;
        var ticks = kvp.Value;
        foreach (var tick in ticks)
        {
            Log($"{symbol} price at {slice.Time}: {tick.Price}");
        }
    }
}

For more information about accessing Crypto data, see Handling Data.

Historical Data

To get historical Binance Crypto Price data, call the Historyhistory method with the Crypto Symbol. If there is no data in the period you request, the history result is empty.

# DataFrame
history_df = self.history(self.btcbusd, 100, Resolution.DAILY)

# TradeBar objects
history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE)

# QuoteBar objects
history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE)

# Tick objects
history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK)
// TradeBar objects 
var historyTradeBars = History(_symbol, 100, Resolution.Daily);

// QuoteBar objects 
var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);

// Tick objects 
var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);

For more information about historical data, see History Requests.

Universe Selection

To select a dynamic universe of Binance Crypto pairs, call the AddUniverseadd_universe method with a CryptoUniverse object. A Crypto universe uses a selection function to select Crypto pairs based on their OHLCV and dollar volume of the previous day as of midnight Coordinated Universal Time (UTC).

from QuantConnect.Data.universe_selection import *

def initialize(self) -> None:
    self.universe_settings.asynchronous = True
    self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))

def universe_selection_filter(self, universe_day):
    return [c.symbol for c in universe_day if c.volume >= 100 and c.volume_in_usd > 10000]
using QuantConnect.Data.UniverseSelection;

public override void Initialize()
{
    UniverseSettings.Asynchronous = True;
    SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    _universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
}

private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
{
    return from c in universeDay
           where c.Volume >= 100m && c.VolumeInUsd > 10000m
           select c.Symbol;
}

For more information about universe settings, see Settings.

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 history = History(_universe, 30, Resolution.Daily);
foreach (var universeDay in history)
{
    foreach (CryptoUniverse universeItem in universeDay)
    {
        Log($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    }
}
# DataFrame example where the columns are the CryptoUniverse attributes: 
history_df = self.history(self._universe, 30, Resolution.DAILY, flatten=True)

# Series example where the values are lists of CryptoUniverse objects: 
history = self.history(self._universe, 30, Resolution.DAILY)
for (univere_symbol, time), universe_day in history.items():
    for universe_item in universe_day:
        self.log(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")

Historical Universe Data in Research

To get historical universe data in research, call the UniverseHistoryuniverse_history method with the Universe object, and the lookback period. The UniverseHistoryuniverse_history 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 universeDay in universeHistory)
{
    foreach (CryptoUniverse universeItem in universeDay)
    {
        Console.WriteLine($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    }
}
# DataFrame example where the columns are the CryptoUniverse attributes: 
history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)

# Series example where the values are lists of CryptoUniverse objects: 
universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
for (univere_symbol, time), universe_day in universe_history.items():
    for universe_item in universe_day:
        print(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")

You can call the Historyhistory method in Research.

Remove Subcriptions

To unsubscribe from a Crypto pair that you added with the AddCryptoadd_crypto method, call the RemoveSecurityremove_security method.

self.remove_security(self.btcbusd)
RemoveSecurity(_symbol);

The RemoveSecurityremove_security method cancels your open orders for the security and liquidates your holdings in the virtual pair.

Supported Assets

The following table shows the available Cryptocurrency pairs:

Example Applications

The Binance Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies:

  • Buy and hold
  • Trading Cryptocurrency volatility and price action
  • Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation

Classic Algorithm Example

The following example algorithm buys and holds Bitcoin through the Binance exchange:

from AlgorithmImports import *
from QuantConnect.DataSource import *
from QuantConnect.Data.UniverseSelection import *

class CoinAPIDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2020, 6, 1)
        self.set_end_date(2021, 6, 1)
        # Set Account Currency to BUSD, since USD-BUSD will not auto-convert and USD cannot be used to trade
        self.set_cash("BUSD", 100000)
        self.universe_settings.asynchronous = True
        # Binance accepts both Cash and Margin account types, select the one you need for the best reality modeling.
        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)

        # Warm up the security with the last known price to avoid conversion error
        self.set_security_initializer(lambda security: security.set_market_price(self.get_last_known_price(security)))
        
        # Requesting data, we only trade on BTCBUSD in Binance exchange
        crypto = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE)
        self.btcbusd = crypto.symbol
        self.minimum_order_size = crypto.symbol_properties.minimum_order_size
        
        # Historical data
        history = self.history(self.btcbusd, 30, Resolution.DAILY)
        self.debug(f"We got {len(history)} items from our history request")

        # Add Crypto Universe Selection that select crypto pairs in Binance exchange
        self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))

        # Historical Universe data
        universe_history = self.history(self._universe, 30, Resolution.DAILY)
        self.debug(f"We got {len(universe_history)} items from our universe history request")
        for (univere_symbol, time), universe_day in universe_history.items():
            for universe_item in universe_day:
                self.debug(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")

    def universe_selection_filter(self, universe_day):
        # Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
        return [universe_item.symbol for universe_item in universe_day
                if universe_item.volume >= 100 
                and universe_item.volume_in_usd > 10000]

    def on_data(self, slice: Slice) -> None:
        # Speculate-invest all available free cash on BTCBUSD, obeying the order quantity restriction to avoid invalid order
        if self.portfolio.cash_book['BTC'].amount == 0:
            free_cash = self.portfolio.cash_book['BUSD'].amount * (1-self.settings.free_portfolio_value_percentage)
            quantity = free_cash / slice[self.btcbusd].price
            quantity -= quantity % self.minimum_order_size
            if quantity > 0:
                self.market_order(self.btcbusd, quantity)
using QuantConnect.DataSource;
using QuantConnect.Data.UniverseSelection;

namespace QuantConnect
{
    public class CoinAPIDataAlgorithm : QCAlgorithm
    {
        private Symbol _btcbusd;
        private Universe _universe;
        private decimal? _minimumOrderSize;
        
        public override void Initialize()
        {
            SetStartDate(2020, 6, 1);
            SetEndDate(2021, 6, 1);
            // Set Account Currency to BUSD, since USD-BUSD will not auto-convert and USD cannot be used to trade
            SetCash("BUSD", 100000);
            UniverseSettings.Asynchronous = True;
            // Binance accepts both Cash and Margin account types, select the one you need for the best reality modeling.
            SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);

            // Warm up the security with the last known price to avoid conversion error
            SetSecurityInitializer(security => security.SetMarketPrice(GetLastKnownPrice(security)));
            
            // Requesting data, we only trade on BTCBUSD in Binance exchange
            var crypto = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance);
            _btcbusd = crypto.Symbol;
            _minimumOrderSize = crypto.SymbolProperties.MinimumOrderSize;
        
             // Historical data
            var history = History(_btcbusd, 30, Resolution.Daily);
            Debug($"We got {history.Count()} items from our history request");

            // Add Crypto Universe Selection that select crypto pairs in Binance exchange
            _universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));

            // Historical Universe data
            var universeHistory = History(_universe, 30, Resolution.Daily);
            Debug($"We got {universeHistory.Count()} items from our history request");
            foreach (var universeDay in universeHistory)
            {
                foreach (CryptoUniverse universeItem in universeDay)
                {
                    Debug($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
                }
            }
        }

        private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
        {
            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
            return from universeItem in universeDay
                   where universeItem.Volume >= 100m 
                   && universeItem.VolumeInUsd > 10000m
                   select universeItem.Symbol;
        }

        public override void OnData(Slice slice)
        {
            // Speculate-invest all available free cash on BTCBUSD, obeying the order quantity restriction to avoid invalid order
            if (Portfolio.CashBook["BTC"].Amount == 0)
            {
                var freeCash = Portfolio.CashBook["USD"].Amount * (1-Settings.FreePortfolioValuePercentage);
                var quantity = freeCash / slice[_btcbusd].Price;
                quantity -= quantity % _minimumOrderSize;
                if (quantity > 0m)
                {
                    MarketOrder(_btcbusd, quantity);
                }
            }
        }
    }
}

Framework Algorithm Example

The following example algorithm creates a dynamic universe of Crypto pairs on the Binance exchange and then forms a equal-weighted portfolio of all the pairs in the universe:

from AlgorithmImports import *
from QuantConnect.DataSource import *
from QuantConnect.Data.UniverseSelection import *

class CoinAPIDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2020, 6, 1)
        self.set_end_date(2021, 6, 1)

        # Set Account Currency to Binance Stable Coin, since USD-BUSD will not auto-convert and USD cannot be used to trade
        self.set_cash("BUSD", 100000)
        # Binance accepts both Cash and Margin account types, select the one you need for the best reality modeling.
        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)

        # Warm up the security with the last known price to avoid conversion error
        self.set_security_initializer(lambda security: security.set_market_price(self.get_last_known_price(security)))
        self.universe_settings.asynchronous = True
        self.universe_settings.resolution = Resolution.MINUTE
        # Add Crypto Universe Selection that select crypto pairs in Binance exchange
        self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
        
        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(minutes = 20), 0.025, None))
        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())

    def universe_selection_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
        # Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
        return [universe_item.symbol for universe_item in universe_day
                if universe_item.volume >= 100 
                and universe_item.volume_in_usd > 10000]

    def on_securities_changed(self, changes: SecurityChanges) -> None:
        for security in changes.added_securities:
            # Historical data
            history = self.history(security.symbol, 30, Resolution.DAILY)
            self.debug(f"We got {len(history)} items from our history request")
using QuantConnect.DataSource;
using QuantConnect.Data.UniverseSelection;

namespace QuantConnect
{
    public class CoinAPIDataAlgorithm : QCAlgorithm
    {
        private Symbol _btcbusd;
        
        public override void Initialize()
        {
            SetStartDate(2020, 6, 1);
            SetEndDate(2021, 6, 1);

            // Set Account Currency to Binance Stable Coin, since USD-BUSD will not auto-convert and USD cannot be used to trade
            SetCash("BUSD", 100000);
            // Binance accepts both Cash and Margin account types, select the one you need for the best reality modeling.
            SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
 
            // Warm up the security with the last known price to avoid conversion error
            SetSecurityInitializer(security => security.SetMarketPrice(GetLastKnownPrice(security)));
            UniverseSettings.Asynchronous = True;
            UniverseSettings.Resolution = Resolution.Minute;
            // Add Crypto Universe Selection that select crypto pairs in Binance exchange
            AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
        
            AddAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, None));
            // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
            SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
        }

        private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
        {
            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
            return from universeItem in universeDay
                   where universeItem.Volume >= 100m 
                   && universeItem.VolumeInUsd > 10000m
                   select universeItem.Symbol;
        }

        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            foreach(var security in changes.AddedSecurities)
            {
                // Historical data
                var history = History(security.Symbol, 30, Resolution.Daily);
                Debug($"We got {history.Count()} items from our history request");
            }
        }
    }
}

Research Example

The following example lists crypto-currency pairs with the greatest dollar volume in the Binance exchange:

var qb = new QuantBook();

// Add Cryptocurrency pair
var symbol = qb.AddCrypto("BTCUSDT", market:Market.Binance).Symbol;

// Historical data
var history = qb.History(symbol, 30, Resolution.Daily);
foreach (var bar in history)
{
    Console.WriteLine($"{bar.EndTime} {bar}");
}

// Add Crypto Universe Selection
IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
{
    return universeDay
        .Where(x => x.VolumeInUsd != None && x.VolumeInUsd > 10000m)
        .OrderByDescending(x => x.VolumeInUsd)
        .Take(5)
        .Select(x => x.Symbol);
}
var universe = qb.AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));

// Historical Universe data
var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
foreach (var universeDay in universeHistory)
{
    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    {
        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    }
}
qb = QuantBook()

# Add Cryptocurrency pair
symbol = qb.add_crypto("BTCUSDT", market=Market.BINANCE).symbol

# Historical data
history = qb.history(symbol, 30, Resolution.DAILY)
for (symbol, time), row in history.iterrows():
    print(f'{time} {symbol} {row.close}')

# Add Crypto Universe Selection
def universe_selection_filter(universe_day):
    selected = sorted([x for x in universe_day
        if x.volume_in_usd and x.volume_in_usd > 10000],
        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    return [x.symbol for x in selected]

universe = qb.add_universe(CryptoUniverse.binance(universe_selection_filter))

# Historical Universe data
history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
for (univere_symbol, time), universe_day in history.items():
    print(f'=== {time} ===')
    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")

Data Point Attributes

The Binance Crypto Price dataset provides TradeBar, QuoteBar, Tick, and CryptoUniverse objects.

TradeBar Attributes

TradeBar objects have the following attributes:

QuoteBar Attributes

QuoteBar objects have the following attributes:

Tick Attributes

Tick objects have the following attributes:

CryptoUniverse Attributes

CryptoUniverse objects have the following attributes:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: