CoinAPI
Binance US Crypto Price Data
Introduction
The Binance US Crypto Price Data by CoinAPI is for Cryptocurrency price and volume data points. The data covers 604 Cryptocurrency pairs, starts in October 2019, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Binance US.
For more information about the Binance US 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 snippets demonstrates how to set the brokerage model, request data, and perform universe selection with the Binance US dataset:
# Binance US only accepts cash accounts
self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
self.btcbusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BINANCE_US).symbol
self._universe = AddUniverse(CryptoUniverse.binance_us(self.universe_selection_filter)); // Binance US only accepts cash accounts
SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
_symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.BinanceUS).Symbol;
_universe = AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
Data Summary
The following table describes the dataset properties:
| Property | Value |
|---|---|
| Start Date | October 2019 |
| Asset Coverage | 604 Cryptocurrency Pairs |
| Data Density | Dense |
| Resolution | Tick, Second, Minute, Hourly, & Daily |
| Timezone | UTC |
| Market Hours | Always Open |
Requesting Data
To add Binance US 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)
self.set_cash(100000)
# BinanceUS accepts Cash account type only, AccountType.MARGIN will result in an exception.
self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
self.btcbusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BINANCE_US).symbol public class CoinAPIDataAlgorithm : QCAlgorithm
{
private Symbol _symbol;
public override void Initialize()
{
SetStartDate(2020, 6, 1);
SetEndDate(2021, 6, 1);
SetCash(100000);
// BinanceUS accepts Cash account type only, AccountType.Margin will result in an exception.
SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
_symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.BinanceUS).Symbol;
}
}
For more information about creating Crypto subscriptions, see Requesting Data.
Accessing Data
To get the current Binance US 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 US 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 US 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).
def initialize(self) -> None:
self.universe_settings.asynchronous = True
self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
self._universe = self.add_universe(CryptoUniverse.binance_us(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] public override void Initialize()
{
UniverseSettings.Asynchronous = true;
SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
_universe = AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
}
private IEnumerable<Symol> 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 Subscriptions
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.
Example Applications
The Binance US 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 US exchange:
from AlgorithmImports import *
class CoinAPIDataAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.universe_settings.asynchronous = True
# Set USDT as the account currency so we can trade BTCUSDT.
self.set_account_currency('USDT', 100_000)
# Binance US accepts Cash account type only. AccountType.MARGIN
# results in an exception.
self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
# Add BTCUSDT data.
self._btc = self.add_crypto("BTCUSDT", Resolution.MINUTE, Market.BINANCE_US)
# Historical data
history = self.history(self._btc.symbol, 30, Resolution.DAILY)
# Add a Crypto universe that selects Crypto pairs on Binance US.
universe = self.add_universe(CryptoUniverse.binance_us(self._select_assets))
# Historical Universe data
universe_history = self.history(universe, 30, Resolution.DAILY)
for (universe_symbol, time), universe_day in universe_history.items():
for universe_item in universe_day:
symbol = universe_item.symbol
price = universe_item.close
def _select_assets(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 > 10_000_000]
def on_data(self, slice: Slice) -> None:
# Speculate-invest all available free cash on BTCUSDT, repecting
# the order quantity restrictions to avoid invalid orders.
if self.portfolio.cash_book['BTC'].amount != 0:
return
# Define a buffer so that we can scale down the order size,
# avoiding trading errors.
buffer = max(
BinanceFeeModel.TAKER_TIER_1_FEE,
self.settings.free_portfolio_value_percentage
)
quantity = (
self.portfolio.cash_book['USDT'].amount
/ self._btc.ask_price
* (1-buffer)
)
# Check if the quantity exceeds the minimum order size. On
# Binance US, the minimum order size is measured in the quote
# currency (USDT in this case).
minimum_order_size = (
self._btc.symbol_properties.minimum_order_size
/ self._btc.ask_price
)
if abs(quantity) < minimum_order_size:
return
self.market_order(self._btc, quantity) public class CoinAPIDataAlgorithm : QCAlgorithm
{
private Crypto _btc;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
// Set USDT as the account currency so we can trade BTCUSDT.
SetAccountCurrency("USDT", 100000);
UniverseSettings.Asynchronous = true;
// Binance US accepts Cash account type only. AccountType.Margin
// results in an exception.
SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
// Add BTCUSDT data.
_btc = AddCrypto("BTCUSDT", Resolution.Minute, Market.BinanceUS);
// Historical data
var history = History(_btc.Symbol, 30, Resolution.Daily);
// Add a Crypto universe that selects trading pairs on Binance US.
var universe = AddUniverse(CryptoUniverse.BinanceUS(SelectAssets));
// Historical Universe data
var universeHistory = History(universe, 30, Resolution.Daily);
foreach (var universeDay in universeHistory)
{
foreach (CryptoUniverse universeItem in universeDay)
{
var symbol = universeItem.Symbol;
var price = universeItem.Close;
}
}
}
private IEnumerable<Symbol> SelectAssets(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 > 10000000m
select universeItem.Symbol;
}
public override void OnData(Slice slice)
{
// Speculate-invest all available free cash on BTCUSDT, repecting
// the order quantity restrictions to avoid invalid orders.
if (Portfolio.CashBook["BTC"].Amount != 0)
{
return;
}
// Define a buffer so that we can scale down the order size,
// avoiding trading errors.
var buffer = Math.Max(BinanceFeeModel.TakerTier1Fee, Settings.FreePortfolioValuePercentage);
var quantity = Portfolio.CashBook["USDT"].Amount / _btc.AskPrice * (1-buffer);
// Check if the quantity exceeds the minimum order size. On
// Binance US, the minimum order size is measured in the quote
// currency (USDT in this case).
var minimumOrderSize = _btc.SymbolProperties.MinimumOrderSize / _btc.AskPrice;
if (Math.Abs(quantity) < minimumOrderSize)
{
return;
}
MarketOrder(_btc, quantity);
}
}
Framework Algorithm Example
The following example algorithm creates a dynamic universe of Crypto pairs on the Binance US exchange and then forms a equal-weighted portfolio of all the pairs in the universe:
from AlgorithmImports import *
class CoinAPIDataAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(1_000_000)
self.settings.free_portfolio_value_percentage = 0.05
# 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
# Add Crypto Universe Selection that select crypto pairs in BinanceUS exchange
self.add_universe(CryptoUniverse.binance_us(self._select_assets))
# Get the pairs on Binance US that have USD as the quote currency.
self._market_pairs = [
x.key.symbol
for x in self.symbol_properties_database.get_symbol_properties_list(Market.BINANCE_US)
if x.value.quote_currency == self.account_currency
]
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 _select_assets(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
# Select pairs where the quote currency is USD.
pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
# Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]
return [c.symbol for c in pairs]
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") public class CoinAPIDataAlgorithm : QCAlgorithm
{
private Symbol _btcusd;
private List<string> _marketPairs;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(1000000);
Settings.FreePortfolioValuePercentage = 0.05m;
// 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 BinanceUS exchange
AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
// Get the pairs on Binance US that have USD as the quote currency.
_marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.BinanceUS)
.Where(x => x.Value.QuoteCurrency == AccountCurrency)
.Select(x => x.Key.Symbol)
.ToList();
AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null) );
// Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
}
private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
{
// Select pairs where the quote currency is USD.
return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
// Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
.OrderBy(c => c.VolumeInUsd)
.TakeLast(3)
.Select(c => c.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 BinanceUS exchange:
var qb = new QuantBook();
// Add Cryptocurrency pair
var symbol = qb.AddCrypto("BTCUSDT", market:Market.BinanceUS).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 != null && x.VolumeInUsd > 10000m)
.OrderByDescending(x => x.VolumeInUsd)
.Take(5)
.Select(x => x.Symbol);
}
var universe = qb.AddUniverse(CryptoUniverse.BinanceUS(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_US).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_us(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 US 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: