Skip to content

Commit

Permalink
Update 99 Examples.html
Browse files Browse the repository at this point in the history
  • Loading branch information
DerekMelchin authored Oct 4, 2024
1 parent 9abad14 commit 76c427e
Showing 1 changed file with 85 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,93 +1,120 @@
<p>The following examples demonstrate some common practices for handling Crypto Futures data.</p>

<h4>Example 1: Margin Cost Reinvest</h4>
<p>This example demonstrates how to reinvest the amount of margin cost of the Crypto Future. We short BTCUSDT Crypto Futures in the beginning. When a margin deduction event happened, the Crypto Future's base currency face amount would deducted, which is "BTC" in this example involving "BTCUSDT". In order to keep the amount of "BTC" invested stable, we can reinvest the same amount to buy back the "BTC" position.</p>
<h4>Example 1: Adjust Holdings on Margin Payments</h4>
<p>
Perpetual futures have a mechanism called <span class='new-term'>funding</span>, where if you're holding a position at certain times (the funding timestamp), you might have to pay or receive funding based on the difference between the perpetual contract price and the spot price.
This example demonstrates how to adjust your position in Crypto Future based on the funding rate.
The funding is settled in the quote currency, which is USDT in this case.
When you receive USDT, the algorithm increases its position size in BTCUSDT.
When you pay USDT, the algorithm decreases its position size.
</p>
<div class="section-example-container">
<pre class="csharp">public class CryptoFutureAlgorithm : QCAlgorithm
{
private Symbol _symbol;
// A day comparing variable to ensure only handle margin once a day.
private decimal _lotSize;
private int _day = -1;

public override void Initialize()
{
SetStartDate(2020, 4, 1);
SetEndDate(2024, 10, 1);
// Set brokerage and account type to match your brokerage environment for accurate fee and margin behavior.
SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
// In Binance brokerage, USD is not a valid currency to trade or automatically convertable.
// Thus, we need to set account currency as USDT and add the starting cash.
// In the Binance brokerage, you can't trade with USD.
// Set the account currency as USDT and add the starting cash.
SetAccountCurrency("USDT", 1000000);
// Add subscription of BTC-USD Futures with specific market to ensure the correct securities are selected.
var btcusdt = AddCryptoFuture("BTCUSDT", market: Market.Binance);
// Subscribe to the BTCUSDT perpetual Future contract.
var btcusdt = AddCryptoFuture("BTCUSDT");
_symbol = btcusdt.Symbol;
// To short BTCUSDT, we need to hold sufficient base currency (BTC) of the pair.
btcusdt.BaseCurrency.SetAmount(10m);
// Save the lot size to avoid order errors.
_lotSize = btcusdt.SymbolProperties.LotSize;
// Set the starting BTC balance to 10.
btcusdt.BaseCurrency.SetAmount(10);
}

public override void OnData(Slice slice)
{
// Make sure to place order when market is open since market on open order is not accepted.
// Only place orders when the market is open since market on open orders aren't supported.
if (!Portfolio.Invested && IsMarketOpen(_symbol))
{
MarketOrder(_symbol, -10);
// Open a long position in the perpetual Crypto Future.
MarketOrder(_symbol, 10);
}

// Margin cost deduction is handled in MarginInterestRates, make sure handled on daily basis only.
if (slice.MarginInterestRates.ContainsKey(_symbol) && _day != Time.Day)
// Only run the following logic once per day.
if (_day == Time.Day)
{
// Calculate the margin paid using the margin interest and holding cost.
// The interest rate on annual basis, so it needs to be divided by 365 to get daily rate.
var interestRate = slice.MarginInterestRates[_symbol].InterestRate;
var marginPaid = Portfolio[_symbol].AbsoluteHoldingsCost * interestRate / 365m;
// Invest the same size as the margin paid to maintain the same level of the quote currency.
MarketOrder(_symbol, -marginPaid);

// Plot the cashbook to ensure the quote currency level is maintained.
var usdt = (Securities[_symbol] as CryptoFuture).QuoteCurrency.Amount;
var btc = (Securities[_symbol] as CryptoFuture).BaseCurrency.Amount;
Plot("CashBook", "USDT", usdt);
Plot("CashBook", "BTC", btc);

_day = Time.Day;
return;
}
// Get the current margin interest rate.
MarginInterestRate interestRate;
if (!slice.MarginInterestRates.TryGetValue(_symbol, out interestRate))
{
return;
}
// Calculate the funding payment.
var holding = Portfolio[_symbol];
var positionValue = holding.GetQuantityValue(holding.Quantity).Amount;
var funding = interestRate.InterestRate * positionValue / holding.Price;
// Increase/decrease the position size based on the funding payment.
var quantity = -(int)(funding / _lotSize) * _lotSize;
if (quantity != 0)
{
MarketOrder(_symbol, quantity);
// Plot the portfolio state.
Plot("CashBook", "USDT", Portfolio.CashBook["USDT"].Amount);
Plot("CashBook", "BTC", Portfolio.CashBook["BTC"].Amount);
Plot("Quantity", "BTCUSDT", Portfolio[_symbol].Quantity);
}
_day = Time.Day;
}
}</pre>
<pre class="python">class CryptoFutureAlgorithm(QCAlgorithm):
def initialize(self) -&gt; None:

def initialize(self) -> None:
self.set_start_date(2020, 4, 1)
self.set_end_date(2024, 10, 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 Binance brokerage, USD is not a valid currency to trade or automatically convertable.
# Thus, we need to set account currency as USDT and add the starting cash.
# 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", 1000000)
# Add subscriptions to BTCUSDT Future with specific market to ensure the correct securities are selected.
btcusdt = self.add_crypto_future("BTCUSDT", market=Market.BINANCE)
# Subscribe to the BTCUSDT perpetual Future contract.
btcusdt = self.add_crypto_future("BTCUSDT")
self._symbol = btcusdt.symbol
# To short BTCUSDT, we need to hold sufficient base currency (BTC) of the pair.
# Save the lot size to avoid order errors.
self._lot_size = btcusdt.symbol_properties.lot_size
# Set the starting BTC balance to 10.
btcusdt.base_currency.set_amount(10)

# A day comparing variable to ensure only handle margin once a day.
# Create a member to track the current day.
self._day = -1

def on_data(self, slice: Slice) -&gt; None:
# Make sure to place order when market is open since market on open order is not accepted.
def on_data(self, slice: Slice) -> None:
# Only place orders when the market is open since market on open orders aren't supported.
if not self.portfolio.invested and self.is_market_open(self._symbol):
self.market_order(self._symbol, -10)

# Margin cost deduction is handled in margin_interest_rates, make sure handled on daily basis only.
if self._symbol in slice.margin_interest_rates and self._day != self.time.day:
# Calculate the margin paid using the margin interest and holding cost.
# The interest rate on annual basis, so it needs to be divided by 365 to get daily rate.
interest_rate = slice.margin_interest_rates[self._symbol].interest_rate
margin_paid = self.portfolio[self._symbol].absolute_holding_cost * interest_rate / 365
# Invest the same size as the margin paid to maintain the same level of the quote currency.
self.market_order(self._symbol, -margin_paid)

# Plot the cashbook to ensure the quote currency level is maintained.
usdt = self.securities[self._symbol].quote_currency.amount
btc = self.securities[self._symbol].base_currency.amount
self.plot("CashBook", "USDT", usdt)
self.plot("CashBook", "BTC", btc)

self._day = self.time.day</pre>
# Open a long position in the perpetual Crypto Future.
self.market_order(self._symbol, 10)
# Only run the following logic once per day.
if self._day == self.time.day:
return
# Get the current margin interest rate.
interest_rate = slice.margin_interest_rates.get(self._symbol)
if not interest_rate:
return
# Calculate the funding payment.
holding = self.portfolio[self._symbol]
position_value = holding.get_quantity_value(holding.quantity).amount
interest_rate = slice.margin_interest_rates[self._symbol].interest_rate
funding = interest_rate * position_value / holding.security.price
# Increase/decrease the position size based on the funding payment.
quantity = -funding // self._lot_size * self._lot_size
if quantity:
self.market_order(self._symbol, quantity)
# Plot the portfolio state.
self.plot("CashBook", "USDT", self.portfolio.cash_book['USDT'].amount)
self.plot("CashBook", "BTC", self.portfolio.cash_book['BTC'].amount)
self.plot("Quantity", "BTCUSDT", self.portfolio[self._symbol].quantity)
self._day = self.time.day</pre>
</div>

<h4>Example 2: Future-Spot Arbitration</h4>
Expand Down

0 comments on commit 76c427e

Please sign in to comment.