Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,4 @@ Research/Notebooks
#Docker result files
Results/
QuantConnect.Lean.sln.DotSettings
DataLibraries/
94 changes: 94 additions & 0 deletions Algorithm.CSharp/Demonstration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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.Algorithm;
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
using QuantConnect;
using QuantConnect.Data;
using QuantConnect.Securities.Future;
using QuantConnect.Util;
using System;
using System.Linq;

namespace QuantConnect.Algorithm.CSharp
{
public class DatabentoFuturesTestAlgorithm : QCAlgorithm
{
private Future _es;

public override void Initialize()
{
Log("Algorithm Initialize");

SetStartDate(2025, 10, 1);
SetEndDate(2025, 10, 16);
SetCash(100000);

var exp = new DateTime(2025, 12, 19);
var symbol = QuantConnect.Symbol.CreateFuture("ES", Market.CME, exp);
//_es = AddFutureContract(symbol, Resolution.Tick, true, 1, true);
_es = AddFutureContract(symbol, Resolution.Second, true, 1, true);
Log($"_es: {_es}");

var history = History<TradeBar>(_es.Symbol, 10, Resolution.Minute).ToList();

Log($"History returned {history.Count} bars");

foreach (var bar in history)
{
Log($"History Bar: {bar.Time} - O:{bar.Open} H:{bar.High} L:{bar.Low} C:{bar.Close} V:{bar.Volume}");
}

}

public override void OnData(Slice slice)
{
if (!slice.HasData)
{
Log("Slice has no data");
return;
}

Log($"OnData: Slice has {slice.Count} data points");

// For Tick resolution, check Ticks collection
if (slice.Ticks.ContainsKey(_es.Symbol))
{
var ticks = slice.Ticks[_es.Symbol];
Log($"Received {ticks.Count} ticks for {_es.Symbol}");

foreach (var tick in ticks)
{
if (tick.TickType == TickType.Trade)
{
Log($"Trade Tick - Price: {tick.Price}, Quantity: {tick.Quantity}, Time: {tick.Time}");
}
else if (tick.TickType == TickType.Quote)
{
Log($"Quote Tick - Bid: {tick.BidPrice}x{tick.BidSize}, Ask: {tick.AskPrice}x{tick.AskSize}, Time: {tick.Time}");
}
}
}

// Access OHLCV bars
foreach (var bar in slice.Bars.Values)
{
Log($"OHLCV BAR: {bar.Symbol.Value} - O: {bar.Open}, H: {bar.High}, L: {bar.Low}, C: {bar.Close}, V: {bar.Volume}");
}
}
}
}
2 changes: 1 addition & 1 deletion Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.Algorithm.CSharp</RootNamespace>
<AssemblyName>QuantConnect.Algorithm.CSharp</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.Algorithm.Framework</RootNamespace>
<AssemblyName>QuantConnect.Algorithm.Framework</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
Expand Down
2 changes: 1 addition & 1 deletion Algorithm.Python/QuantConnect.Algorithm.Python.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.Algorithm.Python</RootNamespace>
<AssemblyName>QuantConnect.Algorithm.Python</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<OutputPath>bin\$(Configuration)\</OutputPath>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
Expand Down
2 changes: 1 addition & 1 deletion Algorithm/QuantConnect.Algorithm.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.Algorithm</RootNamespace>
<AssemblyName>QuantConnect.Algorithm</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
Expand Down
2 changes: 1 addition & 1 deletion AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.AlgorithmFactory</RootNamespace>
<AssemblyName>QuantConnect.AlgorithmFactory</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
Expand Down
2 changes: 1 addition & 1 deletion Api/QuantConnect.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.Api</RootNamespace>
<AssemblyName>QuantConnect.Api</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
Expand Down
2 changes: 1 addition & 1 deletion Brokerages/QuantConnect.Brokerages.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<RootNamespace>QuantConnect.Brokerages</RootNamespace>
<AssemblyName>QuantConnect.Brokerages</AssemblyName>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputPath>bin\$(Configuration)\</OutputPath>
Expand Down
7 changes: 6 additions & 1 deletion Common/Brokerages/BrokerageName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ public enum BrokerageName
/// <summary>
/// Transaction and submit/execution rules will use dYdX models
/// </summary>
dYdX
dYdX,

/// <summary>
/// Transaction and submit/execution rules will use Tradovate models
/// </summary>
Tradovate
}
}
161 changes: 161 additions & 0 deletions Common/Brokerages/TradovateBrokerageModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* 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.Collections.Generic;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.TimeInForces;
using QuantConnect.Securities;
using QuantConnect.Util;

namespace QuantConnect.Brokerages
{
/// <summary>
/// Provides an implementation of <see cref="IBrokerageModel"/> specific to Tradovate brokerage.
/// Tradovate is a futures-focused brokerage supporting CME Group products.
/// </summary>
public class TradovateBrokerageModel : DefaultBrokerageModel
{
/// <summary>
/// The default markets for Tradovate brokerage
/// </summary>
public new static readonly IReadOnlyDictionary<SecurityType, string> DefaultMarketMap = new Dictionary<SecurityType, string>
{
{ SecurityType.Future, Market.CME },
{ SecurityType.FutureOption, Market.CME }
}.ToReadOnlyDictionary();

/// <summary>
/// Order types supported by Tradovate
/// </summary>
protected virtual HashSet<OrderType> SupportedOrderTypes { get; } = new HashSet<OrderType>
{
OrderType.Market,
OrderType.Limit,
OrderType.StopMarket,
OrderType.StopLimit,
OrderType.TrailingStop
};

/// <summary>
/// Time in force types supported by Tradovate
/// </summary>
protected virtual Type[] SupportedTimeInForces { get; } =
{
typeof(GoodTilCanceledTimeInForce),
typeof(DayTimeInForce)
};

/// <summary>
/// Initializes a new instance of the <see cref="TradovateBrokerageModel"/> class
/// </summary>
/// <param name="accountType">The type of account to be modeled, defaults to <see cref="AccountType.Margin"/></param>
public TradovateBrokerageModel(AccountType accountType = AccountType.Margin)
: base(accountType)
{
}

/// <summary>
/// Gets a map of the default markets to be used for each security type
/// </summary>
public override IReadOnlyDictionary<SecurityType, string> DefaultMarkets => DefaultMarketMap;

/// <summary>
/// Returns true if the brokerage could accept this order. This takes into account
/// order type, security type, and order size limits.
/// </summary>
/// <param name="security">The security being ordered</param>
/// <param name="order">The order to be processed</param>
/// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
/// <returns>True if the brokerage could process the order, false otherwise</returns>
public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
{
message = null;

// Validate security type - Tradovate only supports futures
if (security.Type != SecurityType.Future && security.Type != SecurityType.FutureOption)
{
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
$"Tradovate does not support {security.Type} security type. Only Future and FutureOption are supported.");
return false;
}

// Validate order type
if (!SupportedOrderTypes.Contains(order.Type))
{
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
$"Tradovate does not support {order.Type} order type. " +
$"Supported order types are: {string.Join(", ", SupportedOrderTypes)}");
return false;
}

// Validate time in force
if (!IsValidTimeInForce(order.TimeInForce))
{
message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
$"Tradovate does not support {order.TimeInForce.GetType().Name} time in force. " +
"Supported time in force types are: Day, GoodTilCanceled");
return false;
}

return base.CanSubmitOrder(security, order, out message);
}

/// <summary>
/// Returns true if the brokerage would allow updating the order as specified by the request.
/// Tradovate supports order modifications via the order/modifyorder endpoint.
/// </summary>
/// <param name="security">The security of the order</param>
/// <param name="order">The order to be updated</param>
/// <param name="request">The requested update to be made to the order</param>
/// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
/// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
{
message = null;

// Tradovate supports order modifications
// Note: When modifying orders, the timeInForce must match the existing order's setting
return true;
}

/// <summary>
/// Gets a new fee model that represents Tradovate's fee structure
/// </summary>
/// <param name="security">The security to get a fee model for</param>
/// <returns>The new fee model for this brokerage</returns>
public override IFeeModel GetFeeModel(Security security)
{
return new TradovateFeeModel();
}

/// <summary>
/// Validates that the time in force is supported by Tradovate
/// </summary>
private bool IsValidTimeInForce(TimeInForce timeInForce)
{
var timeInForceType = timeInForce.GetType();
foreach (var supportedType in SupportedTimeInForces)
{
if (supportedType == timeInForceType)
{
return true;
}
}
return false;
}
}
}
Loading