Crypto Futures
Requesting Data
Introduction
Request Crypto Futures data in your algorithm to receive a feed of asset prices in the OnData
on_data
method. For more information about the specific datasets we use for backtests, see the Binance Crypto Future Price Data dataset listing. To trade Crypto Futures live, you can use the QuantConnect data provider.
Create Subscriptions
To create a Crypto Futures subscription, in the Initialize
initialize
method, call the AddCryptoFuture
add_crypto_future
method. The AddCryptoFuture
add_crypto_future
method returns a CryptoFuture
object, which contains a Symbol
symbol
property. Save a reference to the Symbol
symbol
so you can use it in OnData
on_data
to access the security data in the Slice
.
_symbol = AddCryptoFuture("BTCUSD").Symbol;
self._symbol = self.add_crypto_future("BTCUSD").symbol
The AddCryptoFuture
add_crypto_future
method creates a subscription for a single Crypto Futures asset and adds it to your user-defined universe.
To view the supported assets in the Crypto Futures dataset, see Supported Assets.
Resolutions
The following table shows the available resolutions and data formats for Crypto Futures contract subscriptions:
Resolution | TradeBar | QuoteBar | Trade Tick | Quote Tick |
---|---|---|---|---|
Tick TICK | ||||
Second SECOND | ||||
Minute MINUTE | ||||
Hour HOUR | ||||
Daily DAILY |
The default resolution for Crypto Futures subscriptions is Resolution.Minute
Resolution.MINUTE
. To change the resolution, pass a resolution
argument to the AddCryptoFuture
add_crypto_future
method.
_symbol = AddCryptoFuture("BTCUSD", Resolution.Daily).Symbol;
self._symbol = self.add_crypto_future("BTCUSD", Resolution.DAILY).symbol
To create custom resolution periods, see Consolidating Data.
Supported Markets
The following Market
enumeration members are available for Cryptofuture:
_symbol = AddCryptoFuture("BTCUSD", market: Market.Binance).Symbol;
self._symbol = self.add_crypto_future("BTCUSD", market=Market.BINANCE).symbol
The brokerage models have a default market for each asset class. If you set a brokerage model, you may not need to specify the market to use.
Fill Forward
Fill forward means if there is no data point for the current slice, LEAN uses the previous data point. Fill forward is the default data setting. If you disable fill forward, you may get stale fills or you may see trade volume as zero.
To disable fill forward for a security, set the fillForward
fill_forward
argument to false when you create the security subscription.
_symbol = AddCryptoFuture("BTCUSD", fillForward: false).Symbol;
self._symbol = self.add_crypto_future("BTCUSD", fill_forward=False).symbol
Margin and Leverage
LEAN models buying power and margin calls to ensure your algorithm stays within the margin requirements. The amount of leverage available to you depends on the brokerage you use. To change the amount of leverage you can use for a security, pass a leverage
argument to the AddCryptoFuture
add_crypto_future
method.
_symbol = AddCryptoFuture("BTCUSD", leverage: 3).Symbol;
self._symbol = self.add_crypto_future("BTCUSD", leverage=3).symbol
For more information about the leverage each brokerage provides, see Brokerages.
Data Normalization
The data normalization mode doesn't affect the data that LEAN passes to OnData
on_data
or the data from history request. If you change the data normalization mode, it won't change the outcome.
Examples
The following examples demonstrate some common practices for requesting Crypto Futures data.
Example 1: Respect Lot Sizes
Like Futures, Crypto Futures contracts have a fixed discrete lot size to trade instead of fractional like spot Crypto pairs. The following algorithm demonstrates how to place orders that respect the lot size to avoid rounding errors.
public class CryptoFutureAlgorithm : QCAlgorithm { private Symbol _symbol; public override void Initialize() { SetStartDate(2020, 4, 1); // Set brokerage and account type to match your brokerage environment for accurate fee and margin behavior. SetBrokerageModel(BrokerageName.Binance, AccountType.Margin); // In the Binance brokerage, you can't trade with USD. // Set the account currency as USDT and add the starting cash. SetAccountCurrency("USDT", 10000); // Subscribe to the BTCUSDT perpetual Future contract. _symbol = AddCryptoFuture("BTCUSDT").Symbol; } public override void OnData(Slice slice) { // Only place orders when market is open since market on open orders aren't supported. if (!Portfolio.Invested && IsMarketOpen(_symbol)) { // Get the lot size from the symbol properties. Placing an order that respects the lot size // ensures the order is valid and allows accurate profit and risk calculations for the whole portfolio. var lotSize = Securities[_symbol].SymbolProperties.LotSize; // This example demonstrates an initial desired order size of 2.5 contracts, which will be rounded // to 2 contracts since the lot size is 1. var quantity = Convert.ToDecimal(Math.Floor(2.5 / (double)lotSize)) * lotSize; MarketOrder(_symbol, quantity); } } }
class CryptoFutureAlgorithm(QCAlgorithm): def initialize(self) -> None: self.set_start_date(2020, 4, 1) # Set brokerage and account type to match your brokerage environment for accurate fee and margin behavior. self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN) # In the Binance brokerage, you can't trade with USD. # Set the account currency as USDT and add the starting cash. self.set_account_currency("USDT", 10000) # Subscribe to the BTCUSDT perpetual Future contract. self._symbol = self.add_crypto_future("BTCUSDT").symbol def on_data(self, slice: Slice) -> None: # Only place orders when market is open since market on open orders aren't supported. if not self.portfolio.invested and self.is_market_open(self._symbol): # Get the lot size from the symbol properties. Placing an order that respects the lot size # ensures the order is valid and allows accurate profit and risk calculations for the whole portfolio. lot_size = self.securities[self._symbol].symbol_properties.lot_size # This example demonstrates an initial desired order size of 2.5 contracts, which will be rounded # to 2 contracts since the lot size is 1. quantity = 2.5 // lot_size * lot_size self.market_order(self._symbol, quantity)