diff --git a/Algorithm.CSharp/DYDXCryptoFuturesRegressionAlgorithm.cs b/Algorithm.CSharp/DYDXCryptoFuturesRegressionAlgorithm.cs new file mode 100644 index 000000000000..f00466008b76 --- /dev/null +++ b/Algorithm.CSharp/DYDXCryptoFuturesRegressionAlgorithm.cs @@ -0,0 +1,128 @@ +/* + * 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; +using QuantConnect.Interfaces; +using System.Collections.Generic; +using QuantConnect.Securities.CryptoFuture; + +namespace QuantConnect.Algorithm.CSharp +{ + /// + /// Regression algorithm asserting DYDX Crypto Future support + /// + public class DYDXCryptoFuturesRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition + { + private CryptoFuture _cryptoFuture; + + /// + /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. + /// + public override void Initialize() + { + SetStartDate(2026, 1, 1); + SetEndDate(2026, 1, 1); + + SetBrokerageModel(Brokerages.BrokerageName.DYDX, AccountType.Margin); + _cryptoFuture = AddCryptoFuture("BTCUSD"); + } + + /// + /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. + /// + /// Slice object keyed by symbol containing the stock data + public override void OnData(Slice slice) + { + if (!Portfolio.Invested) + { + Buy("BTCUSD", 1); + } + else + { + if (Math.Abs(Portfolio.TotalFees - Portfolio.TotalHoldingsValue * 0.0005m) > 1 + || Math.Abs(Portfolio.TotalFees - _cryptoFuture.Price * 0.0005m) > 1) + { + throw new RegressionTestException("Unexpected fees value!"); + } + if (Math.Abs(Portfolio.TotalHoldingsValue - _cryptoFuture.Price) > 1) + { + throw new RegressionTestException("Unexpected holdings value!"); + } + Quit(); + } + } + + /// + /// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm. + /// + public bool CanRunLocally { get; } = true; + + /// + /// This is used by the regression test system to indicate which languages this algorithm is written in. + /// + public List Languages { get; } = new() { Language.CSharp }; + + /// + /// Data Points count of all timeslices of algorithm + /// + public long DataPoints => 5; + + /// + /// Data Points count of the algorithm history + /// + public int AlgorithmHistoryDataPoints => 15; + + /// + /// Final status of the algorithm + /// + public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed; + + /// + /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm + /// + public Dictionary ExpectedStatistics => new Dictionary + { + {"Total Orders", "1"}, + {"Average Win", "0%"}, + {"Average Loss", "0%"}, + {"Compounding Annual Return", "0%"}, + {"Drawdown", "0%"}, + {"Expectancy", "0"}, + {"Start Equity", "100000"}, + {"End Equity", "99929.57"}, + {"Net Profit", "0%"}, + {"Sharpe Ratio", "0"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "0%"}, + {"Loss Rate", "0%"}, + {"Win Rate", "0%"}, + {"Profit-Loss Ratio", "0"}, + {"Alpha", "0"}, + {"Beta", "0"}, + {"Annual Standard Deviation", "0"}, + {"Annual Variance", "0"}, + {"Information Ratio", "0"}, + {"Tracking Error", "0"}, + {"Treynor Ratio", "0"}, + {"Total Fees", "$43.71"}, + {"Estimated Strategy Capacity", "$33000.00"}, + {"Lowest Capacity Asset", "BTCUSD 38Z"}, + {"Portfolio Turnover", "87.48%"}, + {"Drawdown Recovery", "0"}, + {"OrderListHash", "637a937cda83ce88d29a3b279832401d"} + }; + } +} diff --git a/Common/Orders/Fees/dYdXFeeModel.cs b/Common/Orders/Fees/dYdXFeeModel.cs index 4a9163c5aa74..8fcd92ac18ec 100644 --- a/Common/Orders/Fees/dYdXFeeModel.cs +++ b/Common/Orders/Fees/dYdXFeeModel.cs @@ -14,7 +14,6 @@ */ using QuantConnect.Securities; -using QuantConnect.Util; namespace QuantConnect.Orders.Fees; diff --git a/Common/Securities/CryptoFuture/CryptoFutureHolding.cs b/Common/Securities/CryptoFuture/CryptoFutureHolding.cs index 3d0d502c8003..77cdcc5c85b6 100644 --- a/Common/Securities/CryptoFuture/CryptoFutureHolding.cs +++ b/Common/Securities/CryptoFuture/CryptoFutureHolding.cs @@ -40,6 +40,11 @@ public CryptoFutureHolding(Security security, ICurrencyConverter currencyConvert /// The value of the quantity of shares in the account currency 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; diff --git a/Data/cryptofuture/dydx/minute/btcusd/20260101_quote.zip b/Data/cryptofuture/dydx/minute/btcusd/20260101_quote.zip new file mode 100644 index 000000000000..765c76f9107b Binary files /dev/null and b/Data/cryptofuture/dydx/minute/btcusd/20260101_quote.zip differ diff --git a/Data/cryptofuture/dydx/minute/btcusd/20260101_trade.zip b/Data/cryptofuture/dydx/minute/btcusd/20260101_trade.zip new file mode 100644 index 000000000000..acb1ba38334b Binary files /dev/null and b/Data/cryptofuture/dydx/minute/btcusd/20260101_trade.zip differ