From a9dcc7b6d137b85bca87696879138241a2d537ed Mon Sep 17 00:00:00 2001
From: Martin Molinero <martin.molinero1@gmail.com>
Date: Wed, 11 Dec 2024 17:58:12 -0300
Subject: [PATCH] Dotnet 9

---
 .github/workflows/api-tests.yml                 | 11 ++++++++---
 .github/workflows/gh-actions.yml                | 12 +++++++++---
 .github/workflows/rebase-org-branches.yml       |  2 +-
 .github/workflows/regression-tests.yml          | 11 ++++++++---
 .github/workflows/report-generator.yml          | 11 ++++++++---
 .github/workflows/research-regression-tests.yml | 11 ++++++++---
 .github/workflows/virtual-environments.yml      | 11 ++++++++---
 .../QuantConnect.Algorithm.CSharp.csproj        |  2 +-
 .../QuantConnect.Algorithm.Framework.csproj     |  2 +-
 .../CallbackCommandRegressionAlgorithm.py       |  6 +++---
 .../QuantConnect.Algorithm.Python.csproj        |  2 +-
 Algorithm/QuantConnect.Algorithm.csproj         |  2 +-
 .../QuantConnect.AlgorithmFactory.csproj        |  2 +-
 Api/QuantConnect.Api.csproj                     |  2 +-
 Brokerages/QuantConnect.Brokerages.csproj       |  2 +-
 Common/Brokerages/BybitBrokerageModel.cs        |  1 +
 Common/Extensions.cs                            |  7 ++++++-
 Common/QuantConnect.csproj                      |  2 +-
 Common/Util/LinqExtensions.cs                   | 12 ------------
 Compression/QuantConnect.Compression.csproj     |  2 +-
 Configuration/QuantConnect.Configuration.csproj |  2 +-
 DockerfileJupyter                               |  3 ---
 ...nnect.DownloaderDataProvider.Launcher.csproj |  2 +-
 Engine/DataFeeds/DataQueueHandlerManager.cs     | 17 +++++++++++------
 .../Enumerators/LiveSubscriptionEnumerator.cs   |  9 ++++++++-
 .../DataFeeds/Enumerators/RefreshEnumerator.cs  |  5 ++++-
 Engine/QuantConnect.Lean.Engine.csproj          |  2 +-
 Indicators/QuantConnect.Indicators.csproj       |  2 +-
 Launcher/QuantConnect.Lean.Launcher.csproj      |  2 +-
 Logging/QuantConnect.Logging.csproj             |  2 +-
 Messaging/QuantConnect.Messaging.csproj         |  2 +-
 .../QuantConnect.Optimizer.Launcher.csproj      |  2 +-
 Optimizer/QuantConnect.Optimizer.csproj         |  2 +-
 Queues/QuantConnect.Queues.csproj               |  2 +-
 Report/QuantConnect.Report.csproj               |  2 +-
 Research/QuantConnect.Research.csproj           |  2 +-
 Tests/Api/AuthenticationTests.cs                |  2 +-
 .../PythonIndicatorNoinheritanceTests.cs        |  2 +-
 .../PythonIndicatorNoinheritanceTestsLegacy.cs  |  2 +-
 Tests/Indicators/PythonIndicatorTests.cs        |  2 +-
 Tests/Indicators/TestHelper.cs                  |  2 +-
 Tests/QuantConnect.Tests.csproj                 | 13 ++++++++++---
 Tests/app.config                                | 11 -----------
 ToolBox/QuantConnect.ToolBox.csproj             |  2 +-
 44 files changed, 120 insertions(+), 87 deletions(-)
 delete mode 100644 Tests/app.config

diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml
index a9361f687038..b3965a54960d 100644
--- a/.github/workflows/api-tests.yml
+++ b/.github/workflows/api-tests.yml
@@ -9,14 +9,19 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     # Only run on push events (not on pull_request) for security reasons in order to be able to use secrets
     if: ${{ github.event_name == 'push' }}
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      - name: Free space
-        run: df -h && rm -rf /usr/share/dotnet && sudo rm -rf /usr/local/lib/android && sudo rm -rf /opt/ghc && rm -rf /opt/hostedtoolcache* && df -h
+      - name: Liberate disk space
+        uses: jlumbroso/free-disk-space@main
+        with:
+          tool-cache: true
+          large-packages: false
+          docker-images: false
+          swap-storage: false
       - name: Run API Tests
         uses: addnab/docker-run-action@v3
         with:
diff --git a/.github/workflows/gh-actions.yml b/.github/workflows/gh-actions.yml
index fd4345487441..1e69c304cbaa 100644
--- a/.github/workflows/gh-actions.yml
+++ b/.github/workflows/gh-actions.yml
@@ -9,12 +9,18 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      - name: Free space
-        run: df -h && rm -rf /usr/share/dotnet && sudo rm -rf /usr/local/lib/android && sudo rm -rf /opt/ghc && rm -rf /opt/hostedtoolcache* && df -h
+
+      - name: Liberate disk space
+        uses: jlumbroso/free-disk-space@main
+        with:
+          tool-cache: true
+          large-packages: false
+          docker-images: false
+          swap-storage: false
 
       - uses: addnab/docker-run-action@v3
         with:
diff --git a/.github/workflows/rebase-org-branches.yml b/.github/workflows/rebase-org-branches.yml
index a5f95a522213..aaaa1c4e2b6f 100644
--- a/.github/workflows/rebase-org-branches.yml
+++ b/.github/workflows/rebase-org-branches.yml
@@ -7,7 +7,7 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     steps:
       - uses: actions/checkout@v2
         with:
diff --git a/.github/workflows/regression-tests.yml b/.github/workflows/regression-tests.yml
index a8891dc2fff3..130e72ccd2e9 100644
--- a/.github/workflows/regression-tests.yml
+++ b/.github/workflows/regression-tests.yml
@@ -9,12 +9,17 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      - name: Free space
-        run: df -h && rm -rf /usr/share/dotnet && sudo rm -rf /usr/local/lib/android && sudo rm -rf /opt/ghc && rm -rf /opt/hostedtoolcache* && df -h
+      - name: Liberate disk space
+        uses: jlumbroso/free-disk-space@main
+        with:
+          tool-cache: true
+          large-packages: false
+          docker-images: false
+          swap-storage: false
 
       - uses: addnab/docker-run-action@v3
         with:
diff --git a/.github/workflows/report-generator.yml b/.github/workflows/report-generator.yml
index e50a885c4f6e..718693575cf1 100644
--- a/.github/workflows/report-generator.yml
+++ b/.github/workflows/report-generator.yml
@@ -9,12 +9,17 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      - name: Free space
-        run: df -h && rm -rf /usr/share/dotnet && sudo rm -rf /usr/local/lib/android && sudo rm -rf /opt/ghc && rm -rf /opt/hostedtoolcache* && df -h
+      - name: Liberate disk space
+        uses: jlumbroso/free-disk-space@main
+        with:
+          tool-cache: true
+          large-packages: false
+          docker-images: false
+          swap-storage: false
 
       - uses: addnab/docker-run-action@v3
         with:
diff --git a/.github/workflows/research-regression-tests.yml b/.github/workflows/research-regression-tests.yml
index 4b300feeb0e5..8e55b8666cb3 100644
--- a/.github/workflows/research-regression-tests.yml
+++ b/.github/workflows/research-regression-tests.yml
@@ -9,12 +9,17 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      - name: Free space
-        run: df -h && rm -rf /usr/share/dotnet && sudo rm -rf /usr/local/lib/android && sudo rm -rf /opt/ghc && rm -rf /opt/hostedtoolcache* && df -h
+      - name: Liberate disk space
+        uses: jlumbroso/free-disk-space@main
+        with:
+          tool-cache: true
+          large-packages: false
+          docker-images: false
+          swap-storage: false
 
       - uses: addnab/docker-run-action@v3
         with:
diff --git a/.github/workflows/virtual-environments.yml b/.github/workflows/virtual-environments.yml
index c840aefd9b4e..22f876a8abd6 100644
--- a/.github/workflows/virtual-environments.yml
+++ b/.github/workflows/virtual-environments.yml
@@ -9,12 +9,17 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-24.04
     steps:
       - name: Checkout
         uses: actions/checkout@v2
-      - name: Free space
-        run: df -h && rm -rf /usr/share/dotnet && sudo rm -rf /usr/local/lib/android && sudo rm -rf /opt/ghc && rm -rf /opt/hostedtoolcache* && df -h
+      - name: Liberate disk space
+        uses: jlumbroso/free-disk-space@main
+        with:
+          tool-cache: true
+          large-packages: false
+          docker-images: false
+          swap-storage: false
 
       - uses: addnab/docker-run-action@v3
         with:
diff --git a/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj b/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
index bf9c3ff262da..3b86b148aaec 100644
--- a/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
+++ b/Algorithm.CSharp/QuantConnect.Algorithm.CSharp.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Algorithm.CSharp</RootNamespace>
     <AssemblyName>QuantConnect.Algorithm.CSharp</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj b/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
index fa1f265c6a54..84f5c496f0a5 100644
--- a/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
+++ b/Algorithm.Framework/QuantConnect.Algorithm.Framework.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Algorithm.Framework</RootNamespace>
     <AssemblyName>QuantConnect.Algorithm.Framework</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/Algorithm.Python/CallbackCommandRegressionAlgorithm.py b/Algorithm.Python/CallbackCommandRegressionAlgorithm.py
index 094b86b158cd..6fe1f06b9433 100644
--- a/Algorithm.Python/CallbackCommandRegressionAlgorithm.py
+++ b/Algorithm.Python/CallbackCommandRegressionAlgorithm.py
@@ -76,7 +76,7 @@ def initialize(self):
         bool_command.something_else = { "Property": 10 }
         bool_command.array_test = [ "SPY", "BTCUSD" ]
         link = self.link(bool_command)
-        if "&command[array_test][0]=SPY&command[array_test][1]=BTCUSD&command[result]=True&command[something_else][Property]=10&command[$type]=BoolCommand" not in link:
+        if "&command%5barray_test%5d%5b0%5d=SPY&command%5barray_test%5d%5b1%5d=BTCUSD&command%5bresult%5d=True&command%5bsomething_else%5d%5bProperty%5d=10&command%5b%24type%5d=BoolCommand" not in link:
             raise ValueError(f'Invalid link was generated! {link}')
 
         potential_command = VoidCommand()
@@ -85,12 +85,12 @@ def initialize(self):
         potential_command.parameters = { "tag": "Signal X" }
 
         command_link = self.link(potential_command)
-        if "command[target][0]=BAC&command[quantity]=10&command[parameters][tag]=Signal+X&command[$type]=VoidCommand" not in command_link:
+        if "&command%5btarget%5d%5b0%5d=BAC&command%5bquantity%5d=10&command%5bparameters%5d%5btag%5d=Signal+X&command%5b%24type%5d=VoidCommand" not in command_link:
             raise ValueError(f'Invalid link was generated! {command_link}')
         self.notify.email("email@address", "Trade Command Event", f"Signal X trade\nFollow link to trigger: {command_link}")
 
         untyped_command_link = self.link({ "symbol": "SPY", "parameters": { "quantity": 10 } })
-        if "&command[symbol]=SPY&command[parameters][quantity]=10" not in untyped_command_link:
+        if "&command%5bsymbol%5d=SPY&command%5bparameters%5d%5bquantity%5d=10" not in untyped_command_link:
             raise ValueError(f'Invalid link was generated! {untyped_command_link}')
         self.notify.email("email@address", "Untyped Command Event", f"Signal Y trade\nFollow link to trigger: {untyped_command_link}")
 
diff --git a/Algorithm.Python/QuantConnect.Algorithm.Python.csproj b/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
index eab90b412dad..661aa9769e96 100644
--- a/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
+++ b/Algorithm.Python/QuantConnect.Algorithm.Python.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Algorithm.Python</RootNamespace>
     <AssemblyName>QuantConnect.Algorithm.Python</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <OutputPath>bin\$(Configuration)\</OutputPath>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
diff --git a/Algorithm/QuantConnect.Algorithm.csproj b/Algorithm/QuantConnect.Algorithm.csproj
index af31c8e90149..2f56b3634017 100644
--- a/Algorithm/QuantConnect.Algorithm.csproj
+++ b/Algorithm/QuantConnect.Algorithm.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Algorithm</RootNamespace>
     <AssemblyName>QuantConnect.Algorithm</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj b/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
index 29f454310502..1cfd0a97ade2 100644
--- a/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
+++ b/AlgorithmFactory/QuantConnect.AlgorithmFactory.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.AlgorithmFactory</RootNamespace>
     <AssemblyName>QuantConnect.AlgorithmFactory</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/Api/QuantConnect.Api.csproj b/Api/QuantConnect.Api.csproj
index 109e307ff0d2..ce418f98ec03 100644
--- a/Api/QuantConnect.Api.csproj
+++ b/Api/QuantConnect.Api.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Api</RootNamespace>
     <AssemblyName>QuantConnect.Api</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <RestorePackages>true</RestorePackages>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/Brokerages/QuantConnect.Brokerages.csproj b/Brokerages/QuantConnect.Brokerages.csproj
index cc3a37530ffb..d2222ce6e49a 100644
--- a/Brokerages/QuantConnect.Brokerages.csproj
+++ b/Brokerages/QuantConnect.Brokerages.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Brokerages</RootNamespace>
     <AssemblyName>QuantConnect.Brokerages</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Common/Brokerages/BybitBrokerageModel.cs b/Common/Brokerages/BybitBrokerageModel.cs
index 7c6a3e5295ac..d687ba88ad12 100644
--- a/Common/Brokerages/BybitBrokerageModel.cs
+++ b/Common/Brokerages/BybitBrokerageModel.cs
@@ -15,6 +15,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using QuantConnect.Benchmarks;
 using QuantConnect.Orders;
 using QuantConnect.Orders.Fees;
diff --git a/Common/Extensions.cs b/Common/Extensions.cs
index 98212d920edc..97670e5d54f2 100644
--- a/Common/Extensions.cs
+++ b/Common/Extensions.cs
@@ -4376,9 +4376,14 @@ public static decimal SafeDivision(this decimal numerator, decimal denominator,
             }
         }
 
+        /// <summary>
+        /// Retrieve a common custom data types from the given symbols if any
+        /// </summary>
+        /// <param name="symbols">The target symbols to search</param>
+        /// <returns>The custom data type or null</returns>
         public static Type GetCustomDataTypeFromSymbols(Symbol[] symbols)
         {
-            if (symbols.Any())
+            if (symbols.Length != 0)
             {
                 if (!SecurityIdentifier.TryGetCustomDataTypeInstance(symbols[0].ID.Symbol, out var dataType)
                     || symbols.Any(x => !SecurityIdentifier.TryGetCustomDataTypeInstance(x.ID.Symbol, out var customDataType) || customDataType != dataType))
diff --git a/Common/QuantConnect.csproj b/Common/QuantConnect.csproj
index 088dfd992381..ca20add0d8f8 100644
--- a/Common/QuantConnect.csproj
+++ b/Common/QuantConnect.csproj
@@ -2,7 +2,7 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AssemblyName>QuantConnect.Common</AssemblyName>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <RestorePackages>true</RestorePackages>
diff --git a/Common/Util/LinqExtensions.cs b/Common/Util/LinqExtensions.cs
index 2117e2d03b82..38c4ae89ec58 100644
--- a/Common/Util/LinqExtensions.cs
+++ b/Common/Util/LinqExtensions.cs
@@ -26,18 +26,6 @@ namespace QuantConnect.Util
     /// </summary>
     public static class LinqExtensions
     {
-        /// <summary>
-        /// Creates a dictionary enumerable of key value pairs
-        /// </summary>
-        /// <typeparam name="K">The key type</typeparam>
-        /// <typeparam name="V">The value type</typeparam>
-        /// <param name="enumerable">The IEnumerable of KeyValuePair instances to convert to a dictionary</param>
-        /// <returns>A dictionary holding the same data as the enumerable</returns>
-        public static Dictionary<K, V> ToDictionary<K, V>(this IEnumerable<KeyValuePair<K, V>> enumerable)
-        {
-            return enumerable.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
-        }
-
         /// <summary>
         /// Creates a new read-only dictionary from the key value pairs
         /// </summary>
diff --git a/Compression/QuantConnect.Compression.csproj b/Compression/QuantConnect.Compression.csproj
index 083aefed130b..c5f4799bfbed 100644
--- a/Compression/QuantConnect.Compression.csproj
+++ b/Compression/QuantConnect.Compression.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Compression</RootNamespace>
     <AssemblyName>QuantConnect.Compression</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Configuration/QuantConnect.Configuration.csproj b/Configuration/QuantConnect.Configuration.csproj
index f0ef8301c96a..9b27b189cedf 100644
--- a/Configuration/QuantConnect.Configuration.csproj
+++ b/Configuration/QuantConnect.Configuration.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Configuration</RootNamespace>
     <AssemblyName>QuantConnect.Configuration</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <RestorePackages>true</RestorePackages>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/DockerfileJupyter b/DockerfileJupyter
index 52c078e3e99c..669021394b67 100644
--- a/DockerfileJupyter
+++ b/DockerfileJupyter
@@ -37,9 +37,6 @@ ENV PYTHONPATH=${WORK}:${PYTHONPATH}
 RUN mkdir -p /root/.ipython/profile_default/startup/ && \
     ln -s /Lean/Launcher/bin/Debug/start.py /root/.ipython/profile_default/startup/start.py
 
-# conda libc is old and causes issues in research we want to use the hosts version which is updated
-RUN mkdir -p /opt/miniconda3/lib/ && ln -vsf /lib/x86_64-linux-gnu/libstdc++.so.6 /opt/miniconda3/lib/libstdc++.so.6
-
 RUN find ${WORK} -type f -not -name '*.py*' -not -name '*.xml' -not -name '*.exe.config' -not -name '*.exe' -not -name '*.so' -not -name '*.dll' -not -name '*.ipynb' -not -name '*.csx' -not -name 'QuantConnect.Lean.Launcher.runtimeconfig.json' -not -name 'decimal.py' -delete
 
 # Create initialize script
diff --git a/DownloaderDataProvider/QuantConnect.DownloaderDataProvider.Launcher.csproj b/DownloaderDataProvider/QuantConnect.DownloaderDataProvider.Launcher.csproj
index 54f42879b7ad..470a284a7adb 100644
--- a/DownloaderDataProvider/QuantConnect.DownloaderDataProvider.Launcher.csproj
+++ b/DownloaderDataProvider/QuantConnect.DownloaderDataProvider.Launcher.csproj
@@ -6,7 +6,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>QuantConnect.DownloaderDataProvider.Launcher</RootNamespace>
     <AssemblyName>QuantConnect.DownloaderDataProvider.Launcher</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Engine/DataFeeds/DataQueueHandlerManager.cs b/Engine/DataFeeds/DataQueueHandlerManager.cs
index 7a842f3ce957..715ae3a034f7 100644
--- a/Engine/DataFeeds/DataQueueHandlerManager.cs
+++ b/Engine/DataFeeds/DataQueueHandlerManager.cs
@@ -32,7 +32,6 @@ namespace QuantConnect.Lean.Engine.DataFeeds
     /// </summary>
     public class DataQueueHandlerManager : IDataQueueHandler, IDataQueueUniverseProvider
     {
-        private ITimeProvider _frontierTimeProvider;
         private readonly IAlgorithmSettings _algorithmSettings;
         private readonly Dictionary<SubscriptionDataConfig, Queue<IDataQueueHandler>> _dataConfigAndDataHandler = new();
 
@@ -44,6 +43,12 @@ public DataQueueHandlerManager(IAlgorithmSettings settings)
             _algorithmSettings = settings;
         }
 
+        /// <summary>
+        /// Frontier time provider to use
+        /// </summary>
+        /// <remarks>Protected for testing purposes</remarks>
+        protected ITimeProvider FrontierTimeProvider { get; set; }
+
         /// <summary>
         /// Collection of data queue handles being used
         /// </summary>
@@ -73,7 +78,7 @@ public IEnumerator<BaseData> Subscribe(SubscriptionDataConfig dataConfig, EventH
             {
                 // Emit ticks & custom data as soon as we get them, they don't need any kind of batching behavior applied to them
                 // only use the frontier time provider if we need to
-                var immediateEmission = dataConfig.Resolution == Resolution.Tick || dataConfig.IsCustomData || _frontierTimeProvider == null;
+                var immediateEmission = dataConfig.Resolution == Resolution.Tick || dataConfig.IsCustomData || FrontierTimeProvider == null;
                 var exchangeTimeZone = dataConfig.ExchangeTimeZone;
 
                 IEnumerator<BaseData> enumerator;
@@ -84,7 +89,7 @@ public IEnumerator<BaseData> Subscribe(SubscriptionDataConfig dataConfig, EventH
                             // let's only wake up the main thread if the data point is allowed to be emitted, else we could fill forward previous bar and not let this one through
                             var dataAvailable = eventArgs as NewDataAvailableEventArgs;
                             if (dataAvailable == null || dataAvailable.DataPoint == null
-                                || dataAvailable.DataPoint.EndTime.ConvertToUtc(exchangeTimeZone) <= _frontierTimeProvider.GetUtcNow())
+                                || dataAvailable.DataPoint.EndTime.ConvertToUtc(exchangeTimeZone) <= FrontierTimeProvider.GetUtcNow())
                             {
                                 newDataAvailableHandler?.Invoke(sender, eventArgs);
                             }
@@ -113,7 +118,7 @@ public IEnumerator<BaseData> Subscribe(SubscriptionDataConfig dataConfig, EventH
                         return enumerator;
                     }
 
-                    var utcStartTime = _frontierTimeProvider.GetUtcNow();
+                    var utcStartTime = FrontierTimeProvider.GetUtcNow();
 
                     var exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(dataConfig.Symbol.ID.Market, dataConfig.Symbol, dataConfig.Symbol.SecurityType);
                     if (LeanData.UseStrictEndTime(_algorithmSettings.DailyPreciseEndTime, dataConfig.Symbol, dataConfig.Increment, exchangeHours))
@@ -122,7 +127,7 @@ public IEnumerator<BaseData> Subscribe(SubscriptionDataConfig dataConfig, EventH
                         enumerator = new StrictDailyEndTimesEnumerator(enumerator, exchangeHours, utcStartTime.ConvertFromUtc(exchangeTimeZone));
                     }
 
-                    return new FrontierAwareEnumerator(enumerator, _frontierTimeProvider,
+                    return new FrontierAwareEnumerator(enumerator, FrontierTimeProvider,
                         new TimeZoneOffsetProvider(exchangeTimeZone, utcStartTime, Time.EndOfTime)
                     );
                 }
@@ -178,7 +183,7 @@ public void SetJob(LiveNodePacket job)
                 DataHandlers.Add(dataHandler);
             }
 
-            _frontierTimeProvider = InitializeFrontierTimeProvider();
+            FrontierTimeProvider = InitializeFrontierTimeProvider();
         }
 
         /// <summary>
diff --git a/Engine/DataFeeds/Enumerators/LiveSubscriptionEnumerator.cs b/Engine/DataFeeds/Enumerators/LiveSubscriptionEnumerator.cs
index 0c7ae62b4f0d..917f21ad2ea0 100644
--- a/Engine/DataFeeds/Enumerators/LiveSubscriptionEnumerator.cs
+++ b/Engine/DataFeeds/Enumerators/LiveSubscriptionEnumerator.cs
@@ -80,7 +80,14 @@ public bool MoveNext()
             }
 
             var result = _underlyingEnumerator.MoveNext();
-            _current = _underlyingEnumerator.Current;
+            if (result)
+            {
+                _current = _underlyingEnumerator.Current;
+            }
+            else
+            {
+                _current = null;
+            }
 
             if (_current != null && _current.Symbol != _requestedSymbol)
             {
diff --git a/Engine/DataFeeds/Enumerators/RefreshEnumerator.cs b/Engine/DataFeeds/Enumerators/RefreshEnumerator.cs
index 72fa82616bba..4c5954e0a744 100644
--- a/Engine/DataFeeds/Enumerators/RefreshEnumerator.cs
+++ b/Engine/DataFeeds/Enumerators/RefreshEnumerator.cs
@@ -60,7 +60,10 @@ public bool MoveNext()
             try
             {
                 moveNext = _enumerator.MoveNext();
-                _current = _enumerator.Current;
+                if (moveNext)
+                {
+                    _current = _enumerator.Current;
+                }
             }
             catch (IOException exception)
             {
diff --git a/Engine/QuantConnect.Lean.Engine.csproj b/Engine/QuantConnect.Lean.Engine.csproj
index 5d4f43417f73..090746c15c64 100644
--- a/Engine/QuantConnect.Lean.Engine.csproj
+++ b/Engine/QuantConnect.Lean.Engine.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Lean.Engine</RootNamespace>
     <AssemblyName>QuantConnect.Lean.Engine</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <RestorePackages>true</RestorePackages>
     <PublishUrl>publish\</PublishUrl>
diff --git a/Indicators/QuantConnect.Indicators.csproj b/Indicators/QuantConnect.Indicators.csproj
index b044f2f14180..1736fc61357d 100644
--- a/Indicators/QuantConnect.Indicators.csproj
+++ b/Indicators/QuantConnect.Indicators.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Indicators</RootNamespace>
     <AssemblyName>QuantConnect.Indicators</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Launcher/QuantConnect.Lean.Launcher.csproj b/Launcher/QuantConnect.Lean.Launcher.csproj
index be72e18761df..d948abec2537 100644
--- a/Launcher/QuantConnect.Lean.Launcher.csproj
+++ b/Launcher/QuantConnect.Lean.Launcher.csproj
@@ -5,7 +5,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>QuantConnect.Lean.Launcher</RootNamespace>
     <AssemblyName>QuantConnect.Lean.Launcher</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Logging/QuantConnect.Logging.csproj b/Logging/QuantConnect.Logging.csproj
index 4e4aa64991b8..7c932c6eb0d7 100644
--- a/Logging/QuantConnect.Logging.csproj
+++ b/Logging/QuantConnect.Logging.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Logging</RootNamespace>
     <AssemblyName>QuantConnect.Logging</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <RestorePackages>true</RestorePackages>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
diff --git a/Messaging/QuantConnect.Messaging.csproj b/Messaging/QuantConnect.Messaging.csproj
index a37c4480c6c2..76e896c2c550 100644
--- a/Messaging/QuantConnect.Messaging.csproj
+++ b/Messaging/QuantConnect.Messaging.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Messaging</RootNamespace>
     <AssemblyName>QuantConnect.Messaging</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Optimizer.Launcher/QuantConnect.Optimizer.Launcher.csproj b/Optimizer.Launcher/QuantConnect.Optimizer.Launcher.csproj
index ddd049dcad3d..7d740baac8bf 100644
--- a/Optimizer.Launcher/QuantConnect.Optimizer.Launcher.csproj
+++ b/Optimizer.Launcher/QuantConnect.Optimizer.Launcher.csproj
@@ -5,7 +5,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>QuantConnect.Optimizer.Launcher</RootNamespace>
     <AssemblyName>QuantConnect.Optimizer.Launcher</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Optimizer/QuantConnect.Optimizer.csproj b/Optimizer/QuantConnect.Optimizer.csproj
index fd82049e648d..d1ffd365f640 100644
--- a/Optimizer/QuantConnect.Optimizer.csproj
+++ b/Optimizer/QuantConnect.Optimizer.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Optimizer</RootNamespace>
     <AssemblyName>QuantConnect.Optimizer</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Queues/QuantConnect.Queues.csproj b/Queues/QuantConnect.Queues.csproj
index 013e69d19a75..83822ebc3894 100644
--- a/Queues/QuantConnect.Queues.csproj
+++ b/Queues/QuantConnect.Queues.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Queues</RootNamespace>
     <AssemblyName>QuantConnect.Queues</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
     <DocumentationFile>bin\$(Configuration)\QuantConnect.Queues.xml</DocumentationFile>
diff --git a/Report/QuantConnect.Report.csproj b/Report/QuantConnect.Report.csproj
index d35d6b1d3e04..a8ceb5240cdf 100644
--- a/Report/QuantConnect.Report.csproj
+++ b/Report/QuantConnect.Report.csproj
@@ -5,7 +5,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>QuantConnect.Report</RootNamespace>
     <AssemblyName>QuantConnect.Report</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>
diff --git a/Research/QuantConnect.Research.csproj b/Research/QuantConnect.Research.csproj
index e5bc65cd1c5e..c6c609a2cabf 100644
--- a/Research/QuantConnect.Research.csproj
+++ b/Research/QuantConnect.Research.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Research</RootNamespace>
     <AssemblyName>QuantConnect.Research</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <OutputPath>bin\$(Configuration)\</OutputPath>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
diff --git a/Tests/Api/AuthenticationTests.cs b/Tests/Api/AuthenticationTests.cs
index 495cc1969b46..c171b8809b68 100644
--- a/Tests/Api/AuthenticationTests.cs
+++ b/Tests/Api/AuthenticationTests.cs
@@ -45,7 +45,7 @@ public void PopulateQueryString()
             var queryString = HttpUtility.ParseQueryString(string.Empty);
             Authentication.PopulateQueryString(queryString, new[] { new KeyValuePair<string, object>("command", payload) });
 
-            Assert.AreEqual("command[SomeArray][0]=1&command[SomeArray][1]=2&command[SomeArray][2]=3&command[Symbol]=SPY&command[Parameters][Quantity]=10", queryString.ToString());
+            Assert.AreEqual("command%5bSomeArray%5d%5b0%5d=1&command%5bSomeArray%5d%5b1%5d=2&command%5bSomeArray%5d%5b2%5d=3&command%5bSymbol%5d=SPY&command%5bParameters%5d%5bQuantity%5d=10", queryString.ToString());
         }
     }
 }
diff --git a/Tests/Indicators/PythonIndicatorNoinheritanceTests.cs b/Tests/Indicators/PythonIndicatorNoinheritanceTests.cs
index f895a4f59de7..cafef8f5c64a 100644
--- a/Tests/Indicators/PythonIndicatorNoinheritanceTests.cs
+++ b/Tests/Indicators/PythonIndicatorNoinheritanceTests.cs
@@ -96,7 +96,7 @@ protected override void RunTestIndicator(IndicatorBase<IBaseData> indicator)
                     }
                     if (closeIndex * targetIndex < 0)
                     {
-                        Assert.Fail($"Didn't find one of 'Close' or '{line}' in the header: ", TestColumnName);
+                        Assert.Fail($"Didn't find one of 'Close' or '{TestColumnName}' in the header: {line}");
                     }
 
                     continue;
diff --git a/Tests/Indicators/PythonIndicatorNoinheritanceTestsLegacy.cs b/Tests/Indicators/PythonIndicatorNoinheritanceTestsLegacy.cs
index 662b144b0868..b247d37f0c96 100644
--- a/Tests/Indicators/PythonIndicatorNoinheritanceTestsLegacy.cs
+++ b/Tests/Indicators/PythonIndicatorNoinheritanceTestsLegacy.cs
@@ -95,7 +95,7 @@ protected override void RunTestIndicator(IndicatorBase<IBaseData> indicator)
                     }
                     if (closeIndex * targetIndex < 0)
                     {
-                        Assert.Fail($"Didn't find one of 'Close' or '{line}' in the header: ", TestColumnName);
+                        Assert.Fail($"Didn't find one of 'Close' or '{TestColumnName}' in the header: {line}");
                     }
 
                     continue;
diff --git a/Tests/Indicators/PythonIndicatorTests.cs b/Tests/Indicators/PythonIndicatorTests.cs
index b572219f7586..a2807ce13bd9 100644
--- a/Tests/Indicators/PythonIndicatorTests.cs
+++ b/Tests/Indicators/PythonIndicatorTests.cs
@@ -112,7 +112,7 @@ protected override void RunTestIndicator(IndicatorBase<IBaseData> indicator)
                     }
                     if (closeIndex * targetIndex < 0)
                     {
-                        Assert.Fail($"Didn't find one of 'Close' or '{line}' in the header: ", TestColumnName);
+                        Assert.Fail($"Didn't find one of 'Close' or '{TestColumnName}' in the header: {line}");
                     }
 
                     continue;
diff --git a/Tests/Indicators/TestHelper.cs b/Tests/Indicators/TestHelper.cs
index 21b08d17fd2b..0eac582ffde7 100644
--- a/Tests/Indicators/TestHelper.cs
+++ b/Tests/Indicators/TestHelper.cs
@@ -75,7 +75,7 @@ public static void TestIndicator(IndicatorBase<IndicatorDataPoint> indicator, st
             {
                 if (!(parts.ContainsKey("Close") && parts.ContainsKey(targetColumn)))
                 {
-                    Assert.Fail("Didn't find one of 'Close' or '{0}' in the header.", targetColumn);
+                    Assert.Fail($"Didn't find one of 'Close' or '{targetColumn}' in the header.");
                     break;
                 }
 
diff --git a/Tests/QuantConnect.Tests.csproj b/Tests/QuantConnect.Tests.csproj
index 88daa6e7d5f5..0a712089fda9 100644
--- a/Tests/QuantConnect.Tests.csproj
+++ b/Tests/QuantConnect.Tests.csproj
@@ -4,7 +4,7 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <RootNamespace>QuantConnect.Tests</RootNamespace>
     <AssemblyName>QuantConnect.Tests</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
@@ -45,13 +45,20 @@
     <PackageReference Include="NetMQ" Version="4.0.1.6" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
     <PackageReference Include="NodaTime" Version="3.0.5" />
-    <PackageReference Include="NUnit" Version="3.13.3" />
-    <PackageReference Include="NUnit3TestAdapter" Version="4.2.1">
+    <PackageReference Include="NUnit" Version="4.2.2" />
+    <PackageReference Include="NUnit3TestAdapter" Version="4.6.0">
       <PrivateAssets>all</PrivateAssets>
     </PackageReference>
     <PackageReference Include="protobuf-net" Version="3.1.33" />
     <PackageReference Include="RestSharp" Version="106.12.0" />
   </ItemGroup>
+  <ItemGroup>
+    <Using Include="NUnit.Framework.Legacy.ClassicAssert" Alias="Assert" />
+    <Using Include="NUnit.Framework.Legacy.CollectionAssert" Alias="CollectionAssert" />
+    <Using Include="NUnit.Framework.Legacy.StringAssert" Alias="StringAssert" />
+    <Using Include="NUnit.Framework.Legacy.DirectoryAssert" Alias="DirectoryAssert" />
+    <Using Include="NUnit.Framework.Legacy.FileAssert" Alias="FileAssert" />
+  </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Common\Properties\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
     <Content Include="Research\RegressionScripts\Test_QuantBookIndicator.py">
diff --git a/Tests/app.config b/Tests/app.config
deleted file mode 100644
index 46a3342b6776..000000000000
--- a/Tests/app.config
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="Microsoft.VisualStudio.TestPlatform.ObjectModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="15.0.0.0" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
diff --git a/ToolBox/QuantConnect.ToolBox.csproj b/ToolBox/QuantConnect.ToolBox.csproj
index 782dc9c5f97a..9ae34cc44de9 100644
--- a/ToolBox/QuantConnect.ToolBox.csproj
+++ b/ToolBox/QuantConnect.ToolBox.csproj
@@ -5,7 +5,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>QuantConnect.ToolBox</RootNamespace>
     <AssemblyName>QuantConnect.ToolBox</AssemblyName>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <OutputPath>bin\$(Configuration)\</OutputPath>