chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// Binance-specific crypto future margin model that includes supplementary stable coin
|
||||
/// currencies as alternative collateral for non-coin (USDⓈ-M) futures.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// EU/EEA users under MiCA Credits Trading Mode have BNFCR in their account.
|
||||
/// When BNFCR is present, this model aggregates all supplementary collateral assets
|
||||
/// using their walletBalance values converted to the primary collateral currency.
|
||||
/// Non-EU accounts don't have BNFCR — the check is a no-op for them.
|
||||
/// See: https://www.binance.com/en/support/faq/detail/0e857c392a2d47cebde0af762d9255ae
|
||||
/// </remarks>
|
||||
public class BinanceCryptoFutureMarginModel : CryptoFutureMarginModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Binance Futures Credits currency symbol, present in EU/EEA accounts under MiCA Credits Trading Mode.
|
||||
/// </summary>
|
||||
private const string BNFCRCurrency = "BNFCR";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
/// <param name="leverage">The leverage to use, default 25x</param>
|
||||
public BinanceCryptoFutureMarginModel(decimal leverage = 25)
|
||||
: base(leverage)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total collateral amount for a Binance crypto future, including supplementary
|
||||
/// collateral assets for EU/EEA accounts in MiCA Credits Trading Mode.
|
||||
/// For coin futures (e.g. BTCUSD), only the primary collateral (base currency) is used.
|
||||
/// </summary>
|
||||
/// <param name="portfolio">The algorithm's portfolio</param>
|
||||
/// <param name="security">The crypto future security</param>
|
||||
/// <param name="primaryCollateral">The primary collateral cash (e.g. USDT)</param>
|
||||
/// <returns>Total collateral amount in terms of the primary collateral currency</returns>
|
||||
protected override decimal GetTotalCollateralAmount(
|
||||
SecurityPortfolioManager portfolio, Security security, Cash primaryCollateral)
|
||||
{
|
||||
// BNFCR presence means EU/EEA account in MiCA Credits Trading Mode.
|
||||
// Non-EU accounts don't have BNFCR in CashBook — skip entirely.
|
||||
var cashBook = portfolio.CashBook;
|
||||
if (!cashBook.ContainsKey(BNFCRCurrency))
|
||||
{
|
||||
return base.GetTotalCollateralAmount(portfolio, security, primaryCollateral);
|
||||
}
|
||||
|
||||
// Aggregate all collateral assets using walletBalance values.
|
||||
// Binance controls which assets are in the account — we sum everything
|
||||
// with a non-zero balance, converting to the primary collateral currency.
|
||||
// Negative amounts (e.g. BNFCR fees) correctly reduce the total.
|
||||
var total = 0m;
|
||||
foreach (var kvp in cashBook)
|
||||
{
|
||||
var cash = kvp.Value;
|
||||
if (cash.Amount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
total += cashBook.Convert(cash.Amount, cash.Symbol, primaryCollateral.Symbol);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When BNFCR is present (EU/MiCA mode), all USDⓈ-M futures share the same collateral
|
||||
/// pool regardless of quote currency (USDT, USDC, etc.).
|
||||
/// </summary>
|
||||
protected override bool SharesCollateral(SecurityPortfolioManager portfolio, Cash collateralCurrency, Security otherCryptoFuture)
|
||||
{
|
||||
return portfolio.CashBook.ContainsKey(BNFCRCurrency) || base.SharesCollateral(portfolio, collateralCurrency, otherCryptoFuture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Data.Market;
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// The responsability of this model is to apply future funding rate cash flows to the portfolio based on open positions
|
||||
/// </summary>
|
||||
public class BinanceFutureMarginInterestRateModel : IMarginInterestRateModel
|
||||
{
|
||||
private DateTime _nextFundingRateApplication = DateTime.MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// Apply margin interest rates to the portfolio
|
||||
/// </summary>
|
||||
/// <param name="marginInterestRateParameters">The parameters to use</param>
|
||||
public void ApplyMarginInterestRate(MarginInterestRateParameters marginInterestRateParameters)
|
||||
{
|
||||
var security = marginInterestRateParameters.Security;
|
||||
var time = marginInterestRateParameters.Time;
|
||||
var cryptoFuture = (CryptoFuture)security;
|
||||
if (!cryptoFuture.Invested)
|
||||
{
|
||||
// nothing to do
|
||||
_nextFundingRateApplication = DateTime.MaxValue;
|
||||
return;
|
||||
}
|
||||
else if (_nextFundingRateApplication == DateTime.MaxValue)
|
||||
{
|
||||
// we opened a new position
|
||||
_nextFundingRateApplication = GetNextFundingRateApplication(time);
|
||||
}
|
||||
|
||||
var marginInterest = cryptoFuture.Cache.GetData<MarginInterestRate>();
|
||||
if(marginInterest == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while(time >= _nextFundingRateApplication)
|
||||
{
|
||||
// When the funding rate is positive, the price of the perpetual contract is higher than the mark price,
|
||||
// thus, traders who are long pay for short positions. Conversely, a negative funding rate indicates that perpetual
|
||||
// prices are below the mark price, which means that short positions pay for longs.
|
||||
// Funding Amount = Nominal Value of Positions * Funding Rate
|
||||
|
||||
var holdings = cryptoFuture.Holdings;
|
||||
|
||||
var positionValue = cryptoFuture.Holdings.GetQuantityValue(holdings.Quantity);
|
||||
|
||||
var funding = marginInterest.InterestRate * positionValue.Amount;
|
||||
|
||||
funding *= -1;
|
||||
// '* -1' because:
|
||||
// - we pay when 'funding' positive:
|
||||
// long position & positive rate
|
||||
// short position & negative rate
|
||||
// - we ear when 'funding' negative:
|
||||
// long position & negative rate
|
||||
// short position & positive rate
|
||||
positionValue.Cash.AddAmount(funding);
|
||||
|
||||
_nextFundingRateApplication = GetNextFundingRateApplication(_nextFundingRateApplication);
|
||||
}
|
||||
}
|
||||
|
||||
private static DateTime GetNextFundingRateApplication(DateTime currentTime)
|
||||
{
|
||||
if(currentTime.Hour >= 16)
|
||||
{
|
||||
// tomorrow 00:00
|
||||
return currentTime.Date.AddDays(1);
|
||||
}
|
||||
else if (currentTime.Hour >= 8)
|
||||
{
|
||||
return currentTime.Date.AddHours(16);
|
||||
}
|
||||
else
|
||||
{
|
||||
return currentTime.Date.AddHours(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// The responsibility of this model is to apply future funding rate cash flows to the portfolio based on open positions
|
||||
/// </summary>
|
||||
public class BybitFutureMarginInterestRateModel : BinanceFutureMarginInterestRateModel
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.Fills;
|
||||
using QuantConnect.Orders.Slippage;
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// Crypto Future Security Object Implementation for Crypto Future Assets
|
||||
/// </summary>
|
||||
public class CryptoFuture : Security, IBaseCurrencySymbol
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the currency acquired by going long this currency pair
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For example, the EUR/USD has a base currency of the euro, and as a result
|
||||
/// of going long the EUR/USD a trader is acquiring euros in exchange for US dollars
|
||||
/// </remarks>
|
||||
public Cash BaseCurrency { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the Crypto Future security
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol</param>
|
||||
/// <param name="exchangeHours">Defines the hours this exchange is open</param>
|
||||
/// <param name="quoteCurrency">The cash object that represent the quote currency</param>
|
||||
/// <param name="baseCurrency">The cash object that represent the base currency</param>
|
||||
/// <param name="symbolProperties">The symbol properties for this security</param>
|
||||
/// <param name="currencyConverter">Currency converter used to convert <see cref="CashAmount"/>
|
||||
/// instances into units of the account currency</param>
|
||||
/// <param name="registeredTypes">Provides all data types registered in the algorithm</param>
|
||||
/// <param name="cache">The security cache</param>
|
||||
public CryptoFuture(Symbol symbol,
|
||||
SecurityExchangeHours exchangeHours,
|
||||
Cash quoteCurrency,
|
||||
Cash baseCurrency,
|
||||
SymbolProperties symbolProperties,
|
||||
ICurrencyConverter currencyConverter,
|
||||
IRegisteredSecurityDataTypesProvider registeredTypes,
|
||||
SecurityCache cache)
|
||||
: base(symbol,
|
||||
quoteCurrency,
|
||||
symbolProperties,
|
||||
new CryptoFutureExchange(exchangeHours),
|
||||
cache,
|
||||
new SecurityPortfolioModel(),
|
||||
new ImmediateFillModel(),
|
||||
IsCryptoCoinFuture(quoteCurrency.Symbol) ? new BinanceCoinFuturesFeeModel() : new BinanceFuturesFeeModel(),
|
||||
NullSlippageModel.Instance,
|
||||
new ImmediateSettlementModel(),
|
||||
Securities.VolatilityModel.Null,
|
||||
new CryptoFutureMarginModel(),
|
||||
new SecurityDataFilter(),
|
||||
new SecurityPriceVariationModel(),
|
||||
currencyConverter,
|
||||
registeredTypes,
|
||||
// only applies for perpetual futures
|
||||
symbol.ID.Date == SecurityIdentifier.DefaultDate ? new BinanceFutureMarginInterestRateModel() : Securities.MarginInterestRateModel.Null
|
||||
)
|
||||
{
|
||||
BaseCurrency = baseCurrency;
|
||||
Holdings = new CryptoFutureHolding(this, currencyConverter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the security is a crypto coin future
|
||||
/// </summary>
|
||||
/// <returns>True if the security is a crypto coin future</returns>
|
||||
public bool IsCryptoCoinFuture()
|
||||
{
|
||||
return IsCryptoCoinFuture(QuoteCurrency.Symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the security is a crypto coin future
|
||||
/// </summary>
|
||||
/// <param name="quoteCurrency">The security quote currency</param>
|
||||
/// <returns>True if the security is a crypto coin future</returns>
|
||||
private static bool IsCryptoCoinFuture(string quoteCurrency)
|
||||
{
|
||||
return quoteCurrency != "USDT" && quoteCurrency != "BUSD" && quoteCurrency != "USDC";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the securities symbol
|
||||
/// </summary>
|
||||
public static implicit operator Symbol(CryptoFuture security) => security.Symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// Crypto future exchange class - information and helper tools for Crypto future exchange properties
|
||||
/// </summary>
|
||||
/// <seealso cref="SecurityExchange"/>
|
||||
public class CryptoFutureExchange : SecurityExchange
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CryptoFutureExchange"/> class using market hours
|
||||
/// derived from the market-hours-database for the Crypto future market
|
||||
/// </summary>
|
||||
public CryptoFutureExchange(string market)
|
||||
: base(MarketHoursDatabase.FromDataFolder().GetExchangeHours(market, null, SecurityType.CryptoFuture))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CryptoFutureExchange"/> class using the specified
|
||||
/// exchange hours to determine open/close times
|
||||
/// </summary>
|
||||
/// <param name="exchangeHours">Contains the weekly exchange schedule plus holidays</param>
|
||||
public CryptoFutureExchange(SecurityExchangeHours exchangeHours)
|
||||
: base(exchangeHours)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// Crypto Future holdings implementation of the base securities class
|
||||
/// </summary>
|
||||
/// <seealso cref="SecurityHolding"/>
|
||||
public class CryptoFutureHolding : SecurityHolding
|
||||
{
|
||||
/// <summary>
|
||||
/// Crypto Future Holding Class constructor
|
||||
/// </summary>
|
||||
/// <param name="security">The crypto future security being held</param>
|
||||
/// <param name="currencyConverter">A currency converter instance</param>
|
||||
public CryptoFutureHolding(Security security, ICurrencyConverter currencyConverter)
|
||||
: base(security, currencyConverter)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total value of the specified <paramref name="quantity"/> of shares of this security
|
||||
/// in the account currency
|
||||
/// </summary>
|
||||
/// <param name="quantity">The quantity of shares</param>
|
||||
/// <param name="price">The current price</param>
|
||||
/// <returns>The value of the quantity of shares in the account currency</returns>
|
||||
public override ConvertibleCashAmount GetQuantityValue(decimal quantity, decimal price)
|
||||
{
|
||||
if (Symbol.ID.Market == Market.DYDX)
|
||||
{
|
||||
// common math quantity * quote price
|
||||
return base.GetQuantityValue(quantity, price);
|
||||
}
|
||||
var cryptoFuture = (CryptoFuture)Security;
|
||||
|
||||
Cash cash;
|
||||
decimal notionalPositionValue;
|
||||
// We could check quote currency or the contract multiplier being 1
|
||||
if (!cryptoFuture.IsCryptoCoinFuture())
|
||||
{
|
||||
// https://www.binance.com/en/support/faq/how-to-calculate-cost-required-to-open-a-position-in-perpetual-futures-contracts-87fa7ee33b574f7084d42bd2ce2e463b
|
||||
// example BTCUSDT: (9,253.30 * 1 BTC) = 9,253.3 USDT
|
||||
notionalPositionValue = price * quantity * cryptoFuture.SymbolProperties.ContractMultiplier;
|
||||
|
||||
// USDT is the QUOTE currency we will need to convert it into account currency
|
||||
cash = cryptoFuture.QuoteCurrency;
|
||||
}
|
||||
else
|
||||
{
|
||||
// https://www.binance.com/en/support/faq/leverage-and-margin-in-coin-margined-futures-contracts-be2c7d9d95b04a7e8044ed02dd7dfe5c
|
||||
// example BTCUSD: [ (10*100 USD) / 9,800 USD ] = 0.10204 BTC
|
||||
notionalPositionValue = quantity * cryptoFuture.SymbolProperties.ContractMultiplier / price;
|
||||
|
||||
// BTC is the BASE currency we will need to convert it into account currency
|
||||
cash = cryptoFuture.BaseCurrency;
|
||||
}
|
||||
|
||||
return new ConvertibleCashAmount(notionalPositionValue, cash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// The crypto future margin model which supports both Coin and USDT futures
|
||||
/// </summary>
|
||||
public class CryptoFutureMarginModel : SecurityMarginModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
/// <param name="leverage">The leverage to use, used on initial margin requirements, default 25x</param>
|
||||
/// <param name="maintenanceMarginRate">The maintenance margin rate, default 5%</param>
|
||||
/// <param name="maintenanceAmount">The maintenance amount which will reduce maintenance margin requirements, default 0</param>
|
||||
[Obsolete("This constructor is deprecated, please use the overload without maintenanceMarginRate and maintenanceAmount parameters.")]
|
||||
public CryptoFutureMarginModel(decimal leverage, decimal maintenanceMarginRate = 0.05m, decimal maintenanceAmount = 0)
|
||||
: base(leverage, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance
|
||||
/// </summary>
|
||||
/// <param name="leverage">The leverage to use, used on initial margin requirements, default 25x</param>
|
||||
public CryptoFutureMarginModel(decimal leverage = 25)
|
||||
: base(leverage, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the margin currently alloted to the specified holding.
|
||||
/// </summary>
|
||||
/// <param name="parameters">An object containing the security</param>
|
||||
/// <returns>The maintenance margin required for the option</returns>
|
||||
public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
|
||||
{
|
||||
return new MaintenanceMargin(GetInitialMarginRequirement(new InitialMarginParameters(parameters.Security, parameters.Quantity)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The margin that must be held in order to increase the position by the provided quantity
|
||||
/// </summary>
|
||||
/// <param name="parameters">An object containing the security and quantity of shares</param>
|
||||
/// <returns>The initial margin required for the option (i.e. the equity required to enter a position for this option)</returns>
|
||||
public override InitialMargin GetInitialMarginRequirement(InitialMarginParameters parameters)
|
||||
{
|
||||
var security = parameters.Security;
|
||||
var quantity = parameters.Quantity;
|
||||
if (security?.GetLastData() == null || quantity == 0m)
|
||||
{
|
||||
return InitialMargin.Zero;
|
||||
}
|
||||
|
||||
var positionValue = security.Holdings.GetQuantityValue(quantity, security.Price);
|
||||
var marginRequirementInCollateral = Math.Abs(positionValue.Amount) / GetLeverage(security);
|
||||
|
||||
return new InitialMargin(marginRequirementInCollateral * positionValue.Cash.ConversionRate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the margin cash available for a trade
|
||||
/// </summary>
|
||||
/// <param name="portfolio">The algorithm's portfolio</param>
|
||||
/// <param name="security">The security to be traded</param>
|
||||
/// <param name="direction">The direction of the trade</param>
|
||||
/// <returns>The margin available for the trade</returns>
|
||||
/// <remarks>What we do specially here is that instead of using the total portfolio value as potential margin remaining we only consider the collateral currency</remarks>
|
||||
protected override decimal GetMarginRemaining(SecurityPortfolioManager portfolio, Security security, OrderDirection direction)
|
||||
{
|
||||
var collateralCurrency = GetCollateralCash(security);
|
||||
var totalCollateralCurrency = GetTotalCollateralAmount(portfolio, security, collateralCurrency);
|
||||
var result = totalCollateralCurrency;
|
||||
|
||||
foreach (var kvp in portfolio.Where(holdings => holdings.Value.Invested && holdings.Value.Type == SecurityType.CryptoFuture && holdings.Value.Symbol != security.Symbol))
|
||||
{
|
||||
var otherCryptoFuture = portfolio.Securities[kvp.Key];
|
||||
// check if we share the collateral
|
||||
if (SharesCollateral(portfolio, collateralCurrency, otherCryptoFuture))
|
||||
{
|
||||
// we reduce the available collateral based on total usage of all other positions too
|
||||
result -= otherCryptoFuture.BuyingPowerModel.GetMaintenanceMargin(MaintenanceMarginParameters.ForCurrentHoldings(otherCryptoFuture));
|
||||
}
|
||||
}
|
||||
|
||||
if (direction != OrderDirection.Hold)
|
||||
{
|
||||
var holdings = security.Holdings;
|
||||
//If the order is in the same direction as holdings, our remaining cash is our cash
|
||||
//In the opposite direction, our remaining cash is 2 x current value of assets + our cash
|
||||
if (holdings.IsLong)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case OrderDirection.Sell:
|
||||
result +=
|
||||
// portion of margin to close the existing position
|
||||
this.GetMaintenanceMargin(security) +
|
||||
// portion of margin to open the new position
|
||||
this.GetInitialMarginRequirement(security, security.Holdings.AbsoluteQuantity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (holdings.IsShort)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case OrderDirection.Buy:
|
||||
result +=
|
||||
// portion of margin to close the existing position
|
||||
this.GetMaintenanceMargin(security) +
|
||||
// portion of margin to open the new position
|
||||
this.GetInitialMarginRequirement(security, security.Holdings.AbsoluteQuantity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result -= totalCollateralCurrency * RequiredFreeBuyingPowerPercent;
|
||||
// convert into account currency
|
||||
result *= collateralCurrency.ConversionRate;
|
||||
return result < 0 ? 0 : result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given security shares collateral with another crypto future.
|
||||
/// </summary>
|
||||
/// <param name="portfolio">The algorithm's portfolio</param>
|
||||
/// <param name="collateralCurrency">The collateral cash for the current security</param>
|
||||
/// <param name="otherCryptoFuture">The other crypto future security to check</param>
|
||||
/// <returns>True if both securities share the same collateral</returns>
|
||||
protected virtual bool SharesCollateral(SecurityPortfolioManager portfolio, Cash collateralCurrency, Security otherCryptoFuture)
|
||||
{
|
||||
return collateralCurrency == GetCollateralCash(otherCryptoFuture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to determine what's the collateral currency for the given crypto future
|
||||
/// </summary>
|
||||
private static Cash GetCollateralCash(Security security)
|
||||
{
|
||||
var cryptoFuture = (CryptoFuture)security;
|
||||
|
||||
var collateralCurrency = cryptoFuture.BaseCurrency;
|
||||
if (!cryptoFuture.IsCryptoCoinFuture())
|
||||
{
|
||||
collateralCurrency = cryptoFuture.QuoteCurrency;
|
||||
}
|
||||
|
||||
return collateralCurrency;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total collateral amount for the given crypto future position.
|
||||
/// The base implementation returns only the primary collateral amount.
|
||||
/// Override in subclasses to include supplementary collateral currencies.
|
||||
/// </summary>
|
||||
/// <param name="portfolio">The algorithm's portfolio</param>
|
||||
/// <param name="security">The crypto future security</param>
|
||||
/// <param name="primaryCollateral">The primary collateral cash (e.g. USDT for non-coin futures, BTC for coin futures)</param>
|
||||
/// <returns>Total collateral amount in terms of the primary collateral currency</returns>
|
||||
protected virtual decimal GetTotalCollateralAmount(SecurityPortfolioManager portfolio, Security security, Cash primaryCollateral)
|
||||
{
|
||||
return primaryCollateral.Amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Securities.CryptoFuture
|
||||
{
|
||||
/// <summary>
|
||||
/// The responsibility of this model is to apply future funding rate cash flows to the portfolio based on open positions
|
||||
/// </summary>
|
||||
public class dYdXFutureMarginInterestRateModel : BinanceFutureMarginInterestRateModel
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user