From 8e9a80c9e236690bbd66e02e964cfa87c04070a8 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 4 May 2026 00:48:06 +0000 Subject: [PATCH] [create-pull-request] automated change --- single-page/Quantconnect-Cloud-Platform.html | 4785 +- single-page/Quantconnect-Lean-Cli.html | 592 +- single-page/Quantconnect-Local-Platform.html | 12 +- .../Quantconnect-Research-Environment.html | 2308 +- .../Quantconnect-Writing-Algorithms.html | 86898 ++++++++-------- 5 files changed, 49092 insertions(+), 45503 deletions(-) diff --git a/single-page/Quantconnect-Cloud-Platform.html b/single-page/Quantconnect-Cloud-Platform.html index c771a78b22..a3f3bc20c2 100644 --- a/single-page/Quantconnect-Cloud-Platform.html +++ b/single-page/Quantconnect-Cloud-Platform.html @@ -565,7 +565,11 @@

Physical access to our servers is limited to a few dedicated team members whom QuantConnect has vetted. Only those credentialed team members can access the physical servers, and we schedule all work in advance. - Work on the servers is always done in pairs to prevent single rogue actors from accessing the servers. We host our servers in a world-class security facility (Equinix) with security staff 24/7. + Work on the servers is always done in pairs to prevent single rogue actors from accessing the servers. We host our servers in a world-class security facility, on co-located servers racked in + + Equinix + + , with security staff 24/7.

Information and Digital Security @@ -1481,7 +1485,11 @@

Live Trading Nodes

- Live trading nodes enable you to deploy live algorithms to our professionally-managed, co-located servers. + Live trading nodes enable you to deploy live algorithms to our professionally-managed, co-located servers racked in + + Equinix + + . You need a live trading node for each algorithm that you deploy to our co-located servers. Several models of live trading nodes are available. More powerful live trading nodes allow you to run algorithms with larger universes and give you @@ -9333,6 +9341,87 @@

+

Order Tagging

+ + +

+ You can add + + tags + + to your orders to track why each trade was placed. This is useful for debugging your algorithm's trading logic because you can include the indicator values or conditions that triggered the order. +

+
+
public class OrderTaggingAlgorithm : QCAlgorithm
+{
+    private ExponentialMovingAverage _emaShort;
+    private ExponentialMovingAverage _emaLong;
+    private Symbol _symbol;
+
+    public override void Initialize()
+    {
+        SetStartDate(2024, 9, 1);
+        SetEndDate(2024, 12, 31);
+        SetCash(100000);
+
+        _symbol = AddEquity("SPY", Resolution.Daily).Symbol;
+        _emaShort = EMA(_symbol, 10);
+        _emaLong = EMA(_symbol, 30);
+    }
+
+    public override void OnData(Slice data)
+    {
+        if (!_emaShort.IsReady || !_emaLong.IsReady) return;
+
+        if (_emaShort > _emaLong && !Portfolio[_symbol].IsLong)
+        {
+            MarketOrder(_symbol, 100, tag: $"BUY: ema-short: {_emaShort:F4} > ema-long: {_emaLong:F4}");
+        }
+        else if (_emaShort < _emaLong && !Portfolio[_symbol].IsShort)
+        {
+            MarketOrder(_symbol, -100, tag: $"SELL: ema-short: {_emaShort:F4} < ema-long: {_emaLong:F4}");
+        }
+    }
+}
+
class OrderTaggingAlgorithm(QCAlgorithm):
+    def initialize(self) -> None:
+        self.set_start_date(2024, 9, 1)
+        self.set_end_date(2024, 12, 31)
+        self.set_cash(100000)
+
+        self._symbol = self.add_equity("SPY", Resolution.DAILY).symbol
+        self._ema_short = self.ema(self._symbol, 10)
+        self._ema_long = self.ema(self._symbol, 30)
+
+    def on_data(self, data: Slice) -> None:
+        if not self._ema_short.is_ready or not self._ema_long.is_ready:
+            return
+
+        ema_short = self._ema_short.current.value
+        ema_long = self._ema_long.current.value
+        if ema_short > ema_long and not self.portfolio[self._symbol].is_long:
+            self.market_order(self._symbol, 100, tag=f'BUY: ema-short: {ema_short:.4f} > ema-long: {ema_long:.4f}')
+        elif ema_short < ema_long and not self.portfolio[self._symbol].is_short:
+            self.market_order(self._symbol, -100, tag=f'SELL: ema-short: {ema_short:.4f} < ema-long: {ema_long:.4f}')
+
+

+ The tag is saved to the + + result files + + that you can download for local analysis. Unlike + + logging statements + + , order tags are attached directly to each order, so you don't need to search through logs to match a message to a specific trade, and they don't consume your + + log quota + + . +

+ + +

Charting

@@ -9370,7 +9459,7 @@

Object Store

The Object Store is a key-value data store for low-latency information storage and retrieval. - During a backtest, you can build large objects you’d like to analyze and write them for later analysis. + During a backtest, you can build large objects you'd like to analyze and write them for later analysis. This workflow can be helpful when the objects are large and plotting is impossible or when you want to perform analysis across many backtests.

@@ -10592,8 +10681,10 @@

Example

bbdf[['price', 'lowerband', 'middleband', 'upperband']].plot();
-
#load "../QuantConnect.csx"
-using QuantConnect;
+   
#load "../QuantConnect.csx"
+
+
+
using QuantConnect;
 using QuantConnect.Data;
 using QuantConnect.Algorithm;
 using QuantConnect.Research;
@@ -18483,7 +18574,11 @@ 

Delivery

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. @@ -18665,7 +18760,11 @@

Delivery

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. @@ -18813,7 +18912,11 @@

Delivery

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. @@ -18948,7 +19051,11 @@

Delivery

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. @@ -19083,7 +19190,11 @@

Delivery

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. @@ -19249,7 +19360,11 @@

Delivery

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. @@ -19389,7 +19504,11 @@

Delivery

, include a live stream. In these cases, we deliver the data as a live stream to your algorithm.

- Most live trading algorithms run on co-located servers racked in Equinix. Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters. + Most live trading algorithms run on co-located servers racked in + + Equinix + + . Co-location reduces several factors that can interfere with your algorithm, including downtime from internet outages, equipment repairs, and natural disasters.

Live data takes time to travel from the source to your algorithm. The latency of the alternative data depends on the specific dataset you're using. @@ -21666,7 +21785,11 @@

Introduction

- A live algorithm is an algorithm that trades in real-time with real market data. QuantConnect enables you to run your algorithms in live mode with real-time market data. Deploy your algorithms using QuantConnect because our infrastructure is battle-tested. The algorithms that our members create are run on co-located servers and the trading infrastructure is maintained at all times by our team of engineers. It's common for members to achieve 6-months of uptime with no interruptions. + A live algorithm is an algorithm that trades in real-time with real market data. QuantConnect enables you to run your algorithms in live mode with real-time market data. Deploy your algorithms using QuantConnect because our infrastructure is battle-tested. The algorithms that our members create are run on co-located servers racked in + + Equinix + + and the trading infrastructure is maintained at all times by our team of engineers. It's common for members to achieve 6-months of uptime with no interruptions.

@@ -23531,6 +23654,110 @@

+

FIX Integration

+ + +

+ FIX (Financial Information eXchange) integration lets existing Interactive Brokers (IB) clients route orders from QuantConnect through their IB account. If you already hold an IB account, you can subscribe to QuantConnect directly from the IB Client Portal to enable FIX order routing. +

+

+ Before you start, make sure you have an active IB account and access to the IB Client Portal. +

+

+ Follow these steps to add FIX support to your IB account: +

+
    +
  1. + Log in to the + + IB Client Portal + + , open + + Settings + + , click + + Research Subscriptions + + , open + + News & Research Subscriptions + + , and then click + + Manage Subscriptions + + . +
  2. +
  3. + Select + + QuantConnect + + from the list of subscriptions to create the FIX session, and then click + + Continue + + . +
  4. +
  5. + On the + + Review Your Research Subscriptions + + screen, review the market-data agreements and disclosures, and then confirm to proceed. +
  6. +
  7. + On the + + Service Account Configuration + + screen, click the + + Configure + + gear next to QuantConnect. +
  8. +
  9. + In the + + Service Account Configuration for QuantConnect + + dialog, select the IB account(s) you want to link, enter your QuantConnect user name in the + + Quantconnect Username + + field, and then click + + Save + + . +
  10. +

    + The user name you enter is the default subscriber for the QuantConnect service. You can select multiple accounts here. When you later connect from QuantConnect to IB, you enter this same user name to authenticate. +

    +
  11. + Back on the + + Service Account Configuration + + screen, click + + Continue + + . +
  12. +
  13. + Acknowledge and confirm the OMS Riders and Addendum. +
  14. +

    + After you confirm, your subscription is complete and the selected information is added to the FIX connection for order validation. +

    +
+ + +

Asset Classes

@@ -24801,6 +25028,141 @@

Deploy Live Algorithms

+

Deploy Live Algorithms FIX

+ + +

+ You must have an available + + live trading node + + for each live trading algorithm you deploy. +

+

+ Follow these steps to deploy a live algorithm: +

+
    +
  1. + + Open the project + + you want to deploy. +
  2. +
  3. + Click the + Lightning icon + + Deploy Live + + icon. +
  4. +
  5. + On the Deploy Live page, click the + + Brokerage + + field and then click + + + Interactive Brokers + + + from the drop-down menu. +
  6. +
  7. + Enter your + + IB + + user name (see + + FIX Integration + + ). +
  8. +
  9. + Click the + + Node + + field and then click the live trading node that you want to use from the drop-down menu. +
  10. +
  11. + + (Optional) + + In the + + Data Provider + + section, click + + Show + + and change the data provider or add additional providers. +
  12. +

    + In most cases, we suggest using + + both the QC and IB data providers + + . +

    +

    + If you use + + IB + + data provider and trade with a paper trading account, you need to share the market data subscription with your paper trading account. For instructions on sharing market data subscription, see + + Account Types + + . +

    +
  13. + + (Optional) + + + Set up notifications + + . +
  14. +
  15. + Configure the + + Automatically restart algorithm + + setting. +
  16. +

    + By enabling + + automatic restarts + + , the algorithm will use best efforts to restart the algorithm if it fails due to a runtime error. This can help improve the algorithm's resilience to temporary outages such as a brokerage API disconnection. +

    +
  17. + Click + + Deploy + + . +
  18. +
  19. + If your IB account has 2FA enabled, tap the notification on your IB Key device and then enter your pin. +
  20. +
+

+ The deployment process can take up to 5 minutes. When the algorithm deploys, the + + live results page + + displays. If you know your brokerage positions before you deployed, you can verify they have been loaded properly by checking your equity value in the runtime statistics, your cashbook holdings, and your position holdings. +

+ + +

Troubleshooting

@@ -38460,7 +38822,11 @@

Introduction

- Deploy your trading algorithms live to receive real-time market data and submit orders on our co-located servers. As your algorithms run, you can view their performance in the Algorithm Lab. Since the algorithms run in QuantConnect Cloud, you can close the IDE without interrupting the execution of your algorithms. Deploying your algorithms to live trading through QuantConnect is cheaper than purchasing server space, setting up data feeds, and maintaining the software on your own. To deploy your algorithms on QuantConnect, you just need to follow the + Deploy your trading algorithms live to receive real-time market data and submit orders on our co-located servers racked in + + Equinix + + . As your algorithms run, you can view their performance in the Algorithm Lab. Since the algorithms run in QuantConnect Cloud, you can close the IDE without interrupting the execution of your algorithms. Deploying your algorithms to live trading through QuantConnect is cheaper than purchasing server space, setting up data feeds, and maintaining the software on your own. To deploy your algorithms on QuantConnect, you just need to follow the Deploy Live Algorithms @@ -38477,7 +38843,11 @@

Resources

- Live trading nodes enable you to deploy live algorithms to our professionally-managed, co-located servers. + Live trading nodes enable you to deploy live algorithms to our professionally-managed, co-located servers racked in + + Equinix + + . You need a live trading node for each algorithm that you deploy to our co-located servers. Several models of live trading nodes are available. More powerful live trading nodes allow you to run algorithms with larger universes and give you @@ -40577,9 +40947,9 @@

To programmatically analyze orders, call the - + - ReadBacktestOrders + ReadLiveOrders read_live_orders @@ -41195,6 +41565,13 @@

Introduction

If your algorithm is perfectly reconciled, it has an exact overlap between its live and OOS backtest equity curves. Deviations mean that the performance of your algorithm has differed between the two execution modes. Several factors can contribute to the deviations.

+

+ To generate the OOS reconciliation curve for a live deployment and overlay live vs. backtest equity and order fills from the Research Environment, see + + Live Reconciliation + + . +

@@ -47460,44 +47837,48 @@

// Generate a timestamped SHA-256 hashed API token for secure authentication
-#r "nuget:RestSharp"
-using System;
 using System.Security.Cryptography;
-using RestSharp;
+using System.Text;
 
-// Request your API token on https://www.quantconnect.com/settings/ and replace the below values.
-var yourUserId = 0;
-var yourApiToken = "_____";
+// Set the QC_USER_ID and QC_API_TOKEN environment variables with values from https://www.quantconnect.com/settings/.
+var yourUserId = Environment.GetEnvironmentVariable("QC_USER_ID") ?? "0";
+var yourApiToken = Environment.GetEnvironmentVariable("QC_API_TOKEN") ?? "_____";
 
-// Get timestamp
-var stamp = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds();
-var timeStampedToken = $"{<yourApiToken>}:{stamp}";
-
-// Get hashed API token
-var crypt = new SHA256Managed();
-var hashToken = crypt.ComputeHash(Encoding.UTF8.GetBytes(timeStampedToken), 0, Encoding.UTF8.GetByteCount(timeStampedToken));
-var hash = new StringBuilder();
-foreach (var theByte in hashToken)
+Dictionary<string, string> GetHeaders()
 {
-    hash.Append(theByte.ToString("x2"));
+    // Get timestamp
+    var timestamp = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds().ToString();
+    var timeStampedToken = $"{yourApiToken}:{timestamp}";
+
+    // Get hashed API token
+    var hashBytes = SHA256.HashData(Encoding.UTF8.GetBytes(timeStampedToken));
+    var hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
+    var authentication = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{yourUserId}:{hash}"));
+
+    // Create headers dictionary.
+    return new Dictionary<string, string>
+    {
+        { "Authorization", $"Basic {authentication}" },
+        { "Timestamp", timestamp }
+    };
 }
-var apiToken = hash.ToString();
 
# Generate a timestamped SHA-256 hashed API token for secure authentication
+from os import environ
 from base64 import b64encode
 from hashlib import sha256
 from time import time
 
-# Request your API token on https://www.quantconnect.com/settings/ and replace the below values.
-USER_ID = 0
-API_TOKEN = '_____'
+# Set the QC_USER_ID and QC_API_TOKEN environment variables with values from https://www.quantconnect.com/settings/.
+USER_ID = environ.get('QC_USER_ID', 0)
+API_TOKEN = environ.get('QC_API_TOKEN', '_____')
 
 def get_headers():
     # Get timestamp
     timestamp = f'{int(time())}'
     time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
 
-    # Get hased API token
+    # Get hashed API token
     hashed_token = sha256(time_stamped_token).hexdigest()
     authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
     authentication = b64encode(authentication).decode('ascii')
@@ -47512,27 +47893,22 @@ 

Make API Request

-

- Follow the below example to install the hashing into the authenticator and make an API request. -

-

- Follow the below example to install the hashing into the headings and make an API request. +

+ Follow the below example to set the authentication headers and make an API request.

-
// Create REST client and install authenticator.
-var client = new RestClient("<requestUrl>");
-client.Authenticator = new HttpBasicAuthenticator(
-    "<yourUserId>",
-    hash.ToString()
-);
-
-// Create Request and add timestamp header (optional: Json Content).
-var request = new RestRequest();
-request.AddHeader("Timestamp", stamp.ToString());
+   
// Create HTTP client with authentication headers.
+var client = new HttpClient();
+client.BaseAddress = new Uri("https://www.quantconnect.com/api/v2/");
+foreach (var header in GetHeaders())
+{
+    client.DefaultRequestHeaders.Add(header.Key, header.Value);
+}
 
 // Make POST request.
-var response = await client.PostAsync(request);
-var content = response.Content
+var request = new StringContent("{}", Encoding.UTF8, "application/json"); +var response = await client.PostAsync("<requestUrl>", request); +var content = await response.Content.ReadAsStringAsync();
# Create POST Request with headers
 from requests import post
 BASE_URL = 'https://www.quantconnect.com/api/v2/'
@@ -47542,6 +47918,61 @@ 

json = {}) # Use json keyword to send the payload content = response.text

+

+ Using cURL +

+

+ Follow the below example to make an API request with authentication using cURL. +

+
+
# Set the QC_USER_ID and QC_API_TOKEN environment variables with values from https://www.quantconnect.com/settings/.
+YOUR_USER_ID=${QC_USER_ID:-0}
+YOUR_API_TOKEN=${QC_API_TOKEN:-_____}
+
+# Get timestamp
+TIMESTAMP=$(date +%s)
+TIME_STAMPED_TOKEN="${YOUR_API_TOKEN}:${TIMESTAMP}"
+
+# Get hashed API token
+HASHED_TOKEN=$(echo -n "$TIME_STAMPED_TOKEN" | sha256sum | cut -d ' ' -f 1)
+AUTHENTICATION=$(echo -n "${YOUR_USER_ID}:${HASHED_TOKEN}" | base64 -w 0)
+
+# Make POST request with authentication headers
+curl -X POST "https://www.quantconnect.com/api/v2/<request_url>" \
+    -H "Authorization: Basic ${AUTHENTICATION}" \
+    -H "Timestamp: ${TIMESTAMP}" \
+    -H "Content-Type: application/json" \
+    -d '{}'
+
+

+ Using PowerShell +

+

+ Follow the below example to make an API request with authentication using PowerShell. +

+
+
# Set the QC_USER_ID and QC_API_TOKEN environment variables with values from https://www.quantconnect.com/settings/.
+$yourUserId = if ($env:QC_USER_ID) { $env:QC_USER_ID } else { "0" }
+$yourApiToken = if ($env:QC_API_TOKEN) { $env:QC_API_TOKEN } else { "_____" }
+
+# Get timestamp
+$timestamp = [Math]::Floor((([DateTimeOffset]::UtcNow).ToUnixTimeSeconds()))
+$timeStampedToken = "${yourApiToken}:${timestamp}"
+
+# Get hashed API token
+$hasher = [System.Security.Cryptography.SHA256]::Create()
+$hashBytes = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($timeStampedToken))
+$hash = -join ($hashBytes | ForEach-Object { $_.ToString("x2") })
+$authentication = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("${yourUserId}:${hash}"))
+
+# Make POST request with authentication headers
+$headers = @{
+    "Authorization" = "Basic $authentication"
+    "Timestamp" = "$timestamp"
+}
+$response = Invoke-RestMethod -Uri "https://www.quantconnect.com/api/v2/<requestUrl>" -Method Post -Headers $headers -ContentType "application/json" -Body "{}"
+Write-Host "Response: $($response | ConvertTo-Json)"
+
@@ -48115,7 +48546,7 @@

"name": "string" }, "isPinned": true, - "maxFileSize": "string", + "maxFileSize": 0, "sharingTokenBacktest": "q" } ], @@ -48439,7 +48870,7 @@

- object + Grid object
@@ -48448,7 +48879,7 @@


- Configuration of the backtest view grid. + The grid arrangement of charts. @@ -48457,7 +48888,7 @@

- object + Grid object
@@ -48466,7 +48897,7 @@


- Configuration of the live view grid. + The grid arrangement of charts. @@ -48511,7 +48942,7 @@

- object + LiveForm object
@@ -48520,7 +48951,7 @@


- The last live wizard content used. + The live wizard content used. @@ -48583,7 +49014,7 @@

- object + EncryptionKey object
@@ -48592,7 +49023,7 @@


- Text file with at least 32 characters to be used to encrypt the project. + Encryption key details. @@ -48619,7 +49050,7 @@

- int + integer
@@ -48850,7 +49281,7 @@

"name": "string" }, "isPinned": true, - "maxFileSize": "string", + "maxFileSize": 0, "sharingTokenBacktest": "q" }

@@ -49495,7 +49926,7 @@

- object + BrokerageData object
@@ -49504,7 +49935,7 @@


- /. + Brokerage data saved on live deployment. @@ -51615,7 +52046,7 @@

"name": "string" }, "isPinned": true, - "maxFileSize": "string", + "maxFileSize": 0, "sharingTokenBacktest": "q" } ], @@ -51939,7 +52370,7 @@

- object + Grid object
@@ -51948,7 +52379,7 @@


- Configuration of the backtest view grid. + The grid arrangement of charts. @@ -51957,7 +52388,7 @@

- object + Grid object
@@ -51966,7 +52397,7 @@


- Configuration of the live view grid. + The grid arrangement of charts. @@ -52011,7 +52442,7 @@

- object + LiveForm object
@@ -52020,7 +52451,7 @@


- The last live wizard content used. + The live wizard content used. @@ -52083,7 +52514,7 @@

- object + EncryptionKey object
@@ -52092,7 +52523,7 @@


- Text file with at least 32 characters to be used to encrypt the project. + Encryption key details. @@ -52119,7 +52550,7 @@

- int + integer
@@ -52350,7 +52781,7 @@

"name": "string" }, "isPinned": true, - "maxFileSize": "string", + "maxFileSize": 0, "sharingTokenBacktest": "q" }

@@ -52995,7 +53426,7 @@

- object + BrokerageData object
@@ -53004,7 +53435,7 @@


- /. + Brokerage data saved on live deployment. @@ -55000,9 +55431,79 @@

Examples

# Parse the JSON response into python managable dict result = response.json() # Check if the request was successful and print the result +if result['success']: + print(f"Project Collaborator Deleted Successfully: {result}") + if result['success']: print(f"Project Collaborator Deleted Successfully: {result}") +

+ The following example demonstrates how to add a collaborator to all projects that start with a given folder name. +

+
+
from base64 import b64encode
+from hashlib import sha256
+from time import time
+from requests import get, post
+BASE_URL = 'https://www.quantconnect.com/api/v2/'
+
+# You need to replace these with your actual credentials.
+# You can request your credentials at https://www.quantconnect.com/settings/
+# You can find our organization ID at https://www.quantconnect.com/organization/ 
+USER_ID = 0
+API_TOKEN = '____'
+ORGANIZATION_ID = '____'
+
+def get_headers():
+    # Get timestamp
+    timestamp = f'{int(time())}'
+    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
+
+    # Get hased API token
+    hashed_token = sha256(time_stamped_token).hexdigest()
+    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
+    authentication = b64encode(authentication).decode('ascii')
+
+    # Create headers dictionary.
+    return {
+        'Authorization': f'Basic {authentication}',
+        'Timestamp': timestamp
+    }
+
+# Authenticate to verify credentials
+response = post(f'{BASE_URL}/authenticate', headers = get_headers())
+print(response.json())
+
+# --------------------
+
+
+# Define the folder prefix to match (e.g., "SubFolder/")
+folder_prefix = "SubFolder/"
+# Define collaborator ID (replace with actual user ID)
+collaborator_id = 'johnny_walker'
+# Send a POST request to the /projects/read endpoint to get all projects
+response = post(f'{BASE_URL}/projects/read', headers=get_headers())
+result = response.json()
+if result['success']:
+    # Filter projects that start with the given folder prefix
+    matching_projects = [
+        project for project in result['projects']
+        if project['name'].startswith(folder_prefix)
+    ]
+    # Add the collaborator to each matching project
+    for project in matching_projects:
+        response = post(f'{BASE_URL}/projects/collaboration/create', headers=get_headers(), json={
+            "projectId": project['projectId'],
+            "collaboratorUserId": collaborator_id,
+            "collaborationLiveControl": True,
+            "collaborationWrite": True
+        })
+        add_result = response.json()
+        if add_result['success']:
+            print(f"Added collaborator to project '{project['name']}' (ID: {project['projectId']})")
+        else:
+            print(f"Failed to add collaborator to project '{project['name']}': {add_result}")
+
@@ -55521,9 +56022,79 @@

Examples

# Parse the JSON response into python managable dict result = response.json() # Check if the request was successful and print the result +if result['success']: + print(f"Project Collaborator Deleted Successfully: {result}") + if result['success']: print(f"Project Collaborator Deleted Successfully: {result}") +

+ The following example demonstrates how to add a collaborator to all projects that start with a given folder name. +

+
+
from base64 import b64encode
+from hashlib import sha256
+from time import time
+from requests import get, post
+BASE_URL = 'https://www.quantconnect.com/api/v2/'
+
+# You need to replace these with your actual credentials.
+# You can request your credentials at https://www.quantconnect.com/settings/
+# You can find our organization ID at https://www.quantconnect.com/organization/ 
+USER_ID = 0
+API_TOKEN = '____'
+ORGANIZATION_ID = '____'
+
+def get_headers():
+    # Get timestamp
+    timestamp = f'{int(time())}'
+    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
+
+    # Get hased API token
+    hashed_token = sha256(time_stamped_token).hexdigest()
+    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
+    authentication = b64encode(authentication).decode('ascii')
+
+    # Create headers dictionary.
+    return {
+        'Authorization': f'Basic {authentication}',
+        'Timestamp': timestamp
+    }
+
+# Authenticate to verify credentials
+response = post(f'{BASE_URL}/authenticate', headers = get_headers())
+print(response.json())
+
+# --------------------
+
+
+# Define the folder prefix to match (e.g., "SubFolder/")
+folder_prefix = "SubFolder/"
+# Define collaborator ID (replace with actual user ID)
+collaborator_id = 'johnny_walker'
+# Send a POST request to the /projects/read endpoint to get all projects
+response = post(f'{BASE_URL}/projects/read', headers=get_headers())
+result = response.json()
+if result['success']:
+    # Filter projects that start with the given folder prefix
+    matching_projects = [
+        project for project in result['projects']
+        if project['name'].startswith(folder_prefix)
+    ]
+    # Add the collaborator to each matching project
+    for project in matching_projects:
+        response = post(f'{BASE_URL}/projects/collaboration/create', headers=get_headers(), json={
+            "projectId": project['projectId'],
+            "collaboratorUserId": collaborator_id,
+            "collaborationLiveControl": True,
+            "collaborationWrite": True
+        })
+        add_result = response.json()
+        if add_result['success']:
+            print(f"Added collaborator to project '{project['name']}' (ID: {project['projectId']})")
+        else:
+            print(f"Failed to add collaborator to project '{project['name']}': {add_result}")
+
@@ -56091,9 +56662,79 @@

Examples

# Parse the JSON response into python managable dict result = response.json() # Check if the request was successful and print the result +if result['success']: + print(f"Project Collaborator Deleted Successfully: {result}") + if result['success']: print(f"Project Collaborator Deleted Successfully: {result}") +

+ The following example demonstrates how to add a collaborator to all projects that start with a given folder name. +

+
+
from base64 import b64encode
+from hashlib import sha256
+from time import time
+from requests import get, post
+BASE_URL = 'https://www.quantconnect.com/api/v2/'
+
+# You need to replace these with your actual credentials.
+# You can request your credentials at https://www.quantconnect.com/settings/
+# You can find our organization ID at https://www.quantconnect.com/organization/ 
+USER_ID = 0
+API_TOKEN = '____'
+ORGANIZATION_ID = '____'
+
+def get_headers():
+    # Get timestamp
+    timestamp = f'{int(time())}'
+    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
+
+    # Get hased API token
+    hashed_token = sha256(time_stamped_token).hexdigest()
+    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
+    authentication = b64encode(authentication).decode('ascii')
+
+    # Create headers dictionary.
+    return {
+        'Authorization': f'Basic {authentication}',
+        'Timestamp': timestamp
+    }
+
+# Authenticate to verify credentials
+response = post(f'{BASE_URL}/authenticate', headers = get_headers())
+print(response.json())
+
+# --------------------
+
+
+# Define the folder prefix to match (e.g., "SubFolder/")
+folder_prefix = "SubFolder/"
+# Define collaborator ID (replace with actual user ID)
+collaborator_id = 'johnny_walker'
+# Send a POST request to the /projects/read endpoint to get all projects
+response = post(f'{BASE_URL}/projects/read', headers=get_headers())
+result = response.json()
+if result['success']:
+    # Filter projects that start with the given folder prefix
+    matching_projects = [
+        project for project in result['projects']
+        if project['name'].startswith(folder_prefix)
+    ]
+    # Add the collaborator to each matching project
+    for project in matching_projects:
+        response = post(f'{BASE_URL}/projects/collaboration/create', headers=get_headers(), json={
+            "projectId": project['projectId'],
+            "collaboratorUserId": collaborator_id,
+            "collaborationLiveControl": True,
+            "collaborationWrite": True
+        })
+        add_result = response.json()
+        if add_result['success']:
+            print(f"Added collaborator to project '{project['name']}' (ID: {project['projectId']})")
+        else:
+            print(f"Failed to add collaborator to project '{project['name']}': {add_result}")
+
@@ -56611,9 +57252,79 @@

Examples

# Parse the JSON response into python managable dict result = response.json() # Check if the request was successful and print the result +if result['success']: + print(f"Project Collaborator Deleted Successfully: {result}") + if result['success']: print(f"Project Collaborator Deleted Successfully: {result}") +

+ The following example demonstrates how to add a collaborator to all projects that start with a given folder name. +

+
+
from base64 import b64encode
+from hashlib import sha256
+from time import time
+from requests import get, post
+BASE_URL = 'https://www.quantconnect.com/api/v2/'
+
+# You need to replace these with your actual credentials.
+# You can request your credentials at https://www.quantconnect.com/settings/
+# You can find our organization ID at https://www.quantconnect.com/organization/ 
+USER_ID = 0
+API_TOKEN = '____'
+ORGANIZATION_ID = '____'
+
+def get_headers():
+    # Get timestamp
+    timestamp = f'{int(time())}'
+    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
+
+    # Get hased API token
+    hashed_token = sha256(time_stamped_token).hexdigest()
+    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
+    authentication = b64encode(authentication).decode('ascii')
+
+    # Create headers dictionary.
+    return {
+        'Authorization': f'Basic {authentication}',
+        'Timestamp': timestamp
+    }
+
+# Authenticate to verify credentials
+response = post(f'{BASE_URL}/authenticate', headers = get_headers())
+print(response.json())
+
+# --------------------
+
+
+# Define the folder prefix to match (e.g., "SubFolder/")
+folder_prefix = "SubFolder/"
+# Define collaborator ID (replace with actual user ID)
+collaborator_id = 'johnny_walker'
+# Send a POST request to the /projects/read endpoint to get all projects
+response = post(f'{BASE_URL}/projects/read', headers=get_headers())
+result = response.json()
+if result['success']:
+    # Filter projects that start with the given folder prefix
+    matching_projects = [
+        project for project in result['projects']
+        if project['name'].startswith(folder_prefix)
+    ]
+    # Add the collaborator to each matching project
+    for project in matching_projects:
+        response = post(f'{BASE_URL}/projects/collaboration/create', headers=get_headers(), json={
+            "projectId": project['projectId'],
+            "collaboratorUserId": collaborator_id,
+            "collaborationLiveControl": True,
+            "collaborationWrite": True
+        })
+        add_result = response.json()
+        if add_result['success']:
+            print(f"Added collaborator to project '{project['name']}' (ID: {project['projectId']})")
+        else:
+            print(f"Failed to add collaborator to project '{project['name']}': {add_result}")
+
@@ -56914,9 +57625,79 @@

Examples

# Parse the JSON response into python managable dict result = response.json() # Check if the request was successful and print the result +if result['success']: + print(f"Project Collaborator Deleted Successfully: {result}") + if result['success']: print(f"Project Collaborator Deleted Successfully: {result}") +

+ The following example demonstrates how to add a collaborator to all projects that start with a given folder name. +

+
+
from base64 import b64encode
+from hashlib import sha256
+from time import time
+from requests import get, post
+BASE_URL = 'https://www.quantconnect.com/api/v2/'
+
+# You need to replace these with your actual credentials.
+# You can request your credentials at https://www.quantconnect.com/settings/
+# You can find our organization ID at https://www.quantconnect.com/organization/ 
+USER_ID = 0
+API_TOKEN = '____'
+ORGANIZATION_ID = '____'
+
+def get_headers():
+    # Get timestamp
+    timestamp = f'{int(time())}'
+    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
+
+    # Get hased API token
+    hashed_token = sha256(time_stamped_token).hexdigest()
+    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
+    authentication = b64encode(authentication).decode('ascii')
+
+    # Create headers dictionary.
+    return {
+        'Authorization': f'Basic {authentication}',
+        'Timestamp': timestamp
+    }
+
+# Authenticate to verify credentials
+response = post(f'{BASE_URL}/authenticate', headers = get_headers())
+print(response.json())
+
+# --------------------
+
+
+# Define the folder prefix to match (e.g., "SubFolder/")
+folder_prefix = "SubFolder/"
+# Define collaborator ID (replace with actual user ID)
+collaborator_id = 'johnny_walker'
+# Send a POST request to the /projects/read endpoint to get all projects
+response = post(f'{BASE_URL}/projects/read', headers=get_headers())
+result = response.json()
+if result['success']:
+    # Filter projects that start with the given folder prefix
+    matching_projects = [
+        project for project in result['projects']
+        if project['name'].startswith(folder_prefix)
+    ]
+    # Add the collaborator to each matching project
+    for project in matching_projects:
+        response = post(f'{BASE_URL}/projects/collaboration/create', headers=get_headers(), json={
+            "projectId": project['projectId'],
+            "collaboratorUserId": collaborator_id,
+            "collaborationLiveControl": True,
+            "collaborationWrite": True
+        })
+        add_result = response.json()
+        if add_result['success']:
+            print(f"Added collaborator to project '{project['name']}' (ID: {project['projectId']})")
+        else:
+            print(f"Failed to add collaborator to project '{project['name']}': {add_result}")
+
@@ -62086,98 +62867,7 @@

}, "parameterSet": , "rollingWindow": { - "tradeStatistics": { - "startDateTime": "2021-11-26T15:18:27.693Z", - "endDateTime": "2021-11-26T15:18:27.693Z", - "totalNumberOfTrades": 0, - "numberOfWinningTrades": 0, - "numberOfLosingTrades": 0, - "totalProfitLoss": "string", - "totalProfit": "string", - "totalLoss": "string", - "largestProfit": "string", - "largestLoss": "string", - "averageProfitLoss": "string", - "averageProfit": "string", - "averageLoss": "string", - "averageTradeDuration": "string", - "averageWinningTradeDuration": "string", - "averageLosingTradeDuration": "string", - "medianTradeDuration": "string", - "medianWinningTradeDuration": "string", - "medianLosingTradeDuration": "string", - "maxConsecutiveWinningTrades": 0, - "maxConsecutiveLosingTrades": 0, - "profitLossRatio": "string", - "winLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "averageMAE": "string", - "averageMFE": "string", - "largestMAE": "string", - "largestMFE": "string", - "maximumClosedTradeDrawdown": "string", - "maximumIntraTradeDrawdown": "string", - "profitLossStandardDeviation": "string", - "profitLossDownsideDeviation": "string", - "profitFactor": "string", - "sharpeRatio": "string", - "sortinoRatio": "string", - "profitToMaxDrawdownRatio": "string", - "maximumEndTradeDrawdown": "string", - "averageEndTradeDrawdown": "string", - "maximumDrawdownDuration": "string", - "totalFees": "string" - }, - "portfolioStatistics": { - "averageWinRate": "string", - "averageLossRate": "string", - "profitLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "expectancy": "string", - "startEquity": "string", - "endEquity": "string", - "compoundingAnnualReturn": "string", - "drawdown": "string", - "totalNetProfit": "string", - "sharpeRatio": "string", - "probabilisticSharpeRatio": "string", - "sortinoRatio": "string", - "alpha": "string", - "beta": "string", - "annualStandardDeviation": "string", - "annualVariance": "string", - "informationRatio": "string", - "trackingError": "string", - "treynorRatio": "string", - "portfolioTurnover": "string", - "valueAtRisk99": "string", - "valueAtRisk95": "string", - "drawdownRecovery": "string" - }, - "closedTrades": [ - { - "symbol": { - "value": "string", - "id": "string", - "permtick": "string" - }, - "entryTime": "2021-11-26T15:18:27.693Z", - "entryPrice": 0, - "direction": 0, - "quantity": 0, - "exitTime": "2021-11-26T15:18:27.693Z", - "exitPrice": 0, - "profitLoss": 0, - "totalFees": 0, - "mae": 0, - "mfe": 0, - "duration": "string", - "endTradeDrawdown": 0 - } - ] - }, + }, "runtimeStatistics": { "Equity": "$100.00", "Fees": "-$100.00", @@ -62312,7 +63002,21 @@

}, "nodeName": "string", "outOfSampleMaxEndDate": "2021-11-26T15:18:27.693Z", - "outOfSampleDays": 0 + "outOfSampleDays": 0, + "analysis": [ + { + "name": "PerformanceRelativeToBenchmarkAnalysis", + "issue": "The strategy has a lower Sharpe ratio than the benchmark.", + "sample": { + "backtestSharpe": -0.2281345806218534, + "benchmarkSharpe": -0.22182175736916387 + }, + "count": 5, + "solutions": [ + "Try adjusting the trading rules and/or the universe to get a strategy that outperforms the benchmark." + ] + } + ] }, "debugging": true, "success": true, @@ -62701,7 +63405,7 @@

- AlgorithmPerformance object + object
Rolling window detailed statistics. @@ -62749,7 +63453,7 @@

- object + AlgorithmPerformance object
@@ -62758,7 +63462,7 @@


- The algorithm performance statistics. + The AlgorithmPerformance class is a wrapper for TradeStatistics and PortfolioStatistics. @@ -62803,6 +63507,18 @@

Number of days of out of sample days. + + + analysis + + + + AnalysisResult Array + +
+ /. + + Example @@ -62838,98 +63554,7 @@

}, "parameterSet": , "rollingWindow": { - "tradeStatistics": { - "startDateTime": "2021-11-26T15:18:27.693Z", - "endDateTime": "2021-11-26T15:18:27.693Z", - "totalNumberOfTrades": 0, - "numberOfWinningTrades": 0, - "numberOfLosingTrades": 0, - "totalProfitLoss": "string", - "totalProfit": "string", - "totalLoss": "string", - "largestProfit": "string", - "largestLoss": "string", - "averageProfitLoss": "string", - "averageProfit": "string", - "averageLoss": "string", - "averageTradeDuration": "string", - "averageWinningTradeDuration": "string", - "averageLosingTradeDuration": "string", - "medianTradeDuration": "string", - "medianWinningTradeDuration": "string", - "medianLosingTradeDuration": "string", - "maxConsecutiveWinningTrades": 0, - "maxConsecutiveLosingTrades": 0, - "profitLossRatio": "string", - "winLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "averageMAE": "string", - "averageMFE": "string", - "largestMAE": "string", - "largestMFE": "string", - "maximumClosedTradeDrawdown": "string", - "maximumIntraTradeDrawdown": "string", - "profitLossStandardDeviation": "string", - "profitLossDownsideDeviation": "string", - "profitFactor": "string", - "sharpeRatio": "string", - "sortinoRatio": "string", - "profitToMaxDrawdownRatio": "string", - "maximumEndTradeDrawdown": "string", - "averageEndTradeDrawdown": "string", - "maximumDrawdownDuration": "string", - "totalFees": "string" - }, - "portfolioStatistics": { - "averageWinRate": "string", - "averageLossRate": "string", - "profitLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "expectancy": "string", - "startEquity": "string", - "endEquity": "string", - "compoundingAnnualReturn": "string", - "drawdown": "string", - "totalNetProfit": "string", - "sharpeRatio": "string", - "probabilisticSharpeRatio": "string", - "sortinoRatio": "string", - "alpha": "string", - "beta": "string", - "annualStandardDeviation": "string", - "annualVariance": "string", - "informationRatio": "string", - "trackingError": "string", - "treynorRatio": "string", - "portfolioTurnover": "string", - "valueAtRisk99": "string", - "valueAtRisk95": "string", - "drawdownRecovery": "string" - }, - "closedTrades": [ - { - "symbol": { - "value": "string", - "id": "string", - "permtick": "string" - }, - "entryTime": "2021-11-26T15:18:27.693Z", - "entryPrice": 0, - "direction": 0, - "quantity": 0, - "exitTime": "2021-11-26T15:18:27.693Z", - "exitPrice": 0, - "profitLoss": 0, - "totalFees": 0, - "mae": 0, - "mfe": 0, - "duration": "string", - "endTradeDrawdown": 0 - } - ] - }, +}, "runtimeStatistics": { "Equity": "$100.00", "Fees": "-$100.00", @@ -63064,7 +63689,21 @@

}, "nodeName": "string", "outOfSampleMaxEndDate": "2021-11-26T15:18:27.693Z", - "outOfSampleDays": 0 + "outOfSampleDays": 0, + "analysis": [ + { + "name": "PerformanceRelativeToBenchmarkAnalysis", + "issue": "The strategy has a lower Sharpe ratio than the benchmark.", + "sample": { + "backtestSharpe": -0.2281345806218534, + "benchmarkSharpe": -0.22182175736916387 + }, + "count": 5, + "solutions": [ + "Try adjusting the trading rules and/or the universe to get a strategy that outperforms the benchmark." + ] + } + ] } @@ -63175,1223 +63814,1204 @@

- AlgorithmPerformance + RuntimeStatistics - Model - The AlgorithmPerformance class is a wrapper for TradeStatistics and PortfolioStatistics. + Model - tradeStatistics + Equity - TradeStatistics object + string +
+ + + example: $100.00 + +

- A set of statistics calculated from a list of closed trades. + Total portfolio value. - portfolioStatistics + Fees - PortfolioStatistics object + string +
+ + + example: -$100.00 + +

- Represents a set of statistics calculated from equity and benchmark samples. + Transaction fee. - closedTrades + Holdings - Trade Array + string +
+ + + example: $100.00 + +

- The algorithm statistics on portfolio. + Equity value of security holdings. - Example + Net Profit -
-
-{
-  "tradeStatistics": {
-    "startDateTime": "2021-11-26T15:18:27.693Z",
-    "endDateTime": "2021-11-26T15:18:27.693Z",
-    "totalNumberOfTrades": 0,
-    "numberOfWinningTrades": 0,
-    "numberOfLosingTrades": 0,
-    "totalProfitLoss": "string",
-    "totalProfit": "string",
-    "totalLoss": "string",
-    "largestProfit": "string",
-    "largestLoss": "string",
-    "averageProfitLoss": "string",
-    "averageProfit": "string",
-    "averageLoss": "string",
-    "averageTradeDuration": "string",
-    "averageWinningTradeDuration": "string",
-    "averageLosingTradeDuration": "string",
-    "medianTradeDuration": "string",
-    "medianWinningTradeDuration": "string",
-    "medianLosingTradeDuration": "string",
-    "maxConsecutiveWinningTrades": 0,
-    "maxConsecutiveLosingTrades": 0,
-    "profitLossRatio": "string",
-    "winLossRatio": "string",
-    "winRate": "string",
-    "lossRate": "string",
-    "averageMAE": "string",
-    "averageMFE": "string",
-    "largestMAE": "string",
-    "largestMFE": "string",
-    "maximumClosedTradeDrawdown": "string",
-    "maximumIntraTradeDrawdown": "string",
-    "profitLossStandardDeviation": "string",
-    "profitLossDownsideDeviation": "string",
-    "profitFactor": "string",
-    "sharpeRatio": "string",
-    "sortinoRatio": "string",
-    "profitToMaxDrawdownRatio": "string",
-    "maximumEndTradeDrawdown": "string",
-    "averageEndTradeDrawdown": "string",
-    "maximumDrawdownDuration": "string",
-    "totalFees": "string"
-  },
-  "portfolioStatistics": {
-    "averageWinRate": "string",
-    "averageLossRate": "string",
-    "profitLossRatio": "string",
-    "winRate": "string",
-    "lossRate": "string",
-    "expectancy": "string",
-    "startEquity": "string",
-    "endEquity": "string",
-    "compoundingAnnualReturn": "string",
-    "drawdown": "string",
-    "totalNetProfit": "string",
-    "sharpeRatio": "string",
-    "probabilisticSharpeRatio": "string",
-    "sortinoRatio": "string",
-    "alpha": "string",
-    "beta": "string",
-    "annualStandardDeviation": "string",
-    "annualVariance": "string",
-    "informationRatio": "string",
-    "trackingError": "string",
-    "treynorRatio": "string",
-    "portfolioTurnover": "string",
-    "valueAtRisk99": "string",
-    "valueAtRisk95": "string",
-    "drawdownRecovery": "string"
-  },
-  "closedTrades": [
-    {
-      "symbol": {
-        "value": "string",
-        "id": "string",
-        "permtick": "string"
-      },
-      "entryTime": "2021-11-26T15:18:27.693Z",
-      "entryPrice": 0,
-      "direction": 0,
-      "quantity": 0,
-      "exitTime": "2021-11-26T15:18:27.693Z",
-      "exitPrice": 0,
-      "profitLoss": 0,
-      "totalFees": 0,
-      "mae": 0,
-      "mfe": 0,
-      "duration": "string",
-      "endTradeDrawdown": 0
-    }
-  ]
-}
-
+ + string +
+ + + example: $100.00 + + +
+
+ Net profit. - - - - - - - +
- - TradeStatistics - - Model - A set of statistics calculated from a list of closed trades. -
- startDateTime + Probabilistic Sharpe Ratio - string($date-time) + string +
+ + + example: 50.00% + +

- The entry date/time of the first trade. + Probabilistic Sharpe Ratio.
- endDateTime + Return - string($date-time) + string +
+ + + example: 50.00% + +

- The exit date/time of the first trade. + Return.
- totalNumberOfTrades + Unrealized - integer + string +
+ + + example: $100.00 + +

- The total number of trades. + Unrealized profit/loss.
- numberOfWinningTrades + Volume - integer + string +
+ + + example: $100.00 + +

- The total number of winning trades. + Total transaction volume.
- numberOfLosingTrades + Example - - integer - -
- The total number of losing trades. +
+
+{
+  "Equity": "$100.00",
+  "Fees": "-$100.00",
+  "Holdings": "$100.00",
+  "Net Profit": "$100.00",
+  "Probabilistic Sharpe Ratio": "50.00%",
+  "Return": "50.00%",
+  "Unrealized": "$100.00",
+  "Volume": "$100.00"
+}
+
+ + + + + + +
+ + StatisticsResult + + Model - Statistics information sent during the algorithm operations. +
- totalProfitLoss + Total Orders string
- The total profit/loss for all trades (as symbol currency). + Total nuber of orders.
- totalProfit + Average Win string
- The total profit for all winning trades (as symbol currency). + The average rate of return for winning trades.
- totalLoss + Average Loss string
- The total loss for all losing trades (as symbol currency). + The average rate of return for losing trades.
- largestProfit + Compounding Annual Return string
- The largest profit in a single trade (as symbol currency). + Annual compounded returns statistic based on the final-starting capital and years.
- largestLoss + Drawdown string
- The largest loss in a single trade (as symbol currency). + Drawdown maximum percentage.
- averageProfitLoss + Expectancy string
- The average profit/loss (a.k.a. Expectancy or Average Trade) for all trades (as symbol currency). + The expected value of the rate of return.
- averageProfit + Start Equity string
- The average profit for all winning trades (as symbol currency). + Initial Equity Total Value.
- averageLoss + End Equity string
- The average loss for all winning trades (as symbol currency). + Final Equity Total Value.
- averageTradeDuration + Net Profit string
- The average duration for all trades. + The total net profit percentage.
- averageWinningTradeDuration + Sharpe Ratio string
- The average duration for all winning trades. + Sharpe ratio with respect to risk free rate; measures excess of return per unit of risk.
- averageLosingTradeDuration + Sortino Ratio string
- The average duration for all losing trades. + Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk.
- medianTradeDuration + Probabilistic Sharpe Ratio string
- The median duration for all trades. + Is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark.
- medianWinningTradeDuration + Loss Rate string
- The median duration for all winning trades. + The ratio of the number of losing trades to the total number of trades.
- medianLosingTradeDuration + Win Rate string
- The median duration for all losing trades. + The ratio of the number of winning trades to the total number of trades.
- maxConsecutiveWinningTrades + Profit-Loss Ratio - integer + string
- The maximum number of consecutive winning trades. + The ratio of the average win rate to the average loss rate.
- maxConsecutiveLosingTrades + Alpha - integer + string
- The maximum number of consecutive losing trades. + Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns.
- profitLossRatio + Beta string
- The ratio of the average profit per trade to the average loss per trade. + Algorithm "beta" statistic - the covariance between the algorithm and benchmark performance, divided by benchmark's variance.
- winLossRatio + Annual Standard Deviation string
- The ratio of the number of winning trades to the number of losing trades. + Annualized standard deviation.
- winRate + Annual Variance string
- The ratio of the number of winning trades to the total number of trades. + Annualized variance statistic calculation using the daily performance variance and trading days per year.
- lossRate + Information Ratio string
- The ratio of the number of losing trades to the total number of trades. + Information ratio - risk adjusted return.
- averageMAE + Tracking Error string
- The average Maximum Adverse Excursion for all trades. + Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked.
- averageMFE + Treynor Ratio string
- The average Maximum Adverse Excursion for all trades. + Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk.
- largestMAE + Total Fees string
- The average Maximum Favorable Excursion for all trades. + Total amount of fees.
- largestMFE + Estimated Strategy Capacity string
- The largest Maximum Adverse Excursion in a single trade (as symbol currency). + The estimated total capacity of the strategy at a point in time.
- maximumClosedTradeDrawdown + Lowest Capacity Asset string
- The maximum closed-trade drawdown for all trades (as symbol currency). + Provide a reference to the lowest capacity symbol used in scaling down the capacity for debugging.
- maximumIntraTradeDrawdown + Portfolio Turnover string
- The maximum intra-trade drawdown for all trades (as symbol currency). + The average Portfolio Turnover.
- profitLossStandardDeviation + Drawdown Recovery string
- The standard deviation of the profits/losses for all trades (as symbol currency). + /.
- profitLossDownsideDeviation + Example - - string - -
- The downside deviation of the profits/losses for all trades (as symbol currency). +
+
+{
+  "Total Orders": "string",
+  "Average Win": "string",
+  "Average Loss": "string",
+  "Compounding Annual Return": "string",
+  "Drawdown": "string",
+  "Expectancy": "string",
+  "Start Equity": "string",
+  "End Equity": "string",
+  "Net Profit": "string",
+  "Sharpe Ratio": "string",
+  "Sortino Ratio": "string",
+  "Probabilistic Sharpe Ratio": "string",
+  "Loss Rate": "string",
+  "Win Rate": "string",
+  "Profit-Loss Ratio": "string",
+  "Alpha": "string",
+  "Beta": "string",
+  "Annual Standard Deviation": "string",
+  "Annual Variance": "string",
+  "Information Ratio": "string",
+  "Tracking Error": "string",
+  "Treynor Ratio": "string",
+  "Total Fees": "string",
+  "Estimated Strategy Capacity": "string",
+  "Lowest Capacity Asset": "string",
+  "Portfolio Turnover": "string",
+  "Drawdown Recovery": "string"
+}
+
+ + + + + + +
+ + AlgorithmPerformance + + Model - The AlgorithmPerformance class is a wrapper for TradeStatistics and PortfolioStatistics. +
- profitFactor + tradeStatistics - string + TradeStatistics object
- The ratio of the total profit to the total loss. + A set of statistics calculated from a list of closed trades.
- sharpeRatio + portfolioStatistics - string + PortfolioStatistics object
- The ratio of the average profit/loss to the standard deviation. + Represents a set of statistics calculated from equity and benchmark samples.
- sortinoRatio + closedTrades - string + Trade Array
- The ratio of the average profit/loss to the downside deviation. + The algorithm statistics on portfolio.
- profitToMaxDrawdownRatio + Example - - string - -
- The ratio of the total profit/loss to the maximum closed trade drawdown. +
+
+{
+  "tradeStatistics": {
+    "startDateTime": "2021-11-26T15:18:27.693Z",
+    "endDateTime": "2021-11-26T15:18:27.693Z",
+    "totalNumberOfTrades": 0,
+    "numberOfWinningTrades": 0,
+    "numberOfLosingTrades": 0,
+    "totalProfitLoss": "string",
+    "totalProfit": "string",
+    "totalLoss": "string",
+    "largestProfit": "string",
+    "largestLoss": "string",
+    "averageProfitLoss": "string",
+    "averageProfit": "string",
+    "averageLoss": "string",
+    "averageTradeDuration": "string",
+    "averageWinningTradeDuration": "string",
+    "averageLosingTradeDuration": "string",
+    "medianTradeDuration": "string",
+    "medianWinningTradeDuration": "string",
+    "medianLosingTradeDuration": "string",
+    "maxConsecutiveWinningTrades": 0,
+    "maxConsecutiveLosingTrades": 0,
+    "profitLossRatio": "string",
+    "winLossRatio": "string",
+    "winRate": "string",
+    "lossRate": "string",
+    "averageMAE": "string",
+    "averageMFE": "string",
+    "largestMAE": "string",
+    "largestMFE": "string",
+    "maximumClosedTradeDrawdown": "string",
+    "maximumIntraTradeDrawdown": "string",
+    "profitLossStandardDeviation": "string",
+    "profitLossDownsideDeviation": "string",
+    "profitFactor": "string",
+    "sharpeRatio": "string",
+    "sortinoRatio": "string",
+    "profitToMaxDrawdownRatio": "string",
+    "maximumEndTradeDrawdown": "string",
+    "averageEndTradeDrawdown": "string",
+    "maximumDrawdownDuration": "string",
+    "totalFees": "string"
+  },
+  "portfolioStatistics": {
+    "averageWinRate": "string",
+    "averageLossRate": "string",
+    "profitLossRatio": "string",
+    "winRate": "string",
+    "lossRate": "string",
+    "expectancy": "string",
+    "startEquity": "string",
+    "endEquity": "string",
+    "compoundingAnnualReturn": "string",
+    "drawdown": "string",
+    "totalNetProfit": "string",
+    "sharpeRatio": "string",
+    "probabilisticSharpeRatio": "string",
+    "sortinoRatio": "string",
+    "alpha": "string",
+    "beta": "string",
+    "annualStandardDeviation": "string",
+    "annualVariance": "string",
+    "informationRatio": "string",
+    "trackingError": "string",
+    "treynorRatio": "string",
+    "portfolioTurnover": "string",
+    "valueAtRisk99": "string",
+    "valueAtRisk95": "string",
+    "drawdownRecovery": "string"
+  },
+  "closedTrades": [
+    {
+      "symbol": {
+        "value": "string",
+        "id": "string",
+        "permtick": "string"
+      },
+      "entryTime": "2021-11-26T15:18:27.693Z",
+      "entryPrice": 0,
+      "direction": 0,
+      "quantity": 0,
+      "exitTime": "2021-11-26T15:18:27.693Z",
+      "exitPrice": 0,
+      "profitLoss": 0,
+      "totalFees": 0,
+      "mae": 0,
+      "mfe": 0,
+      "duration": "string",
+      "endTradeDrawdown": 0
+    }
+  ]
+}
+
+ + + + + + -
+ + TradeStatistics + + Model - A set of statistics calculated from a list of closed trades. +
- maximumEndTradeDrawdown + startDateTime - string + string($date-time)
- The maximum amount of profit given back by a single trade before exit (as symbol currency). + The entry date/time of the first trade.
- averageEndTradeDrawdown + endDateTime - string + string($date-time)
- The average amount of profit given back by all trades before exit (as symbol currency). + The exit date/time of the first trade.
- maximumDrawdownDuration + totalNumberOfTrades - string + integer
- The maximum amount of time to recover from a drawdown (longest time between new equity highs or peaks). + The total number of trades.
- totalFees + numberOfWinningTrades - string + integer
- The sum of fees for all trades. + The total number of winning trades.
- Example + numberOfLosingTrades -
-
-{
-  "startDateTime": "2021-11-26T15:18:27.693Z",
-  "endDateTime": "2021-11-26T15:18:27.693Z",
-  "totalNumberOfTrades": 0,
-  "numberOfWinningTrades": 0,
-  "numberOfLosingTrades": 0,
-  "totalProfitLoss": "string",
-  "totalProfit": "string",
-  "totalLoss": "string",
-  "largestProfit": "string",
-  "largestLoss": "string",
-  "averageProfitLoss": "string",
-  "averageProfit": "string",
-  "averageLoss": "string",
-  "averageTradeDuration": "string",
-  "averageWinningTradeDuration": "string",
-  "averageLosingTradeDuration": "string",
-  "medianTradeDuration": "string",
-  "medianWinningTradeDuration": "string",
-  "medianLosingTradeDuration": "string",
-  "maxConsecutiveWinningTrades": 0,
-  "maxConsecutiveLosingTrades": 0,
-  "profitLossRatio": "string",
-  "winLossRatio": "string",
-  "winRate": "string",
-  "lossRate": "string",
-  "averageMAE": "string",
-  "averageMFE": "string",
-  "largestMAE": "string",
-  "largestMFE": "string",
-  "maximumClosedTradeDrawdown": "string",
-  "maximumIntraTradeDrawdown": "string",
-  "profitLossStandardDeviation": "string",
-  "profitLossDownsideDeviation": "string",
-  "profitFactor": "string",
-  "sharpeRatio": "string",
-  "sortinoRatio": "string",
-  "profitToMaxDrawdownRatio": "string",
-  "maximumEndTradeDrawdown": "string",
-  "averageEndTradeDrawdown": "string",
-  "maximumDrawdownDuration": "string",
-  "totalFees": "string"
-}
-
+ + integer + +
+ The total number of losing trades.
- - - - - - -
- - PortfolioStatistics - - Model - Represents a set of statistics calculated from equity and benchmark samples. -
- averageWinRate + totalProfitLoss string
- The average rate of return for winning trades. + The total profit/loss for all trades (as symbol currency).
- averageLossRate + totalProfit string
- The average rate of return for losing trades. + The total profit for all winning trades (as symbol currency).
- profitLossRatio + totalLoss string
- The ratio of the average win rate to the average loss rate. + The total loss for all losing trades (as symbol currency).
- winRate + largestProfit string
- The ratio of the number of winning trades to the total number of trades. + The largest profit in a single trade (as symbol currency).
- lossRate + largestLoss string
- The ratio of the number of losing trades to the total number of trades. + The largest loss in a single trade (as symbol currency).
- expectancy + averageProfitLoss string
- The expected value of the rate of return. + The average profit/loss (a.k.a. Expectancy or Average Trade) for all trades (as symbol currency).
- startEquity + averageProfit string
- Initial Equity Total Value. + The average profit for all winning trades (as symbol currency).
- endEquity + averageLoss string
- Final Equity Total Value. + The average loss for all winning trades (as symbol currency).
- compoundingAnnualReturn + averageTradeDuration string
- Annual compounded returns statistic based on the final-starting capital and years. + The average duration for all trades.
- drawdown + averageWinningTradeDuration string
- Drawdown maximum percentage. + The average duration for all winning trades.
- totalNetProfit + averageLosingTradeDuration string
- The total net profit percentage. + The average duration for all losing trades.
- sharpeRatio + medianTradeDuration string
- Sharpe ratio with respect to risk free rate: measures excess of return per unit of risk. + The median duration for all trades.
- probabilisticSharpeRatio + medianWinningTradeDuration string
- Probabilistic Sharpe Ratio is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark. + The median duration for all winning trades.
- sortinoRatio + medianLosingTradeDuration string
- Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk. + The median duration for all losing trades.
- alpha + maxConsecutiveWinningTrades - string + integer
- Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns. + The maximum number of consecutive winning trades.
- beta + maxConsecutiveLosingTrades - string + integer
- Algorithm beta statistic - the covariance between the algorithm and benchmark performance, divided by benchmark variance. + The maximum number of consecutive losing trades.
- annualStandardDeviation + profitLossRatio string
- Annualized standard deviation. + The ratio of the average profit per trade to the average loss per trade.
- annualVariance + winLossRatio string
- Annualized variance statistic calculation using the daily performance variance and trading days per year. + The ratio of the number of winning trades to the number of losing trades.
- informationRatio + winRate string
- Information ratio - risk adjusted return. + The ratio of the number of winning trades to the total number of trades.
- trackingError + lossRate string
- Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked. + The ratio of the number of losing trades to the total number of trades.
- treynorRatio + averageMAE string
- Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk. + The average Maximum Adverse Excursion for all trades.
- portfolioTurnover + averageMFE string
- The average Portfolio Turnover. + The average Maximum Adverse Excursion for all trades.
- valueAtRisk99 + largestMAE string
- The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 99% confidence level, 1 year lookback period, and that the returns are normally distributed. + The average Maximum Favorable Excursion for all trades.
- valueAtRisk95 + largestMFE string
- The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 95% confidence level, 1 year lookback period, and that the returns are normally distributed. + The largest Maximum Adverse Excursion in a single trade (as symbol currency).
- drawdownRecovery + maximumClosedTradeDrawdown string
- /. + The maximum closed-trade drawdown for all trades (as symbol currency).
- Example + maximumIntraTradeDrawdown -
-
-{
-  "averageWinRate": "string",
-  "averageLossRate": "string",
-  "profitLossRatio": "string",
-  "winRate": "string",
-  "lossRate": "string",
-  "expectancy": "string",
-  "startEquity": "string",
-  "endEquity": "string",
-  "compoundingAnnualReturn": "string",
-  "drawdown": "string",
-  "totalNetProfit": "string",
-  "sharpeRatio": "string",
-  "probabilisticSharpeRatio": "string",
-  "sortinoRatio": "string",
-  "alpha": "string",
-  "beta": "string",
-  "annualStandardDeviation": "string",
-  "annualVariance": "string",
-  "informationRatio": "string",
-  "trackingError": "string",
-  "treynorRatio": "string",
-  "portfolioTurnover": "string",
-  "valueAtRisk99": "string",
-  "valueAtRisk95": "string",
-  "drawdownRecovery": "string"
-}
-
+ + string + +
+ The maximum intra-trade drawdown for all trades (as symbol currency).
- - - - - - - - - - - - - - - - - - @@ -64402,23 +65022,47 @@

 {
-  "symbol": {
-    "value": "string",
-    "id": "string",
-    "permtick": "string"
-  },
-  "entryTime": "2021-11-26T15:18:27.693Z",
-  "entryPrice": 0,
-  "direction": 0,
-  "quantity": 0,
-  "exitTime": "2021-11-26T15:18:27.693Z",
-  "exitPrice": 0,
-  "profitLoss": 0,
-  "totalFees": 0,
-  "mae": 0,
-  "mfe": 0,
-  "duration": "string",
-  "endTradeDrawdown": 0
+  "startDateTime": "2021-11-26T15:18:27.693Z",
+  "endDateTime": "2021-11-26T15:18:27.693Z",
+  "totalNumberOfTrades": 0,
+  "numberOfWinningTrades": 0,
+  "numberOfLosingTrades": 0,
+  "totalProfitLoss": "string",
+  "totalProfit": "string",
+  "totalLoss": "string",
+  "largestProfit": "string",
+  "largestLoss": "string",
+  "averageProfitLoss": "string",
+  "averageProfit": "string",
+  "averageLoss": "string",
+  "averageTradeDuration": "string",
+  "averageWinningTradeDuration": "string",
+  "averageLosingTradeDuration": "string",
+  "medianTradeDuration": "string",
+  "medianWinningTradeDuration": "string",
+  "medianLosingTradeDuration": "string",
+  "maxConsecutiveWinningTrades": 0,
+  "maxConsecutiveLosingTrades": 0,
+  "profitLossRatio": "string",
+  "winLossRatio": "string",
+  "winRate": "string",
+  "lossRate": "string",
+  "averageMAE": "string",
+  "averageMFE": "string",
+  "largestMAE": "string",
+  "largestMFE": "string",
+  "maximumClosedTradeDrawdown": "string",
+  "maximumIntraTradeDrawdown": "string",
+  "profitLossStandardDeviation": "string",
+  "profitLossDownsideDeviation": "string",
+  "profitFactor": "string",
+  "sharpeRatio": "string",
+  "sortinoRatio": "string",
+  "profitToMaxDrawdownRatio": "string",
+  "maximumEndTradeDrawdown": "string",
+  "averageEndTradeDrawdown": "string",
+  "maximumDrawdownDuration": "string",
+  "totalFees": "string"
 }
@@ -64429,573 +65073,515 @@

- - - - -
- - Trade - - Model - Represents a closed trade. -
- symbol + profitLossStandardDeviation - Symbol object + string
- Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security. + The standard deviation of the profits/losses for all trades (as symbol currency).
- entryTime + profitLossDownsideDeviation - string($date-time) + string
- The date and time the trade was opened. + The downside deviation of the profits/losses for all trades (as symbol currency).
- entryPrice + profitFactor - number + string
- The price at which the trade was opened (or the average price if multiple entries). + The ratio of the total profit to the total loss.
- direction + sharpeRatio - integer Enum + string
- Direction of a trade. 0=Long, 1=Short. Options : [0, 1] + The ratio of the average profit/loss to the standard deviation.
- quantity + sortinoRatio - number + string
- The total unsigned quantity of the trade. + The ratio of the average profit/loss to the downside deviation.
- exitTime + profitToMaxDrawdownRatio - string($date-time) - -
- The date and time the trade was closed. -
- exitPrice - - - number - -
- The price at which the trade was closed (or the average price if multiple exits). -
- profitLoss - - - number - -
- The gross profit/loss of the trade (as account currency). -
- totalFees - - - number + string
- The total fees associated with the trade (always positive value) (as account currency). + The ratio of the total profit/loss to the maximum closed trade drawdown.
- mae + maximumEndTradeDrawdown - number + string
- The Maximum Adverse Excursion (as account currency). + The maximum amount of profit given back by a single trade before exit (as symbol currency).
- mfe + averageEndTradeDrawdown - number + string
- The Maximum Favorable Excursion (as account currency). + The average amount of profit given back by all trades before exit (as symbol currency).
- duration + maximumDrawdownDuration string
- The duration of the trade. + The maximum amount of time to recover from a drawdown (longest time between new equity highs or peaks).
- endTradeDrawdown + totalFees - number + string
- The amount of profit given back before the trade was closed. + The sum of fees for all trades.
- Symbol + PortfolioStatistics - Model - Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security. + Model - Represents a set of statistics calculated from equity and benchmark samples.
- value + averageWinRate string
- The current symbol for this ticker. + The average rate of return for winning trades.
- id + averageLossRate string
- The security identifier for this symbol. + The average rate of return for losing trades.
- permtick + profitLossRatio string
- The ticker at IPO for this security. -
- Example - -
-
-{
-  "value": "string",
-  "id": "string",
-  "permtick": "string"
-}
-
+ The ratio of the average win rate to the average loss rate.
- - - - - - -
- - RuntimeStatistics - - Model -
- Equity + winRate string -
- - - example: $100.00 - -

- Total portfolio value. + The ratio of the number of winning trades to the total number of trades.
- Fees + lossRate string -
- - - example: -$100.00 - -

- Transaction fee. + The ratio of the number of losing trades to the total number of trades.
- Holdings + expectancy string -
- - - example: $100.00 - -

- Equity value of security holdings. + The expected value of the rate of return.
- Net Profit + startEquity string -
- - - example: $100.00 - -

- Net profit. + Initial Equity Total Value.
- Probabilistic Sharpe Ratio + endEquity string -
- - - example: 50.00% - -

- Probabilistic Sharpe Ratio. + Final Equity Total Value.
- Return + compoundingAnnualReturn string -
- - - example: 50.00% - -

- Return. + Annual compounded returns statistic based on the final-starting capital and years.
- Unrealized + drawdown string -
- - - example: $100.00 - -

- Unrealized profit/loss. + Drawdown maximum percentage.
- Volume + totalNetProfit string -
- - - example: $100.00 - -

- Total transaction volume. + The total net profit percentage.
- Example + sharpeRatio -
-
-{
-  "Equity": "$100.00",
-  "Fees": "-$100.00",
-  "Holdings": "$100.00",
-  "Net Profit": "$100.00",
-  "Probabilistic Sharpe Ratio": "50.00%",
-  "Return": "50.00%",
-  "Unrealized": "$100.00",
-  "Volume": "$100.00"
-}
-
+ + string + +
+ Sharpe ratio with respect to risk free rate: measures excess of return per unit of risk.
- - - - - - +
- - StatisticsResult - - Model - Statistics information sent during the algorithm operations. -
- Total Orders + probabilisticSharpeRatio string
- Total nuber of orders. + Probabilistic Sharpe Ratio is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark.
- Average Win + sortinoRatio string
- The average rate of return for winning trades. + Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk.
- Average Loss + alpha string
- The average rate of return for losing trades. + Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns.
- Compounding Annual Return + beta string
- Annual compounded returns statistic based on the final-starting capital and years. + Algorithm beta statistic - the covariance between the algorithm and benchmark performance, divided by benchmark variance.
- Drawdown + annualStandardDeviation string
- Drawdown maximum percentage. + Annualized standard deviation.
- Expectancy + annualVariance string
- The expected value of the rate of return. + Annualized variance statistic calculation using the daily performance variance and trading days per year.
- Start Equity + informationRatio string
- Initial Equity Total Value. + Information ratio - risk adjusted return.
- End Equity + trackingError string
- Final Equity Total Value. + Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked.
- Net Profit + treynorRatio string
- The total net profit percentage. + Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk.
- Sharpe Ratio + portfolioTurnover string
- Sharpe ratio with respect to risk free rate; measures excess of return per unit of risk. + The average Portfolio Turnover.
- Sortino Ratio + valueAtRisk99 string
- Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk. + The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 99% confidence level, 1 year lookback period, and that the returns are normally distributed.
- Probabilistic Sharpe Ratio + valueAtRisk95 string
- Is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark. + The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 95% confidence level, 1 year lookback period, and that the returns are normally distributed.
- Loss Rate + drawdownRecovery string
- The ratio of the number of losing trades to the total number of trades. + /.
- Win Rate + Example - - string - -
- The ratio of the number of winning trades to the total number of trades. +
+
+{
+  "averageWinRate": "string",
+  "averageLossRate": "string",
+  "profitLossRatio": "string",
+  "winRate": "string",
+  "lossRate": "string",
+  "expectancy": "string",
+  "startEquity": "string",
+  "endEquity": "string",
+  "compoundingAnnualReturn": "string",
+  "drawdown": "string",
+  "totalNetProfit": "string",
+  "sharpeRatio": "string",
+  "probabilisticSharpeRatio": "string",
+  "sortinoRatio": "string",
+  "alpha": "string",
+  "beta": "string",
+  "annualStandardDeviation": "string",
+  "annualVariance": "string",
+  "informationRatio": "string",
+  "trackingError": "string",
+  "treynorRatio": "string",
+  "portfolioTurnover": "string",
+  "valueAtRisk99": "string",
+  "valueAtRisk95": "string",
+  "drawdownRecovery": "string"
+}
+
+ + + + + + @@ -65006,70 +65592,265 @@

 {
-  "Total Orders": "string",
-  "Average Win": "string",
-  "Average Loss": "string",
-  "Compounding Annual Return": "string",
-  "Drawdown": "string",
-  "Expectancy": "string",
-  "Start Equity": "string",
-  "End Equity": "string",
-  "Net Profit": "string",
-  "Sharpe Ratio": "string",
-  "Sortino Ratio": "string",
-  "Probabilistic Sharpe Ratio": "string",
-  "Loss Rate": "string",
-  "Win Rate": "string",
-  "Profit-Loss Ratio": "string",
-  "Alpha": "string",
-  "Beta": "string",
-  "Annual Standard Deviation": "string",
-  "Annual Variance": "string",
-  "Information Ratio": "string",
-  "Tracking Error": "string",
-  "Treynor Ratio": "string",
-  "Total Fees": "string",
-  "Estimated Strategy Capacity": "string",
-  "Lowest Capacity Asset": "string",
-  "Portfolio Turnover": "string",
-  "Drawdown Recovery": "string"
+  "symbol": {
+    "value": "string",
+    "id": "string",
+    "permtick": "string"
+  },
+  "entryTime": "2021-11-26T15:18:27.693Z",
+  "entryPrice": 0,
+  "direction": 0,
+  "quantity": 0,
+  "exitTime": "2021-11-26T15:18:27.693Z",
+  "exitPrice": 0,
+  "profitLoss": 0,
+  "totalFees": 0,
+  "mae": 0,
+  "mfe": 0,
+  "duration": "string",
+  "endTradeDrawdown": 0
 }

+ + Trade + + Model - Represents a closed trade. +
- Profit-Loss Ratio + symbol - string + Symbol object
- The ratio of the average win rate to the average loss rate. + Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security.
- Alpha + entryTime - string + string($date-time)
- Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns. + The date and time the trade was opened.
- Beta + entryPrice - string + number
- Algorithm "beta" statistic - the covariance between the algorithm and benchmark performance, divided by benchmark's variance. + The price at which the trade was opened (or the average price if multiple entries).
- Annual Standard Deviation + direction - string + integer Enum
- Annualized standard deviation. + Direction of a trade. 0=Long, 1=Short. Options : [0, 1]
- Annual Variance + quantity - string + number
- Annualized variance statistic calculation using the daily performance variance and trading days per year. + The total unsigned quantity of the trade.
- Information Ratio + exitTime - string + string($date-time)
- Information ratio - risk adjusted return. + The date and time the trade was closed.
- Tracking Error + exitPrice - string + number
- Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked. + The price at which the trade was closed (or the average price if multiple exits).
- Treynor Ratio + profitLoss - string + number
- Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk. + The gross profit/loss of the trade (as account currency).
- Total Fees + totalFees - string + number
- Total amount of fees. + The total fees associated with the trade (always positive value) (as account currency).
- Estimated Strategy Capacity + mae - string + number
- The estimated total capacity of the strategy at a point in time. + The Maximum Adverse Excursion (as account currency).
- Lowest Capacity Asset + mfe - string + number
- Provide a reference to the lowest capacity symbol used in scaling down the capacity for debugging. + The Maximum Favorable Excursion (as account currency).
- Portfolio Turnover + duration string
- The average Portfolio Turnover. + The duration of the trade.
- Drawdown Recovery + endTradeDrawdown - string + number
- /. + The amount of profit given back before the trade was closed.
-

- 401 Authentication Error -

-
- UnauthorizedError + Symbol - Model - Unauthorized response from the API. Key is missing, invalid, or timestamp is too old for hash. + Model - Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security.
- www_authenticate + value string
- Header + The current symbol for this ticker.
- - - -

Examples

- + + + id + + + + string + +
+ The security identifier for this symbol. + + + + + permtick + + + + string + +
+ The ticker at IPO for this security. + + + + + Example + + +
+
+{
+  "value": "string",
+  "id": "string",
+  "permtick": "string"
+}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + AnalysisResult + + Model - The result of an analysis performed on a result. +
+ name + + + string +
+ + + required + + +
+ + + example: PerformanceRelativeToBenchmarkAnalysis + + +
+
+ The name of the analysis that produced this result. +
+ issue + + + string +
+ + + required + + +
+ + + example: The strategy has a lower Sharpe ratio than the benchmark. + + +
+
+ A short description of why the analysis was triggered. +
+ sample + + + object +
+ + + required + + +
+ + + example: {'backtestSharpe': -0.2281345806218534, 'benchmarkSharpe': -0.22182175736916387} + + +
+
+ A representative sample value of the issue detected by the analysis. +
+ count + + + integer +
+ + + example: 5 + + +
+
+ The total number of matching occurrences found by the analysis. If not present, it should be assumed that there is only one occurrence. +
+ solutions + + + string Array +
+ + + required + + +
+
+ Human-readable suggestions for resolving the detected issue. +
+ Example + +
+
+{
+  "name": "PerformanceRelativeToBenchmarkAnalysis",
+  "issue": "The strategy has a lower Sharpe ratio than the benchmark.",
+  "sample": {
+    "backtestSharpe": -0.2281345806218534,
+    "benchmarkSharpe": -0.22182175736916387
+  },
+  "count": 5,
+  "solutions": [
+    "Try adjusting the trading rules and/or the universe to get a strategy that outperforms the benchmark."
+  ]
+}
+
+
+

+ 401 Authentication Error +

+ + + + + + + + + + +
+ + UnauthorizedError + + Model - Unauthorized response from the API. Key is missing, invalid, or timestamp is too old for hash. +
+ www_authenticate + + + string + +
+ Header +
+ + + +

Examples

+

The following example demonstates creating, reading, updating, deleting, and listing backtests of a project through the cloud API. @@ -65473,98 +66254,7 @@

}, "parameterSet": , "rollingWindow": { - "tradeStatistics": { - "startDateTime": "2021-11-26T15:18:27.693Z", - "endDateTime": "2021-11-26T15:18:27.693Z", - "totalNumberOfTrades": 0, - "numberOfWinningTrades": 0, - "numberOfLosingTrades": 0, - "totalProfitLoss": "string", - "totalProfit": "string", - "totalLoss": "string", - "largestProfit": "string", - "largestLoss": "string", - "averageProfitLoss": "string", - "averageProfit": "string", - "averageLoss": "string", - "averageTradeDuration": "string", - "averageWinningTradeDuration": "string", - "averageLosingTradeDuration": "string", - "medianTradeDuration": "string", - "medianWinningTradeDuration": "string", - "medianLosingTradeDuration": "string", - "maxConsecutiveWinningTrades": 0, - "maxConsecutiveLosingTrades": 0, - "profitLossRatio": "string", - "winLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "averageMAE": "string", - "averageMFE": "string", - "largestMAE": "string", - "largestMFE": "string", - "maximumClosedTradeDrawdown": "string", - "maximumIntraTradeDrawdown": "string", - "profitLossStandardDeviation": "string", - "profitLossDownsideDeviation": "string", - "profitFactor": "string", - "sharpeRatio": "string", - "sortinoRatio": "string", - "profitToMaxDrawdownRatio": "string", - "maximumEndTradeDrawdown": "string", - "averageEndTradeDrawdown": "string", - "maximumDrawdownDuration": "string", - "totalFees": "string" - }, - "portfolioStatistics": { - "averageWinRate": "string", - "averageLossRate": "string", - "profitLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "expectancy": "string", - "startEquity": "string", - "endEquity": "string", - "compoundingAnnualReturn": "string", - "drawdown": "string", - "totalNetProfit": "string", - "sharpeRatio": "string", - "probabilisticSharpeRatio": "string", - "sortinoRatio": "string", - "alpha": "string", - "beta": "string", - "annualStandardDeviation": "string", - "annualVariance": "string", - "informationRatio": "string", - "trackingError": "string", - "treynorRatio": "string", - "portfolioTurnover": "string", - "valueAtRisk99": "string", - "valueAtRisk95": "string", - "drawdownRecovery": "string" - }, - "closedTrades": [ - { - "symbol": { - "value": "string", - "id": "string", - "permtick": "string" - }, - "entryTime": "2021-11-26T15:18:27.693Z", - "entryPrice": 0, - "direction": 0, - "quantity": 0, - "exitTime": "2021-11-26T15:18:27.693Z", - "exitPrice": 0, - "profitLoss": 0, - "totalFees": 0, - "mae": 0, - "mfe": 0, - "duration": "string", - "endTradeDrawdown": 0 - } - ] - }, + }, "runtimeStatistics": { "Equity": "$100.00", "Fees": "-$100.00", @@ -65699,7 +66389,21 @@

}, "nodeName": "string", "outOfSampleMaxEndDate": "2021-11-26T15:18:27.693Z", - "outOfSampleDays": 0 + "outOfSampleDays": 0, + "analysis": [ + { + "name": "PerformanceRelativeToBenchmarkAnalysis", + "issue": "The strategy has a lower Sharpe ratio than the benchmark.", + "sample": { + "backtestSharpe": -0.2281345806218534, + "benchmarkSharpe": -0.22182175736916387 + }, + "count": 5, + "solutions": [ + "Try adjusting the trading rules and/or the universe to get a strategy that outperforms the benchmark." + ] + } + ] }, "debugging": true, "success": true, @@ -66088,7 +66792,7 @@

- AlgorithmPerformance object + object
Rolling window detailed statistics. @@ -66136,7 +66840,7 @@

- object + AlgorithmPerformance object
@@ -66145,7 +66849,7 @@


- The algorithm performance statistics. + The AlgorithmPerformance class is a wrapper for TradeStatistics and PortfolioStatistics. @@ -66190,6 +66894,18 @@

Number of days of out of sample days. + + + analysis + + + + AnalysisResult Array + +
+ /. + + Example @@ -66225,98 +66941,7 @@

}, "parameterSet": , "rollingWindow": { - "tradeStatistics": { - "startDateTime": "2021-11-26T15:18:27.693Z", - "endDateTime": "2021-11-26T15:18:27.693Z", - "totalNumberOfTrades": 0, - "numberOfWinningTrades": 0, - "numberOfLosingTrades": 0, - "totalProfitLoss": "string", - "totalProfit": "string", - "totalLoss": "string", - "largestProfit": "string", - "largestLoss": "string", - "averageProfitLoss": "string", - "averageProfit": "string", - "averageLoss": "string", - "averageTradeDuration": "string", - "averageWinningTradeDuration": "string", - "averageLosingTradeDuration": "string", - "medianTradeDuration": "string", - "medianWinningTradeDuration": "string", - "medianLosingTradeDuration": "string", - "maxConsecutiveWinningTrades": 0, - "maxConsecutiveLosingTrades": 0, - "profitLossRatio": "string", - "winLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "averageMAE": "string", - "averageMFE": "string", - "largestMAE": "string", - "largestMFE": "string", - "maximumClosedTradeDrawdown": "string", - "maximumIntraTradeDrawdown": "string", - "profitLossStandardDeviation": "string", - "profitLossDownsideDeviation": "string", - "profitFactor": "string", - "sharpeRatio": "string", - "sortinoRatio": "string", - "profitToMaxDrawdownRatio": "string", - "maximumEndTradeDrawdown": "string", - "averageEndTradeDrawdown": "string", - "maximumDrawdownDuration": "string", - "totalFees": "string" - }, - "portfolioStatistics": { - "averageWinRate": "string", - "averageLossRate": "string", - "profitLossRatio": "string", - "winRate": "string", - "lossRate": "string", - "expectancy": "string", - "startEquity": "string", - "endEquity": "string", - "compoundingAnnualReturn": "string", - "drawdown": "string", - "totalNetProfit": "string", - "sharpeRatio": "string", - "probabilisticSharpeRatio": "string", - "sortinoRatio": "string", - "alpha": "string", - "beta": "string", - "annualStandardDeviation": "string", - "annualVariance": "string", - "informationRatio": "string", - "trackingError": "string", - "treynorRatio": "string", - "portfolioTurnover": "string", - "valueAtRisk99": "string", - "valueAtRisk95": "string", - "drawdownRecovery": "string" - }, - "closedTrades": [ - { - "symbol": { - "value": "string", - "id": "string", - "permtick": "string" - }, - "entryTime": "2021-11-26T15:18:27.693Z", - "entryPrice": 0, - "direction": 0, - "quantity": 0, - "exitTime": "2021-11-26T15:18:27.693Z", - "exitPrice": 0, - "profitLoss": 0, - "totalFees": 0, - "mae": 0, - "mfe": 0, - "duration": "string", - "endTradeDrawdown": 0 - } - ] - }, +}, "runtimeStatistics": { "Equity": "$100.00", "Fees": "-$100.00", @@ -66451,7 +67076,21 @@

}, "nodeName": "string", "outOfSampleMaxEndDate": "2021-11-26T15:18:27.693Z", - "outOfSampleDays": 0 + "outOfSampleDays": 0, + "analysis": [ + { + "name": "PerformanceRelativeToBenchmarkAnalysis", + "issue": "The strategy has a lower Sharpe ratio than the benchmark.", + "sample": { + "backtestSharpe": -0.2281345806218534, + "benchmarkSharpe": -0.22182175736916387 + }, + "count": 5, + "solutions": [ + "Try adjusting the trading rules and/or the universe to get a strategy that outperforms the benchmark." + ] + } + ] } @@ -66562,1163 +67201,1192 @@

- AlgorithmPerformance + RuntimeStatistics - Model - The AlgorithmPerformance class is a wrapper for TradeStatistics and PortfolioStatistics. + Model - tradeStatistics + Equity - TradeStatistics object + string +
+ + + example: $100.00 + +

- A set of statistics calculated from a list of closed trades. + Total portfolio value. - portfolioStatistics + Fees - PortfolioStatistics object + string +
+ + + example: -$100.00 + +

- Represents a set of statistics calculated from equity and benchmark samples. + Transaction fee. - closedTrades + Holdings - Trade Array + string +
+ + + example: $100.00 + +

- The algorithm statistics on portfolio. + Equity value of security holdings. - Example + Net Profit -
-
-{
-  "tradeStatistics": {
-    "startDateTime": "2021-11-26T15:18:27.693Z",
-    "endDateTime": "2021-11-26T15:18:27.693Z",
-    "totalNumberOfTrades": 0,
-    "numberOfWinningTrades": 0,
-    "numberOfLosingTrades": 0,
-    "totalProfitLoss": "string",
-    "totalProfit": "string",
-    "totalLoss": "string",
-    "largestProfit": "string",
-    "largestLoss": "string",
-    "averageProfitLoss": "string",
-    "averageProfit": "string",
-    "averageLoss": "string",
-    "averageTradeDuration": "string",
-    "averageWinningTradeDuration": "string",
-    "averageLosingTradeDuration": "string",
-    "medianTradeDuration": "string",
-    "medianWinningTradeDuration": "string",
-    "medianLosingTradeDuration": "string",
-    "maxConsecutiveWinningTrades": 0,
-    "maxConsecutiveLosingTrades": 0,
-    "profitLossRatio": "string",
-    "winLossRatio": "string",
-    "winRate": "string",
-    "lossRate": "string",
-    "averageMAE": "string",
-    "averageMFE": "string",
-    "largestMAE": "string",
-    "largestMFE": "string",
-    "maximumClosedTradeDrawdown": "string",
-    "maximumIntraTradeDrawdown": "string",
-    "profitLossStandardDeviation": "string",
-    "profitLossDownsideDeviation": "string",
-    "profitFactor": "string",
-    "sharpeRatio": "string",
-    "sortinoRatio": "string",
-    "profitToMaxDrawdownRatio": "string",
-    "maximumEndTradeDrawdown": "string",
-    "averageEndTradeDrawdown": "string",
-    "maximumDrawdownDuration": "string",
-    "totalFees": "string"
-  },
-  "portfolioStatistics": {
-    "averageWinRate": "string",
-    "averageLossRate": "string",
-    "profitLossRatio": "string",
-    "winRate": "string",
-    "lossRate": "string",
-    "expectancy": "string",
-    "startEquity": "string",
-    "endEquity": "string",
-    "compoundingAnnualReturn": "string",
-    "drawdown": "string",
-    "totalNetProfit": "string",
-    "sharpeRatio": "string",
-    "probabilisticSharpeRatio": "string",
-    "sortinoRatio": "string",
-    "alpha": "string",
-    "beta": "string",
-    "annualStandardDeviation": "string",
-    "annualVariance": "string",
-    "informationRatio": "string",
-    "trackingError": "string",
-    "treynorRatio": "string",
-    "portfolioTurnover": "string",
-    "valueAtRisk99": "string",
-    "valueAtRisk95": "string",
-    "drawdownRecovery": "string"
-  },
-  "closedTrades": [
-    {
-      "symbol": {
-        "value": "string",
-        "id": "string",
-        "permtick": "string"
-      },
-      "entryTime": "2021-11-26T15:18:27.693Z",
-      "entryPrice": 0,
-      "direction": 0,
-      "quantity": 0,
-      "exitTime": "2021-11-26T15:18:27.693Z",
-      "exitPrice": 0,
-      "profitLoss": 0,
-      "totalFees": 0,
-      "mae": 0,
-      "mfe": 0,
-      "duration": "string",
-      "endTradeDrawdown": 0
-    }
-  ]
-}
-
+ + string +
+ + + example: $100.00 + + +
+
+ Net profit. - - - - - - - +
- - TradeStatistics - - Model - A set of statistics calculated from a list of closed trades. -
- startDateTime + Probabilistic Sharpe Ratio - string($date-time) + string +
+ + + example: 50.00% + +

- The entry date/time of the first trade. + Probabilistic Sharpe Ratio.
- endDateTime + Return - string($date-time) + string +
+ + + example: 50.00% + +

- The exit date/time of the first trade. + Return.
- totalNumberOfTrades + Unrealized - integer + string +
+ + + example: $100.00 + +

- The total number of trades. + Unrealized profit/loss.
- numberOfWinningTrades + Volume - integer + string +
+ + + example: $100.00 + +

- The total number of winning trades. + Total transaction volume.
- numberOfLosingTrades + Example - - integer - -
- The total number of losing trades. +
+
+{
+  "Equity": "$100.00",
+  "Fees": "-$100.00",
+  "Holdings": "$100.00",
+  "Net Profit": "$100.00",
+  "Probabilistic Sharpe Ratio": "50.00%",
+  "Return": "50.00%",
+  "Unrealized": "$100.00",
+  "Volume": "$100.00"
+}
+
+ + + + + + +
+ + StatisticsResult + + Model - Statistics information sent during the algorithm operations. +
- totalProfitLoss + Total Orders string
- The total profit/loss for all trades (as symbol currency). + Total nuber of orders.
- totalProfit + Average Win string
- The total profit for all winning trades (as symbol currency). + The average rate of return for winning trades.
- totalLoss + Average Loss string
- The total loss for all losing trades (as symbol currency). + The average rate of return for losing trades.
- largestProfit + Compounding Annual Return string
- The largest profit in a single trade (as symbol currency). + Annual compounded returns statistic based on the final-starting capital and years.
- largestLoss + Drawdown string
- The largest loss in a single trade (as symbol currency). + Drawdown maximum percentage.
- averageProfitLoss + Expectancy string
- The average profit/loss (a.k.a. Expectancy or Average Trade) for all trades (as symbol currency). + The expected value of the rate of return.
- averageProfit + Start Equity string
- The average profit for all winning trades (as symbol currency). + Initial Equity Total Value.
- averageLoss + End Equity string
- The average loss for all winning trades (as symbol currency). + Final Equity Total Value.
- averageTradeDuration + Net Profit string
- The average duration for all trades. + The total net profit percentage.
- averageWinningTradeDuration + Sharpe Ratio string
- The average duration for all winning trades. + Sharpe ratio with respect to risk free rate; measures excess of return per unit of risk.
- averageLosingTradeDuration + Sortino Ratio string
- The average duration for all losing trades. + Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk.
- medianTradeDuration + Probabilistic Sharpe Ratio string
- The median duration for all trades. + Is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark.
- medianWinningTradeDuration + Loss Rate string
- The median duration for all winning trades. + The ratio of the number of losing trades to the total number of trades.
- medianLosingTradeDuration + Win Rate string
- The median duration for all losing trades. + The ratio of the number of winning trades to the total number of trades.
- maxConsecutiveWinningTrades + Profit-Loss Ratio - integer + string
- The maximum number of consecutive winning trades. + The ratio of the average win rate to the average loss rate.
- maxConsecutiveLosingTrades + Alpha - integer + string
- The maximum number of consecutive losing trades. + Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns.
- profitLossRatio + Beta string
- The ratio of the average profit per trade to the average loss per trade. + Algorithm "beta" statistic - the covariance between the algorithm and benchmark performance, divided by benchmark's variance.
- winLossRatio + Annual Standard Deviation string
- The ratio of the number of winning trades to the number of losing trades. + Annualized standard deviation.
- winRate + Annual Variance string
- The ratio of the number of winning trades to the total number of trades. + Annualized variance statistic calculation using the daily performance variance and trading days per year.
- lossRate + Information Ratio string
- The ratio of the number of losing trades to the total number of trades. + Information ratio - risk adjusted return.
- averageMAE + Tracking Error string
- The average Maximum Adverse Excursion for all trades. + Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked.
- averageMFE + Treynor Ratio string
- The average Maximum Adverse Excursion for all trades. + Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk.
- largestMAE + Total Fees string
- The average Maximum Favorable Excursion for all trades. + Total amount of fees.
- largestMFE + Estimated Strategy Capacity string
- The largest Maximum Adverse Excursion in a single trade (as symbol currency). + The estimated total capacity of the strategy at a point in time.
- maximumClosedTradeDrawdown + Lowest Capacity Asset string
- The maximum closed-trade drawdown for all trades (as symbol currency). + Provide a reference to the lowest capacity symbol used in scaling down the capacity for debugging.
- maximumIntraTradeDrawdown + Portfolio Turnover string
- The maximum intra-trade drawdown for all trades (as symbol currency). + The average Portfolio Turnover.
- profitLossStandardDeviation + Drawdown Recovery string
- The standard deviation of the profits/losses for all trades (as symbol currency). + /.
- profitLossDownsideDeviation + Example - - string - -
- The downside deviation of the profits/losses for all trades (as symbol currency). +
+
+{
+  "Total Orders": "string",
+  "Average Win": "string",
+  "Average Loss": "string",
+  "Compounding Annual Return": "string",
+  "Drawdown": "string",
+  "Expectancy": "string",
+  "Start Equity": "string",
+  "End Equity": "string",
+  "Net Profit": "string",
+  "Sharpe Ratio": "string",
+  "Sortino Ratio": "string",
+  "Probabilistic Sharpe Ratio": "string",
+  "Loss Rate": "string",
+  "Win Rate": "string",
+  "Profit-Loss Ratio": "string",
+  "Alpha": "string",
+  "Beta": "string",
+  "Annual Standard Deviation": "string",
+  "Annual Variance": "string",
+  "Information Ratio": "string",
+  "Tracking Error": "string",
+  "Treynor Ratio": "string",
+  "Total Fees": "string",
+  "Estimated Strategy Capacity": "string",
+  "Lowest Capacity Asset": "string",
+  "Portfolio Turnover": "string",
+  "Drawdown Recovery": "string"
+}
+
+ + + + + + + + +
+ + AlgorithmPerformance + + Model - The AlgorithmPerformance class is a wrapper for TradeStatistics and PortfolioStatistics. +
- profitFactor + tradeStatistics - string + TradeStatistics object
- The ratio of the total profit to the total loss. + A set of statistics calculated from a list of closed trades.
- sharpeRatio + portfolioStatistics - string + PortfolioStatistics object
- The ratio of the average profit/loss to the standard deviation. + Represents a set of statistics calculated from equity and benchmark samples.
- sortinoRatio + closedTrades - string + Trade Array
- The ratio of the average profit/loss to the downside deviation. + The algorithm statistics on portfolio.
- profitToMaxDrawdownRatio + Example + +
+
+{
+  "tradeStatistics": {
+    "startDateTime": "2021-11-26T15:18:27.693Z",
+    "endDateTime": "2021-11-26T15:18:27.693Z",
+    "totalNumberOfTrades": 0,
+    "numberOfWinningTrades": 0,
+    "numberOfLosingTrades": 0,
+    "totalProfitLoss": "string",
+    "totalProfit": "string",
+    "totalLoss": "string",
+    "largestProfit": "string",
+    "largestLoss": "string",
+    "averageProfitLoss": "string",
+    "averageProfit": "string",
+    "averageLoss": "string",
+    "averageTradeDuration": "string",
+    "averageWinningTradeDuration": "string",
+    "averageLosingTradeDuration": "string",
+    "medianTradeDuration": "string",
+    "medianWinningTradeDuration": "string",
+    "medianLosingTradeDuration": "string",
+    "maxConsecutiveWinningTrades": 0,
+    "maxConsecutiveLosingTrades": 0,
+    "profitLossRatio": "string",
+    "winLossRatio": "string",
+    "winRate": "string",
+    "lossRate": "string",
+    "averageMAE": "string",
+    "averageMFE": "string",
+    "largestMAE": "string",
+    "largestMFE": "string",
+    "maximumClosedTradeDrawdown": "string",
+    "maximumIntraTradeDrawdown": "string",
+    "profitLossStandardDeviation": "string",
+    "profitLossDownsideDeviation": "string",
+    "profitFactor": "string",
+    "sharpeRatio": "string",
+    "sortinoRatio": "string",
+    "profitToMaxDrawdownRatio": "string",
+    "maximumEndTradeDrawdown": "string",
+    "averageEndTradeDrawdown": "string",
+    "maximumDrawdownDuration": "string",
+    "totalFees": "string"
+  },
+  "portfolioStatistics": {
+    "averageWinRate": "string",
+    "averageLossRate": "string",
+    "profitLossRatio": "string",
+    "winRate": "string",
+    "lossRate": "string",
+    "expectancy": "string",
+    "startEquity": "string",
+    "endEquity": "string",
+    "compoundingAnnualReturn": "string",
+    "drawdown": "string",
+    "totalNetProfit": "string",
+    "sharpeRatio": "string",
+    "probabilisticSharpeRatio": "string",
+    "sortinoRatio": "string",
+    "alpha": "string",
+    "beta": "string",
+    "annualStandardDeviation": "string",
+    "annualVariance": "string",
+    "informationRatio": "string",
+    "trackingError": "string",
+    "treynorRatio": "string",
+    "portfolioTurnover": "string",
+    "valueAtRisk99": "string",
+    "valueAtRisk95": "string",
+    "drawdownRecovery": "string"
+  },
+  "closedTrades": [
+    {
+      "symbol": {
+        "value": "string",
+        "id": "string",
+        "permtick": "string"
+      },
+      "entryTime": "2021-11-26T15:18:27.693Z",
+      "entryPrice": 0,
+      "direction": 0,
+      "quantity": 0,
+      "exitTime": "2021-11-26T15:18:27.693Z",
+      "exitPrice": 0,
+      "profitLoss": 0,
+      "totalFees": 0,
+      "mae": 0,
+      "mfe": 0,
+      "duration": "string",
+      "endTradeDrawdown": 0
+    }
+  ]
+}
+
+
+ + + + + + + + -
+ + TradeStatistics + + Model - A set of statistics calculated from a list of closed trades. +
+ startDateTime - string + string($date-time)
- The ratio of the total profit/loss to the maximum closed trade drawdown. + The entry date/time of the first trade.
- maximumEndTradeDrawdown + endDateTime - string + string($date-time)
- The maximum amount of profit given back by a single trade before exit (as symbol currency). + The exit date/time of the first trade.
- averageEndTradeDrawdown + totalNumberOfTrades - string + integer
- The average amount of profit given back by all trades before exit (as symbol currency). + The total number of trades.
- maximumDrawdownDuration + numberOfWinningTrades - string + integer
- The maximum amount of time to recover from a drawdown (longest time between new equity highs or peaks). + The total number of winning trades.
- totalFees + numberOfLosingTrades - string + integer
- The sum of fees for all trades. + The total number of losing trades.
- Example + totalProfitLoss -
-
-{
-  "startDateTime": "2021-11-26T15:18:27.693Z",
-  "endDateTime": "2021-11-26T15:18:27.693Z",
-  "totalNumberOfTrades": 0,
-  "numberOfWinningTrades": 0,
-  "numberOfLosingTrades": 0,
-  "totalProfitLoss": "string",
-  "totalProfit": "string",
-  "totalLoss": "string",
-  "largestProfit": "string",
-  "largestLoss": "string",
-  "averageProfitLoss": "string",
-  "averageProfit": "string",
-  "averageLoss": "string",
-  "averageTradeDuration": "string",
-  "averageWinningTradeDuration": "string",
-  "averageLosingTradeDuration": "string",
-  "medianTradeDuration": "string",
-  "medianWinningTradeDuration": "string",
-  "medianLosingTradeDuration": "string",
-  "maxConsecutiveWinningTrades": 0,
-  "maxConsecutiveLosingTrades": 0,
-  "profitLossRatio": "string",
-  "winLossRatio": "string",
-  "winRate": "string",
-  "lossRate": "string",
-  "averageMAE": "string",
-  "averageMFE": "string",
-  "largestMAE": "string",
-  "largestMFE": "string",
-  "maximumClosedTradeDrawdown": "string",
-  "maximumIntraTradeDrawdown": "string",
-  "profitLossStandardDeviation": "string",
-  "profitLossDownsideDeviation": "string",
-  "profitFactor": "string",
-  "sharpeRatio": "string",
-  "sortinoRatio": "string",
-  "profitToMaxDrawdownRatio": "string",
-  "maximumEndTradeDrawdown": "string",
-  "averageEndTradeDrawdown": "string",
-  "maximumDrawdownDuration": "string",
-  "totalFees": "string"
-}
-
+ + string + +
+ The total profit/loss for all trades (as symbol currency).
- - - - - - -
- - PortfolioStatistics - - Model - Represents a set of statistics calculated from equity and benchmark samples. -
- averageWinRate + totalProfit string
- The average rate of return for winning trades. + The total profit for all winning trades (as symbol currency).
- averageLossRate + totalLoss string
- The average rate of return for losing trades. + The total loss for all losing trades (as symbol currency).
- profitLossRatio + largestProfit string
- The ratio of the average win rate to the average loss rate. + The largest profit in a single trade (as symbol currency).
- winRate + largestLoss string
- The ratio of the number of winning trades to the total number of trades. + The largest loss in a single trade (as symbol currency).
- lossRate + averageProfitLoss string
- The ratio of the number of losing trades to the total number of trades. + The average profit/loss (a.k.a. Expectancy or Average Trade) for all trades (as symbol currency).
- expectancy + averageProfit string
- The expected value of the rate of return. + The average profit for all winning trades (as symbol currency).
- startEquity + averageLoss string
- Initial Equity Total Value. + The average loss for all winning trades (as symbol currency).
- endEquity + averageTradeDuration string
- Final Equity Total Value. + The average duration for all trades.
- compoundingAnnualReturn + averageWinningTradeDuration string
- Annual compounded returns statistic based on the final-starting capital and years. + The average duration for all winning trades.
- drawdown + averageLosingTradeDuration string
- Drawdown maximum percentage. + The average duration for all losing trades.
- totalNetProfit + medianTradeDuration string
- The total net profit percentage. + The median duration for all trades.
- sharpeRatio + medianWinningTradeDuration string
- Sharpe ratio with respect to risk free rate: measures excess of return per unit of risk. + The median duration for all winning trades.
- probabilisticSharpeRatio + medianLosingTradeDuration string
- Probabilistic Sharpe Ratio is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark. + The median duration for all losing trades.
- sortinoRatio + maxConsecutiveWinningTrades - string + integer
- Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk. + The maximum number of consecutive winning trades.
- alpha + maxConsecutiveLosingTrades - string + integer
- Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns. + The maximum number of consecutive losing trades.
- beta + profitLossRatio string
- Algorithm beta statistic - the covariance between the algorithm and benchmark performance, divided by benchmark variance. + The ratio of the average profit per trade to the average loss per trade.
- annualStandardDeviation + winLossRatio string
- Annualized standard deviation. + The ratio of the number of winning trades to the number of losing trades.
- annualVariance + winRate string
- Annualized variance statistic calculation using the daily performance variance and trading days per year. + The ratio of the number of winning trades to the total number of trades.
- informationRatio + lossRate string
- Information ratio - risk adjusted return. + The ratio of the number of losing trades to the total number of trades.
- trackingError + averageMAE string
- Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked. + The average Maximum Adverse Excursion for all trades.
- treynorRatio + averageMFE string
- Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk. + The average Maximum Adverse Excursion for all trades.
- portfolioTurnover + largestMAE string
- The average Portfolio Turnover. + The average Maximum Favorable Excursion for all trades.
- valueAtRisk99 + largestMFE string
- The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 99% confidence level, 1 year lookback period, and that the returns are normally distributed. + The largest Maximum Adverse Excursion in a single trade (as symbol currency).
- valueAtRisk95 + maximumClosedTradeDrawdown string
- The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 95% confidence level, 1 year lookback period, and that the returns are normally distributed. + The maximum closed-trade drawdown for all trades (as symbol currency).
- drawdownRecovery + maximumIntraTradeDrawdown string
- /. + The maximum intra-trade drawdown for all trades (as symbol currency).
- Example + profitLossStandardDeviation -
-
-{
-  "averageWinRate": "string",
-  "averageLossRate": "string",
-  "profitLossRatio": "string",
-  "winRate": "string",
-  "lossRate": "string",
-  "expectancy": "string",
-  "startEquity": "string",
-  "endEquity": "string",
-  "compoundingAnnualReturn": "string",
-  "drawdown": "string",
-  "totalNetProfit": "string",
-  "sharpeRatio": "string",
-  "probabilisticSharpeRatio": "string",
-  "sortinoRatio": "string",
-  "alpha": "string",
-  "beta": "string",
-  "annualStandardDeviation": "string",
-  "annualVariance": "string",
-  "informationRatio": "string",
-  "trackingError": "string",
-  "treynorRatio": "string",
-  "portfolioTurnover": "string",
-  "valueAtRisk99": "string",
-  "valueAtRisk95": "string",
-  "drawdownRecovery": "string"
-}
-
+ + string + +
+ The standard deviation of the profits/losses for all trades (as symbol currency).
- - - - - - @@ -67727,662 +68395,792 @@

+ + +
- - Trade - - Model - Represents a closed trade. -
- symbol + profitLossDownsideDeviation - Symbol object + string
- Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security. + The downside deviation of the profits/losses for all trades (as symbol currency).
- entryTime + profitFactor - string($date-time) + string
- The date and time the trade was opened. + The ratio of the total profit to the total loss.
- entryPrice + sharpeRatio - number + string
- The price at which the trade was opened (or the average price if multiple entries). + The ratio of the average profit/loss to the standard deviation.
- direction + sortinoRatio - integer Enum + string
- Direction of a trade. 0=Long, 1=Short. Options : [0, 1] + The ratio of the average profit/loss to the downside deviation.
- quantity + profitToMaxDrawdownRatio - number + string
- The total unsigned quantity of the trade. + The ratio of the total profit/loss to the maximum closed trade drawdown.
- exitTime + maximumEndTradeDrawdown - string($date-time) + string
- The date and time the trade was closed. + The maximum amount of profit given back by a single trade before exit (as symbol currency).
- exitPrice + averageEndTradeDrawdown - number + string
- The price at which the trade was closed (or the average price if multiple exits). + The average amount of profit given back by all trades before exit (as symbol currency).
- profitLoss + maximumDrawdownDuration - number + string
- The gross profit/loss of the trade (as account currency). + The maximum amount of time to recover from a drawdown (longest time between new equity highs or peaks).
- number + string
- The total fees associated with the trade (always positive value) (as account currency). + The sum of fees for all trades.
- mae + Example + +
+
+{
+  "startDateTime": "2021-11-26T15:18:27.693Z",
+  "endDateTime": "2021-11-26T15:18:27.693Z",
+  "totalNumberOfTrades": 0,
+  "numberOfWinningTrades": 0,
+  "numberOfLosingTrades": 0,
+  "totalProfitLoss": "string",
+  "totalProfit": "string",
+  "totalLoss": "string",
+  "largestProfit": "string",
+  "largestLoss": "string",
+  "averageProfitLoss": "string",
+  "averageProfit": "string",
+  "averageLoss": "string",
+  "averageTradeDuration": "string",
+  "averageWinningTradeDuration": "string",
+  "averageLosingTradeDuration": "string",
+  "medianTradeDuration": "string",
+  "medianWinningTradeDuration": "string",
+  "medianLosingTradeDuration": "string",
+  "maxConsecutiveWinningTrades": 0,
+  "maxConsecutiveLosingTrades": 0,
+  "profitLossRatio": "string",
+  "winLossRatio": "string",
+  "winRate": "string",
+  "lossRate": "string",
+  "averageMAE": "string",
+  "averageMFE": "string",
+  "largestMAE": "string",
+  "largestMFE": "string",
+  "maximumClosedTradeDrawdown": "string",
+  "maximumIntraTradeDrawdown": "string",
+  "profitLossStandardDeviation": "string",
+  "profitLossDownsideDeviation": "string",
+  "profitFactor": "string",
+  "sharpeRatio": "string",
+  "sortinoRatio": "string",
+  "profitToMaxDrawdownRatio": "string",
+  "maximumEndTradeDrawdown": "string",
+  "averageEndTradeDrawdown": "string",
+  "maximumDrawdownDuration": "string",
+  "totalFees": "string"
+}
+
+
+ + + + + + + + -
+ + PortfolioStatistics + + Model - Represents a set of statistics calculated from equity and benchmark samples. +
+ averageWinRate - number + string
- The Maximum Adverse Excursion (as account currency). + The average rate of return for winning trades.
- mfe + averageLossRate - number + string
- The Maximum Favorable Excursion (as account currency). + The average rate of return for losing trades.
- duration + profitLossRatio string
- The duration of the trade. + The ratio of the average win rate to the average loss rate.
- endTradeDrawdown + winRate - number + string
- The amount of profit given back before the trade was closed. + The ratio of the number of winning trades to the total number of trades.
- Example + lossRate -
-
-{
-  "symbol": {
-    "value": "string",
-    "id": "string",
-    "permtick": "string"
-  },
-  "entryTime": "2021-11-26T15:18:27.693Z",
-  "entryPrice": 0,
-  "direction": 0,
-  "quantity": 0,
-  "exitTime": "2021-11-26T15:18:27.693Z",
-  "exitPrice": 0,
-  "profitLoss": 0,
-  "totalFees": 0,
-  "mae": 0,
-  "mfe": 0,
-  "duration": "string",
-  "endTradeDrawdown": 0
-}
-
+ + string + +
+ The ratio of the number of losing trades to the total number of trades.
- - - - - - -
- - Symbol - - Model - Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security. -
- value + expectancy string
- The current symbol for this ticker. + The expected value of the rate of return.
- id + startEquity string
- The security identifier for this symbol. + Initial Equity Total Value.
- permtick + endEquity string
- The ticker at IPO for this security. + Final Equity Total Value.
- Example + compoundingAnnualReturn -
-
-{
-  "value": "string",
-  "id": "string",
-  "permtick": "string"
-}
-
+ + string + +
+ Annual compounded returns statistic based on the final-starting capital and years.
- - - - - - -
- - RuntimeStatistics - - Model -
- Equity + drawdown string -
- - - example: $100.00 - -

- Total portfolio value. + Drawdown maximum percentage.
- Fees + totalNetProfit string -
- - - example: -$100.00 - -

- Transaction fee. + The total net profit percentage.
- Holdings + sharpeRatio string -
- - - example: $100.00 - -

- Equity value of security holdings. + Sharpe ratio with respect to risk free rate: measures excess of return per unit of risk.
- Net Profit + probabilisticSharpeRatio string -
- - - example: $100.00 - -

- Net profit. + Probabilistic Sharpe Ratio is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark.
- Probabilistic Sharpe Ratio + sortinoRatio string -
- - - example: 50.00% - -

- Probabilistic Sharpe Ratio. + Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk.
- Return + alpha string -
- - - example: 50.00% - -

- Return. + Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns.
- Unrealized + beta string -
- - - example: $100.00 - -

- Unrealized profit/loss. + Algorithm beta statistic - the covariance between the algorithm and benchmark performance, divided by benchmark variance.
- Volume + annualStandardDeviation string -
- - - example: $100.00 - -

- Total transaction volume. + Annualized standard deviation.
- Example + annualVariance -
-
-{
-  "Equity": "$100.00",
-  "Fees": "-$100.00",
-  "Holdings": "$100.00",
-  "Net Profit": "$100.00",
-  "Probabilistic Sharpe Ratio": "50.00%",
-  "Return": "50.00%",
-  "Unrealized": "$100.00",
-  "Volume": "$100.00"
-}
-
+ + string + +
+ Annualized variance statistic calculation using the daily performance variance and trading days per year.
- - - - - - + + + + + + +
- - StatisticsResult - - Model - Statistics information sent during the algorithm operations. -
- Total Orders + informationRatio + + + string + +
+ Information ratio - risk adjusted return. +
+ trackingError string
- Total nuber of orders. + Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked.
- Average Win + treynorRatio string
- The average rate of return for winning trades. + Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk.
- Average Loss + portfolioTurnover string
- The average rate of return for losing trades. + The average Portfolio Turnover.
- Compounding Annual Return + valueAtRisk99 string
- Annual compounded returns statistic based on the final-starting capital and years. + The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 99% confidence level, 1 year lookback period, and that the returns are normally distributed.
- Drawdown + valueAtRisk95 string
- Drawdown maximum percentage. + The 1-day VaR for the portfolio, using the Variance-covariance approach. Assumes a 95% confidence level, 1 year lookback period, and that the returns are normally distributed.
- Expectancy + drawdownRecovery string
- The expected value of the rate of return. + /.
- Start Equity + Example + +
+
+{
+  "averageWinRate": "string",
+  "averageLossRate": "string",
+  "profitLossRatio": "string",
+  "winRate": "string",
+  "lossRate": "string",
+  "expectancy": "string",
+  "startEquity": "string",
+  "endEquity": "string",
+  "compoundingAnnualReturn": "string",
+  "drawdown": "string",
+  "totalNetProfit": "string",
+  "sharpeRatio": "string",
+  "probabilisticSharpeRatio": "string",
+  "sortinoRatio": "string",
+  "alpha": "string",
+  "beta": "string",
+  "annualStandardDeviation": "string",
+  "annualVariance": "string",
+  "informationRatio": "string",
+  "trackingError": "string",
+  "treynorRatio": "string",
+  "portfolioTurnover": "string",
+  "valueAtRisk99": "string",
+  "valueAtRisk95": "string",
+  "drawdownRecovery": "string"
+}
+
+
+ + + + + + + + + + +
+ + Trade + + Model - Represents a closed trade. +
+ symbol - string + Symbol object
- Initial Equity Total Value. + Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security.
- End Equity + entryTime - string + string($date-time)
- Final Equity Total Value. + The date and time the trade was opened.
- Net Profit + entryPrice - string + number
- The total net profit percentage. + The price at which the trade was opened (or the average price if multiple entries).
- Sharpe Ratio + direction - string + integer Enum
- Sharpe ratio with respect to risk free rate; measures excess of return per unit of risk. + Direction of a trade. 0=Long, 1=Short. Options : [0, 1]
- Sortino Ratio + quantity - string + number
- Sortino ratio with respect to risk free rate; measures excess of return per unit of downside risk. + The total unsigned quantity of the trade.
- Probabilistic Sharpe Ratio + exitTime - string + string($date-time)
- Is a probability measure associated with the Sharpe ratio. It informs us of the probability that the estimated Sharpe ratio is greater than a chosen benchmark. + The date and time the trade was closed.
- Loss Rate + exitPrice - string + number
- The ratio of the number of losing trades to the total number of trades. + The price at which the trade was closed (or the average price if multiple exits).
- Win Rate + profitLoss - string + number
- The ratio of the number of winning trades to the total number of trades. + The gross profit/loss of the trade (as account currency).
- Profit-Loss Ratio + totalFees - string + number
- The ratio of the average win rate to the average loss rate. + The total fees associated with the trade (always positive value) (as account currency).
- Alpha + mae - string + number
- Algorithm "Alpha" statistic - abnormal returns over the risk free rate and the relationshio (beta) with the benchmark returns. + The Maximum Adverse Excursion (as account currency).
- Beta + mfe - string + number
- Algorithm "beta" statistic - the covariance between the algorithm and benchmark performance, divided by benchmark's variance. + The Maximum Favorable Excursion (as account currency).
- Annual Standard Deviation + duration string
- Annualized standard deviation. + The duration of the trade.
- Annual Variance + endTradeDrawdown - string + number
- Annualized variance statistic calculation using the daily performance variance and trading days per year. + The amount of profit given back before the trade was closed.
- Information Ratio + Example + +
+
+{
+  "symbol": {
+    "value": "string",
+    "id": "string",
+    "permtick": "string"
+  },
+  "entryTime": "2021-11-26T15:18:27.693Z",
+  "entryPrice": 0,
+  "direction": 0,
+  "quantity": 0,
+  "exitTime": "2021-11-26T15:18:27.693Z",
+  "exitPrice": 0,
+  "profitLoss": 0,
+  "totalFees": 0,
+  "mae": 0,
+  "mfe": 0,
+  "duration": "string",
+  "endTradeDrawdown": 0
+}
+
+
+ + + + + + + + + + +
+ + Symbol + + Model - Represents a unique security identifier. This is made of two components, the unique SID and the Value. The value is the current ticker symbol while the SID is constant over the life of a security. +
+ value string
- Information ratio - risk adjusted return. + The current symbol for this ticker.
- Tracking Error + id string
- Tracking error volatility (TEV) statistic - a measure of how closely a portfolio follows the index to which it is benchmarked. + The security identifier for this symbol.
- Treynor Ratio + permtick string
- Treynor ratio statistic is a measurement of the returns earned in excess of that which could have been earned on an investment that has no diversifiable risk. + The ticker at IPO for this security.
- Total Fees + Example + +
+
+{
+  "value": "string",
+  "id": "string",
+  "permtick": "string"
+}
+
+
+ + + + + + + + @@ -68393,33 +69191,16 @@

 {
-  "Total Orders": "string",
-  "Average Win": "string",
-  "Average Loss": "string",
-  "Compounding Annual Return": "string",
-  "Drawdown": "string",
-  "Expectancy": "string",
-  "Start Equity": "string",
-  "End Equity": "string",
-  "Net Profit": "string",
-  "Sharpe Ratio": "string",
-  "Sortino Ratio": "string",
-  "Probabilistic Sharpe Ratio": "string",
-  "Loss Rate": "string",
-  "Win Rate": "string",
-  "Profit-Loss Ratio": "string",
-  "Alpha": "string",
-  "Beta": "string",
-  "Annual Standard Deviation": "string",
-  "Annual Variance": "string",
-  "Information Ratio": "string",
-  "Tracking Error": "string",
-  "Treynor Ratio": "string",
-  "Total Fees": "string",
-  "Estimated Strategy Capacity": "string",
-  "Lowest Capacity Asset": "string",
-  "Portfolio Turnover": "string",
-  "Drawdown Recovery": "string"
+  "name": "PerformanceRelativeToBenchmarkAnalysis",
+  "issue": "The strategy has a lower Sharpe ratio than the benchmark.",
+  "sample": {
+    "backtestSharpe": -0.2281345806218534,
+    "benchmarkSharpe": -0.22182175736916387
+  },
+  "count": 5,
+  "solutions": [
+    "Try adjusting the trading rules and/or the universe to get a strategy that outperforms the benchmark."
+  ]
 }
@@ -69279,130 +70060,6 @@

Examples

print("List of Backtests:") print(result) -

- The following example demonstrates how to read and plot chart data from a backtest through the cloud API. -

-
-
from base64 import b64encode
-from hashlib import sha256
-from time import time
-from requests import get, post
-BASE_URL = 'https://www.quantconnect.com/api/v2/'
-
-# You need to replace these with your actual credentials.
-# You can request your credentials at https://www.quantconnect.com/settings/
-# You can find our organization ID at https://www.quantconnect.com/organization/ 
-USER_ID = 0
-API_TOKEN = '____'
-ORGANIZATION_ID = '____'
-
-def get_headers():
-    # Get timestamp
-    timestamp = f'{int(time())}'
-    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
-
-    # Get hased API token
-    hashed_token = sha256(time_stamped_token).hexdigest()
-    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
-    authentication = b64encode(authentication).decode('ascii')
-
-    # Create headers dictionary.
-    return {
-        'Authorization': f'Basic {authentication}',
-        'Timestamp': timestamp
-    }
-
-# Authenticate to verify credentials
-response = post(f'{BASE_URL}/authenticate', headers = get_headers())
-print(response.json())
-
-# --------------------
-
-from time import sleep
-import matplotlib.pyplot as plt
-import matplotlib.dates as mdates
-from datetime import datetime, timedelta
-
-# The project and backtest ID of the backtest
-project_id = 12345678
-backtest_id = "..."
-
-### Read Backtest Chart
-# Define the chart name to retrieve
-chart_name = "Strategy Equity"
-# Prepare data payload to fetch chart data
-payload = {
-    "projectId": project_id,  # ID of the project
-    "backtestId": backtest_id,  # ID of the backtest
-    "name": chart_name,  # Name of the chart to retrieve
-    "count": 500,  # Number of data points to fetch
-    "start": 1717801200,  # Start time in Unix timestamp
-    "end": 1743462000  # End time in Unix timestamp
-}
-# Retry up to 10 times if the chart data is still loading
-for attempt in range(10):
-    # Send a POST request to the /backtests/chart/read endpoint
-    response = post(f'{BASE_URL}/backtests/chart/read', headers=get_headers(), json=payload)
-    # Parse the JSON response
-    result = response.json()
-    # Check if the data is still loading
-    if result.get('status') == 'loading':
-        print(f"Chart data is loading... Progress: {result['progress']}% (attempt {attempt + 1}/10)")
-        sleep(10)
-        continue
-    break
-
-# If the request was successful, extract and plot the chart data
-if result['success']:
-    chart = result['chart']
-    # Filter to series with plottable list data points
-    series_items = [(name, data) for name, data in chart['series'].items()
-                    if data['values'] and isinstance(data['values'][0], list)]
-    if not series_items:
-        print("No series data available in the chart.")
-    else:
-        # Create a subplot for each series
-        fig, axes = plt.subplots(len(series_items), 1, figsize=(12, 4 * len(series_items)), sharex=True)
-        if len(series_items) == 1:
-            axes = [axes]
-        for ax, (series_name, series_data) in zip(axes, series_items):
-            values = series_data['values']
-            # Check if the data is OHLC (5 elements: timestamp, open, high, low, close)
-            is_ohlc = len(values[0]) == 5
-            if is_ohlc:
-                # Filter out data points with None values
-                valid = [p for p in values if None not in p[1:]]
-                if not valid:
-                    ax.set_title(f"{series_name} (no valid data)")
-                    continue
-                timestamps = [datetime.utcfromtimestamp(p[0]) for p in valid]
-                dates = mdates.date2num(timestamps)
-                # Calculate bar width as 60% of the average interval between points
-                bar_width = (dates[-1] - dates[0]) / len(dates) * 0.6
-                for i, point in enumerate(valid):
-                    _, o, h, l, c = point
-                    color = 'green' if c >= o else 'red'
-                    # Draw the high-low wick
-                    ax.vlines(dates[i], l, h, color=color, linewidth=0.8)
-                    # Draw the open-close body
-                    ax.bar(dates[i], abs(c - o) or 0.01, bottom=min(o, c),
-                           width=bar_width, color=color, edgecolor=color)
-                ax.xaxis_date()
-                ax.set_ylabel("Price")
-            else:
-                # Filter out data points with None values
-                valid = [p for p in values if p[1] is not None]
-                timestamps = [datetime.utcfromtimestamp(p[0]) for p in valid]
-                y_values = [p[1] for p in valid]
-                ax.plot(timestamps, y_values)
-                ax.set_ylabel("Value")
-            ax.set_title(series_name)
-            ax.tick_params(axis='x', rotation=45)
-        fig.suptitle(chart_name, fontsize=14)
-        plt.tight_layout()
-        plt.savefig(f"{project_id}-{backtest_id}-{chart_name.replace(' ', '_')}.png")
-        plt.show()
-
@@ -78476,128 +79133,6 @@

Examples

print("List of Live Algorithms:") print(result) -

- The following example demonstrates how to read and plot chart data from a live algorithm through the cloud API. -

-
-
from base64 import b64encode
-from hashlib import sha256
-from time import time
-from requests import get, post
-BASE_URL = 'https://www.quantconnect.com/api/v2/'
-
-# You need to replace these with your actual credentials.
-# You can request your credentials at https://www.quantconnect.com/settings/
-# You can find our organization ID at https://www.quantconnect.com/organization/ 
-USER_ID = 0
-API_TOKEN = '____'
-ORGANIZATION_ID = '____'
-
-def get_headers():
-    # Get timestamp
-    timestamp = f'{int(time())}'
-    time_stamped_token = f'{API_TOKEN}:{timestamp}'.encode('utf-8')
-
-    # Get hased API token
-    hashed_token = sha256(time_stamped_token).hexdigest()
-    authentication = f'{USER_ID}:{hashed_token}'.encode('utf-8')
-    authentication = b64encode(authentication).decode('ascii')
-
-    # Create headers dictionary.
-    return {
-        'Authorization': f'Basic {authentication}',
-        'Timestamp': timestamp
-    }
-
-# Authenticate to verify credentials
-response = post(f'{BASE_URL}/authenticate', headers = get_headers())
-print(response.json())
-
-# --------------------
-
-from time import sleep
-import matplotlib.pyplot as plt
-import matplotlib.dates as mdates
-from datetime import datetime, timedelta
-
-# The project ID of the live algorithm
-project_id = 23456789
-
-### Read Live Algorithm Chart
-# Define the chart name to retrieve
-chart_name = "Strategy Equity"
-# Prepare data payload to fetch chart data
-payload = {
-    "projectId": project_id,  # ID of the project that's live trading
-    "name": chart_name,  # Name of the chart to retrieve
-    "count": 500,  # Number of data points to fetch
-    "start": 1717801200,  # Start time in Unix timestamp
-    "end": 1743462000  # End time in Unix timestamp
-}
-# Retry up to 10 times if the chart data is still loading
-for attempt in range(10):
-    # Send a POST request to the /live/chart/read endpoint
-    response = post(f'{BASE_URL}/live/chart/read', headers=get_headers(), json=payload)
-    # Parse the JSON response
-    result = response.json()
-    # Check if the data is still loading
-    if result.get('status') == 'loading':
-        print(f"Chart data is loading... Progress: {result['progress']}% (attempt {attempt + 1}/10)")
-        sleep(10)
-        continue
-    break
-
-# If the request was successful, extract and plot the chart data
-if result['success']:
-    chart = result['chart']
-    # Filter to series with plottable list data points
-    series_items = [(name, data) for name, data in chart['series'].items()
-                    if data['values'] and isinstance(data['values'][0], list)]
-    if not series_items:
-        print("No series data available in the chart.")
-    else:
-        # Create a subplot for each series
-        fig, axes = plt.subplots(len(series_items), 1, figsize=(12, 4 * len(series_items)), sharex=True)
-        if len(series_items) == 1:
-            axes = [axes]
-        for ax, (series_name, series_data) in zip(axes, series_items):
-            values = series_data['values']
-            # Check if the data is OHLC (5 elements: timestamp, open, high, low, close)
-            is_ohlc = len(values[0]) == 5
-            if is_ohlc:
-                # Filter out data points with None values
-                valid = [p for p in values if None not in p[1:]]
-                if not valid:
-                    ax.set_title(f"{series_name} (no valid data)")
-                    continue
-                timestamps = [datetime.utcfromtimestamp(p[0]) for p in valid]
-                dates = mdates.date2num(timestamps)
-                # Calculate bar width as 60% of the average interval between points
-                bar_width = (dates[-1] - dates[0]) / len(dates) * 0.6
-                for i, point in enumerate(valid):
-                    _, o, h, l, c = point
-                    color = 'green' if c >= o else 'red'
-                    # Draw the high-low wick
-                    ax.vlines(dates[i], l, h, color=color, linewidth=0.8)
-                    # Draw the open-close body
-                    ax.bar(dates[i], abs(c - o) or 0.01, bottom=min(o, c),
-                           width=bar_width, color=color, edgecolor=color)
-                ax.xaxis_date()
-                ax.set_ylabel("Price")
-            else:
-                # Filter out data points with None values
-                valid = [p for p in values if p[1] is not None]
-                timestamps = [datetime.utcfromtimestamp(p[0]) for p in valid]
-                y_values = [p[1] for p in valid]
-                ax.plot(timestamps, y_values)
-                ax.set_ylabel("Value")
-            ax.set_title(series_name)
-            ax.tick_params(axis='x', rotation=45)
-        fig.suptitle(chart_name, fontsize=14)
-        plt.tight_layout()
-        plt.savefig(f"{project_id}-{chart_name.replace(' ', '_')}.png")
-        plt.show()
-
@@ -82136,15 +82671,15 @@

Request

"command": { "$type": "OrderCommand", "symbol": { - "id": "BTCUSD 2XR", - "value": "BTCUSD" + "id": "BTCUSD 2XR", + "value": "BTCUSD" }, "order_type": "market", "quantity": "0.1", "limit_price": 0, "stop_price": 0, "tag": "" -} + } } @@ -82510,15 +83045,15 @@

Request

"command": { "$type": "OrderCommand", "symbol": { - "id": "BTCUSD 2XR", - "value": "BTCUSD" + "id": "BTCUSD 2XR", + "value": "BTCUSD" }, "order_type": "market", "quantity": "0.1", "limit_price": 0, "stop_price": 0, "tag": "" -} + } } @@ -84565,7 +85100,12 @@

} ], "outOfSampleMaxEndDate": "2021-11-26T15:18:27.693Z", - "outOfSampleDays": 0 + "outOfSampleDays": 0, + "created": "2021-11-26T15:18:27.693Z", + "psr": 0, + "sharpeRatio": 0, + "trades": 0, + "cloneId": 0 }, "success": true, "errors": [ @@ -84911,6 +85451,96 @@

Number of days of out of sample days.

+ + + + + + + + + + + + + + + + + + + + @@ -92418,7 +93053,7 @@

"version": 2.0, "payload": { "utils.py": "def add(a,b):\n return a+b\n" -}, + }, "payloadType": "StringDict" } diff --git a/single-page/Quantconnect-Lean-Cli.html b/single-page/Quantconnect-Lean-Cli.html index 3e55ed5fc9..112782bacd 100644 --- a/single-page/Quantconnect-Lean-Cli.html +++ b/single-page/Quantconnect-Lean-Cli.html @@ -3006,17 +3006,17 @@

Data that will be purchased and downloaded:
-┌───────────────────────────┬─────────┬────────────────────────┬────────────┬─────────┐
-│ Dataset                   │ Vendor  │ Details                │ File count │ Price   │
-├───────────────────────────┼─────────┼────────────────────────┼────────────┼─────────┤
-│ Binance Crypto Price Data │ CoinAPI │ Data type: Trade       │ 32         │ 800 QCC │
-│                           │         │ Ticker: BTCBUSD        │            │         │
-│                           │         │ Resolution: Second     │            │         │
-│                           │         │ Start date: 2022-05-05 │            │         │
-│                           │         │ End date: 2022-06-05   │            │         │
-└───────────────────────────┴─────────┴────────────────────────┴────────────┴─────────┘
-Total price: 800 QCC
-Organization balance: 1,000 QCC
+┌─────────────┬──────────┬────────────────────────┬────────────┬────────┐
+│ Dataset     │ Vendor   │ Details                │ File count │ Price  │
+├─────────────┼──────────┼────────────────────────┼────────────┼────────┤
+│ US Equities │ AlgoSeek │ Data type: Trade       │ 3          │ 15 QCC │
+│             │          │ Ticker: SPY            │            │        │
+│             │          │ Resolution: Minute     │            │        │
+│             │          │ Start date: 2023-01-01 │            │        │
+│             │          │ End date: 2023-01-05   │            │        │
+└─────────────┴──────────┴────────────────────────┴────────────┴────────┘
+Total price: 15 QCC
+Organization balance: 10,000 QCC
 
 Data Terms of Use has been signed previously.
 Find full agreement at: https://www.quantconnect.com/terms/data/?organization=<organizationId>
@@ -3124,7 +3124,46 @@ 

lean data download - to start an interactive downloading wizard and then enter the dataset category number. + to start an interactive downloading wizard and then select + + QuantConnect + + to list the categories in the + + Dataset Market + + . +
+
$ lean data download
+Select a historical data provider:
+1) Interactive Brokers
+2) Oanda
+3) Bitfinex
+4) Coinbase Advanced Trade
+5) Binance
+6) Kraken
+7) CharlesSchwab
+8) IQFeed
+9) Polygon
+10) FactSet
+11) AlphaVantage
+12) CoinApi
+13) ThetaData
+14) QuantConnect
+15) Local
+16) Terminal Link
+17) Bybit
+18) TradeStation
+19) Alpaca
+20) Tastytrade
+21) Eze
+22) dYdX
+23) Databento
+Enter an option: 14
+
+ +
  • + Enter the dataset category number.
    $ lean data download
     Select a category:
    @@ -3147,38 +3186,37 @@ 

    $ lean data download
     Select a dataset:
    -1) Binance Crypto Future Margin Rate Data
    -2) Binance Crypto Future Price Data
    -3) Binance Crypto Price Data
    -4) Binance US Crypto Price Data
    -5) Bitcoin Metadata
    -6) Bitfinex Crypto Price Data
    -7) Brain Language Metrics on Company Filings
    -8) Brain ML Stock Ranking
    -9) CFD Data
    -10) Coinbase Crypto Price Data
    -11) Composite Factor Bundle
    -12) Cross Asset Model
    -13) FOREX Data
    -14) Insider Trading
    -15) Kraken Crypto Price Data
    -16) NFT Sales
    -17) Tactical
    -18) US Congress Trading
    -19) US ETF Constituents
    -20) US Equities
    -21) US Equity Coarse Universe
    -22) US Equity Options
    -23) US Equity Security Master
    -24) US Federal Reserve (FRED)
    -25) US Futures
    -26) US Futures Security Master
    -27) US Index Options
    -28) US SEC Filings
    -29) US Treasury Yield Curve
    -30) VIX Central Contango
    -31) VIX Daily Price
    -Enter an option: 20
    +1) Bitcoin Metadata +2) Brain Language Metrics on Company Filings +3) Brain ML Stock Ranking +4) CFD Data +5) Composite Factor Bundle +6) Cross Asset Model +7) FOREX Data +8) Insider Trading +9) International Future Universe +10) NFT Sales +11) Tactical +12) US Congress Trading +13) US ETF Constituents +14) US Equities +15) US Equity Coarse Universe +16) US Equity Option Universe +17) US Equity Options +18) US Equity Security Master +19) US Future Option Universe +20) US Future Options +21) US Future Universe +22) US Futures +23) US Futures Security Master +24) US Index Option Universe +25) US Index Options +26) US Interest Rate +27) US SEC Filings +28) US Treasury Yield Curve +29) VIX Central Contango +30) VIX Daily Price +Enter an option: 13

    If you don't have an active subscription to the US Equity Security Master, you'll get the following error message: @@ -4035,444 +4073,6 @@

    Equity Options

    -

    Crypto

    - - -

    - Crypto algorithms require at least one of the - - CoinAPI datasets - - . The CoinAPI datasets are available in several resolutions. The resolution you need depends on the Crypto subscriptions you create in your algorithm and the resolution of data you get in - - history requests - - . The following table describes the file format and costs of each resolution: -

    -
  • + + AnalysisResult + + Model - The result of an analysis performed on a result. +
    + name string +
    + + + required + + +
    + + + example: PerformanceRelativeToBenchmarkAnalysis + +

    - Total amount of fees. + The name of the analysis that produced this result.
    - Estimated Strategy Capacity + issue string +
    + + + required + + +
    + + + example: The strategy has a lower Sharpe ratio than the benchmark. + +

    - The estimated total capacity of the strategy at a point in time. + A short description of why the analysis was triggered.
    - Lowest Capacity Asset + sample - string + object +
    + + + required + + +
    + + + example: {'backtestSharpe': -0.2281345806218534, 'benchmarkSharpe': -0.22182175736916387} + +

    - Provide a reference to the lowest capacity symbol used in scaling down the capacity for debugging. + A representative sample value of the issue detected by the analysis.
    - Portfolio Turnover + count - string + integer +
    + + + example: 5 + +

    - The average Portfolio Turnover. + The total number of matching occurrences found by the analysis. If not present, it should be assumed that there is only one occurrence.
    - Drawdown Recovery + solutions - string + string Array +
    + + + required + +

    - /. + Human-readable suggestions for resolving the detected issue.
    + created + + + string($date-time) +
    + + + required + + +
    +
    + Date and time of when this optimization was created. +
    + psr + + + number +
    + + + required + + +
    +
    + Probabilistic Sharpe ratio statistic. +
    + sharpeRatio + + + number +
    + + + required + + +
    +
    + Sharpe ratio statistic. +
    + trades + + + integer +
    + + + required + + +
    +
    + Number of trades in the best backtest (based on the criterion) of the optimziation. +
    + cloneId + + + integer +
    + + + required + + +
    +
    + Id of project where this current project was originally cloned. +
    Example @@ -84993,7 +85623,12 @@

    } ], "outOfSampleMaxEndDate": "2021-11-26T15:18:27.693Z", - "outOfSampleDays": 0 + "outOfSampleDays": 0, + "created": "2021-11-26T15:18:27.693Z", + "psr": 0, + "sharpeRatio": 0, + "trades": 0, + "cloneId": 0 }

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Resolution - - File Format - - Cost per file -
    - Tick - - One file per security per trading day per brokerage per data format. Quote and trade data are separate files. -
    -
    - 100 QCC = $1 USD -
    - Second - - One file per security per trading day per brokerage per data format. Quote and trade data are separate files. -
    -
    - 25 QCC = $0.25 USD -
    - Minute - - One file per security per trading day per brokerage per data format. Quote and trade data are separate files. -
    -
    - 5 QCC = $0.05 USD -
    - Hour - - One file per security per brokerage. -
    -
    - 400 QCC = $4 USD -
    - Daily - - One file per security per brokerage. -
    -
    - 100 QCC = $1 USD -
    -

    - If you add universes to your algorithm, you also need - - CryptoUniverse - - data. The file format of - - CryptoUniverse - - data is one file per day per brokerage and each file costs 100 QCC = $1 USD. -

    -

    - For example, the following algorithm creates a universe of 100 Cryptocurrencies and then subscribes to minute resolution data for each one in the universe: -

    -
    -
    public class CryptoDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 1, 1);
    -        SetEndDate(2021, 1, 1);
    -        UniverseSettings.Asynchronous = true;            
    -        AddUniverse(CryptoUniverse.Coinbase(universeDay => universeDay.OrderByDescending(cf => cf.VolumeInUsd).Take(100).Select(x => x.Symbol))
    -        );
    -    }
    -}
    -
    class CryptoDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 1, 1)
    -        self.set_end_date(2021, 1, 1)
    -        self.universe_settings.asynchronous = True
    -        self.add_universe(CryptoUniverse.coinbase(self.universe_filter))
    -
    -    def universe_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    -        sorted_by_dollar_volume = sorted(universe_day, key=lambda cf: (cf.volume_in_usd or 0), reverse=True)
    -        return [cf.symbol for cf in sorted_by_dollar_volume[:100]]
    -
    -

    - The following table shows the data cost of the preceding algorithm: -

    - - - - - - - - - - - - - - - - - - - - - - - -
    - Dataset - - Package - - Initial Cost - - Ongoing Cost -
    - Coinbase Crypto Price Data - - Universe Download - - 365 days -
    - => 365 files -
    -
    - 365 files @ 100 QCC/file -
    - => 365 * 100 QCC -
    - = 36,500 QCC -
    - = $365 USD -
    - 1 file per day @ 100 QCC/file -
    - => 100 QCC/day -
    - = $1 USD/day -
    - Coinbase Crypto Price Data - - Minute Download - - 100 securities over 365 trading days with 2 data formats -
    - => 1 * 100 * 365 * 2 files -
    - = 73,000 files -
    -
    - 73,000 files @ 5 QCC/file -
    - => 73,000 * 5 QCC -
    - = 365,000 QCC -
    - = $3,650 USD -
    - 100 securities with 2 data formats -
    - => 100 * 2 files/day -
    - = 200 files/day -
    -
    - 200 files/day @ 5 QCC/file -
    - => 200 * 5 QCC/day -
    - = 1,000 QCC/day -
    - = $10 USD/day -
    -

    - The preceding table assumes you download trade and quote data, but you can run backtests with only trade data. -

    - - - -

    Crypto Future

    - - -

    - Crypto Future algorithms require data from one of the price datasets and one of the margin rate datasets. - The price datasets are available in several resolutions. - The resolution you need depends on the Crypto Future subscriptions you create in your algorithm and the resolution of data you get in - - history requests - - . - The following table describes the file format and costs of each resolution: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Resolution - - File Format - - Cost per file -
    - Tick - - One file per security per trading day per data format. Quote and trade data are separate files. -
    -
    - 100 QCC = $1 USD -
    - Second - - One file per security per trading day per data format. Quote and trade data are separate files. -
    -
    - 25 QCC = $0.25 USD -
    - Minute - - One file per security per trading day per data format. Quote and trade data are separate files. -
    -
    - 5 QCC = $0.05 USD -
    - Hour - - One file per security. Quote and trade data are separate files. -
    -
    - 400 QCC = $4 USD -
    - Daily - - One file per security. Quote and trade data are separate files. -
    -
    - 100 QCC = $1 USD -
    -

    - The file format of the margin rate data is one file per Crypto Future and each file costs 100 QCC = $1 USD. -

    -

    - For example, the following algorithm subscribes to minute resolution data for one Crypto Future: -

    -
    -
    public class CryptoFutureDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 1, 1);
    -        SetEndDate(2021, 1, 1);
    -        SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
    -        AddCryptoFuture("BTCUSD");
    -    }
    -}
    -
    class CryptoFutureDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 1, 1)
    -        self.set_end_date(2021, 1, 1)
    -        self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
    -        self.add_crypto_future('BTCUSD')
    -
    -

    - The following table shows the data cost of the preceding algorithm: -

    - - - - - - - - - - - - - - - - - - - - - - - -
    - Dataset - - Package - - Initial Cost - - Ongoing Cost -
    - Binance Crypto Future Price Data - - Minute Download - - 1 security over 365 trading days with 2 data formats -
    - => 1 * 365 * 2 files -
    - = 730 files -
    -
    - 730 files @ 5 QCC/file -
    - => 730 * 5 QCC -
    - = 3,650 QCC -
    - = $36.50 USD -
    - 2 files per day @ 5 QCC/file -
    - => 2 * 5 QCC/day -
    - = 10 QCC/day -
    - = $0.10 USD/day -
    - Binance Crypto Future Margin Rate Data - - Download On Premise - - 1 security -
    - => 1 file -
    -
    - 1 file @ 100 QCC/file -
    - => 1 * 100 QCC -
    - = 100 QCC -
    - = $1 USD -
    - 1 security -
    - => 1 file/day -
    -
    - 1 file/day @ 100 QCC/file -
    - => 1 * 100 QCC/day -
    - = 100 QCC/day -
    - = $1 USD/day -
    -

    - The preceding table assumes you download trade and quote data, but you can run backtests with only trade data. -

    - - -

    Forex

    @@ -4750,7 +4350,7 @@

    Futures

    One file per ticker per trading day per data format. Trade, quote, and open interest data are separate files. - 6 QCC = $0.06 USD + 150 QCC = $1.50 USD @@ -4761,7 +4361,7 @@

    Futures

    One file per ticker per trading day per data format. Trade, quote, and open interest data are separate files. - 5 QCC = $0.05 USD + 100 QCC = $1.00 USD @@ -4772,7 +4372,7 @@

    Futures

    One file per ticker per trading day per data format. Trade, quote, and open interest data are separate files. - 5 QCC = $0.05 USD + 50 QCC = $0.50 USD @@ -4783,7 +4383,7 @@

    Futures

    One file per ticker per data format. Trade, quote, and open interest data are separate files. - 300 QCC = $3 USD + 1500 QCC = $15 USD @@ -4794,7 +4394,7 @@

    Futures

    One file per ticker per data format. Trade, quote, and open interest data are separate files. - 100 QCC = $1 USD + 1500 QCC = $15 USD @@ -4914,13 +4514,13 @@

    Futures

    = 756 files

    - 756 files @ 5 QCC/file + 756 files @ 50 QCC/file
    - => 756 * 5 QCC + => 756 * 50 QCC
    - = 3,780 QCC + = 37,800 QCC
    - = $37.80 USD + = $378 USD 1 ticker with 3 data formats @@ -4928,11 +4528,11 @@

    Futures

    => 3 files/day

    - 3 file/day @ 5 QCC/file + 3 file/day @ 50 QCC/file
    - => 15 QCC/day + => 150 QCC/day
    - = $0.15 USD/day + = $1.50 USD/day @@ -37422,7 +37022,7 @@

    Options

    - --bybit-use-testnet <enum: live|paper> + --bybit-use-testnet <enum: live|paper|demo> @@ -46024,7 +45624,7 @@

    Options

    - --bybit-use-testnet <enum: live|paper> + --bybit-use-testnet <enum: live|paper|demo> diff --git a/single-page/Quantconnect-Local-Platform.html b/single-page/Quantconnect-Local-Platform.html index 92ba1b958e..5d7f650181 100644 --- a/single-page/Quantconnect-Local-Platform.html +++ b/single-page/Quantconnect-Local-Platform.html @@ -5141,7 +5141,11 @@

    the data providers we support in the cloud - . Your live algorithms run on our co-located servers that have 10 GB transfer speeds and low latency. + . Your live algorithms run on our co-located servers racked in + + Equinix + + that have 10 GB transfer speeds and low latency.

    @@ -8530,8 +8534,10 @@

    Example

    bbdf[['price', 'lowerband', 'middleband', 'upperband']].plot();
    -
    #load "../QuantConnect.csx"
    -using QuantConnect;
    +   
    #load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    diff --git a/single-page/Quantconnect-Research-Environment.html b/single-page/Quantconnect-Research-Environment.html
    index 8d40b9665c..1650433978 100644
    --- a/single-page/Quantconnect-Research-Environment.html
    +++ b/single-page/Quantconnect-Research-Environment.html
    @@ -105,7 +105,8 @@ 

    Table of Content

  • 10.2 Backtest Analysis
  • 10.3 Optimization Analysis
  • 10.4 Live Analysis
  • -
  • 10.5 Live Deployment Automation
  • +
  • 10.5 Live Reconciliation
  • +
  • 10.6 Live Deployment Automation
  • 11 Applying Research
  • 11.1 Key Concepts
  • 11.2 Mean Reversion
  • @@ -206,8 +207,10 @@

    Example

    bbdf[['price', 'lowerband', 'middleband', 'upperband']].plot();
    -
    #load "../QuantConnect.csx"
    -using QuantConnect;
    +   
    #load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -915,8 +918,8 @@ 

    Import C# Libraries

    #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -#r "../Plotly.NET.Interactive.dll"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
     #r "../Deedle.dll"
  • @@ -6037,10 +6040,14 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    -#load "../QuantConnect.csx"
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
     using QuantConnect.Data.Consolidators;
    @@ -6151,13 +6158,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -10244,8 +10255,12 @@ 

  • import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -10320,7 +10335,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -10420,7 +10435,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -10463,10 +10478,16 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -10476,9 +10497,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -10529,7 +10549,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -10608,13 +10628,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -11163,10 +11187,11 @@ 

    Plot Data

    package.
    -
    #r "../Plotly.NET.dll"
    -#r "../Plotly.NET.Interactive.dll"
    -
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
     using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
    @@ -11256,7 +11281,7 @@

    Plot Data

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -11281,18 +11306,23 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using QuantConnect;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Fundamental;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
     
    -// Import Plotly for plotting.
    -#r "../Plotly.NET.dll"
     using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
     
     // Create a QuantBook.
    @@ -11331,7 +11361,7 @@ 

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Create a QuantBook
     qb = QuantBook()
     
    @@ -11612,13 +11642,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -11881,10 +11915,16 @@ 

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using System.Collections.Generic;
     using QuantConnect;
     using QuantConnect.Data;
    @@ -11893,9 +11933,8 @@ 

    using QuantConnect.Algorithm; using QuantConnect.Research; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -11946,7 +11985,7 @@

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Instantiate a QuantBook instance.
     qb = QuantBook()
     # Set the date being studied.
    @@ -12139,13 +12178,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -12759,10 +12802,13 @@ 

    xaxis_rangeslider_visible=False ) ).show()

    -
    #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -
    -using QuantConnect;
    +   
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -12770,6 +12816,7 @@ 

    using QuantConnect.Data.Market; using QuantConnect.Securities.Option; using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Get the SPY Option chain for January 1, 2024. @@ -12781,10 +12828,10 @@

    // Select a contract from the chain. var expiry = chain.Select(contract => contract.Expiry).Min(); var contractSymbol = chain - .Where(contract => - contract.Expiry == expiry && + .Where(contract => + contract.Expiry == expiry && contract.Right == OptionRight.Call && - contract.Greeks.Delta > 0.3m && + contract.Greeks.Delta > 0.3m && contract.Greeks.Delta < 0.7m ) .OrderByDescending(contract => contract.OpenInterest) @@ -12815,7 +12862,7 @@

    layout.SetValue("yaxis", yAxis); layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart))

    +display(chart)
    Candlestick plot of the prices for a SPY Option contract Candlestick plot of the prices for a SPY Option contract @@ -12859,10 +12906,13 @@

    # Plot the open interest history. history.plot(title=f'{contract_symbol.value} Open Interest') plt.show() -
    #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -
    -using QuantConnect;
    +   
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    + +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -12870,6 +12920,7 @@ 

    using QuantConnect.Data.Market; using QuantConnect.Securities.Option; using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Get the TSLA Option chain for January 1, 2024. @@ -12909,7 +12960,7 @@

    layout.SetValue("yaxis", yAxis); layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart)) +display(chart)

    Line plot of the open interest for a TSLA Option contract @@ -12948,13 +12999,17 @@

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -16236,8 +16291,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -16318,7 +16377,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -16426,7 +16485,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -16451,10 +16510,16 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -16464,9 +16529,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -16517,7 +16581,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -16592,13 +16656,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -19877,8 +19945,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -19959,7 +20031,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -20067,7 +20139,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -20092,10 +20164,16 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -20105,9 +20183,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -20158,7 +20235,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -20520,13 +20597,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -22235,10 +22316,16 @@ 

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -22248,9 +22335,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -22306,7 +22392,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -22394,13 +22480,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -22981,18 +23071,21 @@ 

    #load "../Initialize.csx"

    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    -using Plotly.NET.LayoutObjects;
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    -
    #load "../QuantConnect.csx"
    -using QuantConnect;
    +   
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Research;
     using QuantConnect.Securities;
     using QuantConnect.Data.Market;
    -    
    +using Plotly.NET;
    +using Plotly.NET.Interactive;
    +using Plotly.NET.LayoutObjects;
    +
     var qb = new QuantBook();
     // Get the front-month ES contract as of December 31, 2021.
     var future = qb.AddFuture(Futures.Indices.SP500EMini);
    @@ -23021,7 +23114,7 @@ 

    layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart))

    +display(chart)
    Candlestick plot of ES18H22 OHLC Candlestick plot of ES18H22 OHLC @@ -23063,18 +23156,21 @@

    #load "../Initialize.csx"
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    -using Plotly.NET.LayoutObjects;
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    -
    #load "../QuantConnect.csx"
    -using QuantConnect;
    +   
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Research;
     using QuantConnect.Securities;
     using QuantConnect.Data.Market;
    -    
    +using Plotly.NET;
    +using Plotly.NET.Interactive;
    +using Plotly.NET.LayoutObjects;
    +
     var qb = new QuantBook();
     // Get the front-month ES contract as of December 31, 2021.
     var future = qb.AddFuture(Futures.Indices.SP500EMini);
    @@ -23100,7 +23196,7 @@ 

    layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart))

    +display(chart)
    Line chart of close price of Future contracts Line chart of open interest of ES18H22 @@ -23345,13 +23441,17 @@

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -24029,10 +24129,16 @@ 

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using System.Collections.Generic;
     using QuantConnect;
     using QuantConnect.Data;
    @@ -24041,9 +24147,8 @@ 

    using QuantConnect.Algorithm; using QuantConnect.Research; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -24098,7 +24203,7 @@

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Instantiate a QuantBook instance.
     qb = QuantBook()
     # Set the date being studied.
    @@ -24164,13 +24269,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -24771,10 +24880,13 @@ 

    xaxis_rangeslider_visible=False ) ).show()

    -
    #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -
    -using QuantConnect;
    +   
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -24782,6 +24894,7 @@ 

    using QuantConnect.Data.Market; using QuantConnect.Securities; using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Add the underlying Future contract @@ -24829,7 +24942,7 @@

    layout.SetValue("yaxis", yAxis); layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart))

    +display(chart)
    Candlestick plot of the prices for an ES Future Option contract Candlestick plot of the prices for an ES Future Option contract @@ -24867,13 +24980,17 @@

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -27761,8 +27878,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -27843,7 +27964,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -27951,7 +28072,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -27976,10 +28097,16 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -27989,9 +28116,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -28042,7 +28168,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -28117,13 +28243,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -31011,8 +31141,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -31093,7 +31227,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -31201,7 +31335,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -31226,10 +31360,16 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -31239,9 +31379,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -31292,7 +31431,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -31367,13 +31506,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -33633,8 +33776,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -33715,7 +33862,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -33823,7 +33970,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -33848,10 +33995,16 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
    @@ -33861,9 +34014,8 @@ 

    using QuantConnect.Research; using QuantConnect.Securities; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -33914,7 +34066,7 @@

    // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Import plotly library for plotting.
     import plotly.graph_objects as go
     
    @@ -34198,13 +34350,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -34483,10 +34639,16 @@ 

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using System;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using System;
     using System.Collections.Generic;
     using QuantConnect;
     using QuantConnect.Data;
    @@ -34495,9 +34657,8 @@ 

    using QuantConnect.Algorithm; using QuantConnect.Research; -// Import Plotly for plotting. -#r "../Plotly.NET.dll" using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Create a QuantBook. @@ -34549,7 +34710,7 @@

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Instantiate a QuantBook instance.
     qb = QuantBook()
     # Set the date being studied.
    @@ -34744,13 +34905,17 @@ 

    Create Subscriptions

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -35383,10 +35548,13 @@ 

    xaxis_rangeslider_visible=False ) ).show()

    -
    #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -
    -using QuantConnect;
    +   
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -35394,6 +35562,7 @@ 

    using QuantConnect.Data.Market; using QuantConnect.Securities.Option; using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Get the SPX Option chain for January 1, 2024. @@ -35441,7 +35610,7 @@

    layout.SetValue("yaxis", yAxis); layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart))

    +display(chart)
    Candlestick plot of the prices for an SPX Index Option contract Candlestick plot of the prices for an SPX Index Option contract @@ -35487,10 +35656,13 @@

    # Plot the open interest history. history.plot(title=f'{contract_symbol.value} Open Interest') plt.show() -
    #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -
    -using QuantConnect;
    +   
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    + +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -35498,6 +35670,7 @@ 

    using QuantConnect.Data.Market; using QuantConnect.Securities.Option; using Plotly.NET; +using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Get the VIX weekly Option chain for January 1, 2024. @@ -35539,7 +35712,7 @@

    layout.SetValue("yaxis", yAxis); layout.SetValue("title", title); chart.WithLayout(layout); -HTML(GenericChart.toChartHTML(chart)) +display(chart)

    Line plot of the open interest for a VIWX Index Option contract @@ -35583,11 +35756,14 @@

    Create Subscriptions

    Load the required assembly files and data types.
    -
    #load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +    
    #load "../Initialize.csx"
    +
    +
    +
    #load "../QuantConnect.csx"
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -37293,8 +37469,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -37375,7 +37555,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the alternative data. @@ -37483,7 +37663,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -37508,18 +37688,23 @@

    // Load the required assembly files and data types in a separate cell.
    -#load "../Initialize.csx"
    -
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -using QuantConnect;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.DataSource;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
     
    -// Import Plotly for plotting.
    -#r "../Plotly.NET.dll"
     using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
     
     // Create a QuantBook.
    @@ -37558,7 +37743,7 @@ 

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Create a QuantBook
     qb = QuantBook()
     
    @@ -37623,11 +37808,14 @@ 

    Define Custom Data

    methods.

    -
    #load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +   
    #load "../Initialize.csx"
    +
    +
    +
    #load "../QuantConnect.csx"
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -38168,8 +38356,12 @@ 

    import plotly.graph_objects as go
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -38250,7 +38442,7 @@

  • fig.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Candlestick charts display the open, high, low, and close prices of the security. @@ -38344,7 +38536,7 @@

    plt.show()
    -
    HTML(GenericChart.toChartHTML(chart))
    +
    display(chart)

    Line charts display the value of the property you selected in a time series. @@ -39968,21 +40160,23 @@

    // Load the assembly files and data types in their own cell.
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files.
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -#r "../Plotly.NET.Interactive.dll"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Research;
    -            
    +
     using Plotly.NET;
     using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
    -            
    +
     using Accord.Math;
     using Accord.Statistics;
    @@ -40054,7 +40248,7 @@

    Create Candlestick Chart

    chart.WithLayout(layout); // Show the plot. -HTML(GenericChart.toChartHTML(chart));
    +display(chart);

    The Jupyter Notebook displays the candlestick chart. @@ -40103,7 +40297,7 @@

    Create Line Chart

    chart.WithLayout(layout); // Show the plot. -HTML(GenericChart.toChartHTML(chart));
    +display(chart);

    The Jupyter Notebook displays the line chart. @@ -40152,7 +40346,7 @@

    Create Scatter Plot

    chart.WithLayout(layout); // Show the plot. -HTML(GenericChart.toChartHTML(chart)); +display(chart);

    The Jupyter Notebook displays the scatter plot. @@ -40213,7 +40407,7 @@

    Create Heat Map

    heatmap.WithLayout(layout); // Show the plot. -HTML(GenericChart.toChartHTML(heatmap)) +display(heatmap)

    The Jupyter Notebook displays the heat map. @@ -40268,7 +40462,7 @@

    Create 3D Chart

    chart.WithLayout(layout); // Show the plot. -HTML(GenericChart.toChartHTML(heatmap)) +display(chart)

    The Jupyter Notebook displays the scatter plot. @@ -40505,6 +40699,81 @@

    Available Universes

    + + + Binance Crypto Price Data + + + + CryptoUniverse + + + + + Learn more + + + + + + Binance US Crypto Price Data + + + + CryptoUniverse + + + + + Learn more + + + + + + Bitfinex Crypto Price Data + + + + CryptoUniverse + + + + + Learn more + + + + + + Bybit Crypto Price Data + + + + CryptoUniverse + + + + + Learn more + + + + + + Coinbase Crypto Price Data + + + + CryptoUniverse + + + + + Learn more + + + International Future Universe @@ -40529,6 +40798,21 @@

    Available Universes

    + + + Kraken Crypto Price Data + + + + CryptoUniverse + + + + + Learn more + + + US ETF Constituents @@ -40640,96 +40924,6 @@

    Available Universes

    - - - Binance Crypto Price Data - - - - CryptoUniverse - - - - - Learn more - - - - - - Binance US Crypto Price Data - - - - CryptoUniverse - - - - - Learn more - - - - - - Bitfinex Crypto Price Data - - - - CryptoUniverse - - - - - Learn more - - - - - - Bybit Crypto Price Data - - - - CryptoUniverse - - - - - Learn more - - - - - - Coinbase Crypto Price Data - - - - CryptoUniverse - - - - - Learn more - - - - - - Kraken Crypto Price Data - - - - CryptoUniverse - - - - - Learn more - - - Brain Language Metrics on Company Filings @@ -40940,10 +41134,16 @@

    // Load the required assembly files and data types.
    -#load "../Initialize.csx"
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
     using QuantConnect.Algorithm;
    @@ -41034,7 +41234,7 @@ 

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)
    # Instantiate the QuantBook instance for researching.
     qb = QuantBook()
     
    @@ -41468,14 +41668,16 @@ 

    // Load the assembly files and data types in their own cell. 
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files. 
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files. 
     #load "../QuantConnect.csx"
     #r "nuget: Plotly.NET"
    -#r "nuget: Plotly.NET.Interactive"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Data.Market;
     using QuantConnect.Indicators;
    @@ -41776,14 +41978,16 @@ 

    // Load the assembly files and data types in their own cell. 
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files. 
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files. 
     #load "../QuantConnect.csx"
     #r "nuget: Plotly.NET"
    -#r "nuget: Plotly.NET.Interactive"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Data.Market;
     using QuantConnect.Indicators;
    @@ -42081,14 +42285,16 @@ 

    // Load the assembly files and data types in their own cell. 
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files. 
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files. 
     #load "../QuantConnect.csx"
     #r "nuget: Plotly.NET"
    -#r "nuget: Plotly.NET.Interactive"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Data.Market;
     using QuantConnect.Indicators;
    @@ -42429,18 +42635,20 @@ 

    // Load the assembly files and data types in their own cell.
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files.
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -#r "../Plotly.NET.Interactive.dll"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Indicators;
     using QuantConnect.Research;
    -            
    +
     using Plotly.NET;
     using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
    @@ -42491,7 +42699,7 @@ 

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Instantiate the QuantBook instance for researching.
     qb = QuantBook()
     # Request SPY data to work with the indicator.
    @@ -42863,18 +43071,20 @@ 

    // Load the assembly files and data types in their own cell.
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files.
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -#r "../Plotly.NET.Interactive.dll"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Indicators;
     using QuantConnect.Research;
    -            
    +
     using Plotly.NET;
     using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
    @@ -42976,7 +43186,7 @@ 

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Instantiate the QuantBook instance for researching.
     qb = QuantBook()
     # Request SPY data to work with the indicator.
    @@ -43338,18 +43548,20 @@ 

    // Load the assembly files and data types in their own cell.
    -#load "../Initialize.csx"
    -
    -// Load the necessary assembly files.
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
     #load "../QuantConnect.csx"
    -#r "../Plotly.NET.dll"
    -#r "../Plotly.NET.Interactive.dll"
    -
    -// Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting.
     using QuantConnect;
     using QuantConnect.Indicators;
     using QuantConnect.Research;
    -            
    +
     using Plotly.NET;
     using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
    @@ -43442,7 +43654,7 @@ 

    chart.WithLayout(layout); // Display the plot. -HTML(GenericChart.toChartHTML(chart))

    +display(chart)

    # Instantiate the QuantBook instance for researching.
     qb = QuantBook()
     # Request SPY data to work with the indicator.
    @@ -44267,11 +44479,14 @@ 

    Example for Plotting

    // Execute the following command in first
    -#load "../Initialize.csx"
    -
    -// Create a QuantBook object
    -#load "../QuantConnect.csx"
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Research;
     
     var qb = new QuantBook();
    @@ -44312,8 +44527,12 @@

    Example for Plotting

    packages.
    -
    #r "../Plotly.NET.dll"
    -using Plotly.NET;
    +    
    #r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +
    +
    using Plotly.NET;
    +using Plotly.NET.Interactive;
     using Plotly.NET.LayoutObjects;
  • @@ -44383,15 +44602,11 @@

    Example for Plotting

    Line - object and create the - - HTML - - object. + object and display the chart.
  • chart.WithLayout(layout);
    -var result = HTML(GenericChart.toChartHTML(chart));
    +display(chart);
    @@ -44508,11 +44723,11 @@

    Example for Logging

    if (_emaShort > _emaLong && !Portfolio[_symbol].IsLong) { - MarketOrder(_symbol, 100, tag: $"BUY: ema-short: {_emaShort:F4} > ema-long: {_emaLong:F4}"); + MarketOrder(_symbol, 100, tag: $"BUY: ema-short: {_emaShort:F4} > ema-long: {_emaLong:F4}"); } else if (_emaShort < _emaLong && !Portfolio[_symbol].IsShort) { - MarketOrder(_symbol, -100, tag: $"SELL: ema-short: {_emaShort:F4} < ema-long: {_emaLong:F4}"); + MarketOrder(_symbol, -100, tag: $"SELL: ema-short: {_emaShort:F4} < ema-long: {_emaLong:F4}"); } }

    def on_data(self, data: Slice):
    @@ -44522,9 +44737,9 @@ 

    Example for Logging

    ema_short = self._ema_short.current.value ema_long = self._ema_long.current.value if ema_short > ema_long and not self.portfolio[self._symbol].is_long: - self.market_order(self._symbol, 100, tag=f'BUY: ema-short: {ema_short:.4f} > ema-long: {ema_long:.4f}') + self.market_order(self._symbol, 100, tag=f'BUY: ema-short: {ema_short:.4f} > ema-long: {ema_long:.4f}') elif ema_short < ema_long and not self.portfolio[self._symbol].is_short: - self.market_order(self._symbol, -100, tag=f'SELL: ema-short: {ema_short:.4f} < ema-long: {ema_long:.4f}')
    + self.market_order(self._symbol, -100, tag=f'SELL: ema-short: {ema_short:.4f} < ema-long: {ema_long:.4f}')

  • In the @@ -44584,11 +44799,14 @@

    Example for Logging

  • // Execute the following command in first
    -#load "../Initialize.csx"
    -
    -// Create a QuantBook object
    -#load "../QuantConnect.csx"
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Research;
     
     var qb = new QuantBook();
    @@ -44712,11 +44930,11 @@

    Example for Logging

    // Place a market order when the EMAs cross. if (_emaShort > _emaLong && !Portfolio[_symbol].IsLong) { - MarketOrder(_symbol, 100, tag: $"BUY: ema-short: {_emaShort:F4} > ema-long: {_emaLong:F4}"); + MarketOrder(_symbol, 100, tag: $"BUY: ema-short: {_emaShort:F4} > ema-long: {_emaLong:F4}"); } else if (_emaShort < _emaLong && !Portfolio[_symbol].IsShort) { - MarketOrder(_symbol, -100, tag: $"SELL: ema-short: {_emaShort:F4} < ema-long: {_emaLong:F4}"); + MarketOrder(_symbol, -100, tag: $"SELL: ema-short: {_emaShort:F4} < ema-long: {_emaLong:F4}"); } } @@ -44758,9 +44976,9 @@

    Example for Logging

    ema_short = self._ema_short.current.value ema_long = self._ema_long.current.value if ema_short > ema_long and not self.portfolio[self._symbol].is_long: - self.market_order(self._symbol, 100, tag=f'BUY: ema-short: {ema_short:.4f} > ema-long: {ema_long:.4f}') + self.market_order(self._symbol, 100, tag=f'BUY: ema-short: {ema_short:.4f} > ema-long: {ema_long:.4f}') elif ema_short < ema_long and not self.portfolio[self._symbol].is_short: - self.market_order(self._symbol, -100, tag=f'SELL: ema-short: {ema_short:.4f} < ema-long: {ema_long:.4f}') + self.market_order(self._symbol, -100, tag=f'SELL: ema-short: {ema_short:.4f} < ema-long: {ema_long:.4f}') def on_order_event(self, order_event: OrderEvent) -> None: if order_event.status != OrderStatus.FILLED: @@ -50530,10 +50748,13 @@

    Read Backtest Results

    method with the project Id and backtest ID.

    -
    #load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +   
    #load "../Initialize.csx"
    +
    +
    +
    #load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Api;
     
     var backtest = api.ReadBacktest(projectId, backtestId);
    @@ -51324,10 +51545,14 @@

    // Load the necessary assemblies.
    -#load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Api;
     using QuantConnect.Research;
     
    @@ -51473,10 +51698,14 @@ 

    // Load the necessary assemblies.
    -#load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Api;
     using QuantConnect.Research;
     
    @@ -51550,10 +51779,13 @@ 

    Read Live Results

    method with the project Id and deployment ID.

    -
    #load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +   
    #load "../Initialize.csx"
    +
    +
    +
    #load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Api;
     
     var liveAlgorithm = api.ReadLiveAlgorithm(projectId, deployId);
    @@ -51640,74 +51872,6 @@

    Read Live Results

    -

    Reconciliation

    - - -

    - Reconciliation is a way to - - quantify - - the difference between an algorithm's live performance and its out-of-sample (OOS) performance (a backtest run over the live deployment period). -

    -

    - Seeing the difference between live performance and OOS performance gives you a way to determine if the algorithm is making unrealistic assumptions, exploiting data differences, or merely exhibiting behavior that is impractical or impossible in live trading. -

    -

    - A perfectly reconciled algorithm has an exact overlap between its live equity and OOS backtest curves. Any deviation means that the performance of the algorithm has differed for some reason. Several factors can contribute to this, often stemming from the algorithm design. -

    -

    - Live Deployment Reconciliation - - -

    -

    - Reconciliation is scored using two metrics: returns correlation and dynamic time warping (DTW) distance. -

    -

    - What is DTW Distance? -

    -

    - Dynamic Time Warp (DTW) Distance quantifies the difference between two time-series. It is an algorithm that measures the shortest path between the points of two time-series. It uses Euclidean distance as a measurement of - - point-to-point distance - - and returns an overall measurement of the distance on the scale of the initial time-series values. We apply DTW to the returns curve of the live and OOS performance, so the DTW distance measurement is on the scale of percent returns. -

    - $$\begin{equation} -DTW(X,Y) = min\bigg\{\sum_{l=1}^{L}\left(x_{m_l} - y_{n_l}\right)^{2}\in P^{N\times M}\bigg\} -\end{equation}$$ -

    - For the reasons outlined in our research notebook on the topic (linked below), QuantConnect annualizes the daily DTW. An annualized distance provides a user with a measurement of the annual difference in the magnitude of returns between the two curves. A perfect score is 0, meaning the returns for each day were precisely the same. A DTW score of 0 is nearly impossible to achieve, and we consider anything below 0.2 to be a decent score. A distance of 0.2 means the returns between an algorithm's live and OOS performance deviated by 20% over a year. -

    -

    - What is Returns Correlation? -

    -

    - Returns correlation is the simple Pearson correlation between the live and OOS returns. Correlation gives us a rudimentary understanding of how the returns move together. Do they trend up and down at the same time? Do they deviate in direction or timing? -

    - $$\begin{equation} -\rho_{XY} = \frac{cov(X, Y)}{\sigma_X\sigma_Y} -\end{equation}$$ -

    - An algorithm's returns correlation should be as close to 1 as possible. We consider a good score to be 0.8 or above, meaning that there is a strong positive correlation. This indicates that the returns move together most of the time and that for any given return you see from one of the curves, the other curve usually has a similar direction return (positive or negative). -

    -

    - Why Do We Need Both DTW and Returns Correlation? -

    -

    - Each measurement provides insight into distinct elements of time-series similarity, but neither measurement alone gives us the whole picture. Returns correlation tells us whether or not the live and OOS returns move together, but it doesn't account for the possible differences in the magnitude of the returns. DTW distance measures the difference in magnitude of returns but provides no insight into whether or not the returns move in the same direction. It is possible for there to be two cases of equity curve similarity where both pairs have the same DTW distance, but one has perfectly negatively correlated returns, and the other has a perfectly positive correlation. Similarly, it is possible for two pairs of equity curves to each have perfect correlation but substantially different DTW distance. Having both measurements provides us with a more comprehensive understanding of the actual similarity between live and OOS performance. We outline several interesting cases and go into more depth on the topic of reconciliation in - - research - - we have published. -

    - - -

    Plot Order Fills

    @@ -52218,10 +52382,14 @@

    // Load the necessary assemblies.
    -#load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Api;
     using QuantConnect.Research;
     
    @@ -52254,9 +52422,1079 @@ 

     

    - +
    +

    Meta Analysis

    +

    Live Reconciliation

    +
    +
    +

    Introduction

    + + +

    + This page shows you how to generate the out-of-sample (OOS) backtest reconciliation curve from a live deployment in the Research Environment so you can quantitatively and visually compare live versus backtest performance. You read the live deployment's launch datetime and starting equity, run a backtest with matching parameters, and overlay the two "Strategy Equity" curves along with every order fill on a single chart per security. +

    +

    + Reconciliation is a way to + + quantify + + the difference between an algorithm's live performance and its out-of-sample (OOS) performance (a backtest run over the live deployment period). +

    +

    + Seeing the difference between live performance and OOS performance gives you a way to determine if the algorithm is making unrealistic assumptions, exploiting data differences, or merely exhibiting behavior that is impractical or impossible in live trading. +

    +

    + A perfectly reconciled algorithm has an exact overlap between its live equity and OOS backtest curves. Any deviation means that the performance of the algorithm has differed for some reason. Several factors can contribute to this, often stemming from the algorithm design. For a catalogue of common deviation causes (data, modeling, brokerage, third-party indicators, and real-time scheduled events), see + + Reconciliation + + in the Writing Algorithms documentation. +

    + Live Deployment Reconciliation + + +

    + Reconciliation is scored using two metrics: returns correlation and dynamic time warping (DTW) distance. +

    +

    + What is DTW Distance? +

    +

    + Dynamic Time Warp (DTW) Distance quantifies the difference between two time-series. It is an algorithm that measures the shortest path between the points of two time-series. It uses Euclidean distance as a measurement of + + point-to-point distance + + and returns an overall measurement of the distance on the scale of the initial time-series values. We apply DTW to the returns curve of the live and OOS performance, so the DTW distance measurement is on the scale of percent returns. +

    + $$\begin{equation} +DTW(X,Y) = min\bigg\{\sum_{l=1}^{L}\left(x_{m_l} - y_{n_l}\right)^{2}\in P^{N\times M}\bigg\} +\end{equation}$$ +

    + For the reasons outlined in our research notebook on the topic (linked below), QuantConnect annualizes the daily DTW. An annualized distance provides a user with a measurement of the annual difference in the magnitude of returns between the two curves. A perfect score is 0, meaning the returns for each day were precisely the same. A DTW score of 0 is nearly impossible to achieve, and we consider anything below 0.2 to be a decent score. A distance of 0.2 means the returns between an algorithm's live and OOS performance deviated by 20% over a year. +

    +

    + What is Returns Correlation? +

    +

    + Returns correlation is the simple Pearson correlation between the live and OOS returns. Correlation gives us a rudimentary understanding of how the returns move together. Do they trend up and down at the same time? Do they deviate in direction or timing? +

    + $$\begin{equation} +\rho_{XY} = \frac{cov(X, Y)}{\sigma_X\sigma_Y} +\end{equation}$$ +

    + An algorithm's returns correlation should be as close to 1 as possible. We consider a good score to be 0.8 or above, meaning that there is a strong positive correlation. This indicates that the returns move together most of the time and that for any given return you see from one of the curves, the other curve usually has a similar direction return (positive or negative). +

    +

    + Why Do We Need Both DTW and Returns Correlation? +

    +

    + Each measurement provides insight into distinct elements of time-series similarity, but neither measurement alone gives us the whole picture. Returns correlation tells us whether or not the live and OOS returns move together, but it doesn't account for the possible differences in the magnitude of the returns. DTW distance measures the difference in magnitude of returns but provides no insight into whether or not the returns move in the same direction. It is possible for there to be two cases of equity curve similarity where both pairs have the same DTW distance, but one has perfectly negatively correlated returns, and the other has a perfectly positive correlation. Similarly, it is possible for two pairs of equity curves to each have perfect correlation but substantially different DTW distance. Having both measurements provides us with a more comprehensive understanding of the actual similarity between live and OOS performance. We outline several interesting cases and go into more depth on the topic of reconciliation in + + research + + we have published. +

    + + + +

    Get Live Deployment Parameters

    + + +

    + Follow these steps to read the live deployment's start datetime, starting equity, and end datetime — the three parameters the OOS backtest must match. All three values come from the live "Strategy Equity" chart, so you only need the project Id. +

    +
      +
    1. + Define the project Id. +
    2. +
      +
      var projectId = 23034953;
      +
      project_id = 23034953
      +
      +

      + The following table provides links to documentation that explains how to get the project Id, depending on the platform you use: +

      + + + + + + + + + + + + + + + + + + + + + +
      + Platform + + Project Id +
      + Cloud Platform + + + Get Project Id + +
      + Local Platform + + + Get Project Id + +
      + CLI + + + Get Project Id + +
      +
    3. + Read the live "Strategy Equity" chart with the + + ReadLiveChart + + + read_live_chart + + method. The first and last + + Equity + + points give you the start datetime, starting equity, and end datetime. +
    4. +
      +
      var nowSec = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
      +
      +Chart ReadLiveChartWithRetry(int projectId, string chartName)
      +{
      +    for (var attempt = 0; attempt < 10; attempt++)
      +    {
      +        var result = api.ReadLiveChart(projectId, chartName, 0, nowSec, 500);
      +        if (result.Success) return result.Chart;
      +        Console.WriteLine($"Chart data is loading... (attempt {attempt + 1}/10)");
      +        Thread.Sleep(10000);
      +    }
      +    throw new Exception($"Failed to read {chartName} chart after 10 attempts");
      +}
      +
      +var strategyEquity = ReadLiveChartWithRetry(projectId, "Strategy Equity");
      +// The first few points in the series can have a null close, so keep only
      +// the points with a valid close value before extracting start/end.
      +var validValues = strategyEquity.Series["Equity"].Values
      +    .OfType<Candlestick>()
      +    .Where(v => v.Close.HasValue)
      +    .ToList();
      +
      +// Start datetime and starting equity: first valid point.
      +var startDatetime = validValues.First().Time;
      +var startingCash = validValues.First().Close.Value;
      +// End datetime: last valid timestamp of the live Strategy Equity series.
      +// Uncomment the next line instead to reconcile up to "now" and see what
      +// would have happened had you not stopped the live algorithm:
      +// var endDatetime = DateTime.UtcNow;
      +var endDatetime = validValues.Last().Time;
      +
      +Console.WriteLine($"Start (UTC): {startDatetime}");
      +Console.WriteLine($"Starting equity: ${startingCash:N2}");
      +Console.WriteLine($"End (UTC): {endDatetime}");
      +
      from datetime import datetime
      +from time import sleep, time
      +
      +def read_chart(project_id, chart_name, start=0, end=int(time()), count=500):
      +    # Retry up to 10 times until the chart data finishes loading.
      +    for attempt in range(10):
      +        result = api.read_live_chart(project_id, chart_name, start, end, count)
      +        if result.success:
      +            return result.chart
      +        print(f"Chart data is loading... (attempt {attempt + 1}/10)")
      +        sleep(10)
      +    raise RuntimeError(f"Failed to read {chart_name} chart after 10 attempts")
      +
      +strategy_equity = read_chart(project_id, 'Strategy Equity')
      +# The first few points in the series can have a None close, so keep only
      +# the points with a valid close value before extracting start/end.
      +valid_values = [v for v in strategy_equity.series['Equity'].values if v.close is not None]
      +
      +# Start datetime and starting equity: first valid point.
      +start_datetime = valid_values[0].time
      +starting_cash = valid_values[0].close
      +# End datetime: last valid timestamp of the live Strategy Equity series.
      +# Uncomment the next line instead to reconcile up to "now" and see what
      +# would have happened had you not stopped the live algorithm:
      +# end_datetime = datetime.utcnow()
      +end_datetime = valid_values[-1].time
      +
      +print(f"Start (UTC): {start_datetime}")
      +print(f"Starting equity: ${starting_cash:,.2f}")
      +print(f"End (UTC): {end_datetime}")
      +
      +
    + + + +

    Run OOS Backtest

    + + +

    + Follow these steps to run an out-of-sample backtest that mirrors the live deployment. +

    +
      +
    1. + In the project's main algorithm file, set the start date and starting cash to match the values you read in the previous step. Use + + SetStartDate + + + set_start_date + + and + + SetCash + + + set_cash + + so the backtest begins at the same moment and with the same equity as the live deployment. You can either hard-code the values or expose them as + + parameters + + . +
    2. +
    3. + Compile the project by calling the + + CreateCompile + + + create_compile + + method, then poll + + ReadCompile + + + read_compile + + until the compile state is + + BuildSuccess + + . +
    4. +
      +
      var compilation = api.CreateCompile(projectId);
      +var compileId = compilation.CompileId;
      +
      +// Poll until the build succeeds.
      +for (var attempt = 0; attempt < 10; attempt++)
      +{
      +    var result = api.ReadCompile(projectId, compileId);
      +    if (result.State == CompileState.BuildSuccess) break;
      +    if (result.State == CompileState.BuildError)
      +    {
      +        throw new Exception($"Compilation failed: {string.Join(Environment.NewLine, result.Logs)}");
      +    }
      +    Console.WriteLine($"Compile in queue... (attempt {attempt + 1}/10)");
      +    Thread.Sleep(5000);
      +}
      +
      from time import sleep
      +
      +compilation = api.create_compile(project_id)
      +compile_id = compilation.compile_id
      +
      +# Poll until the build succeeds.
      +for attempt in range(10):
      +    result = api.read_compile(project_id, compile_id)
      +    if result.state == 'BuildSuccess':
      +        break
      +    if result.state == 'BuildError':
      +        raise Exception(f"Compilation failed: {result.logs}")
      +    print(f"Compile in queue... (attempt {attempt + 1}/10)")
      +    sleep(5)
      +
      +
    5. + Create the OOS backtest with the + + CreateBacktest + + + create_backtest + + method. +
    6. +
      +
      var backtest = api.CreateBacktest(projectId, compileId, "OOS Reconciliation");
      +var backtestId = backtest.BacktestId;
      +Console.WriteLine($"Backtest Id: {backtestId}");
      +
      backtest = api.create_backtest(project_id, compile_id, 'OOS Reconciliation')
      +backtest_id = backtest.backtest_id
      +print(f"Backtest Id: {backtest_id}")
      +
      +
    7. + Poll the + + ReadBacktest + + + read_backtest + + method until the + + completed + + flag is + + True + + . Log the + + progress + + attribute on each poll so you can watch the backtest advance. +
    8. +
      +
      var completed = false;
      +while (!completed)
      +{
      +    var result = api.ReadBacktest(projectId, backtestId);
      +    completed = result.Completed;
      +    Console.WriteLine($"Backtest running... {result.Progress:P2}");
      +    Thread.Sleep(10000);
      +}
      +Console.WriteLine("Backtest completed.");
      +
      completed = False
      +while not completed:
      +    result = api.read_backtest(project_id, backtest_id)
      +    completed = result.completed
      +    print(f"Backtest running... {result.progress:.2%}")
      +    sleep(10)
      +print("Backtest completed.")
      +
      +
    + + + +

    Plot Equity Curves

    + + +

    + Follow these steps to plot the live and OOS backtest equity curves on the same axes. +

    +
      +
    1. + Read the live "Strategy Equity" chart using the retry helper from the previous step. +
    2. +
      +
      var liveEquityChart = ReadLiveChartWithRetry(projectId, "Strategy Equity");
      +
      live_equity_chart = read_chart(project_id, 'Strategy Equity')
      +
      +
    3. + Read the backtest "Strategy Equity" chart by calling the + + ReadBacktestChart + + + read_backtest_chart + + method with the same retry pattern. +
    4. +
      +
      Chart ReadBacktestChartWithRetry(int projectId, string backtestId, string chartName)
      +{
      +    for (var attempt = 0; attempt < 10; attempt++)
      +    {
      +        var result = api.ReadBacktestChart(projectId, chartName, 0, nowSec, 500, backtestId);
      +        if (result.Success) return result.Chart;
      +        Console.WriteLine($"Chart data is loading... (attempt {attempt + 1}/10)");
      +        Thread.Sleep(10000);
      +    }
      +    throw new Exception($"Failed to read backtest {chartName} chart after 10 attempts");
      +}
      +
      +var backtestEquityChart = ReadBacktestChartWithRetry(projectId, backtestId, "Strategy Equity");
      +
      def read_backtest_chart(project_id, backtest_id, chart_name, start=0, end=int(time()), count=500):
      +    for attempt in range(10):
      +        result = api.read_backtest_chart(project_id, chart_name, start, end, count, backtest_id)
      +        if result.success:
      +            return result.chart
      +        print(f"Chart data is loading... (attempt {attempt + 1}/10)")
      +        sleep(10)
      +    raise RuntimeError(f"Failed to read backtest {chart_name} chart after 10 attempts")
      +
      +backtest_equity_chart = read_backtest_chart(project_id, backtest_id, 'Strategy Equity')
      +
      +
    5. + Extract the + + Equity + + series from each chart, filtering out points with a null close. Python uses a + + pandas.Series + + indexed by timestamp so the two curves can be aligned on the union of their timestamps; C# keeps two lists of + + Candlestick + + points and lets Plotly.NET align them on the same x-axis. +
    6. +
      +
      var liveValues = liveEquityChart.Series["Equity"].Values
      +    .OfType<Candlestick>()
      +    .Where(v => v.Close.HasValue)
      +    .ToList();
      +var backtestValues = backtestEquityChart.Series["Equity"].Values
      +    .OfType<Candlestick>()
      +    .Where(v => v.Close.HasValue)
      +    .ToList();
      +
      import pandas as pd
      +
      +def to_naive(t):
      +    ts = pd.Timestamp(t)
      +    return ts.tz_convert('UTC').tz_localize(None) if ts.tzinfo else ts
      +
      +def to_series(chart, series_name='Equity'):
      +    values = [v for v in chart.series[series_name].values if v.close is not None]
      +    return pd.Series(
      +        [v.close for v in values],
      +        index=pd.DatetimeIndex([to_naive(v.time) for v in values])
      +    )
      +
      +live_series = to_series(live_equity_chart)
      +backtest_series = to_series(backtest_equity_chart)
      +
      +# Keep every timestamp from both sources; align and forward-fill on the union.
      +df = pd.concat([live_series.rename('Live'), backtest_series.rename('OOS Backtest')], axis=1).sort_index().ffill()
      +
      +
    7. + Plot both curves on the same axis. Python uses + + matplotlib + + ; C# uses + + Plotly.NET + + — load + + Plotly.NET + + and + + Plotly.NET.Interactive + + from NuGet and alias + + Plotly.NET.Chart + + to avoid ambiguity with + + QuantConnect.Chart + + . +
    8. +
      +
      #r "nuget: Plotly.NET"
      +#r "nuget: Plotly.NET.Interactive"
      +using PlotlyChart = Plotly.NET.Chart;
      +using Plotly.NET;
      +using Plotly.NET.Interactive;
      +using Plotly.NET.LayoutObjects;
      +
      +var equityChart = PlotlyChart.Combine(new[]
      +{
      +    Chart2D.Chart.Line<DateTime, decimal, string>(
      +        liveValues.Select(v => v.Time),
      +        liveValues.Select(v => v.Close.Value),
      +        Name: "Live"),
      +    Chart2D.Chart.Line<DateTime, decimal, string>(
      +        backtestValues.Select(v => v.Time),
      +        backtestValues.Select(v => v.Close.Value),
      +        Name: "OOS Backtest")
      +}).WithTitle("Live vs OOS Backtest Equity");
      +
      +display(equityChart);
      +
      import matplotlib.pyplot as plt
      +
      +fig, ax = plt.subplots(figsize=(12, 6))
      +ax.plot(df.index, df['Live'], label='Live')
      +ax.plot(df.index, df['OOS Backtest'], label='OOS Backtest')
      +ax.set_title('Live vs OOS Backtest Equity')
      +ax.set_xlabel('Time')
      +ax.set_ylabel('Portfolio Value ($)')
      +ax.legend()
      +plt.show()
      +
      + Live vs OOS backtest equity curves +
    9. + Score the reconciliation with the annualized returns DTW distance and the Pearson correlation of daily returns. Use + + tslearn + + 's + + dtw + + with a Sakoe-Chiba band so the algorithm runs in linear time. The + + tslearn + + library is Python-only; run this step in a Python research notebook. +
    10. +
      +
      from tslearn.metrics import dtw as DynamicTimeWarping
      +
      +returns = df.pct_change().dropna()
      +
      +# Pearson correlation between live and OOS backtest daily returns (closer to 1 is better).
      +returns_correlation = returns.corr().iloc[0, 1]
      +
      +# Raw DTW distance on the returns curves.
      +raw_dtw = DynamicTimeWarping(
      +    returns['Live'], returns['OOS Backtest'],
      +    global_constraint='sakoe_chiba', sakoe_chiba_radius=3
      +)
      +# Annualize so the distance is on the scale of yearly percent returns (closer to 0 is better).
      +annualized_dtw = abs(((1 + (raw_dtw / returns.shape[0])) ** 252) - 1)
      +
      +print(f"Returns correlation: {returns_correlation:.3f}")
      +print(f"Annualized returns DTW: {annualized_dtw:.3f}")
      +
      +
    + + + +

    Plot Order Fills

    + + +

    + Follow these steps to overlay live and OOS backtest order fills on a single marker-only chart per symbol. The chart deliberately omits candlesticks and any price history so the comparison between live and backtest executions is not drowned out by other series. +

    +
      +
    1. + Read the live and backtest orders. Each call to + + ReadLiveOrders + + + read_live_orders + + and + + ReadBacktestOrders + + + read_backtest_orders + + returns at most 100 orders, so paginate in 100-Id windows until the endpoint returns an empty window. The first window can take a few seconds to load, so retry while it is empty. +
    2. +
      +
      List<ApiOrderResponse> ReadAllOrders(Func<int, int, List<ApiOrderResponse>> fetchWindow)
      +{
      +    var all = new List<ApiOrderResponse>();
      +    // Retry the first window while the response is empty (may be loading).
      +    List<ApiOrderResponse> first = null;
      +    for (var attempt = 0; attempt < 10; attempt++)
      +    {
      +        first = fetchWindow(0, 100);
      +        if (first.Any()) break;
      +        Console.WriteLine($"Orders loading... (attempt {attempt + 1}/10)");
      +        Thread.Sleep(10000);
      +    }
      +    if (first == null || !first.Any()) return all;
      +    all.AddRange(first);
      +    // Paginate in 100-Id windows until the endpoint returns an empty window.
      +    var start = 100;
      +    while (true)
      +    {
      +        var window = fetchWindow(start, start + 100);
      +        if (!window.Any()) break;
      +        all.AddRange(window);
      +        start += 100;
      +    }
      +    return all;
      +}
      +
      +var liveOrders = ReadAllOrders((s, e) => api.ReadLiveOrders(projectId, s, e));
      +var backtestOrders = ReadAllOrders((s, e) => api.ReadBacktestOrders(projectId, backtestId, s, e));
      +Console.WriteLine($"Live orders: {liveOrders.Count}, OOS orders: {backtestOrders.Count}");
      +
      from time import sleep
      +
      +def read_all_orders(fetch_window):
      +    orders = []
      +    # Retry the first window while the response is empty (may be loading).
      +    first = []
      +    for attempt in range(10):
      +        first = fetch_window(0, 100)
      +        if first:
      +            break
      +        print(f"Orders loading... (attempt {attempt + 1}/10)")
      +        sleep(10)
      +    if not first:
      +        return orders
      +    orders.extend(first)
      +    # Paginate in 100-Id windows until the endpoint returns an empty window.
      +    start = 100
      +    while True:
      +        window = fetch_window(start, start + 100)
      +        if not window:
      +            break
      +        orders.extend(window)
      +        start += 100
      +    return orders
      +
      +live_orders = read_all_orders(lambda s, e: api.read_live_orders(project_id, s, e))
      +backtest_orders = read_all_orders(lambda s, e: api.read_backtest_orders(project_id, backtest_id, s, e))
      +print(f"Live orders: {len(live_orders)}, OOS orders: {len(backtest_orders)}")
      +
      +

      + For more on the order objects returned, see + + Plot Order Fills + + in the Live Analysis documentation. +

      +
    3. + Organize the trade times and prices for each security into a dictionary for both the live and backtest fills. +
    4. +
      +
      var liveBySymbol = liveOrders.Select(x => x.Order).GroupBy(o => o.Symbol);
      +var backtestBySymbol = backtestOrders.Select(x => x.Order)
      +    .GroupBy(o => o.Symbol)
      +    .ToDictionary(g => g.Key, g => g.ToList());
      +
      import pandas as pd
      +
      +def to_naive(t):
      +    # Strip tzinfo so plotly can serialize the fill times.
      +    ts = pd.Timestamp(t)
      +    return ts.tz_convert('UTC').tz_localize(None) if ts.tzinfo else ts
      +
      +class OrderData:
      +    def __init__(self):
      +        self.buy_fill_times = []
      +        self.buy_fill_prices = []
      +        self.sell_fill_times = []
      +        self.sell_fill_prices = []
      +
      +def group_by_symbol(orders):
      +    data_by_symbol = {}
      +    for order in [x.order for x in orders]:
      +        if order.symbol not in data_by_symbol:
      +            data_by_symbol[order.symbol] = OrderData()
      +        data = data_by_symbol[order.symbol]
      +        is_buy = order.quantity > 0
      +        (data.buy_fill_times if is_buy else data.sell_fill_times).append(to_naive(order.last_fill_time))
      +        (data.buy_fill_prices if is_buy else data.sell_fill_prices).append(order.price)
      +    return data_by_symbol
      +
      +live_by_symbol = group_by_symbol(live_orders)
      +backtest_by_symbol = group_by_symbol(backtest_orders)
      +
      +
    5. + Plot one figure per symbol with four marker traces: live buys, live sells, backtest buys, backtest sells. Distinct markers keep live versus backtest executions visually separable. +
    6. +
      +
      foreach (var liveGroup in liveBySymbol)
      +{
      +    var symbol = liveGroup.Key;
      +    var live = liveGroup.ToList();
      +    var bt = backtestBySymbol.TryGetValue(symbol, out var btList) ? btList : new List<Order>();
      +
      +    var traces = new[]
      +    {
      +        Chart2D.Chart.Point<DateTime, decimal, string>(
      +            live.Where(o => o.Quantity > 0).Select(o => o.LastFillTime ?? o.Time),
      +            live.Where(o => o.Quantity > 0).Select(o => o.Price),
      +            Name: "Live Buys"),
      +        Chart2D.Chart.Point<DateTime, decimal, string>(
      +            live.Where(o => o.Quantity < 0).Select(o => o.LastFillTime ?? o.Time),
      +            live.Where(o => o.Quantity < 0).Select(o => o.Price),
      +            Name: "Live Sells"),
      +        Chart2D.Chart.Point<DateTime, decimal, string>(
      +            bt.Where(o => o.Quantity > 0).Select(o => o.LastFillTime ?? o.Time),
      +            bt.Where(o => o.Quantity > 0).Select(o => o.Price),
      +            Name: "OOS Backtest Buys"),
      +        Chart2D.Chart.Point<DateTime, decimal, string>(
      +            bt.Where(o => o.Quantity < 0).Select(o => o.LastFillTime ?? o.Time),
      +            bt.Where(o => o.Quantity < 0).Select(o => o.Price),
      +            Name: "OOS Backtest Sells")
      +    };
      +    var fillsChart = PlotlyChart.Combine(traces).WithTitle($"{symbol} Live vs OOS Backtest Fills");
      +    display(fillsChart);
      +}
      +
      import plotly.graph_objects as go
      +
      +symbols = set(live_by_symbol.keys()) | set(backtest_by_symbol.keys())
      +
      +for symbol in symbols:
      +    live = live_by_symbol.get(symbol, OrderData())
      +    bt = backtest_by_symbol.get(symbol, OrderData())
      +
      +    fig = go.Figure(layout=go.Layout(
      +        title=go.layout.Title(text=f'{symbol.value} Live vs OOS Backtest Fills'),
      +        xaxis_title='Fill Time',
      +        yaxis_title='Fill Price',
      +        height=600
      +    ))
      +
      +    fig.add_trace(go.Scatter(
      +        x=live.buy_fill_times, y=live.buy_fill_prices, mode='markers', name='Live Buys',
      +        marker=go.scatter.Marker(color='aqua', symbol='triangle-up', size=12)
      +    ))
      +    fig.add_trace(go.Scatter(
      +        x=live.sell_fill_times, y=live.sell_fill_prices, mode='markers', name='Live Sells',
      +        marker=go.scatter.Marker(color='indigo', symbol='triangle-down', size=12)
      +    ))
      +    fig.add_trace(go.Scatter(
      +        x=bt.buy_fill_times, y=bt.buy_fill_prices, mode='markers', name='OOS Backtest Buys',
      +        marker=go.scatter.Marker(color='aqua', symbol='triangle-up-open', size=12, line=dict(width=2))
      +    ))
      +    fig.add_trace(go.Scatter(
      +        x=bt.sell_fill_times, y=bt.sell_fill_prices, mode='markers', name='OOS Backtest Sells',
      +        marker=go.scatter.Marker(color='indigo', symbol='triangle-down-open', size=12, line=dict(width=2))
      +    ))
      +
      +    fig.show()
      +
      +
    +

    + Note: the preceding plots only show the last fill of each trade. If your trade has partial fills, the plots only display the last fill. +

    + + + +

    Examples

    + + +

    + Example 1: Generate an OOS Reconciliation Curve +

    +

    + The following example reads the live deployment's "Strategy Equity" chart, runs an OOS backtest that matches its start datetime and starting cash, and plots both the equity curves and the order fills side by side. Before running it, make sure your project's main algorithm file sets + + StartDate + + + start_date + + and + + Cash + + + cash + + to match the live deployment (or reads them as parameters). +

    +
    +
    // Load the necessary assemblies.
    +#load "../Initialize.csx"
    +#load "../QuantConnect.csx"
    +#r "nuget: Plotly.NET"
    +#r "nuget: Plotly.NET.Interactive"
    +
    +using QuantConnect;
    +using QuantConnect.Api;
    +using QuantConnect.Research;
    +using System;
    +using System.Linq;
    +using System.Threading;
    +using PlotlyChart = Plotly.NET.Chart;
    +using Plotly.NET;
    +using Plotly.NET.Interactive;
    +using Plotly.NET.LayoutObjects;
    +
    +// Instantiate QuantBook instance for researching.
    +var qb = new QuantBook();
    +var projectId = qb.ProjectId;   // Replace if the live algorithm is not in this project.
    +var nowSec = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    +
    +// Read the live Strategy Equity chart. The first and last valid points give
    +// you the start datetime, starting cash, and end datetime.
    +var liveEquity = api.ReadLiveChart(projectId, "Strategy Equity", 0, nowSec, 500).Chart;
    +var equityValues = liveEquity.Series["Equity"].Values
    +    .OfType<Candlestick>()
    +    .Where(v => v.Close.HasValue)
    +    .ToList();
    +var startDate = equityValues.First().Time;
    +var startingCash = equityValues.First().Close.Value;
    +// Uncomment to reconcile up to "now" instead:
    +// var endDate = DateTime.UtcNow;
    +var endDate = equityValues.Last().Time;
    +
    +// Compile and create the OOS backtest (start date and cash must be set in the algorithm itself).
    +var compilation = api.CreateCompile(projectId);
    +var compileId = compilation.CompileId;
    +while (api.ReadCompile(projectId, compileId).State != CompileState.BuildSuccess)
    +{
    +    Thread.Sleep(5000);
    +}
    +var backtest = api.CreateBacktest(projectId, compileId, "OOS Reconciliation");
    +var backtestId = backtest.BacktestId;
    +
    +var completed = false;
    +while (!completed)
    +{
    +    var result = api.ReadBacktest(projectId, backtestId);
    +    completed = result.Completed;
    +    Console.WriteLine($"Backtest running... {result.Progress:P2}");
    +    Thread.Sleep(10000);
    +}
    +Console.WriteLine("Backtest completed.");
    +
    +// Read the backtest Strategy Equity chart.
    +var backtestEquity = api.ReadBacktestChart(projectId, "Strategy Equity", 0, nowSec, 500, backtestId).Chart;
    +
    +// Read live and backtest orders for the fill overlay. Each call returns at
    +// most 100 orders, so paginate in 100-Id windows until we get an empty window.
    +// The first window can take a few seconds to load, so retry while empty.
    +List<ApiOrderResponse> ReadAllOrders(Func<int, int, List<ApiOrderResponse>> fetchWindow)
    +{
    +    var all = new List<ApiOrderResponse>();
    +    List<ApiOrderResponse> first = null;
    +    for (var attempt = 0; attempt < 10; attempt++)
    +    {
    +        first = fetchWindow(0, 100);
    +        if (first.Any()) break;
    +        Thread.Sleep(10000);
    +    }
    +    if (first == null || !first.Any()) return all;
    +    all.AddRange(first);
    +    var start = 100;
    +    while (true)
    +    {
    +        var window = fetchWindow(start, start + 100);
    +        if (!window.Any()) break;
    +        all.AddRange(window);
    +        start += 100;
    +    }
    +    return all;
    +}
    +
    +var liveOrders = ReadAllOrders((s, e) => api.ReadLiveOrders(projectId, s, e));
    +var backtestOrders = ReadAllOrders((s, e) => api.ReadBacktestOrders(projectId, backtestId, s, e));
    +
    +Console.WriteLine($"Start: {startDate}, Starting cash: {startingCash}, End: {endDate}");
    +Console.WriteLine($"Live orders: {liveOrders.Count}, OOS orders: {backtestOrders.Count}");
    +
    +// Overlay the two equity curves with Plotly.NET.
    +var backtestValues = backtestEquity.Series["Equity"].Values
    +    .OfType<Candlestick>()
    +    .Where(v => v.Close.HasValue)
    +    .ToList();
    +
    +var equityChart = PlotlyChart.Combine(new[]
    +{
    +    Chart2D.Chart.Line<DateTime, decimal, string>(
    +        equityValues.Select(v => v.Time),
    +        equityValues.Select(v => v.Close.Value),
    +        Name: "Live"),
    +    Chart2D.Chart.Line<DateTime, decimal, string>(
    +        backtestValues.Select(v => v.Time),
    +        backtestValues.Select(v => v.Close.Value),
    +        Name: "OOS Backtest")
    +}).WithTitle("Live vs OOS Backtest Equity");
    +display(equityChart);
    +
    +// Overlay the live and backtest fills per symbol.
    +var liveBySymbol = liveOrders.Select(x => x.Order).GroupBy(o => o.Symbol);
    +var backtestBySymbol = backtestOrders.Select(x => x.Order).GroupBy(o => o.Symbol).ToDictionary(g => g.Key, g => g.ToList());
    +
    +foreach (var liveGroup in liveBySymbol)
    +{
    +    var symbol = liveGroup.Key;
    +    var live = liveGroup.ToList();
    +    var bt = backtestBySymbol.TryGetValue(symbol, out var btList) ? btList : new List<Order>();
    +
    +    var traces = new[]
    +    {
    +        Chart2D.Chart.Point<DateTime, decimal, string>(
    +            live.Where(o => o.Quantity > 0).Select(o => o.LastFillTime ?? o.Time),
    +            live.Where(o => o.Quantity > 0).Select(o => o.Price),
    +            Name: "Live Buys"),
    +        Chart2D.Chart.Point<DateTime, decimal, string>(
    +            live.Where(o => o.Quantity < 0).Select(o => o.LastFillTime ?? o.Time),
    +            live.Where(o => o.Quantity < 0).Select(o => o.Price),
    +            Name: "Live Sells"),
    +        Chart2D.Chart.Point<DateTime, decimal, string>(
    +            bt.Where(o => o.Quantity > 0).Select(o => o.LastFillTime ?? o.Time),
    +            bt.Where(o => o.Quantity > 0).Select(o => o.Price),
    +            Name: "OOS Backtest Buys"),
    +        Chart2D.Chart.Point<DateTime, decimal, string>(
    +            bt.Where(o => o.Quantity < 0).Select(o => o.LastFillTime ?? o.Time),
    +            bt.Where(o => o.Quantity < 0).Select(o => o.Price),
    +            Name: "OOS Backtest Sells")
    +    };
    +    var fillsChart = PlotlyChart.Combine(traces).WithTitle($"{symbol} Live vs OOS Backtest Fills");
    +    display(fillsChart);
    +}
    +
    # Instantiate QuantBook instance for researching.
    +from datetime import datetime
    +from time import sleep, time
    +import pandas as pd
    +import matplotlib.pyplot as plt
    +import plotly.graph_objects as go
    +from tslearn.metrics import dtw as DynamicTimeWarping
    +
    +qb = QuantBook()
    +project_id = qb.project_id   # Replace if the live algorithm is not in this project.
    +
    +# Read the live Strategy Equity chart. The first and last points give you the
    +# start datetime, starting cash, and end datetime.
    +def read_chart(project_id, chart_name, start=0, end=int(time()), count=500):
    +    for attempt in range(10):
    +        result = api.read_live_chart(project_id, chart_name, start, end, count)
    +        if result.success:
    +            return result.chart
    +        sleep(10)
    +    raise RuntimeError(f"Failed to read {chart_name} chart after 10 attempts")
    +
    +live_equity_chart = read_chart(project_id, 'Strategy Equity')
    +# Skip leading points with a None close (common at the start of a deployment).
    +valid_values = [v for v in live_equity_chart.series['Equity'].values if v.close is not None]
    +start_datetime = valid_values[0].time
    +starting_cash = valid_values[0].close
    +# Uncomment to reconcile up to "now" instead:
    +# end_datetime = datetime.utcnow()
    +end_datetime = valid_values[-1].time
    +
    +# Compile and create the OOS backtest (start date and cash must be set in the algorithm itself).
    +compilation = api.create_compile(project_id)
    +compile_id = compilation.compile_id
    +while api.read_compile(project_id, compile_id).state != 'BuildSuccess':
    +    sleep(5)
    +backtest = api.create_backtest(project_id, compile_id, 'OOS Reconciliation')
    +backtest_id = backtest.backtest_id
    +completed = False
    +while not completed:
    +    result = api.read_backtest(project_id, backtest_id)
    +    completed = result.completed
    +    print(f'Backtest running... {result.progress:.2%}')
    +    sleep(10)
    +
    +# Read the backtest Strategy Equity chart.
    +def read_backtest_chart(project_id, backtest_id, chart_name, start=0, end=int(time()), count=500):
    +    for attempt in range(10):
    +        result = api.read_backtest_chart(project_id, chart_name, start, end, count, backtest_id)
    +        if result.success:
    +            return result.chart
    +        sleep(10)
    +    raise RuntimeError(f"Failed to read backtest {chart_name} chart after 10 attempts")
    +
    +backtest_equity_chart = read_backtest_chart(project_id, backtest_id, 'Strategy Equity')
    +
    +# Overlay the two equity curves.
    +def to_naive(t):
    +    ts = pd.Timestamp(t)
    +    return ts.tz_convert('UTC').tz_localize(None) if ts.tzinfo else ts
    +
    +def to_series(chart, series_name='Equity'):
    +    values = [v for v in chart.series[series_name].values if v.close is not None]
    +    return pd.Series(
    +        [v.close for v in values],
    +        index=pd.DatetimeIndex([to_naive(v.time) for v in values])
    +    )
    +
    +df = pd.concat([
    +    to_series(live_equity_chart).rename('Live'),
    +    to_series(backtest_equity_chart).rename('OOS Backtest')
    +], axis=1).sort_index().ffill()
    +
    +fig, ax = plt.subplots(figsize=(12, 6))
    +ax.plot(df.index, df['Live'], label='Live')
    +ax.plot(df.index, df['OOS Backtest'], label='OOS Backtest')
    +ax.set_title('Live vs OOS Backtest Equity')
    +ax.set_xlabel('Time'); ax.set_ylabel('Portfolio Value ($)')
    +ax.legend(); plt.show()
    +
    +# Score the reconciliation: returns correlation and annualized returns DTW distance.
    +returns = df.pct_change().dropna()
    +returns_correlation = returns.corr().iloc[0, 1]
    +raw_dtw = DynamicTimeWarping(
    +    returns['Live'], returns['OOS Backtest'],
    +    global_constraint='sakoe_chiba', sakoe_chiba_radius=3
    +)
    +annualized_dtw = abs(((1 + (raw_dtw / returns.shape[0])) ** 252) - 1)
    +print(f"Returns correlation: {returns_correlation:.3f}")
    +print(f"Annualized returns DTW: {annualized_dtw:.3f}")
    +
    +# Overlay the live and backtest fills per symbol.
    +class OrderData:
    +    def __init__(self):
    +        self.buy_fill_times, self.buy_fill_prices = [], []
    +        self.sell_fill_times, self.sell_fill_prices = [], []
    +
    +def group_by_symbol(orders):
    +    out = {}
    +    for order in [x.order for x in orders]:
    +        out.setdefault(order.symbol, OrderData())
    +        d = out[order.symbol]
    +        is_buy = order.quantity > 0
    +        (d.buy_fill_times if is_buy else d.sell_fill_times).append(to_naive(order.last_fill_time))
    +        (d.buy_fill_prices if is_buy else d.sell_fill_prices).append(order.price)
    +    return out
    +
    +def read_all_orders(fetch_window):
    +    orders = []
    +    first = []
    +    for attempt in range(10):
    +        first = fetch_window(0, 100)
    +        if first:
    +            break
    +        sleep(10)
    +    if not first:
    +        return orders
    +    orders.extend(first)
    +    start = 100
    +    while True:
    +        window = fetch_window(start, start + 100)
    +        if not window:
    +            break
    +        orders.extend(window)
    +        start += 100
    +    return orders
    +
    +live_by_symbol = group_by_symbol(read_all_orders(lambda s, e: api.read_live_orders(project_id, s, e)))
    +backtest_by_symbol = group_by_symbol(read_all_orders(lambda s, e: api.read_backtest_orders(project_id, backtest_id, s, e)))
    +
    +for symbol in set(live_by_symbol) | set(backtest_by_symbol):
    +    live = live_by_symbol.get(symbol, OrderData())
    +    bt = backtest_by_symbol.get(symbol, OrderData())
    +    fig = go.Figure(layout=go.Layout(
    +        title=go.layout.Title(text=f'{symbol.value} Live vs OOS Backtest Fills'),
    +        xaxis_title='Fill Time', yaxis_title='Fill Price', height=600))
    +    fig.add_trace(go.Scatter(x=live.buy_fill_times, y=live.buy_fill_prices, mode='markers',
    +        name='Live Buys', marker=go.scatter.Marker(color='aqua', symbol='triangle-up', size=12)))
    +    fig.add_trace(go.Scatter(x=live.sell_fill_times, y=live.sell_fill_prices, mode='markers',
    +        name='Live Sells', marker=go.scatter.Marker(color='indigo', symbol='triangle-down', size=12)))
    +    fig.add_trace(go.Scatter(x=bt.buy_fill_times, y=bt.buy_fill_prices, mode='markers',
    +        name='OOS Backtest Buys', marker=go.scatter.Marker(color='aqua', symbol='triangle-up-open', size=12, line=dict(width=2))))
    +    fig.add_trace(go.Scatter(x=bt.sell_fill_times, y=bt.sell_fill_prices, mode='markers',
    +        name='OOS Backtest Sells', marker=go.scatter.Marker(color='indigo', symbol='triangle-down-open', size=12, line=dict(width=2))))
    +    fig.show()
    +
    + + + +

     

    + +
    +

    Meta Analysis

    Live Deployment Automation

    @@ -52309,13 +53547,17 @@

    Get Project Ids

    #load "../Initialize.csx"
  • - Import the data types. + Load the necessary assembly files.
  • #load "../QuantConnect.csx"
    -#r "../Microsoft.Data.Analysis.dll"
    -
    -using QuantConnect;
    +#r "../Microsoft.Data.Analysis.dll"
    +
    +
  • + Import the data types. +
  • +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Algorithm;
     using QuantConnect.Research;
    @@ -52547,10 +53789,14 @@ 

    // Load the necessary assemblies.
    -#load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Api;
     using QuantConnect.Research;
     
    @@ -52875,10 +54121,15 @@ 

    Import Libraries

    libraries by the following:

    -
    #load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +   
    // Load the required assembly files and data types in a separate cell.
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
     using QuantConnect.Algorithm;
    @@ -53427,10 +54678,14 @@ 

    Examples

    // Load the required assembly files and data types.
    -#load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
     using QuantConnect.Algorithm;
    @@ -54362,10 +55617,15 @@ 

    Import Libraries

    libraries by the following:

    -
    #load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +   
    // Load the required assembly files and data types in a separate cell.
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
     using QuantConnect.Algorithm;
    @@ -54917,10 +56177,14 @@ 

    Examples

    // Load the required assembly files and data types.
    -#load "../Initialize.csx"
    -#load "../QuantConnect.csx"
    -
    -using QuantConnect;
    +#load "../Initialize.csx"
    +
    +
    +
    // Load the necessary assembly files.
    +#load "../QuantConnect.csx"
    +
    +
    +
    using QuantConnect;
     using QuantConnect.Data;
     using QuantConnect.Data.Market;
     using QuantConnect.Algorithm;
    diff --git a/single-page/Quantconnect-Writing-Algorithms.html b/single-page/Quantconnect-Writing-Algorithms.html
    index e52c6213e0..d3671384d7 100644
    --- a/single-page/Quantconnect-Writing-Algorithms.html
    +++ b/single-page/Quantconnect-Writing-Algorithms.html
    @@ -154,21 +154,29 @@ 

    Table of Content

  • 6.1 Overview
  • 6.2 QuantConnect
  • 6.2.1 Binance Crypto Future Margin Rate Data
  • -
  • 6.2.2 Bybit Crypto Future Margin Rate Data
  • -
  • 6.2.3 CFD Data
  • -
  • 6.2.4 Cash Indices
  • -
  • 6.2.5 FOREX Data
  • -
  • 6.2.6 Fear and Greed
  • -
  • 6.2.7 International Future Universe
  • -
  • 6.2.8 US ETF Constituents
  • -
  • 6.2.9 US Equities Short Availability
  • -
  • 6.2.10 US Equity Coarse Universe
  • -
  • 6.2.11 US Equity Option Universe
  • -
  • 6.2.12 US Equity Security Master
  • -
  • 6.2.13 US Future Option Universe
  • -
  • 6.2.14 US Future Universe
  • -
  • 6.2.15 US Futures Security Master
  • -
  • 6.2.16 US Index Option Universe
  • +
  • 6.2.2 Binance Crypto Future Price Data
  • +
  • 6.2.3 Binance Crypto Price Data
  • +
  • 6.2.4 Binance US Crypto Price Data
  • +
  • 6.2.5 Bitfinex Crypto Price Data
  • +
  • 6.2.6 Bybit Crypto Future Margin Rate Data
  • +
  • 6.2.7 Bybit Crypto Future Price Data
  • +
  • 6.2.8 Bybit Crypto Price Data
  • +
  • 6.2.9 CFD Data
  • +
  • 6.2.10 Cash Indices
  • +
  • 6.2.11 Coinbase Crypto Price Data
  • +
  • 6.2.12 FOREX Data
  • +
  • 6.2.13 Fear and Greed
  • +
  • 6.2.14 International Future Universe
  • +
  • 6.2.15 Kraken Crypto Price Data
  • +
  • 6.2.16 US ETF Constituents
  • +
  • 6.2.17 US Equities Short Availability
  • +
  • 6.2.18 US Equity Coarse Universe
  • +
  • 6.2.19 US Equity Option Universe
  • +
  • 6.2.20 US Equity Security Master
  • +
  • 6.2.21 US Future Option Universe
  • +
  • 6.2.22 US Future Universe
  • +
  • 6.2.23 US Futures Security Master
  • +
  • 6.2.24 US Index Option Universe
  • 6.3 AlgoSeek
  • 6.3.1 US Equities
  • 6.3.2 US Equity Options
  • @@ -179,69 +187,60 @@

    Table of Content

  • 6.4.1 US Fundamental Data
  • 6.5 TickData
  • 6.5.1 International Futures
  • -
  • 6.6 CoinAPI
  • -
  • 6.6.1 Binance Crypto Future Price Data
  • -
  • 6.6.2 Binance Crypto Price Data
  • -
  • 6.6.3 Binance US Crypto Price Data
  • -
  • 6.6.4 Bitfinex Crypto Price Data
  • -
  • 6.6.5 Bybit Crypto Future Price Data
  • -
  • 6.6.6 Bybit Crypto Price Data
  • -
  • 6.6.7 Coinbase Crypto Price Data
  • -
  • 6.6.8 Kraken Crypto Price Data
  • -
  • 6.7 Benzinga
  • -
  • 6.7.1 Benzinga News Feed
  • -
  • 6.8 Blockchain
  • -
  • 6.8.1 Bitcoin Metadata
  • -
  • 6.9 Brain
  • -
  • 6.9.1 Brain Language Metrics on Company Filings
  • -
  • 6.9.2 Brain ML Stock Ranking
  • -
  • 6.9.3 Brain Sentiment Indicator
  • -
  • 6.9.4 Brain Wikipedia Page Views
  • -
  • 6.10 CoinGecko
  • -
  • 6.10.1 Crypto Market Cap
  • -
  • 6.11 EOD Historical Data
  • -
  • 6.11.1 Economic Events
  • -
  • 6.11.2 Macroeconomics Indicators
  • -
  • 6.11.3 Upcoming Dividends
  • -
  • 6.11.4 Upcoming Earnings
  • -
  • 6.11.5 Upcoming IPOs
  • -
  • 6.11.6 Upcoming Splits
  • -
  • 6.12 Energy Information Administration
  • -
  • 6.12.1 US Energy Information Administration (EIA)
  • -
  • 6.13 ExtractAlpha
  • -
  • 6.13.1 Cross Asset Model
  • -
  • 6.13.2 Estimize
  • -
  • 6.13.3 Tactical
  • -
  • 6.13.4 True Beats
  • -
  • 6.14 FRED
  • -
  • 6.14.1 US Federal Reserve (FRED)
  • -
  • 6.15 Federal Reserve Bank of St Louis
  • -
  • 6.15.1 US Interest Rate
  • -
  • 6.16 Kavout
  • -
  • 6.16.1 Composite Factor Bundle
  • -
  • 6.17 Nasdaq
  • -
  • 6.17.1 Data Link
  • -
  • 6.18 Quiver Quantitative
  • -
  • 6.18.1 CNBC Trading
  • -
  • 6.18.2 Corporate Lobbying
  • -
  • 6.18.3 Insider Trading
  • -
  • 6.18.4 US Congress Trading
  • -
  • 6.18.5 US Government Contracts
  • -
  • 6.18.6 WallStreetBets
  • -
  • 6.19 RegAlytics
  • -
  • 6.19.1 US Regulatory Alerts - Financial Sector
  • -
  • 6.20 Securities and Exchange Commission
  • -
  • 6.20.1 US SEC Filings
  • -
  • 6.21 Smart Insider
  • -
  • 6.21.1 Corporate Buybacks
  • -
  • 6.22 Tiingo
  • -
  • 6.22.1 Tiingo News Feed
  • -
  • 6.23 Treasury Department
  • -
  • 6.23.1 US Treasury Yield Curve
  • -
  • 6.24 US Department of Agriculture
  • -
  • 6.24.1 USDA Fruit And Vegetables
  • -
  • 6.25 VIX Central
  • -
  • 6.25.1 VIX Central Contango
  • +
  • 6.6 Benzinga
  • +
  • 6.6.1 Benzinga News Feed
  • +
  • 6.7 Blockchain
  • +
  • 6.7.1 Bitcoin Metadata
  • +
  • 6.8 Brain
  • +
  • 6.8.1 Brain Language Metrics on Company Filings
  • +
  • 6.8.2 Brain ML Stock Ranking
  • +
  • 6.8.3 Brain Sentiment Indicator
  • +
  • 6.8.4 Brain Wikipedia Page Views
  • +
  • 6.9 CoinGecko
  • +
  • 6.9.1 Crypto Market Cap
  • +
  • 6.10 EOD Historical Data
  • +
  • 6.10.1 Economic Events
  • +
  • 6.10.2 Macroeconomics Indicators
  • +
  • 6.10.3 Upcoming Dividends
  • +
  • 6.10.4 Upcoming Earnings
  • +
  • 6.10.5 Upcoming IPOs
  • +
  • 6.10.6 Upcoming Splits
  • +
  • 6.11 Energy Information Administration
  • +
  • 6.11.1 US Energy Information Administration (EIA)
  • +
  • 6.12 ExtractAlpha
  • +
  • 6.12.1 Cross Asset Model
  • +
  • 6.12.2 Estimize
  • +
  • 6.12.3 Tactical
  • +
  • 6.12.4 True Beats
  • +
  • 6.13 FRED
  • +
  • 6.13.1 US Federal Reserve (FRED)
  • +
  • 6.14 Federal Reserve Bank of St Louis
  • +
  • 6.14.1 US Interest Rate
  • +
  • 6.15 Kavout
  • +
  • 6.15.1 Composite Factor Bundle
  • +
  • 6.16 Nasdaq
  • +
  • 6.16.1 Data Link
  • +
  • 6.17 Quiver Quantitative
  • +
  • 6.17.1 CNBC Trading
  • +
  • 6.17.2 Corporate Lobbying
  • +
  • 6.17.3 Insider Trading
  • +
  • 6.17.4 US Congress Trading
  • +
  • 6.17.5 US Government Contracts
  • +
  • 6.17.6 WallStreetBets
  • +
  • 6.18 RegAlytics
  • +
  • 6.18.1 US Regulatory Alerts - Financial Sector
  • +
  • 6.19 Securities and Exchange Commission
  • +
  • 6.19.1 US SEC Filings
  • +
  • 6.20 Smart Insider
  • +
  • 6.20.1 Corporate Buybacks
  • +
  • 6.21 Tiingo
  • +
  • 6.21.1 Tiingo News Feed
  • +
  • 6.22 Treasury Department
  • +
  • 6.22.1 US Treasury Yield Curve
  • +
  • 6.23 US Department of Agriculture
  • +
  • 6.23.1 USDA Fruit And Vegetables
  • +
  • 6.24 VIX Central
  • +
  • 6.24.1 VIX Central Contango
  • 7 Importing Data
  • 7.1 Key Concepts
  • 7.2 Streaming Data
  • @@ -7337,6 +7336,224 @@

    Performance Chart

    +

    Memory Metrics

    + + +

    + The static + + OS + + class in the + + QuantConnect + + namespace exposes memory and CPU metrics that you can read from your algorithm to monitor resource usage during backtests and live trading. +

    +

    + The following table lists the static members of the + + OS + + class that report memory and CPU usage: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Member + + Data Type + + Description +
    + + ApplicationMemoryUsed + + + APPLICATION_MEMORY_USED + + + + long + + + int + + + Private memory allocated to the current process, including managed and unmanaged memory, in megabytes. +
    + + TotalPhysicalMemoryUsed + + + TOTAL_PHYSICAL_MEMORY_USED + + + + long + + + int + + + Managed-runtime RAM usage (sampled with + + GC.GetTotalMemory + + + gc.get_total_memory + + ), in megabytes. LEAN's memory monitor samples this value. +
    + + CpuUsage + + + CPU_USAGE + + + + decimal + + + float + + + Total CPU usage as a percentage, sampled on a background thread. +
    + + GetServerStatistics() + + + get_server_statistics() + + + + Dictionary<string, string> + + + Dictionary[str, str] + + + Snapshot dictionary with + + CPU Usage + + , + + Used RAM + + , + + Total RAM + + , + + Hostname + + , and + + LEAN Version + + entries. +
    +

    + The following examples show how to read these metrics from an algorithm: +

    +
    +
    // Log the current memory usage of the algorithm process.
    +Log($"Total physical memory used: {OS.TotalPhysicalMemoryUsed} MB");
    +Log($"Application memory used: {OS.ApplicationMemoryUsed} MB");
    +
    +// Log the current CPU usage as a percentage.
    +Log($"CPU usage: {OS.CpuUsage}%");
    +
    +// Log a full snapshot of the server statistics.
    +foreach (var kvp in OS.GetServerStatistics()) Log($"{kvp.Key}: {kvp.Value}");
    +
    # Log the current memory usage of the algorithm process.
    +self.log(f"Total physical memory used: {OS.TOTAL_PHYSICAL_MEMORY_USED} MB")
    +self.log(f"Application memory used: {OS.APPLICATION_MEMORY_USED} MB")
    +
    +# Log the current CPU usage as a percentage.
    +self.log(f"CPU usage: {OS.CPU_USAGE}%")
    +
    +# Log a full snapshot of the server statistics.
    +for kvp in OS.get_server_statistics():
    +    self.log(f"{kvp.key}: {kvp.value}")
    +
    +

    + LEAN monitors the process's RAM usage during backtests and live trading so it can stop the algorithm gracefully when it approaches the node's memory limit, instead of letting the runtime crash. + To avoid killing an algorithm over a short-lived spike, LEAN does not act on the raw reading — it smooths the sampled value first and checks the smoothed value against the limit. +

    +

    + LEAN samples + + OS.TotalPhysicalMemoryUsed + + + OS.TOTAL_PHYSICAL_MEMORY_USED + + once per minute and feeds each sample into an exponential moving average. + The engine sets + + emaPeriod = 60 + + , which gives you roughly a 1-hour rolling window. +

    +
    +
    // Update the smoothed memory reading each minute.
    +sample = OS.TotalPhysicalMemoryUsed;
    +memoryUsed = Convert.ToInt64((emaPeriod-1)/emaPeriod * memoryUsed + (1/emaPeriod)*sample);
    +
    # Update the smoothed memory reading each minute.
    +sample = OS.TOTAL_PHYSICAL_MEMORY_USED
    +memory_used = int((ema_period - 1) / ema_period * memory_used + (1 / ema_period) * sample)
    +
    +

    + If the smoothed value exceeds the node's memory limit, LEAN terminates the algorithm with the runtime message + + Execution Security Error: Memory Usage Maxed Out - {memoryCap}MB max, with last sample of {lastSample}MB. + + , where + + {memoryCap} + + is the node's configured limit and + + {lastSample} + + is the most recent reading. +

    + + +

    JIT Compilation

    @@ -22903,6 +23120,422 @@

    # The arbitary delta criterion might be set due to hedging need or risk adjustment. selected = sorted(chain, key=lambda x: abs(x.greeks.delta - 0.4))[0]

    +

    + Example 4: Delta-Hedged Short Straddle +

    +

    + This example demonstrates a delta-hedged + + short straddle + + strategy that sells an at-the-money (ATM) straddle with 7-30 days to expiration and continuously neutralizes the portfolio delta using the underlying shares. + The + + StraddleSelector + + helper class picks the farthest expiry within the DTE range and the strike closest to the spot price. + On each + + slice + + , the combined Option delta is accumulated from the + + OptionChain + + and the net portfolio delta is computed by adding the underlying position. + The + + DeltaHedger + + helper enforces a minimum share threshold and a rehedge band to avoid over-trading, and applies a time delay between successive hedges. + A + + Scheduled Event + + closes the straddle on expiration day and assignment events are handled to keep the underlying position clean. +

    +
    +
    public class DeltaHedgedStraddleAlgorithm : QCAlgorithm
    +{
    +    private Equity _spy;
    +    private Symbol _canonicalOption;
    +    private OptionStrategy _shortStraddle;
    +    private StraddleSelector _straddleSelector;
    +    private DeltaHedger _hedger;
    +    private decimal _straddleWeight = 0.5m, _delta = 0m;
    +    private DateTime? _exitDay;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1_000_000);
    +        Settings.SeedInitialPrices = true;
    +        _spy = AddEquity("SPY", dataNormalizationMode: DataNormalizationMode.Raw);
    +        // Initialize the straddle selector with 7-30 day DTE range.
    +        _straddleSelector = new StraddleSelector(minDte: 7, maxDte: 30);
    +        // Initialize the delta hedger with 30 share minimum, 20 share rehedge band, and 4 hour delay.
    +        _hedger = new DeltaHedger(30, 20, TimeSpan.FromHours(4));
    +        _canonicalOption = QuantConnect.Symbol.CreateCanonicalOption(_spy.Symbol);
    +        // Schedule the rebalance method to run 30 minutes after market open.
    +        Schedule.On(
    +            DateRules.EveryDay(_spy.Symbol),
    +            TimeRules.AfterMarketOpen(_spy.Symbol, 30),
    +            Rebalance
    +        );
    +        // Schedule the close expiring method to run 60 minutes before market close.
    +        Schedule.On(
    +            DateRules.EveryDay(_spy.Symbol),
    +            TimeRules.BeforeMarketClose(_spy.Symbol, 60),
    +            CloseExpiring
    +        );
    +        SetWarmUp(TimeSpan.FromDays(45));
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        if (IsWarmingUp || !slice.Bars.Any()) return;
    +        if (!slice.OptionChains.TryGetValue(_canonicalOption, out var chain) || _shortStraddle == null) return;
    +
    +        // Accumulate the delta from all option legs in the straddle.
    +        foreach (var leg in _shortStraddle.OptionLegs)
    +        {
    +            if (chain.Contracts.TryGetValue(leg.Symbol, out var contract))
    +            {
    +                _delta += contract.Greeks.Delta;
    +            }
    +        }
    +        // Calculate the net portfolio delta including underlying and options.
    +        var netDelta = _hedger.ComputeNetDelta(this, _shortStraddle.OptionLegs, _spy.Holdings.Quantity, _delta);
    +        // Reset the delta accumulator for the next iteration.
    +        _delta = 0m;
    +        // Exit if it's not time to hedge or net delta is zero.
    +        if (!(_hedger.ShouldHedge(Time) && netDelta != 0)) return;
    +        // Calculate the hedge quantity needed to neutralize delta.
    +        var hedgeQty = _hedger.GetQuantity(netDelta);
    +        if (hedgeQty.HasValue)
    +        {
    +            MarketOrder(_spy.Symbol, hedgeQty.Value, tag: $"Daily delta hedge ({netDelta:F2} share delta)");
    +            // Record the hedge operation with timestamp and delta.
    +            _hedger.RecordHedge(Time, netDelta);
    +            // Update the net delta after the hedge.
    +            netDelta += hedgeQty.Value;
    +        }
    +        Plot("Portfolio Delta", "Delta", netDelta);
    +    }
    +
    +    private void Rebalance()
    +    {
    +        if (IsWarmingUp || Portfolio.Invested) return;
    +        var chain = OptionChain(_spy.Symbol);
    +        if (!chain.Any()) return;
    +        // Use the straddle selector to find the best ATM straddle.
    +        var result = _straddleSelector.Select(chain, _spy.Price, Time.Date);
    +        if (result == null) return;
    +        _delta = result.Value.Delta;
    +        _shortStraddle = OptionStrategies.ShortStraddle(_canonicalOption, result.Value.Strike, result.Value.Expiry);
    +        // Calculate the number of contracts based on portfolio value and weight.
    +        var qty = (int)(Portfolio.TotalPortfolioValue * _straddleWeight / (_spy.Price * 100m));
    +        if (qty > 0)
    +            Buy(_shortStraddle, qty, tag: $"Sell ATM straddle exp {result.Value.Expiry:d}");
    +        _hedger.Reset();
    +        _exitDay = result.Value.Expiry.Date;
    +    }
    +
    +    private void CloseExpiring()
    +    {
    +        if (_shortStraddle == null || !_exitDay.HasValue || Time.Date < _exitDay.Value) return;
    +        // Liquidate all positions before expiration.
    +        Liquidate(tag: "Expiry hedge liquidation");
    +    }
    +
    +    public override void OnOrderEvent(OrderEvent orderEvent)
    +    {
    +        // Handle option assignment events.
    +        if (orderEvent.Status == OrderStatus.Filled && orderEvent.IsAssignment)
    +        {
    +            // Liquidate all option legs of the straddle.
    +            foreach (var leg in _shortStraddle.OptionLegs)
    +            {
    +                Liquidate(leg.Symbol, tag: "Assignment liquidation");
    +            }
    +            // Determine the direction based on whether it's a call or put assignment.
    +            var direction = Securities[orderEvent.Symbol].Symbol.ID.OptionRight == OptionRight.Call ? 1 : -1;
    +            MarketOrder(_spy.Symbol, -_spy.Holdings.Quantity + orderEvent.FillQuantity * direction * 100);
    +            _shortStraddle = null;
    +        }
    +    }
    +}
    +
    +public class StraddleSelector
    +{
    +    private readonly int _minDte, _maxDte;
    +
    +    public StraddleSelector(int minDte, int maxDte)
    +    {
    +        // Store the minimum days to expiration for contract selection.
    +        _minDte = minDte;
    +        // Store the maximum days to expiration for contract selection.
    +        _maxDte = maxDte;
    +    }
    +
    +    public (decimal Delta, DateTime Expiry, decimal Strike)? Select(IEnumerable<OptionContract> chain, decimal spotPrice, DateTime currentDate)
    +    {
    +        // Filter contracts to those within the specified DTE range.
    +        var contracts = chain.Where(c =>
    +        {
    +            var dte = (c.Expiry.Date - currentDate).Days;
    +            return dte >= _minDte && dte <= _maxDte;
    +        }).ToList();
    +        if (!contracts.Any()) return null;
    +        // Select the farthest expiration date from the filtered contracts.
    +        var expiry = contracts.Max(c => c.Expiry);
    +        // Filter to only contracts with the selected expiration.
    +        contracts = contracts.Where(c => c.Expiry == expiry).ToList();
    +        // Find the strike price closest to the current spot price.
    +        var strike = contracts.OrderBy(c => Math.Abs(c.Strike - spotPrice)).First().Strike;
    +        // Filter to only contracts with the selected strike.
    +        contracts = contracts.Where(c => c.Strike == strike).ToList();
    +        // Ensure we have both call and put for a straddle.
    +        if (contracts.Count < 2) return null;
    +        // Return the combined delta, expiry, and strike for the straddle.
    +        return (contracts.Sum(c => c.Greeks.Delta), expiry, strike);
    +    }
    +}
    +
    +public class DeltaHedger
    +{
    +    private readonly int _minShares, _rehedgeBand;
    +    private readonly TimeSpan _hedgeDelay;
    +    private DateTime _nextHedgeTime;
    +    private decimal? _lastHedgedDelta;
    +
    +    public DeltaHedger(int minShares, int rehedgeBand, TimeSpan hedgeDelay)
    +    {
    +        // Store the minimum number of shares required to execute a hedge.
    +        _minShares = minShares;
    +        // Store the rehedge band threshold to prevent excessive hedging.
    +        _rehedgeBand = rehedgeBand;
    +        // Store the time delay between hedging operations.
    +        _hedgeDelay = hedgeDelay;
    +        Reset();
    +    }
    +
    +    public void Reset()
    +    {
    +        _nextHedgeTime = DateTime.MinValue;
    +        _lastHedgedDelta = null;
    +    }
    +
    +    public bool ShouldHedge(DateTime currentTime)
    +    {
    +        // Check if enough time has passed since the last hedge.
    +        return currentTime >= _nextHedgeTime;
    +    }
    +
    +    public decimal ComputeNetDelta(QCAlgorithm algorithm, IEnumerable<Leg> legs, decimal underlyingQuantity, decimal contractDelta)
    +    {
    +        // Calculate the net portfolio delta by combining underlying and option positions.
    +        return underlyingQuantity + legs.Sum(leg =>
    +            algorithm.Securities[leg.Symbol].Holdings.Quantity * contractDelta * 100);
    +    }
    +
    +    public int? GetQuantity(decimal netDelta)
    +    {
    +        if (_lastHedgedDelta.HasValue
    +            && Math.Abs(netDelta - _lastHedgedDelta.Value) < _rehedgeBand
    +            && Math.Abs(netDelta) < _minShares + _rehedgeBand)
    +        {
    +            return null;
    +        }
    +        // Calculate the required hedge quantity to neutralize the net delta.
    +        var hedgeQty = (int)Math.Round(-netDelta);
    +        if (Math.Abs(hedgeQty) < _minShares) return null;
    +        // Return the calculated hedge quantity.
    +        return hedgeQty;
    +    }
    +
    +    public void RecordHedge(DateTime currentTime, decimal netDelta)
    +    {
    +        // Record the delta value after this hedge operation.
    +        _lastHedgedDelta = netDelta;
    +        // Set the next allowed hedge time based on the configured delay.
    +        _nextHedgeTime = currentTime + _hedgeDelay;
    +    }
    +}
    +
    class DeltaHedgedStraddleAlgo(QCAlgorithm):
    +
    +    def initialize(self):
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1_000_000)
    +        self.settings.seed_initial_prices = True
    +        self._spy = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.RAW)
    +        # Initialize the straddle selector with 7-30 day DTE range.
    +        self._straddle_selector = StraddleSelector(min_dte=7, max_dte=30)
    +        # Initialize the delta hedger with 30 share minimum, 20 share rehedge band, and 4 hour delay.
    +        self._hedger = DeltaHedger(30, 20, timedelta(hours=4))
    +        self._canonical_option = Symbol.create_canonical_option(self._spy)
    +        # Set the straddle position size to 50% of portfolio value.
    +        self._straddle_weight = 0.5
    +        self._short_straddle = None
    +        self._exit_day = None
    +        # Schedule the rebalance method to run 30 minutes after market open.
    +        self.schedule.on(
    +            self.date_rules.every_day(self._spy),
    +            self.time_rules.after_market_open(self._spy, 30),
    +            self._rebalance
    +        )
    +        # Schedule the close expiring method to run 60 minutes before market close.
    +        self.schedule.on(
    +            self.date_rules.every_day(self._spy),
    +            self.time_rules.before_market_close(self._spy, 60),
    +            self._close_expiring
    +        )
    +        self.set_warm_up(timedelta(45))
    +
    +    def on_data(self, data):
    +        if self.is_warming_up or not data.bars:
    +            return
    +        chain = data.option_chains.get(self._canonical_option)
    +        if not chain or not self._short_straddle:
    +            return
    +        # Accumulate the delta from all option legs in the straddle.
    +        for leg in self._short_straddle.option_legs:
    +            contract = chain.contracts.get(leg.symbol)
    +            if contract:
    +                self._delta += contract.greeks.delta
    +        # Calculate the net portfolio delta including underlying and options.
    +        net_delta = self._hedger.compute_net_delta(self, self._short_straddle.option_legs, self._spy.holdings.quantity, self._delta)
    +        # Reset the delta accumulator for the next iteration.
    +        self._delta = 0
    +        # Exit if it's not time to hedge or net delta is zero.
    +        if not (self._hedger.should_hedge(self.time) and net_delta):
    +            return
    +        # Calculate the hedge quantity needed to neutralize delta.
    +        hedge_qty = self._hedger.get_quantity(net_delta)
    +        if hedge_qty:
    +            self.market_order(self._spy, hedge_qty, tag=f"Daily delta hedge ({net_delta:.2f} share delta)")
    +            # Record the hedge operation with timestamp and delta.
    +            self._hedger.record_hedge(self.time, net_delta)
    +            # Update the net delta after the hedge.
    +            net_delta += hedge_qty
    +        self.plot("Portfolio Delta", "Delta", net_delta)
    +
    +    def _rebalance(self):
    +        if self.is_warming_up or self.portfolio.invested:
    +            return
    +        chain = self.option_chain(self._spy)
    +        if not chain:
    +            return
    +        # Use the straddle selector to find the best ATM straddle.
    +        result = self._straddle_selector.select(chain, self._spy.price, self.time.date())
    +        if not result:
    +            return
    +        self._delta, expiry, strike = result
    +        self._short_straddle = OptionStrategies.short_straddle(self._canonical_option, strike, expiry)
    +        # Calculate the number of contracts based on portfolio value and weight.
    +        qty = int(self.portfolio.total_portfolio_value * self._straddle_weight / (self._spy.price * 100.0))
    +        if qty:
    +            self.buy(self._short_straddle, qty, tag=f"Sell ATM straddle exp {expiry.date()}")
    +        self._hedger.reset()
    +        self._exit_day = expiry.date()
    +
    +    def _close_expiring(self):
    +        if not self._short_straddle or not self._exit_day or self.time.date() < self._exit_day:
    +            return
    +        # Liquidate all positions before expiration.
    +        self.liquidate(tag="Expiry hedge liquidation")
    +
    +    def on_order_event(self, order_event):
    +        # Handle option assignment events.
    +        if order_event.status == OrderStatus.FILLED and order_event.is_assignment:
    +            # Liquidate all option legs of the straddle.
    +            for leg in self._short_straddle.option_legs:
    +                self.liquidate(leg.symbol, tag="Assignment liquidation")
    +            # Determine the direction based on whether it's a call or put assignment.
    +            direction = 1 if self.securities[order_event.symbol].right == OptionRight.CALL else -1
    +            self.market_order(self._spy, -self._spy.holdings.quantity + order_event.quantity * direction * 100)
    +            self._short_straddle = None
    +
    +
    +class StraddleSelector:
    +
    +    def __init__(self, min_dte, max_dte):
    +        # Store the minimum days to expiration for contract selection.
    +        self._min_dte = min_dte
    +        # Store the maximum days to expiration for contract selection.
    +        self._max_dte = max_dte
    +
    +    def select(self, chain, spot_price, current_date):
    +        # Filter contracts to those within the specified DTE range.
    +        contracts = [
    +            contract for contract in chain
    +            if self._min_dte <= (contract.expiry.date() - current_date).days <= self._max_dte
    +        ]
    +        if not contracts:
    +            return
    +        # Select the farthest expiration date from the filtered contracts.
    +        expiry = max(contract.expiry for contract in contracts)
    +        # Filter to only contracts with the selected expiration.
    +        contracts = [contract for contract in contracts if contract.expiry == expiry]
    +        # Find the strike price closest to the current spot price.
    +        strike = min(contracts, key=lambda c: abs(c.strike - spot_price)).strike
    +        # Filter to only contracts with the selected strike.
    +        contracts = [contract for contract in contracts if contract.strike == strike]
    +        # Ensure we have both call and put for a straddle.
    +        if len(contracts) < 2:
    +            return
    +        # Return the combined delta, expiry, and strike for the straddle.
    +        return sum(contract.greeks.delta for contract in contracts), expiry, strike
    +
    +
    +class DeltaHedger:
    +
    +    def __init__(self, min_shares, rehedge_band, hedge_delay):
    +        # Store the minimum number of shares required to execute a hedge.
    +        self._min_shares = min_shares
    +        # Store the rehedge band threshold to prevent excessive hedging.
    +        self._rehedge_band = rehedge_band
    +        # Store the time delay between hedging operations.
    +        self._hedge_delay = hedge_delay
    +        self.reset()
    +
    +    def reset(self):
    +        self._next_hedge_time = datetime.min
    +        self._last_hedged_delta = None
    +
    +    def should_hedge(self, current_time):
    +        # Check if enough time has passed since the last hedge.
    +        return current_time >= self._next_hedge_time
    +
    +    def compute_net_delta(self, algorithm, legs, underlying_quantity, contract_delta):
    +        # Calculate the net portfolio delta by combining underlying and option positions.
    +        return underlying_quantity + sum(
    +            algorithm.securities[leg.symbol].holdings.quantity * contract_delta * 100
    +            for leg in legs
    +        )
    +
    +    def get_quantity(self, net_delta):
    +        if (
    +            self._last_hedged_delta is not None
    +            and abs(net_delta - self._last_hedged_delta) < self._rehedge_band
    +            and abs(net_delta) < self._min_shares + self._rehedge_band
    +        ):
    +            return
    +        # Calculate the required hedge quantity to neutralize the net delta.
    +        hedge_qty = int(round(-net_delta))
    +        if abs(hedge_qty) < self._min_shares:
    +            return
    +        # Return the calculated hedge quantity.
    +        return hedge_qty
    +
    +    def record_hedge(self, current_time, net_delta):
    +        # Record the delta value after this hedge operation.
    +        self._last_hedged_delta = net_delta
    +        # Set the next allowed hedge time based on the configured delay.
    +        self._next_hedge_time = current_time + self._hedge_delay
    +
    @@ -27905,7 +28538,7 @@

    Introduction

    on_data method. For more information about the specific datasets we use for backtests, see the - + CoinAPI datasets . To trade Crypto live, you can use the @@ -27997,7 +28630,7 @@

    Create Subscriptions

    To view the supported assets, see the - + CoinAPI datasets . @@ -29689,7 +30322,7 @@

    Create Subscriptions

    To view the supported assets in the Crypto Futures dataset, see - + Supported Assets . @@ -31331,7 +31964,7 @@

    Create Subscriptions

    To view the supported Forex pairs, see - + Supported Assets . @@ -113685,7 +114318,7 @@

    Create Subscriptions

    To view the supported assets in the US Cash Indices dataset, see the - + Supported Indices . @@ -129078,7 +129711,7 @@

    OANDA Subscriptions

    To view the supported CFD contracts, see - + Supported Assets . For more information about the specific dataset we use for backtests, see the @@ -150074,102 +150707,194 @@

    Fundamental - object has adjusted price and volume information, so you can do any price-related analysis. + object has daily price and volume information, so you can do any price-related analysis. The following algorithm defines a separate class to contain the indicator of each asset.

    -
    using System.Collections.Concurrent;
    -	
    -public class UpTrendLiquidUniverseAlgorithm : QCAlgorithm
    +   
    public class UpTrendLiquidUniverseAlgorithm  : QCAlgorithm
     {    
    -    // Create a concurrent dictionary to store the EMA data for universe selection.
    -    private ConcurrentDictionary<Symbol, SelectionData> _selectionDataBySymbol = new();
    +    private Dictionary<Symbol, SelectionData> _selectionDataBySymbol = new();
    +    private Universe _universe;
     
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -
    +        Settings.SeedInitialPrices = true;
             // Add the custom universe.
    -        AddUniverse(SelectAssets);
    +        UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
    +        _universe = AddUniverse(SelectAssets);
    +        // Add a warm-up period to warm up the indicators.
    +        SetWarmUp(TimeSpan.FromDays(300));
         }
    -    
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamental)
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamentals)
         {
    -        return (from f in fundamental
    -            // Create/Update the EMA indicators of each stock.
    -            let avg = _selectionDataBySymbol.GetOrAdd(f.Symbol, sym => new SelectionData(200))
    -            where avg.Update(f.EndTime, f.AdjustedPrice)
    -            // Select the Equities that are above their EMA and have a daily volume of $1B.
    -            // These assets are in an uptrend and are very liquid.
    -            where avg.Ema.IsReady && f.Price > avg.Ema.Current.Value && f.DollarVolume > 1000000000
    -            // Select the 10 most liquid Equities to avoid extra slippage.   
    -            orderby f.DollarVolume descending
    -            select f.Symbol).Take(10);
    +        // Update the indicator of all stocks in the universe dataset and
    +        // get the subset of stocks that have their indicator ready.
    +        var readyStocks = new List<Fundamental>();
    +        foreach (var f in fundamentals)
    +        {
    +            if (!_selectionDataBySymbol.TryGetValue(f.Symbol, out var sd))
    +            {
    +                sd = new SelectionData(this, f, 200);
    +                _selectionDataBySymbol[f.Symbol] = sd;
    +            }
    +            if (sd.Update(f))
    +            {
    +                readyStocks.Add(f);
    +            }
    +        }
    +        // As assests leave the Fundamental dataset, delete their SelectionData object.
    +        var activeStocks = fundamentals.Select(f => f.Symbol).ToHashSet();
    +        foreach (var symbol in _selectionDataBySymbol.Keys.Where(s => !activeStocks.Contains(s)).ToList())
    +        {
    +            _selectionDataBySymbol.Remove(symbol);
    +        }
    +        // During warm-up, keep the universe empty.
    +        if (IsWarmingUp)
    +        {
    +            return Enumerable.Empty<Symbol>();
    +        }
    +        // Select the Equities that are above their EMA and have a daily volume of $1B.
    +        // These assets are in an uptrend and are very liquid.
    +        return readyStocks
    +            .Select(f => _selectionDataBySymbol[f.Symbol])
    +            .Where(x => x.IsAboveEma && x.Volume > 1000000000)
    +            // Select the 10 most liquid Equities to avoid extra slippage.    
    +            .OrderBy(x => x.Volume)
    +            .TakeLast(10)
    +            .Select(x => x.Symbol);
         }
     }
     
     // Create a separate class to contain the EMA information of each asset.
    -class SelectionData
    +public class SelectionData
     {
    -    public readonly ExponentialMovingAverage Ema;
    +    private QCAlgorithm _algorithm;
    +    private decimal _priceScaleFactor;
    +    private ExponentialMovingAverage _ema { get; }
    +    public Symbol Symbol;
    +    public bool IsAboveEma = false;
    +    public decimal Volume = 0;
     
    -    // Create an EMA indicator for trend estimation and filtering.
    -    public SelectionData(int period)
    +    public SelectionData(QCAlgorithm algorithm, Fundamental f, int period)
         {
    -        Ema = new ExponentialMovingAverage(period);
    +        _algorithm = algorithm;
    +        _priceScaleFactor = f.PriceScaleFactor;
    +        // Create an EMA indicator for trend estimation and filtering.
    +        Symbol = f.Symbol;
    +        _ema = new ExponentialMovingAverage(period);
         }
     
         // Update your variables and indicators with the latest data.
    -    // You may also want to use the History API here to warm-up the indicator.
    -    public bool Update(DateTime time, decimal value)
    +    public bool Update(Fundamental f)
         {
    -        return Ema.Update(time, value);
    +        // If there hasn't been a split or dividend since the last trading
    +        // day, just update the indicator like normal.
    +        if (f.PriceScaleFactor == _priceScaleFactor)
    +        {
    +            return _update(f.EndTime, f.Volume, f.Price);
    +        }
    +        // Otherwise, reset the indicator and warm it up with the new
    +        // adjusted history.
    +        _priceScaleFactor = f.PriceScaleFactor;
    +        _ema.Reset();
    +        var history = _algorithm.History<TradeBar>(
    +            Symbol,
    +            _ema.WarmUpPeriod,
    +            Resolution.Daily,
    +            dataNormalizationMode: DataNormalizationMode.ScaledRaw
    +        );
    +        foreach (var bar in history)
    +        {
    +            _update(bar.EndTime, bar.Volume, bar.Close);
    +        }
    +        return _ema.IsReady;
    +    }
    +
    +    private bool _update(DateTime endTime, decimal volume, decimal price)
    +    {
    +        Volume = volume * price;
    +        if (_ema.Update(endTime, price))
    +        {
    +            IsAboveEma = price > _ema.Current.Value;
    +        }
    +        return _ema.IsReady;
         }
     }
    class UpTrendLiquidUniverseAlgorithm(QCAlgorithm):
     	
    -    # Create a dictionary to store the EMA data for universe selection.
         _selection_data_by_symbol = {}
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        
    +        self.settings.seed_initial_prices = True
             # Add the custom universe.
    -        self.add_universe(self._select_assets)
    +        self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
    +        self._universe = self.add_universe(self._select_assets)
    +        # Add a warm-up period to warm up the indicators.
    +        self.set_warm_up(timedelta(300))
         
    -    def _select_assets(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -        for f in fundamental:
    -            # Create/Update the EMA indicators of each stock.
    -            if f.symbol not in self._selection_data_by_symbol:
    -                self._selection_data_by_symbol[f.symbol] = SelectionData(f.symbol, 200)
    -            self._selection_data_by_symbol[f.symbol].update(f.end_time, f.adjusted_price, f.dollar_volume)
    -        
    +    def _select_assets(self, fundamentals: List[Fundamental]) -> List[Symbol]:
    +        # Update the indicator of all stocks in the universe dataset and
    +        # get the subset of stocks that have their indicator ready.
    +        ready_stocks = [
    +            f for f in fundamentals
    +            if self._selection_data_by_symbol.setdefault(f.symbol, SelectionData(self, f, 200)).update(f)
    +        ]
    +        # As assests leave the Fundamental dataset, delete their SelectionData object.
    +        for symbol in self._selection_data_by_symbol.keys() - {f.symbol for f in fundamentals}:
    +            del self._selection_data_by_symbol[symbol]
    +        # During warm-up, keep the universe empty.
    +        if self.is_warming_up:
    +            return []
             # Select the Equities that are above their EMA and have a daily volume of $1B.
             # These assets are in an uptrend and are very liquid.
    -        selected = [x for x in self._selection_data_by_symbol.values() if x.is_above_ema and x.volume > 1_000_000_000]
    -            
    +        selected = [self._selection_data_by_symbol[f.symbol] for f in ready_stocks]
    +        selected = [x for x in selected if x.is_above_ema and x.volume > 1_000_000_000]          
             # Select the 10 most liquid Equities to avoid extra slippage.    
    -        return [ x.symbol for x in sorted(selected, key=lambda x: x.volume)[-10:] ]
    +        return [x.symbol for x in sorted(selected, key=lambda x: x.volume)[-10:]]
     
     
     # Create a separate class to contain the EMA information of each asset.
    -class SelectionData(object):
    +class SelectionData:
     
    -    def __init__(self, symbol, period):
    +    def __init__(self, algorithm, f, period):
    +        self._algorithm = algorithm
    +        self._price_scale_factor = f.price_scale_factor
             # Create an EMA indicator for trend estimation and filtering.
    -        self.symbol = symbol
    +        self.symbol = f.symbol
             self._ema = ExponentialMovingAverage(period)
             self.is_above_ema = False
             self.volume = 0
     
         # Update your variables and indicators with the latest data.
    -    # You may also want to use the History API here to warm-up the indicator.
    -    def update(self, time, price, volume):
    -        self.volume = volume
    -        if self._ema.update(time, price):
    -            self.is_above_ema = price > self._ema.current.value
    + def update(self, f): + # If there hasn't been a split or dividend since the last trading + # day, just update the indicator like normal. + if f.price_scale_factor == self._price_scale_factor: + return self._update(f.end_time, f.volume, f.price) + # Otherwise, reset the indicator and warm it up with the new + # adjusted history. + self._price_scale_factor = f.price_scale_factor + self._ema.reset() + history = self._algorithm.history[TradeBar]( + self.symbol, + self._ema.warm_up_period, + Resolution.DAILY, + data_normalization_mode=DataNormalizationMode.SCALED_RAW + ) + for bar in history: + self._update(bar.end_time, bar.volume, bar.close) + return self._ema.is_ready + + def _update(self, end_time, volume, price): + self.volume = volume * price + if self._ema.update(end_time, price): + self.is_above_ema = price > self._ema.current.value + return self._ema.is_ready

    In this example, the @@ -150244,99 +150969,184 @@

    You can use this ratio to select assets that are above their 10-day SMA and sort the results by the Equities that have had the biggest jump since yesterday.

    -
    using System.Collections.Concurrent;
    -
    -public class HighRelativeVolumeUniverseAlgorithm : QCAlgorithm
    +   
    public class HighRelativeVolumeUniverseAlgorithm  : QCAlgorithm
     {    
    -    // Create a dictionary to store the EMA data for universe selection.
    -    private ConcurrentDictionary<Symbol, SelectionData> _selectionDataBySymbol = new();
    +    private Dictionary<Symbol, SelectionData> _selectionDataBySymbol = new();
    +    private Universe _universe;
     
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -
    -        // Add a universe with custom selection rules for filtering.
    -        AddUniverse(SelectAssets);
    +        Settings.SeedInitialPrices = true;
    +        // Add the custom universe.
    +        UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
    +        _universe = AddUniverse(SelectAssets);
    +        // Add a warm-up period to warm up the indicators.
    +        SetWarmUp(TimeSpan.FromDays(30));
         }
    -    
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamental)
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamentals)
         {
    -        return (from f in fundamental
    -            // Create/Update the volume SMA indicator of each stock.
    -            let avg = _selectionDataBySymbol.GetOrAdd(f.Symbol, sym => new SelectionData(f.Symbol, 10))
    -            where avg.Update(f.EndTime, f.Volume)
    -            // Select the Equities with higher trading volume than their SMA, indicating higher capital flow.
    -            where avg.VolumeRatio > 1
    +        // Update the indicator of all stocks in the universe dataset and
    +        // get the subset of stocks that have their indicator ready.
    +        var readyStocks = new List<Fundamental>();
    +        foreach (var f in fundamentals)
    +        {
    +            if (!_selectionDataBySymbol.TryGetValue(f.Symbol, out var sd))
    +            {
    +                sd = new SelectionData(this, f, 10);
    +                _selectionDataBySymbol[f.Symbol] = sd;
    +            }
    +            if (sd.Update(f))
    +            {
    +                readyStocks.Add(f);
    +            }
    +        }
    +        // As assests leave the Fundamental dataset, delete their SelectionData object.
    +        var activeStocks = fundamentals.Select(f => f.Symbol).ToHashSet();
    +        foreach (var symbol in _selectionDataBySymbol.Keys.Where(s => !activeStocks.Contains(s)).ToList())
    +        {
    +            _selectionDataBySymbol.Remove(symbol);
    +        }
    +        // During warm-up, keep the universe empty.
    +        if (IsWarmingUp)
    +        {
    +            return Enumerable.Empty<Symbol>();
    +        }
    +        // Select the Equities with higher trading volume than their SMA, indicating higher capital flow.
    +        return readyStocks
    +            .Select(f => _selectionDataBySymbol[f.Symbol])
    +            .Where(x => x.VolumeRatio > 1)
                 // Select the 10 Equities with the highest relative volume, since they have the highest capactity
    -            // for scalp-trading or intra-day movement.
    -            orderby avg.VolumeRatio descending
    -            select f.Symbol).Take(10);
    +            // for scalp-trading or intra-day movement. 
    +            .OrderBy(x => x.VolumeRatio)
    +            .TakeLast(10)
    +            .Select(x => x.Symbol);
         }
     }
     
    -// Define a separate class to contain and calculate the SMA of each Equity.
    -class SelectionData
    +// Create a separate class to contain the SMA information of each asset.
    +public class SelectionData
     {
    -    public readonly Symbol Symbol;
    -    public readonly SimpleMovingAverage VolumeSma;
    -    public decimal VolumeRatio;
    +    private QCAlgorithm _algorithm;
    +    private decimal _priceScaleFactor;
    +    private SimpleMovingAverage _sma { get; }
    +    public Symbol Symbol;
    +    public decimal VolumeRatio = 0;
     
    -    public SelectionData(Symbol symbol, int period)
    +    public SelectionData(QCAlgorithm algorithm, Fundamental f, int period)
         {
    -        // Create an SMA of volume to track the popularity of the stock.
    -        Symbol = symbol;
    -        VolumeSma = new SimpleMovingAverage(period);
    +        _algorithm = algorithm;
    +        _priceScaleFactor = f.PriceScaleFactor;
    +        // Create an EMA indicator for trend estimation and filtering.
    +        Symbol = f.Symbol;
    +        _sma = new SimpleMovingAverage(period);
         }
    -    
    -    public bool Update(DateTime time, decimal value)
    +
    +    // Update your variables and indicators with the latest data.
    +    public bool Update(Fundamental f)
    +    {
    +        // If there hasn't been a split or dividend since the last trading
    +        // day, just update the indicator like normal.
    +        if (f.PriceScaleFactor == _priceScaleFactor)
    +        {
    +            return _update(f.EndTime, f.Volume);
    +        }
    +        // Otherwise, reset the indicator and warm it up with the new
    +        // adjusted history.
    +        _priceScaleFactor = f.PriceScaleFactor;
    +        _sma.Reset();
    +        var history = _algorithm.History<TradeBar>(
    +            Symbol,
    +            _sma.WarmUpPeriod,
    +            Resolution.Daily,
    +            dataNormalizationMode: DataNormalizationMode.ScaledRaw
    +        );
    +        foreach (var bar in history)
    +        {
    +            _update(bar.EndTime, bar.Volume);
    +        }
    +        return _sma.IsReady;
    +    }
    +
    +    private bool _update(DateTime endTime, decimal volume)
         {
             // Update the SMA with today's data and calculate the relative volume position for filtering.
    -        var ready = VolumeSma.Update(time, value);
    -        VolumeRatio = VolumeSma.Current.Value != 0m ? value / VolumeSma.Current.Value : -1m;
    +        var ready = _sma.Update(endTime, volume);
    +        VolumeRatio = _sma.Current.Value != 0m ? volume / _sma.Current.Value : -1m;
             return ready;
         }
     }
    class HighRelativeVolumeUniverseAlgorithm(QCAlgorithm):
    -    
    -    # Create a dictionary to store the EMA data for universe selection.
    -    _selection_data_by_symbol = {}
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        
    -        # Add a universe with custom selection rules for filtering.
    -        self.add_universe(self._select_assets)
    +        self.settings.seed_initial_prices = True
    +        # Add the custom universe.
    +        self._selection_data_by_symbol = {}
    +        self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
    +        self._universe = self.add_universe(self._select_assets)
    +        # Add a warm-up period to warm up the indicators.
    +        self.set_warm_up(timedelta(30))
         
    -    def _select_assets(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -        # Create/Update the volume SMA indicator of each stock.
    -        for f in fundamental:
    -            if f.symbol not in self._selection_data_by_symbol:
    -                self._selection_data_by_symbol[f.symbol] = SelectionData(f.symbol, 10)
    -            self._selection_data_by_symbol[f.symbol].update(f.end_time, f.adjusted_price, f.dollar_volume)
    -
    +    def _select_assets(self, fundamentals: List[Fundamental]) -> List[Symbol]:
    +        # Update the indicator of all stocks in the universe dataset and
    +        # get the subset of stocks that have their indicator ready.
    +        ready_stocks = [
    +            f for f in fundamentals
    +            if self._selection_data_by_symbol.setdefault(f.symbol, SelectionData(self, f, 10)).update(f)
    +        ]
    +        # As assests leave the Fundamental dataset, delete their SelectionData object.
    +        for symbol in self._selection_data_by_symbol.keys() - {f.symbol for f in fundamentals}:
    +            del self._selection_data_by_symbol[symbol]
    +        # During warm-up, keep the universe empty.
    +        if self.is_warming_up:
    +            return []
             # Select the Equities with higher trading volume than their SMA, indicating higher capital flow.
    -        selected = [sd for sd in self._selection_data_by_symbol.values() if sd.volume_ratio > 1]
    -            
    +        selected = [self._selection_data_by_symbol[f.symbol] for f in ready_stocks]
    +        selected = [sd for sd in selected if sd.volume_ratio > 1]        
             # Select the 10 Equities with the highest relative volume, since they have the highest capactity
             # for scalp-trading or intra-day movement.
    -        return [ x.symbol for x in sorted(selected, key=lambda x: x.volume_ratio)[-10:] ]
    +        return [x.symbol for x in sorted(selected, key=lambda x: x.volume_ratio)[-10:]]
     
     
    -# Define a separate class to contain and calculate the SMA of each Equity.
    -class SelectionData(object):
    -    
    -    def __init__(self, symbol, period):
    -        self.symbol = symbol
    -        self.volume_ratio = 0
    +# Create a separate class to contain the SMA information of each asset.
    +class SelectionData:
    +
    +    def __init__(self, algorithm, f, period):
    +        self._algorithm = algorithm
    +        self._price_scale_factor = f.price_scale_factor
             # Create an SMA of volume to track the popularity of the stock.
    +        self.symbol = f.symbol
             self._sma = SimpleMovingAverage(period)
     
    -    def update(self, time, price, volume):
    +    # Update your variables and indicators with the latest data.
    +    def update(self, f):
    +        # If there hasn't been a split or dividend since the last trading
    +        # day, just update the indicator like normal.
    +        if f.price_scale_factor == self._price_scale_factor:
    +            return self._update(f.end_time, f.volume)
    +        # Otherwise, reset the indicator and warm it up with the new 
    +        # adjusted history.
    +        self._price_scale_factor = f.price_scale_factor
    +        self._sma.reset()
    +        history = self._algorithm.history[TradeBar](
    +            self.symbol, 
    +            self._sma.warm_up_period, 
    +            Resolution.DAILY, 
    +            data_normalization_mode=DataNormalizationMode.SCALED_RAW
    +        )
    +        for bar in history:
    +            self._update(bar.end_time, bar.volume)
    +        return self._sma.is_ready
    +    
    +    def _update(self, end_time, volume):
             # Update the SMA with today's data and calculate the relative volume position for filtering.
    -        if self._sma.update(time, volume):
    -            self.volume_ratio = volume / self._sma.current.value if self._sma.current.value != 0 else -1
    + if self._sma.update(end_time, volume): + self.volume_ratio = volume / self._sma.current.value if self._sma.current.value != 0 else -1 + return self._sma.is_ready

    Example 4: 10 "Fastest Moving" Stocks With a 50-Day EMA > 200 Day EMA @@ -150370,6 +151180,190 @@

    Research post.

    +

    + Example 6: Stocks Far Above Their SMA +

    +

    + The following example shows how to select a universe of US Equities based on their price and SMA indicator. + The + + SelectionData + + class keeps track of the SMA indicator for each stock in the universe dataset. + When a split or dividend occurs for a stock, the data in its indicator becomes invalid because it doesn't account for the price adjustments that the split or dividend causes. + The + + SelectionData + + class resets and warms up the indicator with the + + ScaledRaw + + + SCALED_RAW + + + data normalization mode + + , which gives you accurate indicator values to use in your universe selection after each corporate action. +

    +
    +
    class EquityIndicatorUniverseSelectionAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.settings.seed_initial_prices = True
    +        # Add a universe of US Equities based on an indicator.
    +        self._selection_data_by_symbol = {}
    +        self._universe = self.add_universe(self._select_assets)
    +        # Add a warm-up period to warm up the indicators in the universe selection.
    +        self.set_warm_up(timedelta(60))
    +
    +    def _select_assets(self, fundamentals):
    +        # Update the indicator of all stocks in the universe dataset and
    +        # get the subset of stocks that have their indicator ready.
    +        ready_stocks = [
    +            f for f in fundamentals
    +            if self._selection_data_by_symbol.setdefault(f.symbol, SelectionData(self, f)).update(f)
    +        ]
    +        # As assests leave the Fundamental dataset, delete their SelectionData object.
    +        for symbol in self._selection_data_by_symbol.keys() - {f.symbol for f in fundamentals}:
    +            del self._selection_data_by_symbol[symbol]
    +        # During warm-up, keep the universe empty.
    +        if self.is_warming_up:
    +            return []
    +        # Select a subset of the stocks based on the indicator.
    +        # Example: 10 stocks furthest above their SMA.
    +        factor_by_symbol = {
    +            f.symbol: f.price / self._selection_data_by_symbol[f.symbol].indicator.current.value 
    +            for f in ready_stocks
    +        }
    +        return sorted(
    +            {k: v for k, v in factor_by_symbol.items() if v > 0}, 
    +            key=lambda symbol: factor_by_symbol[symbol]
    +        )[-100:]
    +
    +
    +class SelectionData:
    +
    +    def __init__(self, algorithm, f):
    +        self._algorithm = algorithm
    +        self._price_scale_factor = f.price_scale_factor
    +        self.indicator = SimpleMovingAverage(21)
    +
    +    def update(self, f):
    +        # If there hasn't been a split or dividend since the last trading
    +        # day, just update the indicator like normal.
    +        if f.price_scale_factor == self._price_scale_factor:
    +            return self.indicator.update(f.end_time, f.price)
    +        # Otherwise, reset the indicator and warm it up with the new 
    +        # adjusted history.
    +        self._price_scale_factor = f.price_scale_factor
    +        self.indicator.reset()
    +        history = self._algorithm.history[TradeBar](
    +            f.symbol, 
    +            self.indicator.warm_up_period, 
    +            Resolution.DAILY, 
    +            data_normalization_mode=DataNormalizationMode.SCALED_RAW
    +        )
    +        for bar in history:
    +            self.indicator.update(bar)
    +        return self.indicator.is_ready
    +
    public class EquityIndicatorUniverseSelectionAlgorithm : QCAlgorithm
    +{
    +    private Dictionary<Symbol, SelectionData> _selectionDataBySymbol = new();
    +    private Universe _universe;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        Settings.SeedInitialPrices = true;
    +        // Add a universe of US Equities based on an indicator.
    +        _universe = AddUniverse(SelectAssets);
    +        // Add a warm-up period to warm up the indicators in the universe selection.
    +        SetWarmUp(TimeSpan.FromDays(60));
    +    }
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamentals)
    +    {
    +        // Update the indicator of all stocks in the universe dataset and
    +        // get the subset of stocks that have their indicator ready.
    +        var readyStocks = new List<Fundamental>();
    +        foreach (var f in fundamentals)
    +        {
    +            if (!_selectionDataBySymbol.TryGetValue(f.Symbol, out var sd))
    +            {
    +                sd = new SelectionData(this, f);
    +                _selectionDataBySymbol[f.Symbol] = sd;
    +            }
    +            if (sd.Update(f))
    +            {
    +                readyStocks.Add(f);
    +            }
    +        }
    +        // As assests leave the Fundamental dataset, delete their SelectionData object.
    +        var activeStocks = fundamentals.Select(f => f.Symbol).ToHashSet();
    +        foreach (var symbol in _selectionDataBySymbol.Keys.Where(s => !activeStocks.Contains(s)).ToList())
    +        {
    +            _selectionDataBySymbol.Remove(symbol);
    +        }
    +        // During warm-up, keep the universe empty.
    +        if (IsWarmingUp)
    +        {
    +            return Enumerable.Empty<Symbol>();
    +        }
    +        // Select a subset of the stocks based on the indicator.
    +        // Example: 10 stocks furthest above their SMA.
    +        return readyStocks
    +            .Select(f => (f.Symbol, Factor: f.Price / _selectionDataBySymbol[f.Symbol].Indicator.Current.Value))
    +            .Where(t => t.Factor > 0)
    +            .OrderBy(t => t.Factor)
    +            .TakeLast(100)
    +            .Select(t => t.Symbol);
    +    }
    +}
    +
    +public class SelectionData
    +{
    +    private QCAlgorithm _algorithm;
    +    private decimal _priceScaleFactor;
    +    public SimpleMovingAverage Indicator { get; }
    +
    +    public SelectionData(QCAlgorithm algorithm, Fundamental f)
    +    {
    +        _algorithm = algorithm;
    +        _priceScaleFactor = f.PriceScaleFactor;
    +        Indicator = new SimpleMovingAverage(21);
    +    }
    +
    +    public bool Update(Fundamental f)
    +    {
    +        // If there hasn't been a split or dividend since the last trading
    +        // day, just update the indicator like normal.
    +        if (f.PriceScaleFactor == _priceScaleFactor)
    +        {
    +            return Indicator.Update(f.EndTime, f.Price);
    +        }
    +        // Otherwise, reset the indicator and warm it up with the new
    +        // adjusted history.
    +        _priceScaleFactor = f.PriceScaleFactor;
    +        Indicator.Reset();
    +        var history = _algorithm.History<TradeBar>(
    +            f.Symbol,
    +            Indicator.WarmUpPeriod,
    +            Resolution.Daily,
    +            dataNormalizationMode: DataNormalizationMode.ScaledRaw
    +        );
    +        foreach (var bar in history)
    +        {
    +            Indicator.Update(bar);
    +        }
    +        return Indicator.IsReady;
    +    }
    +}
    +

    Other Examples

    @@ -150471,7 +151465,7 @@

    The ETF ticker. To view the supported ETFs in the US ETF Constituents dataset, see - + Supported ETFs . @@ -150704,7 +151698,7 @@

    Historical Data

    For more information about ETF Constituents data, see - + US ETF Constituents . @@ -151195,7 +152189,7 @@

    Chain Fundamental and Alternative Data

    fundamental universe and a - + QuiverCNBCsUniverse alternative universe . It first selects the 100 most liquid US Equities and then filters them down to those mentioned by CNBC commentator/trader Jim Cramer. The output of the alternative universe selection method is the output of the chained universe. @@ -151262,7 +152256,7 @@

    Chain Fundamental and Alternative Data

    def _fundamental_filter_function(self, fundamental: List[Fundamental]) -> List[Symbol]: # Filter the top 100 liquid equities of the last trading day, and save the symbols for the next filtering. sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume, reverse=True) - self.fundamental = [c.symbol for c in sorted_by_dollar_volume[:100]] + self._fundamental = [c.symbol for c in sorted_by_dollar_volume[:100]] return Universe.UNCHANGED def _mad_money_selection(self, alt_coarse: List[QuiverCNBCsUniverse]) -> List[Symbol]: @@ -151491,7 +152485,7 @@

    Chain ETF and Alternative Data

    ETF universe and a - + QuiverCNBCsUniverse alternative universe . It first selects all constituents of SPY and then filters them down to those mentioned by CNBC commentator/trader Jim Cramer. The output of the alternative universe selection method is the output of the chained universe. @@ -152127,77 +153121,77 @@

    Supported Datasets

    +

    + Example 4: Indicator Universe +

    +

    + The following example shows how to select a universe of Crypto pairs based on indicators. +

    +
    +
    class CryptoIndicatorUniverseSelectionAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Add a universe of Crypto pairs based on indicators.
    +        self._selection_data_by_symbol = {}
    +        self._universe = self.add_universe(CryptoUniverse.coinbase(self._select_assets))
    +        # Add a warm-up period to warm up the indicators in the universe selection.
    +        self.set_warm_up(timedelta(60))
    +
    +    def _select_assets(self, data):
    +        # Update the indicator of all Crypto pairs in the universe dataset and
    +        # get the subset of them that have their indicator ready.
    +        ready_pairs = [
    +            c for c in data
    +            if self._selection_data_by_symbol.setdefault(c.symbol, SelectionData()).update(c)
    +        ]
    +        # As Crypto pairs leave the universe dataset, delete their SelectionData objects.
    +        for symbol in self._selection_data_by_symbol.keys() - {c.symbol for c in data}:
    +            del self._selection_data_by_symbol[symbol]
    +        # During warm-up, keep the universe empty.
    +        if self.is_warming_up:
    +            return []
    +        # Select a subset of the Crypto pairs based on their indicators.
    +        # Example: Pairs trading above their bollinger band with high volume.
    +        filtered = []
    +        for c in ready_pairs:
    +            selection_data = self._selection_data_by_symbol[c.symbol]
    +            if c.close > selection_data.bb.upper_band.current.value:
    +                filtered.append(c)
    +        filtered = sorted(filtered, key=lambda c: self._selection_data_by_symbol[c.symbol].mean_daily_usd_volume)[-10:]
    +        return [c.symbol for c in filtered]
    +
    +
    +class SelectionData:
    +
    +    def __init__(self):
    +        self.mean_daily_usd_volume = SimpleMovingAverage(30)
    +        self.bb = BollingerBands(30, 2)
    +    
    +    def update(self, c):
    +        # Update all the indicators and return true if they are all ready.
    +        return (
    +            self.mean_daily_usd_volume.update(c.end_time, c.volume_in_usd) &
    +            self.bb.update(TradeBar(c.end_time, c.symbol, c.open, c.high, c.low, c.close, c.volume_in_usd))
    +        )
    +
    public class CryptoIndicatorUniverseSelectionAlgorithm : QCAlgorithm
    +{
    +    private Dictionary<Symbol, SelectionData> _selectionDataBySymbol = new();
    +    private Universe _universe;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        // Add a universe of Crypto pairs based on indicators.
    +        _universe = AddUniverse(CryptoUniverse.Coinbase(_SelectAssets));
    +        // Add a warm-up period to warm up the indicators in the universe selection.
    +        SetWarmUp(TimeSpan.FromDays(60));
    +    }
    +
    +    private IEnumerable<Symbol> _SelectAssets(IEnumerable<CryptoUniverse> data)
    +    {
    +        // Update the indicator of all Crypto pairs in the universe dataset and
    +        // get the subset of them that have their indicator ready.
    +        var readyPairs = new List<CryptoUniverse>();
    +        foreach (var c in data)
    +        {
    +            if (!_selectionDataBySymbol.TryGetValue(c.Symbol, out var sd))
    +            {
    +                sd = new SelectionData();
    +                _selectionDataBySymbol[c.Symbol] = sd;
    +            }
    +            if (sd.Update(c))
    +            {
    +                readyPairs.Add(c);
    +            }
    +        }
    +        // As Crypto pairs leave the universe dataset, delete their SelectionData objects.
    +        var activePairs = data.Select(c => c.Symbol).ToHashSet();
    +        foreach (var symbol in _selectionDataBySymbol.Keys.Where(s => !activePairs.Contains(s)).ToList())
    +        {
    +            _selectionDataBySymbol.Remove(symbol);
    +        }
    +        // During warm-up, keep the universe empty.
    +        if (IsWarmingUp)
    +        {
    +            return Enumerable.Empty<Symbol>();
    +        }
    +        // Select a subset of the Crypto pairs based on their indicators.
    +        // Example: Pairs trading above their bollinger band with high volume.
    +        return readyPairs
    +            .Where(c => c.Close > _selectionDataBySymbol[c.Symbol].BB.UpperBand.Current.Value)
    +            .OrderBy(c => _selectionDataBySymbol[c.Symbol].MeanDailyUsdVolume.Current.Value)
    +            .TakeLast(10)
    +            .Select(c => c.Symbol);
    +    }
    +}
    +
    +public class SelectionData
    +{
    +    public SimpleMovingAverage MeanDailyUsdVolume { get; }
    +    public BollingerBands BB { get; }
    +
    +    public SelectionData()
    +    {
    +        MeanDailyUsdVolume = new SimpleMovingAverage(30);
    +        BB = new BollingerBands(30, 2);
    +    }
    +
    +    public bool Update(CryptoUniverse c)
    +    {
    +        // Update all the indicators and return true if they are all ready.
    +        return (
    +            MeanDailyUsdVolume.Update(c.EndTime, (decimal)c.VolumeInUsd) &
    +            BB.Update(new TradeBar(c.EndTime, c.Symbol, c.Open, c.High, c.Low, c.Close, (decimal)c.VolumeInUsd))
    +        );
    +    }
    +}
    +
    @@ -161904,8 +163026,52 @@

    + + + +

    You can also iterate through all of the data objects in the current @@ -165409,19 +166658,42 @@

    Accessing Data

    def on_data(self, slice: Slice) -> None:
    -    for symbol, margin_interest_rate in slice.margin_interest_rates.items():
    -        interest_rate = margin_interest_rate.interest_rate
    -        self.log(f"{symbol} close at {slice.time}: {interest_rate}")
    + for symbol, trade_bar in slice.bars.items(): + self.log(f"{symbol} close at {slice.time}: {trade_bar.close}") + + for symbol, quote_bar in slice.quote_bars.items(): + self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}") + + for symbol, ticks in slice.ticks.items(): + for tick in ticks: + self.log(f"{symbol} price at {slice.time}: {tick.price}")

    public override void OnData(Slice slice)
     {
    -    foreach (var kvp in slice.MarginInterestRates)
    +    foreach (var kvp in slice.Bars)
         {
             var symbol = kvp.Key;
    -        var marginInterestRate = kvp.Value;
    -        var interestRate = marginInterestRate.InterestRate;
    -        Log($"{symbol} price at {slice.Time}: {interestRate}");
    +        var tradeBar = kvp.Value;
    +        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
         }
    -}
    + + foreach (var kvp in slice.QuoteBars) + { + var symbol = kvp.Key; + var quoteBar = kvp.Value; + Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}"); + } + + foreach (var kvp in slice.Ticks) + { + var symbol = kvp.Key; + var ticks = kvp.Value; + foreach (var tick in ticks) + { + Log($"{symbol} price at {slice.Time}: {tick.Price}"); + } + } +} +

    For more information about accessing Crypto Future data, see @@ -165437,21 +166709,14 @@

    Historical Data

    - To get historical Bybit Crypto Future Margin Rate data, call the + To get historical Binance Crypto Future Price data, call the - History<MarginInterestRate> + History history - method with - - - MarginInterestRate - - data type and - - the Crypto Future + method with the Crypto Future Symbol @@ -165459,11 +166724,24 @@

    Historical Data

    # DataFrame
    -history_df = self.history(MarginInterestRate, self.btcusdt, 100, Resolution.DAILY)
    +history_df = self.history(self.btcbusd, 100, Resolution.DAILY)
     
    -# MarginInterestRate objects
    -history = self.history[MarginInterestRate](self.btcusdt, 100, Resolution.DAILY)
    -
    var history = History<MarginInterestRate>(_symbol, 100, Resolution.Daily);
    +# TradeBar objects +history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE) + +# QuoteBar objects +history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE) + +# Tick objects +history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK) +
    // TradeBar objects 
    +var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    +
    +// QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    +
    +// Tick objects 
    +var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);

    For more information about historical data, see @@ -165479,12 +166757,12 @@

    Remove Subscriptions

    - To unsubscribe from a Crypto pair that you added with the + To unsubscribe from a Crypto Future contract that you added with the - AddCrypto + AddCryptoFuture - add_crypto + add_crypto_future method, call the @@ -165496,7 +166774,7 @@

    Remove Subscriptions

    method.

    -
    self.remove_security(self.btcusdt)
    +
    self.remove_security(self.btcbusd)
    RemoveSecurity(_symbol);

    @@ -165507,11 +166785,7 @@

    Remove Subscriptions

    remove_security - method cancels your open orders for the security and liquidates your holdings in the -
    - virtual pair - - . + method cancels your open orders for the security and liquidates your Crypto Future holdings.

    @@ -165527,52 +166801,135 @@

    Supported Assets

    - Pairs Available (631) + Pairs Available (718) - 1CATUSDT + 0GUSDT + + + 1000000BOBUSDT + + + 1000000MOGUSDT + + + 1000BONKUSDC + + + 1000BONKUSDT + + + 1000CATUSDT + + + + + 1000CHEEMSUSDT + + + 1000FLOKIUSDT + + + 1000LUNCBUSD + + + 1000LUNCUSDT + + + 1000PEPEUSDC + + + 1000PEPEUSDT + + + + + 1000RATSUSDT + + + 1000SATSUSDT + + + 1000SHIBBUSD + + + 1000SHIBUSDC + + + 1000SHIBUSDT + + + 1000WHYUSDT + + + + + 1000XECUSDT + + + 1000XUSDT 1INCHUSDT - A8USDT + 1MBABYDOGEUSDT + + + 2ZUSDT + + + 4USDT + + + + + A2ZUSDT AAVEUSD + + AAVEUSDC + AAVEUSDT ACEUSDT - - ACHUSDT + + ACTUSDT ACXUSDT + + ADABUSD + ADAUSD - ADAUSDT + ADAUSDC - AERGOUSDT + ADAUSDT + + AERGOUSDT + AEROUSDT @@ -165580,7 +166937,7 @@

    Supported Assets

    AEVOUSDT - AGIUSDT + AGIXBUSD AGIXUSDT @@ -165588,17 +166945,28 @@

    Supported Assets

    AGLDUSDT + + + + AGTUSDT + AI16ZUSDT - - - AIDOGEUSDT + AIAUSDT - AIOZUSDT + AINUSDT + + + AIOTUSDT + + + AIOUSDT + + AIUSDT @@ -165606,62 +166974,79 @@

    Supported Assets

    AIXBTUSDT - AKROUSDT + AKEUSDT AKTUSDT - - ALCHUSDT - ALEOUSDT + ALGOUSD + + ALGOUSDT ALICEUSDT + + ALLUSDT + ALPACAUSDT ALPHAUSDT + + ALPINEUSDT + ALTUSDT - ALUUSDT + AMBBUSD AMBUSDT + + ANCBUSD + ANIMEUSDT ANKRUSDT + + ANTUSDT - - - APEUSDT + APEBUSD - APEXUSDT + APEUSD + + + APEUSDT API3USDT + + APTBUSD + + + APTUSD @@ -165669,16 +167054,19 @@

    Supported Assets

    APTUSDT - APUUSDT + ARBUSDC - - ARBUSDT ARCUSDT + + ARIAUSDT + + + ARKMUSDT @@ -165691,6 +167079,12 @@

    Supported Assets

    ARUSDT + + ASRUSDT + + + ASTERUSDT + @@ -165702,48 +167096,68 @@

    Supported Assets

    ATHUSDT + + ATOMUSD + ATOMUSDT + + AUCTIONBUSD + + + AUCTIONUSDT AUDIOUSDT - - - AVAAIUSDT + AUSDT - AVAILUSDT + AVAAIUSDT AVAUSDT + + AVAXBUSD + + + AVAXUSD + + AVAXUSDC + AVAXUSDT - AVLUSDT + AVNTUSDT + + + AWEUSDT + + + AXLUSDT - AXLUSDT + AXSUSD AXSUSDT - B3USDT + B2USDT - BABYDOGEUSDT + B3USDT BABYUSDT @@ -165776,6 +167190,12 @@

    Supported Assets

    BANUSDT + + BARDUSDT + + + BASUSDT + BATUSDT @@ -165785,45 +167205,53 @@

    Supported Assets

    BCHUSD + + - BCHUSDT + BCHUSDC - BEAMUSDT + BCHUSDT - - - BEERUSDT + BDXNUSDT - BELUSDT + BEAMXUSDT - BENDOGUSDT + BELUSDT BERAUSDT + + BICOUSDT + + BIDUSDT + BIGTIMEUSDT - - - BILLYUSDT + BIOUSDC BIOUSDT - BLASTUSDT + BLESSUSDT + + - BLUEUSDT + BLUAIUSDT + + + BLUEBIRDUSDT BLURUSDT @@ -165831,10 +167259,19 @@

    Supported Assets

    BLZUSDT + + BMTUSDT + + + BNBBUSD + - BMTUSDT + BNBUSD + + + BNBUSDC BNBUSDT @@ -165846,50 +167283,67 @@

    Supported Assets

    BNXUSDT - BOBAUSDT + BOMEUSDC + + BOMEUSDT - - BONDUSDT - BONKUSDT + BRETTUSDT - BRETTUSDT + BROCCOLI714USDT - BROCCOLIUSDT + BROCCOLIF3BUSDT BRUSDT + + BSVUSDT - - BSWUSDT + + BTCBUSD + + + BTCDOMUSDT + + + BTCSTUSDT + BTCUSD + + + + BTCUSDC + BTCUSDT - BTTUSDT + BTRUSDT - BUSDUSDT + BTSUSDT - BUZZUSDT + BULLAUSDT + + + BUSDT @@ -165906,195 +167360,201 @@

    Supported Assets

    CATIUSDT - CATSUSDT + CELOUSDT - CATUSDT + CELRUSDT - CEEKUSDT + CETUSUSDT - CELOUSDT + CFXUSDT - CELRUSDT + CGPTUSDT - CETUSUSDT + CHESSUSDT - CFXUSDT + CHILLGUYUSDT - CGPTUSDT + CHRUSDT - CHEEMSUSDT + CHZUSD - CHESSUSDT + CHZUSDT - CHILLGUYUSDT + CKBUSDT - CHRUSDT + CLOUSDT - CHZUSDT + COAIUSDT - CKBUSDT + COCOSUSDT - CLANKERUSDT + COMBOUSDT - CLOUDUSDT + COMPUSDT - COMBOUSDT + COOKIEUSDT - COMPUSDT + COSUSDT - COOKIEUSDT + COTIUSDT - COOKUSDT + COWUSDT - COQUSDT + CROSSUSDT - COREUSDT + CRVUSDC - COSUSDT + CRVUSDT - COTIUSDT + CTKUSDT - COVALUSDT + CTSIUSDT - COWUSDT + CUDISUSDT - CPOOLUSDT + CUSDT - CROUSDT + CVCUSDT - CRVUSDT + CVXBUSD - CTCUSDT + CVXUSDT - CTKUSDT + CYBERUSDT - CTSIUSDT + DAMUSDT - CVCUSDT + DARUSDT - CVXUSDT + DASHUSDT - CYBERUSDT + DEEPUSDT - DAOUSDT + DEFIUSDT - DARKUSDT + DEGENUSDT - DARUSDT + DEGOUSDT - DASHUSDT + DENTUSDT - DATAUSDT + DEXEUSDT - DBRUSDT + DFUSDT - DEEPUSDT + DGBUSDT - DEGENUSDT + DIAUSDT - DENTUSDT + DMCUSDT - DEXEUSDT + DODOBUSD - DGBUSDT + DODOXUSDT - DODOUSDT + DOGEBUSD DOGEUSD - DOGEUSDT + DOGEUSDC - DOGSUSDT + DOGEUSDT - DOGUSDT + DOGSUSD + + + DOGSUSDT + + + DOLOUSDT DOODUSDT - DOP1USDT + DOTBUSD DOTUSD + + DOTUSDT DRIFTUSDT - - - DUCKUSDT + DUSDT DUSKUSDT @@ -166105,37 +167565,48 @@

    Supported Assets

    DYMUSDT + + + + EDENUSDT + EDUUSDT - EGLDUSDT + EGLDUSD - - - EIGENUSDT + EGLDUSDT - ELONUSDT + EIGENUSDT - ELXUSDT + ENAUSDC + + ENAUSDT ENJUSDT + + ENSOUSDT + + + ENSUSD + ENSUSDT - - EOSUSD + + EOSUSDT @@ -166146,22 +167617,42 @@

    Supported Assets

    EPTUSDT - ETCUSD + ERAUSDT - ETCUSDT + ESPORTSUSDT + + + ETCBUSD - ETHBTCUSDT + ETCUSD + + + ETCUSDT + + + ETHBTC + + + ETHBUSD + + + ETHFIUSDC ETHFIUSDT + + ETHUSD + + ETHUSDC + ETHUSDT @@ -166169,18 +167660,21 @@

    Supported Assets

    ETHWUSDT - FARTCOINUSDT + EULUSDT + + + EVAAUSDT - FBUSDT + FARTCOINUSDT - FDUSDUSDT + FETUSDT - FETUSDT + FFUSDT FHEUSDT @@ -166189,139 +167683,136 @@

    Supported Assets

    FIDAUSDT - FILUSD + FILBUSD - FILUSDT + FILUSD - FIOUSDT + FILUSDC - FIREUSDT + FILUSDT - FITFIUSDT + FIOUSDT - FLMUSDT + FISUSDT - FLOCKUSDT + FLMUSDT - FLOKIUSDT + FLOCKUSDT FLOWUSDT - FLRUSDT + FLUIDUSDT FLUXUSDT - FORMUSDT + FOOTBALLUSDT - FORTHUSDT + FORMUSDT - FOXYUSDT + FORTHUSDT FRONTUSDT - FTMUSDT + FTMBUSD - FTNUSDT + FTMUSD - FUELUSDT + FTMUSDT - FUNUSDT + FTTBUSD - FUSDT + FTTUSDT - FWOGUSDT + FUNUSDT - FXSUSDT + FUSDT - GALAUSDT + FXSUSDT - GALUSDT + GALABUSD - GASUSDT + GALAUSD - GEMSUSDT + GALAUSDT - GFTUSDT + GALBUSD - GIGAUSDT + GALUSDT - GLMRUSDT + GASUSDT - GLMUSDT + GHSTUSDT - GMEUSDT + GIGGLEUSDT - GMTUSDT + GLMRUSDT - GMXUSDT + GLMUSDT - GNOUSDT + GMTBUSD - GOATUSDT + GMTUSD - GODSUSDT + GMTUSDT - GOMININGUSDT + GMXUSDT - GORKUSDT + GOATUSDT GPSUSDT - - GPTUSDT - GRASSUSDT @@ -166331,11 +167822,11 @@

    Supported Assets

    GRTUSDT - - GTCUSDT + + GUNUSDT @@ -166346,13 +167837,22 @@

    Supported Assets

    HAEDALUSDT - HBARUSDT + HANAUSDT - HEIUSDT + HBARUSDC + + + HBARUSDT + + HEIUSDT + + + HEMIUSDT + HFTUSDT @@ -166365,25 +167865,36 @@

    Supported Assets

    HIPPOUSDT + + HIVEUSDT HMSTRUSDT - - HNTUSDT + + HOLOUSDT + + + HOMEUSDT + HOOKUSDT + + HOTUSDT - HPOS10IUSDT + HUMAUSDT + + + HUSDT HYPERUSDT @@ -166391,17 +167902,31 @@

    Supported Assets

    HYPEUSDT + + ICNTUSDT + + + ICPBUSD + ICPUSDT + + ICXUSD + ICXUSDT IDEXUSDT + + IDOLUSDT + + + IDUSDT @@ -166411,14 +167936,17 @@

    Supported Assets

    IMXUSDT - - INITUSDT INJUSDT + + INUSDT + + + IOSTUSDT @@ -166431,14 +167959,14 @@

    Supported Assets

    IOUSDT - - - IPUSDT + IPUSDC - IQ50USDT + IPUSDT + + JASMYUSDT @@ -166451,19 +167979,19 @@

    Supported Assets

    JSTUSDT - - JTOUSDT JUPUSDT + + - JUSDT + KAIAUSDT - KAIAUSDT + KAITOUSDC KAITOUSDT @@ -166471,26 +167999,32 @@

    Supported Assets

    KASUSDT - - KAVAUSDT KDAUSDT + + KERNELUSDT KEYUSDT + + KGENUSDT + KLAYUSDT KMNOUSDT + + KNCUSD + @@ -166503,28 +168037,48 @@

    Supported Assets

    KSMUSDT - L3USDT + LABUSDT - LADYSUSDT + LAUSDT - LAIUSDT + LAYERUSDT + + LDOBUSD + LDOUSDT + + LEVERBUSD + LEVERUSDT + + LIGHTUSDT + LINAUSDT + + + + LINEAUSDT + + + LINKBUSD + LINKUSD + + LINKUSDC + LINKUSDT @@ -166537,7 +168091,7 @@

    Supported Assets

    LITUSDT - LOOKSUSDT + LOKAUSDT LOOMUSDT @@ -166557,16 +168111,16 @@

    Supported Assets

    LSKUSDT - LTCUSD + LTCBUSD - LTCUSDT + LTCUSD - LTOUSDT + LTCUSDC - LUCEUSDT + LTCUSDT LUMIAUSDT @@ -166574,16 +168128,16 @@

    Supported Assets

    - LUNA2USDT + LUNA2BUSD - LUNCUSDT + LUNA2USDT - MAGICUSDT + LYNUSDT - MAJORUSDT + MAGICUSDT MANAUSD @@ -166594,19 +168148,19 @@

    Supported Assets

    - MANEKIUSDT + MANTAUSDT - MANTAUSDT + MASKUSDT - MAPOUSDT + MATICBUSD - MASAUSDT + MATICUSD - MASKUSDT + MATICUSDC MATICUSDT @@ -166619,26 +168173,20 @@

    Supported Assets

    MAVUSDT - - MAXUSDT - MBLUSDT MBOXUSDT - - MCUSDT - - - MDTUSDT MELANIAUSDT + + MEMEFIUSDT @@ -166651,16 +168199,16 @@

    Supported Assets

    METISUSDT - - - MEUSDT + METUSDT - MEWUSDT + MEUSDT + + - MICHIUSDT + MEWUSDT MILKUSDT @@ -166669,30 +168217,22 @@

    Supported Assets

    MINAUSDT - MKRUSDT - - - - - MLNUSDT + MIRAUSDT - MNTUSD + MITOUSDT - MNTUSDT + MKRUSDT + + - MOBILEUSDT + MLNUSDT MOCAUSDT - - MOGUSDT - - - MONUSDT @@ -166703,19 +168243,10 @@

    Supported Assets

    MORPHOUSDT - MOTHER1USDT - - - MOTHER2USDT - - - MOTHERUSDT + MOVEUSDT - - MOVEUSDT - MOVRUSDT @@ -166726,47 +168257,50 @@

    Supported Assets

    MUBARAKUSDT - MULTIUSDT + MUSDT - MUMUUSDT + MYROUSDT + + + MYXUSDT - MVLUSDT + NAORISUSDT - MYRIAUSDT + NEARBUSD - MYROUSDT + NEARUSD - NCUSDT + NEARUSDC - NEARUSD + NEARUSDT - NEARUSDT + NEIROETHUSDT - NEIROCTOUSDT + NEIROUSDT - NEIROETHUSDT + NEOUSDC NEOUSDT - NFPUSDT + NEWTUSDT - NFTUSDT + NFPUSDT NILUSDT @@ -166780,10 +168314,10 @@

    Supported Assets

    NMRUSDT - NOTUSDT + NOMUSDT - NSUSDT + NOTUSDT NTRNUSDT @@ -166794,14 +168328,11 @@

    Supported Assets

    - NYANUSDT + NXPCUSDT OBOLUSDT - - OBTUSDT - OCEANUSDT @@ -166811,14 +168342,11 @@

    Supported Assets

    OGUSDT - - - - OKBUSDT - OLUSDT + + OMGUSDT @@ -166831,17 +168359,20 @@

    Supported Assets

    ONDOUSDT - - ONEUSDT ONGUSDT + + ONTUSDT + + OPENUSDT + OPUSD @@ -166851,88 +168382,77 @@

    Supported Assets

    ORBSUSDT - - ORCAUSDT + + ORDERUSDT - ORDIUSDT - - - ORNUSDT + ORDIUSDC - OSMOUSDT + ORDIUSDT OXTUSDT - - PARTIUSDT PAXGUSDT - - PEAQUSDT - - - PEIPEIUSDT - + + PENDLEUSDT - PENGUSDT + PENGUUSDC - - PENGUUSDT PEOPLEUSDT - - PEPEUSDT - PERPUSDT PHAUSDT - - PHBUSDT - - PIPPINUSDT + PHBBUSD - PIRATEUSDT + PHBUSDT + + + PIPPINUSDT PIXELUSDT - PIXFIUSDT + PLAYUSDT PLUMEUSDT + + + + PNUTUSDC + PNUTUSDT - - POLUSDT @@ -166945,25 +168465,16 @@

    Supported Assets

    POPCATUSDT - - PORTALUSDT - - - POWRUSDT - - PRCLUSDT - - - PRE05EOSUSDT + PORT3USDT - PRE08EOSUSDT + PORTALUSDT - PRIMEUSDT + POWRUSDT PROMPTUSDT @@ -166971,34 +168482,31 @@

    Supported Assets

    PROMUSDT + + PROVEUSDT + - PROSUSDT + PTBUSDT PUFFERUSDT - PUMPUSDT + PUMPBTCUSDT - PUNDIXUSDT + PUMPUSDT - PUNDUUSDT + PUNDIXUSDT - PYRUSDT + PYTHUSDT - - PYTHUSDT - - - QIUSDT - QNTUSDT @@ -167006,24 +168514,21 @@

    Supported Assets

    QTUMUSDT - QUBICUSDT + QUICKUSDT - QUICKUSDT + QUSDT - - RADUSDT RAREUSDT + + - RATSUSDT - - - RAYDIUMUSDT + RAYSOLUSDT RAYUSDT @@ -167031,14 +168536,20 @@

    Supported Assets

    RDNTUSDT - - + + RECALLUSDT + REDUSDT REEFUSDT + + + + REIUSDT + RENDERUSDT @@ -167046,67 +168557,70 @@

    Supported Assets

    RENUSDT - REQUSDT + RESOLVUSDT - REXUSDT + REZUSDT + + + RIFUSDT - REZUSDT + RIVERUSDT - RFCUSDT + RLCUSDT - RIFSOLUSDT + RNDRUSDT - RIFUSDT + RONINUSDT - RLCUSDT + ROSEUSD - RNDRUSDT + ROSEUSDT - ROAMUSDT + RPLUSDT - RONINUSDT + RSRUSDT - RONUSDT + RUNEUSD - ROSEUSDT + RUNEUSDT - RPLUSDT + RVNUSDT - RSRUSDT + RVVUSDT - RSS3USDT + SAFEUSDT - RUNEUSDT + SAGAUSDT - RVNUSDT + SAHARAUSDT - SAFEUSDT + SANDBUSD - SAGAUSDT + SANDUSD SANDUSDT @@ -167114,10 +168628,10 @@

    Supported Assets

    - SATSUSDT + SANTOSUSDT - SCAUSDT + SAPIENUSDT SCRTUSDT @@ -167129,95 +168643,101 @@

    Supported Assets

    SCUSDT - SDUSDT + SEIUSDT - SEIUSDT + SFPUSDT - SENDUSDT + SHELLUSDT - SERAPHUSDT + SIGNUSDT - SFPUSDT + SIRENUSDT - SHELLUSDT + SKATEUSDT - SHIB1000USDT + SKLUSDT - SIGNUSDT + SKYAIUSDT - SILLYUSDT + SKYUSDT - SIRENUSDT + SLERFUSDT - SKLUSDT + SLPUSDT - SLERFUSDT + SNTUSDT - SLFUSDT + SNXUSDT - SLPUSDT + SOLBUSD - SNTUSDT + SOLUSD - SNXUSDT + SOLUSDC - SOLAYERUSDT + SOLUSDT - SOLOUSDT + SOLVUSDT - SOLUSD + SOMIUSDT - SOLUSDT + SONICUSDT - SOLVUSDT + SOONUSDT - SONICUSDT + SOPHUSDT - SPECUSDT + SPELLUSDT - SPELLUSDT + SPKUSDT SPXUSDT + + SQDUSDT + + + SRMUSDT + SSVUSDT - STARLUSDT + STBLUSDT STEEMUSDT @@ -167225,14 +168745,14 @@

    Supported Assets

    STGUSDT + + STMXUSDT STORJUSDT - - STOUSDT @@ -167245,19 +168765,19 @@

    Supported Assets

    STRKUSDT + + STXUSDT SUIUSD - - - SUIUSDT + SUIUSDC - SUNDOGUSDT + SUIUSDT SUNUSDT @@ -167265,20 +168785,17 @@

    Supported Assets

    SUPERUSDT + + SUSDT SUSHIUSDT - - SWARMSUSDT - - SWEATUSDT - SWELLUSDT @@ -167288,25 +168805,42 @@

    Supported Assets

    SXTUSDT + + SYNUSDT - - + + SYRUPUSDT + SYSUSDT + + TACUSDT + + + TAGUSDT + TAIKOUSDT + + + + TAKEUSDT + - TAIUSDT + TANSSIUSDT TAOUSDT - TEST01SWELLUSDT + TAUSDT + + + THETAUSD THETAUSDT @@ -167317,27 +168851,27 @@

    Supported Assets

    THEUSDT - TIAUSDT + TIAUSDC - TLMUSDT + TIAUSDT - TNSRUSDT + TLMBUSD - TOKENUSDT + TLMUSDT - TOMIUSDT + TNSRUSDT - TOMOUSDT + TOKENUSDT - TONUSD + TOMOUSDT TONUSDT @@ -167346,62 +168880,93 @@

    Supported Assets

    TOSHIUSDT - TRBUSDT + TOWNSUSDT - TROYUSDT + TRADOORUSDT + + TRBUSDT + + + TREEUSDT + + + TROYUSDT + + + TRUMPUSDC + TRUMPUSDT + + TRUTHUSDT + + + TRUUSDT + + TRXBUSD + + + TRXUSD + TRXUSDT - TSTBSCUSDT + TSTUSDT TURBOUSDT + + TUSDT - - TUTUSDT TWTUSDT + + UBUSDT + UMAUSDT UNFIUSDT + + + + UNIBUSD + UNIUSD - UNIUSDT + UNIUSDC - - - UROUSDT + UNIUSDT USDCUSDT - USDEUSDT + USELESSUSDT + + USTCUSDT @@ -167411,8 +168976,6 @@

    Supported Assets

    UXLINKUSDT - - VANAUSDT @@ -167422,43 +168985,37 @@

    Supported Assets

    VELODROMEUSDT + + - VELOUSDT + VELVETUSDT + + + VETUSD VETUSDT - VGXUSDT + VFYUSDT - - VICUSDT VIDTUSDT + + VINEUSDT - - VINUUSDT - VIRTUALUSDT VOXELUSDT - - - - VRAUSDT - - - VRUSDT - VTHOUSDT @@ -167468,68 +169025,65 @@

    Supported Assets

    WALUSDT - - WAVESUSDT - - WAXPUSDT + WAVESBUSD - WCTUSDT + WAVESUSDT - WENUSDT + WAXPUSDT - WHYUSDT + WCTUSDT WIFUSD - WIFUSDT + WIFUSDC - WLDUSDT + WIFUSDT - WOOUSDT + WLDUSD - WSMUSDT + WLDUSDC - WUSDT + WLDUSDT - XAIUSDT + WLFIUSDC - XAUTUSDT + WLFIUSDT - XCHUSDT + WOOUSDT - XCNUSDT + WUSDT - XDCUSDT + XAIUSDT - XECUSDT + XANUSDT - XEMUSDT + XCNUSDT - XIONUSDT + XEMUSDT @@ -167540,61 +169094,67 @@

    Supported Assets

    XLMUSDT - XMRUSDT + XMRUSD - XNOUSDT + XMRUSDT - XRDUSDT + XNYUSDT - XRPUSD + XPINUSDT - XRPUSDT + XPLUSDT - XTERUSDT + XRPBUSD - XTZUSDT + XRPUSD - XUSDT + XRPUSDC - XVGUSDT + XRPUSDT - XVSUSDT + XTZUSD - YFIIUSDT + XTZUSDT - YFIUSDT + XVGUSDT - YGGUSDT + XVSUSDT - ZBCNUSDT + YALAUSDT - ZCXUSDT + YBUSDT - ZECUSDT + YFIUSDT - ZENTUSDT + YGGUSDT + + + ZBTUSDT + + + ZECUSDT ZENUSDT @@ -167605,16 +169165,16 @@

    Supported Assets

    ZETAUSDT + + - ZEUSUSDT + ZILUSD ZILUSDT - - - ZKFUSDT + ZKCUSDT ZKJUSDT @@ -167625,17 +169185,20 @@

    Supported Assets

    ZORAUSDT + + ZRCUSDT ZROUSDT - - ZRXUSDT + + 币安人生USDT + @@ -167647,146 +169210,126 @@

    Example Applications

    - The Binance Crypto Future Margin Rate dataset enables correct margin cost so you can accurately design strategies for Cryptocurrencies with term structure. Examples include the following strategies: + The Binance Crypto Future Price dataset enables you to accurately design strategies for Cryptocurrencies with term structure. Examples include the following strategies:

    • - Horizontal/Diagonal arbitrage with the underlying Cryptocurrencies + Horizontal/Diagonal arbitrage with the underlying cryptocurrencies
    • Trade Contango/Backwardation predictions
    • - Hedge for illiquid Cryptocurrencies + Hedge for illiquid cryptocurrencies

    Classic Algorithm Example

    - The following example algorithm holds a long position in the BTCUSDT perpetual Future contract on the Bybit exchange. When the margin interest rate is relatively low, it flips to a short position. + The following example algorithm buys BTCUSDT perpetual future contract if the last day's close price was close to ask close price than bid close price, sells short of that in opposite, through the Binance exchange:

    -
    from AlgorithmImports import *
    -
    +   
    from AlgorithmImports import *
     
    -class BybitCryptoFutureDataAlgorithm(QCAlgorithm):
     
    -    # Add an indicator to track the low of trailing margin interest rates.
    -    _low_interest_rate = Minimum(10)
    +class BinanceCryptoFutureDataAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        # Set Account Currency to USDT, since USD cannot be used to trade.
    -        self.set_cash("USDT", 100_000)
    -        # Bybit  accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    -        # Seed the price of each asset with its last known price to avoid trading errors.
    -        self.settings.seed_initial_prices = True
    -        # Requesting data, we only trade on BTCUSDT Future in Bybit  exchange
    +        # Set the account currency to USDT, since you can't trade with 
    +        # USD and the algorithm doesn't automatically convert USD & USDT
    +        # holdings.
    +        self.set_account_currency("USDT", 100000)
    +        # Binance Futures Exchange accepts both Cash and Margin account 
    +        # types. Select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
    +        # Add BTCUSDT data from the Binance Future exchange.
             # Perpetual futures does not have a filter function.
    -        self._future = self.add_crypto_future("BTCUSDT", Resolution.DAILY)
    +        self._btc = self.add_crypto_future("BTCUSDT", Resolution.DAILY)
             # Historical data
    -        history = self.history[MarginInterestRate](self._future.symbol, 10, Resolution.DAILY)
    -        for data_point in history:
    -            self._low_interest_rate.update(data_point.end_time, data_point.interest_rate)
    +        history = self.history(self._btc, 10, Resolution.DAILY)
     
         def on_data(self, slice: Slice) -> None:
    -        # Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL
    -        # Or you can calculate the trade size on keeping the quote currency constant
    -        if self._future.symbol not in slice.margin_interest_rates:
    +        # Trade only based on updated price data.
    +        if self._btc.symbol not in slice.bars or self._btc.symbol not in slice.quote_bars:
                 return
    -        interest_rate = slice.margin_interest_rates[self._future.symbol].interest_rate
    -        self.plot('Margin Interest Rate', str(self._future.symbol), interest_rate)
    -        # Short when margin interest rates are relatively low. Otherwise, long.
    -        if interest_rate <= self._low_interest_rate.current.value:
    -            if not self._future.holdings.is_short:
    -                self.set_holdings(self._future.symbol, -0.5)
    -        elif not self._future.holdings.is_long:
    -            self.set_holdings(self._future.symbol, 1)
    -        # Update the indicator.
    -        self._low_interest_rate.update(self.time, interest_rate)
    -
    public class BybitCryptoFutureDataAlgorithm : QCAlgorithm
    +        # Scalp-trade the bid-ask spread based on the supply-demand strength
    +        if self._btc.price - self._btc.bid_price > self._btc.ask_price - self._btc.price:
    +            self.set_holdings(self._btc, -0.5)
    +        else:
    +            self.set_holdings(self._btc, 1)
    +
    public class BinanceCryptoFutureDataAlgorithm : QCAlgorithm
     {
    -    private CryptoFuture _future;
    -    // Add an indicator to track the low of trailing margin interest rates.
    -    private Minimum _lowInterestRate = new(10);
    +    public CryptoFuture _btc;
     
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        // Set Account Currency to USDT, since USD cannot be used to trade.
    -        SetCash("USDT", 100000);
    -        // Bybit  accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    -        // Seed the price of each asset with its last known price to avoid trading errors.
    -        Settings.SeedInitialPrices = true;
    -        // Requesting data, we only trade on BTCUSDT Future in Bybit  exchange
    +        // Set the account currency to USDT, since you can't trade with 
    +        // USD and the algorithm doesn't automatically convert USD & USDT
    +        // holdings.
    +        SetAccountCurrency("USDT", 100000);
    +        // Binance Futures Exchange accepts both Cash and Margin account 
    +        // types. Select the one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
    +        // Add BTCUSDT data from the Binance Future exchange.
             // Perpetual futures does not have a filter function.
    -        _future = AddCryptoFuture("BTCUSDT", Resolution.Daily);
    +        _btc = AddCryptoFuture("BTCUSDT", Resolution.Daily);
             // Historical data
    -        var history = History<MarginInterestRate>(_future.Symbol, 10, Resolution.Daily);
    -        foreach (var dataPoint in history)
    -        {
    -            _lowInterestRate.Update(dataPoint.EndTime, dataPoint.InterestRate);
    -        }
    +        var history = History(_btc, 10, Resolution.Daily);
         }
     
         public override void OnData(Slice slice)
         {
    -        // Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL
    -        // Or you can calculate the trade size on keeping the quote currency constant
    -        if (!slice.MarginInterestRates.TryGetValue(_future.Symbol, out var dataPoint))
    +        // Trade only based on updated price data.
    +        if (!slice.Bars.ContainsKey(_btc) || !slice.QuoteBars.ContainsKey(_btc))
             {
                 return;
             }
    -        var interestRate = dataPoint.InterestRate;
    -        Plot("Margin Interest Rate", _future.Symbol.ToString(), interestRate);
    -        // Short when margin interest rates are relatively low. Otherwise, long.
    -        if (interestRate <= _lowInterestRate)
    +        // Scalp-trade the bid-ask spread based on the supply-demand strength
    +        if (_btc.Price - _btc.BidPrice > _btc.AskPrice - _btc.Price)
             {
    -            if (!_future.Holdings.IsShort)
    -            {
    -                SetHoldings(_future.Symbol, -0.5);
    -            }
    +            SetHoldings(_btc, -0.5m);
             }
    -        else if (!_future.Holdings.IsLong)
    +        else
             {
    -            SetHoldings(_future.Symbol, 1);
    +            SetHoldings(_btc, 1m);
             }
    -        // Update the indicator.
    -        _lowInterestRate.Update(Time, interestRate);
         }
    -}
    +}

    Framework Algorithm Example

    - The following example algorithm holds a long position in the BTCUSDT perpetual Future contract on the Bybit exchange. When the margin interest rate is relatively low, it flips to a short position. + The following example algorithm hold a long BTCUSDT Future portfolio if the last day's close price was close to ask close price than bid close price, while hold short of that in opposite, through the Binance exchange using the + + algorithm framework + + implementation:

    -
    from AlgorithmImports import *
    +   
    from AlgorithmImports import *
     
     
    -class BybitCryptoFutureDataAlgorithm(QCAlgorithm):
    +class BinanceCryptoFutureDataAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        self.settings.free_portfolio_value_percentage = 0.1
    -        # Set Account Currency to USDT, since USD cannot be used to trade.
    -        self.set_cash("USDT", 100000)
    -        # Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    -        # Seed the price of each asset with its last known price to avoid trading errors.
    -        self.settings.seed_initial_prices = True
    +        # Set the account currency to USDT, since you can't trade with 
    +        # USD and the algorithm doesn't automatically convert USD & USDT
    +        # holdings.
    +        self.set_account_currency("USDT", 100000)
    +        # Binance Futures Exchange accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
             self.universe_settings.resolution = Resolution.DAILY
             self.universe_settings.leverage = 2
    -        # We only trade on BTCUSDT Future in Bybit exchange
    -        symbols = Symbol.create("BTCUSDT", SecurityType.CRYPTO_FUTURE, Market.BYBIT)
    +        # We only trade on BTCUSDT Future in Binance Future exchange
    +        symbols = Symbol.create("BTCUSDT", SecurityType.CRYPTO_FUTURE, Market.BINANCE)
             self.add_universe_selection(ManualUniverseSelectionModel(symbols))
             # Custom alpha model to emit insights based on the Crypto Future price data
             self.add_alpha(CryptoFutureAlphaModel())
    @@ -167794,59 +169337,63 @@ 

    self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel()) self.set_execution(ImmediateExecutionModel()) - class CryptoFutureAlphaModel(AlphaModel): - _min_by_symbol = {} + def __init__(self) -> None: + self.symbols = [] def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]: insights = [] - for symbol, low_interest_rate in self._min_by_symbol.items(): - # Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL - # Or you can calculate the trade size on keeping the quote currency constant - if symbol not in slice.margin_interest_rates: + + for symbol in self.symbols: + # Trade only based on updated price data + if not slice.bars.contains_key(symbol) or not slice.quote_bars.contains_key(symbol): continue - interest_rate = slice.margin_interest_rates[symbol].interest_rate - algorithm.plot('Margin Interest Rate', str(symbol), interest_rate) - # Short when margin interest rates are relatively low. Otherwise, long. - if interest_rate <= low_interest_rate.current.value: + + quote = slice.quote_bars[symbol] + price = slice.bars[symbol].price + + # Scalp-trade the bid-ask spread based on the supply-demand strength + if price - quote.bid.close > quote.ask.close - price: direction = InsightDirection.DOWN else: direction = InsightDirection.UP insights.append(Insight.price(symbol, timedelta(1), direction)) - # Update the indicator. - low_interest_rate.update(slice.time, interest_rate) + return insights def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None: for security in changes.added_securities: symbol = security.symbol - # Add an indicator to track the low of trailing margin interest rates. - self._min_by_symbol[symbol] = Minimum(10) + self.symbols.append(symbol) + # Historical data - history = algorithm.history[MarginInterestRate](symbol, 10, Resolution.DAILY) - for data_point in history: - self._min_by_symbol[symbol].update(data_point.end_time, data_point.interest_rate) + history = algorithm.history(symbol, 10, Resolution.DAILY) + for security in changes.removed_securities: - self._min_by_symbol.pop(security.symbol, None)

    -
    public class BybitCryptoFutureDataAlgorithm : QCAlgorithm
    +            symbol = security.symbol
    +            if symbol in self.symbols:
    +                self.symbols.remove(symbol)
    +
    +
    public class BinanceCryptoFutureDataAlgorithm : QCAlgorithm
     {
    +    public Symbol _symbol;
    +
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        Settings.FreePortfolioValuePercentage = 0.1m;
    -        // Set Account Currency to USDT, since USD cannot be used to trade.
    -        SetCash("USDT", 100000);
    -        // Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    -        // Seed the price of each asset with its last known price to avoid trading errors.
    -        Settings.SeedInitialPrices = true;
    +        // Set the account currency to USDT, since you can't trade with 
    +        // USD and the algorithm doesn't automatically convert USD & USDT
    +        // holdings.
    +        SetAccountCurrency("USDT", 100000);
    +        // Binance Futures Exchange accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
             UniverseSettings.Resolution = Resolution.Daily;
             UniverseSettings.Leverage = 2;
    -        // We only trade on BTCUSDT Future in Bybit exchange
    -        var symbols = new List<Symbol>{
    -            QuantConnect.Symbol.Create("BTCUSDT", SecurityType.CryptoFuture, Market.Bybit)
    +        // We only trade on BTCUSDT Future in Binance Future exchange
    +        var symbols = new List<Symbol> {
    +            QuantConnect.Symbol.Create("BTCUSDT", SecurityType.CryptoFuture, Market.Binance)
             };
             AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
             // Custom alpha model to emit insights based on the Crypto Future price data
    @@ -167859,28 +169406,32 @@ 

    public class CryptoFutureAlphaModel : AlphaModel { - private Dictionary<Symbol, Minimum> _minBySymbol = new(); + private List<Symbol> _symbols = new(); public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice) { var insights = new List<Insight>(); - foreach (var kvp in _minBySymbol) + + foreach (var symbol in _symbols) { - var symbol = kvp.Key; - var lowInterestRate = kvp.Value; - // Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL - // Or you can calculate the trade size on keeping the quote currency constant - if (!slice.MarginInterestRates.TryGetValue(symbol, out var dataPoint)) + // Trade only based on updated price data + if (!slice.Bars.ContainsKey(symbol) || !slice.QuoteBars.TryGetValue(symbol, out var quote)) + { continue; - var interestRate = dataPoint.InterestRate; - algorithm.Plot("Margin Interest Rate", symbol.ToString(), interestRate); - // Short when margin interest rates are relatively low. Otherwise, long. - var direction = interestRate <= lowInterestRate.Current.Value - ? InsightDirection.Down - : InsightDirection.Up; + } + var price = slice.Bars[symbol].Price; + + // Scalp-trade the bid-ask spread based on the supply-demand strength + InsightDirection direction; + if (price - quote.Bid.Close > quote.Ask.Close - price) + { + direction = InsightDirection.Down; + } + else + { + direction = InsightDirection.Up; + } insights.Add(Insight.Price(symbol, TimeSpan.FromDays(1), direction)); - // Update the indicator. - lowInterestRate.Update(slice.Time, interestRate); } return insights; } @@ -167890,22 +169441,18 @@

    foreach (var security in changes.AddedSecurities) { var symbol = security.Symbol; - // Add an indicator to track the low of trailing margin interest rates. - var min = new Minimum(10); - _minBySymbol[symbol] = min; + _symbols.Add(symbol); + // Historical data - var history = algorithm.History<MarginInterestRate>(symbol, 10, Resolution.Daily); - foreach (var dataPoint in history) - { - min.Update(dataPoint.EndTime, dataPoint.InterestRate); - } + var history = algorithm.History(symbol, 10, Resolution.Daily); } + foreach (var security in changes.RemovedSecurities) { - _minBySymbol.Remove(security.Symbol); + _symbols.Remove(security.Symbol); } } -}

    +}
    @@ -167914,41 +169461,73 @@

    Data Point Attributes

    - The Binance Crypto Future Margin Rate dataset provides + The Binance Crypto Future Price dataset provides - MarginInterestRate + TradeBar - objects, which have the following attributes: + , + + QuoteBar + + , and + + Tick + + objects.

    -
    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +

     

    - +

    QuantConnect

    -

    CFD Data

    +

    Binance Crypto Price Data

    Introduction

    - The CFD Data by QuantConnect serves 51 - - contracts for differences - - (CFD). The data starts as early as May 2002 and is delivered on any frequency from tick to daily. This dataset is created by QuantConnect processing raw tick data from OANDA. -

    -

    - CFD data does not include ask and bid sizes. + The Binance Crypto Price Data is for Cryptocurrency price and volume data points. The data covers 3,320 Cryptocurrency pairs, starts in July 2017, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Binance.

    - For more information about the CFD Data dataset, including CLI commands and pricing, see the - + For more information about the Binance Crypto Price Data dataset, including CLI commands and pricing, see the + dataset listing . @@ -167962,7 +169541,7 @@

    About the Provider

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. + Binance was founded by Changpeng Zhao in 2017 with the goal to "increase the freedom of money globally". Binance provides access to trading Crypto through spot markets and perpetual Futures. They serve clients with no minimum deposit when depositing Crypto. Binance also provides an NFT marketplace, a mining pool, and services to deposit Crypto coins in liquidity pools to earn rewards.

    @@ -167971,11 +169550,24 @@

    Getting Started

    - The following snippet demonstrates how to request data from the CFD dataset: + The following snippet demonstrates how to request data from the Binance Crypto Price dataset:

    -
    self.xauusd = self.add_cfd("XAUUSD", Resolution.DAILY).symbol
    -
    _symbol = AddCfd("XAUUSD", Resolution.Daily).Symbol;
    +
    # Binance accepts both Cash and Margin account types only.
    +self.set_brokerage_model(BrokerageName.BINANCE, AccountType.CASH)
    +#self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    +
    +self.btcbusd = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE).symbol
    +
    +self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
    +
    +
    // Binance accepts both Cash and Margin account types only.
    +SetBrokerageModel(BrokerageName.Binance, AccountType.Cash);
    +//SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    +
    +_symbol = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance).Symbol;
    +
    +_universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
    @@ -168003,7 +169595,7 @@

    Data Summary

    Start Date - Mixed, earliest starts May 2002 + July 2017 @@ -168011,7 +169603,7 @@

    Data Summary

    Asset Coverage - 51 Contracts + 3,320 Currency Pairs @@ -168027,7 +169619,7 @@

    Data Summary

    Resolution - Tick, Second, Minute, Hour, & Daily + Tick, Second, Minute, Hourly, & Daily @@ -168035,7 +169627,7 @@

    Data Summary

    Timezone - Mixed, in which the contract is listed* + UTC @@ -168043,23 +169635,13 @@

    Data Summary

    Market Hours - + Always Open - , except from Friday 5 PM EST to Sunday 5 PM EST. -
    - Index CFDs depends on the underlying market hour* -

    - * E.g.: - - DE30EUR - - tracks DAX30 Index, which is listed in Europe/Berlin timezone. -

    @@ -168067,53 +169649,57 @@

    Requesting Data

    - To add CFD data to your algorithm, call the + To add Binance Crypto Price data to your algorithm, call the - AddCfd + AddCrypto - add_cfd + add_crypto - method. Save a reference to the CFD + method. Save a reference to the Crypto Symbol so you can access the data later in your algorithm.

    -
    class CfdAlgorithm (QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_account_currency('EUR');
    +   
    class CoinAPIDataAlgorithm(QCAlgorithm):
     
    -        self.set_start_date(2019, 2, 20)
    -        self.set_end_date(2019, 2, 21)
    -        self.set_cash('EUR', 100000)
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
     
    -        self.de30eur = self.add_cfd('DE30EUR').symbol
    +        # Set Account Currency to Binance Stable Coin for USD
    +        self.set_account_currency("BUSD")
    +        self.set_cash(100000)
     
    -        self.set_benchmark(self.de30eur)
    -
    -
    public class CfdAlgorithm : QCAlgorithm
    +        # Binance accepts both Cash and Margin account types.
    +        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    +        
    +        self.btcbusd = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE).symbol
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
     {
         private Symbol _symbol;
    -
    +    
         public override void Initialize()
         {
    -        SetAccountCurrency("EUR");
    -
    -        SetStartDate(2019, 2, 20);
    -        SetEndDate(2019, 2, 21);
    -        SetCash("EUR", 100000);
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
     
    -        _symbol = AddCfd("DE30EUR").Symbol;
    +        // Set Account Currency to Binance Stable Coin for USD
    +        SetAccountCurrency("BUSD");
    +        SetCash(100000);
     
    -        SetBenchmark(_symbol);
    +        // Binance accepts both Cash and Margin account types.
    +        SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    +        
    +        _symbol = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance).Symbol;
         }
     }

    - For more information about creating CFD subscriptions, see - + For more information about creating Crypto subscriptions, see + Requesting Data . @@ -168125,7 +169711,14 @@

    Accessing Data

    - To get the current CFD data, index the + To get the current Binance Crypto Price data, index the + + Bars + + + bars + + , QuoteBars @@ -168145,11 +169738,15 @@

    Accessing Data

    Slice
    - with the CFD + with the Crypto Symbol - . Slice objects deliver unique events to your algorithm as they happen, but the + . + + Slice + + objects deliver unique events to your algorithm as they happen, but the Slice @@ -168161,16 +169758,26 @@

    Accessing Data

    def on_data(self, slice: Slice) -> None:
    -    if self.de30eur in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.de30eur]
    -        self.log(f"{self.de30eur} bid at {slice.time}: {quote_bar.bid.close}")
    +    if self.btcbusd in slice.bars:
    +        trade_bar = slice.bars[self.btcbusd]
    +        self.log(f"{self.btcbusd} close at {slice.time}: {trade_bar.close}")
     
    -    if self.de30eur in slice.ticks:
    -        ticks = slice.ticks[self.de30eur]
    +    if self.btcbusd in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.btcbusd]
    +        self.log(f"{self.btcbusd} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    if self.btcbusd in slice.ticks:
    +        ticks = slice.ticks[self.btcbusd]
             for tick in ticks:
    -            self.log(f"{self.de30eur} price at {slice.time}: {tick.price}")
    + self.log(f"{self.btcbusd} price at {slice.time}: {tick.price}")
    public override void OnData(Slice slice)
     {
    +    if (slice.Bars.ContainsKey(_symbol))
    +    {
    +        var tradeBar = slice.Bars[_symbol];
    +        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
         if (slice.QuoteBars.ContainsKey(_symbol))
         {
             var quoteBar = slice.QuoteBars[_symbol];
    @@ -168197,6 +169804,9 @@ 

    Accessing Data

    def on_data(self, slice: Slice) -> None:
    +    for symbol, trade_bar in slice.bars.items():
    +        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    +
         for symbol, quote_bar in slice.quote_bars.items():
             self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
     
    @@ -168205,6 +169815,13 @@ 

    Accessing Data

    self.log(f"{symbol} price at {slice.time}: {tick.price}")
    public override void OnData(Slice slice)
     {
    +    foreach (var kvp in slice.Bars)
    +    {
    +        var symbol = kvp.Key;
    +        var tradeBar = kvp.Value;
    +        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
         foreach (var kvp in slice.QuoteBars)
         {
             var symbol = kvp.Key;
    @@ -168225,8 +169842,8 @@ 

    Accessing Data

    - For more information about accessing CFD data, see - + For more information about accessing Crypto data, see + Handling Data . @@ -168238,14 +169855,14 @@

    Historical Data

    - To get historical CFD data, call the + To get historical Binance Crypto Price data, call the History history - method with the CFD + method with the Crypto Symbol @@ -168253,14 +169870,20 @@

    Historical Data

    # DataFrame
    -history_df = self.history(self.de30eur, 100, Resolution.MINUTE)
    +history_df = self.history(self.btcbusd, 100, Resolution.DAILY)
    +
    +# TradeBar objects
    +history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE)
     
     # QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.de30eur, 100, Resolution.MINUTE)
    +history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE)
     
     # Tick objects
    -history_ticks = self.history[Tick](self.de30eur, timedelta(seconds=10), Resolution.TICK)
    -
    // QuoteBar objects 
    +history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK)
    +
    // TradeBar objects 
    +var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    +
    +// QuoteBar objects 
     var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
     
     // Tick objects 
    @@ -168276,11 +169899,169 @@ 

    Historical Data

    -

    Remove Subscriptions

    +

    Universe Selection

    - To remove a CFD subscription, call the + To select a dynamic universe of Binance Crypto pairs, call the + + AddUniverse + + + add_universe + + method with a + + CryptoUniverse + + object. A + + Crypto universe + + uses a selection function to select Crypto pairs based on their OHLCV and dollar volume of the previous day as of midnight Coordinated Universal Time (UTC). +

    +
    +
    def initialize(self) -> None:
    +    self.universe_settings.asynchronous = True
    +    self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    +    self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
    +
    +def universe_selection_filter(self, universe_day):
    +    return [c.symbol for c in universe_day if c.volume >= 100 and c.volume_in_usd > 10000]
    +
    using QuantConnect.Data.UniverseSelection;
    +
    +public override void Initialize()
    +{
    +    UniverseSettings.Asynchronous = true;
    +    SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    +    _universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
    +}
    +
    +private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +{
    +    return from c in universeDay
    +           where c.Volume >= 100m && c.VolumeInUsd > 10000m
    +           select c.Symbol;
    +}
    +
    +

    + For more information about universe settings, see + + Settings + + . +

    + + + +

    Universe History

    + + +

    + You can get historical universe data in an algorithm and in the Research Environment. +

    +

    + Historical Universe Data in Algorithms +

    +

    + To get historical universe data in an algorithm, call the + + History + + + history + + method with the + + Universe + + object, and the lookback period. If there is no data in the period you request, the history result is empty. +

    +
    +
    var history = History(_universe, 30, Resolution.Daily);
    +foreach (var universeDay in history)
    +{
    +    foreach (CryptoUniverse universeItem in universeDay)
    +    {
    +        Log($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    +    }
    +}
    +
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    +history_df = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
    +
    +# Series example where the values are lists of CryptoUniverse objects: 
    +history = self.history(self._universe, 30, Resolution.DAILY)
    +for (univere_symbol, time), universe_day in history.items():
    +    for universe_item in universe_day:
    +        self.log(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    +
    +

    + Historical Universe Data in Research +

    +

    + To get historical universe data in research, call the + + UniverseHistory + + + universe_history + + method with the + + Universe + + object, and the lookback period. The + + UniverseHistory + + + universe_history + + returns the filtered universe. If there is no data in the period you request, the history result is empty. +

    +
    +
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var universeDay in universeHistory)
    +{
    +    foreach (CryptoUniverse universeItem in universeDay)
    +    {
    +        Console.WriteLine($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    +    }
    +}
    +
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    +history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    +
    +# Series example where the values are lists of CryptoUniverse objects: 
    +universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (univere_symbol, time), universe_day in universe_history.items():
    +    for universe_item in universe_day:
    +        print(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    +
    +

    + You can call the + + History + + + history + + method in Research. +

    + + + +

    Remove Subcriptions

    + + +

    + To unsubscribe from a Crypto pair that you added with the + + AddCrypto + + + add_crypto + + method, call the RemoveSecurity @@ -168290,7 +170071,7 @@

    Remove Subscriptions

    method.

    -
    self.remove_security(self.de30eur)
    +
    self.remove_security(self.btcbusd)
    RemoveSecurity(_symbol);

    @@ -168301,7 +170082,11 @@

    Remove Subscriptions

    remove_security - method cancels your open orders for the security and liquidates your holdings. + method cancels your open orders for the security and liquidates your holdings in the + + virtual pair + + .

    @@ -168309,46332 +170094,14080 @@

    Remove Subscriptions

    Supported Assets

    -

    - The following table shows the available contracts: -

    + The following table shows the available Cryptocurrency pairs:
    + + + - - -
    - - - -

    Example Applications

    - - -

    - The CFD price data enables you to trade CFD assets in your algorithm. Examples include the following strategies: -

    -
      -
    • - Exploring the daily worldwide news cycles with CFDs that track international indices. -
    • -
    • - Trading price movements of commodities with no delivery of physical goods. For example, pairs trading between gold and silver, corn and wheat, brent and crude oil, etc. -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm implements a pairs trading strategy using Gold and Silver CFDs, XAUUSD and XAGUSD, respectively. When the spread is higher than one standard deviation above its mean, the algorithm buys the spread (buy XAUUSD and sell XAGUSD). When the spread is lower than one standard deviation below its mean, it sells the spread (buy XAGUSD and sell XAUUSD). -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class SMAPairsTrading(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -
    -        # Request gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    -        self.add_cfd('XAUUSD', Resolution.HOUR)
    -        self.add_cfd('XAGUSD', Resolution.HOUR)
    -
    -        # Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    -        self.pair = [ ]
    -        self.spread_mean = SimpleMovingAverage(500)
    -        self.spread_std = StandardDeviation(500)
    -        
    -    def on_data(self, slice: Slice) -> None:
    -        # Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    -        spread = self.pair[1].price - self.pair[0].price
    -        self.spread_mean.update(self.time, spread)
    -        self.spread_std.update(self.time, spread) 
    -        
    -        spread_mean = self.spread_mean.current.value
    -        upperthreshold = spread_mean  + self.spread_std.current.value
    -        lowerthreshold = spread_mean  - self.spread_std.current.value
    -
    -        # If the spread is higher than upper threshold, bet their spread series will revert to mean
    -        if spread > upperthreshold:
    -            self.set_holdings(self.pair[0].symbol, 1)
    -            self.set_holdings(self.pair[1].symbol, -1)
    -        elif spread < lowerthreshold:
    -            self.set_holdings(self.pair[0].symbol, -1)
    -            self.set_holdings(self.pair[1].symbol, 1)
    -        # Close positions if mean reverted
    -        elif (self.portfolio[self.pair[0].symbol].quantity > 0 and spread < spread_mean)\
    -        or (self.portfolio[self.pair[0].symbol].quantity < 0 and spread > spread_mean):
    -            self.liquidate()
    -    
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        self.pair = [x for x in changes.added_securities]
    -        
    -        #1. Call for 500 bars of history data for each symbol in the pair and save to the variable history
    -        history = self.history([x.symbol for x in self.pair], 500)
    -        #2. Unstack the Pandas data frame to reduce it to the history close price
    -        history = history.close.unstack(level=0)
    -        #3. Iterate through the history tuple and update the mean and standard deviation with historical data 
    -        for tuple in history.itertuples():
    -            self.spread_mean.update(tuple[0], tuple[2]-tuple[1])
    -            self.spread_std.update(tuple[0], tuple[2]-tuple[1])
    -
    -
    public class GoldSilverPairsTradingAlgorithm : QCAlgorithm
    -{
    -    // Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    -    private SimpleMovingAverage _spreadMean = new SimpleMovingAverage(500);
    -    private StandardDeviation _spreadStd = new StandardDeviation(500);
    -    private Security[] _pair = new Security[2];
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);  
    -
    -        // Request gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    -        AddCfd("XAUUSD", Resolution.Hour);
    -        AddCfd("XAGUSD", Resolution.Hour);
    -    }
    -
    -    public override void OnData(Slice slice) 
    -    {
    -        // Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    -        var spread = _pair[1].Price - _pair[0].Price;
    -        _spreadMean.Update(Time, spread);
    -        _spreadStd.Update(Time, spread);
    -        
    -        var upperthreshold = _spreadMean + _spreadStd;
    -        var lowerthreshold = _spreadMean - _spreadStd;
    -        
    -        // If the spread is higher than upper threshold, bet their spread series will revert to mean
    -        if (spread > upperthreshold)
    -        {
    -            SetHoldings(_pair[0].Symbol, 1);
    -            SetHoldings(_pair[1].Symbol, -1);
    -        }
    -        else if (spread < lowerthreshold)
    -        {
    -            SetHoldings(_pair[0].Symbol, -1);
    -            SetHoldings(_pair[1].Symbol, 1);
    -        }
    -        // Close positions if mean reverted
    -        else if ((Portfolio[_pair[0].Symbol].Quantity > 0m && spread < _spreadMean)
    -        || (Portfolio[_pair[0].Symbol].Quantity < 0m && spread > _spreadMean))
    -        {
    -            Liquidate();
    -        }
    -    }
    -    
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {    
    -        _pair = changes.AddedSecurities.ToArray();
    -        
    -        //1. Call for 500 days of history data for each symbol in the pair and save to the variable history
    -        var history = History(_pair.Select(x => x.Symbol), 500);
    -        
    -        //2. Iterate through the history tuple and update the mean and standard deviation with historical data 
    -        foreach(var slice in history)
    -        {
    -            var spread = slice[_pair[1].Symbol].Close - slice[_pair[0].Symbol].Close;
    -            _spreadMean.Update(slice.Time, spread);
    -            _spreadStd.Update(slice.Time, spread);
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm implements a pairs trading strategy using Gold and Silver CFDs, XAUUSD and XAGUSD, respectively. When the spread is higher than one standard deviation above its mean, the algorithm buys the spread (buy XAUUSD and sell XAGUSD). When the spread is lower than one standard deviation below its mean, it sells the spread (buy XAGUSD and sell XAUUSD). -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class GoldSilverPairsTradingAlgorithm (QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        
    -        self.universe_settings.resolution = Resolution.HOUR
    -        # Custom universe contains only gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    -        self.set_universe_selection(ManualUniverseSelectionModel
    -        (
    -            [ Symbol.create(x, SecurityType.CFD, Market.OANDA) for x in ["XAUUSD", "XAGUSD"] ]
    -        ))
    -        # Custom alpha model to emit trade insights based on the gold-sliver price spread
    -        self.add_alpha(PairsTradingAlphaModel())
    -        # Equal weighting trades assuming the spread is cointegrated by 1:1 ratio
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -
    -class PairsTradingAlphaModel(AlphaModel):
    -
    -    def __init__(self) -> None:
    -        # Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    -        self.pair = [ ]
    -        self.spread_mean = SimpleMovingAverage(500)
    -        self.spread_std = StandardDeviation(500)
    -        # Assume efficient mean reversal happens within 2 hours
    -        self.period = timedelta(hours=2)
    -        
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        # Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    -        spread = self.pair[1].price - self.pair[0].price
    -        self.spread_mean.update(algorithm.time, spread)
    -        self.spread_std.update(algorithm.time, spread) 
    -        
    -        upperthreshold = self.spread_mean.current.value + self.spread_std.current.value
    -        lowerthreshold = self.spread_mean.current.value - self.spread_std.current.value
    -
    -        # If the spread is higher than upper threshold, bet their spread series will revert to mean
    -        if spread > upperthreshold:
    -            return Insight.group(
    -                [
    -                    Insight.price(self.pair[0].symbol, self.period, InsightDirection.UP),
    -                    Insight.price(self.pair[1].symbol, self.period, InsightDirection.DOWN)
    -                ])
    -        elif spread < lowerthreshold:
    -            return Insight.group(
    -                [
    -                    Insight.price(self.pair[0].symbol, self.period, InsightDirection.DOWN),
    -                    Insight.price(self.pair[1].symbol, self.period, InsightDirection.UP)
    -                ])
    -
    -        return []
    -    
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        self.pair = [x for x in changes.added_securities]
    -        
    -        #1. Call for 500 bars of history data for each symbol in the pair and save to the variable history
    -        history = algorithm.history([x.symbol for x in self.pair], 500)
    -        #2. Unstack the Pandas data frame to reduce it to the history close price
    -        history = history.close.unstack(level=0)
    -        #3. Iterate through the history tuple and update the mean and standard deviation with historical data 
    -        for tuple in history.itertuples():
    -            self.spread_mean.update(tuple[0], tuple[2]-tuple[1])
    -            self.spread_std.update(tuple[0], tuple[2]-tuple[1])
    -
    -
    public class GoldSilverPairsTradingAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);  
    -
    -        UniverseSettings.Resolution = Resolution.Hour;
    -        // Custom universe contains only gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    -        SetUniverseSelection(new ManualUniverseSelectionModel
    -        (
    -            new [] {"XAUUSD", "XAGUSD"}
    -                .Select(x => QuantConnect.Symbol.Create(x, SecurityType.Cfd, Market.Oanda))
    -        ));
    -        // Custom alpha model to emit trade insights based on the gold-sliver price spread
    -        AddAlpha(new PairsTradingAlphaModel());
    -        // Equal weighting trades assuming the spread is cointegrated by 1:1 ratio
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel()); 
    -    }
    -}
    -
    -public partial class PairsTradingAlphaModel : AlphaModel
    -{
    -    // Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    -    private SimpleMovingAverage _spreadMean = new SimpleMovingAverage(500);
    -    private StandardDeviation _spreadStd = new StandardDeviation(500);
    -    // Assume efficient mean reversal happens within 2 hours
    -    private TimeSpan _period = TimeSpan.FromHours(2);
    -    private Security[] _pair = new Security[2];
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice) 
    -    {
    -        // Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    -        var spread = _pair[1].Price - _pair[0].Price;
    -        _spreadMean.Update(algorithm.Time, spread);
    -        _spreadStd.Update(algorithm.Time, spread);
    -        
    -        var upperthreshold = _spreadMean + _spreadStd;
    -        var lowerthreshold = _spreadMean - _spreadStd;
    -
    -        // If the spread is higher than upper threshold, bet their spread series will revert to mean
    -        if (spread > upperthreshold)
    -        {
    -            return Insight.Group( 
    -                Insight.Price(_pair[0].Symbol, _period, InsightDirection.Up),
    -                Insight.Price(_pair[1].Symbol, _period, InsightDirection.Down)
    -            );
    -        }
    -        else if (spread < lowerthreshold)
    -        {
    -            return Insight.Group( 
    -                Insight.Price(_pair[0].Symbol, _period, InsightDirection.Down), 
    -                Insight.Price(_pair[1].Symbol, _period, InsightDirection.Up) 
    -            );
    -        }
    -
    -        return Enumerable.Empty<Insight>();
    -    }
    -    
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {    
    -        _pair = changes.AddedSecurities.ToArray();
    -        
    -        //1. Call for 500 days of history data for each symbol in the pair and save to the variable history
    -        var history = algorithm.History(_pair.Select(x => x.Symbol), 500);
    -        
    -        //2. Iterate through the history tuple and update the mean and standard deviation with historical data 
    -        foreach (var slice in history)
    -        {
    -            var spread = slice[_pair[1].Symbol].Close - slice[_pair[0].Symbol].Close;
    -            _spreadMean.Update(slice.Time, spread);
    -            _spreadStd.Update(slice.Time, spread);
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The CFD dataset provides - - QuoteBar - - and - - Tick - - objects. -

    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - Tick Attributes -

    -

    - - Tick - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    Cash Indices

    -
    -
    -

    Introduction

    - - -

    - The Cash Indices dataset by QuantConnect covers 125 US Indices and 3 International indices. The data starts on various dates from January 1998 and is delivered on any frequency from minute to daily. -

    -

    - For more information about the Cash Indices dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Live Data

    - - -

    - The Cash Indices dataset does not provide a live data feed. To receive Cash Indices' data in your live algorithm, you must add a brokerage or a third-party data provider (see - - Cloud Platform > Datasets - - ). -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the Cash Indices dataset: -

    -
    -
    self.vix = self.add_index("VIX", Resolution.DAILY).symbol
    -
    _symbol = AddIndex("VIX", Resolution.Daily).Symbol;
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 1998 -
    - Coverage - - 125 US Indices and 3 International indices (HSI, SX5E and N225) -
    - Data Density - - Dense -
    - Resolution - - Minute, Hour, & Daily -
    - Timezone - - New York for US Indices, refer to - - Supported Assets - - below for International indices -
    - Market Hours - - - Regular Only - -
    - - - -

    Requesting Data

    - - -

    - To add Cash Indices data to your algorithm, call the - - AddIndex - - - add_index - - method. Save a reference to the Index - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class CashIndexAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000)
    -
    -        self.vix = self.add_index("VIX").symbol
    -
    -
    public class CashIndexAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        
    -        _symbol = AddIndex("VIX").Symbol;
    -    }
    -}
    -
    -

    - For more information about creating Index subscriptions, see - - Requesting Data - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current Cash Indices data, index the - - Bars - - - bars - - property of the current - - - Slice - - - with the Index - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    if self.vix in slice.bars:
    -        trade_bar = slice.bars[self.vix]
    -        self.log(f"{self.vix} close at {slice.time}: {trade_bar.close}")
    -
    public override void OnData(Slice slice)
    -{
    -    if (slice.Bars.ContainsKey(_symbol))
    -    {
    -        var tradeBar = slice.Bars[_symbol];
    -        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -}
    -
    -
    -

    - You can also iterate through all of the data objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for symbol, trade_bar in slice.bars.items():
    -        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.Bars)
    -    {
    -        var symbol = kvp.Key;
    -        var tradeBar = kvp.Value;
    -        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -}
    -
    -
    -

    - For more information about accessing Index data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - To get historical Cash Indices data, call the - - History - - - history - - method with the Index - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.vix, 100, Resolution.DAILY)
    -
    -# TradeBar objects
    -history_bars = self.history[TradeBar](self.vix, 100, Resolution.DAILY)
    -
    // TradeBar objects
    -var historyBars = History(_symbol, 100, Resolution.Daily);
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Remove Subscriptions

    - - -

    - To remove an Index subscription, call the - - RemoveSecurity - - - remove_security - - method. -

    -
    -
    self.remove_security(self.vix)
    -
    RemoveSecurity(_symbol);
    -
    - - - -

    Supported Indices

    - - -

    - US Cash Indices -

    -

    - The following table shows the US Cash indices with Index Option support: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Ticker - - Index - - Expiry - - Start Date -
    - VIX - - S&P500 - - 30 Days - - Jul 2003 -
    - SPX - - S&P500 - - - - - Jan 1998 -
    - NDX - - NASDAQ-100 - - - - - Jan 1998 -
    - RUT - - Russell 2000 - - - - - Jan 2008 -
    -
    - VIX - CBOE Volatility Index -
    -

    - The Cboe Volatility Index (VIX) is a real-time index that represents the market's expectations for the relative strength of near-term price changes of the S&P 500 Index (SPX). Because it's derived from the prices of SPX index Options with near-term expiration dates, it generates a 30-day forward projection of volatility. Volatility, or how fast prices change, is often seen as a way to gauge market sentiment, and in particular, the degree of fear among market participants. -

    -
    - SPX - S&P 500 Index -
    -

    - The S&P 500 Index, or the Standard & Poor's 500 Index, is a market-capitalization-weighted index of the 500 largest publicly-traded companies in the U.S. It is not an exact list of the top 500 U.S. companies by market capitalization because there are other criteria included in the index. The index is widely regarded as the best gauge of large-cap U.S. Equities. -

    -
    - NDX - Nasdaq 100 Index -
    -

    - The Nasdaq-100 Index is a modified market-capitalization-weighted index composed of securities issued by 100 of the largest non-financial companies listed on the Nasdaq Stock Market (Nasdaq). The index includes companies from various industries except for the financial industry, like commercial and investment banks. These non-financial sectors include retail, biotechnology, industrial, technology, health care, and others. -

    -
    - RUT - Russell 2000 Index -
    -

    - The Russell 2000 Index is a small-cap U.S. stock market index that makes up the smallest 2,000 stocks in the Russell Index. It was started by the Frank Russell Company in 1984. The index is maintained by FTSE Russell, a subsidiary of the London Stock Exchange Group (LSEG). -

    -
    - All US Cash Indices -
    - The following table shows all US Cash indices: -
    - - - - - - - + - - -
    -

    - International Cash Indices -

    -

    - The following table shows the International Cash indices: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Ticker - - Index - - Start Date - - Time Zone - - Currency -
    - HSI - - Hang Seng Index - - Dec 2006 - - Asia/Hong Kong - - HKD -
    - SX5E - - EUREX EU STOXX - - Jul 2003 - - Europe/Berlin - - EUR -
    - N225 - - Nikkei 225 - - Jul 2003 - - Asia/Tokyo - - JPY -
    - - - -

    Example Applications

    - - -

    - The Cash Indices enable you to incorporate popular indices into your trading algorithms. Examples include the following use cases: -

    -
      -
    • - Exploring the difference between the Index and the ETF that tracks it -
    • -
    • - Using these indices as the underlying asset fo Index Options strategies -
    • -
    • - Understanding the stock market's level of expected forward-looking volatility, also known as the "fear index". When the VIX starts moving higher, it tells you that traders are getting nervous. When the VIX starts moving lower, it tells you that traders are gaining confidence. -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm tracks the 80-day EMA and 200-day EMA of SPX. When the short EMA crosses above the long EMA, the algorithm buys SPY. Otherwise, it holds cash. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class IndexDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -
    -        # Request SPY data as a trading vehicle for SPX
    -        self.spy = self.add_equity("SPY").symbol
    -
    -        # Request SPX data for trade signal generation
    -        spx = self.add_index("SPX").symbol
    -
    -        # Create short and long-term EMA indicators for trend estimation to trade
    -        self.ema_fast = self.EMA(spx, 80, Resolution.DAILY)
    -        self.ema_slow = self.EMA(spx, 200, Resolution.DAILY)
    -        self.set_warm_up(200, Resolution.DAILY)
    -
    -        # Historical data
    -        history = self.history(spx, 60, Resolution.DAILY)
    -        self.debug(f'We got {len(history.index)} items from our history request')
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Trade signals required indicators to be ready
    -        if self.is_warming_up or not self.ema_slow.is_ready:
    -            return
    -
    -        # If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    -        if not self.portfolio.invested and self.ema_fast > self.ema_slow:
    -            self.set_holdings(self.spy, 1)
    -        # If it is the reverse, it indicates a downtrend, and we liquidate any position
    -        elif self.ema_fast < self.ema_slow:
    -            self.liquidate()
    -
    -
    public class IndexDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _spy;
    -    private ExponentialMovingAverage _emaSlow, _emaFast;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -
    -        // Request SPY data as trading vehicle for SPX
    -        _spy = AddEquity("SPY").Symbol;
    -
    -        // Request SPX data for trade signal generation
    -        var spx = AddIndex("SPX").Symbol;
    -
    -        // Create short and long-term EMA indicators for trend estimation to trade
    -        _emaFast = EMA(spx, 80, Resolution.Daily);
    -        _emaSlow = EMA(spx, 200, Resolution.Daily);
    -        SetWarmUp(200, Resolution.Daily);
    -
    -        // Historical data
    -        var history = History(spx, 60, Resolution.Daily);
    -        Debug($"We got {history.Count()} items from our history request");
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Trade signals required indicators to be ready
    -        if (IsWarmingUp || !_emaSlow.IsReady)
    -        {
    -            return;
    -        }
    -
    -        // If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    -        if (!Portfolio.Invested && _emaFast > _emaSlow)
    -        {
    -            SetHoldings(_spy, 1);
    -        }
    -        // If it is the reverse, it indicates a downtrend, and we liquidate any position
    -        else if (_emaFast < _emaSlow)
    -        {
    -            Liquidate();
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm tracks the 80-day EMA and 200-day EMA of SPX. When the short EMA crosses above the long EMA, the algorithm buys SPY. Otherwise, it holds cash. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class IndexDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -
    -        # Universe contains only SPY as a trading vehicle for SPX
    -        self.set_universe_selection(ManualUniverseSelectionModel
    -        (
    -            Symbol.create("SPY", SecurityType.EQUITY, Market.USA)
    -        ))
    -        # Custom alpha model that emits insights based on SPX index data
    -        self.set_alpha(SpxEmaCrossAlphaModel(self))
    -        # Equally investing can dissipate non-systematic risky event's capital concentration risk evenly
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(Expiry.END_OF_MONTH))
    -    
    -
    -class SpxEmaCrossAlphaModel(AlphaModel):
    -
    -    def __init__(self, algorithm: QCAlgorithm) -> None:
    -        # Request SPX data for trade signal generation
    -        spx = algorithm.add_index("SPX").symbol
    -
    -        # Create short and long-term EMA indicators for trend estimation to trade
    -        self.ema_fast = algorithm.EMA(spx, 80, Resolution.DAILY)
    -        self.ema_slow = algorithm.EMA(spx, 200, Resolution.DAILY)
    -        algorithm.set_warm_up(200, Resolution.DAILY)
    -
    -        # Historical data
    -        history = algorithm.history(spx, 60, Resolution.DAILY)
    -        algorithm.debug(f'We got {len(history.index)} items from our history request')
    -    
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        # Trade signals required indicators to be ready
    -        if algorithm.is_warming_up or not self.ema_slow.is_ready:
    -            return []
    -
    -        # If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    -        if not algorithm.portfolio.invested and self.ema_fast > self.ema_slow:
    -            return [Insight.price(kvp.key, Expiry.END_OF_MONTH, InsightDirection.UP)
    -                for kvp in algorithm.active_securities if kvp.value.is_tradable]
    -        # If it is the reverse, it indicates downtrend, and we liquidate any position
    -        elif self.ema_fast < self.ema_slow:
    -            return [Insight.price(kvp.key, Expiry.END_OF_MONTH, InsightDirection.FLAT)
    -                for kvp in algorithm.active_securities if kvp.value.is_tradable]
    -            
    -        return []
    -
    -
    public class IndexDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -
    -        // Universe contains only SPY as a trading vehicle for SPX
    -        SetUniverseSelection(new ManualUniverseSelectionModel
    -        (
    -            QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)
    -        ));
    -        // Custom alpha model that emits insights based on SPX index data
    -        SetAlpha(new SpxEmaCrossAlphaModel(this));
    -        // Equally invests can dissipate non-systematic risky event's capital concentration risk evenly
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(Expiry.EndOfMonth));
    -    }
    -}
    -
    -public class SpxEmaCrossAlphaModel : AlphaModel
    -{
    -    private ExponentialMovingAverage _emaSlow, _emaFast;
    -
    -    public SpxEmaCrossAlphaModel(QCAlgorithm algorithm)
    -    {
    -        // Request SPX data for trade signal generation
    -        var spx = algorithm.AddIndex("SPX").Symbol;
    -
    -        // Create short and long-term EMA indicators for trend estimation to trade
    -        _emaFast = algorithm.EMA(spx, 80, Resolution.Daily);
    -        _emaSlow = algorithm.EMA(spx, 200, Resolution.Daily);
    -        algorithm.SetWarmUp(200, Resolution.Daily);
    -
    -        // Historical data
    -        var history = algorithm.History(spx, 60, Resolution.Daily);
    -        algorithm.Debug($"We got {history.Count()} items from our history request");
    -    }
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        // Trade signals required indicators to be ready
    -        if (algorithm.IsWarmingUp || !_emaSlow.IsReady)
    -        {
    -            return Enumerable.Empty<Insight>();
    -        }
    -
    -        // If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    -        if (!algorithm.Portfolio.Invested && _emaFast > _emaSlow)
    -        {
    -            return algorithm.ActiveSecurities
    -                .Where(kvp => kvp.Value.IsTradable)
    -                .Select(kvp => Insight.Price(kvp.Key, Expiry.EndOfMonth, InsightDirection.Up));
    -        }
    -        // If it is the reverse, it indicates downtrend, and we liquidate any position
    -        else if (_emaFast < _emaSlow)
    -        {
    -            return algorithm.ActiveSecurities
    -                .Where(kvp => kvp.Value.IsTradable)
    -                .Select(kvp => Insight.Price(kvp.Key, Expiry.EndOfMonth, InsightDirection.Flat));
    -        }
    -
    -        return Enumerable.Empty<Insight>();
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The Cash Indices dataset provides - - TradeBar - - object. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    FOREX Data

    -
    -
    -

    Introduction

    - - -

    - The FOREX Data by QuantConnect serves 71 - - foreign exchange - - (FOREX) pairs, starts on various dates from January 2007, and is delivered on any frequency from tick to daily. This dataset is created by QuantConnect processing raw tick data from OANDA. -

    -

    - FOREX data does not include ask and bid sizes. -

    -

    - For more information about the FOREX Data dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the FOREX dataset: -

    -
    -
    self.eurusd = self.add_forex("EURUSD", Resolution.DAILY).symbol
    -
    _symbol = AddForex("EURUSD", Resolution.Daily).Symbol;
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2007 -
    - Asset Coverage - - 71 Currency pairs -
    - Data Density - - Dense -
    - Resolution - - Tick, Second, Minute, Hour, & Daily -
    - Timezone - - UTC -
    - Market Hours - - - Always Open - - , except from Friday 5 PM EST to Sunday 5 PM EST -
    - - - -

    Requesting Data

    - - -

    - To add FOREX data to your algorithm, call the - - AddForex - - - add_forex - - method. Save a reference to the Forex - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    -class ForexAlgorithm (QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2019, 2, 20)
    -        self.set_end_date(2019, 2, 21)
    -        self.set_cash(100000)
    -
    -        self.eurusd = self.add_forex('EURUSD', Resolution.MINUTE).symbol
    -
    -        self.set_benchmark(self.eurusd)
    -
    -
    public class ForexAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2019, 2, 20);
    -        SetEndDate(2019, 2, 21);
    -        SetCash(100000);
    -
    -        _symbol = AddForex("EURUSD", Resolution.Minute).Symbol;
    -
    -        SetBenchmark(_symbol);
    -    }
    -}
    -
    -

    - For more information about creating Forex subscriptions, see - - Requesting Data - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current Forex data, index the - - QuoteBars - - - quote_bars - - , or - - Ticks - - - ticks - - properties of the current - - - Slice - - - with the Forex - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    if self.eurusd in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.eurusd]
    -        self.log(f"{self.eurusd} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    if self.eurusd in slice.ticks:
    -        ticks = slice.ticks[self.eurusd]
    -        for tick in ticks:
    -            self.log(f"{self.eurusd} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    if (slice.QuoteBars.ContainsKey(_symbol))
    -    {
    -        var quoteBar = slice.QuoteBars[_symbol];
    -        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    if (slice.Ticks.ContainsKey(_symbol))
    -    {
    -        var ticks = slice.Ticks[_symbol];
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - You can also iterate through all of the data objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for symbol, quote_bar in slice.quote_bars.items():
    -        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    for symbol, ticks in slice.ticks.items():
    -        for tick in ticks:
    -            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.QuoteBars)
    -    {
    -        var symbol = kvp.Key;
    -        var quoteBar = kvp.Value;
    -        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    foreach (var kvp in slice.Ticks)
    -    {
    -        var symbol = kvp.Key;
    -        var ticks = kvp.Value;
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - For more information about accessing Forex data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - To get historical Forex data, call the - - History - - - history - - method with the Forex - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.eurusd, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.eurusd, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -history_ticks = self.history[Tick](self.eurusd, timedelta(seconds=10), Resolution.TICK)
    -
    // QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    -
    -// Tick objects 
    -var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Remove Subscriptions

    - - -

    - To remove a Forex pair subscription, call the - - RemoveSecurity - - - remove_security - - method. -

    -
    -
    self.remove_security(self.eurusd)
    -
    RemoveSecurity(_symbol);
    -
    -

    - The - - RemoveSecurity - - - remove_security - - method cancels your open orders for the security and liquidates your holdings. -

    - - - -

    Supported Assets

    - - -

    - The following table shows the available Forex pairs: -

    -
    - - - + + + + + + - - - - - -
    - - - -

    Example Applications

    - - -

    - The FOREX price data enables you to trade currency pairs in the global market. Examples include the following strategies: -

    -
      -
    • - Exploring the impact that daily worldwide news cycles have on international currencies -
    • -
    • - Carry Trade: borrow from a lower interest currency pair to fund the purchase of a currency pair with a higher interest rate -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm implements a FOREX carry trade. It buys the FOREX pair of the country with the lowest interest rate and sells the FOREX pair of the country with the highest interest rate. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class ForexCarryTradeAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(25000)
    -        
    -        # We will use hard-coded interest rates for each base currency
    -        self.rates = {
    -            "USDAUD": 1.5,    # Australia
    -            "USDCAD": 0.5,    # Canada
    -            "USDCNY": 4.35,   # China
    -            "USDEUR": 0.0,    # Euro Area
    -            "USDINR": 6.5,    # India
    -            "USDJPY": -0.1,   # Japan
    -            "USDMXN": 4.25,   # Mexico
    -            "USDTRY": 7.5,    # Turkey
    -            "USDZAR": 7.0     # South Africa
    -        }
    -
    -        # Subscribe to forex data for trading
    -        for ticker in self.rates:
    -            self.add_forex(ticker, Resolution.DAILY)
    -
    -        # Use a month counter as variable to control rebalancing
    -        self.month = -1
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Monthly rebalance checker
    -        if self.month == self.time.month:
    -            return
    -        self.month = self.time.month
    -        
    -        # Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    -        sorted_rates = sorted(self.rates.items(), key = lambda x: x[1])
    -        self.set_holdings(sorted_rates[0][0], -0.5)
    -        self.set_holdings(sorted_rates[-1][0], 0.5)
    -
    -
    public class ForexCarryTradeAlgorithm : QCAlgorithm
    -{
    -    // Use a month counter as variable to control rebalancing
    -    private int _month = -1;
    -    private Dictionary<string, decimal> _rates;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(25000);
    -        
    -        // We will use hard-coded interest rates for each base currency
    -        _rates = new Dictionary<string, decimal>()
    -        {
    -            {"USDAUD", 1.5m},    // Australia
    -            {"USDCAD", 0.5m},    // Canada
    -            {"USDCNY", 4.35m},   // China
    -            {"USDEUR", 0.0m},    // Euro Area
    -            {"USDINR", 6.5m},    // India
    -            {"USDJPY", -0.1m},   // Japan
    -            {"USDMXN", 4.25m},   // Mexico
    -            {"USDTRY", 7.5m},    // Turkey
    -            {"USDZAR", 7.0m}     // South Africa
    -        };
    -
    -        // Subscribe to forex data for trading
    -        foreach (var ticker in _rates.Keys)
    -        {
    -            AddForex(ticker, Resolution.Daily);
    -        }
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Monthly rebalance checker
    -        if (_month == Time.Month) return;
    -        _month = Time.Month;
    -
    -        // Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    -        var sortedRates = (from kvp in _rates orderby kvp.Value ascending select kvp.Key).ToArray();
    -        SetHoldings(sortedRates[0], -0.5);
    -        SetHoldings(sortedRates[sortedRates.Length-1], 0.5);
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm implements a FOREX carry trade. It buys the FOREX pair of the country with the lowest interest rate and sells the FOREX pair of the country with the highest interest rate. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class ForexCarryTradeAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(25000)
    -        
    -        def to_symbol(ticker: str) -> Symbol:
    -            return Symbol.create(ticker, SecurityType.FOREX, Market.OANDA)
    -        
    -        # We will use hard-coded interest rates for each base currency
    -        rates = {
    -            to_symbol("USDAUD"): 1.5,    # Australia
    -            to_symbol("USDCAD"): 0.5,    # Canada
    -            to_symbol("USDCNY"): 4.35,   # China
    -            to_symbol("USDEUR"): 0.0,    # Euro Area
    -            to_symbol("USDINR"): 6.5,    # India
    -            to_symbol("USDJPY"): -0.1,   # Japan
    -            to_symbol("USDMXN"): 4.25,   # Mexico
    -            to_symbol("USDTRY"): 7.5,    # Turkey
    -            to_symbol("USDZAR"): 7.0     # South Africa
    -        }
    -        
    -        self.set_universe_selection(ManualUniverseSelectionModel(list(rates.keys())))
    -        # A custom alpha model to emit insight according to interest rate
    -        self.set_alpha(IntestRatesAlphaModel(rates))
    -        # Equal size to capitalize the monetary value of quote currency only based on interest rate difference
    -        # For dollar-neutral to save margin cost
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(Expiry.END_OF_MONTH))
    -
    -class IntestRatesAlphaModel(AlphaModel):
    -    def __init__(self, rates: float) -> None:
    -        self.rates = rates
    -        # Variable to control the rebalancing time
    -        self.month = -1
    -                
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        # Monthly rebalance
    -        if self.month == algorithm.time.month:
    -            return []
    -        self.month = algorithm.time.month
    -
    -        # # Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    -        sorted_rates = sorted(self.rates.items(), key = lambda x: x[1])
    -        return Insight.group(
    -            Insight.price(sorted_rates[0][0], Expiry.END_OF_MONTH, InsightDirection.UP),
    -            Insight.price(sorted_rates[-1][0], Expiry.END_OF_MONTH, InsightDirection.DOWN)
    -        )
    -
    -
    public class ForexCarryTradeAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(25000);
    -        
    -        Symbol toSymbol(string ticker)
    -        {
    -            return QuantConnect.Symbol.Create(ticker, SecurityType.Forex, Market.Oanda);
    -        }
    -        
    -        // We will use hard-coded interest rates for each base currency
    -        var rates = new Dictionary<Symbol, decimal>()
    -        {
    -            {toSymbol("USDAUD"), 1.5m},    // Australia
    -            {toSymbol("USDCAD"), 0.5m},    // Canada
    -            {toSymbol("USDCNY"), 4.35m},   // China
    -            {toSymbol("USDEUR"), 0.0m},    // Euro Area
    -            {toSymbol("USDINR"), 6.5m},    // India
    -            {toSymbol("USDJPY"), -0.1m},   // Japan
    -            {toSymbol("USDMXN"), 4.25m},   // Mexico
    -            {toSymbol("USDTRY"), 7.5m},    // Turkey
    -            {toSymbol("USDZAR"), 7.0m}     // South Africa
    -        };
    -
    -        SetUniverseSelection(new ManualUniverseSelectionModel(rates.Keys));
    -        // A custom alpha model to emit insight according to interest rate
    -        SetAlpha(new IntestRatesAlphaModel(rates));
    -        // Equal size to capitalize the monetary value of quote currency only based on interest rate difference
    -        // For dollar-neutral to save margin cost
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(Expiry.EndOfMonth));
    -    }
    -}
    -
    -public class IntestRatesAlphaModel : AlphaModel
    -{
    -    // Variable to control the rebalancing time
    -    private int _month = -1;
    -    private Dictionary<Symbol, decimal> _rates;
    -
    -    public IntestRatesAlphaModel(Dictionary<Symbol, decimal> rates)
    -    {
    -        _rates = rates;
    -    }
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        // Monthly rebalance
    -        if (_month == algorithm.Time.Month)
    -        {
    -            return Enumerable.Empty<Insight>();
    -        }
    -        _month = algorithm.Time.Month;
    -
    -        // Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    -        var sortedRates = (from kvp in _rates orderby kvp.Value ascending select kvp.Key).ToArray();
    -        
    -        return Insight.Group(
    -            Insight.Price(sortedRates[0], Expiry.EndOfMonth, InsightDirection.Up),
    -            Insight.Price(sortedRates[sortedRates.Length-1], Expiry.EndOfMonth, InsightDirection.Down)
    -        );
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The FOREX dataset provides - - QuoteBar - - and - - Tick - - objects. -

    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - Tick Attributes -

    -

    - - Tick - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    Fear and Greed

    -
    -
    -

    Introduction

    - - -

    - The Fear and Greed dataset by QuantConnect provides data points to quantify the degree of fear and greed in the US Equity market. The data starts in 2014 and is delivered on a daily frequency, delayed by two days. This dataset is created by aggregating seven indicators, including market volatility, stock market breadth, and put-call ratios. -

    -

    - For more information about the Fear and Greed dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the Fear and Greed dataset: -

    -
    -
    self._dataset_symbol = self.add_data(FearGreedIndex, 'FG').symbol
    -
    _datasetSymbol = AddData<FearGreedIndex>("FG").Symbol;
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - July 2014 -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - - New York -
    -

    - The latest daily data points are about two days since the VIX and SPX prices are inputs into the index and their latest daily prices are also two days old. New data is available at 9 AM EST. -

    - - - -

    Requesting Data

    - - -

    - To add Fear and Greed data to your algorithm, call the - - AddData<FearGreedIndex> - - - add_data - - method. Save a reference to the dataset - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class FearAndGreedDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2019, 1, 1)
    -        self.set_end_date(2020, 6, 1)
    -        self.set_cash(100000)
    -
    -        self._symbol = self.add_equity("SPY", Resolution.DAILY).symbol
    -        self._dataset_symbol = self.add_data(FearGreedIndex, "FG").symbol
    -
    public class FearAndGreedDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol, _datasetSymbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2019, 1, 1);
    -        SetEndDate(2020, 6, 1);
    -        SetCash(100000);
    -        _symbol = AddEquity("SPY", Resolution.Daily).Symbol;
    -        _datasetSymbol = AddData<FearGreedIndex>("FG").Symbol;
    -    }
    -}
    -
    - - - -

    Accessing Data

    - - -

    - To get the current Fear and Greed data, index the current - - - Slice - - - with the dataset - - Symbol - - . - - Slice - - objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your dataset at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    if slice.contains_key(self._dataset_symbol):
    -        data_point = slice[self._dataset_symbol]
    -        self.log(f"{self._dataset_symbol} value at {slice.time}: {data_point.value}")
    -
    public override void OnData(Slice slice)
    -{
    -    if (slice.ContainsKey(_datasetSymbol))
    -    {
    -        var dataPoint = slice[_datasetSymbol];
    -        Log($"{_datasetSymbol} value at {slice.Time}: {dataPoint.Value}");
    -    }
    -}
    -
    -
    - - - -

    Historical Data

    - - -

    - To get historical Fear and Greed data, call the - - History - - - history - - method with the dataset - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self._dataset_symbol, 100, Resolution.DAILY)
    -
    -# Dataset objects
    -history = self.history[FearGreedIndex](self._dataset_symbol, 100, Resolution.DAILY)
    -
    var history = History<FearGreedIndex>(_datasetSymbol, 100, Resolution.Daily);
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Remove Subscription

    - - -

    - To remove a subscription to the Fear and Greed dataset, call the - - RemoveSecurity - - - remove_security - - method. -

    -
    -
    self.remove_security(self._dataset_symbol)
    -
    RemoveSecurity(_datasetSymbol);
    -
    - - - -

    Example Applications

    - - -

    - The Fear and Greed dataset quantifies the degree of fear and greed in the US Equity market. Example use cases include the following strategies: -

    -
      -
    • - Accumulate long-term positions when the market is fearful (the index is low). -
    • -
    • - Short risky assets when the market is greedy. -
    • -
    • - Trade - - butterfly Option strategies - - based on the market volatility indicator. -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm buys SPY when the Fear and Greed index is less than 25 (extreme fear) and sells when it's above 75 (extreme greed). -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class FearAndGreedExampleAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -
    -        # Add the market index to trade.
    -        self._equity = self.add_equity('SPY', Resolution.DAILY)
    -        # Add the Fear and Greed dataset.
    -        self._dataset_symbol = self.add_data(FearGreedIndex, 'FG').symbol
    -    
    -    def on_data(self, data: Slice) -> None:
    -        # Wait until the Fear and Greed dataset has new data.
    -        if self._dataset_symbol not in data:
    -            return
    -        value = data[self._dataset_symbol].value
    -        # Buy when the market is fearful.
    -        if not self._equity.invested and value < 25:
    -            self.set_holdings(self._equity.symbol, 1)
    -        # Sell when the market is greedy.
    -        elif self._equity.invested and value > 75:
    -            self.liquidate()
    -
    public class FearAndGreedExampleAlgorithm : QCAlgorithm
    -{
    -    private Equity _equity;
    -    private Symbol _datasetSymbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -
    -        // Add the market index to trade.
    -        _equity = AddEquity("SPY", Resolution.Daily);
    -        // Add the Fear and Greed dataset.
    -        _datasetSymbol = AddData<FearGreedIndex>("FG").Symbol;
    -    }
    -
    -    public override void OnData(Slice data)
    -    {
    -        // Wait until the Fear and Greed dataset has new data
    -        if (!data.ContainsKey(_datasetSymbol))
    -        {
    -            return;
    -        }
    -        var value = data[_datasetSymbol].Value;
    -        // Buy when the market is fearful.
    -        if (!_equity.Invested && value < 25)
    -        {
    -            SetHoldings(_equity.Symbol, 1);
    -        }
    -        // Sell when the market is greedy.
    -        else if (_equity.Invested && value > 75)
    -        {
    -            Liquidate();
    -        }
    -    }
    -}
    -
    -

    - Framework Example -

    -

    - The following example algorithm buys SPY when the Fear and Greed index is less than 25 (extreme fear) and sells when it's above 75 (extreme greed). -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class FearAndGreedExampleAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -
    -        # Trade SPY on a daily basis.
    -        self.universe_settings.resolution = Resolution.DAILY
    -        symbols = [Symbol.create('SPY', SecurityType.EQUITY, Market.USA)]
    -        self.add_universe_selection(ManualUniverseSelectionModel(symbols))
    -        # Add a custom Alpha model that emits insights based on the Fear and Greed dataset.
    -        self.add_alpha(FearAndGreedAlphaModel(self))
    -        # Set the equal weighted PCM so the algorithm places trades.
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -
    -
    -# Define the custom alpha model.
    -class FearAndGreedAlphaModel(AlphaModel):
    -
    -    def __init__(self, algorithm):
    -        # Create a list to track the current universe.
    -        self._securities = []
    -        # Add the Fear and Greed dataset. 
    -        self._dataset_symbol = algorithm.add_data(FearGreedIndex, 'FG').symbol
    -
    -    def update(self, algorithm: QCAlgorithm, data: Slice) -> List[Insight]:
    -        # Wait until the Fear and Greed dataset has new data.
    -        if self._dataset_symbol not in data:
    -            return []
    -        # Wait until the Fear and Greed index is extreme.
    -        value = data[self._dataset_symbol].value
    -        if 25 <= value <= 75:
    -            return []
    -        insights = []
    -        for security in self._securities:
    -            # Buy when the market is fearful.
    -            if not security.invested and value < 25:
    -                direction = InsightDirection.UP
    -            # Sell when the market is greedy.
    -            elif security.invested and value > 75:
    -                direction = InsightDirection.FLAT
    -            else:
    -                continue
    -            insights.append(Insight.price(security.symbol, timedelta(2*365), direction))
    -        return insights
    -
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        # When assets enter the universe, save them.
    -        for security in changes.added_securities:
    -            self._securities.append(security)
    -        # When assets leave the universe, remove them.
    -        for security in changes.removed_securities:
    -            if security in self._securities:
    -                self._securities.remove(security)
    -
    public class FearAndGreedExampleAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -
    -        // Trade SPY on a daily basis.
    -        UniverseSettings.Resolution = Resolution.Daily;
    -        var symbols = new[] { QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA) };
    -        AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
    -        // Add a custom Alpha model that emits insights based on the Fear and Greed dataset.
    -        AddAlpha(new FearAndGreedAlphaModel(this));
    -        // Set the equal weighted PCM so the algorithm places trades.
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -    }
    -}
    -
    -// Define the custom Alpha model.
    -public class FearAndGreedAlphaModel : AlphaModel
    -{
    -    // Create a list to track the current universe.
    -    private List<Security> _securities = new List<Security>();
    -    private Symbol _datasetSymbol;
    -
    -    public FearAndGreedAlphaModel(QCAlgorithm algorithm)
    -    {
    -        // Add the Fear and Greed dataset. 
    -        _datasetSymbol = algorithm.AddData<FearGreedIndex>("FG").Symbol;
    -    }
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
    -    {
    -        // Wait until the Fear and Greed dataset has new data.
    -        if (!data.ContainsKey(_datasetSymbol))
    -        {
    -            return Enumerable.Empty<Insight>();
    -        }
    -        // Wait until the Fear and Greed index is extreme.
    -        var value = data[_datasetSymbol].Value;
    -        if (value >= 25 && value <= 75)
    -        {
    -            return Enumerable.Empty<Insight>();
    -        }
    -
    -        var insights = new List<Insight>();
    -        foreach (var security in _securities)
    -        {
    -            InsightDirection direction;
    -            // Buy when the market is fearful.
    -            if (!security.Invested && value < 25)
    -            {
    -                direction = InsightDirection.Up;
    -            }
    -            // Sell when the market is greedy.
    -            else if (security.Invested && value > 75)
    -            {
    -                direction = InsightDirection.Flat;
    -            }
    -            else
    -            {
    -                continue;
    -            }
    -            insights.Add(Insight.Price(security.Symbol, TimeSpan.FromDays(2 * 365), direction));
    -        }
    -        return insights;
    -    }
    -
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        // When assets enter the universe, save them.
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            _securities.Add(security);
    -        }
    -        // When assets leave the universe, remove them.
    -        foreach (var security in changes.RemovedSecurities)
    -        {
    -            _securities.Remove(security);
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The Fear and Greed dataset provides - - FearGreedIndex - - objects, which have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    International Future Universe

    -
    -
    -

    Introduction

    - - -

    - The International Future Universe dataset by QuantConnect lists the available International Future contracts, their daily trading volume, and Open Interest. The data covers 4 contracts (DAX, FESX, HSI, and NKD), starts in July 1998, and is delivered on daily frequency. This dataset is created by monitoring the trading activity on the EUREX, HKFE, and CME. -

    -

    - This dataset depends on the - - US Futures Security Master - - dataset because the US Futures Security Master dataset contains information on symbol changes of the contracts. -

    -

    - This dataset - - does not - - contain market data. For market data, see - - International Futures by TickData - - and - - US Futures by AlgoSeek - - for NKD. -

    -

    - For more information about the International Future Universe dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The International Futures Universe dataset provides data for contract filtering/selection: -

    -
    -
    hsi = self.add_future(Futures.Indices.HANG_SENG, Resolution.MINUTE)           # "HSI"
    -hsi.set_filter(0, 90)
    -dax = self.add_future(Futures.Indices.DAX, Resolution.MINUTE)                 # "DAX"
    -dax.set_filter(0, 90)
    -fesx = self.add_future(Futures.Indices.EURO_STOXX_50, Resolution.MINUTE)      # "FESX"
    -fesx.set_filter(0, 90)
    -nkd = self.add_future(Futures.Indices.NIKKEI_225_DOLLAR, Resolution.MINUTE)   # "NKD"
    -nkd.set_filter(0, 90)
    -
    var hsi= AddFuture(Futures.Indices.HangSeng, Resolution.Minute)           // "HSI";
    -hsi.SetFilter(0, 90);
    -var dax = AddFuture(Futures.Indices.Dax, Resolution.Minute)               // "DAX";
    -dax.SetFilter(0, 90);
    -var fesx = AddFuture(Futures.Indices.EuroStoxx50, Resolution.Minute)      // "FESX";
    -fesx.SetFilter(0, 90);
    -var nkd = AddFuture(Futures.Indices.Nikkei225Dollar, Resolution.Minute)   // "NKD";
    -nkd.SetFilter(0, 90);
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - July 1998 (for details, see - - Supported Assets - - ) -
    - Coverage - - 4 Contracts -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - - Various (for details, see - - Supported Assets - - ) -
    - Market Hours - - - Regular and Extended - -
    - - - -

    Requesting Data

    - - -

    - To add International Future Universe data to your algorithm, call the - - AddFuture - - - add_future - - method. Save a reference to the Future object so you can access the data later in your algorithm. To define which contracts should be in your universe, specify the filter when requesting the Future data. -

    -

    - The - - AddFuture - - - add_future - - method provides a daily stream of Future chain data. To get the most recent daily chain, call the - - FuturesChain - - - futures_chain - - method with the underlying Future Symbol. The - - FuturesChain - - - futures_chain - - method returns data on all the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    class InternationalFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2013, 12, 20) 
    -        self.set_end_date(2014, 2, 20) 
    -        self.set_cash(1000000) 
    -        self.universe_settings.asynchronous = True
    -        self._future = self.add_future(Futures.Indices.HANG_SENG)
    -        # Set our contract filter for this Future chain.
    -        self._future.set_filter(lambda universe: universe.standards_only().front_month())
    -        # Get the entire Futures chain for the current day.
    -        chain = self.futures_chain(self._future.symbol, flatten=True).data_frame
    -
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Future _future;
    -        
    -    public override void Initialize()
    -    {
    -        SetStartDate(2013, 12, 20);
    -        SetEndDate(2014, 2, 20);
    -        SetCash(1000000);
    -        UniverseSettings.Asynchronous = true;
    -        var future = AddFuture(Futures.Indices.HangSeng);
    -        // Set our contract filter for this Future chain.
    -        _future.SetFilter((universe) => universe.StandardsOnly().FrontMonth());
    -        // Get the entire Futures chain for the current day.
    -        var chain = FuturesChain(_future.Symbol);
    -    }
    -}
    -
    -

    - For more information about creating Future Universes, see - - Futures - - . -

    - - - -

    Accessing Data

    - - -

    - For information about accessing International Future Universe data, see - - Futures - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical International Future Universe data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical International Future Universe data in an algorithm, call the - - History<FutureUniverse> - - - history - - method with continuous Future - - Symbol - - and a lookback period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. -

    -
    -
    # Add the Future and save a reference to it.
    -future = self.add_future(Futures.Indices.HANG_SENG)
    -
    -# DataFrame example where the columns are the FutureUniverse attributes:
    -history_df = self.history(FutureUniverse, future.symbol, 5, flatten=True)
    -
    -# Series example where the values are lists of FutureUniverse objects: 
    -history_series = self.history(FutureUniverse, future.symbol, 5, flatten=False)
    -
    -# FutureUniverse objects example:
    -history = self.history[FutureUniverse](future.symbol, 5)
    -
    // Add the Future and save a reference to it.
    -var future = AddFuture(Futures.Indices.HangSeng);
    -
    -// Get historical data.
    -var history = History<FutureUniverse>(future.Symbol, 5);
    -
    -

    - For more information about historical International Future Universe data in algorithms, see - - Contracts - - . -

    -

    - Historical Data In Research -

    -

    - To get historical International Future Universe data in the Research Environment, call the - - History<FutureUniverse> - - - history - - method with continuous Future - - Symbol - - and a time period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. -

    -
    -
    # Add the Future and save a reference to it.
    -future = qb.add_future(Futures.Indices.HANG_SENG)
    -
    -# DataFrame example where the columns are the FutureUniverse attributes:
    -history_df = qb.history(FutureUniverse, future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1), flatten=True)
    -
    -# Series example where the values are lists of FutureUniverse objects: 
    -history_series = qb.history(FutureUniverse, future.symbol, 5, flatten=False)
    -
    -# FutureUniverse objects example:
    -history = qb.history[FutureUniverse](future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1))
    -
    // Add the Future and save a reference to it.
    -var future = qb.AddFuture(Futures.Indices.HangSeng);
    -
    -// Get historical data.
    -var history = qb.History<FutureUniverse>(future.Symbol, new DateTime(2025, 1, 1), new DateTime(2025, 4, 1));
    -
    -

    - For more information about historical International Future Universe data in the Research Environment, see - - Daily Prices History - - . -

    - - - -

    Supported Assets

    - - -

    - The following table shows the available Futures: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Ticker - - Future - - Start Date - - Time Zone - - Currency -
    - HSI - - Hang Seng Index Futures - - Jan 2010 - - Asia/Hong Kong - - HKD -
    - DAX - - German Index Futures - - Jan 2010 - - Europe/Berlin - - EUR -
    - FESX - - EURO STOXX 50 Index Futures - - Jul 1998 - - Europe/Berlin - - EUR -
    - NKD - - Nikkei 225 Index Futures - - Jan 2007 - - America/Chicago - - USD -
    - - - -

    Example Applications

    - - -

    - The International Futures Universe dataset enables you to design Futures strategies accurately. Examples include the following strategies: -

    -
      -
    • - Buying the Futures contract with the most open interest to reduce slippage and market impact -
    • -
    • - Trade speculation on an International Index -
    • -
    • - Trading bull calendar spreads to reduce volatility and margin requirements -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm uses the - - ZigZag indicator - - to determine the trend of Hang Seng Index. It then trades the Index with HSI Futures. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class InternationalFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Set the time zone to HKT to make it more comparable with the exchange.
    -        self.set_time_zone(TimeZones.HONG_KONG)
    -        # Set the account currency as HKD to trade HSI Futures.
    -        self.set_account_currency("HKD", 1000000)
    -        # Seed the last price of the contracts for filling.
    -        self.settings.seed_initial_prices = True
    -
    -        # Request HSI Futures to trade. 
    -        # Note that we will trade the contract with the highest open interest for liquidity.
    -        self.hsi_future = self.add_future(
    -            Futures.Indices.HANG_SENG,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
    -            contract_depth_offset=0
    -        )
    -        # Adds contracts that expiry within 90 days. We will trade the farthest contract
    -        self.hsi_future.set_filter(0,90)
    -        # Request the corresponding underlying Index for feeding indicator for trade signal generation.
    -        hsi_index = self.add_index("HSI").symbol
    -
    -        # Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    -        self._zz = self.zz(hsi_index, 0.15, 5, Resolution.DAILY)
    -        # Warm up indicator for immediate readiness to trade.
    -        self.warm_up_indicator(hsi_index, self._zz, Resolution.DAILY)
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    -        if self.is_market_open(self.hsi_future.symbol) and self._zz.is_ready:
    -            pivot = self._zz.pivot_type
    -            # If the last pivot point is a low point, the current trend is increasing after this low point.
    -            if pivot == PivotPointType.LOW:
    -                contracts = sorted([x.symbol for x in slice.future_chains.get(self.hsi_future.symbol)],
    -                    key=lambda x: x.id.date)
    -                self.set_holdings(contracts[-1], 0.2)
    -            # If the last pivot point is a high point, the current trend is decreasing after this high point.
    -            if pivot == PivotPointType.HIGH:
    -                contracts = sorted([x.symbol for x in slice.future_chains.get(self.hsi_future.symbol)],
    -                    key=lambda x: x.id.date)
    -                self.set_holdings(contracts[-1], -0.2)
    -
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Future _hsiFuture;
    -    private ZigZag _zz;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Set the time zone to HKT to make it more comparable with the exchange.
    -        SetTimeZone(TimeZones.HongKong);
    -        // Set the account currency as HKD to trade HSI Futures.
    -        SetAccountCurrency("HKD", 1000000);
    -
    -        // Seed the last price of the contracts for filling.
    -        Settings.SeedInitialPrices = true;
    -
    -        // Request HSI Futures to trade. 
    -        // Note that we will trade the contract with the highest open interest for liquidity.
    -        _hsiFuture = AddFuture(
    -            Futures.Indices.HangSeng,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.LastTradingDay,
    -            contractDepthOffset: 0
    -        );
    -        // Adds contracts that expiry within 90 days. We will trade the farthest contract
    -        _hsiFuture.SetFilter(0,90);
    -        // Request the corresponding underlying index for feeding indicators for trade signal generation.
    -        var hsiIndex = AddIndex("HSI").Symbol;
    -
    -        // Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    -        _zz = ZZ(hsiIndex, 0.15m, 5, Resolution.Daily);
    -        // Warm up indicator for immediate readiness to trade.
    -        WarmUpIndicator(hsiIndex, _zz, Resolution.Daily);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    -        if (IsMarketOpen(_hsiFuture.Symbol) && _zz.IsReady)
    -        {
    -            var pivot = _zz.PivotType;
    -            FuturesChain chain;
    -            // If the last pivot point is low, the current trend is increasing after this low point.
    -            if (pivot == PivotPointType.Low && slice.FutureChains.TryGetValue(_hsiFuture.Symbol, out chain))
    -            {
    -                var contract = chain.OrderBy(x => x.Expiry).LastOrDefault()?.Symbol;                    
    -                SetHoldings(contract, 0.2m);
    -            }
    -            // If the last pivot point is high, the current trend decreases after this high point.
    -            if (pivot == PivotPointType.High && slice.FutureChains.TryGetValue(_hsiFuture.Symbol, out chain))
    -            {
    -                var contract = chain.OrderBy(x => x.Expiry).LastOrDefault()?.Symbol;                    
    -                SetHoldings(contract, -0.2m);
    -            }
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The International Future Universe dataset provides - - FutureFilterUniverse - - and - - FutureUniverse - - objects. -

    -

    - FutureFilterUniverse Attributes -

    -

    - - FutureFilterUniverse - - objects have the following attributes: -

    -
    -
    -

    - FutureUniverse Attributes -

    -

    - - FutureUniverse - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US ETF Constituents

    -
    -
    -

    Introduction

    - - -

    - The US ETF Constituents dataset by QuantConnect tracks the constituents and weighting of US Equities in 2,650 ETF listings. The data starts in June 2009 and is delivered on a daily basis (monthly basis before January 2015). This dataset is created by tracking the host ETF websites and can be delayed by up to 1 week. -

    -

    - This dataset depends on the - - US Equity Security Master - - dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. -

    -

    - For more information about the US ETF Constituents dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 160,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US ETF Constituents dataset: -

    -
    -
    def initialize(self) -> None:
    -    self.universe_settings.asynchronous = True
    -    # Use the following method for a Classic Algorithm
    -    self._universe = self.add_universe(self.universe.etf("SPY", Market.USA, self.universe_settings, self.etf_constituents_filter))
    -
    -    symbol = Symbol.create("SPY", SecurityType.EQUITY, Market.USA)
    -    # Use the following method for a Framework Algorithm
    -    self.add_universe_selection(ETFConstituentsUniverseSelectionModel(symbol, self.universe_settings, self.etf_constituents_filter))
    -
    -    def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    -        # Add all Symbols of the ETFConstituentUniverse
    -       return [x.symbol for x in constituents]
    -
    public override void Initialize()
    -{
    -    UniverseSettings.Asynchronous = true;
    -    // Use the following method for a Classic Algorithm
    -    _universe = AddUniverse(Universe.ETF("SPY", Market.USA, UniverseSettings, ETFConstituentsFilter));
    -
    -    var symbol = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
    -    // Use the following method for a Framework Algorithm
    -    AddUniverseSelection(new ETFConstituentsUniverseSelectionModel(symbol, UniverseSettings, ETFConstituentsFilter));
    -}
    -private IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable <ETFConstituentUniverse> constituents)
    -{
    -    // Add all Symbols of the ETFConstituentUniverse
    -    return constituents.Select(x => x.Symbol);
    -}
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - June 2009 -
    - Asset Coverage - - 2,650 US ETF Listings -
    - Data Density - - Dense -
    - Resolution - - Daily (Monthly before Jan 2015) -
    - Timezone - - New York -
    - - - -

    Requesting Data

    - - -

    - To add US ETF Constituents data to your algorithm, call the - - AddUniverse - - - add_universe - - and - - Universe.ETF - - - universe.etf - - methods. To select which constituents occupy the universe, provide the ETF - - Symbol - - and a selection function. -

    -
    -
    class ETFConstituentUniverseAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2018, 1, 1)
    -        self.set_end_date(2020, 8, 25)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        self._universe = self.add_universe(self.universe.etf("SPY", self.universe_settings, self.etf_constituents_filter))
    -
    public class ETFConstituentUniverseAlgorithm : QCAlgorithm
    -{
    -    private Universe _universe;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2018, 1, 1);
    -        SetEndDate(2020, 8, 25);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        _universe = AddUniverse(Universe.ETF("SPY", UniverseSettings, ETFConstituentsFilter));
    -    }
    -}
    -
    -
    -

    - For more information about universe settings, see - - Settings - - . -

    - - - -

    Accessing Data

    - - -

    - To access the US ETF Constituent data, use the - - ETFConstituentUniverse - - objects in your selection function. The data is available in daily resolution. The - - Symbol - - objects you return from your selection function defines the universe constituents. -

    -
    -
    def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    -    for c in constituents:
    -        self.debug(f'{c.end_time} :: {c.last_update} :: {c.weight} :: {c.shares_held} :: {c.market_value}')
    -    return [x.symbol for x in constituents]
    -
    -public IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentUniverse> constituents)
    -{
    -    foreach (var c in constituents)
    -    {
    -        Debug($"{c.EndTime} :: {c.LastUpdate} :: {c.Weight} :: {c.SharesHeld} :: {c.MarketValue}");
    -    }
    -
    -    return constituents.Select(c => c.Symbol);
    -}
    -
    -
    - - - -

    Historical Data

    - - -

    - You can get historical universe data in an algorithm and in the Research Environment. -

    -

    - Historical Universe Data in Algorithms -

    -

    - To get historical universe data in an algorithm, call the - - History - - - history - - method with the - - Universe - - object and the lookback period. If there is no data in the period you request, the history result is empty. -

    -
    -
    var history = History(_universe, 30, Resolution.Daily);
    -foreach (var constituents in history)
    -{
    -    foreach (ETFConstituentUniverse constituent in constituents)
    -    {
    -        Log($"{constituent.Symbol} weight at {constituent.EndTime}: {constituent.Weight}");
    -    }
    -}
    -
    # DataFrame example where the columns are the ETFConstituentUniverse attributes: 
    -df_history = self.history(self.universe, 30, Resolution.DAILY, flatten=True)
    -
    -# Series example where the values are lists of ETFConstituentUniverse objects: 
    -series_history = self.history(self.universe, 30, Resolution.DAILY)
    -for (universe_symbol, time), constituents in series_history.items():
    -    for constituent in constituents:
    -        self.log(f'{constituent.symbol} weight at {constituent.end_time}: {constituent.weight}')
    -
    -

    - Historical Universe Data in Research -

    -

    - To get historical universe data in research, call the - - UniverseHistory - - - universe_history - - method with the - - Universe - - object and the lookback period. The - - UniverseHistory - - - universe_history - - returns the filtered universe. If there is no data in the period you request, the history result is empty. -

    -
    -
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var constituents in universeHistory )
    -{
    -    foreach (ETFConstituentUniverse constituent in constituents)
    -    {
    -        Console.WriteLine($"{constituent.Symbol} weight at {constituent.EndTime}: {constituent.Weight}");
    -    }
    -}
    -
    # DataFrame example where the columns are the ETFConstituentUniverse attributes: 
    -df_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    -
    -# Series example where the values are lists of ETFConstituentUniverse objects: 
    -series_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (universe_symbol, time), constituents in series_history.items():
    -    for constituent in constituents:
    -       print(f"{constituent.symbol} weight at {constituent.end_time}: {constituent.weight}")
    -
    -

    - You can call the - - History - - - history - - method in Research. -

    - - - -

    Supported ETFs

    - - -

    - The following table shows the available ETFs: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    Example Applications

    - - -

    - The ETF Constituents dataset provides an excellent source of tradable universes for strategies without selection bias. When you use an ETF universe, the original ETF can serve as an excellent benchmark for your strategy performance. Other use cases include the following: -

    -
      -
    • - Creating an index-tracking algorithm for customized passive portfolio management -
    • -
    • - Performing statistical arbitrage with the base ETF -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm creates a dynamic universe of the 10 largest US Equities in the SPY ETF. Each day, the algorithm forms a dollar-neutral and market-neutral portfolio by buying the 10 ETF constituents and shorting the SPY ETF. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class ETFConstituentUniverseAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        # Add the SPY to trade.
    -        self._spy = self.add_equity("SPY").symbol
    -        # Add an ETF constituents universe that selects the large caps 
    -        # in SPY. Save the universe object so you can get history
    -        # for the universe.
    -        universe = self.add_universe(
    -            self.universe.etf(
    -                self._spy, 
    -                universe_filter_func=self._select_assets
    -            )
    -        )
    -        # Get historical universe data.
    -        history = self.history(universe, 30, Resolution.DAILY, flatten=True)
    -        # Show an example of wrangling the historical data.
    -        etf_weights = history.weight.unstack(1)  
    -        # Create a dictionary to store the ETF weights each day.
    -        self._weight_by_symbol = {}
    -        # Add a Scheduled Event to rebalance the portfolio each day.
    -        self.schedule.on(
    -            self.date_rules.every_day(self._spy),
    -            self.time_rules.after_market_open(self._spy, 1),
    -            self._rebalance
    -        )
    -
    -    def _select_assets(
    -            self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    -        # Select the 10 largest stocks in the SPY.
    -        selected = sorted(
    -            [c for c in constituents if c.weight], 
    -            key=lambda c: c.weight
    -        )[-10:]
    -        # Save the weights for position sizing.
    -        self._weight_by_symbol = {c.symbol: c.weight for c in selected}
    -        # Return the selected assets.
    -        return list(self._weight_by_symbol.keys())
    -
    -    def _rebalance(self) -> None:
    -        # Create a long-short portfolio to earn the excess return of the 
    -        # top 10 weighted stocks from SPY.
    -        spy_weight = sum(self._weight_by_symbol.values())
    -        targets = [PortfolioTarget(self._spy, -0.5)]
    -        for symbol, weight in self._weight_by_symbol.items():
    -            targets.append(PortfolioTarget(symbol, 0.5*weight/spy_weight))
    -        # Liquidate the stocks that aren't in top 10.
    -        self.set_holdings(targets, True)
    -
    -
    public class ETFConstituentUniverseAlgorithm : QCAlgorithm
    -{ 
    -    private Symbol _spy;
    -    // Create a dictionary to store the ETF weights each day.
    -    private Dictionary<Symbol, decimal> _weightBySymbol = new();
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        // Add the SPY to trade.
    -        _spy = AddEquity("SPY").Symbol;
    -        // Add an ETF constituents universe that selects the large caps 
    -        // in SPY. Save the universe object so you can get history
    -        // for the universe.
    -        var universe = AddUniverse(Universe.ETF(_spy, universeFilterFunc: SelectAssets));
    -        // Get historical universe data.
    -        var history = History(universe, 30, Resolution.Daily);
    -        // Show an example of iterating through the historical data.
    -        foreach (var constituents in history)
    -        {
    -            var t = constituents.EndTime;
    -            foreach (ETFConstituentUniverse constituent in constituents)
    -            {
    -                var symbol = constituent.Symbol;
    -                var weight = constituent.Weight;
    -            }
    -        }
    -        // Add a Scheduled Event to rebalance the portfolio each day.
    -        Schedule.On(DateRules.EveryDay(_spy), TimeRules.AfterMarketOpen(_spy, 1), Rebalance);
    -    }
    -    
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<ETFConstituentUniverse> constituents)
    -    {
    -        // Select the 10 largest stocks in the SPY. 
    -        _weightBySymbol = constituents.OrderByDescending(c => c.Weight).Take(10)
    -            // Save the weights for position sizing.
    -            .ToDictionary(c => c.Symbol, c => c.Weight ?? 0m);
    -        // Return the selected assets.
    -        return _weightBySymbol.Keys;
    -    }
    -    
    -    private void Rebalance()
    -    {
    -        // Create a long-short portfolio to earn the excess return of the 
    -        // top 10 weighted stocks from SPY.
    -        var spyWeight = _weightBySymbol.Values.Sum();
    -        var targets = new List<PortfolioTarget>() { new PortfolioTarget(_spy, -0.5m) };
    -        foreach (var kvp in _weightBySymbol)
    -        {
    -            targets.Add(new PortfolioTarget(kvp.Key, 0.5m * kvp.Value / spyWeight));
    -        }
    -        // Liquidate the stocks that aren't in top 10.
    -        SetHoldings(targets, true);
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm creates a dynamic universe of the 10 largest US Equities in the SPY ETF. Each day, the algorithm forms a dollar-neutral and market-neutral portfolio by buying the 10 ETF constituents and shorting the SPY ETF. -

    -
    -
    class ETFConstituentUniverseFrameworkAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = False
    -        self.universe_settings.resolution = Resolution.MINUTE
    -        self.weight_by_symbol = {}
    -        
    -        # Add universe selection on SPY's constituents to select only from large cap stocks
    -        # Save the universe to access its members for historical data call
    -        spy = self.add_equity("SPY").symbol
    -        self.add_universe_selection(ETFConstituentsUniverseSelectionModel(spy, self.universe_settings, self.etf_constituents_filter))
    -
    -        # Add alpha model that set normalized weight as investment insight
    -        self.add_alpha(ETFConstituentsAlphaModel(self, spy))
    -
    -        # Set up portfolio construction model that invest by the insight weights
    -        pcm = InsightWeightingPortfolioConstructionModel()
    -        # Avoid excessive rebalance on insight changes
    -        pcm.rebalance_on_insight_changes = False
    -        self.set_portfolio_construction(pcm)
    -
    -        self.add_risk_management(NullRiskManagementModel())
    -
    -        self.set_execution(ImmediateExecutionModel())
    -
    -    def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    -        # The top 10 weighted securities are considered better active selections
    -        # Save the weights for position sizing
    -        selected = sorted([c for c in constituents if c.weight],
    -            key=lambda c: c.weight, reverse=True)[:10]
    -        self.weight_by_symbol = {c.symbol: c.weight for c in selected}
    -
    -        return list(self.weight_by_symbol.keys())
    -
    -class ETFConstituentsAlphaModel(AlphaModel):
    -
    -    def __init__(self, algorithm: QCAlgorithm, etf: Symbol) -> None:
    -        self.algorithm = algorithm
    -        self.etf = etf
    -        self.day = -1
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        # Rebalance daily since selection is on daily basis
    -        if self.day == algorithm.time.day:
    -            return []
    -
    -        self.day = algorithm.time.day
    -
    -        insights = []
    -
    -        # Create a long-short portfolio to earn excess return of the top 10 weighted stocks from SPY
    -        etf_weight = sum(self.algorithm.weight_by_symbol.values())
    -        if etf_weight> 0:
    -            # Invest half the portfolio by normalized weights of the top 10 constituents
    -            for symbol, weight in self.algorithm.weight_by_symbol.items():
    -                if algorithm.securities.contains_key(symbol):
    -                    insights.append(Insight.price(symbol, Expiry.END_OF_DAY, InsightDirection.UP, weight=0.5*weight/etf_weight))
    -            
    -            # Short the other half with SPY, looking to profit from the active selection
    -            insights.append(Insight.price(self.etf, Expiry.END_OF_DAY, InsightDirection.DOWN, weight=0.5))
    -
    -        return insights
    -
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        # Liquidate the ones not in top 10 weights
    -        symbols = [x.symbol for x in changes.removed_securities if x.invested]
    -        algorithm.liquidate(symbols, tag='Removed From Universe')
    -
    public class ETFConstituentUniverseFrameworkAlgorithm : QCAlgorithm
    -{ 
    -    public Dictionary<Symbol, decimal> WeightBySymbol = [];
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = false;
    -        UniverseSettings.Resolution = Resolution.Minute;
    -
    -        // Add universe selection on SPY's constituents to select only from large cap stocks
    -        // Save the universe to access its members for historical data call
    -        var spy = AddEquity("SPY").Symbol;
    -        AddUniverseSelection(new ETFConstituentsUniverseSelectionModel(spy, UniverseSettings, ETFConstituentsFilter));
    -        
    -        // Add alpha model that set normalized weight as investment insight
    -        AddAlpha(new ETFConstituentsAlphaModel(this, spy));
    -
    -        // Set up portfolio construction model that invest by the insight weights
    -        SetPortfolioConstruction(new InsightWeightingPortfolioConstructionModel
    -        {
    -            // Avoid excessive rebalance on insight changes
    -            RebalanceOnInsightChanges = false
    -        });
    -        
    -        AddRiskManagement(new NullRiskManagementModel());
    -        
    -        SetExecution(new ImmediateExecutionModel());
    -    }
    -    
    -    private IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentUniverse> constituents)
    -    {
    -        // The top 10 weighted securities are considered better active selections
    -        // Save the weights for position sizing
    -        WeightBySymbol = constituents.Where(c=> c.Weight.HasValue).OrderByDescending(c => c.Weight).Take(10)
    -            .ToDictionary(c => c.Symbol, c => c.Weight.Value);
    -
    -        return WeightBySymbol.Keys;
    -    }
    -}
    -
    -public class ETFConstituentsAlphaModel : AlphaModel
    -{
    -    private int _day = -1;
    -    private Symbol _etf;
    -    private ETFConstituentUniverseFrameworkAlgorithm _algorithm;
    -    
    -    public ETFConstituentsAlphaModel(ETFConstituentUniverseFrameworkAlgorithm algorithm, Symbol etf)
    -    {
    -        _etf = etf;
    -        _algorithm = algorithm;
    -    }
    -    
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        // Rebalance daily since selection is on daily basis
    -        if (_day == algorithm.Time.Day)
    -        {
    -            return [];
    -        }
    -        
    -        _day = algorithm.Time.Day;
    -        
    -        var insights = new List<Insight>();
    -        
    -        // Create a long-short portfolio to earn excess return of the top 10 weighted stocks from SPY
    -        var etfWeight = (double)_algorithm.WeightBySymbol.Values.Sum();
    -        if (etfWeight > 0)
    -        {
    -            // Invest half the portfolio by normalized weights of the top 10 constituents
    -            foreach(var kvp in _algorithm.WeightBySymbol)
    -            {
    -                insights.Add(Insight.Price(kvp.Key, Expiry.EndOfDay, InsightDirection.Up, weight: (double)kvp.Value/etfWeight * 0.5));
    -            }
    -
    -            // Short the other half with SPY, looking to profit from the active selection
    -            insights.Add(Insight.Price(_etf, Expiry.EndOfDay, InsightDirection.Down, weight: 0.5));
    -        }
    -        
    -        return insights;
    -    }
    -    
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        // Liquidate the ones not in top 10 weights
    -        var symbols = changes.RemovedSecurities.Where(x => x.Invested).Select(x => x.Symbol);
    -        algorithm.Liquidate(symbols, tag: "Removed From Universe");
    -    }
    -}
    -
    -

    - Research Example -

    -

    - The following example lists ETF constituents with the greatest weight in the SPY: -

    -
    -
    var qb = new QuantBook();
    -
    -// Add the ETF
    -var symbol = qb.AddEquity("SPY").Symbol;
    -
    -// Add ETF Universe Selection
    -IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentUniverse> constituents)
    -{
    -    // Take the top 10 weighted constituents
    -    return constituents
    -        .OrderByDescending(c => c.Weight)
    -        .Take(10)
    -        .Select(c => c.Symbol);
    -}
    -
    -var universe = qb.AddUniverse(qb.Universe.ETF(spy, qb.UniverseSettings, ETFConstituentsFilter)); 
    -
    -// Historical Universe data
    -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var constituents in universeHistory )
    -{
    -    foreach (ETFConstituentUniverse constituent in constituents)
    -    {
    -        Console.WriteLine($"{constituent.Symbol} weight at {constituent.EndTime}: {constituent.Weight}");
    -    }
    -}
    -
    qb = QuantBook()
    -
    -# Add the ETF
    -qb.spy = qb.add_equity("SPY").symbol
    -
    -# Add ETF Universe Selection
    -def etf_constituents_filter(constituents):
    -    # Take the top 10 weighted constituents
    -    selected = sorted([c for c in constituents if c.weight],
    -        key=lambda c: c.weight, reverse=True)[:10]
    -    return [c.symbol for c in selected]
    -
    -universe = qb.add_universe(qb.universe.etf(qb.spy, qb.universe_settings, etf_constituents_filter))
    -
    -# Historical Universe data
    -universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (universe_symbol, time), constituents in universe_history.items():
    -    for constituent in constituents:
    -        print(f"{constituent.symbol} weight at {constituent.end_time}: {constituent.weight}")
    -
    - - - -

    Data Point Attributes

    - - -

    - The ETF Constituents dataset provides - - ETFConstituentUniverse - - objects, which have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Equities Short Availability

    -
    -
    -

    Introduction

    - - -

    - The US Equity Short Availability dataset provides the available shares for open short positions and their borrowing cost in the US Equity market. The data covers 10,500 US Equities, starts in January 2018, and is delivered on a daily frequency. This dataset is created using information from the exchanges. -

    -

    - This dataset depends on the - - US Equity Security Master - - dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. -

    -

    - For more information about the US Equities Short Availability dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippets demonstrate how to request data from the US Equities Short Availability dataset. -

    -

    - Interactive Brokers Data -

    -
    -
    security.set_shortable_provider(InteractiveBrokersShortableProvider())
    -
    security.SetShortableProvider(new InteractiveBrokersShortableProvider());
    -
    -

    - Axos Clearing Data -

    -
    -
    security.set_shortable_provider(LocalDiskShortableProvider("axos"))
    -
    security.SetShortableProvider(new LocalDiskShortableProvider("axos"));
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2018 -
    - Asset Coverage - - 10,500 US Equities -
    - Data Density - - Sparse -
    - Resolution - - Daily -
    - Timezone - - New York -
    - - - -

    Requesting Data

    - - -

    - To add US Equities Short Availability data to your algorithm, set the - - shortable provider - - of each US Equity in your algorithm. -

    -
    -
    class ShortAvailabilityDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2019, 1, 1)
    -        security = self.add_equity("AAPL")
    -        # Set shortable provider as IB
    -        security.set_shortable_provider(InteractiveBrokersShortableProvider())
    -        self._symbol = security.symbol
    -
    public class ShortAvailabilityDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2019, 1, 1);
    -        var security = AddEquity("AAPL");
    -        // Set shortable provider as IB
    -        security.SetShortableProvider(new InteractiveBrokersShortableProvider());
    -        _symbol = security.Symbol;
    -    }
    -}
    -
    - - - -

    Accessing Data

    - - -

    - To check how many shares are available for a security to short, call the - - ShortableQuantity - - - shortable_quantity - - method of the - - ShortableProvider - - - shortable_provider - -

    -
    -
    var shortableProvider = Securities[_symbol].ShortableProvider;
    -// Get the shortable quantity of the selected symbol at the selected time
    -var shortableQuantity = shortableProvider.ShortableQuantity(_symbol, Time);
    -
    -// Check if there are a certain quantity of shares available
    -var quantity = 100;
    -var isShortableQuantity = Shortable(_symbol, quantity);
    -
    shortable_provider = self.securities[self._symbol].shortable_provider
    -# Get the shortable quantity of the selected symbol at the selected time
    -shortable_quantity = shortable_provider.shortable_quantity(self._symbol, self.time)
    -
    -# Check if there are a certain quantity of shares available
    -quantity = 100;
    -is_shortable_quantity = self.shortable(self._symbol, quantity)
    -
    -

    - To check borrowing cost, call the - - FeeRate - - - fee_rate - - or - - RebateRate - - - rebate_rate - - method of the - - ShortableProvider - - - shortable_provider - -

    -
    -
    var feeRate = shortableProvider.FeeRate(_symbol, Time);
    -var rebateRate = shortableProvider.RebateRate(_symbol, Time);
    -
    fee_rate = shortable_provider.fee_rate(self._symbol, self.time);
    -rebate_rate = shortable_provider.rebate_rate(self._symbol, self.time);
    -
    - To get valid borrowing rates, use the - - InteractiveBrokersShortableProvider - - - . - - - - -

    Example Applications

    - - -

    - The US Equities Short Availability dataset enables you to accurately design strategies harnessing information about short availability. Examples include the following use cases: -

    -
      -
    • - Avoiding short orders that the brokerage will reject -
    • -
    • - Selecting securities based on how many shares are available to short -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm shorts GameStop every day there are shares available to short. If the algorithm receives a margin call, it liquidates the position and start again on the next day. -

    -
    -
    from AlgorithmImports import *
    -
    -class ShortAvailabilityDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(1000)
    -        # Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    -        self.settings.seed_initial_prices = True
    -        self.add_security_initializer(self._custom_security_initializer)
    -
    -        self.equity = self.add_equity("GME")
    -
    -        # Set up daily rebalance scheduled event, since shortable quantity is updated daily
    -        self.schedule.on(
    -            self.date_rules.every_day(self.equity.symbol),
    -            self.time_rules.after_market_open(self.equity.symbol, 10),
    -            self.rebalance)
    -
    -    def rebalance(self) -> None:
    -        symbol = self.equity.symbol
    -        
    -        # You can obtain the shortable quantity to decide the submission of a short order
    -        shortable_quantity = self.equity.shortable_provider.shortable_quantity(symbol, self.time)
    -        if not shortable_quantity:
    -            shortable_quantity = 0
    -        # Fee and rebate rate is also available, such that you can calculate the expected return and decide if the margin is worthwhile
    -        self.plot('Total Shortable Quantity', symbol, shortable_quantity)
    -        self.plot('Borrowing Cost', "Fee Rate", self.equity.shortable_provider.fee_rate(symbol, self.time))
    -        self.plot('Borrowing Cost', "Rebate Rate", self.equity.shortable_provider.rebate_rate(symbol, self.time))
    -
    -        # Test whether we can short the desired quantity
    -        quantity = self.calculate_order_quantity(symbol, -1)
    -        if quantity and self.shortable(symbol, quantity):
    -            self.market_order(symbol, quantity)
    -
    -    def on_margin_call_warning(self) -> None:
    -        self.liquidate()
    -
    -    def _custom_security_initializer(self, security: Security) -> None:
    -        # Set the shortable provider as your broker for accurate short reality modeling
    -        security.set_shortable_provider(InteractiveBrokersShortableProvider())
    -
    public class ShortAvailabilityDataAlgorithm : QCAlgorithm
    -{
    -    private Equity _equity;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000);
    -        // Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    -        Settings.SeedInitialPrices = true;
    -        AddSecurityInitializer(security =>
    -        {
    -            // Set the shortable provider as your broker for accurate short reality modeling
    -            security.SetShortableProvider(new InteractiveBrokersShortableProvider());    
    -        });
    -        
    -        _equity = AddEquity("GME");
    -        
    -        // Set up daily rebalance scheduled event, since shortable quantity is updated daily
    -        Schedule.On(
    -            DateRules.EveryDay(_equity.Symbol),
    -            TimeRules.AfterMarketOpen(_equity.Symbol, 10),
    -            Rebalance);
    -    }
    -    
    -    public void Rebalance()
    -    {
    -        var symbol = _equity.Symbol;
    -
    -        // You can obtain the shortable quantity to decide the submission of a short order
    -        // Fee and rebate rate is also available, such that you can calculate the expected return and decide if the margin is worthwhile
    -        Plot("Total Shortable Quantity", symbol, _equity.ShortableProvider.ShortableQuantity(symbol, Time) ?? 0m);
    -        Plot("Borrowing Cost", "Fee Rate", _equity.ShortableProvider.FeeRate(symbol, Time));
    -        Plot("Borrowing Cost", "Rebate Rate", _equity.ShortableProvider.RebateRate(symbol, Time));
    -
    -        // Test whether we can short the desired quantity
    -        var quantity = CalculateOrderQuantity(symbol, -1m);
    -        if (quantity != 0 && Shortable(symbol, quantity))
    -        {
    -            MarketOrder(symbol, quantity);
    -        }
    -    }
    -
    -    public override void OnMarginCallWarning()
    -    {
    -        Liquidate();
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm shorts GameStop every day there are shares available to short. If the algorithm receives a margin call, it liquidates the position and start again on the next day. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class ShortAvailabilityDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(1000)
    -        # Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    -        self.settings.seed_initial_prices = True
    -        self.add_security_initializer(self._custom_security_initializer)
    -
    -        self.set_universe_selection(ManualUniverseSelectionModel(
    -            [Symbol.create("GME", SecurityType.EQUITY, Market.USA)]))           
    -
    -        # Emit down-direction insights to short all securities in the universe            
    -        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.DOWN, timedelta(1)))
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -        self.set_execution(ShortableExecutionModel())
    -
    -    # On Margin Call, emit flat-direction insights to liquidate the positions
    -    def on_margin_call_warning(self) -> None:
    -        self.emit_insights([Insight.price(kvp.Key, timedelta(1), InsightDirection.FLAT)
    -            for kvp in self.securities if kvp.Value.invested])
    -
    -    def _custom_security_initializer(self, security: Security) -> None:
    -        # Set the shortable provider as IB
    -        security.set_shortable_provider(InteractiveBrokersShortableProvider())
    -
    -class ShortableExecutionModel(ExecutionModel):
    -    def __init__(self) -> None:
    -        self.targets_collection = PortfolioTargetCollection()
    -
    -    def execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None:
    -        '''Immediately submits orders for the specified portfolio targets.
    -        Args:
    -            algorithm: The algorithm instance
    -            targets: The portfolio targets to be ordered'''
    -
    -        # for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    -        self.targets_collection.add_range(targets)
    -        if self.targets_collection.count > 0:
    -            for target in self.targets_collection.order_by_margin_impact(algorithm):
    -                # calculate remaining quantity to be ordered
    -                quantity = OrderSizing.get_unordered_quantity(algorithm, target)
    -                # If the quantity is negative, ensure that the security is shortable
    -                if quantity > 0 or algorithm.shortable(target.symbol, quantity):
    -                    algorithm.market_order(target.symbol, quantity)
    -
    -            self.targets_collection.clear_fulfilled(algorithm)
    -
    public class ShortAvailabilityDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000);
    -        // Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    -        Settings.SeedInitialPrices = true;
    -        AddSecurityInitializer(security =>
    -        {
    -            // Set the shortable provider as your broker for accurate short reality modeling
    -            security.SetShortableProvider(new InteractiveBrokersShortableProvider());    
    -        });
    -
    -        SetUniverseSelection(new ManualUniverseSelectionModel(
    -            QuantConnect.Symbol.Create("GME", SecurityType.Equity, Market.USA)));            
    -        
    -        // Emit down-direction insights to short all securities in the universe            
    -        SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Down, TimeSpan.FromDays(1)));
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -        SetExecution(new ShortableExecutionModel());
    -    }
    -
    -    // On Margin Call, emit flat-direction insights to liquidate the positions
    -    public override void OnMarginCallWarning()
    -    {
    -        EmitInsights(Securities
    -            .Where(kvp => kvp.Value.Invested)
    -            .Select(kvp => Insight.Price(kvp.Key, TimeSpan.FromDays(1), InsightDirection.Flat))
    -            .ToArray());
    -    }
    -
    -    public class ShortableExecutionModel : ImmediateExecutionModel
    -    {
    -        private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
    -
    -        public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
    -        {
    -            _targetsCollection.AddRange(targets);
    -            // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    -            if (_targetsCollection.Count > 0)
    -            {
    -                foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
    -                {
    -                    // calculate remaining quantity to be ordered
    -                    var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);
    -                    // If the quantity is negative, ensure that the security is shortable
    -                    if (quantity > 0 || algorithm.Shortable(target.Symbol, quantity))
    -                    {
    -                        algorithm.MarketOrder(target.Symbol, quantity);
    -                    }
    -                }
    -
    -                _targetsCollection.ClearFulfilled(algorithm);
    -            }
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Equities Short Availability data is a - - Symbol - - /decimal pair for - - ShortQuantity - - , - - FeeRate - - , - and - - RebateRate - - . -

    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Equity Coarse Universe

    -
    -
    -

    Introduction

    - - -

    - The US Equity Coarse Universe dataset by QuantConnect is a daily universe of all trading stocks in the US for a given day with the end of day price and volume. The data covers 30,000 US Equities in total, with approximately 8,000 Equities per day. The data starts in January 1998 and is delivered each trading day. This dataset is created by taking the closing auction price tick from the daily L1 trade and quote exchange dumps. -

    -

    - This dataset depends on the - - US Equities by AlgoSeek - - dataset because - - universe selection - - adds and removes market data subscriptions and on the - - US Equity Security Master - - dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. -

    -

    - QuantConnect/LEAN combines the data of this dataset with - - MorningStar Fundamental data - - in runtime. You can use this dataset in local development without the Morningstar counterpart. -

    -

    - For more information about the US Equity Coarse Universe dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Equity Coarse Universe dataset: -

    -
      -
    • - Direct Access using the Security object -
    • -
    -
    -
    equity = self.add_equity("IBM")
    -ibm_fundamental = equity.fundamentals
    -
    var equity = AddEquity("IBM");
    -var ibmFundamental = equity.Fundamentals;
    -
    -
      -
    • - Direct Access using the Symbol object -
    • -
    -
    -
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    -ibm_fundamental = self.fundamentals
    -
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    -var ibmFundamental = Fundamentals(ibm);
    -
    -
      -
    • - Universe Selection -
    • -
    -
    -
    def initialize(self) -> None:
    -    # Universe selection
    -    self._universe = self.add_universe(self.fundamental_filter_function)
    -
    -def fundamental_filter_function(self, fundamental: List[Fundamental]):
    -    # Sort all equities with price above $10 by dollar volume
    -    sorted_by_dollar_volume = sorted([f for f in fundamental if f.price > 10],
    -                                key=lambda f: f.dollar_volume, reverse=True)
    -    # Take the top 10
    -    return [f.symbol for f in sorted_by_dollar_volume[:10]]
    -
    public override void Initialize()
    -{
    -    // Universe selection
    -    _universe = AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    -}
    -
    -public override List<Symbol> FundamentalFilterFunction(List<Fundamental> fundamental)
    -{
    -    // Sort all equities with price above $10 by dollar volume, take the top 10
    -    return (from f in fundamental
    -            where f.Price > 10
    -            orderby f.DollarVolume descending
    -            select f.Symbol).Take(10);
    -}
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 1998 -
    - Asset Coverage - - 30,000 US Equities -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - - New York -
    -

    - This dataset doesn't include Over-the-Counter (OTC) stocks. -

    - - - -

    Requesting Data

    - - -

    - You don't need any special code to request US Coarse Fundamental Data. You can access the current and historical fundamental data for any of the US Equities that this dataset includes. -

    -
    -
    class CoarseFundamentalDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2021, 1, 1)
    -        self.set_end_date(2021, 7, 1)
    -        self.set_cash(100000) 
    -        self.universe_settings.asynchronous = True
    -
    -        # Option 1: Subscribe to individual US Equity assets
    -        self.add_equity("IBM")  
    -
    -        # Option 2A: Create a fundamental universe (classic version)
    -        self._universe = self.add_universe(self.fundamental_function)
    -
    -        # Option 2B: Create a fundamental universe (framework version)
    -        self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_function))
    -
    public class CoarseFundamentalDataAlgorithm : QCAlgorithm
    -{
    -    private Universe _universe;
    -    public override void Initialize()
    -    {
    -        SetStartDate(2021, 1, 1);
    -        SetEndDate(2021, 7, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        
    -        // Option 1: Subscribe to individual US Equity assets
    -        AddEquity("IBM");
    -
    -        // Option 2A: Create a fundamental universe (classic version)
    -        _universe = AddUniverse(FundamentalFilterFunction);
    -
    -        // Option 2B: Create a fundamental universe (framework version)
    -        AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    -    }
    -}
    -
    -

    - For more information about universe settings, see - - Settings - - . -

    - - - -

    Accessing Data

    - - -

    - If you add a - - fundamental universe - - to your algorithm, you can access fundamental data in the universe selection function. -

    -
    -
    def fundamental_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -    sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume, reverse=True)[:3]
    -    for cf in sorted_by_dollar_volume:
    -        self.debug(f"{cf.end_time} :: {cf.symbol} : {cf.adjusted_price} :: {cf.dollar_volume}")
    -
    -    return [ x.symbol for x in sorted_by_dollar_volume]
    -
    public IEnumerable<Symbol> FundamentalFunction(IEnumerable<Fundamental> fundamental)
    -{
    -    var sortedByDollarVolume = fundamental
    -        .OrderByDescending(x => x.DollarVolume)
    -        .Take(3).ToList();
    -
    -    foreach (var cf in sortedByDollarVolume)
    -    {
    -        Debug($"{cf.EndTime} :: {cf.Symbol} : {cf.AdjustedPrice} :: {cf.DollarVolume}");
    -    }
    -
    -    return sortedByDollarVolume.Select(x => x.Symbol);
    -}
    -
    -

    - To get fundamental data for Equities in your algorithm, use the - - Fundamentals - - - fundamentals - - property of the - - Equity - - objects. The fundamental data represent the corporate fundamentals for the current algorithm time. -

    -
    -
    fundamentals = self.securities[symbol].fundamentals
    -
    var fundamentals = Securities[symbol].Fundamentals;
    -
    -

    - To get fundamental data for Equities, regardless of whether or not you have subscribed to them in your algorithm, call the - - Fundamentals - - - fundamentals - - method. If you pass one - - Symbol - - , the method returns a - - Fundamental - - object. If you pass a list of - - Symbol - - objects, the method returns a list of - - Fundamental - - objects. -

    -
    -
    // Single asset 
    -var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    -var ibmFundamental = Fundamentals(ibm);
    -
    -// Multiple assets
    -var nb = QuantConnect.Symbol.Create("NB", SecurityType.Equity, Market.USA);
    -var fundamentals = Fundamentals(new List<Symbol>{ nb, ibm }).ToList();
    -
    # Single asset
    -ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    -ibm_fundamental = self.fundamentals(ibm)
    -
    -# Multiple assets
    -nb = Symbol.create("NB", SecurityType.EQUITY, Market.USA)
    -fundamentals = self.fundamentals([ nb, ibm ])
    -
    - - - -

    Historical Data

    - - -

    - You can get historical fundamental data in an algorithm and in the Research Environment. -

    -

    - Historical Data in Algorithms -

    -

    - To get historical fundamental data in an algorithm, call the - - History - - - history - - method with - - Fundamental - - type and the Equity - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    -
    -// Fundamental objects
    -var fundamentalHistory = History<Fundamental>(ibm, TimeSpan.FromDays(30));
    -
    -// Fundamentals objects for all US Equities (including delisted companies)
    -var fundamentalsHistory = History<Fundamentals>(TimeSpan.FromDays(30));
    -
    -// Collection of Fundamental objects for all US Equities (including delisted companies)
    -var collectionHistory = History(_universe, 30, Resolution.Daily);
    -foreach (var fundamental in collectionHistory)
    -{
    -    // Cast to Fundamental is required
    -    var mostLiquid = fundamental.OfType<Fundamental>().OrderByDescending(x => x.DollarVolume).Take(5);
    -}
    -
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    -
    -# DataFrame of fundamental data for a given asset
    -df_history = self.history(Fundamental, ibm, timedelta(30), flatten=True)
    -
    -# Fundamental objects
    -fundamental_history = self.history[Fundamental](ibm, timedelta(30))
    -
    -# Fundamentals objects for all US Equities (including delisted companies)
    -fundamentals_history = self.history[Fundamentals](timedelta(30))
    -
    -# DataFrame of fundamental data for universe constituents
    -df_history = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
    -
    -# Series of fundamental data for universe constituents
    -series_history = self.history(self._universe, 30, Resolution.DAILY)
    -for (universe_symbol, time), fundamental in series_history.items():
    -    most_liquid = sorted(fundamental, key=lambda x: x.dollar_volume)[-5:]
    -
    -

    - Historical Universe Data in Research -

    -

    - To get historical universe data in the Research Environment, call the - - UniverseHistory - - - universe_history - - method with the - - Universe - - object and the lookback period. This method returns the filtered universe. If there is no data in the period you request, the history result is empty. -

    -
    -
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var fundamentals in universeHistory)
    -{
    -    foreach (Fundamental fundamental in fundamentals)
    -    {
    -        Console.WriteLine($"{fundamental.Symbol} dollar volume at {fundamental.EndTime}: {fundamental.DollarVolume}");
    -    }
    -}
    -
    # DataFrame of fundamental data for universe constituents
    -df_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    -
    -# Series of fundamental data for universe constituents
    -series_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (universe_symbol, time), fundamentals in series_history.items():
    -    for fundamental in fundamentals:
    -        print(f"{fundamental.symbol} dollar volume at {fundamental.end_time}: {fundamental.dollar_volume}")
    -
    -

    - For more information about historical US Equity fundamental data, see - - Equity Fundamental Data - - . -

    - - - -

    Example Applications

    - - -

    - The US Equity Coarse Universe dataset enables you to accurately design a universe of US Equities. Examples include the following strategies: -

    -
      -
    • - Selecting securities with the largest dollar volume -
    • -
    • - Selecting securities within a specific price range -
    • -
    • - Selecting securities that have fundamental data available (together with - - MorningStar Fundamental data - - in - - Fundamental - - objects) -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm creates a dynamic universe of the three most liquid US Equities. Each time the universe changes, the algorithm forms an equal-weighted portfolio of the three companies. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class USEquityCoarseUniverseConstituentsDataAlgorithm(QCAlgorithm):
    -
    -    _number_of_symbols = 3
    -    _changes = None
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        # Set Asynchronous to True to improve speed performance.
    -        self.universe_settings.asynchronous = True
    -        # Add a universe of US Equities.
    -        universe = self.add_universe(self._select_assets)
    -        # Get historical data for the universe.
    -        history = self.history(universe, 30, Resolution.DAILY, flatten=True)
    -
    -    def _select_assets(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -        # Select the top traded stocks, since they are the most popular 
    -        # with high capital flow.
    -        return [ 
    -            x.symbol for x in sorted(
    -                fundamental, key=lambda x: x.dollar_volume
    -            )[-self._number_of_symbols:] 
    -        ]
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # If we have no changes, do nothing.
    -        if not slice.bars or self._changes is None: 
    -            return
    -        # Liquidate removed securities, since they are not the most 
    -        # popular stocks.
    -        for security in self._changes.removed_securities:
    -            if security.invested:
    -                self.liquidate(security.symbol)
    -        # We want 1/N allocation for each security in our universe to
    -        # evenly dissipate risk.
    -        for security in self._changes.added_securities:
    -            self.set_holdings(security.symbol, 1 / self._number_of_symbols)
    -        self._changes = None
    -
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        self._changes = changes
    -
    -
    public class USEquityCoarseUniverseConstituentsDataAlgorithm : QCAlgorithm
    -{
    -    private int _numberOfSymbols = 3;
    -    private SecurityChanges _changes = SecurityChanges.None;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -    
    -        // Set Asynchronous to true to improve speed performance 
    -        UniverseSettings.Asynchronous = true;
    -        // Requesting data
    -        var universe = AddUniverse(SelectAssets);
    -        // Get historical data for the universe.
    -        var history = History(universe, 30, Resolution.Daily);
    -        foreach (var fundamentals in history)
    -        {
    -            // Iterate through each asset in the universe on this day 
    -            // and access its data point attributes.
    -            foreach (Fundamental f in fundamentals)
    -            {
    -                var symbol = f.Symbol;
    -                var t = f.EndTime;
    -                var dollarVolume = f.DollarVolume;
    -            }
    -        }
    -    }
    -
    -    public IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamental)
    -    {
    -        // Select the top traded stocks, since they are the most popular 
    -        // with high capital flow.
    -        return fundamental.OrderByDescending(x => x.DollarVolume)
    -            .Take(_numberOfSymbols).Select(x => x.Symbol);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // If we have no changes, do nothing.
    -        if (slice.Bars.Count == 0 || _changes == SecurityChanges.None) return;
    -        // Liquidate removed securities, since they are not the most 
    -        // popular stocks.
    -        foreach (var security in _changes.RemovedSecurities)
    -        {
    -            if (security.Invested)
    -            {
    -                Liquidate(security.Symbol);
    -            }
    -        }
    -        // We want 1/N allocation for each security in our universe to
    -        // evenly dissipate risk.
    -        foreach (var security in _changes.AddedSecurities)
    -        {
    -            SetHoldings(security.Symbol, 1m / _numberOfSymbols);
    -        }
    -        _changes = SecurityChanges.None;
    -    }
    -    
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {
    -        _changes = changes;
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm creates a dynamic universe of the three most liquid US Equities and forms an equal-weighted portfolio with them. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class USEquityCoarseUniverseConstituentsDataAlgorithm(QCAlgorithm):
    -
    -    _number_of_symbols = 3
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -
    -        # Set Asynchronous to True to improve speed performance
    -        self.universe_settings.asynchronous = True
    -            
    -        # Requesting data
    -        self.set_universe_selection(
    -            FundamentalUniverseSelectionModel(self.fundamental_selection_function))
    -        
    -        # we want 1/N allocation in each security in our universe to evenly dissipate risk
    -        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(1)))
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -         
    -        self.add_risk_management(NullRiskManagementModel())
    -        
    -        self.set_execution(ImmediateExecutionModel())
    -
    -    def fundamental_selection_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -        # Select the top traded stocks, since they are the most popular with high capital flow
    -        sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume, reverse=True)
    -        return [ x.symbol for x in sorted_by_dollar_volume[:self._number_of_symbols] ]
    -
    public class USEquityCoarseUniverseConstituentsDataAlgorithm : QCAlgorithm
    -{
    -    private int _numberOfSymbols = 3;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -
    -        // Set Asynchronous to true to improve speed performance
    -        UniverseSettings.Asynchronous = true;
    -
    -        // Requesting data
    -        SetUniverseSelection(
    -            new FundamentalUniverseSelectionModel(FundamentalSelectionFunction));
    -
    -        // we want 1/N allocation in each security in our universe to evenly dissipate risk
    -        SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)));
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -        
    -        AddRiskManagement(new NullRiskManagementModel());
    -        
    -        SetExecution(new ImmediateExecutionModel());
    -    }
    -
    -    public IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamental)
    -    {
    -        // Select the top traded stocks, since they are the most popular with high capital flow
    -        return fundamental.OrderByDescending(x => x.DollarVolume)
    -            .Take(_numberOfSymbols).Select(x => x.Symbol);
    -    }
    -}
    -
    -

    - Research Example -

    -

    - The following example lists the three most liquid US Equities: -

    -
    -
    var qb = new QuantBook();
    -
    -// Add Fundamental Universe Selection
    -IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamentals)
    -{
    -    return fundamentals.OrderByDescending(x => c.DollarVolume).Take(10).Select(x => c.Symbol);
    -}
    -
    -var universe = qb.AddUniverse(FundamentalSelectionFunction); 
    -
    -// Historical Universe data
    -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var fundamentals in universeHistory)
    -{
    -    foreach (Fundamental fundamental in fundamentals)
    -    {
    -        Console.WriteLine($"{fundamental.Symbol} dollar volume at {fundamental.EndTime}: {fundamental.DollarVolume}");
    -    }
    -}
    -
    qb = QuantBook()
    -
    -# Add Fundamental Universe Selection
    -def fundamental_selection_function(fundamentals):
    -    selected = sorted(fundamentals, key=lambda x: x.dollar_volume, reverse=True)[:10]
    -    return [x.symbol for x in selected]
    -
    -universe = qb.add_universe(fundamental_selection_function)
    -
    -# Historical Universe data
    -universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (universe_symbol, time), fundamentals in universe_history.items():
    -    for fundamental in fundamentals:
    -        print(f"{fundamental.symbol} dollar volume at {fundamental.end_time}: {fundamental.dollar_volume}")
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Equity Coarse Universe dataset provides its data within - - Fundamental - - objects, which have the following . The attributes from - - market_cap - - - MarketCap - - to - - asset_classification - - - AssetClassification - - listed in the following widget are NaN until this dataset is combined with the - - MorningStar Fundamental - - dataset. -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Equity Option Universe

    -
    -
    -

    Introduction

    - - -

    - The US Equity Option Universe dataset by QuantConnect lists the available US Equity Options contracts and the current Implied Volatility and Greeks. The data covers 4,000 Symbols, starts in January 2012, and is delivered on a daily update frequency. To create this dataset, we use - - our implementation - - of the forward tree pricing model, which accounts for the interest rate, dividend payments, and daily closing prices. The values in this dataset are the same values you can get from daily - - indicators - - with mirror Options. -

    -

    - This dataset depends on the - - US Equity Security Master - - dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes of the underlying security. -

    -

    - This dataset - - does not - - contain market data. For market data, see - - US Equity Options by AlgoSeek - - . -

    -

    - For more information about the US Equity Option Universe dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Equity Options Universe dataset: -

    -
    -
    option = self.add_option("GOOG")
    -self.option_symbol = option.symbol
    -option.set_filter(lambda universe: universe.delta(0.4, 0.6))
    -
    var option = AddOption("GOOG");
    -_optionSymbol = option.Symbol;
    -option.SetFilter(universe => universe.delta(0.4m, 0.6m));
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2012 -
    - Asset Coverage - - 4,000 Symbols -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - - New York -
    - - - -

    Requesting Data

    - - -

    - To add US Equity Options Universe data to your algorithm, call the - - AddOption - - - add_option - - method. Save a reference to the Equity Option - - Symbol - - so you can access the data later in your algorithm. To define which contracts should be in your universe, call the - - SetFilter - - - set_filter - - method of the Option object. -

    -

    - The - - AddOption - - - add_option - - method provides a daily stream of Option chain data. To get the most recent daily chain, call the - - OptionChain - - - option_chain - - method with the underlying Equity Symbol. The - - OptionChain - - - option_chain - - method returns data on all the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    class USEquityOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        option = self.add_option("GOOG")
    -        self.option_symbol = option.symbol
    -        # Set our strike/expiry filter for this option chain
    -        option.set_filter(self._option_filter)
    -        # Get the entire Option chain for the current day.
    -        chain = self.option_chain(option.symbol.underlying, flatten=True).data_frame
    -
    -    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Contracts can be filtered by greeks, implied volatility, open interest:
    -        return universe \
    -            .delta(0.5, 1.5) \
    -            .gamma(0.0001, 0.0006) \
    -            .vega(0.01, 1.5) \
    -            .theta(-2.0, -0.5) \
    -            .rho(0.5, 3.0) \
    -            .implied_volatility(1, 3) \
    -            .open_interest(100,500)
    -
    -
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _optionSymbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        // Requesting data
    -        var option = AddOption("GOOG");
    -        _optionSymbol = option.Symbol;
    -        // Set our strike/expiry filter for this option chain
    -        option.SetFilter(OptionFilter);
    -        // Get the entire Option chain for the current day.
    -        var chain = OptionChain(option.Symbol.Underlying);
    -    }
    -
    -    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    -    {
    -        // Contracts can be filtered by greeks, implied volatility, open interest:
    -        return universe
    -            .Delta(0.5m, 1.5m)
    -            .Gamma(0.0001m, 0.0006m)
    -            .Vega(0.01m, 1.5m)
    -            .Theta(-2.0m, -0.5m)
    -            .Rho(0.5m, 3.0m)
    -            .ImpliedVolatility(1.0m, 3.0m)
    -            .OpenInterest(100, 500);
    -    }
    -}
    -
    -

    - The Equity resolution must be less than or equal to the Equity Option resolution. For example, if you set the Equity resolution to minute, then you must set the Equity Option resolution to minute, hour, or daily. -

    -

    - For more information about creating US Equity Option Universes, see - - Equity Options - - . -

    - - - -

    Accessing Data

    - - -

    - For information about accessing US Equity Options Universe data, see - - Equity Options - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Equity Options Universe data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Equity Options Universe data in an algorithm, call the - - History<OptionUniverse> - - - history - - method with the canonical Equity Option - - Symbol - - . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.option_symbol, timedelta(3), flatten=True)
    -
    -# OptionUniverse objects
    -history = self.history[OptionUniverse](self.option_symbol, timedelta(3))
    -
    // OptionUniverse objects 
    -var history = History<OptionUniverse>(_optionSymbol, TimeSpan.FromDays(3)).ToList();
    -
    -

    - For more information about historical Equity Options Universe data in algorithms, see - - Historical Data - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Equity Options Universe data in the Research Environment, call the - - History<OptionUniverse> - - - history - - method with the canonical Option - - Symbol - - . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    qb = QuantBook()
    -option = qb.add_option("GOOG")
    -history = qb.history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5), flatten=True)
    -
    var qb = new QuantBook();
    -var option = qb.AddOption("GOOG");
    -var history = qb.History<OptionUniverse>(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 6));
    -foreach (var chain in history)
    -{
    -    var endTime = chain.EndTime;
    -    var filteredContracts = chain.Data
    -        .Select(contract => contract as OptionUniverse)
    -        .Where(contract => contract.Greeks.Delta > 0.3m);
    -    foreach (var contract in filteredContracts)
    -    {
    -        var price = contract.Price;
    -        var iv = contract.ImpliedVolatility;
    -    }
    -}
    -
    -

    - For more information about historical Equity Options Universe data in the Research Environment, see - - Universes - - . -

    - - - -

    Supported Assets

    - - -

    - To view the supported assets in the US Equity Options Universe dataset, see the - - Data Explorer - - . -

    - - - -

    Example Applications

    - - -

    - The US Equity Options Universe dataset enables you to accurately design Option strategies. Examples include the following strategies: -

    -
      -
    • - Buying put Options to hedge against downward price movement in positive Equity positions -
    • -
    • - Exploiting arbitrage opportunities that arise when the price of Option contracts deviate from their theoretical value -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm subscribes to Google put options that fall within delta range between -1 and -0.95, open interest range between 10 and 1000, and expire within seven days. Within this Option chain, the algorithm holds the put Option contract that has the minimum delta (closest to -1) during market hour to hedge the underlying intra-day movement completely. It avoid volatility from sentiment and only earns from inter-day movement from longer-term factors. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. -

    -
    -
    from AlgorithmImports import *
    -
    -class USEquityOptionsUniverseAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(10000000)
    -
    -        # Asynchronous can use computational resources efficiently
    -        self.universe_settings.asynchronous = True
    -        # Subscribe to the underlying for the underlying position
    -        # Set the data normalization mode to raw for strike price comparability
    -        self.equity = self.add_equity("GOOG", data_normalization_mode=DataNormalizationMode.RAW).symbol
    -        # Requesting option data and filter for the hedge candidates
    -        option = self.add_option(self.equity)
    -        option.set_filter(self.option_filter)
    -        self.option_symbol = option.symbol
    -
    -        # Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    -        self.schedule.on(
    -            self.date_rules.every_day(self.equity),
    -            self.time_rules.after_market_open(self.equity, 1),
    -            self.buy_hedge_contract
    -        )
    -
    -        # Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    -        # Leave 2 minutes contingency to fill
    -        self.schedule.on(
    -            self.date_rules.every_day(self.equity),
    -            self.time_rules.before_market_close(self.equity, 2),
    -            self.sell_hedge_contract
    -        )
    -
    -        self.hedge = None
    -        
    -    def option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Select the contracts with delta very close to -1 and high open interest
    -        # This can effectively hedge most of the price change of the underlying and ensure the liquidity
    -        # Make sure the contract is expiring close for its tradbility
    -        return universe.puts_only().expiration(2, 7).delta(-1, -0.95).open_interest(10, 1000)
    -
    -    def buy_hedge_contract(self) -> None:
    -        chain = self.current_slice.option_chains.get(self.option_symbol)
    -        if chain:
    -            # Order the underlying if not hold, the order size should match the option contract
    -            # Order only if option chain data ready for hedging
    -            if not self.portfolio[self.equity].invested:
    -                self.market_order(self.equity, self.securities[self.option_symbol].symbol_properties.contract_multiplier)
    -
    -            # Get the contract with delta closest to -1 (lowest possible delta)
    -            contract = sorted(chain, key=lambda x: x.greeks.delta)[0]
    -            self.hedge = contract.symbol
    -            # Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    -            self.market_order(self.hedge, 1)
    -        
    -    def sell_hedge_contract(self) -> None:
    -        # Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    -        if self.hedge:
    -            self.liquidate(self.hedge)
    -            self.hedge = None
    -
    public class USEquityOptionsUniverseAlgorithm : QCAlgorithm
    -{
    -    private Symbol _equity, _optionSymbol, _hedge;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(10000000);
    -        // Asynchronous can use computational resources efficiently
    -        UniverseSettings.Asynchronous = true;
    -
    -        // Subscribe to the underlying for the underlying position
    -        // Set the data normalization mode to raw for strike price comparability
    -        _equity = AddEquity("GOOG", dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
    -        // Requesting option data and filter for the hedge candidates
    -        var option = AddOption(_equity);
    -        _optionSymbol = option.Symbol;
    -        option.SetFilter(OptionFilter);
    -
    -        // Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    -        Schedule.On(
    -            DateRules.EveryDay(_equity),
    -            TimeRules.AfterMarketOpen(_equity, 1),
    -            BuyHedgeContract
    -        );
    -
    -        // Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    -        // Leave 2 minutes contingency to fill
    -        Schedule.On(
    -            DateRules.EveryDay(_equity),
    -            TimeRules.BeforeMarketClose(_equity, 2),
    -            SellHedgeContract
    -        );
    -    }
    -
    -    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    -    {
    -        // Select the contracts with delta very close to -1 and high open interest
    -        // This can effectively hedge most of the price change of the underlying and ensure the liquidity
    -        // Make sure the contract is expiring close for its tradbility
    -        return universe
    -            .PutsOnly()
    -            .Expiration(2, 7)
    -            .Delta(-1m, -0.95m)
    -            .OpenInterest(10, 1000);
    -    }
    -
    -    private void BuyHedgeContract()
    -    {
    -        if (CurrentSlice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    -        {
    -            // Order the underlying if not hold, the order size should match the option contract
    -            // Order only if option chain data ready for hedging
    -            if (!Portfolio[_equity].Invested)
    -            {
    -                MarketOrder(_equity, Securities[_optionSymbol].SymbolProperties.ContractMultiplier);
    -            }
    -
    -            // Get the contract with delta closest to -1 (lowest possible delta)
    -            var contract = chain.MinBy(x => x.Greeks.Delta);
    -            _hedge = contract.Symbol;
    -            // Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    -            MarketOrder(_hedge, 1);
    -        }
    -    }
    -
    -    private void SellHedgeContract()
    -    {
    -        // Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    -        if (_hedge != null)
    -        {
    -            Liquidate(_hedge);
    -            _hedge = null;
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm demonstrating a Gamma Scalping strategy through framework algorithm. It filters NVDA options with expiration between 30 to 90 days and open interest between 50 and 1000, due to liquidity concern and lower Gamma fluctuation. Assuming a significant upward trend is expecting, it orders a long straddle strategy from the strike price with Delta-neutral and the highest Gamma to earn the highest profit from upward underlying movement. -

    -
    -
    from AlgorithmImports import *
    -
    -class USEquityOptionsUniverseFrameworkAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        # Asynchronous can use computational resources efficiently
    -        self.universe_settings.asynchronous = True
    -
    -        # Universe selection that select based on liquidity of the option contracts (by open interest)
    -        self.add_universe_selection(EquityOptionsUniverseSelectionModel())
    -        # Custom alpha model that use Delta and Gamma to signal insights
    -        self.add_alpha(OptionDeltaGammaAlphaModel())
    -        # To maintain long-short size equal, use a PCM that order a single contract
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -
    -class EquityOptionsUniverseSelectionModel(OptionUniverseSelectionModel):
    -    def __init__(self) -> None:
    -        # Daily update with the select_option_chain_symbols function
    -        super().__init__(timedelta(1), self.select_option_chain_symbols)
    -
    -    def select_option_chain_symbols(self, dt: datetime) -> List[Symbol]:
    -        # Select only NVDA options as our focus, which is a highly traded volatile equity with great upward momentum
    -        return [Symbol.create("NVDA", SecurityType.OPTION, Market.USA)]
    -
    -    def filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    -        # A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    -        return universe.expiration(30, 90).open_interest(50, 1000)
    -
    -class OptionDeltaGammaAlphaModel(AlphaModel):
    -    def __init__(self) -> None:
    -        # A day count variable to control the alpha model only trade once a day
    -        self._day = -1
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        insights = []
    -
    -        if self._day != slice.time.day:
    -            # We open position for each option underlying as separate bet
    -            for _, chain in slice.option_chains.items():
    -                # For theta-neutral, select the same expiry for both call and put
    -                expiry = min(x.expiry for x in chain)
    -                contracts = [x for x in chain if x.expiry == expiry]
    -
    -                # Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    -                delta_gamma_symbols = []
    -                strikes = set(x.strike for x in contracts if len([y for y in contracts if y.strike == x.strike]) == 2)
    -                for strike in strikes:
    -                    # Get both call and put for their aggregated delta and gamma
    -                    call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == strike, contracts))
    -                    put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == strike, contracts))
    -                    delta_gamma_symbols.append((call.greeks.delta + put.greeks.delta, call.greeks.gamma + put.greeks.gamma, call.symbol, put.symbol))
    -                
    -                if len(delta_gamma_symbols) == 0:
    -                    continue
    -
    -                # We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    -                # Less than 2d.p. difference is non-significant, which we can risk for better reward
    -                # Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    -                # Make sure the aggregated gamma to be positive to bet on large uptrend
    -                # So it will earn more when the price really go up higher and higher, but locally immune for small noise
    -                filtered = [item for item in delta_gamma_symbols if round(item[0], 2) <= 0.01 and item[1] > 0]
    -                if len(filtered) == 0:
    -                    continue
    -                selected = sorted(filtered, key=lambda x: x[1], reverse=True)[0]
    -
    -                # Provide trade signal and roll the day count to let the position stay for the whole day
    -                selected_call = selected[2]
    -                selected_put = selected[3]
    -                insights.extend([
    -                    Insight.price(selected_call, Expiry.END_OF_DAY, InsightDirection.UP),
    -                    Insight.price(selected_put, Expiry.END_OF_DAY, InsightDirection.UP)
    -                ])
    -                self._day = slice.time.day
    -        
    -        return insights
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                # Use a whole number target to order the exact number of share for size-matching
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class USEquityOptionsUniverseFrameworkAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        // Asynchronous can use computational resources efficiently
    -        UniverseSettings.Asynchronous = true;
    -
    -        // Universe selection that select based on liquidity of the option contracts (by open interest)
    -        AddUniverseSelection(new EquityOptionsUniverseSelectionModel());
    -        // Custom alpha model that use Delta and Gamma to signal insights
    -        AddAlpha(new OptionDeltaGammaAlphaModel());
    -        // To maintain long-short size equal, use a PCM that order a single contract
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}       
    -    
    -class EquityOptionsUniverseSelectionModel : OptionUniverseSelectionModel
    -{
    -    // Daily update with the SelectOptionChainSymbols function
    -    public EquityOptionsUniverseSelectionModel()
    -            : base(TimeSpan.FromDays(1), SelectOptionChainSymbols) {}
    -    
    -    private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
    -    {
    -        // Select only NVDA options as our focus, which is a highly traded volatile equity with great upward momentum
    -        return new[] {QuantConnect.Symbol.Create("NVDA", SecurityType.Option, Market.USA)};
    -    }
    -
    -    protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
    -    {
    -        // To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    -        // A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    -        return filter
    -            .Expiration(30, 90)
    -            .OpenInterest(50, 1000);
    -    }
    -}
    -    
    -class OptionDeltaGammaAlphaModel : AlphaModel
    -{
    -    // A day count variable to control the alpha model only trade once a day
    -    private int _day = -1;
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -        
    -        if (_day != slice.Time.Day)
    -        {
    -            // We open position for each option underlying as separate bet
    -            foreach (var kvp in slice.OptionChains)
    -            {
    -                var chain = kvp.Value;
    -
    -                // For theta-neutral, select the same expiry for both call and put
    -                var expiry = chain.Min(x => x.Expiry);
    -                var contracts = chain.Where(x => x.Expiry == expiry).ToList();
    -
    -                // Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    -                var deltaGammaSymbols = new List<(decimal, decimal, Symbol, Symbol)>();
    -                var strikes = contracts.Select(x => x.Strike)
    -                    .Where(x => contracts.Count(y => y.Strike == x) == 2)
    -                    .Distinct();
    -                foreach (var strike in strikes)
    -                {
    -                    // Get both call and put for their aggregated delta and gamma
    -                    var call = contracts.Single(x => x.Right == OptionRight.Call && x.Strike == strike);
    -                    var put = contracts.Single(x => x.Right == OptionRight.Put && x.Strike == strike);
    -                    deltaGammaSymbols.Add((call.Greeks.Delta + put.Greeks.Delta, call.Greeks.Gamma + put.Greeks.Gamma, call.Symbol, put.Symbol));
    -                }
    -
    -                if (deltaGammaSymbols.Count == 0)
    -                {
    -                    continue;
    -                }
    -
    -                // We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    -                // Less than 2d.p. difference is non-significant, which we can risk for better reward
    -                // Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    -                // Make sure the aggregated gamma to be positive to bet on large uptrend
    -                // So it will earn more when the price really go up higher and higher, but locally immune for small noise
    -                var filtered = deltaGammaSymbols.Where(item => Math.Round(item.Item1, 2) <= 0.01m && item.Item2 > 0).ToList();
    -                if (filtered.Count == 0)
    -                {
    -                    continue;
    -                }
    -                var selected = filtered.OrderByDescending(item => item.Item2).First();
    -
    -                // Provide trade signal and roll the day count to let the position stay for the whole day
    -                var selectedCall = selected.Item3;
    -                var selectedPut = selected.Item4;
    -                insights.AddRange(new[] {
    -                    Insight.Price(selectedCall, Expiry.EndOfDay, InsightDirection.Up),
    -                    Insight.Price(selectedPut, Expiry.EndOfDay, InsightDirection.Up)
    -                });
    -                _day = slice.Time.Day;
    -            }
    -        }
    -
    -        return insights;
    -    }
    -}
    -    
    -class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        var targets = new List<PortfolioTarget>();
    -        foreach (var insight in insights)
    -        {
    -            if (algorithm.Securities[insight.Symbol].IsTradable)
    -            {
    -                // Use a whole number target to order the exact number of share for size-matching
    -                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -            }
    -        }
    -        return targets;
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Equity Options Universe dataset provides - - OptionFilterUniverse - - , - - OptionUniverse - - , and - - OptionChain - - objects. -

    -

    - OptionFilterUniverse Attributes -

    -

    - - OptionFilterUniverse - - objects have the following attributes: -

    -
    -
    -

    - OptionUniverse Attributes -

    -

    - - OptionUniverse - - objects have the following attributes: -

    -
    -
    -

    - OptionChain Attributes -

    -

    - - OptionChain - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Equity Security Master

    -
    -
    -

    Introduction

    - - -

    - The US Equity Security Master dataset by QuantConnect tracks US Equity corporate actions, including splits, dividends, delistings, mergers, and ticker changes through history. The data covers approximately 27,500 US Equities, starts in January 1998, and is delivered on a daily update frequency. You can easily download and install the dataset with the LEAN CLI so it's ready to use by LEAN. LEAN automatically handles all corporate actions and passes them into your algorithm as - - events - - . -

    -

    - This is - - NOT - - the underlying Equity data ( - - US Equities - - dataset), which you need to purchase separately with a license from AlgoSeek. This security master dataset is required to purchase the US Equities or US Equities Options datasets. -

    -

    - For more information about the US Equity Security Master dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Data Summary

    - - -

    - Data is delivered as a daily updated zip archive of map and factor files. The data is designed to be used in the LEAN Engine and cannot be consumed another way. The following table shows the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 1998 -
    - Data Points - - Splits, Dividends, Mergers, IPO, & Delistings -
    - Asset Coverage - - 27,500 US Equities -
    - Resolution - - Daily -
    - Timezone - - New York -
    -

    - This is - - not - - the underlying Equity data ( - - US Equities - - dataset), which you need to purchase separately with a license from AlgoSeek. This security master dataset is required to purchase the US Equities or US Equities Options datasets. -

    - - - -

    Getting Started

    - - -

    - You don't need any special code to utilize the US Equity Security Master. It automatically loads when you - - request US Equities data - - . -

    - - - -

    Accessing Splits

    - - -

    - To get the current split data, index the - - Splits - - - splits - - property of the current - - - Slice - - - with the Equity - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Check if any splits for the symbol
    -    if slice.splits.contains_key(self._symbol):
    -        # If so, get the mapped split object
    -        split = slice.splits[self._symbol]
    -        split_type = {0: "Warning", 1: "SplitOccurred"}.get(split.type)
    -        self.log(f"Split: {split.symbol}\t{split.split_factor}\t{split.reference_price}\t{split_type}")
    -
    public override void OnData(Slice slice)
    -{
    -    // Check if any splits for the symbol
    -    if (slice.Splits.ContainsKey(_symbol))
    -    {
    -        // If so, get the mapped split object
    -        var split = slice.Splits[_symbol];
    -        Log($"Split: {split.Symbol}\t{split.SplitFactor}\t{split.ReferencePrice}\t{split.Type}");
    -    }
    -}
    -
    -

    - For more information about accessing splits, see - - Splits - - . -

    - - - -

    Accessing Dividends

    - - -

    - To get the current dividend data, index the - - Dividends - - - dividends - - property of the current - - Slice - - with the Equity - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Check if any dividend for the symbol
    -    if slice.dividends.contains_key(self._symbol):
    -        # If so, get the mapped dividend object
    -        dividend = slice.dividends[self._symbol]
    -        self.log(f'Dividend: {dividend.symbol}\t{dividend.distribution}\t{dividend.reference_price}')
    -
    public override void OnData(Slice slice)
    -{
    -    // Check if any dividend for the symbol
    -    if (slice.Dividends.ContainsKey(_symbol))
    -    {
    -        // If so, get the mapped dividend object
    -        var dividend = slice.Dividends[_symbol];
    -        Log($"Dividend: {dividend.Symbol}\t{dividend.Distribution}\t{dividend.ReferencePrice}");
    -    }
    -}
    -
    -

    - For more information about accessing dividends, see - - Dividends - - . -

    - - - -

    Accessing Delistings

    - - -

    - To get the current Delistings data, index the - - Delistings - - - delistings - - property of the current - - Slice - - with the Equity - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Check if any delisting for the symbol
    -    if slice.delistings.contains_key(self._symbol):
    -        # If so, get the mapped delisting object
    -        delisting = slice.delistings[self._symbol]
    -        delisting_type = {0: "Warning", 1: "Delisted"}.get(delisting.type)
    -        self.log(f'Delistings: {delisting_type}')
    -
    public override void OnData(Slice slice)
    -{
    -    // Check if any delisting for the symbol
    -    if (slice.Delistings.ContainsKey(_symbol))
    -    {
    -        // If so, get the mapped delisting object
    -        var delisting = slice.Delistings[_symbol];
    -        Log($"Delistings: {delisting.Type}");
    -    }
    -}
    -
    -

    - For more information about accessing delistings, see - - Delistings - - . -

    - - - -

    Accessing Symbol Change Events

    - - -

    - To get the current Symbol change events, index the - - SymbolChangedEvents - - - symbol_changed_events - - property of the current - - Slice - - with the Equity - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Check if any symbol change event for the symbol
    -    if slice.symbol_changed_events.contains_key(self._symbol):
    -        # If so, get the mapped SymbolChangeEvent object
    -        symbol_changed_event = slice.symbol_changed_events[self._symbol]
    -        self.log(f"Symbol changed: {symbol_changed_event.old_symbol} -> {symbol_changed_event.new_symbol}")
    -
    -
    -public override void OnData(Slice slice){
    -    // Check if any symbol change event for the symbol
    -    if (slice.SymbolChangedEvents.ContainsKey(_symbol))
    -    {
    -        // If so, get the mapped SymbolChangeEvent object
    -        var symbolChangedEvent = slice.SymbolChangedEvents[_symbol];
    -        Log($"Symbol changed: {symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.NewSymbol}");
    -    }
    -}
    -
    -

    - For more information about accessing Symbol change events, see - - Symbol Changes - - . -

    - - - -

    Historical Data

    - - -

    - To get historical US Equity Security Master data, call the - - History - - - history - - method with the data type and the Equity - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # Splits
    -split_history_df = self.history(Split, self._symbol, timedelta(5*365))
    -split_history = self.history[Split](self._symbol, timedelta(5*365))
    -
    -# Dividends
    -dividend_history_df = self.history(Dividend, self._symbol, timedelta(5*365))
    -dividend_history = self.history[Dividend](self._symbol, timedelta(5*365))
    -
    -# Symbol Changes
    -symbol_change_history_df = self.history(SymbolChangedEvent, self._symbol, timedelta(5*365))
    -symbol_change_history = self.history[SymbolChangedEvent](self._symbol, timedelta(5*365))
    -
    -# Delistings
    -delisting_history_df = self.history(Delisting, self._symbol, timedelta(5*365))
    -delisting_history = self.history[Delisting](self._symbol, timedelta(5*365))
    -
    // Splits
    -var splitHistory = History<Split>(_symbol, TimeSpan.FromDays(5*365));
    -
    -// Dividends 
    -var dividendHistory = History<Dividend>(_symbol, TimeSpan.FromDays(5*365));
    -
    -// Symbol Changes
    -var symbolChangeHistory = History<SymbolChangedEvent>(_symbol, TimeSpan.FromDays(5*365));
    -
    -// Delistings
    -var delistingHistory = History<Delisting>(_symbol, TimeSpan.FromDays(5*365));
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Live Trading Considerations

    - - -

    - In backtesting, corporate actions occurs at midnight (ET). In live trading, the live data for corporate actions arrives at 6/7 AM ET, so that's when they occur. -

    - - - -

    Supported Assets

    - - -

    - To view the supported assets in the US Equity Security Master dataset, see the - - Data Explorer - - . This dataset doesn't include Over-the-Counter (OTC) stocks. -

    - - - -

    Example Applications

    - - -

    - The US Security Master enables you to accurately design strategies harnessing any core corporate actions. Examples include the following strategies: -

    -
      -
    • - Post-dividend announcement trading strategies. -
    • -
    • - Trading on new Equities by monitoring for IPOs. -
    • -
    • - Harnessing split announcements for reverse-split announcement momentum. -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm logs the - - Split - - , - - Dividend - - , - - Delisting - - , and - - SymbolChangedEvent - - objects of Apple: -

    -
    -
    from AlgorithmImports import *
    -
    -class USEquitySecurityMasterAlgorithm (QCAlgorithm):
    -
    -    def initialize(self):
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(1000000)
    -        
    -        self.equity = self.add_equity("AAPL", Resolution.DAILY).symbol
    -        
    -    def on_data(self, slice: Slice) -> None:
    -        # Accessing Data - Splits
    -        split = slice.splits.get(self.equity)
    -        if split:
    -            self.debug(f"{self.time} >> SPLIT >> {split.symbol} - {split.split_factor} - {self.portfolio.cash} - {self.portfolio[self.equity].price}")
    -        
    -        # Accessing Data - Dividends
    -        dividend = slice.dividends.get(self.equity)
    -        if dividend:
    -            self.debug(f"{self.time} >> DIVIDEND >> {dividend.symbol} - {dividend.distribution} - {self.portfolio.cash} - {self.portfolio[self.equity].price}")
    -
    -        # Accessing Data - Delisting
    -        delisting = slice.delistings.get(self.equity)
    -        if delisting:
    -            delistingType = {0: "Warning", 1: "Delisted"}.get(delisting.type)
    -            self.debug(f"{self.time} >> DELISTING >> {delisting.symbol} - {delistingType}")
    -            
    -        # Accessing Data - Symbol Changed Event
    -        symbolChangedEvent = slice.symbol_changed_events.get(self.equity)
    -        if symbolChangedEvent:
    -            self.debug(f"{self.time} >> SYMBOL CHANGED >> {symbolChangedEvent.old_symbol} -> {symbolChangedEvent.new_symbol}")
    -
    -
    public class USEquitySecurityMasterAlgorithm : QCAlgorithm
    -{
    -    private Symbol _equity;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -        
    -        _equity = AddEquity("AAPL", Resolution.Daily).Symbol;
    -    }
    -    
    -    public override void OnData(Slice slice)
    -    {
    -        // Accessing Data - Splits
    -        if (slice.Splits.ContainsKey(_equity))
    -        {
    -            var split = slice.Splits[_equity];
    -            Debug($"Split: {split.Symbol}\t{split.SplitFactor}\t{split.ReferencePrice}\t{split.Type}");
    -        }
    -        
    -        // Accessing Data - Dividends
    -        if (slice.Dividends.ContainsKey(_equity))
    -        {
    -            var dividend = slice.Dividends[_equity];
    -            Log($"Dividend: {dividend.Symbol}\t{dividend.Distribution}\t{dividend.ReferencePrice}");
    -        }
    -        
    -        // Accessing Data - Delisting
    -        if (slice.Delistings.ContainsKey(_equity))
    -        {
    -            var delisting = slice.Delistings[_equity];
    -            Log($"Delistings: {delisting.Type}");
    -        }
    -        
    -        // Accessing Data - Symbol Changed Event
    -        if (slice.SymbolChangedEvents.ContainsKey(_equity))
    -        {
    -            var symbolChangedEvent = slice.SymbolChangedEvents[_equity];
    -            Log($"Symbol changed: {symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.NewSymbol}");
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following algorithm demonstrates the payments for cash dividends in backtesting. When the data normalization mode is - - Raw - - , your portfolio receives cash dividends. -

    -
    -
    from AlgorithmImports import *
    -
    -class PaymentAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -
    -        # this will use the Tradier Brokerage open order split behavior
    -        # forward split will modify open order to maintain order value
    -        # reverse split open orders will be canceled
    -        self.set_brokerage_model(BrokerageName.TRADIER_BROKERAGE)
    -
    -        self.universe_settings.resolution = Resolution.DAILY
    -        self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
    -        
    -        # MSFT: Splits and Dividends
    -        # GOOG: Symbol Changed Event
    -        # AAA.1: Delisting
    -        
    -        self.set_universe_selection(ManualUniverseSelectionModel(
    -            Symbol.create("MSFT", SecurityType.EQUITY, Market.USA)))
    -
    -        self.set_alpha(PaymentAlphaModel())
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -        self.set_execution(BracketExecutionModel())
    -            
    -class PaymentAlphaModel(AlphaModel):
    -
    -    symbol = Symbol.EMPTY
    -    
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        # Accessing Data - Splits
    -        split = slice.splits.get(self.symbol)
    -        if split:
    -            algorithm.debug(f"{algorithm.time} >> SPLIT >> {split.symbol} - {split.split_factor} - {algorithm.portfolio.cash} - {algorithm.portfolio[self.symbol].price}")
    -
    -        # Accessing Data - Dividends
    -        dividend = slice.dividends.get(self.symbol)
    -        if dividend:
    -            algorithm.debug(f"{algorithm.time} >> DIVIDEND >> {dividend.symbol} - {dividend.distribution} - {algorithm.portfolio.cash} - {algorithm.portfolio[self.symbol].price}")
    -
    -        # Accessing Data - Delistings
    -        delisting = slice.delistings.get(self.symbol)
    -        if delisting:
    -            delistingType = {0: "Warning", 1: "Delisted"}.get(delisting.type)
    -            algorithm.debug(f"{algorithm.time} >> DELISTING >> {delisting.symbol} - {delistingType}")
    -
    -        # Accessing Data - Symbol Changed Events
    -        symbolChangedEvent = slice.symbol_changed_events.get(self.symbol)
    -        if symbolChangedEvent:
    -            algorithm.debug(f"{algorithm.time} >> SYMBOL CHANGED >> {symbolChangedEvent.old_symbol} -> {symbolChangedEvent.new_symbol}")
    -
    -        bar = slice.bars.get(self.symbol)
    -        return [Insight.price(self.symbol, timedelta(1), InsightDirection.UP)] if bar else []
    -
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        self.symbol = list(changes.added_securities)[0].symbol
    -
    -class BracketExecutionModel(ExecutionModel):
    -    
    -    def __init__(self) -> None:
    -        '''Initializes a new instance of the ImmediateExecutionModel class'''
    -        self.targets_collection = PortfolioTargetCollection()
    -
    -    def execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None:
    -
    -        # for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    -        self.targets_collection.add_range(targets)
    -        if self.targets_collection.count > 0:
    -            for target in self.targets_collection.order_by_margin_impact(algorithm):
    -                # calculate remaining quantity to be ordered
    -                quantity = OrderSizing.get_unordered_quantity(algorithm, target)
    -                if quantity != 0 and algorithm.transactions.orders_count == 0:
    -                    bar = algorithm.securities[target.symbol].get_last_data()
    -                    algorithm.market_order(target.symbol, quantity)
    -                    # place some orders that won't fill, when the split comes in they'll get modified to reflect the split
    -                    algorithm.stop_market_order(target.symbol, -quantity, bar.low/2)
    -                    algorithm.limit_order(target.symbol, -quantity, bar.high*2)
    -
    -            self.targets_collection.clear_fulfilled(algorithm)
    -
    -
    public class PaymentsAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -            
    -        // this will use the Tradier Brokerage open order split behavior
    -        // forward split will modify open order to maintain order value
    -        // reverse split open orders will be canceled
    -        SetBrokerageModel(BrokerageName.TradierBrokerage);
    -        
    -        UniverseSettings.Resolution = Resolution.Daily;
    -        UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
    -        
    -        // MSFT: Splits and Dividends
    -        // GOOG: Symbol Changed Event
    -        // AAA.1: Delisting
    -        SetUniverseSelection(new ManualUniverseSelectionModel(
    -            QuantConnect.Symbol.Create("MSFT", SecurityType.Equity, Market.USA)));
    -
    -        SetAlpha(new PaymentAlphaModel());
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -        SetExecution(new BracketExecutionModel());
    -    }
    -}
    -
    -public class PaymentAlphaModel : AlphaModel
    -{
    -    private Symbol _symbol = Symbol.Empty;
    -    
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        // Accessing Data - Splits
    -        if (slice.Splits.ContainsKey(_symbol))
    -        {
    -            var split = slice.Splits[_symbol];
    -            algorithm.Debug($"{split.Time.ToIso8601Invariant()} >> SPLIT >> {split.Symbol} - " +
    -                $"{split.SplitFactor.ToStringInvariant()} - " +
    -                $"{algorithm.Portfolio.Cash.ToStringInvariant()} - " +
    -                $"{algorithm.Portfolio[_symbol].Quantity.ToStringInvariant()}");
    -        }
    -        
    -        // Accessing Data - Dividends
    -        if (slice.Dividends.ContainsKey(_symbol))
    -        {
    -            var dividend = slice.Dividends[_symbol];
    -            algorithm.Debug($"{dividend.Time.ToStringInvariant("o")} >> DIVIDEND >> {dividend.Symbol} - " +
    -                $"{dividend.Distribution.ToStringInvariant("C")} - {algorithm.Portfolio.Cash} - " +
    -                $"{algorithm.Portfolio[_symbol].Price.ToStringInvariant("C")}");
    -        }
    -
    -        // Accessing Data - Delisting
    -        if (slice.Delistings.ContainsKey(_symbol))
    -        {
    -            var delisting = slice.Delistings[_symbol];
    -            algorithm.Debug($"{delisting.Time.ToStringInvariant("o")} >> DELISTING >> {delisting.Type}");
    -        }
    -
    -        // Accessing Data - Symbol Changed Event
    -        if (slice.SymbolChangedEvents.ContainsKey(_symbol))
    -        {
    -            var symbolChangedEvent = slice.SymbolChangedEvents[_symbol];
    -            algorithm.Debug($"{symbolChangedEvent.Time.ToStringInvariant("o")} >> Symbol Changed Event >> " +
    -                $"{symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.OldSymbol}");
    -        }
    -        
    -        return slice.Bars.ContainsKey(_symbol)
    -            ? new [] { Insight.Price(_symbol, TimeSpan.FromDays(1), InsightDirection.Up) }
    -            : Enumerable.Empty<Insight>();
    -    }
    -    
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        _symbol = changes.AddedSecurities.First().Symbol;
    -    }
    -}
    -
    -public class BracketExecutionModel : ExecutionModel
    -{
    -    private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
    -
    -    public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
    -    {
    -        _targetsCollection.AddRange(targets);
    -        // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    -        if (_targetsCollection.Count > 0)
    -        {
    -            foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
    -            {
    -                // calculate remaining quantity to be ordered
    -                var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);
    -                if (quantity != 0 && algorithm.Transactions.OrdersCount == 0)
    -                {
    -                    var bar = algorithm.Securities[target.Symbol].GetLastData() as TradeBar;
    -                    algorithm.MarketOrder(target.Symbol, quantity);
    -                    // place some orders that won't fill, when the split comes in they'll get modified to reflect the split
    -                    algorithm.StopMarketOrder(target.Symbol, -quantity, bar.Low/2);
    -                    algorithm.LimitOrder(target.Symbol, -quantity, bar.High*2);
    -                }
    -            }
    -
    -            _targetsCollection.ClearFulfilled(algorithm);
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Equity Security Master dataset provides - - Split - - , - - Dividend - - , - - Delisting - - , and - - SymbolChangedEvent - - objects. -

    -

    - Split Attributes -

    -

    - When a split or merger occurs, we pass the previous - - Symbol - - data into your algorithm. - - Split - - objects have the following attributes: -

    -
    -
    -

    - Dividend Attributes -

    -

    - Dividend events are triggered on the payment date. - - Dividend - - objects have the following attributes: -

    -
    -
    -

    - Delisting Attributes -

    -

    - When a security is delisted, we notify your algorithm. - - Delisting - - objects have the following attributes: -

    -
    -
    -

    - SymbolChangedEvent Attributes -

    -

    - When a security changes their ticker, we notify your algorithm. - - SymbolChangedEvent - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Future Option Universe

    -
    -
    -

    Introduction

    - - -

    - The US Future Option Universe dataset by QuantConnect lists the available US Future Options contracts and the current open interest. The data covers 15 Monthly Future contracts, starts in January 2012, and is delivered on a daily update frequency. This dataset is created by monitoring the trading activity on the CME, CBOT, NYMEX, and COMEX markets. -

    -

    - The US Future Option Universe dataset depends on the - - US Future Universe - - dataset because the US Future Universe dataset contains the universe of underlying Futures contracts. - This dataset also depends on the - - US Futures Security Master - - dataset because the US Futures Security Master dataset contains information on symbol changes of the contracts. -

    -

    - This dataset - - does not - - contain market data. For market data, see - - US Future Options by AlgoSeek - - . -

    -

    - For more information about the US Future Option Universe dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Future Options Universe dataset: -

    -
    -
    future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    -future.set_filter(0, 90)
    -self.add_future_option(future.symbol, lambda universe: universe.strikes(-1, 1))
    -
    var future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    -future.SetFilter(0, 90);
    -AddFutureOption(future.Symbol, universe => universe.Strikes(-1, 1));
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2012 -
    - Asset Coverage - - 15 Monthly Future Contracts. Standard expires only. No weeklies or 0DTE contracts. -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - - New York -
    - Market Hours - - - Regular and Extended - -
    - - - -

    Requesting Data

    - - -

    - To add US Future Options Universe data to your algorithm, call the - - AddFutureOption - - - add_future_option - - method. To define which contracts should be in your universe, specify the filter when requesting the Future Option data. -

    -

    - The - - AddFutureOption - - - add_future_option - - method provides a daily stream of Option chain data. To get the most recent daily chain, call the - - OptionChain - - - option_chain - - method with the underlying Future Symbol. The - - OptionChain - - - option_chain - - method returns data on all the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    class USFutureOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        
    -        self.future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    -        self.future.set_filter(0, 90)
    -        # Set our strike/expiry filter for this option chain
    -        self.add_future_option(self.future.symbol, self._option_filter)
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Get the entire Option chain for the current day.
    -        symbol = Symbol.create_canonical_option(self.future.mapped)
    -        chain = self.option_chain(symbol, flatten=True).data_frame
    -
    -    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Contracts can be filtered by strike, and expiration
    -        return universe.strikes(-1, 1)
    -
    public class USFutureOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Future _future;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        
    -        _future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    -        _future.SetFilter(0, 90);
    -        // Set our strike/expiry filter for this option chain
    -        AddFutureOption(_future.Symbol, OptionFilter);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol.
    -        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_future.Mapped);
    -        // Get the entire Option chain for the current day.
    -        var chain = OptionChain(symbol);
    -    }
    -
    -    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    -    {
    -        // Contracts can be filtered by strike, and expiration
    -        return universe.Strikes(-1, 1);
    -    }
    -}
    -
    -

    - The Future resolution must be less than or equal to the Future Option resolution. For example, if you set the Future resolution to minute, then you must set the Future Option resolution to minute, hour, or daily. -

    -

    - For more information about creating US Future Option universes, see - - Future Options - - . -

    - - - -

    Accessing Data

    - - -

    - For information about accessing US Future Options Universe data, see - - Future Options - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Future Options Universe data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Future Options Universe data in an algorithm, call the - - History<OptionUniverse> - - - history - - method with the canonical mapped Future Option - - Symbol - - . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty. -

    -
    -
    future_option_symbol = Symbol.create_canonical_option(self.future.mapped)
    -# DataFrame
    -history_df = self.history(future_option_symbol, timedelta(10), flatten=True)
    -# OptionUniverse objects
    -history = self.history[OptionUniverse](future_option_symbol, timedelta(10))
    -
    var futureOptionSymbol = QuantConnect.Symbol.CreateCanonicalOption(_future.Mapped);
    -var history = History<OptionUniverse>(futureOptionSymbol, TimeSpan.FromDays(10)).ToList();
    -
    -

    - For more information about historical US Future Options Universe data in algorithms, see - - Historical Data - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Future Options Universe data in the Research Environment, call the - - History<OptionUniverse> - - - history - - method with the canonical Option - - Symbol - - . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    qb = QuantBook()
    -future = qb.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    -future.set_filter(0, 90)
    -symbol = Symbol.create_canonical_option(future.mapped)
    -history = qb.history(symbol, datetime(2020, 6, 1), datetime(2020, 6, 5), flatten=True)
    -
    var qb = new QuantBook();
    -var future = qb.AddFuture(Futures.Metals.Gold, Resolution.Minute);
    -var symbol = QuantConnect.Symbol.CreateCanonicalOption(future.Mapped);
    -var history = qb.History<OptionUniverse>(symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 6));
    -foreach (var chain in history)
    -{
    -    var endTime = chain.EndTime;
    -    var filteredContracts = chain.Data
    -        .Select(contract => contract as OptionUniverse)
    -        .Where(contract => contract.Greeks.Delta > 0.3m);
    -    foreach (var contract in filteredContracts)
    -    {
    -        var price = contract.Price;
    -        var iv = contract.ImpliedVolatility;
    -    }
    -}
    -
    -

    - For more information about historical Future Options Universe data in the Research Environment, see - - Universes - - . -

    - - - -

    Supported Assets

    - - -

    - The following list shows the available (15) Futures Options: -

    -
      -
    • - - Futures.Energy.CrudeOilWTI - - - Futures.Energy.CRUDE_OIL_WTI - - : Crude Oil WTI Futures (NYMEX: LO | Underlying: CL) -
    • -
    • - - Futures.Energy.Gasoline - - - Futures.Energy.GASOLINE - - : Gasoline RBOB Futures (NYMEX: OB | Underlying: RB) -
    • -
    • - - Futures.Energy.HeatingOil - - - Futures.Energy.HEATING_OIL - - : Heating Oil Futures (NYMEX: OH | Underlying: HO) -
    • -
    • - - Futures.Energy.NaturalGas - - - Futures.Energy.NATURAL_GAS - - : Natural Gas Futures (NYMEX: ON | Underlying: NG) -
    • -
    • - - Futures.Financials.Y10TreasuryNote - - - Futures.Financials.Y_10_TREASURY_NOTE - - : 10Y U.S. Treasury Note Futures (CBOT: OZN | Underlying: ZN) -
    • -
    • - - Futures.Financials.Y2TreasuryNote - - - Futures.Financials.Y_2_TREASURY_NOTE - - : 2Y U.S. Treasury Note Futures (CBOT: OZT | Underlying: ZT) -
    • -
    • - - Futures.Financials.Y30TreasuryBond - - - Futures.Financials.Y_30_TREASURY_BOND - - : 30Y U.S. Treasury Bond Futures (CBOT: OZB | Underlying: ZB) -
    • -
    • - - Futures.Grains.Corn - - - Futures.Grains.CORN - - : Corn Futures (CBOT: OZC | Underlying: ZC) -
    • -
    • - - Futures.Grains.Soybeans - - - Futures.Grains.SOYBEANS - - : Soybeans Futures (CBOT: OZS | Underlying: ZS) -
    • -
    • - - Futures.Grains.Wheat - - - Futures.Grains.WHEAT - - : Default wheat contract is SRWWheat (CBOT: OZW | Underlying: ZW) -
    • -
    • - - Futures.Indices.NASDAQ100EMini - - - Futures.Indices.NASDAQ_100_E_MINI - - : E-mini NASDAQ 100 Futures (CME: NQ) -
    • -
    • - - Futures.Indices.SP500EMini - - - Futures.Indices.SP_500_E_MINI - - : E-mini S&P 500 Futures (CME: ES) -
    • -
    • - - Futures.Metals.Copper - - - Futures.Metals.COPPER - - : Copper Futures (COMEX: HXE | Underlying: HG) -
    • -
    • - - Futures.Metals.Gold - - - Futures.Metals.GOLD - - : Gold Futures (COMEX: OG | Underlying: GC) -
    • -
    • - - Futures.Metals.Silver - - - Futures.Metals.SILVER - - : Silver Futures (COMEX: SO | Underlying: SI) -
    • -
    - - - -

    Example Applications

    - - -

    - The US Future Options dataset enables you to accurately design Future Option strategies. Examples include the following strategies: -

    -
      -
    • - Selling out of the money Future Option contracts to collect the premium that the Option buyer pays -
    • -
    • - Buying put Options to hedge against downward price movement in Future contracts you bought -
    • -
    • - Exploiting arbitrage opportunities that arise when the price of Option contracts deviate from their theoretical value -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example demonstrates a bull call spread Option strategy using universe filtering. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class FutureOptionAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Filter the underlying continuous Futures to narrow the FOP spectrum.
    -        self.underlying = self.add_future(Futures.Indices.SP_500_E_MINI,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -            contract_depth_offset=0)
    -        self.underlying.set_filter(0, 182)
    -        # Use CallSpread filter to obtain the 2 best-matched contracts that forms a call spread.
    -        # It simplifies from further filtering and reduce computation on redundant subscription.
    -        self.add_future_option(self.underlying.symbol, lambda u: u.call_spread(5, 5, -5))
    -    
    -    def on_data(self, slice: Slice) -> None:
    -        if self.portfolio.invested:
    -            return
    -        # Create canonical symbol for the mapped future contract, since we need that to access the option chain.
    -        symbol = Symbol.create_canonical_option(self.underlying.mapped)
    -    
    -        # Get option chain data for the mapped future only.
    -        # It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present.
    -        chain = slice.option_chains.get(symbol)
    -        if not chain or len(list(chain)) < 2:
    -            return
    -            
    -        # Separate the contracts by strike, as we need to access their strike.
    -        expiry = min([x.expiry for x in chain])
    -        sorted_by_strike = sorted([x.strike for x in chain])
    -        itm_strike = sorted_by_strike[0]
    -        otm_strike = sorted_by_strike[-1]
    -        
    -        # Use abstraction method to order a bull call spread to avoid manual error.
    -        option_strategy = OptionStrategies.bull_call_spread(symbol, itm_strike, otm_strike, expiry)
    -        self.buy(option_strategy, 1)
    -
    public class FutureOptionAlgorithm : QCAlgorithm
    -{
    -    private Future _underlying;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Filter the underlying continuous Futures to narrow the FOP spectrum.
    -        _underlying = AddFuture(Futures.Indices.SP500EMini,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.OpenInterest,
    -            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -            contractDepthOffset: 0);
    -        _underlying.SetFilter(0, 182);
    -        // Use CallSpread filter to obtain the 2 best-matched contracts that forms a call spread.
    -        // It simplifies from further filtering and reduce computation on redundant subscription.
    -        AddFutureOption(_underlying.Symbol, (u) => u.CallSpread(5, 5, -5));
    -    }
    -    
    -    public override void OnData(Slice slice)
    -    {
    -        if (Portfolio.Invested)
    -            return;
    -
    -        // Create canonical symbol for the mapped future contract, since we need that to access the option chain.
    -        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_underlying.Mapped);
    -    
    -        // Get option chain data for the mapped future only.
    -        // It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present.
    -        if (!slice.OptionChains.TryGetValue(symbol, out var chain) || chain.Count() < 2)
    -            return;
    -    
    -        // Separate the contracts by strike, as we need to access their strike.
    -        var expiry = chain.Min(x => x.Expiry);
    -        var itmStrike = chain.Min(x => x.Strike);
    -        var otmStrike = chain.Max(x => x.Strike);
    -    
    -        // Use abstraction method to order a bull call spread to avoid manual error.
    -        var optionStrategy = OptionStrategies.BullCallSpread(symbol, itmStrike, otmStrike, expiry);
    -        Buy(optionStrategy, 1);
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Future Options Universe dataset provides - - OptionFilterUniverse - - and - - OptionUniverse - - objects. -

    -

    - OptionFilterUniverse Attributes -

    -

    - - OptionFilterUniverse - - objects have the following attributes: -

    -
    -
    -

    - OptionUniverse Attributes -

    -

    - - OptionUniverse - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Future Universe

    -
    -
    -

    Introduction

    - - -

    - The US Future Universe dataset by QuantConnect lists the available US Future contracts, their daily trading volume, and Open Interest. The data covers the 157 most liquid contracts, starts in May 2009, and is delivered on daily frequency. This dataset is created by monitoring the trading activity on the CFE, CBOT, CME, COMEX, NYMEX, and ICE - - * - - . -

    -

    - This dataset depends on the - - US Futures Security Master - - dataset because the US Futures Security Master dataset contains information on symbol changes of the contracts. -

    -

    - This dataset - - does not - - contain market data. For market data, see - - US Futures by AlgoSeek - - . -

    -

    - For more information about the US Future Universe dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Future Universe dataset: -

    -
    -
    future = self.add_future(Futures.Metals.GOLD)
    -future.set_filter(0, 90)
    -
    var future = AddFuture(Futures.Metals.Gold);
    -future.SetFilter(0, 90);
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - May 2009 -
    - Asset Coverage - - 157 Futures -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - -
      -
    • - Chicago (CFE, CME or CBOT) -
    • -
    • - New York (ICE, NYMEX or COMEX) -
    • -
    -
    - Market Hours - - - Regular and Extended - -
    - - - -

    Requesting Data

    - - -

    - To add US Future Universe data to your algorithm, call the - - AddFuture - - - add_future - - method. Save a reference to the Future object so you can access the data later in your algorithm. To define which contracts should be in your universe, specify the filter when requesting the Future data. -

    -

    - The - - AddFuture - - - add_future - - method provides a daily stream of Future chain data. To get the most recent daily chain, call the - - FuturesChain - - - futures_chain - - method with the underlying Future Symbol. The - - FuturesChain - - - futures_chain - - method returns data on all the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    class USFutureDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        self._future = self.add_future(Futures.Metals.GOLD)
    -        # Set our contract filter for this Future chain.
    -        self._future.set_filter(lambda universe: universe.standards_only().front_month())
    -        # Get the entire Futures chain for the current day.
    -        chain = self.futures_chain(self._future.symbol, flatten=True).data_frame
    -
    public class USFutureDataAlgorithm : QCAlgorithm
    -{
    -    private Future _future;
    -        
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        _future = AddFuture(Futures.Metals.Gold);
    -        // Set our contract filter for this Future chain.
    -        _future.SetFilter((universe) => universe.StandardsOnly().FrontMonth());
    -        // Get the entire Futures chain for the current day.
    -        var chain = FuturesChain(_future.Symbol);
    -    }
    -}
    -
    -

    - For more information about creating US Future universes, see - - Futures - - . -

    - - - -

    Accessing Data

    - - -

    - For information about accessing US Future Universe data, see - - Futures - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Future Universe data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Future Universe data in an algorithm, call the - - History<FutureUniverse> - - - history - - method with continuous Future - - Symbol - - and a lookback period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. -

    -
    -
    # Add the Future and save a reference to it.
    -future = self.add_future(Futures.Metals.GOLD)
    -
    -# DataFrame example where the columns are the FutureUniverse attributes:
    -history_df = self.history(FutureUniverse, future.symbol, 5, flatten=True)
    -
    -# Series example where the values are lists of FutureUniverse objects: 
    -history_series = self.history(FutureUniverse, future.symbol, 5, flatten=False)
    -
    -# FutureUniverse objects example:
    -history = self.history[FutureUniverse](future.symbol, 5)
    -
    // Add the Future and save a reference to it.
    -var future = AddFuture(Futures.Metals.Gold);
    -
    -// Get historical data.
    -var history = History<FutureUniverse>(future.Symbol, 5);
    -
    -

    - For more information about historical US Future Universe data in algorithms, see - - Contracts - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Future Universe data in the Research Environment, call the - - History<FutureUniverse> - - - history - - method with continuous Future - - Symbol - - and a time period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. -

    -
    -
    # Add the Future and save a reference to it.
    -future = qb.add_future(Futures.Metals.GOLD)
    -
    -# DataFrame example where the columns are the FutureUniverse attributes:
    -history_df = qb.history(FutureUniverse, future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1), flatten=True)
    -
    -# Series example where the values are lists of FutureUniverse objects: 
    -history_series = qb.history(FutureUniverse, future.symbol, 5, flatten=False)
    -
    -# FutureUniverse objects example:
    -history = qb.history[FutureUniverse](future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1))
    -
    // Add the Future and save a reference to it.
    -var future = qb.AddFuture(Futures.Metals.Gold);
    -
    -// Get historical data.
    -var history = qb.History<FutureUniverse>(future.Symbol, new DateTime(2025, 1, 1), new DateTime(2025, 4, 1));
    -
    -

    - For more information about historical US Future Universe data in the Research Environment, see - - Daily Prices History - - . -

    - - - -

    Supported Assets

    - - -

    - The following list shows the available (157) Futures: -

    -
      -
    • - - Futures.Currencies.AUD - - : Australian Dollar Futures (CME: 6A) -
    • -
    • - - Futures.Currencies.AUDCAD - - : Australian Dollar/Canadian Dollar Futures (CME: ACD) -
    • -
    • - - Futures.Currencies.AUDJPY - - : Australian Dollar/Japanese Yen Futures (CME: AJY) -
    • -
    • - - Futures.Currencies.AUDNZD - - : Australian Dollar/New Zealand Dollar Futures (CME: ANE) -
    • -
    • - - Futures.Currencies.BRL - - : Brazillian Real Futures (CME: 6L) -
    • -
    • - - Futures.Currencies.BTC - - : Bitcoin Futures (CME: BTC) -
    • -
    • - - Futures.Currencies.BTICMicroBTC - - - Futures.Currencies.BTIC_MICRO_BTC - - : BTIC on Micro Bitcoin Futures (CME: MIB) -
    • -
    • - - Futures.Currencies.BTICMicroEther - - - Futures.Currencies.BTIC_MICRO_ETHER - - : BTIC on Micro Ether Futures (CME: MRB) -
    • -
    • - - Futures.Currencies.CAD - - : Canadian Dollar Futures (CME: 6C) -
    • -
    • - - Futures.Currencies.CADJPY - - : Canadian Dollar/Japanese Yen Futures (CME: CJY) -
    • -
    • - - Futures.Currencies.CHF - - : Swiss Franc Futures (CME: 6S) -
    • -
    • - - Futures.Currencies.ETH - - : Ether Futures (CME: ETH) -
    • -
    • - - Futures.Currencies.EUR - - : Euro FX Futures (CME: 6E) -
    • -
    • - - Futures.Currencies.EURAUD - - : Euro/Australian Dollar Futures (CME: EAD) -
    • -
    • - - Futures.Currencies.EURCAD - - : Euro/Canadian Dollar Futures (CME: ECD) -
    • -
    • - - Futures.Currencies.EuroFXEmini - - - Futures.Currencies.EURO_FX_EMINI - - : E-mini Euro FX Futures (CME: E7) -
    • -
    • - - Futures.Currencies.EURSEK - - : Euro/Swedish Krona Futures (CME: ESK) -
    • -
    • - - Futures.Currencies.GBP - - : British Pound Futures (CME: 6B) -
    • -
    • - - Futures.Currencies.JapaneseYenEmini - - - Futures.Currencies.JAPANESE_YEN_EMINI - - : E-mini Japanese Yen Futures (CME: J7) -
    • -
    • - - Futures.Currencies.JPY - - : Japanese Yen Futures (CME: 6J) -
    • -
    • - - Futures.Currencies.MicroAUD - - - Futures.Currencies.MICRO_AUD - - : Micro AUD/USD Futures (CME: M6A) -
    • -
    • - - Futures.Currencies.MicroBTC - - - Futures.Currencies.MICRO_BTC - - : Micro Bitcoin Futures (CME: MBT) -
    • -
    • - - Futures.Currencies.MicroCAD - - - Futures.Currencies.MICRO_CAD - - : Micro USD/CAD Futures (CME: M6C) -
    • -
    • - - Futures.Currencies.MicroCADUSD - - - Futures.Currencies.MICRO_CADUSD - - : Micro CAD/USD Futures (CME: MCD) -
    • -
    • - - Futures.Currencies.MicroCHF - - - Futures.Currencies.MICRO_CHF - - : Micro CHF/USD Futures (CME: MSF) -
    • -
    • - - Futures.Currencies.MicroEther - - - Futures.Currencies.MICRO_ETHER - - : Micro Ether Futures (CME: MET) -
    • -
    • - - Futures.Currencies.MicroEUR - - - Futures.Currencies.MICRO_EUR - - : Micro EUR/USD Futures (CME: M6E) -
    • -
    • - - Futures.Currencies.MicroGBP - - - Futures.Currencies.MICRO_GBP - - : Micro GBP/USD Futures (CME: M6B) -
    • -
    • - - Futures.Currencies.MicroINRUSD - - - Futures.Currencies.MICRO_INRUSD - - : Micro INR/USD Futures (CME: MIR) -
    • -
    • - - Futures.Currencies.MicroJPY - - - Futures.Currencies.MICRO_JPY - - : Micro JPY/USD Futures (CME: MJY) -
    • -
    • - - Futures.Currencies.MicroUSDCHF - - - Futures.Currencies.MICRO_USDCHF - - : Micro USD/CHF Futures (CME: M6S) -
    • -
    • - - Futures.Currencies.MicroUSDCNH - - - Futures.Currencies.MICRO_USDCNH - - : Micro USD/CNH Futures (CME: MNH) -
    • -
    • - - Futures.Currencies.MicroUSDJPY - - - Futures.Currencies.MICRO_USDJPY - - : Micro USD/JPY Futures (CME: M6J) -
    • -
    • - - Futures.Currencies.MXN - - : Mexican Peso Futures (CME: 6M) -
    • -
    • - - Futures.Currencies.NZD - - : New Zealand Dollar Futures (CME: 6N) -
    • -
    • - - Futures.Currencies.RUB - - : Russian Ruble Futures (CME: 6R) -
    • -
    • - - Futures.Currencies.StandardSizeUSDOffshoreRMBCNH - - - Futures.Currencies.STANDARD_SIZE_USD_OFFSHORE_RMBCNH - - : Standard-Size USD/Offshore RMB (CNH) Futures (CME: CNH) -
    • -
    • - - Futures.Currencies.ZAR - - : South African Rand Futures (CME: 6Z) -
    • -
    • - - Futures.Energy.ArgusLLSvsWTIArgusTradeMonth - - - Futures.Energy.ARGUS_LL_SVS_WTI_ARGUS_TRADE_MONTH - - : Argus LLS vs. WTI (Argus) Trade Month Futures (NYMEX: AE5) -
    • -
    • - - Futures.Energy.ArgusPropaneFarEastIndex - - - Futures.Energy.ARGUS_PROPANE_FAR_EAST_INDEX - - : Argus Propane Far East Index Futures (NYMEX: A7E) -
    • -
    • - - Futures.Energy.ArgusPropaneSaudiAramco - - - Futures.Energy.ARGUS_PROPANE_SAUDI_ARAMCO - - : Argus Propane (Saudi Aramco) Futures (NYMEX: A9N) -
    • -
    • - - Futures.Energy.BrentCrudeOilVsDubaiCrudeOilPlatts - - - Futures.Energy.BRENT_CRUDE_OIL_VS_DUBAI_CRUDE_OIL_PLATTS - - : Brent Crude Oil vs. Dubai Crude Oil (Platts) Futures (NYMEX: ADB) -
    • -
    • - - Futures.Energy.BrentLastDayFinancial - - - Futures.Energy.BRENT_LAST_DAY_FINANCIAL - - : Brent Last Day Financial Futures (NYMEX: BZ) -
    • -
    • - - Futures.Energy.ChicagoEthanolPlatts - - - Futures.Energy.CHICAGO_ETHANOL_PLATTS - - : Chicago Ethaanol (Platts) Futures (NYMEX: CU) -
    • -
    • - - Futures.Energy.ConwayPropaneOPIS - - - Futures.Energy.CONWAY_PROPANE_OPIS - - : Conway Propane (OPIS) Futures (NYMEX: A8K) -
    • -
    • - - Futures.Energy.CrudeOilWTI - - - Futures.Energy.CRUDE_OIL_WTI - - : Crude Oil WTI Futures (NYMEX: CL) -
    • -
    • - - Futures.Energy.DubaiCrudeOilPlattsFinancial - - - Futures.Energy.DUBAI_CRUDE_OIL_PLATTS_FINANCIAL - - : Dubai Crude Oil (Platts) Financial Futures (NYMEX: DCB) -
    • -
    • - - Futures.Energy.EastWestGasolineSpreadPlattsArgus - - - Futures.Energy.EAST_WEST_GASOLINE_SPREAD_PLATTS_ARGUS - - : East-West Gasoline Spread (Platts-Argus) Futures (NYMEX: EWG) -
    • -
    • - - Futures.Energy.EastWestNaphthaJapanCFvsCargoesCIFNWESpreadPlatts - - - Futures.Energy.EAST_WEST_NAPHTHA_JAPAN_C_FVS_CARGOES_CIFNWE_SPREAD_PLATTS - - : East-West Naphtha: Japan C&F vs. Cargoes CIF NWE Spread (Platts) Futures (NYMEX: EWN) -
    • -
    • - - Futures.Energy.Ethanol - - - Futures.Energy.ETHANOL - - : Ethanol Futures (CBOT: EH) -
    • -
    • - - Futures.Energy.EthanolT2FOBRdamIncludingDutyPlatts - - - Futures.Energy.ETHANOL_T_2_FOB_RDAM_INCLUDING_DUTY_PLATTS - - : Ethanol T2 FOB Rdam Including Duty (Platts) Futures (NYMEX: AZ1) -
    • -
    • - - Futures.Energy.EuropeanNaphthaPlattsCrackSpread - - - Futures.Energy.EUROPEAN_NAPHTHA_PLATTS_CRACK_SPREAD - - : European Naphtha (Platts) Crack Spread Futures (NYMEX: EN) -
    • -
    • - - Futures.Energy.EuropeanPropaneCIFARAArgus - - - Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS - - : European Propane CIF ARA (Argus) Futures (NYMEX: APS) -
    • -
    • - - Futures.Energy.EuropeanPropaneCIFARAArgusVsNaphthaCargoesCIFNWEPlatts - - - Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS_VS_NAPHTHA_CARGOES_CIFNWE_PLATTS - - : European Propane CIF ARA (Argus) vs. Naphtha Cargoes CIF NWE (Platts) Futures (NYMEX: EPN) -
    • -
    • - - Futures.Energy.FreightRouteTC14Baltic - - - Futures.Energy.FREIGHT_ROUTE_TC_14_BALTIC - - : Freight Route TC14 (Baltic) Futures (NYMEX: FRC) -
    • -
    • - - Futures.Energy.Gasoline - - - Futures.Energy.GASOLINE - - : Gasoline RBOB Futures (NYMEX: RB) -
    • -
    • - - Futures.Energy.GasolineEurobobOxyNWEBargesArgus - - - Futures.Energy.GASOLINE_EUROBOB_OXY_NWE_BARGES_ARGUS - - : Gasoline Euro-bob Oxy NWE Barges (Argus) Futures (NYMEX: B7H) -
    • -
    • - - Futures.Energy.GroupThreeSuboctaneGasolinePlattsVsRBOB - - - Futures.Energy.GROUP_THREE_SUBOCTANE_GASOLINE_PLATTS_VS_RBOB - - : Group Three Sub-octane Gasoliine (Platts) vs. RBOB Futures (NYMEX: AA8) -
    • -
    • - - Futures.Energy.GroupThreeULSDPlattsVsNYHarborULSD - - - Futures.Energy.GROUP_THREE_ULSD_PLATTS_VS_NY_HARBOR_ULSD - - : Group Three ULSD (Platts) vs. NY Harbor ULSD Futures (NYMEX: AA6) -
    • -
    • - - Futures.Energy.GulfCoastCBOBGasolineA2PlattsVsRBOBGasoline - - - Futures.Energy.GULF_COAST_CBOB_GASOLINE_A_2_PLATTS_VS_RBOB_GASOLINE - - : Gulf Coast CBOB Gasoline A2 (Platts) vs. RBOB Gasoline Futures (NYMEX: CRB) -
    • -
    • - - Futures.Energy.GulfCoastHSFOPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.GULF_COAST_HSFO_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : Gulf Coast HSFO (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: GCU) -
    • -
    • - - Futures.Energy.HeatingOil - - - Futures.Energy.HEATING_OIL - - : Heating Oil Futures (NYMEX: HO) -
    • -
    • - - Futures.Energy.LosAngelesCARBOBGasolineOPISvsRBOBGasoline - - - Futures.Energy.LOS_ANGELES_CARBOB_GASOLINE_OPI_SVS_RBOB_GASOLINE - - : Los Angeles CARBOB Gasoline (OPIS) vs. RBOB Gasoline Futures (NYMEX: AJL) -
    • -
    • - - Futures.Energy.LosAngelesCARBDieselOPISvsNYHarborULSD - - - Futures.Energy.LOS_ANGELES_CARB_DIESEL_OPI_SVS_NY_HARBOR_ULSD - - : Los Angeles CARB Diesel (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AKL) -
    • -
    • - - Futures.Energy.LosAngelesJetOPISvsNYHarborULSD - - - Futures.Energy.LOS_ANGELES_JET_OPI_SVS_NY_HARBOR_ULSD - - : Los Angeles Jet (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AJS) -
    • -
    • - - Futures.Energy.MarsArgusVsWTIFinancial - - - Futures.Energy.MARS_ARGUS_VS_WTI_FINANCIAL - - : Mars (Argus) vs. WTI Financial Futures (NYMEX: AYX) -
    • -
    • - - Futures.Energy.MarsArgusVsWTITradeMonth - - - Futures.Energy.MARS_ARGUS_VS_WTI_TRADE_MONTH - - : Mars (Argus) vs. WTI Trade Month Futures (NYMEX: AYV) -
    • -
    • - - Futures.Energy.MicroCrudeOilWTI - - - Futures.Energy.MICRO_CRUDE_OIL_WTI - - : Micro WTI Crude Oil Futures (NYMEX: MCL) -
    • -
    • - - Futures.Energy.MicroEuropeanFOBRdamMarineFuelZeroPointFivePercentBargesPlatts - - - Futures.Energy.MICRO_EUROPEAN_FOB_RDAM_MARINE_FUEL_ZERO_POINT_FIVE_PERCENT_BARGES_PLATTS - - : Micro European FOB Rdam Marine Fuel 0.5% Barges (Platts) Futures (NYMEX: R5O) -
    • -
    • - - Futures.Energy.MicroEuropeanThreePointFivePercentOilBargesFOBRdamPlatts - - - Futures.Energy.MICRO_EUROPEAN_THREE_POINT_FIVE_PERCENT_OIL_BARGES_FOB_RDAM_PLATTS - - : Micro European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: MEF) -
    • -
    • - - Futures.Energy.MicroGasoilZeroPointOnePercentBargesFOBARAPlatts - - - Futures.Energy.MICRO_GASOIL_ZERO_POINT_ONE_PERCENT_BARGES_FOBARA_PLATTS - - : Micro Gasoil 0.1% Barges FOB ARA (Platts) Futures (NYMEX: M1B) -
    • -
    • - - Futures.Energy.MicroSingaporeFOBMarineFuelZeroPointFivePercetPlatts - - - Futures.Energy.MICRO_SINGAPORE_FOB_MARINE_FUEL_ZERO_POINT_FIVE_PERCET_PLATTS - - : Micro Singapore FOB Marine Fuel 0.5% (Platts) Futures (NYMEX: S5O) -
    • -
    • - - Futures.Energy.MicroSingaporeFuelOil380CSTPlatts - - - Futures.Energy.MICRO_SINGAPORE_FUEL_OIL_380_CST_PLATTS - - : Micro Singapore Fuel Oil 380CST (Platts) Futures (NYMEX: MAF) -
    • -
    • - - Futures.Energy.MiniEuropeanThreePointPercentFiveFuelOilBargesPlatts - - - Futures.Energy.MINI_EUROPEAN_THREE_POINT_PERCENT_FIVE_FUEL_OIL_BARGES_PLATTS - - : Mini European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: A0D) -
    • -
    • - - Futures.Energy.MiniSingaporeFuelOil180CstPlatts - - - Futures.Energy.MINI_SINGAPORE_FUEL_OIL_180_CST_PLATTS - - : Mini Singapore Fuel Oil 180 cst (Platts) Futures (NYMEX: A0F) -
    • -
    • - - Futures.Energy.MontBelvieuEthaneOPIS - - - Futures.Energy.MONT_BELVIEU_ETHANE_OPIS - - : Mont Belvieu Ethane (OPIS) Futures (NYMEX: AC0) -
    • -
    • - - Futures.Energy.MontBelvieuLDHPropaneOPIS - - - Futures.Energy.MONT_BELVIEU_LDH_PROPANE_OPIS - - : Mont Belvieu LDH Propane (OPIS) Futures (NYMEX: B0) -
    • -
    • - - Futures.Energy.MontBelvieuNaturalGasolineOPIS - - - Futures.Energy.MONT_BELVIEU_NATURAL_GASOLINE_OPIS - - : Mont Belvieu Natural Gasoline (OPIS) Futures (NYMEX: A7Q) -
    • -
    • - - Futures.Energy.MontBelvieuNormalButaneOPIS - - - Futures.Energy.MONT_BELVIEU_NORMAL_BUTANE_OPIS - - : Mont Belvieu Normal Butane (OPIS) Futures (NYMEX: AD0) -
    • -
    • - - Futures.Energy.NaturalGas - - - Futures.Energy.NATURAL_GAS - - : Natural Gas Futures (NYMEX: NG) -
    • -
    • - - Futures.Energy.NaturalGasHenryHubLastDayFinancial - - - Futures.Energy.NATURAL_GAS_HENRY_HUB_LAST_DAY_FINANCIAL - - : Natural Gas (Henry Hub) Last-day Financial Futures (NYMEX: HH) -
    • -
    • - - Futures.Energy.NaturalGasHenryHubPenultimateFinancial - - - Futures.Energy.NATURAL_GAS_HENRY_HUB_PENULTIMATE_FINANCIAL - - : Natural Gas (Henry Hub) Penultimate Financial Futures (NYMEX: HP) -
    • -
    • - - Futures.Energy.OnePercentFuelOilCargoesFOBNWEPlattsVsThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.ONE_PERCENT_FUEL_OIL_CARGOES_FOBNWE_PLATTS_VS_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : 1% Fuel Oil Cargoes FOB NWE (Platts) vs. 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: FSS) -
    • -
    • - - Futures.Energy.PremiumUnleadedGasoline10ppmFOBMEDPlatts - - - Futures.Energy.PREMIUM_UNLEADED_GASOLINE_10_PPM_FOBMED_PLATTS - - : Premium Unleaded Gasoline 10 ppm FOB MED (Platts) Futures (NYMEX: A3G) -
    • -
    • - - Futures.Energy.PropaneNonLDHMontBelvieuOPIS - - - Futures.Energy.PROPANE_NON_LDH_MONT_BELVIEU_OPIS - - : Propane Non-LDH Mont Belvieu (OPIS) Futures (NYMEX: A1R) -
    • -
    • - - Futures.Energy.RBOBGasolineCrackSpread - - - Futures.Energy.RBOB_GASOLINE_CRACK_SPREAD - - : RBOB Gasoline Crack Spread Futures (NYMEX: ARE) -
    • -
    • - - Futures.Energy.RBOBGasolineVsEurobobOxyNWEBargesArgusThreeHundredFiftyThousandGallons - - - Futures.Energy.RBOB_GASOLINE_VS_EUROBOB_OXY_NWE_BARGES_ARGUS_THREE_HUNDRED_FIFTY_THOUSAND_GALLONS - - : RBOB Gasoline vs. Euro-bob Oxy NWE Barges (Argus) (350,000 gallons) Futures (NYMEX: EXR) -
    • -
    • - - Futures.Energy.SingaporeFuelOil380cstPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.SINGAPORE_FUEL_OIL_380_CST_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : Singapore Fuel Oil 380 cst (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: EVC) -
    • -
    • - - Futures.Energy.SingaporeGasoilPlattsVsLowSulphurGasoilFutures - - - Futures.Energy.SINGAPORE_GASOIL_PLATTS_VS_LOW_SULPHUR_GASOIL_FUTURES - - : Singapore Gasoil (Platts) vs. Low Sulphur Gasoil Futures (NYMEX: AGA) -
    • -
    • - - Futures.Energy.SingaporeMogas92UnleadedPlattsBrentCrackSpread - - - Futures.Energy.SINGAPORE_MOGAS_92_UNLEADED_PLATTS_BRENT_CRACK_SPREAD - - : Singapore Mogas 92 Unleaded (Platts) Brent Crack Spread Futures (NYMEX: D1N) -
    • -
    • - - Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread - - - Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD - - : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread Futures (NYMEX: FO) -
    • -
    • - - Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread1000mt - - - Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD_1000_MT - - : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread (1000mt) Futures (NYMEX: BOO) -
    • -
    • - - Futures.Energy.WTIBrentFinancial - - - Futures.Energy.WTI_BRENT_FINANCIAL - - : WTI-Brent Financial Futures (NYMEX: BK) -
    • -
    • - - Futures.Energy.WTIFinancial - - - Futures.Energy.WTI_FINANCIAL - - : WTI Financial Futures (NYMEX: CSX) -
    • -
    • - - Futures.Energy.WTIHoustonArgusVsWTITradeMonth - - - Futures.Energy.WTI_HOUSTON_ARGUS_VS_WTI_TRADE_MONTH - - : WTI Houston (Argus) vs. WTI Trade Month Futures (NYMEX: HTT) -
    • -
    • - - Futures.Energy.WTIHoustonCrudeOil - - - Futures.Energy.WTI_HOUSTON_CRUDE_OIL - - : WTI Houston Crude Oil Futures (NYMEX: HCL) -
    • -
    • - - Futures.Financials.EuroDollar - - - Futures.Financials.EURO_DOLLAR - - : EuroDollar Futures (CME: GE) -
    • -
    • - - Futures.Financials.FiveYearUSDMACSwap - - - Futures.Financials.FIVE_YEAR_USDMAC_SWAP - - : 5-Year USD MAC Swap Futures (CBOT: F1U) -
    • -
    • - - Futures.Financials.MicroY10TreasuryNote - - - Futures.Financials.MICRO_Y_10_TREASURY_NOTE - - : Micro 10-Year Yield Futures (CBOT: 10Y) -
    • -
    • - - Futures.Financials.MicroY2TreasuryBond - - - Futures.Financials.MICRO_Y_2_TREASURY_BOND - - : Micro 2-Year Yield Futures (CBOT: 2YY) -
    • -
    • - - Futures.Financials.MicroY30TreasuryBond - - - Futures.Financials.MICRO_Y_30_TREASURY_BOND - - : Micro 30-Year Yield Futures (CBOT: 30Y) -
    • -
    • - - Futures.Financials.MicroY5TreasuryBond - - - Futures.Financials.MICRO_Y_5_TREASURY_BOND - - : Micro 5-Year Yield Futures (CBOT: 5YY) -
    • -
    • - - Futures.Financials.UltraTenYearUSTreasuryNote - - - Futures.Financials.ULTRA_TEN_YEAR_US_TREASURY_NOTE - - : Ultra 10-Year U.S. Treasury Note Futures (CBOT: TN) -
    • -
    • - - Futures.Financials.UltraUSTreasuryBond - - - Futures.Financials.ULTRA_US_TREASURY_BOND - - : Ultra U.S. Treasury Bond Futures (CBOT: UB) -
    • -
    • - - Futures.Financials.Y10TreasuryNote - - - Futures.Financials.Y_10_TREASURY_NOTE - - : 10Y U.S. Treasury Note Futures (CBOT: ZN) -
    • -
    • - - Futures.Financials.Y2TreasuryNote - - - Futures.Financials.Y_2_TREASURY_NOTE - - : 2Y U.S. Treasury Note Futures (CBOT: ZT) -
    • -
    • - - Futures.Financials.Y30TreasuryBond - - - Futures.Financials.Y_30_TREASURY_BOND - - : 30Y U.S. Treasury Bond Futures (CBOT: ZB) -
    • -
    • - - Futures.Financials.Y5TreasuryNote - - - Futures.Financials.Y_5_TREASURY_NOTE - - : 5Y U.S. Treasury Note Futures (CBOT: ZF) -
    • -
    • - - Futures.Forestry.Lumber - - - Futures.Forestry.LUMBER - - : Lumber Futures (CME: LBR) -
    • -
    • - - Futures.Forestry.RandomLengthLumber - - - Futures.Forestry.RANDOM_LENGTH_LUMBER - - : Random Length Lumber Futures (CME: LBS) -
    • -
    • - - Futures.Grains.BlackSeaCornFinanciallySettledPlatts - - - Futures.Grains.BLACK_SEA_CORN_FINANCIALLY_SETTLED_PLATTS - - : Black Sea Corn Financially Settled (Platts) Futures (CBOT: BCF) -
    • -
    • - - Futures.Grains.BlackSeaWheatFinanciallySettledPlatts - - - Futures.Grains.BLACK_SEA_WHEAT_FINANCIALLY_SETTLED_PLATTS - - : Black Sea Wheat Financially Settled (Platts) Futures (CBOT: BWF) -
    • -
    • - - Futures.Grains.Corn - - - Futures.Grains.CORN - - : Corn Futures (CBOT: ZC) -
    • -
    • - - Futures.Grains.HRWWheat - - - Futures.Grains.HRW_WHEAT - - : KC HRW Wheat Futures (CBOT: KE) -
    • -
    • - - Futures.Grains.Oats - - - Futures.Grains.OATS - - : Oats Futures (CBOT: ZO) -
    • -
    • - - Futures.Grains.Soybeans - - - Futures.Grains.SOYBEANS - - : Soybeans Futures (CBOT: ZS) -
    • -
    • - - Futures.Grains.SoybeanMeal - - - Futures.Grains.SOYBEAN_MEAL - - : Soybean Meal Futures (CBOT: ZM) -
    • -
    • - - Futures.Grains.SoybeanOil - - - Futures.Grains.SOYBEAN_OIL - - : Soybean Oil Futures (CBOT: ZL) -
    • -
    • - - Futures.Grains.Wheat - - - Futures.Grains.WHEAT - - : Default wheat contract is SRWWheat (CBOT: ZW) -
    • -
    • - - Futures.Indices.BloombergCommodityIndex - - - Futures.Indices.BLOOMBERG_COMMODITY_INDEX - - : Bloomberg Commodity Index Futures (CBOT: AW) -
    • -
    • - - Futures.Indices.Dow30EMini - - - Futures.Indices.DOW_30_E_MINI - - : E-mini Dow Indu 30 Futures (CBOT: YM) -
    • -
    • - - Futures.Indices.DowJonesRealEstate - - - Futures.Indices.DOW_JONES_REAL_ESTATE - - : Dow Jones Real Estate futures on CME (CME: RX) -
    • -
    • - - Futures.Indices.FTSEEmergingEmini - - - Futures.Indices.FTSE_EMERGING_EMINI - - : E-mini FTSE Emerging Index Futures (CME: EI) -
    • -
    • - - Futures.Indices.MicroDow30EMini - - - Futures.Indices.MICRO_DOW_30_E_MINI - - : Micro E-mini Dow Jones Industrial Average Index Futures (CBOT: MYM) -
    • -
    • - - Futures.Indices.MicroNASDAQ100EMini - - - Futures.Indices.MICRO_NASDAQ_100_E_MINI - - : Micro E-mini Nasdaq-100 Index Futures (CME: MNQ) -
    • -
    • - - Futures.Indices.MicroRussell2000EMini - - - Futures.Indices.MICRO_RUSSELL_2000_E_MINI - - : Micro E-mini Russell 2000 Index Futures (CME: M2K) -
    • -
    • - - Futures.Indices.MicroSP500EMini - - - Futures.Indices.MICRO_SP_500_E_MINI - - : Micro E-mini S&P 500 Index Futures (CME: MES) -
    • -
    • - - Futures.Indices.NASDAQ100BiotechnologyEMini - - - Futures.Indices.NASDAQ_100_BIOTECHNOLOGY_E_MINI - - : E-mini Nasdaq-100 Biotechnology Index Futures (CME: BIO) -
    • -
    • - - Futures.Indices.NASDAQ100EMini - - - Futures.Indices.NASDAQ_100_E_MINI - - : E-mini NASDAQ 100 Futures (CME: NQ) -
    • -
    • - - Futures.Indices.Nikkei225Dollar - - - Futures.Indices.NIKKEI_225_DOLLAR - - : Nikkei-225 Dollar Futures (CME: NKD) -
    • -
    • - - Futures.Indices.Nikkei225YenCME - - - Futures.Indices.NIKKEI_225_YEN_CME - - : Nikkei-225 Yen denominated Futures on CME (CME: NIY) -
    • -
    • - - Futures.Indices.Russell1000EMini - - - Futures.Indices.RUSSELL_1000_E_MINI - - : E-mini Russell 1000 futures on CME (CME: RS1) -
    • -
    • - - Futures.Indices.Russell2000EMini - - - Futures.Indices.RUSSELL_2000_E_MINI - - : E-mini Russell 2000 Futures (CME: RTY) -
    • -
    • - - Futures.Indices.SPGSCICommodity - - - Futures.Indices.SPGSCI_COMMODITY - - : S&P-GSCI Commodity Index Futures (CME: GD) -
    • -
    • - - Futures.Indices.SP400MidCapEmini - - - Futures.Indices.SP_400_MID_CAP_EMINI - - : E-mini S&P MidCap 400 Futures (CME: EMD) -
    • -
    • - - Futures.Indices.SP500AnnualDividendIndex - - - Futures.Indices.SP_500_ANNUAL_DIVIDEND_INDEX - - : (CME: SDA) -
    • -
    • - - Futures.Indices.SP500EMini - - - Futures.Indices.SP_500_E_MINI - - : E-mini S&P 500 Futures (CME: ES) -
    • -
    • - - Futures.Indices.TOPIXYEN - - : YEN Denominated Topix Index Futures on CME (CME: TPY) -
    • -
    • - - Futures.Indices.USDDenominatedIbovespa - - - Futures.Indices.USD_DENOMINATED_IBOVESPA - - : USD-Denominated Ibovespa Index Futures (CME: IBV) -
    • -
    • - - Futures.Indices.VIX - - : CBOE Volatility Index Futures (CFE: VX) -
    • -
    • - - Futures.Meats.FeederCattle - - - Futures.Meats.FEEDER_CATTLE - - : Feeder Cattle Futures (CME: GF) -
    • -
    • - - Futures.Meats.LeanHogs - - - Futures.Meats.LEAN_HOGS - - : Lean Hogs Futures (CME: HE) -
    • -
    • - - Futures.Meats.LiveCattle - - - Futures.Meats.LIVE_CATTLE - - : Live Cattle Futures (CME: LE) -
    • -
    • - - Futures.Metals.AluminiumEuropeanPremiumDutyPaidMetalBulletin - - - Futures.Metals.ALUMINIUM_EUROPEAN_PREMIUM_DUTY_PAID_METAL_BULLETIN - - : Aluminium European Premium Duty-Paid (Metal Bulletin) Futures (COMEX: EDP) -
    • -
    • - - Futures.Metals.AluminumMWUSTransactionPremiumPlatts25MT - - - Futures.Metals.ALUMINUM_MWUS_TRANSACTION_PREMIUM_PLATTS_25_MT - - : Aluminum MW U.S. Transaction Premium Platts (25MT) Futures (COMEX: AUP) -
    • -
    • - - Futures.Metals.Copper - - - Futures.Metals.COPPER - - : Copper Futures (COMEX: HG) -
    • -
    • - - Futures.Metals.Gold - - - Futures.Metals.GOLD - - : Gold Futures (COMEX: GC) -
    • -
    • - - Futures.Metals.MicroGold - - - Futures.Metals.MICRO_GOLD - - : Micro Gold Futures (COMEX: MGC) -
    • -
    • - - Futures.Metals.MicroGoldTAS - - - Futures.Metals.MICRO_GOLD_TAS - - : Micro Gold TAS Futures (COMEX: MGT) -
    • -
    • - - Futures.Metals.MicroPalladium - - - Futures.Metals.MICRO_PALLADIUM - - : Micro Palladium Futures (NYMEX: PAM) -
    • -
    • - - Futures.Metals.MicroSilver - - - Futures.Metals.MICRO_SILVER - - : Micro Silver Futures (COMEX: SIL) -
    • -
    • - - Futures.Metals.Palladium - - - Futures.Metals.PALLADIUM - - : Palladium Futures (NYMEX: PA) -
    • -
    • - - Futures.Metals.Platinum - - - Futures.Metals.PLATINUM - - : Platinum Futures (NYMEX: PL) -
    • -
    • - - Futures.Metals.Silver - - - Futures.Metals.SILVER - - : Silver Futures (COMEX: SI) -
    • -
    • - - Futures.Metals.USMidwestDomesticHotRolledCoilSteelCRUIndex - - - Futures.Metals.US_MIDWEST_DOMESTIC_HOT_ROLLED_COIL_STEEL_CRU_INDEX - - : U.S. Midwest Domestic Hot-Rolled Coil Steel (CRU) Index Futures (NYMEX: HRC) -
    • -
    • - - Futures.Softs.Sugar11 - - - Futures.Softs.SUGAR_11 - - : Sugar #11 Futures ICE (ICE: SB) -
    • -
    • - - Futures.Softs.Sugar11CME - - - Futures.Softs.SUGAR_11_CME - - : Sugar #11 Futures CME (NYMEX: YO) -
    • -
    - - - -

    Example Applications

    - - -

    - The US Future Universe dataset enables you to accurately design Futures strategies. Examples include the following strategies: -

    -
      -
    • - Buying the Futures contract with the most open interest to reduce slippage and market impact -
    • -
    • - Trading bull calendar spreads to reduce volatility and margin requirements -
    • -
    • - Trading bull calendar spreads to speculate contango -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm selects and buys the front-month Mini Gold Futures contract and sells the front-month Micro Gold Futures contract. When the front-month contract changes, the algorithm rebalances the portfolio. -

    -
    -
    from AlgorithmImports import *
    -
    -class USFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(1000000) 
    -        self.universe_settings.asynchronous = True
    -        # Requesting data on gold and micro-gold contracts.
    -        # Filter the universe to trade only the contracts expiring within 90 days to ensure liquidity.
    -        self.mini_gold = self.add_future(Futures.Metals.GOLD) 
    -        self.mini_gold.set_filter(0, 90)
    -        
    -        self.micro_gold = self.add_future(Futures.Metals.MICRO_GOLD) 
    -        self.micro_gold.set_filter(0, 90)
    -        
    -        # Save a cache of the mapped symbol to trade.
    -        self.contract = {self.mini_gold.symbol: None, self.micro_gold.symbol: None}
    -    
    -    def on_data(self, slice: Slice) -> None:
    -        for symbol, chain in slice.future_chains.items():
    -            if symbol in self.contract:
    -                # Select the contract with the greatest open interest to trade with the most efficiency.
    -                most_liquid_contract = sorted(chain, key=lambda contract: contract.open_interest, reverse=True)[0]
    -                
    -                if self.contract[symbol] is None or most_liquid_contract.symbol != self.contract[symbol].symbol:
    -                    # Liquidate any unmapped contracts.
    -                    if self.contract[symbol] is not None:
    -                        self.liquidate(self.contract[symbol].symbol)
    -                    self.contract[symbol] = most_liquid_contract
    -                    
    -                    # Buy mini-gold and short micro-gold contracts as planned.
    -                    if symbol == self.mini_gold.symbol:
    -                        self.market_order(self.contract[symbol].symbol, 1)
    -                    elif symbol == self.micro_gold.symbol:
    -                        self.market_order(self.contract[symbol].symbol, -1)
    -
    public class USFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Future _miniGold;
    -    private Future _microGold;
    -    // Save a cache of the mapped symbol to trade.
    -    private Dictionary<Symbol, FuturesContract?> _contract = new ();
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -        UniverseSettings.Asynchronous = true;
    -
    -        // Requesting data on gold and micro-gold contracts.
    -        // Filter the universe to trade only the contracts expiring within 90 days to ensure liquidity.
    -        _miniGold = AddFuture(Futures.Metals.Gold);
    -        _miniGold.SetFilter(0, 90);
    -        _contract.Add(_miniGold.Symbol, null);
    -        
    -        _microGold = AddFuture(Futures.Metals.MicroGold);
    -        _microGold.SetFilter(0, 90);
    -        _contract.Add(_microGold.Symbol, null);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        foreach (var (symbol, chain) in slice.FutureChains)
    -        {
    -            if (_contract.ContainsKey(symbol))
    -            {
    -                // Select the contract with the greatest open interest to trade with the most efficiency.
    -                var mostLiquidContract = chain.OrderBy(x => x.OpenInterest).Last();
    -                
    -                if (_contract[symbol] == null || mostLiquidContract.Symbol != _contract[symbol].Symbol)
    -                {
    -                    // Liquidate any unmapped contracts.
    -                    if (_contract[symbol] != null)
    -                    {
    -                        Liquidate(_contract[symbol].Symbol);
    -                    }
    -                    _contract[symbol] = mostLiquidContract;
    -
    -                    // Buy mini-gold and short micro-gold contracts as planned.
    -                    if (symbol == _miniGold.Symbol)
    -                    {
    -                        MarketOrder(_contract[symbol].Symbol, 1);
    -                    }
    -                    else if (symbol == _microGold.Symbol)
    -                    {
    -                        MarketOrder(_contract[symbol].Symbol, -1);
    -                    }
    -                }
    -            }
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm selects and buys the front-month Mini Gold Futures contract and sells the front-month Micro Gold Futures contract. When the front-month contract changes, the algorithm rebalances the portfolio. -

    -
    -
    from AlgorithmImports import *
    -
    -class USFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        # Set up an universe selection model that selects the front month contract
    -        self.set_universe_selection(FrontMonthFutureUniverseSelectionModel())
    -        self.add_alpha(ConstantFuturesAlphaModel())
    -        # A portfolio construction model that only order a single share per insight signal
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -        
    -class FrontMonthFutureUniverseSelectionModel(FutureUniverseSelectionModel):
    -    def __init__(self,) -> None:
    -        # Daily updating with select_future_chain_symbols function
    -        super().__init__(timedelta(1), self.select_future_chain_symbols)
    -
    -    def select_future_chain_symbols(self, utcTime: datetime) -> List[Symbol]:
    -        # Select gold and micro gold contracts for the strategy need
    -        future_pairs = [
    -            (Futures.Metals.GOLD, Market.COMEX),
    -            (Futures.Metals.MICRO_GOLD, Market.COMEX)
    -        ]
    -        return [Symbol.create(pair[0], SecurityType.FUTURE, pair[1]) for pair in future_pairs]
    -
    -    def filter(self, filter: FutureFilterUniverse) -> FutureFilterUniverse:
    -        # Filter only front month contract for liquidity and most informed information
    -        return filter.front_month().only_apply_filter_at_market_open()
    -
    -class ConstantFuturesAlphaModel(AlphaModel):
    -    # Long gold and short micro gold in this strategy
    -    long_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX)
    -    short_symbol = Symbol.create(Futures.Metals.MICRO_GOLD, SecurityType.FUTURE, Market.COMEX)
    -        
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        if algorithm.portfolio.invested:
    -            return []
    -        
    -        insights = []
    -        # For both gold and micro gold, select the front month contract (only contract) in the chain
    -        for kvp in slice.future_chains:
    -            chain = [contract for contract in kvp.Value]
    -            contract = chain[0]
    -            
    -            # Long gold and short micro gold as planned
    -            if kvp.Key == self.long_symbol:
    -                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.UP))
    -            elif kvp.Key == self.short_symbol:
    -                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.DOWN))
    -        
    -        return insights
    -        
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            # Historical data
    -            history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    -            algorithm.debug(f"We got {len(history)} from our history request for {security.symbol}")
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                # Single share only using integer portfolio target
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class USFuturesDataAlgorithm : QCAlgorithm
    -{        
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -        UniverseSettings.Asynchronous = true;
    -        // Set up an universe selection model that selects the front month contract
    -        SetUniverseSelection(new FrontMonthFutureUniverseSelectionModel());
    -        SetAlpha(new ConstantFuturesAlphaModel());
    -        // A portfolio construction model that only order a single share per insight signal
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}
    -    
    -class FrontMonthFutureUniverseSelectionModel : FutureUniverseSelectionModel
    -{
    -    // Daily updating with select_future_chain_symbols function
    -    public FrontMonthFutureUniverseSelectionModel()
    -        : base(TimeSpan.FromDays(1), SelectFutureChainSymbols) {}
    -
    -    private static IEnumerable<Symbol> SelectFutureChainSymbols(DateTime utcTime)
    -    {
    -        //Select gold and micro gold contracts for the strategy need
    -        return new List<Symbol> {
    -            QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX),
    -            QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX)
    -        };
    -    }
    -
    -    protected override FutureFilterUniverse Filter(FutureFilterUniverse filter)
    -    {
    -        // Filter only front month contract for liquidity and most informed information
    -        return filter.FrontMonth().OnlyApplyFilterAtMarketOpen();
    -    }
    -}
    -
    -
    -class ConstantFuturesAlphaModel : AlphaModel
    -{
    -    // Long gold and short micro gold in this strategy
    -    private Symbol 
    -        _longSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX), 
    -        _shortSymbol = QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX);
    -    
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -
    -        if (algorithm.Portfolio.Invested)
    -        {
    -            return insights;
    -        }
    -        
    -        // For both gold and micro gold, select the front month contract (only contract) in the chain
    -        foreach (var kvp in slice.FutureChains)
    -        {
    -            var symbol = kvp.Key;
    -            var chain = kvp.Value;
    -            var contract = chain.First();
    -            
    -            // Long gold and short micro gold as planned
    -            if (symbol == _longSymbol)
    -            {
    -                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Up));
    -            }
    -            else if (symbol == _shortSymbol)
    -            {
    -                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Down));
    -            }
    -        }
    -
    -        return insights;
    -    }
    -    
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            // Historical data
    -            var history = algorithm.History(security.Symbol, 100, Resolution.Minute);
    -            algorithm.Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    -        }
    -    }
    -}
    -    
    -    
    -class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        var targets = new List<PortfolioTarget>();
    -        foreach (var insight in insights)
    -        {
    -            if (algorithm.Securities[insight.Symbol].IsTradable)
    -            {
    -                // Single share only using integer portfolio target
    -                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -            }
    -        }
    -        return targets;
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Future Universe dataset provides - - FutureFilterUniverse - - and - - FutureUniverse - - objects. -

    -

    - FutureFilterUniverse Attributes -

    -

    - - FutureFilterUniverse - - objects have the following attributes: -

    -
    -
    -

    - FutureUniverse Attributes -

    -

    - - FutureUniverse - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Futures Security Master

    -
    -
    -

    Introduction

    - - -

    - The US Futures Security Master dataset by QuantConnect provides mapping reference data for the most liquid contracts of the CME Group exchanges, calculated with popular rolling techniques. The data covers 157 root Future contracts, starts in May 2009, and is delivered on a daily frequency with a zip file with all the contract mappings. This dataset is created by daily processing of the US historical Future chains. -

    -

    - This dataset, paired with the US Futures dataset, supports the following rolling techniques: forward panama canal, backwards panama canal, and backwards ratio. You can set the specific rolling date to occur on the last trading day, first day month, or the day when the contract with the greatest open interest changes. -

    -

    - VIX Futures don't support continous contract rolling with open interest. -

    -

    - This is - - NOT - - the underlying Futures data ( - - US Futures - - dataset), which you need to purchase separately with a license from AlgoSeek. This security master dataset is required to purchase the US Futures or US Future Options datasets. -

    -

    - For more information about the US Futures Security Master dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - You don't need any special code to utilize the US Futures Security Master. It automatically loads when you - - request US Futures data - - . -

    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - May 2009 -
    - Asset Coverage - - 157 Liquid Futures -
    - Data Density - - Regular -
    - Resolution - - Daily -
    -

    - VIX Futures don't support continous contract rolling with open interest. -

    - - - -

    Key Concept

    - - -

    - The US Futures Security Master lets you to construct continuous Futures, allowing the access of normalized historical data of the underlying assets, as well as trading the “lead” Future contracts for those assets. -

    -

    - Continuous Futures refer to sets of rolling lead Future contracts during their actively trading periods. Since Future contracts expire at their maturities, to analyze the historical price of a Future and to apply technical indicators, you need the continuous Future price series. -

    -

    - To access the continuous Future, use the Future's - - Symbol - - - symbol - - property. -

    -
    -
    # Set the data normalization mode and data mapping mode to select the contract as the continuous contract with price adjustment for smooth price series
    -future = self.add_future(Futures.Energy.CRUDE_OIL_WTI,
    -    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -    data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -    contract_depth_offset=0)
    -self.continuous_contract_symbol = future.symbol
    -
    // Set the data normalization mode and data mapping mode to select the contract as the continuous contract with price adjustment for smooth price series
    -var future = AddFuture(Futures.Energy.CrudeOilWTI,
    -    dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -    dataMappingMode: DataMappingMode.OpenInterest,
    -    contractDepthOffset: 0
    -);
    -_continuousFutureSymbol = future.Symbol;
    -
    -

    - The - - dataNormalizationMode - - and - - dataMappingMode - - arguments makes the transition of the underlying contracts seemless. However, the Future - - Symbol - - doesn't map to an underlying Future contract. It works fine to trade within backtests, but could be subjected to friction costs during live trading since the order price could be a normalized price. For more information about this topic, see the - - Live Trading Considerations - - section. -

    - - - -

    Data Normalization Modes

    - - -

    - The data normalization mode defines how the price series of two contracts are stitched together when the contract rollovers occur. The - - DataNormalizatoinMode - - enumeration has the following members available for continuous contracts: -

    -
    -
    -

    - If you use a data normalization mode that's not in the preceding list, LEAN automatically converts it to - - DataNormalizationMode.BackwardsRatio - - . -

    - - - -

    Data Mapping Modes

    - - -

    - The data mapping mode defines when contract rollovers occur. The - - DataMappingMode - - enumeration has the following members: -

    -
    -
    -

    - VIX Futures don't support continous contract rolling with - - DataMappingMode.OpenInterest - - - DataMappingMode.OPEN_INTEREST - - and - - DataMappingMode.OpenInterestAnnuak - - - DataMappingMode.OPEN_INTEREST_ANNUAL - - . -

    - - - -

    Tracking Contract Changes

    - - -

    - As the contracts roll over, the - - Mapped - - - mapped - - property of the - - Future - - object references the next contract in the series and you receive a - - SymbolChangedEvent - - . To get the current - - Symbol - - change events, index the - - SymbolChangedEvents - - - symbol_changed_events - - property of the current - - - Slice - - - with the continuous Futures - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your Future at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Get Symbol Change Event of the Continuous Future (change in mapped contract)
    -    changed_event = slice.symbol_changed_events.get(self.continuous_future_symbol)
    -    if changed_event:
    -        old_symbol = changed_event.old_symbol
    -        new_symbol = self.add_future_contract(changed_event.new_symbol).symbol
    -        tag = f"Rollover - Symbol changed at {self.time}: {old_symbol} -> {new_symbol}"
    -        quantity = self.portfolio[old_symbol].quantity
    -
    -        # Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    -        self.liquidate(old_symbol, tag = tag)
    -        if quantity != 0: self.market_order(new_symbol, quantity, tag = tag)
    -        self.log(tag)
    -
    public override void OnData(Slice slice)
    -{
    -    // Get Symbol Change Event of the Continuous Future (change in mapped contract)
    -    if (slice.SymbolChangedEvents.TryGetValue(_continuousFutureSymbol, out var changedEvent))
    -    {
    -        var oldSymbol = changedEvent.OldSymbol;
    -        var newSymbol = AddFutureContract(changedEvent.NewSymbol).Symbol;
    -        var tag = $"Rollover - Symbol changed at {Time}: {oldSymbol} -> {newSymbol}";
    -        var quantity = Portfolio[oldSymbol].Quantity;
    -        // Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    -        Liquidate(oldSymbol, tag: tag);
    -        if (quantity != 0) MarketOrder(newSymbol, quantity, tag: tag);
    -        Log(tag);
    -    }
    -}
    -
    -

    - - SymbolChangedEvent - - objects have the following attributes: -

    -
    -
    - - - -

    Live Trading Considerations

    - - -

    - You can trade continuous Futures, but the continuous Future - - Symbol - - doesn't map to a single underlying Future contract. Instead, it represents a set of rolling contracts. Thus, the prices could be frictional during a contract rollover, which could be catastrophic in live trading! For live trading, you should place your orders directly on the underlying contracts. To get the current underlying contract in the continuous Future series, use the - - Mapped - - - mapped - - property. -

    -
    -
    # Get the mapped symbol
    -current_contract = self.continuous_contract.mapped
    -self.buy(current_contract, 1)
    -
    // Get the mapped symbol
    -var currentContract = _continuousContract.Mapped;
    -Buy(currentContract, 1);
    -
    - - - -

    Data Format

    - - -

    - If you download the files in the US Futures Security Master, you get a factor file and a map file for each of the exchanges with supported continuous Futures. To view the files, see the - - \data\future\<exchange_name> - - directory under your LEAN CLI base directory. -

    -

    - For the factor file, it is a - - .zip - - collection of REST API styled - - .csv - - files for each Future - - Symbol - - , including the date, scaling factors for each type of data normalization and the data mapping mode that indicates the Symbol changing event is on that day for that mapping mode. The following line is an example line in the - - .csv - - file: -

    - - {"Date":"2009-10-31T00:00:00","BackwardsRatioScale":[0.9914163090128755364806866953,1.0,1.0],"BackwardsPanamaCanalScale":[-2.0,0.0,0.0],"ForwardPanamaCanalScale":[0.0,0.0,0.0],"DataMappingMode":1} - -
    -

    - For the map file, it is a - - .zip - - collection of - - .csv - - files for each Future - - Symbol - - , including the date, new underlying contract Symbol, the exchange code, and the data mapping mode that indicates the Symbol changing event is on that day for that mapping mode. The following line is an example line in the - - .csv - - file: -

    - - 20091130,aw uii3j0m6zbj9,CBOT,1 - - - - -

    Historical Data

    - - -

    - You can get historical US Future Security Master data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Future Security Master data in an algorithm, call the - - History<SymbolChangedEvent> - - - history - - method with continuous Future - - Symbol - - and a lookback period. This method returns the old and new contract of each rollover. If there is no data for the period you requested, the history result is empty. -

    -
    -
    # Add the Future and define its rollover settings.
    -future = self.add_future(
    -    Futures.Indices.SP_500_E_MINI,
    -    data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -    contract_depth_offset=0
    -)
    -
    -# DataFrame example where the columns are the SymbolChangedEvent attributes:
    -history_df = self.history(SymbolChangedEvent, future.symbol, timedelta(365))
    -
    -# SymbolChangedEvent objects example:
    -history = self.history[SymbolChangedEvent](future.symbol, timedelta(365))
    -
    // Add the Future and define its rollover settings.
    -var future = AddFuture(
    -    Futures.Indices.SP500EMini,
    -    dataMappingMode: DataMappingMode.OpenInterest,
    -    dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -    contractDepthOffset: 0
    -);
    -
    -// Get historical data.
    -var history = History<SymbolChangedEvent>(future.Symbol, TimeSpan.FromDays(365));
    -
    -

    - For more information about historical US Future Security Master data in algorithms, see - - Symbol Changes - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Future Security Master data in the Research Environment, call the - - History<SymbolChangedEvent> - - - history - - method with continuous Future - - Symbol - - and a time period. This method returns the old and new contract of each rollover. If there is no data for the period you requested, the history result is empty. -

    -
    -
    # Add the Future and define its rollover settings.
    -future = qb.add_future(
    -    Futures.Indices.SP_500_E_MINI,
    -    data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -    contract_depth_offset=0
    -)
    -
    -# DataFrame example where the columns are the SymbolChangedEvent attributes:
    -history_df = qb.history(SymbolChangedEvent, future.symbol, datetime(2023, 1, 1), datetime(2025, 1, 1))
    -
    -# SymbolChangedEvent objects example:
    -history = qb.history[SymbolChangedEvent](future.symbol, datetime(2023, 1, 1), datetime(2025, 1, 1))
    -
    // Add the Future and define its rollover settings.
    -var future = qb.AddFuture(
    -    Futures.Indices.SP500EMini,
    -    dataMappingMode: DataMappingMode.OpenInterest,
    -    dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -    contractDepthOffset: 0
    -);
    -
    -// Get historical data.
    -var history = qb.History<SymbolChangedEvent>(future.Symbol, new DateTime(2023, 1, 1), new DateTime(2025, 1, 1));
    -
    -

    - For more information about historical US Future Security Master data in the Research Environment, see - - Symbol Changes History - - . -

    - - - -

    Supported Assets

    - - -

    - The following list shows the available (157) Futures: -

    -
      -
    • - - Futures.Currencies.AUD - - : Australian Dollar Futures (CME: 6A) -
    • -
    • - - Futures.Currencies.AUDCAD - - : Australian Dollar/Canadian Dollar Futures (CME: ACD) -
    • -
    • - - Futures.Currencies.AUDJPY - - : Australian Dollar/Japanese Yen Futures (CME: AJY) -
    • -
    • - - Futures.Currencies.AUDNZD - - : Australian Dollar/New Zealand Dollar Futures (CME: ANE) -
    • -
    • - - Futures.Currencies.BRL - - : Brazillian Real Futures (CME: 6L) -
    • -
    • - - Futures.Currencies.BTC - - : Bitcoin Futures (CME: BTC) -
    • -
    • - - Futures.Currencies.BTICMicroBTC - - - Futures.Currencies.BTIC_MICRO_BTC - - : BTIC on Micro Bitcoin Futures (CME: MIB) -
    • -
    • - - Futures.Currencies.BTICMicroEther - - - Futures.Currencies.BTIC_MICRO_ETHER - - : BTIC on Micro Ether Futures (CME: MRB) -
    • -
    • - - Futures.Currencies.CAD - - : Canadian Dollar Futures (CME: 6C) -
    • -
    • - - Futures.Currencies.CADJPY - - : Canadian Dollar/Japanese Yen Futures (CME: CJY) -
    • -
    • - - Futures.Currencies.CHF - - : Swiss Franc Futures (CME: 6S) -
    • -
    • - - Futures.Currencies.ETH - - : Ether Futures (CME: ETH) -
    • -
    • - - Futures.Currencies.EUR - - : Euro FX Futures (CME: 6E) -
    • -
    • - - Futures.Currencies.EURAUD - - : Euro/Australian Dollar Futures (CME: EAD) -
    • -
    • - - Futures.Currencies.EURCAD - - : Euro/Canadian Dollar Futures (CME: ECD) -
    • -
    • - - Futures.Currencies.EuroFXEmini - - - Futures.Currencies.EURO_FX_EMINI - - : E-mini Euro FX Futures (CME: E7) -
    • -
    • - - Futures.Currencies.EURSEK - - : Euro/Swedish Krona Futures (CME: ESK) -
    • -
    • - - Futures.Currencies.GBP - - : British Pound Futures (CME: 6B) -
    • -
    • - - Futures.Currencies.JapaneseYenEmini - - - Futures.Currencies.JAPANESE_YEN_EMINI - - : E-mini Japanese Yen Futures (CME: J7) -
    • -
    • - - Futures.Currencies.JPY - - : Japanese Yen Futures (CME: 6J) -
    • -
    • - - Futures.Currencies.MicroAUD - - - Futures.Currencies.MICRO_AUD - - : Micro AUD/USD Futures (CME: M6A) -
    • -
    • - - Futures.Currencies.MicroBTC - - - Futures.Currencies.MICRO_BTC - - : Micro Bitcoin Futures (CME: MBT) -
    • -
    • - - Futures.Currencies.MicroCAD - - - Futures.Currencies.MICRO_CAD - - : Micro USD/CAD Futures (CME: M6C) -
    • -
    • - - Futures.Currencies.MicroCADUSD - - - Futures.Currencies.MICRO_CADUSD - - : Micro CAD/USD Futures (CME: MCD) -
    • -
    • - - Futures.Currencies.MicroCHF - - - Futures.Currencies.MICRO_CHF - - : Micro CHF/USD Futures (CME: MSF) -
    • -
    • - - Futures.Currencies.MicroEther - - - Futures.Currencies.MICRO_ETHER - - : Micro Ether Futures (CME: MET) -
    • -
    • - - Futures.Currencies.MicroEUR - - - Futures.Currencies.MICRO_EUR - - : Micro EUR/USD Futures (CME: M6E) -
    • -
    • - - Futures.Currencies.MicroGBP - - - Futures.Currencies.MICRO_GBP - - : Micro GBP/USD Futures (CME: M6B) -
    • -
    • - - Futures.Currencies.MicroINRUSD - - - Futures.Currencies.MICRO_INRUSD - - : Micro INR/USD Futures (CME: MIR) -
    • -
    • - - Futures.Currencies.MicroJPY - - - Futures.Currencies.MICRO_JPY - - : Micro JPY/USD Futures (CME: MJY) -
    • -
    • - - Futures.Currencies.MicroUSDCHF - - - Futures.Currencies.MICRO_USDCHF - - : Micro USD/CHF Futures (CME: M6S) -
    • -
    • - - Futures.Currencies.MicroUSDCNH - - - Futures.Currencies.MICRO_USDCNH - - : Micro USD/CNH Futures (CME: MNH) -
    • -
    • - - Futures.Currencies.MicroUSDJPY - - - Futures.Currencies.MICRO_USDJPY - - : Micro USD/JPY Futures (CME: M6J) -
    • -
    • - - Futures.Currencies.MXN - - : Mexican Peso Futures (CME: 6M) -
    • -
    • - - Futures.Currencies.NZD - - : New Zealand Dollar Futures (CME: 6N) -
    • -
    • - - Futures.Currencies.RUB - - : Russian Ruble Futures (CME: 6R) -
    • -
    • - - Futures.Currencies.StandardSizeUSDOffshoreRMBCNH - - - Futures.Currencies.STANDARD_SIZE_USD_OFFSHORE_RMBCNH - - : Standard-Size USD/Offshore RMB (CNH) Futures (CME: CNH) -
    • -
    • - - Futures.Currencies.ZAR - - : South African Rand Futures (CME: 6Z) -
    • -
    • - - Futures.Energy.ArgusLLSvsWTIArgusTradeMonth - - - Futures.Energy.ARGUS_LL_SVS_WTI_ARGUS_TRADE_MONTH - - : Argus LLS vs. WTI (Argus) Trade Month Futures (NYMEX: AE5) -
    • -
    • - - Futures.Energy.ArgusPropaneFarEastIndex - - - Futures.Energy.ARGUS_PROPANE_FAR_EAST_INDEX - - : Argus Propane Far East Index Futures (NYMEX: A7E) -
    • -
    • - - Futures.Energy.ArgusPropaneSaudiAramco - - - Futures.Energy.ARGUS_PROPANE_SAUDI_ARAMCO - - : Argus Propane (Saudi Aramco) Futures (NYMEX: A9N) -
    • -
    • - - Futures.Energy.BrentCrudeOilVsDubaiCrudeOilPlatts - - - Futures.Energy.BRENT_CRUDE_OIL_VS_DUBAI_CRUDE_OIL_PLATTS - - : Brent Crude Oil vs. Dubai Crude Oil (Platts) Futures (NYMEX: ADB) -
    • -
    • - - Futures.Energy.BrentLastDayFinancial - - - Futures.Energy.BRENT_LAST_DAY_FINANCIAL - - : Brent Last Day Financial Futures (NYMEX: BZ) -
    • -
    • - - Futures.Energy.ChicagoEthanolPlatts - - - Futures.Energy.CHICAGO_ETHANOL_PLATTS - - : Chicago Ethaanol (Platts) Futures (NYMEX: CU) -
    • -
    • - - Futures.Energy.ConwayPropaneOPIS - - - Futures.Energy.CONWAY_PROPANE_OPIS - - : Conway Propane (OPIS) Futures (NYMEX: A8K) -
    • -
    • - - Futures.Energy.CrudeOilWTI - - - Futures.Energy.CRUDE_OIL_WTI - - : Crude Oil WTI Futures (NYMEX: CL) -
    • -
    • - - Futures.Energy.DubaiCrudeOilPlattsFinancial - - - Futures.Energy.DUBAI_CRUDE_OIL_PLATTS_FINANCIAL - - : Dubai Crude Oil (Platts) Financial Futures (NYMEX: DCB) -
    • -
    • - - Futures.Energy.EastWestGasolineSpreadPlattsArgus - - - Futures.Energy.EAST_WEST_GASOLINE_SPREAD_PLATTS_ARGUS - - : East-West Gasoline Spread (Platts-Argus) Futures (NYMEX: EWG) -
    • -
    • - - Futures.Energy.EastWestNaphthaJapanCFvsCargoesCIFNWESpreadPlatts - - - Futures.Energy.EAST_WEST_NAPHTHA_JAPAN_C_FVS_CARGOES_CIFNWE_SPREAD_PLATTS - - : East-West Naphtha: Japan C&F vs. Cargoes CIF NWE Spread (Platts) Futures (NYMEX: EWN) -
    • -
    • - - Futures.Energy.Ethanol - - - Futures.Energy.ETHANOL - - : Ethanol Futures (CBOT: EH) -
    • -
    • - - Futures.Energy.EthanolT2FOBRdamIncludingDutyPlatts - - - Futures.Energy.ETHANOL_T_2_FOB_RDAM_INCLUDING_DUTY_PLATTS - - : Ethanol T2 FOB Rdam Including Duty (Platts) Futures (NYMEX: AZ1) -
    • -
    • - - Futures.Energy.EuropeanNaphthaPlattsCrackSpread - - - Futures.Energy.EUROPEAN_NAPHTHA_PLATTS_CRACK_SPREAD - - : European Naphtha (Platts) Crack Spread Futures (NYMEX: EN) -
    • -
    • - - Futures.Energy.EuropeanPropaneCIFARAArgus - - - Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS - - : European Propane CIF ARA (Argus) Futures (NYMEX: APS) -
    • -
    • - - Futures.Energy.EuropeanPropaneCIFARAArgusVsNaphthaCargoesCIFNWEPlatts - - - Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS_VS_NAPHTHA_CARGOES_CIFNWE_PLATTS - - : European Propane CIF ARA (Argus) vs. Naphtha Cargoes CIF NWE (Platts) Futures (NYMEX: EPN) -
    • -
    • - - Futures.Energy.FreightRouteTC14Baltic - - - Futures.Energy.FREIGHT_ROUTE_TC_14_BALTIC - - : Freight Route TC14 (Baltic) Futures (NYMEX: FRC) -
    • -
    • - - Futures.Energy.Gasoline - - - Futures.Energy.GASOLINE - - : Gasoline RBOB Futures (NYMEX: RB) -
    • -
    • - - Futures.Energy.GasolineEurobobOxyNWEBargesArgus - - - Futures.Energy.GASOLINE_EUROBOB_OXY_NWE_BARGES_ARGUS - - : Gasoline Euro-bob Oxy NWE Barges (Argus) Futures (NYMEX: B7H) -
    • -
    • - - Futures.Energy.GroupThreeSuboctaneGasolinePlattsVsRBOB - - - Futures.Energy.GROUP_THREE_SUBOCTANE_GASOLINE_PLATTS_VS_RBOB - - : Group Three Sub-octane Gasoliine (Platts) vs. RBOB Futures (NYMEX: AA8) -
    • -
    • - - Futures.Energy.GroupThreeULSDPlattsVsNYHarborULSD - - - Futures.Energy.GROUP_THREE_ULSD_PLATTS_VS_NY_HARBOR_ULSD - - : Group Three ULSD (Platts) vs. NY Harbor ULSD Futures (NYMEX: AA6) -
    • -
    • - - Futures.Energy.GulfCoastCBOBGasolineA2PlattsVsRBOBGasoline - - - Futures.Energy.GULF_COAST_CBOB_GASOLINE_A_2_PLATTS_VS_RBOB_GASOLINE - - : Gulf Coast CBOB Gasoline A2 (Platts) vs. RBOB Gasoline Futures (NYMEX: CRB) -
    • -
    • - - Futures.Energy.GulfCoastHSFOPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.GULF_COAST_HSFO_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : Gulf Coast HSFO (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: GCU) -
    • -
    • - - Futures.Energy.HeatingOil - - - Futures.Energy.HEATING_OIL - - : Heating Oil Futures (NYMEX: HO) -
    • -
    • - - Futures.Energy.LosAngelesCARBOBGasolineOPISvsRBOBGasoline - - - Futures.Energy.LOS_ANGELES_CARBOB_GASOLINE_OPI_SVS_RBOB_GASOLINE - - : Los Angeles CARBOB Gasoline (OPIS) vs. RBOB Gasoline Futures (NYMEX: AJL) -
    • -
    • - - Futures.Energy.LosAngelesCARBDieselOPISvsNYHarborULSD - - - Futures.Energy.LOS_ANGELES_CARB_DIESEL_OPI_SVS_NY_HARBOR_ULSD - - : Los Angeles CARB Diesel (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AKL) -
    • -
    • - - Futures.Energy.LosAngelesJetOPISvsNYHarborULSD - - - Futures.Energy.LOS_ANGELES_JET_OPI_SVS_NY_HARBOR_ULSD - - : Los Angeles Jet (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AJS) -
    • -
    • - - Futures.Energy.MarsArgusVsWTIFinancial - - - Futures.Energy.MARS_ARGUS_VS_WTI_FINANCIAL - - : Mars (Argus) vs. WTI Financial Futures (NYMEX: AYX) -
    • -
    • - - Futures.Energy.MarsArgusVsWTITradeMonth - - - Futures.Energy.MARS_ARGUS_VS_WTI_TRADE_MONTH - - : Mars (Argus) vs. WTI Trade Month Futures (NYMEX: AYV) -
    • -
    • - - Futures.Energy.MicroCrudeOilWTI - - - Futures.Energy.MICRO_CRUDE_OIL_WTI - - : Micro WTI Crude Oil Futures (NYMEX: MCL) -
    • -
    • - - Futures.Energy.MicroEuropeanFOBRdamMarineFuelZeroPointFivePercentBargesPlatts - - - Futures.Energy.MICRO_EUROPEAN_FOB_RDAM_MARINE_FUEL_ZERO_POINT_FIVE_PERCENT_BARGES_PLATTS - - : Micro European FOB Rdam Marine Fuel 0.5% Barges (Platts) Futures (NYMEX: R5O) -
    • -
    • - - Futures.Energy.MicroEuropeanThreePointFivePercentOilBargesFOBRdamPlatts - - - Futures.Energy.MICRO_EUROPEAN_THREE_POINT_FIVE_PERCENT_OIL_BARGES_FOB_RDAM_PLATTS - - : Micro European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: MEF) -
    • -
    • - - Futures.Energy.MicroGasoilZeroPointOnePercentBargesFOBARAPlatts - - - Futures.Energy.MICRO_GASOIL_ZERO_POINT_ONE_PERCENT_BARGES_FOBARA_PLATTS - - : Micro Gasoil 0.1% Barges FOB ARA (Platts) Futures (NYMEX: M1B) -
    • -
    • - - Futures.Energy.MicroSingaporeFOBMarineFuelZeroPointFivePercetPlatts - - - Futures.Energy.MICRO_SINGAPORE_FOB_MARINE_FUEL_ZERO_POINT_FIVE_PERCET_PLATTS - - : Micro Singapore FOB Marine Fuel 0.5% (Platts) Futures (NYMEX: S5O) -
    • -
    • - - Futures.Energy.MicroSingaporeFuelOil380CSTPlatts - - - Futures.Energy.MICRO_SINGAPORE_FUEL_OIL_380_CST_PLATTS - - : Micro Singapore Fuel Oil 380CST (Platts) Futures (NYMEX: MAF) -
    • -
    • - - Futures.Energy.MiniEuropeanThreePointPercentFiveFuelOilBargesPlatts - - - Futures.Energy.MINI_EUROPEAN_THREE_POINT_PERCENT_FIVE_FUEL_OIL_BARGES_PLATTS - - : Mini European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: A0D) -
    • -
    • - - Futures.Energy.MiniSingaporeFuelOil180CstPlatts - - - Futures.Energy.MINI_SINGAPORE_FUEL_OIL_180_CST_PLATTS - - : Mini Singapore Fuel Oil 180 cst (Platts) Futures (NYMEX: A0F) -
    • -
    • - - Futures.Energy.MontBelvieuEthaneOPIS - - - Futures.Energy.MONT_BELVIEU_ETHANE_OPIS - - : Mont Belvieu Ethane (OPIS) Futures (NYMEX: AC0) -
    • -
    • - - Futures.Energy.MontBelvieuLDHPropaneOPIS - - - Futures.Energy.MONT_BELVIEU_LDH_PROPANE_OPIS - - : Mont Belvieu LDH Propane (OPIS) Futures (NYMEX: B0) -
    • -
    • - - Futures.Energy.MontBelvieuNaturalGasolineOPIS - - - Futures.Energy.MONT_BELVIEU_NATURAL_GASOLINE_OPIS - - : Mont Belvieu Natural Gasoline (OPIS) Futures (NYMEX: A7Q) -
    • -
    • - - Futures.Energy.MontBelvieuNormalButaneOPIS - - - Futures.Energy.MONT_BELVIEU_NORMAL_BUTANE_OPIS - - : Mont Belvieu Normal Butane (OPIS) Futures (NYMEX: AD0) -
    • -
    • - - Futures.Energy.NaturalGas - - - Futures.Energy.NATURAL_GAS - - : Natural Gas Futures (NYMEX: NG) -
    • -
    • - - Futures.Energy.NaturalGasHenryHubLastDayFinancial - - - Futures.Energy.NATURAL_GAS_HENRY_HUB_LAST_DAY_FINANCIAL - - : Natural Gas (Henry Hub) Last-day Financial Futures (NYMEX: HH) -
    • -
    • - - Futures.Energy.NaturalGasHenryHubPenultimateFinancial - - - Futures.Energy.NATURAL_GAS_HENRY_HUB_PENULTIMATE_FINANCIAL - - : Natural Gas (Henry Hub) Penultimate Financial Futures (NYMEX: HP) -
    • -
    • - - Futures.Energy.OnePercentFuelOilCargoesFOBNWEPlattsVsThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.ONE_PERCENT_FUEL_OIL_CARGOES_FOBNWE_PLATTS_VS_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : 1% Fuel Oil Cargoes FOB NWE (Platts) vs. 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: FSS) -
    • -
    • - - Futures.Energy.PremiumUnleadedGasoline10ppmFOBMEDPlatts - - - Futures.Energy.PREMIUM_UNLEADED_GASOLINE_10_PPM_FOBMED_PLATTS - - : Premium Unleaded Gasoline 10 ppm FOB MED (Platts) Futures (NYMEX: A3G) -
    • -
    • - - Futures.Energy.PropaneNonLDHMontBelvieuOPIS - - - Futures.Energy.PROPANE_NON_LDH_MONT_BELVIEU_OPIS - - : Propane Non-LDH Mont Belvieu (OPIS) Futures (NYMEX: A1R) -
    • -
    • - - Futures.Energy.RBOBGasolineCrackSpread - - - Futures.Energy.RBOB_GASOLINE_CRACK_SPREAD - - : RBOB Gasoline Crack Spread Futures (NYMEX: ARE) -
    • -
    • - - Futures.Energy.RBOBGasolineVsEurobobOxyNWEBargesArgusThreeHundredFiftyThousandGallons - - - Futures.Energy.RBOB_GASOLINE_VS_EUROBOB_OXY_NWE_BARGES_ARGUS_THREE_HUNDRED_FIFTY_THOUSAND_GALLONS - - : RBOB Gasoline vs. Euro-bob Oxy NWE Barges (Argus) (350,000 gallons) Futures (NYMEX: EXR) -
    • -
    • - - Futures.Energy.SingaporeFuelOil380cstPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.SINGAPORE_FUEL_OIL_380_CST_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : Singapore Fuel Oil 380 cst (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: EVC) -
    • -
    • - - Futures.Energy.SingaporeGasoilPlattsVsLowSulphurGasoilFutures - - - Futures.Energy.SINGAPORE_GASOIL_PLATTS_VS_LOW_SULPHUR_GASOIL_FUTURES - - : Singapore Gasoil (Platts) vs. Low Sulphur Gasoil Futures (NYMEX: AGA) -
    • -
    • - - Futures.Energy.SingaporeMogas92UnleadedPlattsBrentCrackSpread - - - Futures.Energy.SINGAPORE_MOGAS_92_UNLEADED_PLATTS_BRENT_CRACK_SPREAD - - : Singapore Mogas 92 Unleaded (Platts) Brent Crack Spread Futures (NYMEX: D1N) -
    • -
    • - - Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread - - - Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD - - : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread Futures (NYMEX: FO) -
    • -
    • - - Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread1000mt - - - Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD_1000_MT - - : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread (1000mt) Futures (NYMEX: BOO) -
    • -
    • - - Futures.Energy.WTIBrentFinancial - - - Futures.Energy.WTI_BRENT_FINANCIAL - - : WTI-Brent Financial Futures (NYMEX: BK) -
    • -
    • - - Futures.Energy.WTIFinancial - - - Futures.Energy.WTI_FINANCIAL - - : WTI Financial Futures (NYMEX: CSX) -
    • -
    • - - Futures.Energy.WTIHoustonArgusVsWTITradeMonth - - - Futures.Energy.WTI_HOUSTON_ARGUS_VS_WTI_TRADE_MONTH - - : WTI Houston (Argus) vs. WTI Trade Month Futures (NYMEX: HTT) -
    • -
    • - - Futures.Energy.WTIHoustonCrudeOil - - - Futures.Energy.WTI_HOUSTON_CRUDE_OIL - - : WTI Houston Crude Oil Futures (NYMEX: HCL) -
    • -
    • - - Futures.Financials.EuroDollar - - - Futures.Financials.EURO_DOLLAR - - : EuroDollar Futures (CME: GE) -
    • -
    • - - Futures.Financials.FiveYearUSDMACSwap - - - Futures.Financials.FIVE_YEAR_USDMAC_SWAP - - : 5-Year USD MAC Swap Futures (CBOT: F1U) -
    • -
    • - - Futures.Financials.MicroY10TreasuryNote - - - Futures.Financials.MICRO_Y_10_TREASURY_NOTE - - : Micro 10-Year Yield Futures (CBOT: 10Y) -
    • -
    • - - Futures.Financials.MicroY2TreasuryBond - - - Futures.Financials.MICRO_Y_2_TREASURY_BOND - - : Micro 2-Year Yield Futures (CBOT: 2YY) -
    • -
    • - - Futures.Financials.MicroY30TreasuryBond - - - Futures.Financials.MICRO_Y_30_TREASURY_BOND - - : Micro 30-Year Yield Futures (CBOT: 30Y) -
    • -
    • - - Futures.Financials.MicroY5TreasuryBond - - - Futures.Financials.MICRO_Y_5_TREASURY_BOND - - : Micro 5-Year Yield Futures (CBOT: 5YY) -
    • -
    • - - Futures.Financials.UltraTenYearUSTreasuryNote - - - Futures.Financials.ULTRA_TEN_YEAR_US_TREASURY_NOTE - - : Ultra 10-Year U.S. Treasury Note Futures (CBOT: TN) -
    • -
    • - - Futures.Financials.UltraUSTreasuryBond - - - Futures.Financials.ULTRA_US_TREASURY_BOND - - : Ultra U.S. Treasury Bond Futures (CBOT: UB) -
    • -
    • - - Futures.Financials.Y10TreasuryNote - - - Futures.Financials.Y_10_TREASURY_NOTE - - : 10Y U.S. Treasury Note Futures (CBOT: ZN) -
    • -
    • - - Futures.Financials.Y2TreasuryNote - - - Futures.Financials.Y_2_TREASURY_NOTE - - : 2Y U.S. Treasury Note Futures (CBOT: ZT) -
    • -
    • - - Futures.Financials.Y30TreasuryBond - - - Futures.Financials.Y_30_TREASURY_BOND - - : 30Y U.S. Treasury Bond Futures (CBOT: ZB) -
    • -
    • - - Futures.Financials.Y5TreasuryNote - - - Futures.Financials.Y_5_TREASURY_NOTE - - : 5Y U.S. Treasury Note Futures (CBOT: ZF) -
    • -
    • - - Futures.Forestry.Lumber - - - Futures.Forestry.LUMBER - - : Lumber Futures (CME: LBR) -
    • -
    • - - Futures.Forestry.RandomLengthLumber - - - Futures.Forestry.RANDOM_LENGTH_LUMBER - - : Random Length Lumber Futures (CME: LBS) -
    • -
    • - - Futures.Grains.BlackSeaCornFinanciallySettledPlatts - - - Futures.Grains.BLACK_SEA_CORN_FINANCIALLY_SETTLED_PLATTS - - : Black Sea Corn Financially Settled (Platts) Futures (CBOT: BCF) -
    • -
    • - - Futures.Grains.BlackSeaWheatFinanciallySettledPlatts - - - Futures.Grains.BLACK_SEA_WHEAT_FINANCIALLY_SETTLED_PLATTS - - : Black Sea Wheat Financially Settled (Platts) Futures (CBOT: BWF) -
    • -
    • - - Futures.Grains.Corn - - - Futures.Grains.CORN - - : Corn Futures (CBOT: ZC) -
    • -
    • - - Futures.Grains.HRWWheat - - - Futures.Grains.HRW_WHEAT - - : KC HRW Wheat Futures (CBOT: KE) -
    • -
    • - - Futures.Grains.Oats - - - Futures.Grains.OATS - - : Oats Futures (CBOT: ZO) -
    • -
    • - - Futures.Grains.Soybeans - - - Futures.Grains.SOYBEANS - - : Soybeans Futures (CBOT: ZS) -
    • -
    • - - Futures.Grains.SoybeanMeal - - - Futures.Grains.SOYBEAN_MEAL - - : Soybean Meal Futures (CBOT: ZM) -
    • -
    • - - Futures.Grains.SoybeanOil - - - Futures.Grains.SOYBEAN_OIL - - : Soybean Oil Futures (CBOT: ZL) -
    • -
    • - - Futures.Grains.Wheat - - - Futures.Grains.WHEAT - - : Default wheat contract is SRWWheat (CBOT: ZW) -
    • -
    • - - Futures.Indices.BloombergCommodityIndex - - - Futures.Indices.BLOOMBERG_COMMODITY_INDEX - - : Bloomberg Commodity Index Futures (CBOT: AW) -
    • -
    • - - Futures.Indices.Dow30EMini - - - Futures.Indices.DOW_30_E_MINI - - : E-mini Dow Indu 30 Futures (CBOT: YM) -
    • -
    • - - Futures.Indices.DowJonesRealEstate - - - Futures.Indices.DOW_JONES_REAL_ESTATE - - : Dow Jones Real Estate futures on CME (CME: RX) -
    • -
    • - - Futures.Indices.FTSEEmergingEmini - - - Futures.Indices.FTSE_EMERGING_EMINI - - : E-mini FTSE Emerging Index Futures (CME: EI) -
    • -
    • - - Futures.Indices.MicroDow30EMini - - - Futures.Indices.MICRO_DOW_30_E_MINI - - : Micro E-mini Dow Jones Industrial Average Index Futures (CBOT: MYM) -
    • -
    • - - Futures.Indices.MicroNASDAQ100EMini - - - Futures.Indices.MICRO_NASDAQ_100_E_MINI - - : Micro E-mini Nasdaq-100 Index Futures (CME: MNQ) -
    • -
    • - - Futures.Indices.MicroRussell2000EMini - - - Futures.Indices.MICRO_RUSSELL_2000_E_MINI - - : Micro E-mini Russell 2000 Index Futures (CME: M2K) -
    • -
    • - - Futures.Indices.MicroSP500EMini - - - Futures.Indices.MICRO_SP_500_E_MINI - - : Micro E-mini S&P 500 Index Futures (CME: MES) -
    • -
    • - - Futures.Indices.NASDAQ100BiotechnologyEMini - - - Futures.Indices.NASDAQ_100_BIOTECHNOLOGY_E_MINI - - : E-mini Nasdaq-100 Biotechnology Index Futures (CME: BIO) -
    • -
    • - - Futures.Indices.NASDAQ100EMini - - - Futures.Indices.NASDAQ_100_E_MINI - - : E-mini NASDAQ 100 Futures (CME: NQ) -
    • -
    • - - Futures.Indices.Nikkei225Dollar - - - Futures.Indices.NIKKEI_225_DOLLAR - - : Nikkei-225 Dollar Futures (CME: NKD) -
    • -
    • - - Futures.Indices.Nikkei225YenCME - - - Futures.Indices.NIKKEI_225_YEN_CME - - : Nikkei-225 Yen denominated Futures on CME (CME: NIY) -
    • -
    • - - Futures.Indices.Russell1000EMini - - - Futures.Indices.RUSSELL_1000_E_MINI - - : E-mini Russell 1000 futures on CME (CME: RS1) -
    • -
    • - - Futures.Indices.Russell2000EMini - - - Futures.Indices.RUSSELL_2000_E_MINI - - : E-mini Russell 2000 Futures (CME: RTY) -
    • -
    • - - Futures.Indices.SPGSCICommodity - - - Futures.Indices.SPGSCI_COMMODITY - - : S&P-GSCI Commodity Index Futures (CME: GD) -
    • -
    • - - Futures.Indices.SP400MidCapEmini - - - Futures.Indices.SP_400_MID_CAP_EMINI - - : E-mini S&P MidCap 400 Futures (CME: EMD) -
    • -
    • - - Futures.Indices.SP500AnnualDividendIndex - - - Futures.Indices.SP_500_ANNUAL_DIVIDEND_INDEX - - : (CME: SDA) -
    • -
    • - - Futures.Indices.SP500EMini - - - Futures.Indices.SP_500_E_MINI - - : E-mini S&P 500 Futures (CME: ES) -
    • -
    • - - Futures.Indices.TOPIXYEN - - : YEN Denominated Topix Index Futures on CME (CME: TPY) -
    • -
    • - - Futures.Indices.USDDenominatedIbovespa - - - Futures.Indices.USD_DENOMINATED_IBOVESPA - - : USD-Denominated Ibovespa Index Futures (CME: IBV) -
    • -
    • - - Futures.Indices.VIX - - : CBOE Volatility Index Futures (CFE: VX) -
    • -
    • - - Futures.Meats.FeederCattle - - - Futures.Meats.FEEDER_CATTLE - - : Feeder Cattle Futures (CME: GF) -
    • -
    • - - Futures.Meats.LeanHogs - - - Futures.Meats.LEAN_HOGS - - : Lean Hogs Futures (CME: HE) -
    • -
    • - - Futures.Meats.LiveCattle - - - Futures.Meats.LIVE_CATTLE - - : Live Cattle Futures (CME: LE) -
    • -
    • - - Futures.Metals.AluminiumEuropeanPremiumDutyPaidMetalBulletin - - - Futures.Metals.ALUMINIUM_EUROPEAN_PREMIUM_DUTY_PAID_METAL_BULLETIN - - : Aluminium European Premium Duty-Paid (Metal Bulletin) Futures (COMEX: EDP) -
    • -
    • - - Futures.Metals.AluminumMWUSTransactionPremiumPlatts25MT - - - Futures.Metals.ALUMINUM_MWUS_TRANSACTION_PREMIUM_PLATTS_25_MT - - : Aluminum MW U.S. Transaction Premium Platts (25MT) Futures (COMEX: AUP) -
    • -
    • - - Futures.Metals.Copper - - - Futures.Metals.COPPER - - : Copper Futures (COMEX: HG) -
    • -
    • - - Futures.Metals.Gold - - - Futures.Metals.GOLD - - : Gold Futures (COMEX: GC) -
    • -
    • - - Futures.Metals.MicroGold - - - Futures.Metals.MICRO_GOLD - - : Micro Gold Futures (COMEX: MGC) -
    • -
    • - - Futures.Metals.MicroGoldTAS - - - Futures.Metals.MICRO_GOLD_TAS - - : Micro Gold TAS Futures (COMEX: MGT) -
    • -
    • - - Futures.Metals.MicroPalladium - - - Futures.Metals.MICRO_PALLADIUM - - : Micro Palladium Futures (NYMEX: PAM) -
    • -
    • - - Futures.Metals.MicroSilver - - - Futures.Metals.MICRO_SILVER - - : Micro Silver Futures (COMEX: SIL) -
    • -
    • - - Futures.Metals.Palladium - - - Futures.Metals.PALLADIUM - - : Palladium Futures (NYMEX: PA) -
    • -
    • - - Futures.Metals.Platinum - - - Futures.Metals.PLATINUM - - : Platinum Futures (NYMEX: PL) -
    • -
    • - - Futures.Metals.Silver - - - Futures.Metals.SILVER - - : Silver Futures (COMEX: SI) -
    • -
    • - - Futures.Metals.USMidwestDomesticHotRolledCoilSteelCRUIndex - - - Futures.Metals.US_MIDWEST_DOMESTIC_HOT_ROLLED_COIL_STEEL_CRU_INDEX - - : U.S. Midwest Domestic Hot-Rolled Coil Steel (CRU) Index Futures (NYMEX: HRC) -
    • -
    • - - Futures.Softs.Sugar11 - - - Futures.Softs.SUGAR_11 - - : Sugar #11 Futures ICE (ICE: SB) -
    • -
    • - - Futures.Softs.Sugar11CME - - - Futures.Softs.SUGAR_11_CME - - : Sugar #11 Futures CME (NYMEX: YO) -
    • -
    - - - -

    Example Applications

    - - -

    - The US Futures Security Master enables you to design strategies harnessing continuous Futures contracts. Examples include the following strategies: -

    -
      -
    • - Trading cyclical patterns in commodity Futures. -
    • -
    • - Buying gold Futures as an inflation hedge with automatic contract roll-overs. -
    • -
    • - Detecting arbitrage opportunities between index Futures and Equities. -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm buys the continuous Future contract for Crude Oil when its price rises above its simple moving average. When its price drops below its simple moving average, the algorithm sells the continuous contract. Each time the continuous Future contract rolls over, the algorithm logs the event. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class USFuturesSecurityMasterDataClassicAlgorithm(QCAlgorithm):
    -    # Define a threshold for the SMA cross.
    -    _threshold = 0.01
    -    
    -    def initialize(self) -> None:
    -        self.set_cash(1000000)
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Seed the price of each asset with its last known price to 
    -        # avoid trading errors.
    -        self.settings.seed_initial_prices = True
    -        # Add a Future. Set the continuous contract mapping criteria to
    -        # the contract with highest open interest to provide the best 
    -        # price information for trend estimation.
    -        self._future = self.add_future(
    -            Futures.Energy.CRUDE_OIL_WTI,
    -            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -            contract_depth_offset=0
    -        )                      
    -        # Historical data: Get the contract rollovers for the trailing 
    -        # year.
    -        history = self.history(
    -            SymbolChangedEvent, self._future.symbol, timedelta(365)
    -        )
    -        # Set up an SMA indicator for to estimate the trend direction.
    -        self._sma = self.sma(self._future.symbol, 10, Resolution.DAILY)
    -        # Warm up the SMA indicator so we can trade right away.
    -        self.warm_up_indicator(self._future.symbol, self._sma)
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Wait until we have the latest TradeBar and the indicator is 
    -        # ready.
    -        if not (self._future.symbol in slice.bars and self._sma.is_ready):
    -            return
    -        contract = self.portfolio[self._future.mapped]
    -        # Long during an uptrend.
    -        if (not contract.is_long and 
    -            self._future.price > self._sma.current.value * (1+self._threshold)):
    -            quantity = 1
    -        # Short during an downtrend.
    -        elif (not contract.is_short and 
    -            self._future.price < self._sma.current.value * (1-self._threshold)):
    -            quantity = -1
    -        else:
    -            return
    -        self.market_order(self._future.mapped, quantity - contract.quantity)
    -
    -    def on_symbol_changed_events(self, symbol_changed_events):
    -        for symbol, changed_event in symbol_changed_events.items():
    -            old_symbol = changed_event.old_symbol
    -            new_symbol = changed_event.new_symbol
    -            # The quantity to roll over should be consistent.
    -            quantity = self.portfolio[old_symbol].quantity
    -            if not quantity:
    -                continue
    -            # Rolling over: Liquidate the old mapped contract and switch
    -            # to the new mapped contract.
    -            tag = f"Rollover: {old_symbol} -> {new_symbol}"
    -            self.liquidate(old_symbol, tag=tag)
    -            self.market_order(new_symbol, quantity, tag=tag)
    -
    public class USFuturesSecurityMasterDataClassicAlgorithm  : QCAlgorithm
    -{
    -    private Future _future;
    -    // Define a threshold for the SMA cross.
    -    private decimal _threshold = 0.01m;
    -    private SimpleMovingAverage _sma;
    -    
    -    public override void Initialize()
    -    {
    -        SetCash(1000000);
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Seed the price of each asset with its last known price to 
    -        // avoid trading errors.
    -        Settings.SeedInitialPrices = true;
    -        // Add a Future. Set the continuous contract mapping criteria to
    -        // the contract with highest open interest to provide the best 
    -        // price information for trend estimation.
    -        _future = AddFuture(
    -            Futures.Energy.CrudeOilWTI,
    -            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -            dataMappingMode: DataMappingMode.OpenInterest,
    -            contractDepthOffset: 0
    -        );
    -        // Historical data: Get the contract rollovers for the trailing 
    -        // year.
    -        var history = History<SymbolChangedEvent>(_future.Symbol, TimeSpan.FromDays(365));
    -        foreach (var symbolChangedEvent in history)
    -        {
    -            var t = symbolChangedEvent.EndTime;
    -            var oldSymbol = symbolChangedEvent.OldSymbol;
    -            var newSymbol = symbolChangedEvent.NewSymbol;
    -        }
    -        // Set up an SMA indicator for to estimate the trend direction.
    -        _sma = SMA(_future.Symbol, 10, Resolution.Daily);
    -        // Warm up the SMA indicator so we can trade right away.
    -        WarmUpIndicator(_future.Symbol, _sma);
    -    }
    -    
    -    public override void OnData(Slice slice)
    -    {       
    -        // Wait until we have the latest TradeBar and the indicator is 
    -        // ready.
    -        if (!(slice.Bars.ContainsKey(_future.Symbol) && _sma.IsReady))
    -        {
    -            return;
    -        }
    -        var contract = Portfolio[_future.Mapped];
    -        int quantity;
    -        // Long during an uptrend.
    -        if (!contract.IsLong && _future.Price > _sma.Current.Value * (1+_threshold))
    -        {
    -            quantity = 1;
    -        }
    -        // Short during an downtrend.
    -        else if (!contract.IsShort && _future.Price < _sma.Current.Value * (1-_threshold))
    -        {
    -            quantity = -1;
    -        }
    -        else
    -        {
    -            return;
    -        }
    -        MarketOrder(_future.Mapped, quantity - contract.Quantity);
    -    }
    -
    -    public override void OnSymbolChangedEvents(SymbolChangedEvents symbolChangedEvents)
    -    {
    -        foreach (var (symbol, changedEvent) in symbolChangedEvents)
    -        {
    -            var oldSymbol = changedEvent.OldSymbol;
    -            var newSymbol = changedEvent.NewSymbol;
    -            // The quantity to roll over should be consistent.
    -            var quantity = Portfolio[oldSymbol].Quantity;
    -            if (quantity == 0)
    -            {
    -                continue;
    -            }
    -            // Rolling over: Liquidate the old mapped contract and switch 
    -            // to the new mapped contract.
    -            var tag = $"Rollover: {oldSymbol} -> {newSymbol}";
    -            Liquidate(oldSymbol, tag: tag);
    -            MarketOrder(newSymbol, quantity, tag: tag);
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm buys the continuous Future contract for Crude Oil when its price rises above its simple moving average. When its price drops below its simple moving average, the algorithm sells the continuous contract. Each time the contract rolls over, the algorithm logs the event. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class USFuturesSecurityMasterDataFrameworkAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_cash(1000000)
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -
    -        # Setting the continuous contract mapping criteria, the contract with highest open interest provide the best price information for trend estimation
    -        self.add_future(Futures.Energies.CRUDE_OIL_WTI,
    -                       data_normalization_mode = DataNormalizationMode.BACKWARDS_RATIO,
    -                       data_mapping_mode = DataMappingMode.OPEN_INTEREST,
    -                       contract_depth_offset = 0)
    -        self.add_alpha(ContinuousFuturesAlphaModel())
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -
    -class ContinuousFuturesAlphaModel(AlphaModel):
    -    # 1% margin to reassure trend direction
    -    threshold = 0.01
    -    symbol = None
    -    continuous_contract = None
    -    
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        insights = []
    -        # Check if contract data available, since all trades are based on that only
    -        if self.continuous_contract_symbol is None or self.continuous_contract is None:
    -            return insights 
    -        
    -        # Up-to-date handling of switching the mapped contract for trade liquidity
    -        for symbol, changed_event in slice.symbol_changed_events.items():
    -            old_symbol = changed_event.old_symbol
    -            if algorithm.insights.has_active_insights(old_symbol, algorithm.utc_time):
    -                new_symbol = changed_event.new_symbol
    -                tag = f"Rollover - Symbol changed at {algorithm.time}: {old_symbol} -> {new_symbol}"
    -                last_insight = sorted(algorithm.insights[old_symbol], key=lambda x: x.close_time_utc)[-1]
    -                insights.append(Insight.price(new_symbol, last_insight.close_time_utc, last_insight.direction, tag= tag))
    -                algorithm.insights.clear([old_symbol])
    -                algorithm.log(tag)
    -         
    -        mapped_symbol = self.continuous_contract.mapped
    -        # Make sure trade decisions are based on newly received data
    -        if not slice.bars.contains_key(self.continuous_contract_symbol) or not self.sma.is_ready or not mapped_symbol:
    -            return insights 
    -        
    -        direction = None
    -        # Long if trend up by threshold to follow the trend
    -        if slice.bars[self.continuous_contract_symbol].price > self.sma.current.value * (1+self.threshold) and not algorithm.portfolio[mapped_symbol].is_long:
    -            direction = InsightDirection.UP
    -        # Short if trend down by threshold to follow the trend
    -        elif slice.bars[self.continuous_contract_symbol].price < self.sma.current.value * (1-self.threshold) and not algorithm.portfolio[mapped_symbol].is_short:
    -            direction = InsightDirection.DOWN
    -        
    -        if direction:
    -            insights.append(Insight.price(mapped_symbol, timedelta(days=14), direction))
    -        
    -        return insights
    -        
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            symbol = security.symbol
    -            # Set up SMA indicator for trend direction estimator, only for the canonical symbol
    -            if symbol.is_canonical():
    -                self.continuous_contract = security
    -                self.continuous_contract_symbol = symbol
    -                self.sma = algorithm.SMA(self.continuous_contract_symbol, 10, Resolution.DAILY)
    -            
    -                # Historical data
    -                history = algorithm.history(symbol, 60*24*10, Resolution.MINUTE)
    -                algorithm.debug(f"We got {len(history)} from our history request for {symbol}")
    -                
    -                if history.empty:
    -                    continue
    -                # Warm up the SMA indicator for its readiness for immediate use
    -                for time, row in history.droplevel(0).loc[self.continuous_contract_symbol].iterrows():
    -                    self.sma.update(IndicatorDataPoint(time, row.close))
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class USFuturesSecurityMasterDataFrameworkAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetCash(1000000);
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -
    -        // Setting the continuous contract mapping criteria, the contract with highest open interest provide the best price information for trend estimation
    -        AddFuture(Futures.Energies.CrudeOilWTI,
    -            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -            dataMappingMode: DataMappingMode.OpenInterest,
    -            contractDepthOffset: 0
    -        );
    -        AddAlpha(new ContinuousFuturesAlphaModel());
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -    
    -    class ContinuousFuturesAlphaModel : AlphaModel
    -    {
    -        private Future _continuousContract;
    -        private Symbol _symbol;
    -        // 1% margin to reassure trend direction
    -        private decimal _threshold = 0.01m;
    -        private SimpleMovingAverage _sma;
    -    
    -        public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -        {
    -            var insights = new List<Insight>();
    -            
    -            //  Check if contract data available, since all trades are based on that only
    -            if (_symbol == null || _continuousContract == null)
    -            {
    -                return insights;
    -            }
    -            
    -            // Up-to-date handling of switching the mapped contract for trade liquidity
    -            foreach (var (symbol, changedEvent) in slice.SymbolChangedEvents)
    -            {
    -                var oldSymbol = changedEvent.OldSymbol;
    -                if (algorithm.Insights.HasActiveInsights(oldSymbol, algorithm.UtcTime))
    -                {
    -                    var newSymbol = changedEvent.NewSymbol;
    -                    var tag = $"Rollover - Symbol changed at {algorithm.Time}: {oldSymbol} -> {newSymbol}";
    -                    var lastInsight = algorithm.Insights[oldSymbol].OrderBy(x => x.CloseTimeUtc).LastOrDefault();
    -                    insights.Add(Insight.Price(newSymbol, lastInsight.CloseTimeUtc, lastInsight.Direction, tag: tag));
    -                    algorithm.Insights.Clear(new Symbol[] { oldSymbol });
    -                    algorithm.Log(tag);
    -                }
    -            }
    -            
    -            var mappedSymbol = _continuousContract.Mapped;
    -            // Make sure trade decisions are based on newly received data
    -            if (!slice.Bars.ContainsKey(_symbol) || !_sma.IsReady || mappedSymbol == null)
    -            {
    -                return insights;
    -            }
    -            
    -            // Long if trend up by threshold to follow the trend
    -            if (slice.Bars[_symbol].Price > _sma.Current.Value * (1+_threshold) && !algorithm.Portfolio[mappedSymbol].IsLong)
    -            {
    -                insights.Add(Insight.Price(mappedSymbol, TimeSpan.FromDays(14), InsightDirection.Up));
    -            }
    -            // Short if trend down by threshold to follow the trend
    -            else if (slice.Bars[_symbol].Price < _sma.Current.Value * (1-_threshold) && !algorithm.Portfolio[mappedSymbol].IsShort)
    -            {
    -                insights.Add(Insight.Price(mappedSymbol, TimeSpan.FromDays(14), InsightDirection.Down));
    -            }
    -            
    -            return insights;
    -        }
    -    
    -        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -        {
    -            foreach (var security in changes.AddedSecurities)
    -            {
    -                var symbol = security.Symbol;
    -                // Set up SMA indicator for trend direction estimator, only for the canonical symbol
    -                if (symbol.IsCanonical())
    -                {
    -                    _continuousContract = (Future)security;
    -                    _symbol = symbol;
    -                    _sma = algorithm.SMA(_symbol, 10, Resolution.Daily);
    -                    
    -                    // Historical data 
    -                    var history = algorithm.History(symbol, 60*24*10, Resolution.Minute);
    -                    algorithm.Debug($"We got {history.Count()} from our history request for {symbol}");
    -                    
    -                    // Warm up the SMA indicator for its readiness for immediate use
    -                    foreach (var bar in history)
    -                    {
    -                        _sma.Update(new IndicatorDataPoint(bar.Time, bar.Close));
    -                    }
    -                }
    -            }
    -        }
    -    }
    -    
    -    class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -    {
    -        public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -        {
    -            var targets = new List<PortfolioTarget>();
    -            foreach (var insight in insights)
    -            {
    -                if (algorithm.Securities[insight.Symbol].IsTradable)
    -                {
    -                    targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -                }
    -            }
    -            return targets;
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Futures Security Master dataset provides - - SymbolChangedEvent - - objects, which have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    QuantConnect

    -

    US Index Option Universe

    -
    -
    -

    Introduction

    - - -

    - The US Index Option Universe dataset by QuantConnect lists the available US Index Options contracts and the current Implied Volatility and Greeks. The data covers European Option contracts for 3 US Indices: SPX, VIX, and NDX. It starts in January 2012 and is delivered on a daily update frequency. To create this dataset, we use - - our implementation - - of the forward tree pricing model, which accounts for the interest rate, dividend payments, and daily closing prices. The values in this dataset are the same values you can get from daily - - indicators - - with mirror Options. -

    -

    - This dataset - - does not - - contain market data. For market data, see - - US Index Options by AlgoSeek - - . -

    -

    - For more information about the US Index Option Universe dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Index Options Universe dataset: -

    -
    -
    option = self.add_index_option('VIX')
    -option.set_filter(lambda universe: universe.delta(0.4, 0.6))
    -self.option_symbol = option.symbol
    -
    var option = AddIndexOption("VIX");
    -option.SetFilter(universe => universe.delta(0.4m, 0.6m));
    -_optionSymbol = option.Symbol;
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2012 -
    - Asset Coverage - - 7 Index Options -
    - Data Density - - Dense -
    - Resolution - - Daily -
    - Timezone - - New York -
    - - - -

    Specification Over Time

    - - -

    - According to the SPX Options - - contract specification - - , some SPX contracts expire every month and SPXW contracts expires every day. Before 2021, you could only trade SPX contracts with the following expiration dates: -

    -
      -
    • - Expires within the next 4 months -
    • -
    • - Expires in September within the next 14 months -
    • -
    • - Expires in January, March, or June within the next 2 years -
    • -
    • - Expires in December within the next 3 years -
    • -
    -

    - During this time, SPXW didn't have 0DTE every day. -

    -

    - - Sources - - : -
    - - - - Cboe Options Exchange to List Three Long-Dated SPX Options Expirations, Beginning November 1, 2021 - -
    - - - - S&P 500 Weekly Options Now Expire Five Days a Week - -

    - - - -

    Requesting Data

    - - -

    - To add US Index Options Universe data to your algorithm, call the - - AddIndexOption - - - add_index_option - - method. Save a reference to the Index Option - - Symbol - - so you can access the data later in your algorithm. To define which contracts should be in your universe, call the - - SetFilter - - - set_filter - - method of the - - IndexOption - - object. -

    -

    - The - - AddIndexOption - - - add_index_option - - method provides a daily stream of Option chain data. To get the most recent daily chain, call the - - OptionChain - - - option_chain - - method with the canonical Index Option Symbol. The - - OptionChain - - - option_chain - - method returns data on all the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    class IndexOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2021, 1, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(1_000_000)
    -        self.universe_settings.asynchronous = True
    -        self.index_symbol = self.add_index('VIX').symbol
    -        
    -        standard_option = self.add_index_option(self.index_symbol)
    -        standard_option.set_filter(self._option_filter)
    -        self.standard_option_symbol = standard_option.symbol
    -        standard_chain = self.option_chain(standard_option.symbol, flatten=True).data_frame
    -
    -        weekly_option = self.add_index_option(self.index_symbol, "VIXW")
    -        weekly_option.set_filter(self._option_filter)
    -        self.weekly_option_symbol = weekly_option.symbol
    -        weekly_chain = self.option_chain(weekly_option.symbol, flatten=True).data_frame
    -        weekly_chain = weekly_chain[
    -            weekly_chain.index.map(lambda symbol: not IndexOptionSymbol.is_standard(symbol))
    -        ]
    -        
    -
    -    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Contracts can be filtered by greeks, implied volatility, open interest:
    -        return universe \
    -            .delta(0.5, 1.5) \
    -            .gamma(0.0001, 0.0006) \
    -            .vega(0.01, 1.5) \
    -            .theta(-2.0, -0.5) \
    -            .rho(0.5, 3.0) \
    -            .implied_volatility(1, 3) \
    -            .open_interest(100,500)
    -
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _indexSymbol, _standardOptionSymbol, _weeklyOptionSymbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2021, 1, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        _indexSymbol = AddIndex("VIX").Symbol;
    -
    -        var standardOption = AddIndexOption(_indexSymbol);
    -        standardOption.SetFilter(OptionFilter);
    -        _standardOptionSymbol = standardOption.Symbol;
    -        var standardChain = OptionChain(_standardOptionSymbol);
    -
    -        var weeklyOption = AddIndexOption(_indexSymbol, "VIXW");
    -        weeklyOption.SetFilter(OptionFilter);
    -        _weeklyOptionSymbol = weeklyOption.Symbol;
    -        var weeklyChain = OptionChain(_weeklyOptionSymbol)
    -            .Where(contract => !IndexOptionSymbol.IsStandard(contract.Symbol));
    -    }
    -
    -    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    -    {
    -        // Contracts can be filtered by greeks, implied volatility, open interest:
    -        return universe
    -            .Delta(0.5m, 1.5m)
    -            .Gamma(0.0001m, 0.0006m)
    -            .Vega(0.01m, 1.5m)
    -            .Theta(-2.0m, -0.5m)
    -            .Rho(0.5m, 3.0m)
    -            .ImpliedVolatility(1.0m, 3.0m)
    -            .OpenInterest(100, 500);
    -    }
    -}
    -
    -

    - The Index resolution must be less than or equal to the Index Option resolution. For example, if you set the Index resolution to minute, then you must set the Index Option resolution to minute, hour, or daily. -

    -

    - For more information about creating US Index Option subscriptions, see - - Index Options - - . -

    - - - -

    Accessing Data

    - - -

    - For information about accessing US Equity Options data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Index Options data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Index Options Universe data in an algorithm, call the - - History<OptionUniverse> - - - history - - method with the canonical Index Option - - Symbol - - . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.standard_option_symbol, timedelta(3))
    -
    -# OptionUniverse objects
    -history = self.history[OptionUniverse](self.standard_option_symbol, timedelta(3))
    -
    // OptionUniverse objects 
    -var history = History<OptionUniverse>(_standardOptionSymbol, TimeSpan.FromDays(3)).ToList();
    -
    -

    - For more information about Index Options Universe data in algorithms, see - - Historical Data - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Index Options Universe data in the Research Environment, call the - - History<OptionUniverse> - - - history - - method with the canonical Option - - Symbol - - . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. -

    -
    -
    qb = QuantBook()
    -index_symbol = qb.add_index('VIX').symbol
    -option = qb.add_index_option(index_symbol) # or qb.add_index_option(index_symbol, "VIXW")
    -history = qb.history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    -
    var qb = new QuantBook();
    -var indexSymbol = qb.AddIndex("VIX").Symbol;
    -var option = qb.AddIndexOption(indexSymbol); // or qb.AddIndexOption(indexSymbol, "VIXW");
    -var history = qb.History<OptionUniverse>(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 6));
    -foreach (var chain in history)
    -{
    -    var endTime = chain.EndTime;
    -    var filteredContracts = chain.Data
    -        .Select(contract => contract as OptionUniverse)
    -        .Where(contract => contract.Greeks.Delta > 0.3m);
    -    foreach (var contract in filteredContracts)
    -    {
    -        var price = contract.Price;
    -        var iv = contract.ImpliedVolatility;
    -    }
    -}
    -
    -

    - For more information about historical Index Options Universe data in the Research Environment, see - - Universes - - . -

    - - - -

    Supported Assets

    - - -

    - The following table shows the available Index Options: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Underlying Index - - Underlying Ticker - - Target Ticker - - Standard Contracts - - Weekly Contracts - - Tradable on Expiry Day -
    - NASDAQ-100 - - NDX - - - green check - - -
    - NASDAQ-100 - - NDX - - NDXP - - green check - - - green check -
    - NASDAQ-100 - - NDX - - NQX - - green check - - green check - - green check -
    - Russell 2000 - - RUT - - - green check - - -
    - Russell 2000 - - RUT - - RUTW - - - green check - - green check -
    - S&P500 - - SPX - - - green check - - -
    - S&P500 - - SPX - - SPXW - - - green check - - green check -
    - S&P500 - - VIX - - - green check - - -
    - S&P500 - - VIX - - VIXW - - - green check - -
    -

    - For more information about each underlying Index, see - - Supported Indices - - . -

    - - - -

    Example Applications

    - - -

    - The US Index Options Universe dataset enables you to accurately design strategies for Index Options. Examples include the following strategies: -

    -
      -
    • - Buying VIX call Options to hedge against upcoming volatility -
    • -
    • - Buying VIX put Options to capture the natural downward price movement in the VIX index -
    • -
    • - Buying SPX put Options to protect against downward price movement in the S&P 500 -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm subscribes to SPX put options that fall within delta range between -1 and -0.95, open interest range between 10 and 1000, and expire within seven days. Within this Option chain, the algorithm holds the put Option contract that has the minimum delta (closest to -1) during market hour to hedge the underlying intra-day movement completely. It avoid volatility from sentiment and only earns from inter-day movement from longer-term factors. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. -

    -
    -
    from AlgorithmImports import *
    -
    -class IndexOptionsUniverseAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(10000000)
    -
    -        # Asynchronous can use computational resources efficiently
    -        self.universe_settings.asynchronous = True
    -        # Subscribe to the underlying for the underlying position
    -        # Set the data normalization mode to raw for strike price comparability
    -        self.index = self.add_index("SPX").symbol
    -        # Requesting option data and filter for the hedge candidates
    -        option = self.add_index_option(self.index)
    -        option.set_filter(self.option_filter)
    -        self.option_symbol = option.symbol
    -
    -        # Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    -        self.schedule.on(
    -            self.date_rules.every_day(self.index),
    -            self.time_rules.after_market_open(self.index, 1),
    -            self.buy_hedge_contract
    -        )
    -
    -        # Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    -        # Leave 2 minutes contingency to fill
    -        self.schedule.on(
    -            self.date_rules.every_day(self.index),
    -            self.time_rules.before_market_close(self.index, 2),
    -            self.sell_hedge_contract
    -        )
    -
    -        self.hedge = None
    -        
    -    def option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Select the contracts with delta very close to -1 and high open interest
    -        # This can effectively hedge most of the price change of the underlying and ensure the liquidity
    -        # Make sure the contract is expiring close for its tradbility
    -        return universe.puts_only().expiration(2, 7).delta(-1, -0.95).open_interest(10, 1000)
    -
    -    def buy_hedge_contract(self) -> None:
    -        chain = self.current_slice.option_chains.get(self.option_symbol)
    -        if chain:
    -            # Order the underlying if not hold, the order size should match the option contract
    -            # Order only if option chain data ready for hedging
    -            if not self.portfolio[self.index].invested:
    -                self.market_order(self.index, self.securities[self.option_symbol].symbol_properties.contract_multiplier)
    -
    -            # Get the contract with delta closest to -1 (lowest possible delta)
    -            contract = sorted(chain, key=lambda x: x.greeks.delta)[0]
    -            self.hedge = contract.symbol
    -            # Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    -            self.market_order(self.hedge, 1)
    -        
    -    def sell_hedge_contract(self) -> None:
    -        # Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    -        if self.hedge:
    -            self.liquidate(self.hedge)
    -            self.hedge = None
    -
    public class IndexOptionsUniverseAlgorithm : QCAlgorithm
    -{
    -    private Symbol _index, _optionSymbol, _hedge;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(10000000);
    -        // Asynchronous can use computational resources efficiently
    -        UniverseSettings.Asynchronous = true;
    -
    -        // Subscribe to the underlying for the underlying position
    -        // Set the data normalization mode to raw for strike price comparability
    -        _index = AddIndex("SPX").Symbol;
    -        // Requesting option data and filter for the hedge candidates
    -        var option = AddIndexOption(_index);
    -        _optionSymbol = option.Symbol;
    -        option.SetFilter(OptionFilter);
    -
    -        // Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    -        Schedule.On(
    -            DateRules.EveryDay(_index),
    -            TimeRules.AfterMarketOpen(_index, 1),
    -            BuyHedgeContract
    -        );
    -
    -        // Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    -        // Leave 2 minutes contingency to fill
    -        Schedule.On(
    -            DateRules.EveryDay(_index),
    -            TimeRules.BeforeMarketClose(_index, 2),
    -            SellHedgeContract
    -        );
    -    }
    -
    -    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    -    {
    -        // Select the contracts with delta very close to -1 and high open interest
    -        // This can effectively hedge most of the price change of the underlying and ensure the liquidity
    -        // Make sure the contract is expiring close for its tradbility
    -        return universe
    -            .PutsOnly()
    -            .Expiration(2, 7)
    -            .Delta(-1m, -0.95m)
    -            .OpenInterest(10, 1000);
    -    }
    -
    -    private void BuyHedgeContract()
    -    {
    -        if (CurrentSlice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    -        {
    -            // Order the underlying if not hold, the order size should match the option contract
    -            // Order only if option chain data ready for hedging
    -            if (!Portfolio[_index].Invested)
    -            {
    -                MarketOrder(_index, Securities[_optionSymbol].SymbolProperties.ContractMultiplier);
    -            }
    -
    -            // Get the contract with delta closest to -1 (lowest possible delta)
    -            var contract = chain.MinBy(x => x.Greeks.Delta);
    -            _hedge = contract.Symbol;
    -            // Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    -            MarketOrder(_hedge, 1);
    -        }
    -    }
    -
    -    private void SellHedgeContract()
    -    {
    -        // Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    -        if (_hedge != null)
    -        {
    -            Liquidate(_hedge);
    -            _hedge = null;
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm demonstrating a Gamma Scalping strategy through framework algorithm. It filters SPX options with expiration between 30 to 90 days and open interest between 50 and 1000, due to liquidity concern and lower Gamma fluctuation. Assuming a significant upward trend is expecting, it orders a long straddle strategy from the strike price with Delta-neutral and the highest Gamma to earn the highest profit from upward underlying movement. -

    -
    -
    from AlgorithmImports import *
    -
    -class IndexOptionsUniverseFrameworkAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 12, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(1000000)
    -        # Asynchronous can use computational resources efficiently
    -        self.universe_settings.asynchronous = True
    -
    -        # Universe selection that select based on liquidity of the option contracts (by open interest)
    -        self.add_universe_selection(IndexOptionsUniverseSelectionModel())
    -        # Custom alpha model that use Delta and Gamma to signal insights
    -        self.add_alpha(OptionDeltaGammaAlphaModel())
    -        # To maintain long-short size equal, use a PCM that order a single contract
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -
    -class IndexOptionsUniverseSelectionModel(OptionUniverseSelectionModel):
    -    def __init__(self) -> None:
    -        # Daily update with the select_option_chain_symbols function
    -        super().__init__(timedelta(1), self.select_option_chain_symbols)
    -
    -    def select_option_chain_symbols(self, dt: datetime) -> List[Symbol]:
    -        # Select only SPX options as our focus, which is a highly traded volatile index with great upward momentum
    -        return [Symbol.create("SPX", SecurityType.INDEX_OPTION, Market.USA)]
    -
    -    def filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    -        # A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    -        return universe.expiration(30, 90).open_interest(50, 1000)
    -
    -class OptionDeltaGammaAlphaModel(AlphaModel):
    -    def __init__(self) -> None:
    -        # A day count variable to control the alpha model only trade once a day
    -        self._day = -1
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        insights = []
    -
    -        if self._day != slice.time.day:
    -            # We open position for each option underlying as separate bet
    -            for _, chain in slice.option_chains.items():
    -                # For theta-neutral, select the same expiry for both call and put
    -                expiry = min(x.expiry for x in chain)
    -                contracts = [x for x in chain if x.expiry == expiry]
    -
    -                # Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    -                delta_gamma_symbols = []
    -                strikes = set(x.strike for x in contracts if len([y for y in contracts if y.strike == x.strike]) == 2)
    -                for strike in strikes:
    -                    # Get both call and put for their aggregated delta and gamma
    -                    call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == strike, contracts))
    -                    put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == strike, contracts))
    -                    delta_gamma_symbols.append((call.greeks.delta + put.greeks.delta, call.greeks.gamma + put.greeks.gamma, call.symbol, put.symbol))
    -                
    -                if len(delta_gamma_symbols) == 0:
    -                    continue
    -
    -                # We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    -                # Less than 2d.p. difference is non-significant, which we can risk for better reward
    -                # Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    -                # Make sure the aggregated gamma to be positive to bet on large uptrend
    -                # So it will earn more when the price really go up higher and higher, but locally immune for small noise
    -                filtered = [item for item in delta_gamma_symbols if round(item[0], 2) <= 0.01 and item[1] > 0]
    -                if len(filtered) == 0:
    -                    continue
    -                selected = sorted(filtered, key=lambda x: x[1])[0]
    -
    -                # Provide trade signal and roll the day count to let the position stay for the whole day
    -                selected_call = selected[2]
    -                selected_put = selected[3]
    -                insights.extend([
    -                    Insight.price(selected_call, Expiry.END_OF_DAY, InsightDirection.UP),
    -                    Insight.price(selected_put, Expiry.END_OF_DAY, InsightDirection.UP)
    -                ])
    -                self._day = slice.time.day
    -        
    -        return insights
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                # Use a whole number target to order the exact number of share for size-matching
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class IndexOptionsUniverseFrameworkAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 12, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -        // Asynchronous can use computational resources efficiently
    -        UniverseSettings.Asynchronous = true;
    -
    -        // Universe selection that select based on liquidity of the option contracts (by open interest)
    -        AddUniverseSelection(new IndexOptionsUniverseSelectionModel());
    -        // Custom alpha model that use Delta and Gamma to signal insights
    -        AddAlpha(new OptionDeltaGammaAlphaModel());
    -        // To maintain long-short size equal, use a PCM that order a single contract
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}       
    -    
    -class IndexOptionsUniverseSelectionModel : OptionUniverseSelectionModel
    -{
    -    // Daily update with the SelectOptionChainSymbols function
    -    public IndexOptionsUniverseSelectionModel()
    -            : base(TimeSpan.FromDays(1), SelectOptionChainSymbols) {}
    -    
    -    private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
    -    {
    -        // Select only SPX options as our focus, which is a highly traded volatile index with great upward momentum
    -        return new[] {QuantConnect.Symbol.Create("SPX", SecurityType.IndexOption, Market.USA)};
    -    }
    -
    -    protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
    -    {
    -        // To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    -        // A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    -        return filter
    -            .Expiration(30, 90)
    -            .OpenInterest(50, 1000);
    -    }
    -}
    -    
    -class OptionDeltaGammaAlphaModel : AlphaModel
    -{
    -    // A day count variable to control the alpha model only trade once a day
    -    private int _day = -1;
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -        
    -        if (_day != slice.Time.Day)
    -        {
    -            // We open position for each option underlying as separate bet
    -            foreach (var kvp in slice.OptionChains)
    -            {
    -                var chain = kvp.Value;
    -
    -                // For theta-neutral, select the same expiry for both call and put
    -                var expiry = chain.Min(x => x.Expiry);
    -                var contracts = chain.Where(x => x.Expiry == expiry).ToList();
    -
    -                // Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    -                var deltaGammaSymbols = new List<(decimal, decimal, Symbol, Symbol)>();
    -                var strikes = contracts.Select(x => x.Strike)
    -                    .Where(x => contracts.Count(y => y.Strike == x) == 2)
    -                    .Distinct();
    -                foreach (var strike in strikes)
    -                {
    -                    // Get both call and put for their aggregated delta and gamma
    -                    var call = contracts.Single(x => x.Right == OptionRight.Call && x.Strike == strike);
    -                    var put = contracts.Single(x => x.Right == OptionRight.Put && x.Strike == strike);
    -                    deltaGammaSymbols.Add((call.Greeks.Delta + put.Greeks.Delta, call.Greeks.Gamma + put.Greeks.Gamma, call.Symbol, put.Symbol));
    -                }
    -
    -                if (deltaGammaSymbols.Count == 0)
    -                {
    -                    continue;
    -                }
    -
    -                // We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    -                // Less than 2d.p. difference is non-significant, which we can risk for better reward
    -                // Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    -                // Make sure the aggregated gamma to be positive to bet on large uptrend
    -                // So it will earn more when the price really go up higher and higher, but locally immune for small noise
    -                var filtered = deltaGammaSymbols.Where(item => Math.Round(item.Item1, 2) <= 0.01m && item.Item2 > 0).ToList();
    -                if (filtered.Count == 0)
    -                {
    -                    continue;
    -                }
    -                var selected = filtered.OrderByDescending(item => item.Item2).First();
    -
    -                // Provide trade signal and roll the day count to let the position stay for the whole day
    -                var selectedCall = selected.Item3;
    -                var selectedPut = selected.Item4;
    -                insights.AddRange(new[] {
    -                    Insight.Price(selectedCall, Expiry.EndOfDay, InsightDirection.Up),
    -                    Insight.Price(selectedPut, Expiry.EndOfDay, InsightDirection.Up)
    -                });
    -                _day = slice.Time.Day;
    -            }
    -        }
    -
    -        return insights;
    -    }
    -}
    -    
    -class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        var targets = new List<PortfolioTarget>();
    -        foreach (var insight in insights)
    -        {
    -            if (algorithm.Securities[insight.Symbol].IsTradable)
    -            {
    -                // Use a whole number target to order the exact number of share for size-matching
    -                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -            }
    -        }
    -        return targets;
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Index Options Universe dataset provides - - OptionFilterUniverse - - , - - OptionUniverse - - , and - - OptionChain - - objects. -

    -

    - OptionFilterUniverse Attributes -

    -

    - - OptionFilterUniverse - - objects have the following attributes: -

    -
    -
    -

    - OptionUniverse Attributes -

    -

    - - OptionUniverse - - objects have the following attributes: -

    -
    -
    -

    - OptionChain Attributes -

    -

    - - OptionChain - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    Datasets

    -

    AlgoSeek

    -
    -
    - - -
    -
    -

    - AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit - - algoseek.com - - . -

    -
    - -
    - - - -

     

    - -
    -
    -

    AlgoSeek

    -

    US Equities

    -
    -
    -

    Introduction

    - - -

    - The US Equities dataset by AlgoSeek is survivorship bias-free daily coverage of every stock traded in the US Securities Information Processors (SIP) CTA/UTP feed since 1998. The dataset covers approximately 27,500 securities, starts in January 1998, and is delivered in any resolution from tick to daily. The Data is collected from the full SIP feed via our Equinix co-located servers, including all trades and quotes published to every exchange as well as FINRA. Over-the-Counter (OTC) trades are not included. -

    -

    - This dataset depends on the - - US Equity Security Master - - dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. -

    -

    - For more information about the US Equities dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit - - algoseek.com - - . -

    - - - -

    Getting Started

    - - -

    - AlgoSeek is the default US Equities dataset on QuantConnect. The following snippet demonstrates how to request data from the US Equities dataset: -

    -
    -
    self.aapl = self.add_equity("AAPL", Resolution.DAILY).symbol
    -
    _aapl = AddEquity("AAPL", Resolution.Daily).Symbol;
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 1998 -
    - Asset Coverage - - 27,500 US Equities -
    - Data Density - - Dense -
    - Resolution - - Tick, Second, Minute, Hourly, & Daily -
    - Timezone - - New York -
    - Market Hours - - - Regular and Extended - -
    - - - -

    Requesting Data

    - - -

    - To add US Equities data to your algorithm, call the - - AddEquity - - - add_equity - - method. Save a reference to the Equity - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class USEquityDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2018, 1, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000) 
    -        # Subscribe to AAPL data
    -        self.aapl = self.add_equity("AAPL", Resolution.MINUTE).symbol
    -
    public class USEquityDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol; 
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2018, 1, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        // Subscribe to AAPL data
    -        _symbol = AddEquity("AAPL", Resolution.Minute).Symbol;
    -    }
    -}
    -
    -

    - For more information about creating US Equity subscriptions, see - - Requesting Data - - or - - US Equity Universes - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current US Equities data, index the - - Bars - - - bars - - , - - QuoteBars - - - quote_bars - - , or - - Ticks - - - ticks - - properties of the current - - - Slice - - - with the Equity - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Access data: TradeBar data
    -    if self.aapl in slice.bars:
    -        trade_bar = slice.bars[self.aapl]
    -        self.log(f"{self.aapl} close at {slice.time}: {trade_bar.close}")
    -
    -    # Access data: QuoteBar data
    -    if self.aapl in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.aapl]
    -        self.log(f"{self.aapl} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    # Access data: Ticks data
    -    if self.aapl in slice.ticks:
    -        ticks = slice.ticks[self.aapl]
    -        for tick in ticks:
    -            self.log(f"{self.aapl} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    // Access data: TradeBar data
    -    if (slice.Bars.ContainsKey(_symbol))
    -    {
    -        var tradeBar = slice.Bars[_symbol];
    -        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    // Access data: QuoteBar data
    -    if (slice.QuoteBars.ContainsKey(_symbol))
    -    {
    -        var quoteBar = slice.QuoteBars[_symbol];
    -        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    // Access data: Ticks data
    -    if (slice.Ticks.ContainsKey(_symbol))
    -    {
    -        var ticks = slice.Ticks[_symbol];
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - You can also iterate through all of the data objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Iterate all TradeBar received
    -    for symbol, trade_bar in slice.bars.items():
    -        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    -
    -    # Iterate all QuoteBar received
    -    for symbol, quote_bar in slice.quote_bars.items():
    -        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    # Iterate all Ticks received
    -    for symbol, ticks in slice.ticks.items():
    -        for tick in ticks:
    -            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    // Iterate all TradeBar received
    -    foreach (var kvp in slice.Bars)
    -    {
    -        var symbol = kvp.Key;
    -        var tradeBar = kvp.Value;
    -        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    // Iterate all QuoteBar received
    -    foreach (var kvp in slice.QuoteBars)
    -    {
    -        var symbol = kvp.Key;
    -        var quoteBar = kvp.Value;
    -        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    // Iterate all Ticks received
    -    foreach (var kvp in slice.Ticks)
    -    {
    -        var symbol = kvp.Key;
    -        var ticks = kvp.Value;
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - For more information about accessing US Equities data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - To get historical US Equity data, call the - - History - - - history - - method with the Equity - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.aapl, 100, Resolution.DAILY)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](self.aapl, 100, Resolution.DAILY)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.aapl, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -history_ticks = self.history[Tick](self.aapl, timedelta(seconds=10), Resolution.TICK)
    -
    // TradeBar objects 
    -var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    -
    -// Tick objects 
    -var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Universe Selection

    - - -

    - To select a universe of US Equities, see - - Equity Universes - - . -

    - - - -

    Remove Subscriptions

    - - -

    - To unsubscribe from a US Equity that you added with the - - AddEquity - - - add_equity - - method, call the - - RemoveSecurity - - - remove_security - - method. -

    -
    -
    self.remove_security(self.aapl)
    -
    RemoveSecurity(_symbol);
    -
    -

    - The - - RemoveSecurity - - - remove_security - - method cancels your open orders for the security and liquidates your holdings. -

    - - - -

    Supported Assets

    - - -

    - To view the supported assets in the US Equities dataset, see the - - Data Explorer - - . This dataset doesn't include Over-the-Counter (OTC) stocks. -

    - - - -

    Example Applications

    - - -

    - The US Equities dataset enables you to accurately design Equity trading strategies. Examples include the following strategies: -

    -
      -
    • - Momentum strategies using historical returns on the premise that the momentum will continue -
    • -
    • - Value strategies using fundamental factors on the premise that the price of undervalued securities will rise -
    • -
    • - Factor investing with periodic rebalancing -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm buys and holds Apple stock: -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class USEquityDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        
    -        # Requesting single equity data, since we only trade AAPL
    -        self.aapl = self.add_equity("AAPL", Resolution.DAILY).symbol
    -        
    -        # Historical data
    -        history = self.history(self.aapl, 60, Resolution.DAILY)
    -        self.debug(f"We got {len(history)} items from our history request")
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Check if the current slice containing AAPL and if we hold any position
    -        # As we make use of the most updated price data to decide the order size
    -        if slice.contains_key(self.aapl) and slice[self.aapl] is not None and not self.portfolio.invested:
    -            self.set_holdings(self.aapl, 1)
    -
    public class USEquityDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -
    -        // Requesting single equity data, since we only trade AAPL
    -        _symbol = AddEquity("AAPL", Resolution.Daily).Symbol;
    -        
    -        // Historical data
    -        var history = History(_symbol, 60, Resolution.Daily);
    -        Debug($"We got {history.Count()} items from our history request");
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Check if the current slice containing AAPL and if we hold any position
    -        // As we make use of the most updated price data to decide the order size
    -        if (slice.ContainsKey(_symbol) && slice[_symbol] != null && !Portfolio.Invested)
    -        {
    -            SetHoldings(_symbol, 1);
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm buys and holds Apple stock: -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class USEquityDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        
    -        self.universe_settings.resolution = Resolution.DAILY
    -        # To select only AAPL, use a manual selection universe
    -        symbols = [Symbol.create("AAPL", SecurityType.EQUITY, Market.USA)]
    -        self.add_universe_selection(ManualUniverseSelectionModel(symbols))    
    -        
    -        # Constant investment signal
    -        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(days=7), 0.025, None))
    -        
    -        # Invest in all members equally
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -
    public class USEquityDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        
    -        UniverseSettings.Resolution = Resolution.Daily;
    -        // To select only AAPL, use a manual selection universe
    -        var symbols = new[] {QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)};
    -        AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
    -        
    -        // Constant investment signal
    -        AddAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(7), 0.025, null));
    -
    -        // Invest in all members equally
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Equities dataset provides - - TradeBar - - , - - QuoteBar - - , and - - Tick - - objects. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - Tick Attributes -

    -

    - - Tick - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    AlgoSeek

    -

    US Equity Options

    -
    -
    -

    Introduction

    - - -

    - The US Equity Options data by AlgoSeek provides Option data, including prices, strikes, expires, and open interest. The data covers 4,000 Symbols, starts in January 2012, and is delivered on a minute frequency. This dataset is created by monitoring Options Price Reporting Authority (OPRA) data feed, which consolidates last sale and quotation information originating from the national securities exchanges that have been approved by the Securities and Exchange Commission. -

    -

    - This dataset depends on the following datasets: -

    - -

    - For more information about the US Equity Options dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - - AlgoSeek - - was in 2014 with the goal of providing the highest quality, most accurate, ready-to-use data in the financial data industry. AlgoSeek provides access to Equities, ETFs, ETNs, Equity Indices, Equity Options, Futures, and Future Options for quantitative firms and traders. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Equity Options dataset: -

    -
    -
    option = self.add_option("GOOG")
    -self.option_symbol = option.symbol
    -option.set_filter(-2, +2, 0, 180)
    -
    var option = AddOption("GOOG");
    -_optionSymbol = option.Symbol;
    -option.SetFilter(-2, +2, 0, 180);
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2012* -
    - Asset Coverage - - 4,000 Symbols -
    - Data Density - - Dense -
    - Resolution - - Minute, Hourly, & Daily -
    - Timezone - - New York -
    - Market Hours - - - Regular Only - -
    -

    - * Some data is available before this date. In 2012, AlgoSeek started to fetch data from 48 OPRA channels instead of 24, increasing the quality of the data. -

    - - - -

    Requesting Data

    - - -

    - To add US Equity Options data to your algorithm, call the - - AddOption - - - add_option - - method. Save a reference to the Equity Option - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class USEquityOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        # Request GOOG option data
    -        option = self.add_option("GOOG")
    -        self.option_symbol = option.symbol
    -        # Set our strike/expiry filter for this option chain
    -        option.set_filter(-2, +2, 0, 180)
    -
    -
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _optionSymbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        // Request GOOG option data
    -        var option = AddOption("GOOG");
    -        _optionSymbol = option.Symbol;
    -        // Set our strike/expiry filter for this option chain
    -        option.SetFilter(-2, +2, 0, 180);
    -    }
    -}
    -
    -

    - The Equity resolution must be less than or equal to the Equity Option resolution. For example, if you set the Equity resolution to minute, then you must set the Equity Option resolution to minute, hour, or daily. -

    -

    - For more information about creating US Equity Option subscriptions, see - - Requesting Data - - or - - Equity Options Universes - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current US Equity Options data, index the - - OptionChains - - - option_chains - - property of the current - - - Slice - - - with the canonical Equity Option - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your Index Option at every time step. To avoid issues, call the - - Get - - - get - - method. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Get the wanted option chain with the canonical symbol
    -    chain = slice.option_chains.get(self.option_symbol)
    -    if chain:
    -        # Iterate the option contracts in chain
    -        for contract in chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    -
    public override void OnData(Slice slice)
    -{
    -    // Get the wanted option chain with the canonical symbol
    -    if (slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    -    {
    -        // Iterate the option contracts in chain
    -        foreach (var contract in chain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - You can also iterate through all of the - - OptionChain - - objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Iterate all option chains of all symbols
    -    for canonical_symbol, chain in slice.option_chains.items():
    -        # Iterate the option contracts in chain
    -        for contract in chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    -
    public override void OnData(Slice slice)
    -{
    -    // Iterate all option chains of all symbols
    -    foreach (var kvp in slice.OptionChains)
    -    {
    -        var canonicalSymbol = kvp.Key;
    -        var chain = kvp.Value;
    -        // Iterate the option contracts in chain
    -        foreach (var contract in chain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - For more information about accessing US Equity Options data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Equity Options data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Equity Options data in an algorithm, call the - - History - - - history - - method with the Equity Option contract - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame of trade and quote data
    -history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    -
    -# DataFrame of open interest data
    -history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    -
    -# OpenInterest objects
    -history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
    -
    // TradeBar objects 
    -var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    -
    -// OpenInterest objects
    -var historyOpenInterest = History<OpenInterest>(contract.Symbol, 100, Resolution.Minute);
    -
    -

    - For more information about historical data in algorithms, see - - History Requests - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Equity Options data in the Research Environment, call the - - History - - - history - - or - - OptionHistory - - - option_history - - method. The - - History - - - history - - method returns the price, volume, and open interest history for some given Option contract(s). The - - OptionHistory - - - option_history - - method returns the price and volume history for the contracts that pass your daily universe filter. -

    -
    -
    qb = QuantBook()
    -option = qb.add_option("GOOG") 
    -option.set_filter(-2, 2, 0, 90)
    -history = qb.option_history(option.symbol.underlying, datetime(2020, 6, 1), datetime(2020, 6, 5))
    -history_df = history.data_frame
    -expiries = history.get_expiry_dates() 
    -strikes = history.get_strikes()
    -
    var qb = new QuantBook();
    -var option = qb.AddOption("GOOG");
    -option.SetFilter(-2, 2, 0, 90);
    -var history = qb.OptionHistory(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    -
    -var contracts = history
    -    .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys))
    -    .Distinct().ToList();
    -var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    -var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
    -
    -

    - To get historical data for arbitrary US Equity Option contracts instead of just the that pass your universe filter, call the - - History - - - history - - method like you would in an algorithm, but on the - - QuantBook - - object. For more information about historical data in the Research Environment, see - - Key Concepts - - . -

    -

    - Historical Greeks and IV Data -

    -

    - To get historical data for the Greeks and implied volatility of Equity Options, see the - - US Equity Option Universe - - dataset. -

    - - - -

    Supported Assets

    - - -

    - To view the supported assets in the US Equity Options dataset, see the - - Data Explorer - - . -

    - - - -

    Example Applications

    - - -

    - The US Equity Options dataset enables you to accurately design Option strategies. Examples include the following strategies: -

    -
      -
    • - Buying put Options to hedge against downward price movement in positive Equity positions -
    • -
    • - Exploiting arbitrage opportunities that arise when the price of Option contracts deviates from their theoretical value -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm subscribes to Google Options that fall within two strikes of the underlying stock price and expire within seven days. Within this Option chain, the algorithm buys the call Option contract that has the furthest expiry and has its strike price closest to the underlying stock price. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. -

    -
    -
    from AlgorithmImports import *
    -
    -class USEquityOptionsDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        # Requesting data
    -        self.underlying = self.add_equity("GOOG").symbol
    -        option = self.add_option("GOOG")
    -        self.option_symbol = option.symbol
    -        # To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    -        # -2/+2 strike buffer is given for small price change
    -        option.set_filter(lambda u: u.calls_only().strikes(-2, +2).expiration(0, 6))
    -        
    -        self.contract = None
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # If the Option contract is exercised, close the underlying position.
    -        if self.portfolio[self.underlying].invested:
    -            self.liquidate(self.underlying)
    -        # If the Option contract expires, rollover to the next contract.
    -        if self.contract and not self.portfolio[self.contract.symbol].invested:
    -            self.contract = None
    -        # Select with the lastest option chain data only
    -        chain = slice.option_chains.get(self.option_symbol)
    -        if not self.contract and chain:
    -            # Select the call contracts with the furthest expiration (week end)
    -            furthest_expiry = max([c.expiry for c in chain])
    -            furthest_expiry_calls = [contract for contract in chain if contract.expiry == furthest_expiry]
    -            # Get the ATM call for speculate trade with low cost and limited loss
    -            self.contract = sorted(furthest_expiry_calls, key = lambda x: abs(chain.underlying.price - x.strike))[0]
    -            self.market_order(self.contract.symbol, 1)
    -            
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            # Historical data
    -            history = self.history(security.symbol, 10, Resolution.MINUTE)
    -            self.debug(f"We got {len(history)} from our history request for {security.symbol}")
    -
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _underlying, _optionSymbol;
    -    private OptionContract? _contract = null;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        // Requesting data
    -        _underlying = AddEquity("GOOG").Symbol;
    -        var option = AddOption("GOOG");
    -        _optionSymbol = option.Symbol;
    -        // To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    -        // -2/+2 strike buffer is given for small price change
    -        option.SetFilter((u) => u.CallsOnly().Strikes(-2, +2).Expiration(0, 7));
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // If the Option contract is exercised, close the underlying position.
    -        if (Portfolio[_underlying].Invested)
    -        {
    -            Liquidate(_underlying);
    -        }
    -        // If the Option contract expires, rollover to the next contract.
    -        if (_contract != null && !Portfolio[_contract.Symbol].Invested)
    -        {
    -            _contract = null;
    -        }
    -        // Select with the lastest option chain data only
    -        if (_contract == null && slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    -        {
    -            // Select the call contracts with the furthest expiration (week end)
    -            var furthestExpiry = chain.Max(c => c.Expiry);
    -            var furthestExpiryCalls = chain.Where(c => c.Expiry == furthestExpiry);
    -            // Get the ATM call for speculate trade with low cost and limited loss
    -            _contract = furthestExpiryCalls.OrderByDescending(x => Math.Abs(chain.Underlying.Price - x.Strike)).Last();
    -            MarketOrder(_contract.Symbol, 1);
    -        }
    -    }
    -    
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            // Historical data
    -            var history = History(security.Symbol, 100, Resolution.Minute);
    -            Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm buys a call Option contract for Google that falls within one strike of the underlying stock price and expires within seven days. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. -

    -
    -
    from AlgorithmImports import *
    -
    -class USEquityOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        # Requesting data
    -        self.set_universe_selection(EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel())
    -        
    -        self.set_alpha(ConstantOptionsAlphaModel())
    -
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -        
    -        
    -class EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel(OptionUniverseSelectionModel):
    -
    -    def __init__(self) -> None:
    -        # Daily update with the select_option_chain_symbols function
    -        super().__init__(timedelta(1), self.select_option_chain_symbols)
    -
    -    def select_option_chain_symbols(self, utcTime: datetime) -> List[Symbol]:
    -        # Always select only GOOG options as our focus
    -        return [ Symbol.create("GOOG", SecurityType.OPTION, Market.USA) ]
    -
    -    def filter(self, filter: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    -        # -1/+1 strike buffer is given for small price change
    -        return (filter.calls_only()
    -                      .strikes(-1, -1)
    -                      .expiration(0, 7))  
    -        
    -
    -class ConstantOptionsAlphaModel(AlphaModel):
    -
    -    underlying = None
    -    contract = None
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        
    -        insights = []
    -        
    -        # Liquidate the underlying if the option is being exercised/assigned
    -        if algorithm.portfolio[self.underlying].invested:
    -            insights.append(Insight.price(self.underlying, timedelta(days=7), InsightDirection.FLAT))
    -
    -        if self.contract is not None and algorithm.portfolio[self.contract.symbol].invested:
    -            return insights
    -
    -        # Get the ATM call for speculate trade with low cost and limited loss that expires at week end
    -        for kvp in slice.option_chains:
    -            chain = kvp.Value
    -            expiry = max(x.expiry for x in chain)
    -            self.contract = sorted([x for x in chain if x.expiry == expiry],
    -                                               key=lambda x: abs(x.strike - x.underlying_last_price))[0]
    -            insights.append(Insight.price(self.contract.symbol, self.contract.expiry + timedelta(days=1), InsightDirection.UP))
    -        
    -        return insights
    -        
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            if security.type == SecurityType.EQUITY:
    -                self.underlying = security.symbol
    -            else:
    -                # Historical data
    -                history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    -                algorithm.debug(f"We got {len(history)} from our history request for {security.symbol}")
    -
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    -{        
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        // Requesting data
    -        SetUniverseSelection(new EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel());
    -        
    -        SetAlpha(new ConstantOptionsAlphaModel());
    -        
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}   
    -    
    -class EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel : OptionUniverseSelectionModel
    -{
    -    // Daily update with the SelectOptionChainSymbols function
    -    public EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel()
    -            : base(TimeSpan.FromDays(1), SelectOptionChainSymbols) {}
    -    
    -    private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
    -    {
    -        // Select only GOOG options as our focus
    -        return new[] {QuantConnect.Symbol.Create("GOOG", SecurityType.Option, Market.USA)};
    -    }
    -
    -    protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
    -    {
    -        // To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    -        // -2/+2 strike buffer is given for small price change
    -        return filter.CallsOnly()
    -            .Strikes(-1, -1)
    -            .Expiration(0, 7);
    -    }
    -}
    -    
    -class ConstantOptionsAlphaModel : AlphaModel
    -{ 
    -    private Symbol? _underlying = null;
    -    private OptionContract? _contract = null;
    -    
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -        
    -        // Liquidate the underlying if the option is being exercised/assigned
    -        if (algorithm.Portfolio[_underlying].Invested)
    -        {
    -            insights.Add(Insight.Price(_underlying, TimeSpan.FromDays(7), InsightDirection.Flat));
    -        }
    -            
    -        if (_contract != null && algorithm.Portfolio[_contract.Symbol].Invested)
    -        {
    -            return insights;
    -        }
    -        
    -        // Get the ATM call for speculate trade with low cost and limited loss that expires at week end
    -        foreach (var kvp in slice.OptionChains)
    -        {
    -            var chain = kvp.Value;
    -            var expiry = chain.Max(x => x.Expiry);
    -            _contract = chain.Where(x => x.Expiry == expiry)
    -                .OrderBy(x => Math.Abs(x.Strike - x.UnderlyingLastPrice))
    -                .First();
    -            insights.Add(Insight.Price(_contract.Symbol, _contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Up));
    -        }    
    -        return insights;
    -    }
    -
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            if (security.Type == SecurityType.Equity)
    -            {
    -                _underlying = security.Symbol;
    -            }
    -            else {
    -                // Historical data
    -                var history = algorithm.History(security.Symbol, 100, Resolution.Minute);
    -                algorithm.Debug($"We got {history.Count()} from our history request for {security.Symbol}");    
    -            }
    -        }
    -    }
    -}
    -    
    -    
    -class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        var targets = new List<PortfolioTarget>();
    -        foreach (var insight in insights)
    -        {
    -            if (algorithm.Securities[insight.Symbol].IsTradable)
    -            {
    -                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -            }
    -        }
    -        return targets;
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Equity Options dataset provides - - TradeBar - - , - - QuoteBar - - , and - - OpenInterest - - objects. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - OpenInterest Attributes -

    -

    - - OpenInterest - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    AlgoSeek

    -

    US Future Options

    -
    -
    -

    Introduction

    - - -

    - The US Future Options dataset by AlgoSeek provides Option data on US Future contracts, including prices, strikes, and expires. The data covers 15 Monthly Future contracts, starts in January 2012, and is delivered on a minute frequency. This dataset is created by monitoring the trading activity on the CME, CBOT, NYMEX, and COMEX markets. -

    -

    - This dataset depends on the following datasets: -

    - -

    - For more information about the US Future Options dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering equities, futures, options, cash forex, and cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit - - algoseek.com - - . -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Future Options dataset: -

    -
    -
    future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    -future.set_filter(0, 90)
    -self.add_future_option(future.symbol, lambda universe: universe.strikes(-5, +5))
    -
    var future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    -future.SetFilter(0, 90);
    -AddFutureOption(future.Symbol, universe => universe.Strikes(-5, +5));
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2012 -
    - Asset Coverage - - 15 Monthly Future Contracts. Standard expires only*. -
    - Data Density - - Dense -
    - Resolution - - Minute, Hourly, & Daily -
    - Timezone - - New York -
    - Market Hours - - - Regular and Extended - -
    - * No weeklies or 0DTE contracts. - - - -

    Requesting Data

    - - -

    - To add US Future Options data to your algorithm, call the - - AddFutureOption - - - add_future_option - - method. -

    -
    -
    class FutureOptionDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 1, 28)
    -        self.set_end_date(2020, 6, 1)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    -        future.set_filter(0, 90)
    -        self.add_future_option(future.symbol, lambda universe: universe.strikes(-5, +5))
    -
    public class FutureOptionDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 1, 28);
    -        SetEndDate(2020, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        var future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    -        future.SetFilter(0, 90);
    -        AddFutureOption(future.Symbol, universe => universe.Strikes(-5, +5));
    -    }
    -}
    -
    -

    - The Future resolution must be less than or equal to the Future Option resolution. For example, if you set the Future resolution to minute, then the Future Option resolution must be minute, hour, or daily. -

    -

    - For more information about creating Future Options subscriptions, see - - Requesting Data - - or - - Future Options Universes - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current Future Options data, iterate through the - - OptionChains - - - option_chains - - property of the current - - - Slice - - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your Future Options at every time step. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for canonical_fop_symbol, chain in slice.option_chains.items():
    -        for contract in chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.OptionChains)
    -    {
    -        var canonicalFOPSymbol = kvp.Key;
    -        var chain = kvp.Value;
    -        foreach (var contract in chain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - You can also iterate through the - - FuturesChains - - - futures_chains - - in the current - - Slice - - first. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for continuous_future_symbol, futures_chain in slice.futures_chains.items():
    -        # Select a Future Contract and create its canonical FOP Symbol
    -        futures_contract = [contract for contract in futures_chain][0]
    -        canonical_fop_symbol = Symbol.create_canonical_option(futures_contract.symbol)
    -        option_chain = slice.option_chains.get(canonical_fop_symbol)
    -        if option_chain:
    -            for fop_contract in option_chain:
    -                 self.log(f"{fop_contract.symbol} price at {slice.time}: {fop_contract.last_price}")
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.FuturesChains)
    -    {
    -        var continuousContractSymbol = kvp.Key;
    -        var futuresChain = kvp.Value;
    -        
    -        // Select a Future Contract and create its canonical FOP Symbol
    -        var futuresContract = futuresChain.First();
    -        var canonicalFOPSymbol = QuantConnect.Symbol.CreateCanonicalOption(futuresContract.Symbol);
    -        if (slice.OptionChains.TryGetValue(canonicalFOPSymbol, out var optionChain))
    -        {
    -            foreach (var fopContract in optionChain)
    -            {
    -                Log($"{fopContract.Symbol} price at {slice.Time}: {fopContract.LastPrice}");
    -            }
    -        }
    -    }
    -}
    -
    -

    - For more information about accessing Future Options data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Future Options data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Future Options data in an algorithm, call the - - History - - - history - - method with the Future Option contract - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame of trade and quote data
    -history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    -
    -# DataFrame of open interest data
    -history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    -
    -# OpenInterest objects
    -history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
    -
    -
    // TradeBar objects 
    -var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    -
    -// OpenInterest objects 
    -var historyOpenInterest = History<OpenInterest >(contract.Symbol, 100, Resolution.Minute);
    -
    -

    - For more information about historical data in algorithms, see - - History Requests - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Future Options data in the Research Environment, call the - - History - - - history - - or - - OptionHistory - - - option_history - - method. The - - History - - - history - - method returns the price, volume, and open interest history for some given Future Option contract(s). The - - OptionHistory - - - option_history - - method returns the price and volume history for the contracts that pass your daily universe filter. -

    -
    -
    qb = QuantBook()
    -future = qb.add_future(Futures.Indices.SP_500_E_MINI)
    -start_date = datetime(2024, 1, 2)
    -future_contract_symbol = sorted(
    -    qb.future_chain_provider.get_future_contract_list(future.symbol, start_date), 
    -    key=lambda s: s.id.date
    -)[0]
    -history = qb.option_history(
    -    future_contract_symbol, start_date, future_contract_symbol.id.date, Resolution.HOUR
    -)
    -history_df = history.data_frame
    -expiries = history.get_expiry_dates()
    -strikes = history.get_strikes()
    -
    var qb = new QuantBook();
    -var future = qb.AddFuture(Futures.Indices.SP500EMini);
    -var startDate = new DateTime(2024, 1, 2);
    -var futureContractSymbol = qb.FutureChainProvider.GetFutureContractList(future.Symbol, startDate)
    -    .OrderBy(x => x.ID.Date)
    -    .First();
    -var history = qb.OptionHistory(
    -    futureContractSymbol, startDate, futureContractSymbol.ID.Date, Resolution.Hour
    -);
    -
    -var contracts = history
    -    .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys))
    -    .Distinct().ToList();
    -var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    -var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
    -
    -

    - To get historical data for arbitrary US Equity Option contracts instead of just the that pass your universe filter, call the - - History - - - history - - method like you would in an algorithm, but on the - - QuantBook - - object. For more information about historical data in the Research Environment, see - - Key Concepts - - . -

    - - - -

    Supported Assets

    - - -

    - The following list shows the available (15) Futures Options: -

    -
      -
    • - - Futures.Energy.CrudeOilWTI - - - Futures.Energy.CRUDE_OIL_WTI - - : Crude Oil WTI Futures (NYMEX: LO | Underlying: CL) -
    • -
    • - - Futures.Energy.Gasoline - - - Futures.Energy.GASOLINE - - : Gasoline RBOB Futures (NYMEX: OB | Underlying: RB) -
    • -
    • - - Futures.Energy.HeatingOil - - - Futures.Energy.HEATING_OIL - - : Heating Oil Futures (NYMEX: OH | Underlying: HO) -
    • -
    • - - Futures.Energy.NaturalGas - - - Futures.Energy.NATURAL_GAS - - : Natural Gas Futures (NYMEX: ON | Underlying: NG) -
    • -
    • - - Futures.Financials.Y10TreasuryNote - - - Futures.Financials.Y_10_TREASURY_NOTE - - : 10Y U.S. Treasury Note Futures (CBOT: OZN | Underlying: ZN) -
    • -
    • - - Futures.Financials.Y2TreasuryNote - - - Futures.Financials.Y_2_TREASURY_NOTE - - : 2Y U.S. Treasury Note Futures (CBOT: OZT | Underlying: ZT) -
    • -
    • - - Futures.Financials.Y30TreasuryBond - - - Futures.Financials.Y_30_TREASURY_BOND - - : 30Y U.S. Treasury Bond Futures (CBOT: OZB | Underlying: ZB) -
    • -
    • - - Futures.Grains.Corn - - - Futures.Grains.CORN - - : Corn Futures (CBOT: OZC | Underlying: ZC) -
    • -
    • - - Futures.Grains.Soybeans - - - Futures.Grains.SOYBEANS - - : Soybeans Futures (CBOT: OZS | Underlying: ZS) -
    • -
    • - - Futures.Grains.Wheat - - - Futures.Grains.WHEAT - - : Default wheat contract is SRWWheat (CBOT: OZW | Underlying: ZW) -
    • -
    • - - Futures.Indices.NASDAQ100EMini - - - Futures.Indices.NASDAQ_100_E_MINI - - : E-mini NASDAQ 100 Futures (CME: NQ) -
    • -
    • - - Futures.Indices.SP500EMini - - - Futures.Indices.SP_500_E_MINI - - : E-mini S&P 500 Futures (CME: ES) -
    • -
    • - - Futures.Metals.Copper - - - Futures.Metals.COPPER - - : Copper Futures (COMEX: HXE | Underlying: HG) -
    • -
    • - - Futures.Metals.Gold - - - Futures.Metals.GOLD - - : Gold Futures (COMEX: OG | Underlying: GC) -
    • -
    • - - Futures.Metals.Silver - - - Futures.Metals.SILVER - - : Silver Futures (COMEX: SO | Underlying: SI) -
    • -
    - - - -

    Example Applications

    - - -

    - The US Future Options dataset enables you to accurately design Future Option strategies. Examples include the following strategies: -

    -
      -
    • - Selling out of the money Future Option contracts to collect the premium that the Option buyer pays -
    • -
    • - Buying put Options to hedge against downward price movement in Future contracts you bought -
    • -
    • - Exploiting arbitrage opportunities that arise when the price of Option contracts deviates from their theoretical value -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example demonstrates a weekly-renewing - - covered call - - strategy to collect credit of selling the option. It filters the ATM call contract that expires within the current week at week start using - - SetFilter - - filtering function. -

    -
    -
    from AlgorithmImports import *
    -
    -class FutureOptionExampleAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(5_000_000)
    -        # Subscribe the underlying since the updated price is needed for filtering
    -        self.underlying = self.add_future(Futures.Indices.SP_500_E_MINI,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -            contract_depth_offset=0)
    -        # Filter the underlying continuous Futures to narrow the FOP spectrum
    -        self.underlying.set_filter(0, 182)
    -        # Filter for the current-week-expiring calls to formulate a covered call that expires at the end of week
    -        self.add_future_option(self.underlying.symbol, lambda u: u.calls_only().expiration(0, 5))
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol
    -        symbol = Symbol.create_canonical_option(self.underlying.mapped)
    -
    -        # Get option chain data for the mapped future, as both the underlying and FOP have the highest liquidity among all other contracts
    -        chain = slice.option_chains.get(symbol)
    -        if not self.portfolio.invested and chain:
    -            # Obtain the ATM call that expires at the end of week, such that both underlying and the FOP expires the same time
    -            expiry = max(x.expiry for x in chain)
    -            atm_call = sorted([x for x in chain if x.expiry == expiry],
    -                key=lambda x: abs(x.strike - x.underlying_last_price))[0]
    -
    -            # Use abstraction method to order a covered call to avoid manual error
    -            option_strategy = OptionStrategies.covered_call(symbol, atm_call.strike,expiry)
    -            self.buy(option_strategy, 1)
    -        
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            if security.type == SecurityType.FUTURE_OPTION:
    -                # Historical data
    -                history = self.history(security.symbol, 10, Resolution.MINUTE)
    -
    public class FutureOptionExampleAlgorithm : QCAlgorithm
    -{
    -    private Future _underlying;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(5000000);
    -        // Subscribe the underlying since the updated price is needed for filtering
    -        _underlying = AddFuture(Futures.Indices.SP500EMini,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.OpenInterest,
    -            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -            contractDepthOffset: 0);
    -        // Filter the underlying continuous Futures to narrow the FOP spectrum
    -        _underlying.SetFilter(0, 182);
    -        // Filter for the current-week-expiring calls to formulate a covered call that expires at the end of week
    -        AddFutureOption(_underlying.Symbol, (u) => u.CallsOnly().Expiration(0, 5));
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol
    -        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_underlying.Mapped);
    -
    -        // Get option chain data for the mapped future, as both the underlying and FOP have the highest liquidity among all other contracts
    -        if (!Portfolio.Invested && 
    -            slice.OptionChains.TryGetValue(symbol, out var chain))
    -        {
    -            // Obtain the ATM call that expires at the end of week, such that both underlying and the FOP expires the same time
    -            var expiry = chain.Max(x => x.Expiry);
    -            var atmCall = chain.Where(x => x.Expiry == expiry)
    -                .OrderBy(x => Math.Abs(x.Strike - x.UnderlyingLastPrice))
    -                .First();
    -
    -            // Use abstraction method to order a covered call to avoid manual error
    -            var optionStrategy = OptionStrategies.CoveredCall(symbol, atmCall.Strike, expiry);
    -            Buy(optionStrategy, 1);
    -        }
    -    }
    -
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            if (security.Type == SecurityType.FutureOption)
    -            {
    -                // Historical data
    -                var history = History(security.Symbol, 10, Resolution.Minute);
    -            }
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example demonstrates a daily renewing speculation trade on upward movement of Gold with FOP using algorithm framework. Using FOP, traders can achieve lower cost to get similar absolute profit, given the FOP is selected to be deep ITM with high Delta value. -

    -
    -
    from AlgorithmImports import *
    -
    -class USFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        # Override an option universe selection model to select the FOPs
    -        self.set_universe_selection(GoldFOPUniverseSelectionModel(self))
    -        # Handle the FOP trading logic in an alpha model
    -        self.add_alpha(ConstantFutureOptionsAlphaModel())
    -        # To order a single contract per insight, use a custom portfolio construction model
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -        
    -
    -class GoldFOPUniverseSelectionModel(OptionUniverseSelectionModel):
    -
    -    # Daily renewed universe since option contract list is updated on a daily basis
    -    def __init__(self, algorithm) -> None:
    -        self._algorithm = algorithm
    -        super().__init__(timedelta(1), self.select_fop_symbols)
    -
    -    def select_fop_symbols(self, utc_time: datetime) -> List[Symbol]:
    -        #  Create the underlying symbol to get the FOP contracts later
    -        future_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX)
    -        # Get all gold FOP contracts of the front month gold contract expiring within 3 months, since their liquidity is the highest
    -        future_contract_list = self._algorithm.future_chain_provider.get_future_contract_list(future_symbol, self._algorithm.time)
    -        return [Symbol.create_canonical_option(x) for x in future_contract_list 
    -                    if x.id.date <= self._algorithm.time + timedelta(90)]
    -
    -    def filter(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Filter for the ATM calls that expires latest (same expiry as the underlying)
    -        # +/-5 strike range buffer for price movement
    -        return option_filter_universe.back_month().strikes(-5, +5).calls_only()
    -
    -
    -class ConstantFutureOptionsAlphaModel(AlphaModel):
    -
    -    # A dictionary to cache the mapped FOP of the underlying Future for filtering wanted option chain data and check if invested
    -    option_contract_by_future_underlying_contract = {}
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        insights = []
    -
    -        for kvp in slice.option_chains:
    -            # Liquidate underlying Future contract after Option assignment
    -            underlying_future_contract = kvp.key.underlying
    -            if algorithm.portfolio[underlying_future_contract].invested:
    -                algorithm.insights.cancel([underlying_future_contract])
    -                del self.option_contract_by_future_underlying_contract[underlying_future_contract]
    -
    -            # Do not repeatly invest in the same underlying's FOP
    -            chain = [contract for contract in kvp.value if algorithm.securities[contract.symbol].is_tradable]
    -            if not chain or underlying_future_contract in self.option_contract_by_future_underlying_contract:
    -                continue
    -            
    -            # Select the Option contract with the lowest strike price to speculate trade the underlying with lowest cost and highest delta
    -            contract = sorted(chain, key=lambda x: x.strike)[0]
    -            insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(1), InsightDirection.UP))
    -            self.option_contract_by_future_underlying_contract[underlying_future_contract] = contract
    -        
    -        return insights
    -
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                # Use integer target to create a portfolio target to trade a single contract
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class FutureOptionDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        // Override an option universe selection model to select the FOPs
    -        AddUniverseSelection(new GoldFOPUniverseSelectionModel(this));
    -        // Handle the FOP trading logic in an alpha model
    -        SetAlpha(new ConstantFutureOptionsAlphaModel());
    -        // To order a single contract per insight, use a custom portfolio construction model
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}
    -
    -public class GoldFOPUniverseSelectionModel : OptionUniverseSelectionModel
    -{
    -    // Daily renewed universe since option contract list is updated on a daily basis
    -    public GoldFOPUniverseSelectionModel(QCAlgorithm algorithm)
    -        : base(TimeSpan.FromDays(1), _ => OptionChainSymbolSelector(algorithm, _))
    -    {
    -    }
    -
    -    private static IEnumerable<Symbol> OptionChainSymbolSelector(QCAlgorithm algorithm, DateTime utcTime)
    -    {
    -        // Create the underlying symbol to get the FOP contracts later
    -        var futureSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX);
    -        // Get all gold FOP contracts of the front month gold contract expiring within 3 months, since their liquidity is the highest
    -        return algorithm.FutureChainProvider.GetFutureContractList(futureSymbol, algorithm.Time)
    -            .Where(futureContractSymbol => futureContractSymbol.ID.Date <= algorithm.Time + TimeSpan.FromDays(90))
    -            .Select(futureContractSymbol => QuantConnect.Symbol.CreateCanonicalOption(futureContractSymbol));
    -    }
    -
    -    protected override OptionFilterUniverse Filter(OptionFilterUniverse optionFilterUniverse)
    -    {
    -        // Filter for the ATM calls that expires latest (same expiry as the underlying)
    -        // +/-5 strike range buffer for price movement
    -        return optionFilterUniverse.BackMonth().Strikes(-5, +5).CallsOnly();
    -    }
    -}
    -
    -
    -class ConstantFutureOptionsAlphaModel : AlphaModel
    -{
    -    // A dictionary to cache the mapped FOP of the underlying Future for filtering wanted option chain data and check if invested
    -    private Dictionary<Symbol, OptionContract> optionContractByUnderlyingFutureContract = new Dictionary<Symbol, OptionContract>();
    -    
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -        
    -        foreach (var kvp in slice.OptionChains)
    -        {
    -            // Liquidate underlying Future contract after Option assignment
    -            var underlyingFutureContract = kvp.Key.Underlying;
    -            if (algorithm.Portfolio[underlyingFutureContract].Invested)
    -            {
    -                algorithm.Insights.Cancel(new[] { underlyingFutureContract });
    -                optionContractByUnderlyingFutureContract.Remove(underlyingFutureContract);
    -            }
    -            
    -            // Do not repeatly invest in the same underlying's FOP
    -            var chain = kvp.Value.Where(contract => algorithm.Securities[contract.Symbol].IsTradable);
    -            if (chain.Count() == 0 || optionContractByUnderlyingFutureContract.ContainsKey(underlyingFutureContract))
    -            {
    -                continue;
    -            }
    -
    -            // Select the Option contract with the lowest strike price to speculate trade the underlying with lowest cost and highest delta
    -            var contract = chain.MinBy(contract => contract.Strike);
    -            insights.Add(Insight.Price(contract.Symbol, contract.Expiry.AddDays(1), InsightDirection.Up));
    -            optionContractByUnderlyingFutureContract.Add(kvp.Key.Underlying, contract);
    -        }            
    -        return insights;
    -    }
    -}
    -
    -
    -class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        var targets = new List<PortfolioTarget>();
    -        foreach (var insight in insights)
    -        {
    -            if (algorithm.Securities[insight.Symbol].IsTradable)
    -            {
    -                // Use integer target to create a portfolio target to trade a single contract
    -                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -            }
    -        }
    -        return targets;
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Future Options dataset provides - - TradeBar - - , - - QuoteBar - - , and - - OpenInterest - - objects. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - OpenInterest Attributes -

    -

    - - OpenInterest - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    AlgoSeek

    -

    US Futures

    -
    -
    -

    Introduction

    - - -

    - The US Futures dataset by AlgoSeek provides Futures data, including price, volume, open interest, and expiry. The data covers the 157 most liquid contracts, starts in May 2009, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on the CFE - - * - - , CBOT, CME, COMEX, NYMEX, and ICE - - * - - . -

    -

    - This dataset also depends on the - - US Futures Security Master - - because the US Futures Security Master dataset contains information to construct continuous Futures. -

    -

    - For more information about the US Futures dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering equities, futures, options, cash forex, and cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit - - algoseek.com - - . -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Futures dataset: -

    -
    -
    future = self.add_future(Futures.Metals.GOLD)
    -future.set_filter(0, 90)
    -
    var future = AddFuture(Futures.Metals.Gold);
    -future.SetFilter(0, 90);
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - May 2009 -
    - Asset Coverage - - 157 Futures -
    - Data Density - - Dense -
    - Resolution - - Tick, Second, Minute, Hour, & Daily -
    - Timezone - -
      -
    • - Chicago (CFE, CME or CBOT) -
    • -
    • - New York (ICE, NYMEX or COMEX) -
    • -
    -
    - Market Hours - - - Regular and Extended - -
    -

    - This dataset only includes Sugar (SB) from the ICE exchange. -

    -

    - This data provider doesn't include a live data feed for the CFE market (VIX). -

    -

    - LBS (Random Length Lumber) was deprecated for LBR (Lumber). -

    - - - -

    Volume Discrepancies

    - - -

    - The volume of the daily trade bars from this dataset is different from the daily volume that CME and other platforms like Yahoo Finance report because the CME includes pit trades in their daily volume calculation. In contrast, the volume of the daily trade bars in this dataset (from AlgoSeek) doesn't include pit trades because pit trades are over-the-counter, which algorithms can't trade. -

    -

    - Another discrepancy occurs from the start and end times of the daily bars. Daily bars from the CME and Yahoo Finance span from 5 PM Central Time (CT) to 4 PM CT on the following day. In contrast, QuantConnect consolidates daily bars from from 12 AM Eastern Time (ET) to 12 AM ET the following day. Therefore, to calculate the daily volume in the same way that CME does (excluding the pit trades), sum the volume of intraday bars that span 5 PM CT to 4 PM CT on the following day. For an example implementation, see - - Examples - - . -

    - - - -

    Requesting Data

    - - -

    - To add US Futures data to your algorithm, call the - - AddFuture - - - add_future - - method. Save a reference to the Future so you can access the data later in your algorithm. -

    -
    -
    class USFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2013, 12, 20) 
    -        self.set_end_date(2014, 2, 20) 
    -        self.set_cash(1000000) 
    -        self.universe_settings.asynchronous = True
    -        # Request Gold Future data
    -        future = self.add_future(Futures.Metals.GOLD) 
    -        # Set filter to obtain the contracts expire within 90 days
    -        future.set_filter(0, 90)
    -        self.future_symbol = future.symbol
    -
    public class USFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _futureSymbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2013, 12, 20);
    -        SetEndDate(2014, 2, 20);
    -        SetCash(1000000);
    -        UniverseSettings.Asynchronous = true;
    -        // Request Gold Future data
    -        var future = AddFuture(Futures.Metals.Gold);
    -        // Set filter to obtain the contracts expire within 90 days
    -        future.SetFilter(0, 90);
    -        _futureSymbol = future.Symbol;
    -    }
    -}
    -
    -
    -

    - For more information about creating Future subscriptions, see - - Requesting Data - - or - - Futures Universes - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current US Futures data, index the - - Bars - - - bars - - , - - QuoteBars - - - quote_bars - - , or - - Ticks - - - ticks - - properties of the current - - - Slice - - - with the Future - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Access data: TradeBar data
    -    if self.future_symbol in slice.bars:
    -        trade_bar = slice.bars[self.future_symbol]
    -        self.log(f"{self.future_symbol} close at {slice.time}: {trade_bar.close}")
    -
    -    # Access data: QuoteBar data
    -    if self.future_symbol in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.future_symbol]
    -        self.log(f"{self.future_symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    # Access data: Ticks data
    -    if self.future_symbol in slice.ticks:
    -        ticks = slice.ticks[self.future_symbol]
    -        for tick in ticks:
    -            self.log(f"{self.future_symbol} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    // Access data: TradeBar data
    -    if (slice.Bars.TryGetValue(_futureSymbol, out var tradeBar))
    -    {
    -        Log($"{_futureSymbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    // Access data: QuoteBar data
    -    if (slice.QuoteBars.TryGetValue(_futureSymbol, out var quoteBar))
    -    {
    -        Log($"{_futureSymbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    // Access data: Ticks data
    -    if (slice.Ticks.TryGetValue(_futureSymbol, out var ticks))
    -    {
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{_futureSymbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - You can also iterate through all of the data objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Iterate all TradeBar received
    -    for symbol, trade_bar in slice.bars.items():
    -        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    -
    -    # Iterate all QuoteBar received
    -    for symbol, quote_bar in slice.quote_bars.items():
    -        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    # Iterate all Ticks received
    -    for symbol, ticks in slice.ticks.items():
    -        for tick in ticks:
    -            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    // Iterate all TradeBar received
    -    foreach (var kvp in slice.Bars)
    -    {
    -        var symbol = kvp.Key;
    -        var tradeBar = kvp.Value;
    -        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    // Iterate all QuoteBar received
    -    foreach (var kvp in slice.QuoteBars)
    -    {
    -        var symbol = kvp.Key;
    -        var quoteBar = kvp.Value;
    -        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    // Iterate all Ticks received
    -    foreach (var kvp in slice.Ticks)
    -    {
    -        var symbol = kvp.Key;
    -        var ticks = kvp.Value;
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - For more information about accessing US Futures data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Futures data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Futures data in an algorithm, call the - - History - - - history - - method with the canonical Futures - - Symbol - - or a Futures contract - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame objects
    -contract_history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    -continuous_history_df = self.history(self.future_symbol,
    -    start=self.time - timedelta(days=15), 
    -    end=self.time, 
    -    resolution=Resolution.MINUTE, 
    -    fill_forward=False, 
    -    extended_market_hours=False,
    -    data_mapping_mode=DataMappingMode.OPEN_INTEREST, 
    -    data_normalization_mode=DataNormalizationMode.RAW, 
    -    contract_depth_offset=0)
    -
    -# TradeBar objects
    -contract_history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    -continous_history_trade_bars = self.history[TradeBar](self.future_symbol, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -contract_history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    -continous_history_quote_bars = self.history[QuoteBar](self.future_symbol, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -contract_history_ticks = self.history[Tick](contract.symbol, timedelta(seconds=10), Resolution.TICK)
    -continous_history_ticks = self.history[Tick](self.future_symbol, timedelta(seconds=10), Resolution.TICK)
    -
    // TradeBar objects
    -var contractHistoryTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    -var continuousHistoryTradeBars = History(
    -    symbols: new[] {_futureSymbol}, 
    -    start: Time - TimeSpan.FromDays(15),
    -    end: Time,
    -    resolution: Resolution.Minute,
    -    fillForward: false,
    -    extendedMarketHours: false,
    -    dataMappingMode: DataMappingMode.OpenInterest,
    -    dataNormalizationMode: DataNormalizationMode.Raw,
    -    contractDepthOffset: 0);
    -
    -// QuoteBar objects
    -var contractHistoryQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    -var continuousHistoryQuoteBars = History<QuoteBar>(_futureSymbol, 100, Resolution.Minute);
    -
    -// Tick objects
    -var contractHistoryTicks = History<Tick>(contract.Symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -var continuousHistoryTicks = History<Tick>(_futureSymbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -
    -

    - For more information about historical data in algorithms, see - - History Requests - - . For more information about the price adjustments for continuous contracts, see - - Continous Contracts - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Futures data in the Research Environment for an entire Futures chain, call the - - FutureHistory - - - future_history - - method with the canonical Future - - Symbol - - . -

    -
    -
    qb = QuantBook()
    -future = qb.add_future(Futures.Metals.GOLD) 
    -future.set_filter(0, 90)
    -history = qb.future_history(future.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    -history_df = history.data_frame
    -all_history = history.get_all_data()
    -expiries = history.get_expiry_dates()
    -
    var qb = new QuantBook();
    -var future = qb.AddFuture(Futures.Metals.Gold);
    -future.SetFilter(0, 90);
    -var history = qb.FutureHistory(future.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    -    
    -var contracts = history.SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys)).Distinct().ToList();
    -var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    -
    -

    - To get historical data for a single US Futures contract or the continuous Futures contract, call the - - History - - - history - - method like you would in an algorithm but on the - - QuantBook - - object. For more information about historical data in the Research Environment, see - - Futures - - . -

    - - - -

    Supported Assets

    - - -

    - The following list shows the available (157) Futures: -

    -
      -
    • - - Futures.Currencies.AUD - - : Australian Dollar Futures (CME: 6A) -
    • -
    • - - Futures.Currencies.AUDCAD - - : Australian Dollar/Canadian Dollar Futures (CME: ACD) -
    • -
    • - - Futures.Currencies.AUDJPY - - : Australian Dollar/Japanese Yen Futures (CME: AJY) -
    • -
    • - - Futures.Currencies.AUDNZD - - : Australian Dollar/New Zealand Dollar Futures (CME: ANE) -
    • -
    • - - Futures.Currencies.BRL - - : Brazillian Real Futures (CME: 6L) -
    • -
    • - - Futures.Currencies.BTC - - : Bitcoin Futures (CME: BTC) -
    • -
    • - - Futures.Currencies.BTICMicroBTC - - - Futures.Currencies.BTIC_MICRO_BTC - - : BTIC on Micro Bitcoin Futures (CME: MIB) -
    • -
    • - - Futures.Currencies.BTICMicroEther - - - Futures.Currencies.BTIC_MICRO_ETHER - - : BTIC on Micro Ether Futures (CME: MRB) -
    • -
    • - - Futures.Currencies.CAD - - : Canadian Dollar Futures (CME: 6C) -
    • -
    • - - Futures.Currencies.CADJPY - - : Canadian Dollar/Japanese Yen Futures (CME: CJY) -
    • -
    • - - Futures.Currencies.CHF - - : Swiss Franc Futures (CME: 6S) -
    • -
    • - - Futures.Currencies.ETH - - : Ether Futures (CME: ETH) -
    • -
    • - - Futures.Currencies.EUR - - : Euro FX Futures (CME: 6E) -
    • -
    • - - Futures.Currencies.EURAUD - - : Euro/Australian Dollar Futures (CME: EAD) -
    • -
    • - - Futures.Currencies.EURCAD - - : Euro/Canadian Dollar Futures (CME: ECD) -
    • -
    • - - Futures.Currencies.EuroFXEmini - - - Futures.Currencies.EURO_FX_EMINI - - : E-mini Euro FX Futures (CME: E7) -
    • -
    • - - Futures.Currencies.EURSEK - - : Euro/Swedish Krona Futures (CME: ESK) -
    • -
    • - - Futures.Currencies.GBP - - : British Pound Futures (CME: 6B) -
    • -
    • - - Futures.Currencies.JapaneseYenEmini - - - Futures.Currencies.JAPANESE_YEN_EMINI - - : E-mini Japanese Yen Futures (CME: J7) -
    • -
    • - - Futures.Currencies.JPY - - : Japanese Yen Futures (CME: 6J) -
    • -
    • - - Futures.Currencies.MicroAUD - - - Futures.Currencies.MICRO_AUD - - : Micro AUD/USD Futures (CME: M6A) -
    • -
    • - - Futures.Currencies.MicroBTC - - - Futures.Currencies.MICRO_BTC - - : Micro Bitcoin Futures (CME: MBT) -
    • -
    • - - Futures.Currencies.MicroCAD - - - Futures.Currencies.MICRO_CAD - - : Micro USD/CAD Futures (CME: M6C) -
    • -
    • - - Futures.Currencies.MicroCADUSD - - - Futures.Currencies.MICRO_CADUSD - - : Micro CAD/USD Futures (CME: MCD) -
    • -
    • - - Futures.Currencies.MicroCHF - - - Futures.Currencies.MICRO_CHF - - : Micro CHF/USD Futures (CME: MSF) -
    • -
    • - - Futures.Currencies.MicroEther - - - Futures.Currencies.MICRO_ETHER - - : Micro Ether Futures (CME: MET) -
    • -
    • - - Futures.Currencies.MicroEUR - - - Futures.Currencies.MICRO_EUR - - : Micro EUR/USD Futures (CME: M6E) -
    • -
    • - - Futures.Currencies.MicroGBP - - - Futures.Currencies.MICRO_GBP - - : Micro GBP/USD Futures (CME: M6B) -
    • -
    • - - Futures.Currencies.MicroINRUSD - - - Futures.Currencies.MICRO_INRUSD - - : Micro INR/USD Futures (CME: MIR) -
    • -
    • - - Futures.Currencies.MicroJPY - - - Futures.Currencies.MICRO_JPY - - : Micro JPY/USD Futures (CME: MJY) -
    • -
    • - - Futures.Currencies.MicroUSDCHF - - - Futures.Currencies.MICRO_USDCHF - - : Micro USD/CHF Futures (CME: M6S) -
    • -
    • - - Futures.Currencies.MicroUSDCNH - - - Futures.Currencies.MICRO_USDCNH - - : Micro USD/CNH Futures (CME: MNH) -
    • -
    • - - Futures.Currencies.MicroUSDJPY - - - Futures.Currencies.MICRO_USDJPY - - : Micro USD/JPY Futures (CME: M6J) -
    • -
    • - - Futures.Currencies.MXN - - : Mexican Peso Futures (CME: 6M) -
    • -
    • - - Futures.Currencies.NZD - - : New Zealand Dollar Futures (CME: 6N) -
    • -
    • - - Futures.Currencies.RUB - - : Russian Ruble Futures (CME: 6R) -
    • -
    • - - Futures.Currencies.StandardSizeUSDOffshoreRMBCNH - - - Futures.Currencies.STANDARD_SIZE_USD_OFFSHORE_RMBCNH - - : Standard-Size USD/Offshore RMB (CNH) Futures (CME: CNH) -
    • -
    • - - Futures.Currencies.ZAR - - : South African Rand Futures (CME: 6Z) -
    • -
    • - - Futures.Energy.ArgusLLSvsWTIArgusTradeMonth - - - Futures.Energy.ARGUS_LL_SVS_WTI_ARGUS_TRADE_MONTH - - : Argus LLS vs. WTI (Argus) Trade Month Futures (NYMEX: AE5) -
    • -
    • - - Futures.Energy.ArgusPropaneFarEastIndex - - - Futures.Energy.ARGUS_PROPANE_FAR_EAST_INDEX - - : Argus Propane Far East Index Futures (NYMEX: A7E) -
    • -
    • - - Futures.Energy.ArgusPropaneSaudiAramco - - - Futures.Energy.ARGUS_PROPANE_SAUDI_ARAMCO - - : Argus Propane (Saudi Aramco) Futures (NYMEX: A9N) -
    • -
    • - - Futures.Energy.BrentCrudeOilVsDubaiCrudeOilPlatts - - - Futures.Energy.BRENT_CRUDE_OIL_VS_DUBAI_CRUDE_OIL_PLATTS - - : Brent Crude Oil vs. Dubai Crude Oil (Platts) Futures (NYMEX: ADB) -
    • -
    • - - Futures.Energy.BrentLastDayFinancial - - - Futures.Energy.BRENT_LAST_DAY_FINANCIAL - - : Brent Last Day Financial Futures (NYMEX: BZ) -
    • -
    • - - Futures.Energy.ChicagoEthanolPlatts - - - Futures.Energy.CHICAGO_ETHANOL_PLATTS - - : Chicago Ethaanol (Platts) Futures (NYMEX: CU) -
    • -
    • - - Futures.Energy.ConwayPropaneOPIS - - - Futures.Energy.CONWAY_PROPANE_OPIS - - : Conway Propane (OPIS) Futures (NYMEX: A8K) -
    • -
    • - - Futures.Energy.CrudeOilWTI - - - Futures.Energy.CRUDE_OIL_WTI - - : Crude Oil WTI Futures (NYMEX: CL) -
    • -
    • - - Futures.Energy.DubaiCrudeOilPlattsFinancial - - - Futures.Energy.DUBAI_CRUDE_OIL_PLATTS_FINANCIAL - - : Dubai Crude Oil (Platts) Financial Futures (NYMEX: DCB) -
    • -
    • - - Futures.Energy.EastWestGasolineSpreadPlattsArgus - - - Futures.Energy.EAST_WEST_GASOLINE_SPREAD_PLATTS_ARGUS - - : East-West Gasoline Spread (Platts-Argus) Futures (NYMEX: EWG) -
    • -
    • - - Futures.Energy.EastWestNaphthaJapanCFvsCargoesCIFNWESpreadPlatts - - - Futures.Energy.EAST_WEST_NAPHTHA_JAPAN_C_FVS_CARGOES_CIFNWE_SPREAD_PLATTS - - : East-West Naphtha: Japan C&F vs. Cargoes CIF NWE Spread (Platts) Futures (NYMEX: EWN) -
    • -
    • - - Futures.Energy.Ethanol - - - Futures.Energy.ETHANOL - - : Ethanol Futures (CBOT: EH) -
    • -
    • - - Futures.Energy.EthanolT2FOBRdamIncludingDutyPlatts - - - Futures.Energy.ETHANOL_T_2_FOB_RDAM_INCLUDING_DUTY_PLATTS - - : Ethanol T2 FOB Rdam Including Duty (Platts) Futures (NYMEX: AZ1) -
    • -
    • - - Futures.Energy.EuropeanNaphthaPlattsCrackSpread - - - Futures.Energy.EUROPEAN_NAPHTHA_PLATTS_CRACK_SPREAD - - : European Naphtha (Platts) Crack Spread Futures (NYMEX: EN) -
    • -
    • - - Futures.Energy.EuropeanPropaneCIFARAArgus - - - Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS - - : European Propane CIF ARA (Argus) Futures (NYMEX: APS) -
    • -
    • - - Futures.Energy.EuropeanPropaneCIFARAArgusVsNaphthaCargoesCIFNWEPlatts - - - Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS_VS_NAPHTHA_CARGOES_CIFNWE_PLATTS - - : European Propane CIF ARA (Argus) vs. Naphtha Cargoes CIF NWE (Platts) Futures (NYMEX: EPN) -
    • -
    • - - Futures.Energy.FreightRouteTC14Baltic - - - Futures.Energy.FREIGHT_ROUTE_TC_14_BALTIC - - : Freight Route TC14 (Baltic) Futures (NYMEX: FRC) -
    • -
    • - - Futures.Energy.Gasoline - - - Futures.Energy.GASOLINE - - : Gasoline RBOB Futures (NYMEX: RB) -
    • -
    • - - Futures.Energy.GasolineEurobobOxyNWEBargesArgus - - - Futures.Energy.GASOLINE_EUROBOB_OXY_NWE_BARGES_ARGUS - - : Gasoline Euro-bob Oxy NWE Barges (Argus) Futures (NYMEX: B7H) -
    • -
    • - - Futures.Energy.GroupThreeSuboctaneGasolinePlattsVsRBOB - - - Futures.Energy.GROUP_THREE_SUBOCTANE_GASOLINE_PLATTS_VS_RBOB - - : Group Three Sub-octane Gasoliine (Platts) vs. RBOB Futures (NYMEX: AA8) -
    • -
    • - - Futures.Energy.GroupThreeULSDPlattsVsNYHarborULSD - - - Futures.Energy.GROUP_THREE_ULSD_PLATTS_VS_NY_HARBOR_ULSD - - : Group Three ULSD (Platts) vs. NY Harbor ULSD Futures (NYMEX: AA6) -
    • -
    • - - Futures.Energy.GulfCoastCBOBGasolineA2PlattsVsRBOBGasoline - - - Futures.Energy.GULF_COAST_CBOB_GASOLINE_A_2_PLATTS_VS_RBOB_GASOLINE - - : Gulf Coast CBOB Gasoline A2 (Platts) vs. RBOB Gasoline Futures (NYMEX: CRB) -
    • -
    • - - Futures.Energy.GulfCoastHSFOPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.GULF_COAST_HSFO_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : Gulf Coast HSFO (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: GCU) -
    • -
    • - - Futures.Energy.HeatingOil - - - Futures.Energy.HEATING_OIL - - : Heating Oil Futures (NYMEX: HO) -
    • -
    • - - Futures.Energy.LosAngelesCARBOBGasolineOPISvsRBOBGasoline - - - Futures.Energy.LOS_ANGELES_CARBOB_GASOLINE_OPI_SVS_RBOB_GASOLINE - - : Los Angeles CARBOB Gasoline (OPIS) vs. RBOB Gasoline Futures (NYMEX: AJL) -
    • -
    • - - Futures.Energy.LosAngelesCARBDieselOPISvsNYHarborULSD - - - Futures.Energy.LOS_ANGELES_CARB_DIESEL_OPI_SVS_NY_HARBOR_ULSD - - : Los Angeles CARB Diesel (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AKL) -
    • -
    • - - Futures.Energy.LosAngelesJetOPISvsNYHarborULSD - - - Futures.Energy.LOS_ANGELES_JET_OPI_SVS_NY_HARBOR_ULSD - - : Los Angeles Jet (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AJS) -
    • -
    • - - Futures.Energy.MarsArgusVsWTIFinancial - - - Futures.Energy.MARS_ARGUS_VS_WTI_FINANCIAL - - : Mars (Argus) vs. WTI Financial Futures (NYMEX: AYX) -
    • -
    • - - Futures.Energy.MarsArgusVsWTITradeMonth - - - Futures.Energy.MARS_ARGUS_VS_WTI_TRADE_MONTH - - : Mars (Argus) vs. WTI Trade Month Futures (NYMEX: AYV) -
    • -
    • - - Futures.Energy.MicroCrudeOilWTI - - - Futures.Energy.MICRO_CRUDE_OIL_WTI - - : Micro WTI Crude Oil Futures (NYMEX: MCL) -
    • -
    • - - Futures.Energy.MicroEuropeanFOBRdamMarineFuelZeroPointFivePercentBargesPlatts - - - Futures.Energy.MICRO_EUROPEAN_FOB_RDAM_MARINE_FUEL_ZERO_POINT_FIVE_PERCENT_BARGES_PLATTS - - : Micro European FOB Rdam Marine Fuel 0.5% Barges (Platts) Futures (NYMEX: R5O) -
    • -
    • - - Futures.Energy.MicroEuropeanThreePointFivePercentOilBargesFOBRdamPlatts - - - Futures.Energy.MICRO_EUROPEAN_THREE_POINT_FIVE_PERCENT_OIL_BARGES_FOB_RDAM_PLATTS - - : Micro European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: MEF) -
    • -
    • - - Futures.Energy.MicroGasoilZeroPointOnePercentBargesFOBARAPlatts - - - Futures.Energy.MICRO_GASOIL_ZERO_POINT_ONE_PERCENT_BARGES_FOBARA_PLATTS - - : Micro Gasoil 0.1% Barges FOB ARA (Platts) Futures (NYMEX: M1B) -
    • -
    • - - Futures.Energy.MicroSingaporeFOBMarineFuelZeroPointFivePercetPlatts - - - Futures.Energy.MICRO_SINGAPORE_FOB_MARINE_FUEL_ZERO_POINT_FIVE_PERCET_PLATTS - - : Micro Singapore FOB Marine Fuel 0.5% (Platts) Futures (NYMEX: S5O) -
    • -
    • - - Futures.Energy.MicroSingaporeFuelOil380CSTPlatts - - - Futures.Energy.MICRO_SINGAPORE_FUEL_OIL_380_CST_PLATTS - - : Micro Singapore Fuel Oil 380CST (Platts) Futures (NYMEX: MAF) -
    • -
    • - - Futures.Energy.MiniEuropeanThreePointPercentFiveFuelOilBargesPlatts - - - Futures.Energy.MINI_EUROPEAN_THREE_POINT_PERCENT_FIVE_FUEL_OIL_BARGES_PLATTS - - : Mini European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: A0D) -
    • -
    • - - Futures.Energy.MiniSingaporeFuelOil180CstPlatts - - - Futures.Energy.MINI_SINGAPORE_FUEL_OIL_180_CST_PLATTS - - : Mini Singapore Fuel Oil 180 cst (Platts) Futures (NYMEX: A0F) -
    • -
    • - - Futures.Energy.MontBelvieuEthaneOPIS - - - Futures.Energy.MONT_BELVIEU_ETHANE_OPIS - - : Mont Belvieu Ethane (OPIS) Futures (NYMEX: AC0) -
    • -
    • - - Futures.Energy.MontBelvieuLDHPropaneOPIS - - - Futures.Energy.MONT_BELVIEU_LDH_PROPANE_OPIS - - : Mont Belvieu LDH Propane (OPIS) Futures (NYMEX: B0) -
    • -
    • - - Futures.Energy.MontBelvieuNaturalGasolineOPIS - - - Futures.Energy.MONT_BELVIEU_NATURAL_GASOLINE_OPIS - - : Mont Belvieu Natural Gasoline (OPIS) Futures (NYMEX: A7Q) -
    • -
    • - - Futures.Energy.MontBelvieuNormalButaneOPIS - - - Futures.Energy.MONT_BELVIEU_NORMAL_BUTANE_OPIS - - : Mont Belvieu Normal Butane (OPIS) Futures (NYMEX: AD0) -
    • -
    • - - Futures.Energy.NaturalGas - - - Futures.Energy.NATURAL_GAS - - : Natural Gas Futures (NYMEX: NG) -
    • -
    • - - Futures.Energy.NaturalGasHenryHubLastDayFinancial - - - Futures.Energy.NATURAL_GAS_HENRY_HUB_LAST_DAY_FINANCIAL - - : Natural Gas (Henry Hub) Last-day Financial Futures (NYMEX: HH) -
    • -
    • - - Futures.Energy.NaturalGasHenryHubPenultimateFinancial - - - Futures.Energy.NATURAL_GAS_HENRY_HUB_PENULTIMATE_FINANCIAL - - : Natural Gas (Henry Hub) Penultimate Financial Futures (NYMEX: HP) -
    • -
    • - - Futures.Energy.OnePercentFuelOilCargoesFOBNWEPlattsVsThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.ONE_PERCENT_FUEL_OIL_CARGOES_FOBNWE_PLATTS_VS_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : 1% Fuel Oil Cargoes FOB NWE (Platts) vs. 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: FSS) -
    • -
    • - - Futures.Energy.PremiumUnleadedGasoline10ppmFOBMEDPlatts - - - Futures.Energy.PREMIUM_UNLEADED_GASOLINE_10_PPM_FOBMED_PLATTS - - : Premium Unleaded Gasoline 10 ppm FOB MED (Platts) Futures (NYMEX: A3G) -
    • -
    • - - Futures.Energy.PropaneNonLDHMontBelvieuOPIS - - - Futures.Energy.PROPANE_NON_LDH_MONT_BELVIEU_OPIS - - : Propane Non-LDH Mont Belvieu (OPIS) Futures (NYMEX: A1R) -
    • -
    • - - Futures.Energy.RBOBGasolineCrackSpread - - - Futures.Energy.RBOB_GASOLINE_CRACK_SPREAD - - : RBOB Gasoline Crack Spread Futures (NYMEX: ARE) -
    • -
    • - - Futures.Energy.RBOBGasolineVsEurobobOxyNWEBargesArgusThreeHundredFiftyThousandGallons - - - Futures.Energy.RBOB_GASOLINE_VS_EUROBOB_OXY_NWE_BARGES_ARGUS_THREE_HUNDRED_FIFTY_THOUSAND_GALLONS - - : RBOB Gasoline vs. Euro-bob Oxy NWE Barges (Argus) (350,000 gallons) Futures (NYMEX: EXR) -
    • -
    • - - Futures.Energy.SingaporeFuelOil380cstPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts - - - Futures.Energy.SINGAPORE_FUEL_OIL_380_CST_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS - - : Singapore Fuel Oil 380 cst (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: EVC) -
    • -
    • - - Futures.Energy.SingaporeGasoilPlattsVsLowSulphurGasoilFutures - - - Futures.Energy.SINGAPORE_GASOIL_PLATTS_VS_LOW_SULPHUR_GASOIL_FUTURES - - : Singapore Gasoil (Platts) vs. Low Sulphur Gasoil Futures (NYMEX: AGA) -
    • -
    • - - Futures.Energy.SingaporeMogas92UnleadedPlattsBrentCrackSpread - - - Futures.Energy.SINGAPORE_MOGAS_92_UNLEADED_PLATTS_BRENT_CRACK_SPREAD - - : Singapore Mogas 92 Unleaded (Platts) Brent Crack Spread Futures (NYMEX: D1N) -
    • -
    • - - Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread - - - Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD - - : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread Futures (NYMEX: FO) -
    • -
    • - - Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread1000mt - - - Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD_1000_MT - - : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread (1000mt) Futures (NYMEX: BOO) -
    • -
    • - - Futures.Energy.WTIBrentFinancial - - - Futures.Energy.WTI_BRENT_FINANCIAL - - : WTI-Brent Financial Futures (NYMEX: BK) -
    • -
    • - - Futures.Energy.WTIFinancial - - - Futures.Energy.WTI_FINANCIAL - - : WTI Financial Futures (NYMEX: CSX) -
    • -
    • - - Futures.Energy.WTIHoustonArgusVsWTITradeMonth - - - Futures.Energy.WTI_HOUSTON_ARGUS_VS_WTI_TRADE_MONTH - - : WTI Houston (Argus) vs. WTI Trade Month Futures (NYMEX: HTT) -
    • -
    • - - Futures.Energy.WTIHoustonCrudeOil - - - Futures.Energy.WTI_HOUSTON_CRUDE_OIL - - : WTI Houston Crude Oil Futures (NYMEX: HCL) -
    • -
    • - - Futures.Financials.EuroDollar - - - Futures.Financials.EURO_DOLLAR - - : EuroDollar Futures (CME: GE) -
    • -
    • - - Futures.Financials.FiveYearUSDMACSwap - - - Futures.Financials.FIVE_YEAR_USDMAC_SWAP - - : 5-Year USD MAC Swap Futures (CBOT: F1U) -
    • -
    • - - Futures.Financials.MicroY10TreasuryNote - - - Futures.Financials.MICRO_Y_10_TREASURY_NOTE - - : Micro 10-Year Yield Futures (CBOT: 10Y) -
    • -
    • - - Futures.Financials.MicroY2TreasuryBond - - - Futures.Financials.MICRO_Y_2_TREASURY_BOND - - : Micro 2-Year Yield Futures (CBOT: 2YY) -
    • -
    • - - Futures.Financials.MicroY30TreasuryBond - - - Futures.Financials.MICRO_Y_30_TREASURY_BOND - - : Micro 30-Year Yield Futures (CBOT: 30Y) -
    • -
    • - - Futures.Financials.MicroY5TreasuryBond - - - Futures.Financials.MICRO_Y_5_TREASURY_BOND - - : Micro 5-Year Yield Futures (CBOT: 5YY) -
    • -
    • - - Futures.Financials.UltraTenYearUSTreasuryNote - - - Futures.Financials.ULTRA_TEN_YEAR_US_TREASURY_NOTE - - : Ultra 10-Year U.S. Treasury Note Futures (CBOT: TN) -
    • -
    • - - Futures.Financials.UltraUSTreasuryBond - - - Futures.Financials.ULTRA_US_TREASURY_BOND - - : Ultra U.S. Treasury Bond Futures (CBOT: UB) -
    • -
    • - - Futures.Financials.Y10TreasuryNote - - - Futures.Financials.Y_10_TREASURY_NOTE - - : 10Y U.S. Treasury Note Futures (CBOT: ZN) -
    • -
    • - - Futures.Financials.Y2TreasuryNote - - - Futures.Financials.Y_2_TREASURY_NOTE - - : 2Y U.S. Treasury Note Futures (CBOT: ZT) -
    • -
    • - - Futures.Financials.Y30TreasuryBond - - - Futures.Financials.Y_30_TREASURY_BOND - - : 30Y U.S. Treasury Bond Futures (CBOT: ZB) -
    • -
    • - - Futures.Financials.Y5TreasuryNote - - - Futures.Financials.Y_5_TREASURY_NOTE - - : 5Y U.S. Treasury Note Futures (CBOT: ZF) -
    • -
    • - - Futures.Forestry.Lumber - - - Futures.Forestry.LUMBER - - : Lumber Futures (CME: LBR) -
    • -
    • - - Futures.Forestry.RandomLengthLumber - - - Futures.Forestry.RANDOM_LENGTH_LUMBER - - : Random Length Lumber Futures (CME: LBS) -
    • -
    • - - Futures.Grains.BlackSeaCornFinanciallySettledPlatts - - - Futures.Grains.BLACK_SEA_CORN_FINANCIALLY_SETTLED_PLATTS - - : Black Sea Corn Financially Settled (Platts) Futures (CBOT: BCF) -
    • -
    • - - Futures.Grains.BlackSeaWheatFinanciallySettledPlatts - - - Futures.Grains.BLACK_SEA_WHEAT_FINANCIALLY_SETTLED_PLATTS - - : Black Sea Wheat Financially Settled (Platts) Futures (CBOT: BWF) -
    • -
    • - - Futures.Grains.Corn - - - Futures.Grains.CORN - - : Corn Futures (CBOT: ZC) -
    • -
    • - - Futures.Grains.HRWWheat - - - Futures.Grains.HRW_WHEAT - - : KC HRW Wheat Futures (CBOT: KE) -
    • -
    • - - Futures.Grains.Oats - - - Futures.Grains.OATS - - : Oats Futures (CBOT: ZO) -
    • -
    • - - Futures.Grains.Soybeans - - - Futures.Grains.SOYBEANS - - : Soybeans Futures (CBOT: ZS) -
    • -
    • - - Futures.Grains.SoybeanMeal - - - Futures.Grains.SOYBEAN_MEAL - - : Soybean Meal Futures (CBOT: ZM) -
    • -
    • - - Futures.Grains.SoybeanOil - - - Futures.Grains.SOYBEAN_OIL - - : Soybean Oil Futures (CBOT: ZL) -
    • -
    • - - Futures.Grains.Wheat - - - Futures.Grains.WHEAT - - : Default wheat contract is SRWWheat (CBOT: ZW) -
    • -
    • - - Futures.Indices.BloombergCommodityIndex - - - Futures.Indices.BLOOMBERG_COMMODITY_INDEX - - : Bloomberg Commodity Index Futures (CBOT: AW) -
    • -
    • - - Futures.Indices.Dow30EMini - - - Futures.Indices.DOW_30_E_MINI - - : E-mini Dow Indu 30 Futures (CBOT: YM) -
    • -
    • - - Futures.Indices.DowJonesRealEstate - - - Futures.Indices.DOW_JONES_REAL_ESTATE - - : Dow Jones Real Estate futures on CME (CME: RX) -
    • -
    • - - Futures.Indices.FTSEEmergingEmini - - - Futures.Indices.FTSE_EMERGING_EMINI - - : E-mini FTSE Emerging Index Futures (CME: EI) -
    • -
    • - - Futures.Indices.MicroDow30EMini - - - Futures.Indices.MICRO_DOW_30_E_MINI - - : Micro E-mini Dow Jones Industrial Average Index Futures (CBOT: MYM) -
    • -
    • - - Futures.Indices.MicroNASDAQ100EMini - - - Futures.Indices.MICRO_NASDAQ_100_E_MINI - - : Micro E-mini Nasdaq-100 Index Futures (CME: MNQ) -
    • -
    • - - Futures.Indices.MicroRussell2000EMini - - - Futures.Indices.MICRO_RUSSELL_2000_E_MINI - - : Micro E-mini Russell 2000 Index Futures (CME: M2K) -
    • -
    • - - Futures.Indices.MicroSP500EMini - - - Futures.Indices.MICRO_SP_500_E_MINI - - : Micro E-mini S&P 500 Index Futures (CME: MES) -
    • -
    • - - Futures.Indices.NASDAQ100BiotechnologyEMini - - - Futures.Indices.NASDAQ_100_BIOTECHNOLOGY_E_MINI - - : E-mini Nasdaq-100 Biotechnology Index Futures (CME: BIO) -
    • -
    • - - Futures.Indices.NASDAQ100EMini - - - Futures.Indices.NASDAQ_100_E_MINI - - : E-mini NASDAQ 100 Futures (CME: NQ) -
    • -
    • - - Futures.Indices.Nikkei225Dollar - - - Futures.Indices.NIKKEI_225_DOLLAR - - : Nikkei-225 Dollar Futures (CME: NKD) -
    • -
    • - - Futures.Indices.Nikkei225YenCME - - - Futures.Indices.NIKKEI_225_YEN_CME - - : Nikkei-225 Yen denominated Futures on CME (CME: NIY) -
    • -
    • - - Futures.Indices.Russell1000EMini - - - Futures.Indices.RUSSELL_1000_E_MINI - - : E-mini Russell 1000 futures on CME (CME: RS1) -
    • -
    • - - Futures.Indices.Russell2000EMini - - - Futures.Indices.RUSSELL_2000_E_MINI - - : E-mini Russell 2000 Futures (CME: RTY) -
    • -
    • - - Futures.Indices.SPGSCICommodity - - - Futures.Indices.SPGSCI_COMMODITY - - : S&P-GSCI Commodity Index Futures (CME: GD) -
    • -
    • - - Futures.Indices.SP400MidCapEmini - - - Futures.Indices.SP_400_MID_CAP_EMINI - - : E-mini S&P MidCap 400 Futures (CME: EMD) -
    • -
    • - - Futures.Indices.SP500AnnualDividendIndex - - - Futures.Indices.SP_500_ANNUAL_DIVIDEND_INDEX - - : (CME: SDA) -
    • -
    • - - Futures.Indices.SP500EMini - - - Futures.Indices.SP_500_E_MINI - - : E-mini S&P 500 Futures (CME: ES) -
    • -
    • - - Futures.Indices.TOPIXYEN - - : YEN Denominated Topix Index Futures on CME (CME: TPY) -
    • -
    • - - Futures.Indices.USDDenominatedIbovespa - - - Futures.Indices.USD_DENOMINATED_IBOVESPA - - : USD-Denominated Ibovespa Index Futures (CME: IBV) -
    • -
    • - - Futures.Indices.VIX - - : CBOE Volatility Index Futures (CFE: VX) -
    • -
    • - - Futures.Meats.FeederCattle - - - Futures.Meats.FEEDER_CATTLE - - : Feeder Cattle Futures (CME: GF) -
    • -
    • - - Futures.Meats.LeanHogs - - - Futures.Meats.LEAN_HOGS - - : Lean Hogs Futures (CME: HE) -
    • -
    • - - Futures.Meats.LiveCattle - - - Futures.Meats.LIVE_CATTLE - - : Live Cattle Futures (CME: LE) -
    • -
    • - - Futures.Metals.AluminiumEuropeanPremiumDutyPaidMetalBulletin - - - Futures.Metals.ALUMINIUM_EUROPEAN_PREMIUM_DUTY_PAID_METAL_BULLETIN - - : Aluminium European Premium Duty-Paid (Metal Bulletin) Futures (COMEX: EDP) -
    • -
    • - - Futures.Metals.AluminumMWUSTransactionPremiumPlatts25MT - - - Futures.Metals.ALUMINUM_MWUS_TRANSACTION_PREMIUM_PLATTS_25_MT - - : Aluminum MW U.S. Transaction Premium Platts (25MT) Futures (COMEX: AUP) -
    • -
    • - - Futures.Metals.Copper - - - Futures.Metals.COPPER - - : Copper Futures (COMEX: HG) -
    • -
    • - - Futures.Metals.Gold - - - Futures.Metals.GOLD - - : Gold Futures (COMEX: GC) -
    • -
    • - - Futures.Metals.MicroGold - - - Futures.Metals.MICRO_GOLD - - : Micro Gold Futures (COMEX: MGC) -
    • -
    • - - Futures.Metals.MicroGoldTAS - - - Futures.Metals.MICRO_GOLD_TAS - - : Micro Gold TAS Futures (COMEX: MGT) -
    • -
    • - - Futures.Metals.MicroPalladium - - - Futures.Metals.MICRO_PALLADIUM - - : Micro Palladium Futures (NYMEX: PAM) -
    • -
    • - - Futures.Metals.MicroSilver - - - Futures.Metals.MICRO_SILVER - - : Micro Silver Futures (COMEX: SIL) -
    • -
    • - - Futures.Metals.Palladium - - - Futures.Metals.PALLADIUM - - : Palladium Futures (NYMEX: PA) -
    • -
    • - - Futures.Metals.Platinum - - - Futures.Metals.PLATINUM - - : Platinum Futures (NYMEX: PL) -
    • -
    • - - Futures.Metals.Silver - - - Futures.Metals.SILVER - - : Silver Futures (COMEX: SI) -
    • -
    • - - Futures.Metals.USMidwestDomesticHotRolledCoilSteelCRUIndex - - - Futures.Metals.US_MIDWEST_DOMESTIC_HOT_ROLLED_COIL_STEEL_CRU_INDEX - - : U.S. Midwest Domestic Hot-Rolled Coil Steel (CRU) Index Futures (NYMEX: HRC) -
    • -
    • - - Futures.Softs.Sugar11 - - - Futures.Softs.SUGAR_11 - - : Sugar #11 Futures ICE (ICE: SB) -
    • -
    • - - Futures.Softs.Sugar11CME - - - Futures.Softs.SUGAR_11_CME - - : Sugar #11 Futures CME (NYMEX: YO) -
    • -
    - - - -

    Example Applications

    - - -

    - The US Futures dataset enables you to accurately design Futures strategies. Examples include the following strategies: -

    -
      -
    • - Buying the Futures contract with the most open interest to reduce slippage and market impact -
    • -
    • - Trading bull calendar spreads to reduce volatility and margin requirements -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm buys the Mini Gold Futures contract with the greatest open interest and sells the Micro Gold Futures contract with the greatest open interest. When the open interest of a different contract exceeds the open interest of a contract in the portfolio, the algorithm rebalances the portfolio. -

    -
    -
    from AlgorithmImports import *
    -
    -class USFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(1000000)
    -        # Setting the continuous contract mapping criteria for both Gold and Micro Gold contracts, since we want to order the highest liquidity contracts
    -        self.settings.seed_initial_prices = True
    -        self.gold = self.add_future(Futures.Metals.GOLD,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -            contract_depth_offset=0)
    -        self.micro_gold = self.add_future(Futures.Metals.MICRO_GOLD,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    -            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    -            contract_depth_offset=0)
    -        # The contract multiplier is cached in the Security symbol_properties property from the symbol properties database
    -        self.gold_multiplier = self.gold.symbol_properties.contract_multiplier
    -        self.micro_gold_multiplier = self.micro_gold.symbol_properties.contract_multiplier
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Make sure to calculate the order size by the most updated price data of both contracts
    -        if not self.portfolio.invested and self.gold.symbol in slice.bars and self.micro_gold.symbol in slice.bars:
    -            # Calculate the order size for $500k
    -            # Get the quotient after dividing the contract multiplier since the order size must be whole number
    -            gold_quantity = 500000 / slice.bars[self.gold.symbol].close // self.gold_multiplier
    -            micro_gold_quantity = 500000 / slice.bars[self.micro_gold.symbol].close // self.micro_gold_multiplier
    -
    -            self.market_order(self.gold.mapped, gold_quantity)
    -            self.market_order(self.micro_gold.mapped, micro_gold_quantity)
    -                
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            # Historical data
    -            history = self.history(security.symbol, 10, Resolution.MINUTE)
    -            self.debug(f"We got {len(history)} from our history request for {security.symbol}")
    -
    public class USFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Future _gold, _microGold;
    -    private decimal _goldMulitplier, _microGoldMulitplier;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -        // Setting the continuous contract mapping criteria for both Gold and Micro Gold contracts, since we want to order the highest liquidity contracts
    -        Settings.SeedInitialPrices = true;
    -        _gold = AddFuture(Futures.Metals.Gold,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.OpenInterest,
    -            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -            contractDepthOffset: 0);
    -        _microGold = AddFuture(Futures.Metals.MicroGold,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.OpenInterest,
    -            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    -            contractDepthOffset: 0);
    -        // The contract multiplier is cached in the Security SymbolProperties property from the symbol properties database
    -        _goldMulitplier = _gold.SymbolProperties.ContractMultiplier;
    -        _microGoldMulitplier = _microGold.SymbolProperties.ContractMultiplier;
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Make sure to calculate the order size by the most updated price data of both contracts
    -        if (!Portfolio.Invested && slice.Bars.ContainsKey(_gold.Symbol) && slice.Bars.ContainsKey(_microGold.Symbol))
    -        {
    -            // Calculate the order size for $500k
    -            // Get the quotient after dividing the contract multiplier since the order size must be whole number
    -            var goldQuantity = Math.Floor(500000m / slice.Bars[_gold.Symbol].Close / _goldMulitplier);
    -            var microGoldQuantity = Math.Floor(500000m / slice.Bars[_microGold.Symbol].Close / _microGoldMulitplier);
    -
    -            MarketOrder(_gold.Mapped, goldQuantity);
    -            MarketOrder(_microGold.Mapped, microGoldQuantity);
    -        }
    -    }
    -    
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            // Historical data
    -            var history = History(security.Symbol, 100, Resolution.Minute);
    -            Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm buys the front-month Mini Gold Futures contract and sells the front-month Micro Gold Futures contract. When the front-month contract changes, the algorithm rebalances the portfolio. -

    -
    -
    from AlgorithmImports import *
    -
    -class USFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.universe_settings.asynchronous = True
    -        # Set up an universe selection model that selects the front month contract
    -        self.set_universe_selection(FrontMonthFutureUniverseSelectionModel())
    -        self.add_alpha(ConstantFuturesAlphaModel())
    -        # A portfolio construction model that only order a single share per insight signal
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -        
    -class FrontMonthFutureUniverseSelectionModel(FutureUniverseSelectionModel):
    -    def __init__(self,) -> None:
    -        # Daily updating with select_future_chain_symbols function
    -        super().__init__(timedelta(1), self.select_future_chain_symbols)
    -
    -    def select_future_chain_symbols(self, utcTime: datetime) -> List[Symbol]:
    -        # Select gold and micro gold contracts for the strategy need
    -        future_pairs = [
    -            (Futures.Metals.GOLD, Market.COMEX),
    -            (Futures.Metals.MICRO_GOLD, Market.COMEX)
    -        ]
    -        return [Symbol.create(pair[0], SecurityType.FUTURE, pair[1]) for pair in future_pairs]
    -
    -    def filter(self, filter: FutureFilterUniverse) -> FutureFilterUniverse:
    -        # Filter only front month contract for liquidity and most informed information
    -        return filter.front_month().only_apply_filter_at_market_open()
    -
    -class ConstantFuturesAlphaModel(AlphaModel):
    -    # Long gold and short micro gold in this strategy
    -    long_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX)
    -    short_symbol = Symbol.create(Futures.Metals.MICRO_GOLD, SecurityType.FUTURE, Market.COMEX)
    -        
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        if algorithm.portfolio.invested:
    -            return []
    -        
    -        insights = []
    -        # For both gold and micro gold, select the front month contract (only contract) in the chain
    -        for symbol, contracts in slice.future_chains.items():
    -            chain = [contract for contract in contracts]
    -            contract = chain[0]
    -            
    -            # Long gold and short micro gold as planned
    -            if symbol == self.long_symbol:
    -                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.UP))
    -            elif symbol == self.short_symbol:
    -                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.DOWN))
    -        
    -        return insights
    -        
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            # Historical data
    -            history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    -            algorithm.debug(f"We got {len(history)} from our history request for {security.symbol}")
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        targets = []
    -        for insight in insights:
    -            if algorithm.securities[insight.symbol].is_tradable:
    -                # Single share only using integer portfolio target
    -                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    -        return targets
    -
    public class USFuturesDataAlgorithm : QCAlgorithm
    -{        
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(1000000);
    -        UniverseSettings.Asynchronous = true;
    -        // Set up an universe selection model that selects the front month contract
    -        SetUniverseSelection(new FrontMonthFutureUniverseSelectionModel());
    -        SetAlpha(new ConstantFuturesAlphaModel());
    -        // A portfolio construction model that only order a single share per insight signal
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}
    -    
    -class FrontMonthFutureUniverseSelectionModel : FutureUniverseSelectionModel
    -{
    -    // Daily updating with select_future_chain_symbols function
    -    public FrontMonthFutureUniverseSelectionModel()
    -        : base(TimeSpan.FromDays(1), SelectFutureChainSymbols) {}
    -
    -    private static IEnumerable<Symbol> SelectFutureChainSymbols(DateTime utcTime)
    -    {
    -        //Select gold and micro gold contracts for the strategy need
    -        return new List<Symbol> {
    -            QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX),
    -            QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX)
    -        };
    -    }
    -
    -    protected override FutureFilterUniverse Filter(FutureFilterUniverse filter)
    -    {
    -        // Filter only front month contract for liquidity and most informed information
    -        return filter.FrontMonth().OnlyApplyFilterAtMarketOpen();
    -    }
    -}
    -
    -
    -class ConstantFuturesAlphaModel : AlphaModel
    -{
    -    // Long gold and short micro gold in this strategy
    -    private Symbol 
    -        _longSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX), 
    -        _shortSymbol = QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX);
    -    
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -
    -        if (algorithm.Portfolio.Invested)
    -        {
    -            return insights;
    -        }
    -        
    -        // For both gold and micro gold, select the front month contract (only contract) in the chain
    -        foreach (var kvp in slice.FutureChains)
    -        {
    -            var symbol = kvp.Key;
    -            var chain = kvp.Value;
    -            var contract = chain.First();
    -            
    -            // Long gold and short micro gold as planned
    -            if (symbol == _longSymbol)
    -            {
    -                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Up));
    -            }
    -            else if (symbol == _shortSymbol)
    -            {
    -                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Down));
    -            }
    -        }
    -
    -        return insights;
    -    }
    -    
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            // Historical data
    -            var history = algorithm.History(security.Symbol, 100, Resolution.Minute);
    -            algorithm.Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    -        }
    -    }
    -}
    -    
    -    
    -class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        var targets = new List<PortfolioTarget>();
    -        foreach (var insight in insights)
    -        {
    -            if (algorithm.Securities[insight.Symbol].IsTradable)
    -            {
    -                // Single share only using integer portfolio target
    -                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    -            }
    -        }
    -        return targets;
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Futures dataset provides - - FuturesChain - - , - - Future - - , and - - OpenInterest - - objects. To configure the continuous Future settings, use the - - DataNormalizationMode - - and - - DataMappingMode - - enumerations. -

    -

    - DataNormalizationMode Values -

    -

    - The - - DataNormalizationMode - - enumeration has the following values: -

    -
    -
    -

    - DataMappingMode Values -

    -

    - The - - DataMappingMode - - enumeration has the following values: -

    -
    -
    -

    - Future Attributes -

    -

    - - Future - - objects have the following attributes: -

    -
    -
    -

    - FuturesChain Attributes -

    -

    - - FuturesChain - - objects have the following attributes: -

    -
    -
    -

    - OpenInterest Attributes -

    -

    - - OpenInterest - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    AlgoSeek

    -

    US Index Options

    -
    -
    -

    Introduction

    - - -

    - The US Index Options dataset by AlgoSeek provides Option data, including prices, strikes, expires, and open interest. The data covers European Option contracts for 3 US Indices: SPX, VIX, and NDX. It starts from January 2012 and is delivered on minute resolution. This dataset is created by monitoring the Options Price Reporting Authority (OPRA) data feed, which consolidates last sale and quotation information originating from the national securities exchanges that have been approved by the Securities and Exchange Commission. -

    -

    - The US Index Options dataset depends on the - - US Index Option Universe - - dataset because the US Index Options Universe dataset contains information on the available contracts, including their daily Greeks and implied volatility values. -

    -

    - For more information about the US Index Options dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit - - algoseek.com - - . -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the US Index Options dataset: -

    -
    -
    self.index_symbol = self.add_index('VIX').symbol
    -option = self.add_index_option(self.index_symbol)
    -option.set_filter(-2, 2, 0, 90)
    -self.option_symbol = option.symbol
    -
    _indexSymbol = AddIndex("VIX").Symbol;
    -var option = AddIndexOption(_indexSymbol);
    -option.SetFilter(-2, 2, 0, 90);
    -_optionSymbol = option.Symbol;
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 2012 -
    - Asset Coverage - - 7 Index Options -
    - Data Density - - Regular -
    - Resolution - - Minute, Hourly, & Daily -
    - Timezone - - New York -
    - Market Hours - - - Regular Only - -
    - - - -

    Specification Over Time

    - - -

    - According to the SPX Options - - contract specification - - , some SPX contracts expire every month and SPXW contracts expires every day. Before 2021, you could only trade SPX contracts with the following expiration dates: -

    -
      -
    • - Expires within the next 4 months -
    • -
    • - Expires in September within the next 14 months -
    • -
    • - Expires in January, March, or June within the next 2 years -
    • -
    • - Expires in December within the next 3 years -
    • -
    -

    - During this time, SPXW didn't have 0DTE every day. -

    -

    - - Sources - - : -
    - - - - Cboe Options Exchange to List Three Long-Dated SPX Options Expirations, Beginning November 1, 2021 - -
    - - - - S&P 500 Weekly Options Now Expire Five Days a Week - -

    - - - -

    Requesting Data

    - - -

    - To add US Index Options data to your algorithm, call the - - AddIndexOption - - - add_index_option - - method. Save a reference to the Index Option - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class IndexOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2021, 1, 1);
    -        self.set_end_date(2021, 6, 1);
    -        self.set_cash(1000000);
    -        self.universe_settings.asynchronous = True
    -        self.index_symbol = self.add_index('VIX').symbol
    -        
    -        standard_option = self.add_index_option(self.index_symbol)
    -        standard_option.set_filter(-2, 2, 0, 90)
    -        self.standard_option_symbol = standard_option.symbol
    -
    -        weekly_option = self.add_index_option(self.index_symbol, "VIXW")
    -        weekly_option.set_filter(-2, 2, 0, 90)
    -        self.weekly_option_symbol = weekly_option.symbol
    -
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _indexSymbol, _standardOptionSymbol, _weeklyOptionSymbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2021, 1, 1);
    -        SetEndDate(2021, 6, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        _indexSymbol = AddIndex("VIX").Symbol;
    -
    -        var standardOption = AddIndexOption(_indexSymbol);
    -        standardOption.SetFilter(-2, 2, 0, 90);
    -        _standardOptionSymbol = standardOption.Symbol;
    -
    -        var weeklyOption = AddIndexOption(_indexSymbol, "VIXW");
    -        weeklyOption.SetFilter(-2, 2, 0, 90);
    -        _weeklyOptionSymbol = weeklyOption.Symbol;
    -    }
    -}
    -
    -

    - The Index resolution must be less than or equal to the Index Option resolution. For example, if you set the Index resolution to minute, then you must set the Index Option resolution to minute, hour, or daily. -

    -

    - For more information about creating US Index Option subscriptions, see - - Requesting Data - - or - - Index Options Universes - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current US Index Options data, index the - - OptionChains - - - option_chains - - property of the current - - - Slice - - - with the canonical Index Option - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your Index Option at every time step. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    standard_chain = slice.option_chains.get(self.standard_option_symbol)
    -    if standard_chain:
    -        for contract in standard_chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    -    weekly_chain = slice.option_chains.get(self.weekly_option_symbol)
    -    if weekly_chain:
    -        for contract in weekly_chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    public override void OnData(Slice slice)
    -{
    -    if (slice.OptionChains.ContainsKey(_standardOptionSymbol))
    -    {
    -        var standardChain = slice.OptionChains[_standardOptionSymbol];
    -        foreach (var contract in standardChain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -
    -    if (slice.OptionChains.ContainsKey(_weeklyOptionSymbol))
    -    {
    -        var weeklyChain = slice.OptionChains[_weeklyOptionSymbol];
    -        foreach (var contract in weeklyChain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - You can also iterate through all of the - - OptionChain - - objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for canonical_symbol, chain in slice.option_chains.items():
    -        for contract in chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.OptionChains)
    -    {
    -        var canonicalSymbol = kvp.Key;
    -        var chain = kvp.Value;
    -        foreach (var contract in chain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - For more information about accessing US Index Options data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical US Index Options data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical US Index Options data in an algorithm, call the - - History - - - history - - method with the Index Option contract - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame of trade and quote data
    -history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    -
    -# DataFrame of open interest data
    -history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    -
    -# OpenInterest objects
    -history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
    -
    // TradeBar objects 
    -var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    -
    -// OpenInterest objects
    -var historyOpenInterest = History<OpenInterest>(contract.Symbol, 100, Resolution.Minute);
    -
    -

    - For more information about historical data in algorithms, see - - History Requests - - . -

    -

    - Historical Data In Research -

    -

    - To get historical US Index Options data in the Research Environment, call the - - History - - - history - - or - - OptionHistory - - - option_history - - method. The - - History - - - history - - method returns the price, volume, and open interest history for some given Option contract(s). The - - OptionHistory - - - option_history - - method returns the price and volume history for the contracts that pass your daily universe filter. -

    -
    -
    qb = QuantBook()
    -index_symbol = qb.add_index('VIX').symbol
    -option = qb.add_index_option(index_symbol) # or qb.add_index_option(index_symbol, "VIXW")
    -option.set_filter(-2, 2, 0, 90)
    -history = qb.option_history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    -history_df = history.data_frame
    -expiries = history.get_expiry_dates() 
    -strikes = history.get_strikes()
    -
    var qb = new QuantBook();
    -var indexSymbol = qb.AddIndex("VIX").Symbol;
    -var option = qb.AddIndexOption(indexSymbol); // or qb.AddIndexOption(indexSymbol, "VIXW");
    -option.SetFilter(-2, 2, 0, 90);
    -var history = qb.OptionHistory(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    -
    -var contracts = history
    -    .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys))
    -    .Distinct().ToList();
    -var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    -var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
    -
    -

    - To get historical data for arbitrary US Index Option contracts instead of just the that pass your universe filter, call the - - History - - - history - - method like you would in an algorithm, but on the - - QuantBook - - object. For more information about historical data in the Research Environment, see - - Key Concepts - - . -

    -

    - Historical Greeks and IV Data -

    -

    - To get historical data for the Greeks and implied volatility of Index Options, see the - - US Index Option Universe - - dataset. -

    - - - -

    Supported Assets

    - - -

    - The following table shows the available Index Options: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Underlying Index - - Underlying Ticker - - Target Ticker - - Standard Contracts - - Weekly Contracts - - Tradable on Expiry Day -
    - NASDAQ-100 - - NDX - - - green check - - -
    - NASDAQ-100 - - NDX - - NDXP - - green check - - - green check -
    - NASDAQ-100 - - NDX - - NQX - - green check - - green check - - green check -
    - Russell 2000 - - RUT - - - green check - - -
    - Russell 2000 - - RUT - - RUTW - - - green check - - green check -
    - S&P500 - - SPX - - - green check - - -
    - S&P500 - - SPX - - SPXW - - - green check - - green check -
    - S&P500 - - VIX - - - green check - - -
    - S&P500 - - VIX - - VIXW - - - green check - -
    -

    - For more information about each underlying Index, see - - Supported Indices - - . -

    - - - -

    Example Applications

    - - -

    - The US Index Options dataset enables you to accurately design strategies for Index Options. Examples include the following strategies: -

    -
      -
    • - Buying VIX call Options to hedge against upcoming volatility -
    • -
    • - Buying VIX put Options to capture the natural downward price movement in the VIX index -
    • -
    • - Buying SPX put Options to protect against downward price movement in the S&P 500 -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm buys the VIX Index Option Bull Call Spread with the furthest expiration: -

    -
    -
    from AlgorithmImports import *
    -
    -class IndexOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(200000)
    -        # Asynchronous can use computational resources efficiently
    -        self.universe_settings.asynchronous = True
    -        # Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    -        option = self.add_index_option("SPX")
    -        option.set_filter(lambda u: u.calls_only().strikes(-2, +2).expiration(0, 180))
    -        self.option_symbol = option.symbol
    -
    -    def on_data(self, slice: Slice) -> None:
    -        if not self.portfolio.invested and self.is_market_open(self.option_symbol):
    -            # Make sure getting the updated VIX option chain
    -            chain = slice.option_chains.get(self.option_symbol)
    -            if chain:
    -                expiry = max([c.expiry for c in chain])
    -                call_contracts = sorted([c for c in chain if c.expiry == expiry],
    -                    key=lambda c: c.strike)
    -                
    -                # Need 2 contracts to form a call spread
    -                if len(call_contracts) < 2:
    -                    return
    -                
    -                # Obtain 2 call contracts with different strike price to form the call spread
    -                longCall, shortCall = call_contracts[0:2]
    -                
    -                # Use all the buying power, but need to ensure the order size of the long and short call are the same
    -                quantity = min([
    -                    abs(self.calculate_order_quantity(shortCall.symbol, -1)),
    -                    abs(self.calculate_order_quantity(longCall.symbol, 1))])
    -                if not quantity:
    -                    return
    -
    -                # Bull call spread consists of long a lower-strike call and short a higher-strike call
    -                self.market_order(shortCall.symbol, -quantity)
    -                self.market_order(longCall.symbol, quantity)
    -                
    -                expected_margin_usage = max((longCall.strike - shortCall.strike) * self.securities[longCall.symbol].symbol_properties.contract_multiplier * quantity, 0)
    -                if expected_margin_usage != self.portfolio.total_margin_used:
    -                    raise Exception("Unexpect margin used!")
    -
    -
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            if security.type == SecurityType.INDEX_OPTION:
    -                # Historical data
    -                history = self.history(security.symbol, 10, Resolution.MINUTE)
    -
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _optionSymbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(200000);
    -        // Asynchronous can use computational resources efficiently
    -        UniverseSettings.Asynchronous = true;
    -        // Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    -        var option = AddIndexOption("SPX");
    -        option.SetFilter((u) => u.CallsOnly().Strikes(-2, +2).Expiration(0, 180));
    -        _optionSymbol = option.Symbol;
    -    }
    -    
    -    public override void OnData(Slice slice)
    -    {
    -        if (!Portfolio.Invested && IsMarketOpen(_optionSymbol))
    -        {
    -            // Make sure getting the updated VIX option chain
    -            if (slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    -            {
    -                var expiry = chain.Max(x => x.Expiry);
    -                var callContracts = chain
    -                    .Where(x => x.Expiry == expiry)
    -                    .OrderBy(x => x.Strike)
    -                    .ToList();
    -
    -                // Need 2 contracts to form a call spread
    -                if (callContracts.Count < 2)
    -                {
    -                    return;
    -                }
    -
    -                // Obtain 2 call contracts with different strike price to form the call spread
    -                var longCall = callContracts.First();
    -                var shortCall = callContracts.First(contract => contract.Strike > longCall.Strike);
    -
    -                // Use all the buying power, but need to ensure the order size of the long and short call are the same
    -                var quantity = new[] {
    -                    CalculateOrderQuantity(shortCall.Symbol, -1m),
    -                    CalculateOrderQuantity(longCall.Symbol, 1m) }
    -                    .Min(x=> Math.Abs(x));
    -                if (quantity == 0) return;
    -
    -                // Bull call spread consists of long a lower-strike call and short a higher-strike call
    -                MarketOrder(shortCall.Symbol, -quantity);
    -                MarketOrder(longCall.Symbol, quantity);
    -
    -                var expectedMarginUsage = Math.Max((longCall.Strike - shortCall.Strike) * Securities[longCall.Symbol].SymbolProperties.ContractMultiplier * quantity, 0);
    -                if (expectedMarginUsage != Portfolio.TotalMarginUsed)
    -                {
    -                    throw new Exception("Unexpect margin used!");
    -                }
    -            }
    -        }
    -    }
    -
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            if (security.Type == SecurityType.IndexOption)
    -            {
    -                // Historical data
    -                var history = History(security.Symbol, 10, Resolution.Minute);
    -            }
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm buys the VIX Index Option Bull Call Spread with the furthest expiration: -

    -
    -
    from AlgorithmImports import *
    -
    -class IndexOptionsDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(200000)
    -        self.universe_settings.asynchronous = True
    -        self.set_universe_selection(VIXIndexOptionUniverseSelectionModel())
    -
    -        self.set_alpha(BullCallSpreadAlphaModel())
    -
    -        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    -
    -
    -class VIXIndexOptionUniverseSelectionModel(OptionUniverseSelectionModel):
    -
    -    def __init__(self):
    -        super().__init__(timedelta(1), self.option_chain_symbol_selector)
    -    
    -    def option_chain_symbol_selector(self, utc_time: datetime) -> List[Symbol]:
    -        # Only interest in VIX options
    -        return [Symbol.create("VIX", SecurityType.INDEX_OPTION, Market.USA)]
    -
    -    def filter(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
    -        # Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    -        return option_filter_universe.calls_only().strikes(-2, +2).expiration(0, 180)
    -
    -
    -class BullCallSpreadAlphaModel(AlphaModel):
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        if algorithm.portfolio.invested:
    -            return []
    -            
    -        for canonical_symbol, chain in slice.option_chains.items():
    -            if not chain:
    -                return []
    -            # Bull call spread legs are having the same expiry                  
    -            expiry = max([c.expiry for c in chain])
    -            call_contracts = sorted([c for c in chain if c.expiry == expiry],
    -                key=lambda c: c.strike)
    -
    -            # Need 2 contracts to form a call spread
    -            if len(call_contracts) < 2:
    -                return []
    -
    -            # Obtain 2 call contracts with different strike price to form the call spread
    -            long_call, short_call = call_contracts[0:2]
    -            
    -            # Bull call spread consists of long a lower-strike call and short a higher-strike call
    -            return Insight.group(
    -                [
    -                    Insight.price(long_call.symbol, expiry + timedelta(1), InsightDirection.UP),
    -                    Insight.price(short_call.symbol, expiry + timedelta(1), InsightDirection.DOWN)
    -                ])
    -        return []
    -        
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            if security.type == SecurityType.INDEX_OPTION:
    -                # Historical data
    -                history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    -
    -
    -class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    -
    -    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    -        if not insights:
    -            return []
    -        # Only a single contract toi ensure both legs size is equal
    -        quantity = min([abs(algorithm.calculate_order_quantity(i.symbol, int(i.direction)))
    -            for i in insights])
    -    
    -        return [PortfolioTarget(i.symbol, quantity * int(i.direction))
    -            for i in insights]
    -
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    -{
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(200000);
    -        UniverseSettings.Asynchronous = true;
    -        SetUniverseSelection(new VIXIndexOptionUniverseSelectionModel());
    -
    -        SetAlpha(new BullCallSpreadAlphaModel());
    -
    -        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    -    }
    -}
    -
    -public class VIXIndexOptionUniverseSelectionModel : OptionUniverseSelectionModel
    -{
    -    // Only interest in VIX options
    -    public VIXIndexOptionUniverseSelectionModel()
    -        : base(TimeSpan.FromDays(1), 
    -            _ => new[] {QuantConnect.Symbol.Create("VIX", SecurityType.IndexOption, Market.USA)})
    -    {
    -    }
    -
    -    protected override OptionFilterUniverse Filter(OptionFilterUniverse optionFilterUniverse)
    -    {
    -        // Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    -        return optionFilterUniverse.CallsOnly().Strikes(-2, +2).Expiration(0, 180);
    -    }
    -}
    -
    -public class BullCallSpreadAlphaModel : AlphaModel
    -{
    -    public BullCallSpreadAlphaModel()
    -    {
    -    }
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = Enumerable.Empty<Insight>();
    -        if (algorithm.Portfolio.Invested)
    -        {
    -            return insights;
    -        }
    -            
    -        foreach (var kvp in slice.OptionChains)
    -        {
    -            var canoncialSymbol = kvp.Key;
    -            var chain = kvp.Value;
    -            if (chain.IsNullOrEmpty())
    -            {
    -                return insights;
    -            }
    -            // Bull call spread legs are having the same expiry
    -            var expiry = chain.Max(contract => contract.Expiry);
    -            var callContracts = chain
    -                .Where(contract => contract.Expiry == expiry)
    -                .OrderBy(x => x.Strike)
    -                .ToList();
    -
    -            // Need 2 contracts to form a call spread
    -            if (callContracts.Count < 2)
    -            {
    -                return insights;
    -            }
    -
    -            // Obtain 2 call contracts with different strike price to form the call spread
    -            var longCall = callContracts.First();
    -            var shortCall = callContracts.First(contract => contract.Strike > longCall.Strike);
    -
    -            // Bull call spread consists of long a lower-strike call and short a higher-strike call
    -            return Insight.Group(
    -                Insight.Price(longCall.Symbol, expiry.AddDays(1), InsightDirection.Up),
    -                Insight.Price(shortCall.Symbol, expiry.AddDays(1), InsightDirection.Down));
    -        }
    -        return insights;
    -    }
    -}
    -    
    -public class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    -{
    -    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    -    {
    -        if (insights.Count() == 0)
    -        {
    -            return Enumerable.Empty<PortfolioTarget>();
    -        }
    -        // Only a single contract toi ensure both legs size is equal
    -        var quantity = insights
    -            .Select(i => Math.Abs(algorithm.CalculateOrderQuantity(i.Symbol, (decimal)i.Direction)))
    -            .Min();
    -
    -        return insights.Select(i => new PortfolioTarget(i.Symbol, quantity * (decimal)i.Direction));
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Index Options dataset provides - - TradeBar - - , - - QuoteBar - - , and - - OpenInterest - - objects. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - OpenInterest Attributes -

    -

    - - OpenInterest - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    Datasets

    -

    Morningstar

    -
    -
    - - -
    -
    -

    - Morningstar was founded by Joe Mansueto in 1984 with the goal of empowering investors by connecting people to the investing information and tools they need. Morningstar provides access extensive line of products and services for individual investors, financial advisors, asset managers, and retirement plan providers. Morningstar provides data on approximately 525,000 investment offerings including stocks, mutual funds, and similar vehicles, along with real-time global market data on nearly 18 million equities, indexes, futures, options, commodities, and precious metals, in addition to foreign exchange and Treasury markets. Morningstar also offers investment management services through its investment advisory subsidiaries, with $244 billion in assets under advisement or management as of 2021. -

    -
    - -
    - - - -

     

    - -
    -
    -

    Morningstar

    -

    US Fundamental Data

    -
    -
    -

    Introduction

    - - -

    - The US Fundamental Data by Morningstar tracks US Equity fundamentals. The data covers 8,000 US Equities, starts in January 1998, and is delivered on a daily frequency. The data does not include ETFs, ADRs, or OTC equities. This dataset is created by using a combination of string matching, Regular Expressions, and Machine Learning to gather the fundamental data published by companies. -

    -

    - For older symbols, the file date is approximated 45 days after the as of date. When a filing date is present on the Morningstar data, it is used. As we are a quant platform, all the data is loaded using "As Original Reported" figures. If there was a mistake reporting the figure, this will not be fixed later. The market typically responds quickly to these initially reported figures. Data is available for multiple periods depending on the property. Periods available include: 1 mo, 2 mo, 3 mo, 6 mo, 9 mo, 12 mo, 1 Yr, 2 Yr, 3 Yr, and 5 Yr. Morningstar symbols cover the NYSE, NASDAQ, AMEX, and BATS exchanges. -

    -

    - In live trading, Morningstar data is delivered to your algorithm at approximately 6 am each day. The majority of the fundamental data update occurs once per month. This includes updates to all of the key information for each security Morningstar supports. On top of this monthly update, there are daily updates of the financial ratios. -

    -

    - As Morningstar data arrives, it updates the master copy and is passed into your algorithm, similar to how TradeBars are fill-forwarded in your data feed. If there have been no updates for a day, you'll receive the same fundamental data. -

    -

    - This dataset depends on the - - US Equity Security Master - - dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. -

    -

    - QuantConnect/LEAN combines the data of this dataset with - - US Coarse Universe - - data in runtime. -

    -

    - For more information about the US Fundamental Data dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - Morningstar was founded by Joe Mansueto in 1984 with the goal of empowering investors by connecting people to the investing information and tools they need. Morningstar provides access extensive line of products and services for individual investors, financial advisors, asset managers, and retirement plan providers. Morningstar provides data on approximately 525,000 investment offerings including stocks, mutual funds, and similar vehicles, along with real-time global market data on nearly 18 million equities, indexes, futures, options, commodities, and precious metals, in addition to foreign exchange and Treasury markets. Morningstar also offers investment management services through its investment advisory subsidiaries, with $244 billion in assets under advisement or management as of 2021. -

    - - - -

    Getting Started

    - - -

    - The following snippets demonstrate how to request data from the US Fundamental dataset: -

    -
      -
    • - Direct Access using the Security object -
    • -
    -
    -
    equity = self.add_equity("IBM")
    -ibm_fundamental = equity.fundamentals
    -
    var equity = AddEquity("IBM");
    -var ibmFundamental = equity.Fundamentals;
    -
    -
      -
    • - Direct Access using the Symbol object -
    • -
    -
    -
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    -ibm_fundamental = self.fundamentals(ibm)
    -
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    -var ibmFundamental = Fundamentals(ibm);
    -
    -
      -
    • - Universe Selection -
    • -
    -
    -
    def initialize(self) -> None:
    -    self._universe = self.add_universe(self.fundamental_filter_function)
    -
    -def fundamental_filter_function(self, fundamental: List[Fundamental]):
    -    filtered = [f for f in fundamental if f.has_fundamental_data and f.price > 10 and not np.isnan(f.valuation_ratios.pe_ratio)]
    -    sorted_by_pe_ratio = sorted(filtered, key=lambda f: f.valuation_ratios.pe_ratio)
    -    return [f.symbol for f in sorted_by_pe_ratio[:10]]
    -
    public override void Initialize()
    -{
    -    _universe = AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    -}
    -
    -public override List<Symbol> FundamentalFilterFunction(List<Fundamental> fundamental)
    -{
    -    return (from f in fundamental
    -            where f.HasFundamentalData && f.Price > 10 && !Double.IsNaN(f.ValuationRatios.PERatio)
    -            orderby f.ValuationRatios.PERatio
    -            select f.Symbol).Take(10);
    -}
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - January 1998 -
    - Asset Coverage - - 8,000 US Equities - - * - -
    - Corporate Indicators / Tracked Fields - - 900 Fields -
    - Data Density - - Sparse -
    - Resolution - - Daily -
    - Timezone - - New York -
    - - * - - The data does not include ETFs, ADRs, or OTC equities. - - - -

    Requesting Data

    - - -

    - You don't need any special code to request US Fundamental Data. You can access the current and historical fundamental data for any of the US Equities that this dataset includes. -

    -
    -
    class MorningStarDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2021, 1, 1)
    -        self.set_end_date(2021, 7, 1)
    -        self.set_cash(100000) 
    -        self.universe_settings.asynchronous = True
    -
    -        # Option 1: Subscribe to individual US Equity assets
    -        self.add_equity("IBM")        
    -
    -        # Option 2A: Create a fundamental universe (classic version)
    -        self._universe = self.add_universe(self.fundamental_function)
    -
    -        # Option 2B: Create a fundamental universe (framework version)
    -        self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_function))
    -
    public class MorningStarDataAlgorithm : QCAlgorithm
    -{
    -    private Universe _universe;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2021, 1, 1);
    -        SetEndDate(2021, 7, 1);
    -        SetCash(100000);
    -        UniverseSettings.Asynchronous = true;
    -        
    -        // Option 1: Subscribe to individual US Equity assets
    -        AddEquity("IBM");
    -
    -        // Option 2A: Create a fundamental universe (classic version)
    -        _universe = AddUniverse(FundamentalFilterFunction);
    -
    -        // Option 2B: Create a fundamental universe (framework version)
    -        AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    -    }
    -}
    -
    -

    - For more information about universe settings, see - - Settings - - . -

    - - - -

    Accessing Data

    - - -

    - If you add a - - fundamental universe - - to your algorithm, you can access fundamental data in the universe selection function. -

    -
    -
    def fundamental_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -    return [f.symbol for f in fundamental if f.price > 10 and f.valuation_ratios.pe_ratio > 30]
    -
    public IEnumerable<Symbol> FundamentalFunction(IEnumerable<Fundamental> fundamental)
    -{
    -    return fundamental.Where(f => f.Price > 10 && f.ValuationRatios.PERatios > 30).Select(f => f.Symbol);
    -}
    -
    -

    - To get fundamental data for Equities in your algorithm, use the - - Fundamentals - - - fundamentals - - property of the - - Equity - - objects. The fundamental data represent the corporate fundamentals for the current algorithm time. -

    -
    -
    fundamentals = self.securities[symbol].fundamentals
    -
    var fundamentals = Securities[symbol].Fundamentals;
    -
    -

    - To get fundamental data for Equities, regardless of whether or not you have subscribed to them in your algorithm, call the - - Fundamentals - - - fundamentals - - method. If you pass one - - Symbol - - , the method returns a - - Fundamental - - object. If you pass a list of - - Symbol - - objects, the method returns a list of - - Fundamental - - objects. -

    -
    -
    // Single asset 
    -var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    -var ibmFundamental = Fundamentals(ibm);
    -
    -// Multiple assets
    -var nb = QuantConnect.Symbol.Create("NB", SecurityType.Equity, Market.USA);
    -var fundamentals = Fundamentals(new List<Symbol>{ nb, ibm }).ToList();
    -
    # Single asset
    -ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    -ibm_fundamental = self.fundamentals(ibm)
    -
    -# Multiple assets
    -nb = Symbol.create("NB", SecurityType.EQUITY, Market.USA)
    -fundamentals = self.fundamentals([ nb, ibm ])
    -
    - - - -

    Historical Data

    - - -

    - You can get historical fundamental data in an algorithm and in the Research Environment. -

    -

    - Historical Data in Algorithms -

    -

    - To get historical fundamental data in an algorithm, call the - - History - - - history - - method with - - Fundamental - - type and the Equity - - Symbol - - or the - - Universe - - object. If there is no data in the period you request, the history result is empty. -

    -
    -
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    -
    -// Fundamental objects
    -var fundamentalHistory = History<Fundamental>(ibm, TimeSpan.FromDays(30));
    -
    -// Fundamentals objects for all US Equities (including delisted companies)
    -var fundamentalsHistory = History<Fundamentals>(TimeSpan.FromDays(30));
    -
    -// Collection of Fundamental objects for all US Equities (including delisted companies)
    -var collectionHistory = History(_universe, 30, Resolution.Daily);
    -foreach (var fundamental in collectionHistory)
    -{
    -    // Cast to Fundamental is required
    -    var highestMarketCap = fundamental.OfType<Fundamental>().OrderByDescending(x => x.MarketCap).Take(5);
    -}
    -
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    -
    -# DataFrame object where the columns are the Fundamental attributes
    -asset_df_history = self.history(Fundamental, ibm, timedelta(30), flatten=True)
    -
    -# Fundamental objects
    -fundamental_history= self.history[Fundamental](ibm, timedelta(30))
    -
    -# Fundamentals objects for all US Equities (including delisted companies)
    -fundamentals_history = self.history[Fundamentals](timedelta(30))
    -
    -# Multi-index Series objects where the values are lists of Fundamental objects
    -series_history = self.history(self.universe, 30, Resolution.DAILY)
    -for (universe_symbol, time), fundamentals in series_history.items():
    -    highest_market_cap = sorted(fundamentals, key=lambda x: x.market_cap)[-5:]
    -
    -

    - Historical Data in the Research Environment -

    -

    - To get historical data in the Research Environment, call any of the preceding methods or call the - - UniverseHistory - - - universe_history - - method with the - - Universe - - object, a start date, and an end date. This method returns the filtered universe. Alternatively, call the - - GetFundamental - - - get_fundamental - - method with the Equity - - Symbol - - , a - - Fundamental - - property, a start date, and an end date. If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame object where the columns are the Fundamental attributes
    -universe_history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    -
    -# Multi-index Series objects where the values are lists of Fundamental objects
    -universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (universe_symbol, time), fundamentals in universe_history.items():
    -    for fundamental in fundamentals:
    -        print(f"{fundamental.symbol} market cap at {fundamental.end_time}: {fundamental.market_cap}")
    -
    -# DataFrame of a single Fundamental attribute
    -history = qb.get_fundamental(symbol, "ValuationRatios.pe_ratios", datetime(2021, 1, 1), datetime(2021, 7, 1))
    -
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var fundamentals in universeHistory)
    -{
    -    foreach (Fundamental fundamental in fundamentals)
    -    {
    -        Console.WriteLine($"{fundamental.Symbol} market cap at {fundamental.EndTime}: {fundamental.MarketCap}");
    -    }
    -}
    -
    -var history = qb.GetFundamental(symbol, "ValuationRatios.PERatios", new DateTime(2021, 1, 1), new DateTime(2021, 7, 1));
    -
    -

    - For more information about historical US Equity fundamental data, see - - Equity Fundamental Data - - . -

    - - - -

    Example Applications

    - - -

    - The US Fundamentals dataset enables you to design strategies harnessing fundamental data points. Examples include the following strategies: -

    -
      -
    • - Ranking a universe of securities by a value factor like the - - Piotroski F-score - - and buying a subset of the universe with the best factor ranking -
    • -
    • - Using the Morningstar asset classification to target specific industries or to ensure your strategy is diversified across several sectors -
    • -
    • - Trading securities that recently performed an IPO -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm creates a dynamic universe of US Equities. The first stage filter selects the 100 most liquid US Equities and the second stage filter selects the 10 assets with the greatest PE ratio. The algorithm then forms an equal-weighted portfolio with the 10 assets in the universe. -

    -
    -
    from AlgorithmImports import *
    -
    -class MorningStarDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000) 
    -        # Seed the price of each asset with its last known price to avoid trading errors.
    -        self.settings.seed_initial_prices = True
    -        self.universe_settings.resolution = Resolution.DAILY
    -        self.universe_size = 10
    -        # Add universe selection to filter with fundamental data
    -        self.add_universe(self.fundamental_selection_function)
    -        
    -    def fundamental_selection_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    -        # Make sure fundamental data and PE ratio available 
    -        # To avoid penny stocks with high volatility, set price above $1
    -        selected = [f for f in fundamental if f.has_fundamental_data and f.price > 1 and not np.isnan(f.valuation_ratios.pe_ratio)]
    -        # Filter the top 100 high dollar volume equities to ensure liquidity
    -        sorted_by_dollar_volume = sorted(selected, key=lambda f: f.dollar_volume, reverse=True)[:100]
    -        # Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    -        sorted_by_pe_ratio = sorted(sorted_by_dollar_volume, key=lambda f: f.valuation_ratios.pe_ratio, reverse=True)[:self.universe_size]
    -        return [ f.symbol for f in sorted_by_pe_ratio ]
    -        
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # if we have no changes, do nothing
    -        if self._changes is None or not slice.bars: return
    -
    -        # liquidate removed securities, as not being the most popular stocks anymore
    -        for security in self._changes.removed_securities:
    -            if security.invested:
    -                self.liquidate(security.symbol)
    -
    -        # we want 1/N allocation in each security in our universe to evenly dissipate risk
    -        for security in self._changes.added_securities:
    -            self.set_holdings(security.symbol, 1 / self.universe_size)
    -
    -        self._changes = None
    -           
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        self._changes = changes
    -
    -
    public class MorningStarDataAlgorithm : QCAlgorithm
    -{
    -    private int _universeSize = 10;
    -    private SecurityChanges _changes = SecurityChanges.None;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        // Seed the price of each asset with its last known price to avoid trading errors.
    -        Settings.SeedInitialPrices = true;
    -        // Requesting data
    -        UniverseSettings.Resolution = Resolution.Daily;
    -        // Add universe selection to filter with fundamental data
    -        AddUniverse(FundamentalSelectionFunction);
    -    }
    -
    -    public IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamental)
    -    {
    -        // Make sure fundamental data and PE ratio available 
    -        // To avoid penny stocks with high volatility, set price above $1
    -        // Filter the top 100 high dollar volume equities to ensure liquidity
    -        // Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    -        return fundamental
    -            .Where(x => x.HasFundamentalData && x.Price > 1 && !Double.IsNaN(x.ValuationRatios.PERatio))
    -            .OrderByDescending(x => x.DollarVolume)
    -            .Take(100)
    -            .OrderByDescending(x => x.ValuationRatios.PERatio)
    -            .Take(_universeSize)
    -            .Select(x => x.Symbol);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // if we have no changes, do nothing
    -        if (_changes == SecurityChanges.None || slice.Bars.Count == 0) return;
    -
    -        // liquidate removed securities, as not being the most popular stocks anymore
    -        foreach (var security in _changes.RemovedSecurities)
    -        {
    -            if (security.Invested)
    -            {
    -                Liquidate(security.Symbol);
    -            }
    -        }
    -
    -        // we want 1/N allocation in each security in our universe to evenly dissipate risk
    -        foreach (var security in _changes.AddedSecurities)
    -        {
    -            SetHoldings(security.Symbol, 1m / _universeSize);
    -        }
    -
    -        _changes = SecurityChanges.None;
    -    }
    -    
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    -    {
    -        _changes = changes;
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm creates a dynamic universe of US Equities. The first stage filter selects the 100 most liquid US Equities and the second stage filter selects the 10 assets with the greatest PE ratio. The algorithm then forms an equal-weighted portfolio with the 10 assets in the universe. -

    -
    -
    from AlgorithmImports import *
    -
    -class MorningStarDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000) 
    -
    -        # Add universe selection to filter with fundamental data
    -        self.universe_settings.resolution = Resolution.DAILY
    -        self.set_universe_selection(CustomFundamentalUniverseSelectionModel())
    -
    -        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(1)))
    -
    -        # we want 1/N allocation in each security in our universe to evenly dissipate risk
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -
    -        self.add_risk_management(NullRiskManagementModel())
    -
    -        self.set_execution(ImmediateExecutionModel())
    -
    -
    -class CustomFundamentalUniverseSelectionModel(FundamentalUniverseSelectionModel):
    -
    -    def select(self, algorithm: QCAlgorithm, fundamental: List[Fundamental]) -> List[Symbol]:
    -        # Make sure fundamental data and PE ratio available 
    -        # To avoid penny stocks with high volatility, set price above $1
    -        # Filter the top 100 high dollar volume equities to ensure liquidity
    -        sorted_by_dollar_volume = sorted([x for x in fundamental if x.price > 1 and not np.isnan(x.valuation_ratios.pe_ratio)],
    -            key=lambda x: x.dollar_volume, reverse=True)[:100]
    -        # Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    -        sorted_by_pe_ratio = sorted(sorted_by_dollar_volume, key=lambda x: x.valuation_ratios.pe_ratio, reverse=True)[:10]
    -
    -        # Take the top entries from our sorted collection
    -        return [ x.symbol for x in sorted_by_pe_ratio ]
    -
    public class MorningStarDataAlgorithm : QCAlgorithm
    -{        
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        
    -        // Add universe selection to filter with fundamental data
    -        UniverseSettings.Resolution = Resolution.Daily;
    -        AddUniverseSelection(new CustomFundamentalUniverseSelectionModel());
    -        
    -        SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)));
    -
    -        // we want 1/N allocation in each security in our universe to evenly dissipate risk
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -        
    -        AddRiskManagement(new NullRiskManagementModel());
    -        
    -        SetExecution(new ImmediateExecutionModel());
    -    }
    -}
    -
    -public class CustomFundamentalUniverseSelectionModel : FundamentalUniverseSelectionModel
    -{
    -    public override IEnumerable<Symbol> Select(QCAlgorithm algorithm, IEnumerable<Fundamental> fundamental)
    -    {
    -        return fundamental
    -            // Make sure fundamental data and PE ratio available 
    -            // To avoid penny stocks with high volatility, set price above $1
    -            .Where(x => x.HasFundamentalData && x.Price > 1 && !Double.IsNaN(x.ValuationRatios.PERatio))
    -            // Filter the top 100 high dollar volume equities to ensure liquidity
    -            .OrderByDescending(x => x.DollarVolume)
    -            .Take(100)
    -            // Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    -            .OrderByDescending(x => x.ValuationRatios.PERatio)
    -            .Take(10)
    -            .Select(x => x.Symbol);
    -    }
    -}
    -
    -

    - Research Example -

    -

    - The following example selects the 100 most liquid US Equities and lists the 10 assets with the greatest PE ratio.: -

    -
    -
    var qb = new QuantBook();
    -
    -// Add Fundamental Universe Selection
    -IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamentals)
    -{
    -    return fundamentals
    -        .Where(x => !Double.IsNaN(x.ValuationRatios.PERatio))
    -        .OrderByDescending(x => x.DollarVolume).Take(100)
    -        .OrderByDescending(x => x.ValuationRatios.PERatio).Take(10)
    -        .Select(x => x.Symbol);
    -}
    -
    -var universe = qb.AddUniverse(FundamentalSelectionFunction); 
    -
    -// Historical Universe data
    -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var fundamentals in universeHistory)
    -{
    -    foreach (Fundamental fundamental in fundamentals)
    -    {
    -        Console.WriteLine($"{fundamental.Symbol} PE ratio at {fundamental.EndTime}: {fundamental.ValuationRatios.PERatio}");
    -    }
    -}
    -
    qb = QuantBook()
    -
    -# Add Fundamental Universe Selection
    -def fundamental_selection_function(fundamentals):
    -    selected = [f for f in fundamentals if not np.isnan(f.valuation_ratios.pe_ratio)]
    -    sorted_by_dollar_volume = sorted(selected, key=lambda f: f.dollar_volume, reverse=True)[:100]
    -
    -    sorted_by_pe_ratio = sorted(sorted_by_dollar_volume,
    -        key=lambda f: f.valuation_ratios.pe_ratio, reverse=True)[:10]
    -    return [ f.symbol for f in sorted_by_pe_ratio ]
    -
    -universe = qb.add_universe(fundamental_selection_function)
    -
    -# Historical Universe data
    -universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (universe_symbol, time), fundamentals in universe_history.items():
    -    for fundamental in fundamentals:
    -        print(f"{fundamental.symbol} PE ratio volume at {fundamental.end_time}: {fundamental.valuation_ratios.pe_ratio}")
    -
    - - - -

    Data Point Attributes

    - - -

    - The US Fundamentals dataset provides - - Fundamental - - objects. To filter - - Fundamental - - objects, you can use the - - MorningstarSectorCode - - , - - MorningstarIndustryGroupCode - - , and - - MorningstarIndustryCode - - enumeration values. -

    -

    - Fundamental Attributes -

    -

    - - Fundamental - - objects have the following attributes: -

    -
    -
    -

    - MorningstarSectorCode Enumeration -

    -

    - Sectors are large super categories of data. To access the sector of an Equity, use the - - MorningstarSectorCode - - property. -

    -
    -
    filteredFundamentals = fundamental.Where(x =>
    -    x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Technology);
    -
    filtered_fundamentals = [x for x in fundamental
    -    if x.asset_classification.morningstar_sector_code == MorningstarSectorCode.TECHNOLOGY]
    -
    -

    - The - - MorningstarSectorCode - - enumeration has the following members: -

    -
    -
    -

    - MorningstarIndustryGroupCode Enumeration -

    -

    - Industry groups are clusters of related industries that tie together. To access the industry group of an Equity, use the - - MorningstarIndustryGroupCode - - property. -

    -
    -
    filteredFundamentals = fundamental.Where(x =>
    -    x.AssetClassification.MorningstarIndustryGroupCode == MorningstarIndustryGroupCode.Software);
    -
    filtered_fundamentals = [x for x in fundamental
    -    if x.asset_classification.morningstar_industry_group_code == MorningstarIndustryGroupCode.SOFTWARE]
    -
    -

    - The - - MorningstarIndustryGroupCode - - enumeration has the following members: -

    -
    -
    -

    - MorningstarIndustryCode Enumeration -

    -

    - Industries are the finest classification level available and are the individual industries according to the Morningstar classification system. To access the industry group of an Equity, use the - - MorningstarIndustryCode - - property. -

    -
    -
    filteredFundamentals = fundamental.Where(x =>
    -    x.AssetClassification.MorningstarIndustryCode == MorningstarIndustryCode.SoftwareApplication);
    -
    filtered_fundamentals = [x for x in fundamental
    -    if x.asset_classification.morningstar_industry_code == MorningstarIndustryCode.SOFTWARE_APPLICATION]
    -
    -

    - The - - MorningstarIndustryCode - - enumeration has the following members: -

    -
    -
    -

    - Exchange ID Values -

    -

    - The exchange ID represents the exchange that lists the Equity. To access the exchange ID of an Equity, use the - - PrimaryExchangeID - - property. -

    -
    -
    filteredFundamentals = fundamental.Where(x =>
    -    x.CompanyReference.PrimaryExchangeID == "NAS");
    -
    filtered_fundamentals = [x for x in fundamental
    -    if x.company_reference.primary_exchange_id == "NAS"]
    -
    -

    - The exchanges are represented by the following string values: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - String Representation - - Exchange -
    - NYS - - New York Stock Exchange (NYSE) -
    - NAS - - NASDAQ -
    - ASE - - American Stock Exchange (AMEX) -
    - TSE - - Tokyo Stock Exchange -
    - AMS - - Amsterdam Internet Exchange -
    - SGO - - Santiago Stock Exchange -
    - XMAD - - Madrid Stock Exchange -
    - ASX - - Australian Securities Exchange -
    - BVMF - - B3 (stock exchange) -
    - LON - - London Stock Exchange -
    - TKS - - Istanbul Stock Exchange Settlement and Custody Bank -
    - SHG - - Shanghai Exchange -
    - LIM - - Lima Stock Exchange -
    - FRA - - Frankfurt Stock Exchange -
    - JSE - - Johannesburg Stock Exchange -
    - MIL - - Milan Stock Exchange -
    - TAE - - Tel Aviv Stock Exchange -
    - STO - - Stockholm Stock Exchange -
    - ETR - - Deutsche Boerse Xetra Core -
    - PAR - - Paris Stock Exchange -
    - BUE - - Buenos Aires Stock Exchange -
    - KRX - - Korea Exchange -
    - SWX - - SIX Swiss Exchange -
    - PINX - - Pink Sheets (OTC) -
    - CSE - - Canadian Securities Exchange -
    - PHS - - Philippine Stock Exchange -
    - MEX - - Mexican Stock Exchange -
    - TAI - - Taiwan Stock Exchange -
    - IDX - - Indonesia Stock Exchange -
    - OSL - - Oslo Stock Exchange -
    - BOG - - Colombia Stock Exchange -
    - NSE - - National Stock Exchange of India -
    - HEL - - Nasdaq Helsinki -
    - MISX - - Moscow Exchange -
    - HKG - - Hong Kong Stock Exchange -
    - IST - - Istanbul Stock Exchange -
    - BOM - - Bombay Stock Exchange -
    - TSX - - Toronto Stock Exchange -
    - BRU - - Brussels Stock Exchange -
    - BATS - - BATS Global Markets -
    - ARCX - - NYSE Arca -
    - GREY - - Grey Market (OTC) -
    - DUS - - Dusseldorf Stock Exchange -
    - BER - - Berlin Stock Exchange -
    - ROCO - - Taipei Exchange -
    - CNQ - - Canadian Trading and Quotation System Inc. -
    - BSP - - Bangko Sentral ng Pilipinas -
    - NEOE - - NEO Exchange -
    - - - -

     

    - -
    -
    -

    Datasets

    -

    TickData

    -
    -
    - - -
    -
    -

    - - TickData - - was founded by a futures broker and a programmer in 1984 as the first company in the world to offer historical tick-by-tick prices on the futures and index markets. TickData provides access to comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cash Indices. -

    -
    - -
    - - - -

     

    - -
    -
    -

    TickData

    -

    International Futures

    -
    -
    -

    Introduction

    - - -

    - The International Futures dataset by TickData provides Futures data, including price, volume, open interest, and expiry. The data covers the 4 contracts, DAX, FESX, HSI, and NKD, starting in July 1998 and is delivered on any frequency from tick to daily. This dataset is created by TickData, which negotiates directly with exchanges for their official archive and partners with real-time data providers with direct exchange connections and multiple redundant ticker plants. -

    -

    - This dataset also depends on the - - US Futures Security Master - - because the US Futures Security Master dataset contains information to construct continuous Futures. -

    -

    - For more information about the International Futures dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - - TickData - - was founded by a futures broker and a programmer in 1984 as the first company in the world to offer historical tick-by-tick prices on the futures and index markets. TickData provides access to comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cash Indices. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the International Futures dataset: -

    -
    -
    hsi = self.add_future(Futures.Indices.HANG_SENG, Resolution.MINUTE).symbol           # "HSI"
    -dax = self.add_future(Futures.Indices.DAX, Resolution.MINUTE).symbol                 # "DAX"
    -fesx = self.add_future(Futures.Indices.EURO_STOXX_50, Resolution.MINUTE).symbol      # "FESX"
    -nkd = self.add_future(Futures.Indices.NIKKEI_225_DOLLAR, Resolution.MINUTE).symbol   # "NKD"
    -
    var hsi= AddFuture(Futures.Indices.HangSeng, Resolution.Minute).Symbol           // "HSI";
    -var dax = AddFuture(Futures.Indices.Dax, Resolution.Minute).Symbol               // "DAX";
    -var fesx = AddFuture(Futures.Indices.EuroStoxx50, Resolution.Minute).Symbol      // "FESX";
    -var nkd = AddFuture(Futures.Indices.Nikkei225Dollar, Resolution.Minute).Symbol   // "NKD";
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - July 1998, see - - Supported Assets - - below for details -
    - Coverage - - 4 Contracts -
    - Data Density - - Dense -
    - Resolution - - Minute, Hour, & Daily -
    - Timezone - - Various, refer to - - Supported Assets - - below -
    - Market Hours - - - Regular and Extended - -
    - - - -

    Volume Discrepancies

    - - - For Futures contracts trading in the US, for example, NKD, see - - US Futures - - . - - - -

    Requesting Data

    - - -

    - To add International Futures data to your algorithm, call the - - AddFuture - - - add_future - - method. Save a reference to the Future so you can access the data later in your algorithm. -

    -
    -
    class InternationalFuturesDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2013, 12, 20) 
    -        self.set_end_date(2014, 2, 20) 
    -        self.set_cash(1000000) 
    -        self.universe_settings.asynchronous = True
    -        # Request Hang Seng Index Futures data
    -        future = self.add_future(Futures.Indices.HANG_SENG) 
    -        # Set filter to obtain the contracts expire within 90 days
    -        future.set_filter(0, 90)
    -        self.future_symbol = future.symbol
    -
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _futureSymbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2013, 12, 20);
    -        SetEndDate(2014, 2, 20);
    -        SetCash(1000000);
    -        UniverseSettings.Asynchronous = true;
    -        // Request Hang Seng Index Futures data
    -        var future = AddFuture(Futures.Indices.HangSeng);
    -        // Set filter to obtain the contracts expire within 90 days
    -        future.SetFilter(0, 90);
    -        _futureSymbol = future.Symbol;
    -    }
    -}
    -
    -

    - For more information about creating Future subscriptions, see - - Requesting Data - - or - - Futures Universes - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current International Futures data, index the - - FuturesChains - - - futures_chains - - property of the current - - - Slice - - - with the canonical Futures - - Symbol - - . Slice objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your Future at every time step. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Get future chain of the canonical symbol
    -    chain = slice.futures_chains.get(self.future_symbol)
    -    if chain:
    -        # Iterate each contract in the future chain
    -        for contract in chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    -
    public override void OnData(Slice slice)
    -{
    -    // Get future chain of the canonical symbol
    -    if (slice.FuturesChains.TryGetValue(_futureSymbol, out var chain))
    -    {
    -        // Iterate each contract in the future chain
    -        foreach (var contract in chain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - You can also iterate through all of the - - FuturesChain - - objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    # Iterate all future chains
    -    for canonical_symbol, chain in slice.futures_chains.items():
    -        # Iterate each contract in the future chain
    -        for contract in chain:
    -            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    -
    public override void OnData(Slice slice)
    -{
    -    // Iterate all future chains
    -    foreach (var kvp in slice.FuturesChains)
    -    {
    -        var canonicalSymbol = kvp.Key;
    -        var chain = kvp.Value;
    -        // Iterate each contract in the future chain
    -        foreach (var contract in chain)
    -        {
    -            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    -        }
    -    }
    -}
    -
    -

    - For more information about accessing Futures data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - You can get historical International Futures data in an algorithm and the Research Environment. -

    -

    - Historical Data In Algorithms -

    -

    - To get historical International Futures data in an algorithm, call the - - History - - - history - - method with the canonical Futures - - Symbol - - or a Futures contract - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame objects
    -contract_history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    -continuous_history_df = self.history(self.future_symbol,
    -    start=self.time - timedelta(days=15), 
    -    end=self.time, 
    -    resolution=Resolution.MINUTE, 
    -    fill_forward=False, 
    -    extended_market_hours=False,
    -    data_mapping_mode=DataMappingMode.OPEN_INTEREST, 
    -    data_normalization_mode=DataNormalizationMode.RAW, 
    -    contract_depth_offset=0)
    -
    -# TradeBar objects
    -contract_history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    -continous_history_trade_bars = self.history[TradeBar](self.future_symbol, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -contract_history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    -continous_history_quote_bars = self.history[QuoteBar](self.future_symbol, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -contract_history_ticks = self.history[Tick](contract.symbol, timedelta(seconds=10), Resolution.TICK)
    -continous_history_ticks = self.history[Tick](self.future_symbol, timedelta(seconds=10), Resolution.TICK)
    -
    // TradeBar objects
    -var contractHistoryTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    -var continuousHistoryTradeBars = History(
    -    symbols: new[] {_futureSymbol}, 
    -    start: Time - TimeSpan.FromDays(15),
    -    end: Time,
    -    resolution: Resolution.Minute,
    -    fillForward: false,
    -    extendedMarketHours: false,
    -    dataMappingMode: DataMappingMode.OpenInterest,
    -    dataNormalizationMode: DataNormalizationMode.Raw,
    -    contractDepthOffset: 0);
    -
    -// QuoteBar objects
    -var contractHistoryQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    -var continuousHistoryQuoteBars = History<QuoteBar>(_futureSymbol, 100, Resolution.Minute);
    -
    -// Tick objects
    -var contractHistoryTicks = History<Tick>(contract.Symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -var continuousHistoryTicks = History<Tick>(_futureSymbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -
    -

    - For more information about historical data in algorithms, see - - History Requests - - . For more information about the price adjustments for continuous contracts, see - - Continous Contracts - - . -

    -

    - Historical Data In Research -

    -

    - To get historical International Futures data in the Research Environment for an entire Futures chain, call the - - FutureHistory - - - future_history - - method with the canonical Future - - Symbol - - . -

    -
    -
    qb = QuantBook()
    -future = qb.add_future(Futures.Indices.HANG_SENG) 
    -future.set_filter(0, 90)
    -history = qb.future_history(future.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    -history_df = history.data_frame
    -all_history = history.get_all_data()
    -expiries = history.get_expiry_dates()
    -
    var qb = new QuantBook();
    -var future = qb.AddFuture(Futures.Indices.HangSeng);
    -future.SetFilter(0, 90);
    -var history = qb.FutureHistory(future.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    -    
    -var contracts = history.SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys)).Distinct().ToList();
    -var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    -
    -

    - To get historical data for a single International Futures contract or the continuous Futures contract, call the - - History - - - history - - method like you would in an algorithm but on the - - QuantBook - - object. For more information about historical data in the Research Environment, see - - Futures - - . -

    - - - -

    Supported Assets

    - - -

    - The following table shows the available Futures: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Ticker - - Future - - Start Date - - Time Zone - - Currency -
    - HSI - - Hang Seng Index Futures - - Jan 2010 - - Asia/Hong Kong - - HKD -
    - DAX - - German Index Futures - - Jan 2010 - - Europe/Berlin - - EUR -
    - FESX - - EURO STOXX 50 Index Futures - - Jul 1998 - - Europe/Berlin - - EUR -
    - NKD - - Nikkei 225 Index Futures - - Jan 2007 - - America/Chicago - - USD -
    - - - -

    Example Applications

    - - -

    - The International Futures dataset enables you to design Futures strategies accurately. Examples include the following strategies: -

    -
      -
    • - Buying the Futures contract with the most open interest to reduce slippage and market impact -
    • -
    • - Trade speculation on an International Index -
    • -
    • - Trading bull calendar spreads to reduce volatility and margin requirements -
    • -
    -

    - Classic Algorithm Example -- HSI Futures -

    -

    - The following example algorithm uses - - ZigZag - - to determine the trend of Hang Seng Index. To trade the Indices, we make use of the HSI Futures. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class InternationalFuturesDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Set the time zone to HKT to make it more comparable with the exchange.
    -        self.set_time_zone(TimeZones.HONG_KONG)
    -        # Set the account currency as HKD to trade HSI Futures.
    -        self.set_account_currency("HKD", 1000000)
    -        # Seed the last price of the contracts for filling.
    -        self.settings.seed_initial_prices = True
    -
    -        # Request HSI Futures to trade. 
    -        # Note that we will trade the contract with the highest open interest for liquidity.
    -        self.hsi_future = self.add_future(
    -            Futures.Indices.HANG_SENG,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
    -            contract_depth_offset=0
    -        )
    -        # Request the corresponding underlying Index for feeding indicator for trade signal generation.
    -        hsi_index = self.add_index("HSI").symbol
    -
    -        # Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    -        self._zz = self.zz(hsi_index, 0.15, 5, Resolution.DAILY)
    -        # Warm up indicator for immediate readiness to trade.
    -        self.warm_up_indicator(hsi_index, self._zz, Resolution.DAILY)
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    -        if self.is_market_open(self.hsi_future.symbol) and self._zz.is_ready:
    -            pivot = self._zz.pivot_type
    -            # If the last pivot point is a low point, the current trend is increasing after this low point.
    -            if pivot == PivotPointType.LOW and not self.portfolio[self.hsi_future.symbol].is_long:
    -                self.set_holdings(self.hsi_future.mapped, 0.2)
    -            # If the last pivot point is a high point, the current trend is decreasing after this high point.
    -            elif pivot == PivotPointType.HIGH and not self.portfolio[self.hsi_future.symbol].is_short:
    -                self.set_holdings(self.hsi_future.mapped, -0.2)
    -
    -        # Handle rollover in case the current mapped contract changes.
    -        for _, changed_event in slice.symbol_changed_events.items():
    -            old_symbol = changed_event.old_symbol
    -            new_symbol = self.add_future_contract(changed_event.new_symbol).symbol
    -            quantity = self.portfolio[old_symbol].quantity
    -            # Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    -            self.liquidate(old_symbol)
    -            if quantity != 0:
    -                self.market_order(new_symbol, quantity)
    -
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Future _hsiFuture;
    -    private ZigZag _zz;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Set the time zone to HKT to make it more comparable with the exchange.
    -        SetTimeZone(TimeZones.HongKong);
    -        // Set the account currency as HKD to trade HSI Futures.
    -        SetAccountCurrency("HKD", 1000000);
    -
    -        // Seed the last price of the contracts for filling.
    -        Settings.SeedInitialPrices = true;
    -
    -        // Request HSI Futures to trade. 
    -        // Note that we will trade the contract with the highest open interest for liquidity.
    -        _hsiFuture = AddFuture(
    -            Futures.Indices.HangSeng,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.LastTradingDay,
    -            contractDepthOffset: 0
    -        );
    -        // Request the corresponding underlying index for feeding indicators for trade signal generation.
    -        var hsiIndex = AddIndex("HSI").Symbol;
    -
    -        // Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    -        _zz = ZZ(hsiIndex, 0.15m, 5, Resolution.Daily);
    -        // Warm up indicator for immediate readiness to trade.
    -        WarmUpIndicator(hsiIndex, _zz, Resolution.Daily);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    -        if (IsMarketOpen(_hsiFuture.Symbol) && _zz.IsReady)
    -        {
    -            var pivot = _zz.PivotType;
    -            // If the last pivot point is low, the current trend is increasing after this low point.
    -            if (pivot == PivotPointType.Low && !Portfolio[_hsiFuture.Symbol].IsLong)
    -            {
    -                SetHoldings(_hsiFuture.Mapped, 0.2m);
    -            }
    -            // If the last pivot point is high, the current trend decreases after this high point.
    -            else if (pivot == PivotPointType.High && !Portfolio[_hsiFuture.Symbol].IsShort)
    -            {
    -                SetHoldings(_hsiFuture.Mapped, -0.2m);
    -            }
    -        }
    -
    -        // Handle rollover in case the current mapped contract changes.
    -        foreach (var (_, changedEvent) in slice.SymbolChangedEvents)
    -        {
    -            var oldSymbol = changedEvent.OldSymbol;
    -            var newSymbol = AddFutureContract(changedEvent.NewSymbol).Symbol;
    -            var quantity = Portfolio[oldSymbol].Quantity;
    -            // Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    -            Liquidate(oldSymbol);
    -            if (quantity != 0)
    -            {
    -                MarketOrder(newSymbol, quantity);
    -            }
    -        }
    -    }
    -}
    -
    -

    - Classic Algorithm Example -- FESX Futures -

    -

    - The following example algorithm uses the - - MACD - - indicator to determine the trend of the EuroStoxx50 Index. To trade the Index, we make use of the FESX Futures. -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class InternationalFuturesDataAlgorithm(QCAlgorithm):
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Set the time zone to Berlin to make it more comparable with the exchange.
    -        self.set_time_zone(TimeZones.BERLIN)
    -        # Set the account currency as EUR to trade FSX Futures.
    -        self.set_account_currency("EUR", 1000000)
    -        # Seed the last price of the contracts for filling.
    -        self.settings.seed_initial_prices = True
    -
    -        # Request FESX Futures to trade. 
    -        # Note that we will trade the contract with the highest open interest for liquidity.
    -        self.fesx_future = self.add_future(
    -            Futures.Indices.EURO_STOXX_50,
    -            extended_market_hours=True,
    -            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
    -            contract_depth_offset=0
    -        )
    -        # Request the corresponding underlying Index for feeding indicator for trade signal generation.
    -        fesx_index = self.add_index("SX5E").symbol
    -
    -        # Create a MACD indicator to trade EuroStoxx trend changes on the fast-slow term trend convergence.
    -        self._macd = self.macd(fesx_index, 12, 26, 9, resolution=Resolution.DAILY)
    -        # Warm up indicator for immediate readiness to trade.
    -        self.warm_up_indicator(fesx_index, self._macd, Resolution.DAILY)
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    -        if self.is_market_open(self.fesx_future.symbol) and self._macd.is_ready:
    -            # To identify a sensitive change in trend, use the change in the histogram value of the MACD.
    -            histogram = self._macd.histogram
    -            histogram_chg = histogram.current.value - histogram.previous.value
    -            # Positive histogram value increasing means the fast trend is rising faster than the slow trend, indicating a strong uptrend.
    -            if histogram_chg > 0 and histogram.current.value > 0 and not self.portfolio[self.fesx_future.symbol].is_long:
    -                self.set_holdings(self.fesx_future.mapped, 0.2)
    -            # Negative histogram value decreasing means the slow trend is dropping faster than the fast trend, indicating a strong downtrend.
    -            elif histogram_chg < 0 and histogram.current.value < 0 and not self.portfolio[self.fesx_future.symbol].is_short:
    -                self.set_holdings(self.fesx_future.mapped, -0.2)
    -
    -        # Handle rollover in case the current mapped contract changes.
    -        for _, changed_event in slice.symbol_changed_events.items():
    -            old_symbol = changed_event.old_symbol
    -            new_symbol = self.add_future_contract(changed_event.new_symbol).symbol
    -            quantity = self.portfolio[old_symbol].quantity
    -            # Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    -            self.liquidate(old_symbol)
    -            if quantity != 0:
    -                self.market_order(new_symbol, quantity)
    -
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    -{
    -    private Future _fesxFuture;
    -    private MovingAverageConvergenceDivergence _macd;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Set the time zone to Berlin to make it more comparable with the exchange.
    -        SetTimeZone(TimeZones.Berlin);
    -        // Set the account currency as EUR to trade FSX Futures.
    -        SetAccountCurrency("EUR", 1000000);
    -        // Seed the last price of the contracts for filling.
    -        Settings.SeedInitialPrices = true;
    -
    -        // Request FESX Futures to trade. 
    -        // Note that we will trade the contract with the highest open interest for liquidity.
    -        _fesxFuture = AddFuture(
    -            Futures.Indices.EuroStoxx50,
    -            extendedMarketHours: true,
    -            dataMappingMode: DataMappingMode.LastTradingDay,
    -            contractDepthOffset: 0
    -        );
    -        // Request the corresponding underlying Index for feeding indicator for trade signal generation.
    -        var fesxIndex = AddIndex("SX5E").Symbol;
    -
    -        // Create a MACD indicator to trade EuroStoxx trend changes on the fast-slow term trend convergence.
    -        _macd = MACD(fesxIndex, 12, 26, 9, resolution: Resolution.Daily);
    -        // Warm up indicator for immediate readiness to trade.
    -        WarmUpIndicator(fesxIndex, _macd, Resolution.Daily);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    -        if (IsMarketOpen(_fesxFuture.Symbol) && _macd.IsReady)
    -        {
    -            // To identify a sensitive change in trend, use the change in the histogram value of the MACD.
    -            var histogram = _macd.Histogram;
    -            var histogramChg = histogram - histogram.Previous;
    -            // Positive histogram value increasing means the fast trend is rising faster than the slow trend, indicating a strong uptrend.
    -            if (histogramChg > 0 && histogram > 0 && !Portfolio[_fesxFuture.Symbol].IsLong)
    -            {
    -                SetHoldings(_fesxFuture.Mapped, 0.2m);
    -            }
    -            // Negative histogram value decreasing means the slow trend is dropping faster than the fast trend, indicating a strong downtrend.
    -            else if (histogramChg < 0 && histogram < 0 && !Portfolio[_fesxFuture.Symbol].IsShort)
    -            {
    -                SetHoldings(_fesxFuture.Mapped, -0.2m);
    -            }
    -        }
    -
    -        // Handle rollover in case the current mapped contract changes.
    -        foreach (var (_, changedEvent) in slice.SymbolChangedEvents)
    -        {
    -            var oldSymbol = changedEvent.OldSymbol;
    -            var newSymbol = AddFutureContract(changedEvent.NewSymbol).Symbol;
    -            var quantity = Portfolio[oldSymbol].Quantity;
    -            // Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    -            Liquidate(oldSymbol);
    -            if (quantity != 0)
    -            {
    -                MarketOrder(newSymbol, quantity);
    -            }
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The International Futures dataset provides - - Future - - , - - FuturesChain - - , and - - OpenInterest - - objects. To configure the continuous Future settings, use the - - DataNormalizationMode - - and - - DataMappingMode - - enumerations. -

    -

    - Future Attributes -

    -

    - - Future - - objects have the following attributes: -

    -
    -
    -

    - FuturesChain Attributes -

    -

    - - FuturesChain - - objects have the following attributes: -

    -
    -
    -

    - OpenInterest Attributes -

    -

    - - OpenInterest - - objects have the following attributes: -

    -
    -
    -

    - DataNormalizationMode Values -

    -

    - The - - DataNormalizationMode - - enumeration has the following values: -

    -
    -
    -

    - DataMappingMode Values -

    -

    - The - - DataMappingMode - - enumeration has the following values: -

    -
    -
    - - - -

     

    - -
    -
    -

    Datasets

    -

    CoinAPI

    -
    -
    - - -
    -
    -

    - - CoinAPI - - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. -

    -
    - -
    - - - -

     

    - -
    -
    -

    CoinAPI

    -

    Binance Crypto Future Price Data

    -
    -
    -

    Introduction

    - - -

    - The Binance Crypto Future Price Data by CoinAPI is for Crypto-currency futures price and volume data points. The data covers 718 Cryptocurrency pairs, starts in August 2020, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Binance. -

    -

    - The - - Binance Crypto Future Margin Rate Data - - dataset provides margin interest data to model margin costs. -

    -

    - For more information about the Binance Crypto Future Price Data dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - - CoinAPI - - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the Binance Crypto Future Price dataset: -

    -
    -
    def initialize(self) -> None:
    -    self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
    -    #self.set_brokerage_model(BrokerageName.BINANCE_COIN_FUTURES, AccountType.MARGIN)
    -
    -    self.crypto_future_symbol = self.add_crypto_future("BTCBUSD", Resolution.MINUTE).symbol
    -
    -
    private Symbol _cryptoFutureSymbol;
    -
    -public override void Initialize
    -{
    -    SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
    -    //SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Margin);
    -
    -    // perpetual futures does not have a filter function
    -    _cryptoFutureSymbol = AddCryptoFuture("BTCBUSD", Resolution.Minute).Symbol;
    -}
    -
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - August 2020 -
    - Asset Coverage - - 718 Crypto Futures Pairs -
    - Data Density - - Dense -
    - Resolution - - Tick, Second, Minute, Hourly, & Daily -
    - Timezone - - UTC -
    - Market Hours - - - Always Open - -
    - - - -

    Requesting Data

    - - -

    - To add Binance Crypto Future Price data to your algorithm, call the - - AddCryptoFuture - - - add_crypto_future - - method. Save a reference to the Crypto Future - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class CoinAPIDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -
    -        # Set Account Currency to Binance Stable Coin for USD
    -        self.set_account_currency("BUSD")
    -        self.set_cash(100000)
    -
    -        self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
    -        self.set_brokerage_model(BrokerageName.BINANCE_COIN_FUTURES, AccountType.MARGIN)
    -        
    -        crypto_future = self.add_crypto_future("BTCBUSD", Resolution.MINUTE)
    -        # perpetual futures does not have a filter function
    -        self.btcbusd = crypto_future.symbol
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol ;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -
    -        // Set Account Currency to Binance Stable Coin for USD
    -        SetAccountCurrency("BUSD");
    -        SetCash(100000);
    -
    -        SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
    -        SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Margin);
    -        
    -        var cryptoFuture = AddCryptoFuture("BTCBUSD", Resolution.Minute);
    -        // perpetual futures does not have a filter function
    -        _symbol = cryptoFuture.Symbol;
    -    }
    -}
    -
    -

    - For more information about creating Crypto Future subscriptions, see - - Requesting Data - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current Binance Crypto Future Price data, index the - - Bars - - - bars - - , - - QuoteBars - - - quote_bars - - , or - - Ticks - - - ticks - - properties of the current - - - Slice - - - with the Crypto Future - - Symbol - - . - - Slice - - objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    if self.btcbusd in slice.bars:
    -        trade_bar = slice.bars[self.btcbusd]
    -        self.log(f"{self.btcbusd} close at {slice.time}: {trade_bar.close}")
    -
    -    if self.btcbusd in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.btcbusd]
    -        self.log(f"{self.btcbusd} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    if self.btcbusd in slice.ticks:
    -        ticks = slice.ticks[self.btcbusd]
    -        for tick in ticks:
    -            self.log(f"{self.btcbusd} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    if (slice.Bars.ContainsKey(_symbol))
    -    {
    -        var tradeBar = slice.Bars[_symbol];
    -        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    if (slice.QuoteBars.ContainsKey(_symbol))
    -    {
    -        var quoteBar = slice.QuoteBars[_symbol];
    -        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    if (slice.Ticks.ContainsKey(_symbol))
    -    {
    -        var ticks = slice.Ticks[_symbol];
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - You can also iterate through all of the data objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for symbol, trade_bar in slice.bars.items():
    -        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    -
    -    for symbol, quote_bar in slice.quote_bars.items():
    -        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    for symbol, ticks in slice.ticks.items():
    -        for tick in ticks:
    -            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.Bars)
    -    {
    -        var symbol = kvp.Key;
    -        var tradeBar = kvp.Value;
    -        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    foreach (var kvp in slice.QuoteBars)
    -    {
    -        var symbol = kvp.Key;
    -        var quoteBar = kvp.Value;
    -        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    foreach (var kvp in slice.Ticks)
    -    {
    -        var symbol = kvp.Key;
    -        var ticks = kvp.Value;
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - For more information about accessing Crypto Future data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - To get historical Binance Crypto Future Price data, call the - - History - - - history - - method with the Crypto Future - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.btcbusd, 100, Resolution.DAILY)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK)
    -
    // TradeBar objects 
    -var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    -
    -// Tick objects 
    -var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Remove Subscriptions

    - - -

    - To unsubscribe from a Crypto Future contract that you added with the - - AddCryptoFuture - - - add_crypto_future - - method, call the - - RemoveSecurity - - - remove_security - - method. -

    -
    -
    self.remove_security(self.btcbusd)
    -
    RemoveSecurity(_symbol);
    -
    -

    - The - - RemoveSecurity - - - remove_security - - method cancels your open orders for the security and liquidates your Crypto Future holdings. -

    - - - -

    Supported Assets

    - - -

    - The following table shows the available Crypto Future pairs: -

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - -
    - - - -

    Example Applications

    - - -

    - The Binance Crypto Future Price dataset enables you to accurately design strategies for Cryptocurrencies with term structure. Examples include the following strategies: -

    -
      -
    • - Horizontal/Diagonal arbitrage with the underlying cryptocurrencies -
    • -
    • - Trade Contango/Backwardation predictions -
    • -
    • - Hedge for illiquid cryptocurrencies -
    • -
    -

    - Classic Algorithm Example -

    -

    - The following example algorithm buys BTCUSDT perpetual future contract if the last day's close price was close to ask close price than bid close price, sells short of that in opposite, through the Binance exchange: -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class BinanceCryptoFutureDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Set the account currency to USDT, since you can't trade with 
    -        # USD and the algorithm doesn't automatically convert USD & USDT
    -        # holdings.
    -        self.set_account_currency("USDT", 100000)
    -        # Binance Futures Exchange accepts both Cash and Margin account 
    -        # types. Select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
    -        # Add BTCUSDT data from the Binance Future exchange.
    -        # Perpetual futures does not have a filter function.
    -        self._btc = self.add_crypto_future("BTCUSDT", Resolution.DAILY)
    -        # Historical data
    -        history = self.history(self._btc, 10, Resolution.DAILY)
    -
    -    def on_data(self, slice: Slice) -> None:
    -        # Trade only based on updated price data.
    -        if self._btc.symbol not in slice.bars or self._btc.symbol not in slice.quote_bars:
    -            return
    -        # Scalp-trade the bid-ask spread based on the supply-demand strength
    -        if self._btc.price - self._btc.bid_price > self._btc.ask_price - self._btc.price:
    -            self.set_holdings(self._btc, -0.5)
    -        else:
    -            self.set_holdings(self._btc, 1)
    -
    public class BinanceCryptoFutureDataAlgorithm : QCAlgorithm
    -{
    -    public CryptoFuture _btc;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Set the account currency to USDT, since you can't trade with 
    -        // USD and the algorithm doesn't automatically convert USD & USDT
    -        // holdings.
    -        SetAccountCurrency("USDT", 100000);
    -        // Binance Futures Exchange accepts both Cash and Margin account 
    -        // types. Select the one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
    -        // Add BTCUSDT data from the Binance Future exchange.
    -        // Perpetual futures does not have a filter function.
    -        _btc = AddCryptoFuture("BTCUSDT", Resolution.Daily);
    -        // Historical data
    -        var history = History(_btc, 10, Resolution.Daily);
    -    }
    -
    -    public override void OnData(Slice slice)
    -    {
    -        // Trade only based on updated price data.
    -        if (!slice.Bars.ContainsKey(_btc) || !slice.QuoteBars.ContainsKey(_btc))
    -        {
    -            return;
    -        }
    -        // Scalp-trade the bid-ask spread based on the supply-demand strength
    -        if (_btc.Price - _btc.BidPrice > _btc.AskPrice - _btc.Price)
    -        {
    -            SetHoldings(_btc, -0.5m);
    -        }
    -        else
    -        {
    -            SetHoldings(_btc, 1m);
    -        }
    -    }
    -}
    -
    -

    - Framework Algorithm Example -

    -

    - The following example algorithm hold a long BTCUSDT Future portfolio if the last day's close price was close to ask close price than bid close price, while hold short of that in opposite, through the Binance exchange using the - - algorithm framework - - implementation: -

    -
    -
    from AlgorithmImports import *
    -
    -
    -class BinanceCryptoFutureDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2024, 9, 1)
    -        self.set_end_date(2024, 12, 31)
    -        # Set the account currency to USDT, since you can't trade with 
    -        # USD and the algorithm doesn't automatically convert USD & USDT
    -        # holdings.
    -        self.set_account_currency("USDT", 100000)
    -        # Binance Futures Exchange accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BINANCE_FUTURES, AccountType.MARGIN)
    -        self.universe_settings.resolution = Resolution.DAILY
    -        self.universe_settings.leverage = 2
    -        # We only trade on BTCUSDT Future in Binance Future exchange
    -        symbols = Symbol.create("BTCUSDT", SecurityType.CRYPTO_FUTURE, Market.BINANCE)
    -        self.add_universe_selection(ManualUniverseSelectionModel(symbols))
    -        # Custom alpha model to emit insights based on the Crypto Future price data
    -        self.add_alpha(CryptoFutureAlphaModel())
    -        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    -        self.set_execution(ImmediateExecutionModel())
    -
    -class CryptoFutureAlphaModel(AlphaModel):
    -
    -    def __init__(self) -> None:
    -        self.symbols = []
    -
    -    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    -        insights = []
    -
    -        for symbol in self.symbols:
    -            # Trade only based on updated price data
    -            if not slice.bars.contains_key(symbol) or not slice.quote_bars.contains_key(symbol):
    -                continue
    -
    -            quote = slice.quote_bars[symbol]
    -            price = slice.bars[symbol].price
    -            
    -            # Scalp-trade the bid-ask spread based on the supply-demand strength
    -            if price - quote.bid.close > quote.ask.close - price:
    -                direction = InsightDirection.DOWN
    -            else:
    -                direction = InsightDirection.UP
    -            insights.append(Insight.price(symbol, timedelta(1), direction))
    -            
    -        return insights
    -
    -    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            symbol = security.symbol
    -            self.symbols.append(symbol)
    -
    -            # Historical data
    -            history = algorithm.history(symbol, 10, Resolution.DAILY)
    -
    -        for security in changes.removed_securities:
    -            symbol = security.symbol
    -            if symbol in self.symbols:
    -                self.symbols.remove(symbol)
    -
    -
    public class BinanceCryptoFutureDataAlgorithm : QCAlgorithm
    -{
    -    public Symbol _symbol;
    -
    -    public override void Initialize()
    -    {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        // Set the account currency to USDT, since you can't trade with 
    -        // USD and the algorithm doesn't automatically convert USD & USDT
    -        // holdings.
    -        SetAccountCurrency("USDT", 100000);
    -        // Binance Futures Exchange accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
    -        UniverseSettings.Resolution = Resolution.Daily;
    -        UniverseSettings.Leverage = 2;
    -        // We only trade on BTCUSDT Future in Binance Future exchange
    -        var symbols = new List<Symbol> {
    -            QuantConnect.Symbol.Create("BTCUSDT", SecurityType.CryptoFuture, Market.Binance)
    -        };
    -        AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
    -        // Custom alpha model to emit insights based on the Crypto Future price data
    -        AddAlpha(new CryptoFutureAlphaModel());
    -        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -        SetExecution(new ImmediateExecutionModel());
    -    }
    -}
    -
    -public class CryptoFutureAlphaModel : AlphaModel
    -{
    -    private List<Symbol> _symbols = new();
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    -    {
    -        var insights = new List<Insight>();
    -
    -        foreach (var symbol in _symbols)
    -        {
    -            // Trade only based on updated price data
    -            if (!slice.Bars.ContainsKey(symbol) || !slice.QuoteBars.TryGetValue(symbol, out var quote))
    -            {
    -                continue;
    -            }
    -            var price = slice.Bars[symbol].Price;
    -            
    -            // Scalp-trade the bid-ask spread based on the supply-demand strength
    -            InsightDirection direction;
    -            if (price - quote.Bid.Close > quote.Ask.Close - price)
    -            {
    -                direction = InsightDirection.Down;
    -            }
    -            else
    -            {
    -                direction = InsightDirection.Up;
    -            }
    -            insights.Add(Insight.Price(symbol, TimeSpan.FromDays(1), direction));
    -        }
    -        return insights;
    -    }
    -
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    -        {
    -            var symbol = security.Symbol;
    -            _symbols.Add(symbol);
    -
    -            // Historical data
    -            var history = algorithm.History(symbol, 10, Resolution.Daily);
    -        }
    -
    -        foreach (var security in changes.RemovedSecurities)
    -        {
    -            _symbols.Remove(security.Symbol);
    -        }
    -    }
    -}
    -
    - - - -

    Data Point Attributes

    - - -

    - The Binance Crypto Future Price dataset provides - - TradeBar - - , - - QuoteBar - - , and - - Tick - - objects. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - Tick Attributes -

    -

    - - Tick - - objects have the following attributes: -

    -
    -
    - - - -

     

    - -
    -
    -

    CoinAPI

    -

    Binance Crypto Price Data

    -
    -
    -

    Introduction

    - - -

    - The Binance Crypto Price Data by CoinAPI is for Cryptocurrency price and volume data points. The data covers 3,320 Cryptocurrency pairs, starts in July 2017, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Binance. -

    -

    - For more information about the Binance Crypto Price Data dataset, including CLI commands and pricing, see the - - dataset listing - - . -

    -

    -

    - - - -

    About the Provider

    - - -

    - - CoinAPI - - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. -

    - - - -

    Getting Started

    - - -

    - The following snippet demonstrates how to request data from the Binance Crypto Price dataset: -

    -
    -
    # Binance accepts both Cash and Margin account types only.
    -self.set_brokerage_model(BrokerageName.BINANCE, AccountType.CASH)
    -#self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    -
    -self.btcbusd = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE).symbol
    -
    -self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
    -
    -
    // Binance accepts both Cash and Margin account types only.
    -SetBrokerageModel(BrokerageName.Binance, AccountType.Cash);
    -//SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    -
    -_symbol = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance).Symbol;
    -
    -_universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
    -
    - - - -

    Data Summary

    - - -

    - The following table describes the dataset properties: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Property - - Value -
    - Start Date - - July 2017 -
    - Asset Coverage - - 3,320 Currency Pairs -
    - Data Density - - Dense -
    - Resolution - - Tick, Second, Minute, Hourly, & Daily -
    - Timezone - - UTC -
    - Market Hours - - - Always Open - -
    - - - -

    Requesting Data

    - - -

    - To add Binance Crypto Price data to your algorithm, call the - - AddCrypto - - - add_crypto - - method. Save a reference to the Crypto - - Symbol - - so you can access the data later in your algorithm. -

    -
    -
    class CoinAPIDataAlgorithm(QCAlgorithm):
    -
    -    def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 6, 1)
    -
    -        # Set Account Currency to Binance Stable Coin for USD
    -        self.set_account_currency("BUSD")
    -        self.set_cash(100000)
    -
    -        # Binance accepts both Cash and Margin account types.
    -        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    -        
    -        self.btcbusd = self.add_crypto("BTCBUSD", Resolution.MINUTE, Market.BINANCE).symbol
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    -{
    -    private Symbol _symbol;
    -    
    -    public override void Initialize()
    -    {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 6, 1);
    -
    -        // Set Account Currency to Binance Stable Coin for USD
    -        SetAccountCurrency("BUSD");
    -        SetCash(100000);
    -
    -        // Binance accepts both Cash and Margin account types.
    -        SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    -        
    -        _symbol = AddCrypto("BTCBUSD", Resolution.Minute, Market.Binance).Symbol;
    -    }
    -}
    -
    -

    - For more information about creating Crypto subscriptions, see - - Requesting Data - - . -

    - - - -

    Accessing Data

    - - -

    - To get the current Binance Crypto Price data, index the - - Bars - - - bars - - , - - QuoteBars - - - quote_bars - - , or - - Ticks - - - ticks - - properties of the current - - - Slice - - - with the Crypto - - Symbol - - . - - Slice - - objects deliver unique events to your algorithm as they happen, but the - - Slice - - may not contain data for your security at every time step. To avoid issues, check if the - - Slice - - contains the data you want before you index it. -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    if self.btcbusd in slice.bars:
    -        trade_bar = slice.bars[self.btcbusd]
    -        self.log(f"{self.btcbusd} close at {slice.time}: {trade_bar.close}")
    -
    -    if self.btcbusd in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.btcbusd]
    -        self.log(f"{self.btcbusd} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    if self.btcbusd in slice.ticks:
    -        ticks = slice.ticks[self.btcbusd]
    -        for tick in ticks:
    -            self.log(f"{self.btcbusd} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    if (slice.Bars.ContainsKey(_symbol))
    -    {
    -        var tradeBar = slice.Bars[_symbol];
    -        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    if (slice.QuoteBars.ContainsKey(_symbol))
    -    {
    -        var quoteBar = slice.QuoteBars[_symbol];
    -        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    if (slice.Ticks.ContainsKey(_symbol))
    -    {
    -        var ticks = slice.Ticks[_symbol];
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - You can also iterate through all of the data objects in the current - - Slice - - . -

    -
    -
    def on_data(self, slice: Slice) -> None:
    -    for symbol, trade_bar in slice.bars.items():
    -        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    -
    -    for symbol, quote_bar in slice.quote_bars.items():
    -        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    for symbol, ticks in slice.ticks.items():
    -        for tick in ticks:
    -            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    -
    public override void OnData(Slice slice)
    -{
    -    foreach (var kvp in slice.Bars)
    -    {
    -        var symbol = kvp.Key;
    -        var tradeBar = kvp.Value;
    -        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    foreach (var kvp in slice.QuoteBars)
    -    {
    -        var symbol = kvp.Key;
    -        var quoteBar = kvp.Value;
    -        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    foreach (var kvp in slice.Ticks)
    -    {
    -        var symbol = kvp.Key;
    -        var ticks = kvp.Value;
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    -        }
    -    }
    -}
    -
    -
    -

    - For more information about accessing Crypto data, see - - Handling Data - - . -

    - - - -

    Historical Data

    - - -

    - To get historical Binance Crypto Price data, call the - - History - - - history - - method with the Crypto - - Symbol - - . If there is no data in the period you request, the history result is empty. -

    -
    -
    # DataFrame
    -history_df = self.history(self.btcbusd, 100, Resolution.DAILY)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK)
    -
    // TradeBar objects 
    -var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    -
    -// Tick objects 
    -var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    -
    -

    - For more information about historical data, see - - History Requests - - . -

    - - - -

    Universe Selection

    - - -

    - To select a dynamic universe of Binance Crypto pairs, call the - - AddUniverse - - - add_universe - - method with a - - CryptoUniverse - - object. A - - Crypto universe - - uses a selection function to select Crypto pairs based on their OHLCV and dollar volume of the previous day as of midnight Coordinated Universal Time (UTC). -

    -
    -
    def initialize(self) -> None:
    -    self.universe_settings.asynchronous = True
    -    self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    -    self._universe = self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
    -
    -def universe_selection_filter(self, universe_day):
    -    return [c.symbol for c in universe_day if c.volume >= 100 and c.volume_in_usd > 10000]
    -
    using QuantConnect.Data.UniverseSelection;
    -
    -public override void Initialize()
    -{
    -    UniverseSettings.Asynchronous = true;
    -    SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    -    _universe = AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
    -}
    -
    -private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    -{
    -    return from c in universeDay
    -           where c.Volume >= 100m && c.VolumeInUsd > 10000m
    -           select c.Symbol;
    -}
    -
    -

    - For more information about universe settings, see - - Settings - - . -

    - - - -

    Universe History

    - - -

    - You can get historical universe data in an algorithm and in the Research Environment. -

    -

    - Historical Universe Data in Algorithms -

    -

    - To get historical universe data in an algorithm, call the - - History - - - history - - method with the - - Universe - - object, and the lookback period. If there is no data in the period you request, the history result is empty. -

    -
    -
    var history = History(_universe, 30, Resolution.Daily);
    -foreach (var universeDay in history)
    -{
    -    foreach (CryptoUniverse universeItem in universeDay)
    -    {
    -        Log($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    -    }
    -}
    -
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    -history_df = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
    -
    -# Series example where the values are lists of CryptoUniverse objects: 
    -history = self.history(self._universe, 30, Resolution.DAILY)
    -for (univere_symbol, time), universe_day in history.items():
    -    for universe_item in universe_day:
    -        self.log(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    -
    -

    - Historical Universe Data in Research -

    -

    - To get historical universe data in research, call the - - UniverseHistory - - - universe_history - - method with the - - Universe - - object, and the lookback period. The - - UniverseHistory - - - universe_history - - returns the filtered universe. If there is no data in the period you request, the history result is empty. -

    -
    -
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var universeDay in universeHistory)
    -{
    -    foreach (CryptoUniverse universeItem in universeDay)
    -    {
    -        Console.WriteLine($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    -    }
    -}
    -
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    -history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    -
    -# Series example where the values are lists of CryptoUniverse objects: 
    -universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (univere_symbol, time), universe_day in universe_history.items():
    -    for universe_item in universe_day:
    -        print(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    -
    -

    - You can call the - - History - - - history - - method in Research. -

    - - - -

    Remove Subcriptions

    - - -

    - To unsubscribe from a Crypto pair that you added with the - - AddCrypto - - - add_crypto - - method, call the - - RemoveSecurity - - - remove_security - - method. -

    -
    -
    self.remove_security(self.btcbusd)
    -
    RemoveSecurity(_symbol);
    -
    -

    - The - - RemoveSecurity - - - remove_security - - method cancels your open orders for the security and liquidates your holdings in the - - virtual pair - - . -

    - - - -

    Supported Assets

    - - - The following table shows the available Cryptocurrency pairs: -
    - - + + + - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +

    Example Applications

    + + +

    + The Binance Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: +

    +
      +
    • + Buy and hold +
    • +
    • + Trading Cryptocurrency volatility and price action +
    • +
    • + Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys and holds Bitcoin through the Binance exchange: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Set the account currency to USDT, since you can't trade with 
    +        # USD and the algorithm doesn't automatically convert USD & USDT
    +        # holdings.
    +        self.set_account_currency("USDT", 100000)
    +        self.universe_settings.asynchronous = True
    +        # Binance accepts both Cash and Margin account types. Select the
    +        # one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    +        # Add BTCUSDT data.
    +        self._btc = self.add_crypto("BTCUSDT", Resolution.MINUTE, Market.BINANCE)
    +        # Historical data
    +        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    +        # Add a Crypto universe that selects trading pairs on Binance.
    +        universe = self.add_universe(CryptoUniverse.binance(self._select_assets))
    +        # Historical Universe data
    +        universe_history = self.history(universe, 30, Resolution.DAILY)
    +        for (universe_symbol, time), universe_day in universe_history.items():
    +            for universe_item in universe_day:
    +                symbol = universe_item.symbol
    +                price = universe_item.close
    +
    +    def _select_assets(self, universe_day):
    +        # Filter for materially traded Crypto pairs with significant 
    +        # size and dollar volume, assuming higher capital flow in for 
    +        # higher return.
    +        return [universe_item.symbol for universe_item in universe_day
    +                if universe_item.volume >= 100 
    +                and universe_item.volume_in_usd > 10_000_000]
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Speculate-invest all available free cash on BTCUSDT, repecting 
    +        # the order quantity restrictions to avoid invalid orders.
    +        if self.portfolio.cash_book['BTC'].amount != 0:
    +            return
    +        # Define a buffer so that we can scale down the order size,
    +        # avoiding trading errors.
    +        buffer = max(
    +            BinanceFeeModel.TAKER_TIER_1_FEE, 
    +            self.settings.free_portfolio_value_percentage
    +        )
    +        quantity = (
    +            self.portfolio.cash_book['USDT'].amount
    +            / self._btc.ask_price
    +            * (1-buffer)
    +        )
    +        # Check if the quantity exceeds the minimum order size. On 
    +        # Binance, the minimum order size is measured in the quote
    +        # currency (USDT in this case).
    +        minimum_order_size = (
    +            self._btc.symbol_properties.minimum_order_size 
    +            / self._btc.ask_price
    +        )
    +        if abs(quantity) < minimum_order_size:
    +            return
    +        self.market_order(self._btc, quantity)
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private Crypto _btc;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        // Set the account currency to USDT, since you can't trade with 
    +        // USD and the algorithm doesn't automatically convert USD & USDT
    +        // holdings.
    +        SetAccountCurrency("USDT", 100000);
    +        UniverseSettings.Asynchronous = true;
    +        // Binance accepts both Cash and Margin account types. Select the
    +        // one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    +        // Add BTCUSDT data.
    +        _btc = AddCrypto("BTCUSDT", Resolution.Minute, Market.Binance);   
    +        // Historical data
    +        var history = History(_btc.Symbol, 30, Resolution.Daily);
    +        // Add a Crypto universe that selects trading pairs on Binance.
    +        var universe = AddUniverse(CryptoUniverse.Binance(SelectAssets));
    +        // Historical Universe data
    +        var universeHistory = History(universe, 30, Resolution.Daily);
    +        foreach (var universeDay in universeHistory)
    +        {
    +            foreach (CryptoUniverse universeItem in universeDay)
    +            {
    +                var symbol = universeItem.Symbol;
    +                var price = universeItem.Close;
    +            }
    +        }
    +    }
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Filter for materially traded Crypto pairs with significant 
    +        // size and dollar volume, assuming higher capital flow in for 
    +        // higher return.
    +        return from universeItem in universeDay
    +                where universeItem.Volume >= 100m 
    +                && universeItem.VolumeInUsd > 10000000m
    +                select universeItem.Symbol;
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Speculate-invest all available free cash on BTCUSDT, repecting 
    +        // the order quantity restrictions to avoid invalid orders.
    +        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        {
    +            return;
    +        }
    +        // Define a buffer so that we can scale down the order size,
    +        // avoiding trading errors.
    +        var buffer = Math.Max(BinanceFeeModel.TakerTier1Fee, Settings.FreePortfolioValuePercentage);
    +        var quantity = Portfolio.CashBook["USDT"].Amount / _btc.AskPrice * (1-buffer);
    +        // Check if the quantity exceeds the minimum order size. On 
    +        // Binance, the minimum order size is measured in the quote 
    +        // currency (USDT in this case).
    +        var minimumOrderSize = _btc.SymbolProperties.MinimumOrderSize / _btc.AskPrice;
    +        if (Math.Abs(quantity) < minimumOrderSize)
    +        {
    +            return;
    +        }
    +        MarketOrder(_btc, quantity);
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of Crypto pairs on the Binance exchange and then forms a equal-weighted portfolio of all the pairs in the universe: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Set Account Currency to Tether, since USD and USDT will not auto-convert and USD cannot be used to trade
    +        self.set_account_currency("USDT", 100000)
    +        self.settings.free_portfolio_value_percentage = 0.05
    +
    +        # Binance accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
    +
    +        # Warm up the security with the last known price to avoid conversion error
    +        self.settings.seed_initial_prices = True
    +        self.universe_settings.asynchronous = True
    +        self.universe_settings.resolution = Resolution.MINUTE
    +        # Add Crypto Universe Selection that select crypto pairs in Binance exchange
    +        self.add_universe(CryptoUniverse.binance(self.universe_selection_filter))
    +        # Get the pairs on Binance that have USDT as the quote currency.
    +        self._market_pairs = [
    +            x.key.symbol 
    +            for x in self.symbol_properties_database.get_symbol_properties_list(Market.BINANCE) 
    +            if x.value.quote_currency == self.account_currency
    +        ]
    +        
    +        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(minutes = 20), 0.025, None))
    +        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    +    def universe_selection_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    +        # Select pairs where the quote currency is USDT.
    +        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    +        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    +        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    +        return [c.symbol for c in pairs]
    +
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = self.history(security.symbol, 30, Resolution.DAILY)
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private List<string> _marketPairs;
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        Settings.FreePortfolioValuePercentage = 0.05m;
    +
    +        // Set Account Currency to Tether, since USD and USDT will not auto-convert and USD cannot be used to trade
    +        SetAccountCurrency("USDT", 100000);
    +        // Binance accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Binance, AccountType.Margin);
    +
    +        // Warm up the security with the last known price to avoid conversion error
    +        Settings.SeedInitialPrices = true;
    +        UniverseSettings.Asynchronous = true;
    +        UniverseSettings.Resolution = Resolution.Minute;
    +        // Add Crypto Universe Selection that select crypto pairs in Binance exchange
    +        AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
    +        // Get the pairs on Binance that have USDT as the quote currency.
    +        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Binance)
    +            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    +            .Select(x => x.Key.Symbol)
    +            .ToList();
    +
    +        AddAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
    +        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +    }
    +
    +    private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Select pairs where the quote currency is USDT.
    +        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    +            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    +            .OrderBy(c => c.VolumeInUsd)
    +            .TakeLast(3)
    +            .Select(c => c.Symbol);
    +    }
    +
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach(var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = History(security.Symbol, 30, Resolution.Daily);
    +        }
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example lists crypto-currency pairs with the greatest dollar volume in the Binance exchange: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add Cryptocurrency pair
    +var symbol = qb.AddCrypto("BTCUSDT", market:Market.Binance).Symbol;
    +
    +// Historical data
    +var history = qb.History(symbol, 30, Resolution.Daily);
    +foreach (var bar in history)
    +{
    +    Console.WriteLine($"{bar.EndTime} {bar}");
    +}
    +
    +// Add Crypto Universe Selection
    +IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +{
    +    return universeDay
    +        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    +        .OrderByDescending(x => x.VolumeInUsd)
    +        .Take(5)
    +        .Select(x => x.Symbol);
    +}
    +var universe = qb.AddUniverse(CryptoUniverse.Binance(UniverseSelectionFilter));
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var universeDay in universeHistory)
    +{
    +    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    +    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    +    {
    +        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add Cryptocurrency pair
    +symbol = qb.add_crypto("BTCUSDT", market=Market.BINANCE).symbol
    +
    +# Historical data
    +history = qb.history(symbol, 30, Resolution.DAILY)
    +for (symbol, time), row in history.iterrows():
    +    print(f'{time} {symbol} {row.close}')
    +
    +# Add Crypto Universe Selection
    +def universe_selection_filter(universe_day):
    +    selected = sorted([x for x in universe_day
    +        if x.volume_in_usd and x.volume_in_usd > 10000],
    +        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    +    return [x.symbol for x in selected]
    +
    +universe = qb.add_universe(CryptoUniverse.binance(universe_selection_filter))
    +
    +# Historical Universe data
    +history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (univere_symbol, time), universe_day in history.items():
    +    print(f'=== {time} ===')
    +    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    +        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The Binance Crypto Price dataset provides + + TradeBar + + , + + QuoteBar + + , + + Tick + + , and + + CryptoUniverse + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    +

    + CryptoUniverse Attributes +

    +

    + + CryptoUniverse + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    Binance US Crypto Price Data

    +
    +
    +

    Introduction

    + + +

    + The Binance US Crypto Price Data is for Cryptocurrency price and volume data points. The data covers 604 Cryptocurrency pairs, starts in October 2019, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Binance US. +

    +

    + For more information about the Binance US Crypto Price Data dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + Binance was founded by Changpeng Zhao in 2017 with the goal to "increase the freedom of money globally". Binance provides access to trading Crypto through spot markets and perpetual Futures. They serve clients with no minimum deposit when depositing Crypto. Binance also provides an NFT marketplace, a mining pool, and services to deposit Crypto coins in liquidity pools to earn rewards. +

    + + + +

    Getting Started

    + + +

    + The following snippets demonstrates how to set the brokerage model, request data, and perform universe selection with the Binance US dataset: +

    +
    +
    # Binance US only accepts cash accounts
    +self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
    +
    +self.btcbusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BINANCE_US).symbol
    +
    +self._universe = AddUniverse(CryptoUniverse.binance_us(self.universe_selection_filter));
    +
    // Binance US only accepts cash accounts
    +SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
    +
    +_symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.BinanceUS).Symbol;
    +
    +_universe = AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + October 2019 +
    + Asset Coverage + + 604 Cryptocurrency Pairs +
    + Data Density + + Dense +
    + Resolution + + Tick, Second, Minute, Hourly, & Daily +
    + Timezone + + UTC +
    + Market Hours + + + Always Open + +
    + + + +

    Requesting Data

    + + +

    + To add Binance US Crypto Price data to your algorithm, call the + + AddCrypto + + + add_crypto + + method. Save a reference to the Crypto + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000)
    +
    +        # BinanceUS accepts Cash account type only, AccountType.MARGIN will result in an exception.
    +        self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
    +        
    +        self.btcbusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BINANCE_US).symbol
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +    
    +        // BinanceUS accepts Cash account type only, AccountType.Margin will result in an exception.
    +        SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
    +        
    +        _symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.BinanceUS).Symbol;
    +    }
    +}
    +
    +

    + For more information about creating Crypto subscriptions, see + + Requesting Data + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current Binance US Crypto Price data, index the + + Bars + + + bars + + , + + QuoteBars + + + quote_bars + + , or + + Ticks + + + ticks + + properties of the current + + + Slice + + + with the Crypto + + Symbol + + . + + Slice + + objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    if self.btcbusd in slice.bars:
    +        trade_bar = slice.bars[self.btcbusd]
    +        self.log(f"{self.btcbusd} close at {slice.time}: {trade_bar.close}")
    +
    +    if self.btcbusd in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.btcbusd]
    +        self.log(f"{self.btcbusd} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    if self.btcbusd in slice.ticks:
    +        ticks = slice.ticks[self.btcbusd]
    +        for tick in ticks:
    +            self.log(f"{self.btcbusd} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    if (slice.Bars.ContainsKey(_symbol))
    +    {
    +        var tradeBar = slice.Bars[_symbol];
    +        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
    +    if (slice.QuoteBars.ContainsKey(_symbol))
    +    {
    +        var quoteBar = slice.QuoteBars[_symbol];
    +        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    if (slice.Ticks.ContainsKey(_symbol))
    +    {
    +        var ticks = slice.Ticks[_symbol];
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + You can also iterate through all of the data objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for symbol, trade_bar in slice.bars.items():
    +        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    +
    +    for symbol, quote_bar in slice.quote_bars.items():
    +        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    for symbol, ticks in slice.ticks.items():
    +        for tick in ticks:
    +            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.Bars)
    +    {
    +        var symbol = kvp.Key;
    +        var tradeBar = kvp.Value;
    +        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
    +    foreach (var kvp in slice.QuoteBars)
    +    {
    +        var symbol = kvp.Key;
    +        var quoteBar = kvp.Value;
    +        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    foreach (var kvp in slice.Ticks)
    +    {
    +        var symbol = kvp.Key;
    +        var ticks = kvp.Value;
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + For more information about accessing Crypto data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + To get historical Binance US Crypto Price data, call the + + History + + + history + + method with the Crypto + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.btcbusd, 100, Resolution.DAILY)
    +
    +# TradeBar objects
    +history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE)
    +
    +# Tick objects
    +history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK)
    +
    // TradeBar objects 
    +var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    +
    +// QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    +
    +// Tick objects 
    +var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Universe Selection

    + + +

    + To select a dynamic universe of Binance US Crypto pairs, call the + + AddUniverse + + + add_universe + + method with a + + CryptoUniverse + + object. A + + Crypto universe + + uses a selection function to select Crypto pairs based on their OHLCV and dollar volume of the previous day as of midnight Coordinated Universal Time (UTC). +

    +
    +
    def initialize(self) -> None:
    +    self.universe_settings.asynchronous = True
    +    self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
    +    self._universe = self.add_universe(CryptoUniverse.binance_us(self.universe_selection_filter))
    +
    +def universe_selection_filter(self, universe_day):
    +    return [c.symbol for c in universe_day if c.volume >= 100 and c.volume_in_usd > 10000]
    +
    public override void Initialize()
    +{
    +    UniverseSettings.Asynchronous = true;
    +    SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
    +    _universe = AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
    +}
    +
    +private IEnumerable<Symol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +{
    +    return from c in universeDay
    +           where c.Volume >= 100m && c.VolumeInUsd > 10000m
    +           select c.Symbol;
    +}
    +
    +

    + For more information about universe settings, see + + Settings + + . +

    + + + +

    Universe History

    + + +

    + You can get historical universe data in an algorithm and in the Research Environment. +

    +

    + Historical Universe Data in Algorithms +

    +

    + To get historical universe data in an algorithm, call the + + History + + + history + + method with the + + Universe + + object, and the lookback period. If there is no data in the period you request, the history result is empty. +

    +
    +
    var history = History(_universe, 30, Resolution.Daily);
    +foreach (var universeDay in history)
    +{
    +    foreach (CryptoUniverse universeItem in universeDay)
    +    {
    +        Log($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    +    }
    +}
    +
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    +history_df = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
    +
    +# Series example where the values are lists of CryptoUniverse objects: 
    +history = self.history(self._universe, 30, Resolution.DAILY)
    +for (univere_symbol, time), universe_day in history.items():
    +    for universe_item in universe_day:
    +        self.log(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    +
    +

    + Historical Universe Data in Research +

    +

    + To get historical universe data in research, call the + + UniverseHistory + + + universe_history + + method with the + + Universe + + object, and the lookback period. The + + UniverseHistory + + + universe_history + + returns the filtered universe. If there is no data in the period you request, the history result is empty. +

    +
    +
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var universeDay in universeHistory)
    +{
    +    foreach (CryptoUniverse universeItem in universeDay)
    +    {
    +        Console.WriteLine($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    +    }
    +}
    +
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    +history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    +
    +# Series example where the values are lists of CryptoUniverse objects: 
    +universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (univere_symbol, time), universe_day in universe_history.items():
    +    for universe_item in universe_day:
    +        print(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    +
    +

    + You can call the + + History + + + history + + method in Research. +

    + + + +

    Remove Subscriptions

    + + +

    + To unsubscribe from a Crypto pair that you added with the + + AddCrypto + + + add_crypto + + method, call the + + RemoveSecurity + + + remove_security + + method. +

    +
    +
    self.remove_security(self.btcbusd)
    +
    RemoveSecurity(_symbol);
    +
    +

    + The + + RemoveSecurity + + + remove_security + + method cancels your open orders for the security and liquidates your holdings in the + + virtual pair + + . +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available Cryptocurrency pairs: +

    +
    + + - - - - - - + + + + + @@ -215133,7 +184660,7 @@

    Data Summary

    Asset Coverage @@ -215179,7 +184706,7 @@

    Requesting Data

    - To add Binance US Crypto Price data to your algorithm, call the + To add Bitfinex Crypto Price data to your algorithm, call the AddCrypto @@ -215200,10 +184727,10 @@

    Requesting Data

    self.set_end_date(2021, 6, 1) self.set_cash(100000) - # BinanceUS accepts Cash account type only, AccountType.MARGIN will result in an exception. - self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH) + # Bitfinex accepts both Cash and Margin type account. + self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN) - self.btcbusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BINANCE_US).symbol + self.btcusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BITFINEX).symbol
    public class CoinAPIDataAlgorithm : QCAlgorithm
     {
         private Symbol _symbol;
    @@ -215213,11 +184740,11 @@ 

    Requesting Data

    SetStartDate(2020, 6, 1); SetEndDate(2021, 6, 1); SetCash(100000); - - // BinanceUS accepts Cash account type only, AccountType.Margin will result in an exception. - SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash); + + // Bitfinex accepts both Cash and Margin type account. + SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin); - _symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.BinanceUS).Symbol; + _symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.Bitfinex).Symbol; } }
    @@ -215235,7 +184762,7 @@

    Accessing Data

    - To get the current Binance US Crypto Price data, index the + To get the current Bitfinex Crypto Price data, index the Bars @@ -215282,18 +184809,18 @@

    Accessing Data

    def on_data(self, slice: Slice) -> None:
    -    if self.btcbusd in slice.bars:
    -        trade_bar = slice.bars[self.btcbusd]
    -        self.log(f"{self.btcbusd} close at {slice.time}: {trade_bar.close}")
    +    if self.btcusd in slice.bars:
    +        trade_bar = slice.bars[self.btcusd]
    +        self.log(f"{self.btcusd} close at {slice.time}: {trade_bar.close}")
     
    -    if self.btcbusd in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.btcbusd]
    -        self.log(f"{self.btcbusd} bid at {slice.time}: {quote_bar.bid.close}")
    +    if self.btcusd in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.btcusd]
    +        self.log(f"{self.btcusd} bid at {slice.time}: {quote_bar.bid.close}")
     
    -    if self.btcbusd in slice.ticks:
    -        ticks = slice.ticks[self.btcbusd]
    +    if self.btcusd in slice.ticks:
    +        ticks = slice.ticks[self.btcusd]
             for tick in ticks:
    -            self.log(f"{self.btcbusd} price at {slice.time}: {tick.price}")
    + self.log(f"{self.btcusd} price at {slice.time}: {tick.price}")
    public override void OnData(Slice slice)
     {
         if (slice.Bars.ContainsKey(_symbol))
    @@ -215379,7 +184906,7 @@ 

    Historical Data

    - To get historical Binance US Crypto Price data, call the + To get historical Bitfinex Crypto Price data, call the History @@ -215394,16 +184921,16 @@

    Historical Data

    # DataFrame
    -history_df = self.history(self.btcbusd, 100, Resolution.DAILY)
    +history_df = self.history(self.btcusd, 100, Resolution.DAILY)
     
     # TradeBar objects
    -history_trade_bars = self.history[TradeBar](self.btcbusd, 100, Resolution.MINUTE)
    +history_trade_bars = self.history[TradeBar](self.btcusd, 100, Resolution.MINUTE)
     
     # QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.btcbusd, 100, Resolution.MINUTE)
    +history_quote_bars = self.history[QuoteBar](self.btcusd, 100, Resolution.MINUTE)
     
     # Tick objects
    -history_ticks = self.history[Tick](self.btcbusd, timedelta(seconds=10), Resolution.TICK)
    +history_ticks = self.history[Tick](self.btcusd, timedelta(seconds=10), Resolution.TICK)
    // TradeBar objects 
     var historyTradeBars = History(_symbol, 100, Resolution.Daily);
     
    @@ -215427,7 +184954,7 @@ 

    Universe Selection

    - To select a dynamic universe of Binance US Crypto pairs, call the + To select a dynamic universe of Bitfinex Crypto pairs, call the AddUniverse @@ -215447,19 +184974,19 @@

    Universe Selection

    def initialize(self) -> None:
         self.universe_settings.asynchronous = True
    -    self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH)
    -    self._universe = self.add_universe(CryptoUniverse.binance_us(self.universe_selection_filter))
    +    self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN)
    +    self._universe = self.add_universe(CryptoUniverse.bitfinex(self.universe_selection_filter))
     
     def universe_selection_filter(self, universe_day):
         return [c.symbol for c in universe_day if c.volume >= 100 and c.volume_in_usd > 10000]
    public override void Initialize()
     {
         UniverseSettings.Asynchronous = true;
    -    SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash);
    -    _universe = AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
    +    SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
    +    _universe = AddUniverse(CryptoUniverse.Bitfinex(UniverseSelectionFilter));
     }
     
    -private IEnumerable<Symol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
     {
         return from c in universeDay
                where c.Volume >= 100m && c.VolumeInUsd > 10000m
    @@ -215593,7 +185120,7 @@ 

    Remove Subscriptions

    method.

    -
    self.remove_security(self.btcbusd)
    +
    self.remove_security(self.btcusd)
    RemoveSecurity(_symbol);

    @@ -215624,172 +185151,135 @@

    Supported Assets

    - - - - - - - - - - - - - - - + + - - @@ -215797,173 +185287,130 @@

    Supported Assets

    ARBUSDT - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -217574,73 +186981,79 @@

    Supported Assets

    XRPUSDT + + @@ -217653,7 +187066,7 @@

    Example Applications

    - The Binance US Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: + The Bitfinex Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies:

    • @@ -217670,7 +187083,7 @@

      Classic Algorithm Example

      - The following example algorithm buys and holds Bitcoin through the Binance US exchange: + The following example algorithm buys and holds Bitcoin through the Bitfinex exchange:

      from AlgorithmImports import *
      @@ -217682,17 +187095,16 @@ 

      self.set_start_date(2024, 9, 1) self.set_end_date(2024, 12, 31) self.universe_settings.asynchronous = True - # Set USDT as the account currency so we can trade BTCUSDT. - self.set_account_currency('USDT', 100_000) - # Binance US accepts Cash account type only. AccountType.MARGIN - # results in an exception. - self.set_brokerage_model(BrokerageName.BINANCE_US, AccountType.CASH) - # Add BTCUSDT data. - self._btc = self.add_crypto("BTCUSDT", Resolution.MINUTE, Market.BINANCE_US) + self.set_cash(100_000) + # Bitfinex accepts both Cash and Margin account types. Select the + # one you need for the best reality modeling. + self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN) + # Add BTCUSD data. + self._btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BITFINEX) # Historical data history = self.history(self._btc.symbol, 30, Resolution.DAILY) - # Add a Crypto universe that selects Crypto pairs on Binance US. - universe = self.add_universe(CryptoUniverse.binance_us(self._select_assets)) + # Add a Crypto universe that selects Crypto pairs on Bitfinex. + universe = self.add_universe(CryptoUniverse.bitfinex(self._select_assets)) # Historical Universe data universe_history = self.history(universe, 30, Resolution.DAILY) for (universe_symbol, time), universe_day in universe_history.items(): @@ -217709,29 +187121,25 @@

      and universe_item.volume_in_usd > 10_000_000] def on_data(self, slice: Slice) -> None: - # Speculate-invest all available free cash on BTCUSDT, repecting + # Speculate-invest all available free cash on BTCUSD, repecting # the order quantity restrictions to avoid invalid orders. if self.portfolio.cash_book['BTC'].amount != 0: return # Define a buffer so that we can scale down the order size, # avoiding trading errors. buffer = max( - BinanceFeeModel.TAKER_TIER_1_FEE, + BitfinexFeeModel.TAKER_FEE, self.settings.free_portfolio_value_percentage ) quantity = ( - self.portfolio.cash_book['USDT'].amount + self.portfolio.cash_book['USD'].amount / self._btc.ask_price * (1-buffer) ) # Check if the quantity exceeds the minimum order size. On - # Binance US, the minimum order size is measured in the quote - # currency (USDT in this case). - minimum_order_size = ( - self._btc.symbol_properties.minimum_order_size - / self._btc.ask_price - ) - if abs(quantity) < minimum_order_size: + # Bitfinex, the minimum order size is measured in the base + # currency (BTC in this case). + if abs(quantity) < self._btc.symbol_properties.minimum_order_size: return self.market_order(self._btc, quantity)

      public class CoinAPIDataAlgorithm : QCAlgorithm
      @@ -217742,18 +187150,17 @@ 

      { SetStartDate(2024, 9, 1); SetEndDate(2024, 12, 31); - // Set USDT as the account currency so we can trade BTCUSDT. - SetAccountCurrency("USDT", 100000); UniverseSettings.Asynchronous = true; - // Binance US accepts Cash account type only. AccountType.Margin - // results in an exception. - SetBrokerageModel(BrokerageName.BinanceUS, AccountType.Cash); - // Add BTCUSDT data. - _btc = AddCrypto("BTCUSDT", Resolution.Minute, Market.BinanceUS); + SetCash(100000); + // Bitfinex accepts both Cash and Margin account types. Select the + // one you need for the best reality modeling. + SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin); + // Add BTCUSD data. + _btc = AddCrypto("BTCUSD", Resolution.Minute, Market.Bitfinex); // Historical data var history = History(_btc.Symbol, 30, Resolution.Daily); - // Add a Crypto universe that selects trading pairs on Binance US. - var universe = AddUniverse(CryptoUniverse.BinanceUS(SelectAssets)); + // Add a Crypto universe that selects trading pairs on Bitfinex. + var universe = AddUniverse(CryptoUniverse.Bitfinex(SelectAssets)); // Historical Universe data var universeHistory = History(universe, 30, Resolution.Daily); foreach (var universeDay in universeHistory) @@ -217779,7 +187186,7 @@

      public override void OnData(Slice slice) { - // Speculate-invest all available free cash on BTCUSDT, repecting + // Speculate-invest all available free cash on BTCUSD, repecting // the order quantity restrictions to avoid invalid orders. if (Portfolio.CashBook["BTC"].Amount != 0) { @@ -217787,13 +187194,12 @@

      } // Define a buffer so that we can scale down the order size, // avoiding trading errors. - var buffer = Math.Max(BinanceFeeModel.TakerTier1Fee, Settings.FreePortfolioValuePercentage); - var quantity = Portfolio.CashBook["USDT"].Amount / _btc.AskPrice * (1-buffer); + var buffer = Math.Max(BitfinexFeeModel.TakerFee, Settings.FreePortfolioValuePercentage); + var quantity = Portfolio.CashBook["USD"].Amount / _btc.AskPrice * (1-buffer); // Check if the quantity exceeds the minimum order size. On - // Binance US, the minimum order size is measured in the quote - // currency (USDT in this case). - var minimumOrderSize = _btc.SymbolProperties.MinimumOrderSize / _btc.AskPrice; - if (Math.Abs(quantity) < minimumOrderSize) + // Bitfinex, the minimum order size is measured in the base + // currency (BTC in this case). + if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize) { return; } @@ -217805,7 +187211,7 @@

      Framework Algorithm Example

      - The following example algorithm creates a dynamic universe of Crypto pairs on the Binance US exchange and then forms a equal-weighted portfolio of all the pairs in the universe: + The following example algorithm creates a dynamic universe of Crypto pairs on the Bitfinex exchange and then forms a equal-weighted portfolio of all the pairs in the universe:

      from AlgorithmImports import *
      @@ -217816,20 +187222,24 @@ 

      def initialize(self) -> None: self.set_start_date(2024, 9, 1) self.set_end_date(2024, 12, 31) - self.set_cash(1_000_000) + self.set_cash(100000) self.settings.free_portfolio_value_percentage = 0.05 + # Bitfinex accepts both Cash and Margin account types, select the one you need for the best reality modeling. + self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN) + # Warm up the security with the last known price to avoid conversion error self.settings.seed_initial_prices = True self.universe_settings.asynchronous = True - # Add Crypto Universe Selection that select crypto pairs in BinanceUS exchange - self.add_universe(CryptoUniverse.binance_us(self._select_assets)) - # Get the pairs on Binance US that have USD as the quote currency. + self.universe_settings.resolution = Resolution.MINUTE + # Add Crypto Universe Selection that select crypto pairs in Bitfinex exchange + self.add_universe(CryptoUniverse.bitfinex(self._select_assets)) + # Get the pairs on Bitfinex that have USD as the quote currency. self._market_pairs = [ x.key.symbol - for x in self.symbol_properties_database.get_symbol_properties_list(Market.BINANCE_US) + for x in self.symbol_properties_database.get_symbol_properties_list(Market.BITFINEX) if x.value.quote_currency == self.account_currency ] - self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(minutes=20), 0.025, None)) + self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(hours=4), 0.025, None)) # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel()) @@ -217839,7 +187249,7 @@

      # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return. pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:] return [c.symbol for c in pairs] - + def on_securities_changed(self, changes: SecurityChanges) -> None: for security in changes.added_securities: # Historical data @@ -217847,32 +187257,34 @@

      self.debug(f"We got {len(history)} items from our history request")

      public class CoinAPIDataAlgorithm : QCAlgorithm
       {
      -    private Symbol _btcusd;
           private List<string> _marketPairs;
           
           public override void Initialize()
           {
               SetStartDate(2024, 9, 1);
               SetEndDate(2024, 12, 31);
      -        SetCash(1000000);
      +        SetCash(100000);
               Settings.FreePortfolioValuePercentage = 0.05m;
      +        // Bitfinex accepts both Cash and Margin account types, select the one you need for the best reality modeling.
      +        SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
      +
               // Warm up the security with the last known price to avoid conversion error
               Settings.SeedInitialPrices = true;
               UniverseSettings.Asynchronous = true;
               UniverseSettings.Resolution = Resolution.Minute;
      -        // Add Crypto Universe Selection that select crypto pairs in BinanceUS exchange
      -        AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter));
      -        // Get the pairs on Binance US that have USD as the quote currency.
      -        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.BinanceUS)
      +        // Add Crypto Universe Selection that select crypto pairs in Bitfinex exchange            
      +        AddUniverse(CryptoUniverse.Bitfinex(SelectAssets));
      +        // Get the pairs on Bitfinex that have USD as the quote currency.
      +        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Bitfinex)
                   .Where(x => x.Value.QuoteCurrency == AccountCurrency)
                   .Select(x => x.Key.Symbol)
                   .ToList();
      -        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null) );
      +        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(4), 0.025, null) );
               // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
               SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
           }
       
      -    private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
      +    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
           {
               // Select pairs where the quote currency is USD.
               return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
      @@ -217894,16 +187306,16 @@ 

      }

      - Research Example + Research Example

      - The following example lists crypto-currency pairs with the greatest dollar volume in the BinanceUS exchange: + The following example lists crypto-currency pairs with the greatest dollar volume in the Bitfinex exchange:

      var qb = new QuantBook();
       
       // Add Cryptocurrency pair
      -var symbol = qb.AddCrypto("BTCUSDT", market:Market.BinanceUS).Symbol;
      +var symbol = qb.AddCrypto("BTCUSDT", market:Market.Bitfinex).Symbol;
       
       // Historical data
       var history = qb.History(symbol, 30, Resolution.Daily);
      @@ -217921,7 +187333,7 @@ 

      .Take(5) .Select(x => x.Symbol); } -var universe = qb.AddUniverse(CryptoUniverse.BinanceUS(UniverseSelectionFilter)); +var universe = qb.AddUniverse(CryptoUniverse.Bitfinex(UniverseSelectionFilter)); // Historical Universe data var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time); @@ -217936,7 +187348,7 @@

      qb = QuantBook()
       
       # Add Cryptocurrency pair
      -symbol = qb.add_crypto("BTCUSDT", market=Market.BINANCE_US).symbol
      +symbol = qb.add_crypto("BTCUSDT", market=Market.BITFINEX).symbol
       
       # Historical data
       history = qb.history(symbol, 30, Resolution.DAILY)
      @@ -217950,7 +187362,7 @@ 

      key=lambda x: x.volume_in_usd, reverse=True)[:5] return [x.symbol for x in selected] -universe = qb.add_universe(CryptoUniverse.binance_us(universe_selection_filter)) +universe = qb.add_universe(CryptoUniverse.bitfinex(universe_selection_filter)) # Historical Universe data history = qb.universe_history(universe, qb.time-timedelta(30), qb.time) @@ -217966,7 +187378,7 @@

      Data Point Attributes

      - The Binance US Crypto Price dataset provides + The Bitfinex Crypto Price dataset provides TradeBar @@ -218032,22 +187444,29 @@

       

      - +
      -
      -

      CoinAPI

      -

      Bitfinex Crypto Price Data

      +
      +

      QuantConnect

      +

      Bybit Crypto Future Margin Rate Data

      Introduction

      - The Bitfinex Crypto Price Data by CoinAPI is for Cryptocurrency price and volume data points. The data covers 570 Cryptocurrency pairs, starts in January 2013, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Bitfinex. + The Bybit Crypto Future Margin Rate Data by QuantConnect is for Cryptocurrency Futures margin interest data points. The data covers 631 Cryptocurrency pairs, starts in August 2020, and is delivered on a daily update frequency. This dataset is created by downloading data using Bybit API.

      - For more information about the Bitfinex Crypto Price Data dataset, including CLI commands and pricing, see the - + This dataset is an important companion to the + + Bybit Crypto Future Price Data + + dataset because it contains information on margin interest data to model margin costs. +

      +

      + For more information about the Bybit Crypto Future Margin Rate Data dataset, including CLI commands and pricing, see the + dataset listing . @@ -218061,10 +187480,7 @@

      About the Provider

      - - CoinAPI - - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month.

      @@ -218073,24 +187489,28 @@

      Getting Started

      - The following snippet demonstrates how to request data from the Bitfinex Crypto Price dataset: + The following snippet demonstrates how to request data from the Bybit Crypto Future Margin Rate dataset:

      -
      # Bitfinex accepts both Cash and Margin type account.
      -self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.CASH)
      -#self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN)
      -
      -self.btcusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BITFINEX).symbol
      +   
      def Initialize(self) -> None:
      +    self.SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin)
       
      -self._universe = self.add_universe(CryptoUniverse.bitfinex(self.universe_selection_filter))
      -
      // Bitfinex accepts both Cash and Margin type account.
      -SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Cash);
      -//SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
      +    self.crypto_future_symbol = self.AddCryptoFuture("BTCBUSD", Resolution.Minute).Symbol
      +
      +
      private Symbol _cryptoFutureSymbol;
       
      -_symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.Bitfinex).Symbol;
      +public override void Initialize
      +{
      +    SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
       
      -_universe = AddUniverse(CryptoUniverse.Bitfinex(UniverseSelectionFilter));
      + // perpetual futures does not have a filter function + _cryptoFutureSymbol = AddCryptoFuture("BTCBUSD", Resolution.Minute).Symbol; +} +
      +

      + The Bybit Crypto Future Margin Rate data is added to your algorithm along with the market data when you add a crypto future subscription. +

      @@ -218117,7 +187537,7 @@

      Data Summary

      Start Date

    @@ -218125,7 +187545,7 @@

    Data Summary

    Asset Coverage @@ -218133,7 +187553,7 @@

    Data Summary

    Data Density @@ -218141,7 +187561,7 @@

    Data Summary

    Resolution @@ -218171,51 +187591,60 @@

    Requesting Data

    - To add Bitfinex Crypto Price data to your algorithm, call the + To add Bybit Crypto Future Margin Rate data to your algorithm, call the - AddCrypto + AddCryptoFuture - add_crypto + add_crypto_future - method. Save a reference to the Crypto + method. Save a reference to the Crypto Future Symbol so you can access the data later in your algorithm.

    -
    class CoinAPIDataAlgorithm(QCAlgorithm):
    +   
    from AlgorithmImports import *
    +from QuantConnect.DataSource import *
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2020, 6, 1)
             self.set_end_date(2021, 6, 1)
    -        self.set_cash(100000)
     
    -        # Bitfinex accepts both Cash and Margin type account.
    -        self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN)
    +        # Set Account Currency to Tether
    +        self.set_account_currency("USDT", 100000)
    +
    +        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
             
    -        self.btcusd = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BITFINEX).symbol
    + crypto_future = self.add_crypto_future("BTCUSDT", Resolution.MINUTE) + # perpetual futures does not have a filter function + self.btcusdt = crypto_future.symbol
    public class CoinAPIDataAlgorithm : QCAlgorithm
     {
    -    private Symbol _symbol;
    +    private Symbol _symbol ;
         
         public override void Initialize()
         {
             SetStartDate(2020, 6, 1);
             SetEndDate(2021, 6, 1);
    -        SetCash(100000);
     
    -        // Bitfinex accepts both Cash and Margin type account.
    -        SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
    +        // Set Account Currency to Tether
    +        SetAccountCurrency("USDT", 100000);
    +
    +        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
             
    -        _symbol = AddCrypto("BTCUSD", Resolution.Minute, Market.Bitfinex).Symbol;
    +        var cryptoFuture = AddCryptoFuture("BTCUSDT", Resolution.Minute);
    +        // perpetual futures does not have a filter function
    +        _symbol = cryptoFuture.Symbol;
         }
     }

    - For more information about creating Crypto subscriptions, see - + For more information about creating Crypto Future subscriptions, see + Requesting Data . @@ -218227,34 +187656,20 @@

    Accessing Data

    - To get the current Bitfinex Crypto Price data, index the - - Bars - - - bars - - , - - QuoteBars - - - quote_bars - - , or + To get the current Bybit Crypto Margin Rate data, index the - Ticks + MarginInterestRates - ticks + margin_interest_rates - properties of the current + property of the current Slice - with the Crypto + with the Crypto Future Symbol @@ -218274,42 +187689,17 @@

    Accessing Data

    def on_data(self, slice: Slice) -> None:
    -    if self.btcusd in slice.bars:
    -        trade_bar = slice.bars[self.btcusd]
    -        self.log(f"{self.btcusd} close at {slice.time}: {trade_bar.close}")
    -
    -    if self.btcusd in slice.quote_bars:
    -        quote_bar = slice.quote_bars[self.btcusd]
    -        self.log(f"{self.btcusd} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    if self.btcusd in slice.ticks:
    -        ticks = slice.ticks[self.btcusd]
    -        for tick in ticks:
    -            self.log(f"{self.btcusd} price at {slice.time}: {tick.price}")
    + if self.btcusdt in slice.margin_interest_rates: + interest_rate = slice.margin_interest_rates[self.btcusdt].interest_rate + self.log(f"{self.btcusdt} close at {slice.time}: {interest_rate}")
    public override void OnData(Slice slice)
     {
    -    if (slice.Bars.ContainsKey(_symbol))
    -    {
    -        var tradeBar = slice.Bars[_symbol];
    -        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    if (slice.QuoteBars.ContainsKey(_symbol))
    -    {
    -        var quoteBar = slice.QuoteBars[_symbol];
    -        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    if (slice.Ticks.ContainsKey(_symbol))
    +    if (slice.MarginInterestRates.ContainsKey(_symbol))
         {
    -        var ticks = slice.Ticks[_symbol];
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    -        }
    +        var interestRate = slice.MarginInterestRates[_symbol].InterestRate;
    +        Log($"{_symbol} price at {slice.Time}: {interestRate}");
         }
    -}
    -
    +}

    You can also iterate through all of the data objects in the current @@ -218320,46 +187710,23 @@

    Accessing Data

    def on_data(self, slice: Slice) -> None:
    -    for symbol, trade_bar in slice.bars.items():
    -        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    -
    -    for symbol, quote_bar in slice.quote_bars.items():
    -        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    -
    -    for symbol, ticks in slice.ticks.items():
    -        for tick in ticks:
    -            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    + for symbol, margin_interest_rate in slice.margin_interest_rates.items(): + interest_rate = margin_interest_rate.interest_rate + self.log(f"{symbol} close at {slice.time}: {interest_rate}")
    public override void OnData(Slice slice)
     {
    -    foreach (var kvp in slice.Bars)
    -    {
    -        var symbol = kvp.Key;
    -        var tradeBar = kvp.Value;
    -        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    -    }
    -
    -    foreach (var kvp in slice.QuoteBars)
    -    {
    -        var symbol = kvp.Key;
    -        var quoteBar = kvp.Value;
    -        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    -    }
    -
    -    foreach (var kvp in slice.Ticks)
    +    foreach (var kvp in slice.MarginInterestRates)
         {
             var symbol = kvp.Key;
    -        var ticks = kvp.Value;
    -        foreach (var tick in ticks)
    -        {
    -            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    -        }
    +        var marginInterestRate = kvp.Value;
    +        var interestRate = marginInterestRate.InterestRate;
    +        Log($"{symbol} price at {slice.Time}: {interestRate}");
         }
    -}
    -
    +}

    - For more information about accessing Crypto data, see - + For more information about accessing Crypto Future data, see + Handling Data . @@ -218371,14 +187738,21 @@

    Historical Data

    - To get historical Bitfinex Crypto Price data, call the + To get historical Bybit Crypto Future Margin Rate data, call the - History + History<MarginInterestRate> history - method with the Crypto + method with + + + MarginInterestRate + + data type and + + the Crypto Future Symbol @@ -218386,24 +187760,11 @@

    Historical Data

    # DataFrame
    -history_df = self.history(self.btcusd, 100, Resolution.DAILY)
    -
    -# TradeBar objects
    -history_trade_bars = self.history[TradeBar](self.btcusd, 100, Resolution.MINUTE)
    -
    -# QuoteBar objects
    -history_quote_bars = self.history[QuoteBar](self.btcusd, 100, Resolution.MINUTE)
    -
    -# Tick objects
    -history_ticks = self.history[Tick](self.btcusd, timedelta(seconds=10), Resolution.TICK)
    -
    // TradeBar objects 
    -var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    -
    -// QuoteBar objects 
    -var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    +history_df = self.history(MarginInterestRate, self.btcusdt, 100, Resolution.DAILY)
     
    -// Tick objects 
    -var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +# MarginInterestRate objects +history = self.history[MarginInterestRate](self.btcusdt, 100, Resolution.DAILY) +
    var history = History<MarginInterestRate>(_symbol, 100, Resolution.Daily);

    For more information about historical data, see @@ -218415,155 +187776,6 @@

    Historical Data

    -

    Universe Selection

    - - -

    - To select a dynamic universe of Bitfinex Crypto pairs, call the - - AddUniverse - - - add_universe - - method with a - - CryptoUniverse - - object. A - - Crypto universe - - uses a selection function to select Crypto pairs based on their OHLCV and dollar volume of the previous day as of midnight Coordinated Universal Time (UTC). -

    -
    -
    def initialize(self) -> None:
    -    self.universe_settings.asynchronous = True
    -    self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN)
    -    self._universe = self.add_universe(CryptoUniverse.bitfinex(self.universe_selection_filter))
    -
    -def universe_selection_filter(self, universe_day):
    -    return [c.symbol for c in universe_day if c.volume >= 100 and c.volume_in_usd > 10000]
    -
    public override void Initialize()
    -{
    -    UniverseSettings.Asynchronous = true;
    -    SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
    -    _universe = AddUniverse(CryptoUniverse.Bitfinex(UniverseSelectionFilter));
    -}
    -
    -private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    -{
    -    return from c in universeDay
    -           where c.Volume >= 100m && c.VolumeInUsd > 10000m
    -           select c.Symbol;
    -}
    -
    -

    - For more information about universe settings, see - - Settings - - . -

    - - - -

    Universe History

    - - -

    - You can get historical universe data in an algorithm and in the Research Environment. -

    -

    - Historical Universe Data in Algorithms -

    -

    - To get historical universe data in an algorithm, call the - - History - - - history - - method with the - - Universe - - object, and the lookback period. If there is no data in the period you request, the history result is empty. -

    -
    -
    var history = History(_universe, 30, Resolution.Daily);
    -foreach (var universeDay in history)
    -{
    -    foreach (CryptoUniverse universeItem in universeDay)
    -    {
    -        Log($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    -    }
    -}
    -
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    -history_df = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
    -
    -# Series example where the values are lists of CryptoUniverse objects: 
    -history = self.history(self._universe, 30, Resolution.DAILY)
    -for (univere_symbol, time), universe_day in history.items():
    -    for universe_item in universe_day:
    -        self.log(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    -
    -

    - Historical Universe Data in Research -

    -

    - To get historical universe data in research, call the - - UniverseHistory - - - universe_history - - method with the - - Universe - - object, and the lookback period. The - - UniverseHistory - - - universe_history - - returns the filtered universe. If there is no data in the period you request, the history result is empty. -

    -
    -
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var universeDay in universeHistory)
    -{
    -    foreach (CryptoUniverse universeItem in universeDay)
    -    {
    -        Console.WriteLine($"{universeItem.Symbol} price at {universeItem.EndTime}: {universeItem.Close}");
    -    }
    -}
    -
    # DataFrame example where the columns are the CryptoUniverse attributes: 
    -history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    -
    -# Series example where the values are lists of CryptoUniverse objects: 
    -universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (univere_symbol, time), universe_day in universe_history.items():
    -    for universe_item in universe_day:
    -        print(f"{universe_item.symbol} price at {universe_item.end_time}: {universe_item.close}")
    -
    -

    - You can call the - - History - - - history - - method in Research. -

    - - -

    Remove Subscriptions

    @@ -218585,7 +187797,7 @@

    Remove Subscriptions

    method.

    -
    self.remove_security(self.btcusd)
    +
    self.remove_security(self.btcusdt)
    RemoveSecurity(_symbol);

    @@ -218609,27 +187821,27 @@

    Supported Assets

    - The following table shows the available Cryptocurrency pairs: + The following table shows the available Crypto Future pairs:

    + + + + + + + + + + + @@ -218789,376 +188030,407 @@

    Supported Assets

    AVAXUSDT + + + + + + + + + + + + + @@ -219169,10 +188441,10 @@

    Supported Assets

    EOSUSDT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -220531,144 +189948,117 @@

    Example Applications

    - The Bitfinex Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: + The Binance Crypto Future Margin Rate dataset enables correct margin cost so you can accurately design strategies for Cryptocurrencies with term structure. Examples include the following strategies:

    • - Buy and hold + Horizontal/Diagonal arbitrage with the underlying Cryptocurrencies
    • - Trading Cryptocurrency volatility and price action + Trade Contango/Backwardation predictions
    • - Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation + Hedge for illiquid Cryptocurrencies

    Classic Algorithm Example

    - The following example algorithm buys and holds Bitcoin through the Bitfinex exchange: + The following example algorithm holds a long position in the BTCUSDT perpetual Future contract on the Bybit exchange. When the margin interest rate is relatively low, it flips to a short position.

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    +class BybitCryptoFutureDataAlgorithm(QCAlgorithm):
    +
    +    # Add an indicator to track the low of trailing margin interest rates.
    +    _low_interest_rate = Minimum(10)
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        self.universe_settings.asynchronous = True
    -        self.set_cash(100_000)
    -        # Bitfinex accepts both Cash and Margin account types. Select the
    -        # one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN)
    -        # Add BTCUSD data.
    -        self._btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.BITFINEX)
    +        # Set Account Currency to USDT, since USD cannot be used to trade.
    +        self.set_cash("USDT", 100_000)
    +        # Bybit  accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    +        # Seed the price of each asset with its last known price to avoid trading errors.
    +        self.settings.seed_initial_prices = True
    +        # Requesting data, we only trade on BTCUSDT Future in Bybit  exchange
    +        # Perpetual futures does not have a filter function.
    +        self._future = self.add_crypto_future("BTCUSDT", Resolution.DAILY)
             # Historical data
    -        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    -        # Add a Crypto universe that selects Crypto pairs on Bitfinex.
    -        universe = self.add_universe(CryptoUniverse.bitfinex(self._select_assets))
    -        # Historical Universe data
    -        universe_history = self.history(universe, 30, Resolution.DAILY)
    -        for (universe_symbol, time), universe_day in universe_history.items():
    -            for universe_item in universe_day:
    -                symbol = universe_item.symbol
    -                price = universe_item.close
    -
    -    def _select_assets(self, universe_day):
    -        # Filter for materially traded Crypto pairs with significant 
    -        # size and dollar volume, assuming higher capital flow in for 
    -        # higher return.
    -        return [universe_item.symbol for universe_item in universe_day
    -                if universe_item.volume >= 100 
    -                and universe_item.volume_in_usd > 10_000_000]
    +        history = self.history[MarginInterestRate](self._future.symbol, 10, Resolution.DAILY)
    +        for data_point in history:
    +            self._low_interest_rate.update(data_point.end_time, data_point.interest_rate)
     
         def on_data(self, slice: Slice) -> None:
    -        # Speculate-invest all available free cash on BTCUSD, repecting 
    -        # the order quantity restrictions to avoid invalid orders.
    -        if self.portfolio.cash_book['BTC'].amount != 0:
    -            return
    -        # Define a buffer so that we can scale down the order size,
    -        # avoiding trading errors.
    -        buffer = max(
    -            BitfinexFeeModel.TAKER_FEE, 
    -            self.settings.free_portfolio_value_percentage
    -        )
    -        quantity = (
    -            self.portfolio.cash_book['USD'].amount
    -            / self._btc.ask_price
    -            * (1-buffer)
    -        )
    -        # Check if the quantity exceeds the minimum order size. On 
    -        # Bitfinex, the minimum order size is measured in the base
    -        # currency (BTC in this case).
    -        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    +        # Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL
    +        # Or you can calculate the trade size on keeping the quote currency constant
    +        if self._future.symbol not in slice.margin_interest_rates:
                 return
    -        self.market_order(self._btc, quantity)
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +        interest_rate = slice.margin_interest_rates[self._future.symbol].interest_rate
    +        self.plot('Margin Interest Rate', str(self._future.symbol), interest_rate)
    +        # Short when margin interest rates are relatively low. Otherwise, long.
    +        if interest_rate <= self._low_interest_rate.current.value:
    +            if not self._future.holdings.is_short:
    +                self.set_holdings(self._future.symbol, -0.5)
    +        elif not self._future.holdings.is_long:
    +            self.set_holdings(self._future.symbol, 1)
    +        # Update the indicator.
    +        self._low_interest_rate.update(self.time, interest_rate)
    +
    public class BybitCryptoFutureDataAlgorithm : QCAlgorithm
     {
    -    private Crypto _btc;
    -    
    +    private CryptoFuture _future;
    +    // Add an indicator to track the low of trailing margin interest rates.
    +    private Minimum _lowInterestRate = new(10);
    +
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        UniverseSettings.Asynchronous = true;
    -        SetCash(100000);
    -        // Bitfinex accepts both Cash and Margin account types. Select the
    -        // one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
    -        // Add BTCUSD data.
    -        _btc = AddCrypto("BTCUSD", Resolution.Minute, Market.Bitfinex);   
    +        // Set Account Currency to USDT, since USD cannot be used to trade.
    +        SetCash("USDT", 100000);
    +        // Bybit  accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    +        // Seed the price of each asset with its last known price to avoid trading errors.
    +        Settings.SeedInitialPrices = true;
    +        // Requesting data, we only trade on BTCUSDT Future in Bybit  exchange
    +        // Perpetual futures does not have a filter function.
    +        _future = AddCryptoFuture("BTCUSDT", Resolution.Daily);
             // Historical data
    -        var history = History(_btc.Symbol, 30, Resolution.Daily);
    -        // Add a Crypto universe that selects trading pairs on Bitfinex.
    -        var universe = AddUniverse(CryptoUniverse.Bitfinex(SelectAssets));
    -        // Historical Universe data
    -        var universeHistory = History(universe, 30, Resolution.Daily);
    -        foreach (var universeDay in universeHistory)
    +        var history = History<MarginInterestRate>(_future.Symbol, 10, Resolution.Daily);
    +        foreach (var dataPoint in history)
             {
    -            foreach (CryptoUniverse universeItem in universeDay)
    -            {
    -                var symbol = universeItem.Symbol;
    -                var price = universeItem.Close;
    -            }
    +            _lowInterestRate.Update(dataPoint.EndTime, dataPoint.InterestRate);
             }
         }
     
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    -    {
    -        // Filter for materially traded Crypto pairs with significant 
    -        // size and dollar volume, assuming higher capital flow in for 
    -        // higher return.
    -        return from universeItem in universeDay
    -                where universeItem.Volume >= 100m 
    -                && universeItem.VolumeInUsd > 10000000m
    -                select universeItem.Symbol;
    -    }
    -
         public override void OnData(Slice slice)
         {
    -        // Speculate-invest all available free cash on BTCUSD, repecting 
    -        // the order quantity restrictions to avoid invalid orders.
    -        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        // Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL
    +        // Or you can calculate the trade size on keeping the quote currency constant
    +        if (!slice.MarginInterestRates.TryGetValue(_future.Symbol, out var dataPoint))
             {
                 return;
             }
    -        // Define a buffer so that we can scale down the order size,
    -        // avoiding trading errors.
    -        var buffer = Math.Max(BitfinexFeeModel.TakerFee, Settings.FreePortfolioValuePercentage);
    -        var quantity = Portfolio.CashBook["USD"].Amount / _btc.AskPrice * (1-buffer);
    -        // Check if the quantity exceeds the minimum order size. On 
    -        // Bitfinex, the minimum order size is measured in the base
    -        // currency (BTC in this case).
    -        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +        var interestRate = dataPoint.InterestRate;
    +        Plot("Margin Interest Rate", _future.Symbol.ToString(), interestRate);
    +        // Short when margin interest rates are relatively low. Otherwise, long.
    +        if (interestRate <= _lowInterestRate)
             {
    -            return;
    +            if (!_future.Holdings.IsShort)
    +            {
    +                SetHoldings(_future.Symbol, -0.5);
    +            }
             }
    -        MarketOrder(_btc, quantity);
    +        else if (!_future.Holdings.IsLong)
    +        {
    +            SetHoldings(_future.Symbol, 1);
    +        }
    +        // Update the indicator.
    +        _lowInterestRate.Update(Time, interestRate);
         }
     }
    @@ -220676,165 +190066,147 @@

    Framework Algorithm Example

    - The following example algorithm creates a dynamic universe of Crypto pairs on the Bitfinex exchange and then forms a equal-weighted portfolio of all the pairs in the universe: + The following example algorithm holds a long position in the BTCUSDT perpetual Future contract on the Bybit exchange. When the margin interest rate is relatively low, it flips to a short position.

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    +class BybitCryptoFutureDataAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.settings.free_portfolio_value_percentage = 0.05
    -        # Bitfinex accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BITFINEX, AccountType.MARGIN)
    -
    -        # Warm up the security with the last known price to avoid conversion error
    +        self.settings.free_portfolio_value_percentage = 0.1
    +        # Set Account Currency to USDT, since USD cannot be used to trade.
    +        self.set_cash("USDT", 100000)
    +        # Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    +        # Seed the price of each asset with its last known price to avoid trading errors.
             self.settings.seed_initial_prices = True
    -        self.universe_settings.asynchronous = True
    -        self.universe_settings.resolution = Resolution.MINUTE
    -        # Add Crypto Universe Selection that select crypto pairs in Bitfinex exchange
    -        self.add_universe(CryptoUniverse.bitfinex(self._select_assets))
    -        # Get the pairs on Bitfinex that have USD as the quote currency.
    -        self._market_pairs = [
    -            x.key.symbol 
    -            for x in self.symbol_properties_database.get_symbol_properties_list(Market.BITFINEX) 
    -            if x.value.quote_currency == self.account_currency
    -        ]
    -        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(hours=4), 0.025, None))
    +        self.universe_settings.resolution = Resolution.DAILY
    +        self.universe_settings.leverage = 2
    +        # We only trade on BTCUSDT Future in Bybit exchange
    +        symbols = Symbol.create("BTCUSDT", SecurityType.CRYPTO_FUTURE, Market.BYBIT)
    +        self.add_universe_selection(ManualUniverseSelectionModel(symbols))
    +        # Custom alpha model to emit insights based on the Crypto Future price data
    +        self.add_alpha(CryptoFutureAlphaModel())
             # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
             self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +        self.set_execution(ImmediateExecutionModel())
     
    -    def _select_assets(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    -        # Select pairs where the quote currency is USD.
    -        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    -        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    -        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    -        return [c.symbol for c in pairs]
     
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +class CryptoFutureAlphaModel(AlphaModel):
    +
    +    _min_by_symbol = {}
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        insights = []
    +        for symbol, low_interest_rate in self._min_by_symbol.items():
    +            # Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL
    +            # Or you can calculate the trade size on keeping the quote currency constant
    +            if symbol not in slice.margin_interest_rates:
    +                continue
    +            interest_rate = slice.margin_interest_rates[symbol].interest_rate
    +            algorithm.plot('Margin Interest Rate', str(symbol), interest_rate)
    +            # Short when margin interest rates are relatively low. Otherwise, long.
    +            if interest_rate <= low_interest_rate.current.value:
    +                direction = InsightDirection.DOWN
    +            else:
    +                direction = InsightDirection.UP
    +            insights.append(Insight.price(symbol, timedelta(1), direction))
    +            # Update the indicator.
    +            low_interest_rate.update(slice.time, interest_rate)
    +        return insights
    +
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
             for security in changes.added_securities:
    +            symbol = security.symbol
    +            # Add an indicator to track the low of trailing margin interest rates.
    +            self._min_by_symbol[symbol] = Minimum(10)
                 # Historical data
    -            history = self.history(security.symbol, 30, Resolution.DAILY)
    -            self.debug(f"We got {len(history)} items from our history request")
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +            history = algorithm.history[MarginInterestRate](symbol, 10, Resolution.DAILY)
    +            for data_point in history:
    +                self._min_by_symbol[symbol].update(data_point.end_time, data_point.interest_rate)
    +        for security in changes.removed_securities:
    +            self._min_by_symbol.pop(security.symbol, None)
    +
    public class BybitCryptoFutureDataAlgorithm : QCAlgorithm
     {
    -    private List<string> _marketPairs;
    -    
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        Settings.FreePortfolioValuePercentage = 0.05m;
    -        // Bitfinex accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
    -
    -        // Warm up the security with the last known price to avoid conversion error
    +        Settings.FreePortfolioValuePercentage = 0.1m;
    +        // Set Account Currency to USDT, since USD cannot be used to trade.
    +        SetCash("USDT", 100000);
    +        // Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    +        // Seed the price of each asset with its last known price to avoid trading errors.
             Settings.SeedInitialPrices = true;
    -        UniverseSettings.Asynchronous = true;
    -        UniverseSettings.Resolution = Resolution.Minute;
    -        // Add Crypto Universe Selection that select crypto pairs in Bitfinex exchange            
    -        AddUniverse(CryptoUniverse.Bitfinex(SelectAssets));
    -        // Get the pairs on Bitfinex that have USD as the quote currency.
    -        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Bitfinex)
    -            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    -            .Select(x => x.Key.Symbol)
    -            .ToList();
    -        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(4), 0.025, null) );
    +        UniverseSettings.Resolution = Resolution.Daily;
    +        UniverseSettings.Leverage = 2;
    +        // We only trade on BTCUSDT Future in Bybit exchange
    +        var symbols = new List<Symbol>{
    +            QuantConnect.Symbol.Create("BTCUSDT", SecurityType.CryptoFuture, Market.Bybit)
    +        };
    +        AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
    +        // Custom alpha model to emit insights based on the Crypto Future price data
    +        AddAlpha(new CryptoFutureAlphaModel());
             // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
             SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +        SetExecution(new ImmediateExecutionModel());
         }
    +}
     
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    -    {
    -        // Select pairs where the quote currency is USD.
    -        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    -            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    -            .OrderBy(c => c.VolumeInUsd)
    -            .TakeLast(3)
    -            .Select(c => c.Symbol);
    -    }
    +public class CryptoFutureAlphaModel : AlphaModel
    +{
    +    private Dictionary<Symbol, Minimum> _minBySymbol = new();
     
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
         {
    -        foreach(var security in changes.AddedSecurities)
    +        var insights = new List<Insight>();
    +        foreach (var kvp in _minBySymbol)
             {
    -            // Historical data
    -            var history = History(security.Symbol, 30, Resolution.Daily);
    -            Debug($"We got {history.Count()} items from our history request");
    +            var symbol = kvp.Key;
    +            var lowInterestRate = kvp.Value;
    +            // Note that you may want to access the margin interest of the crypto future to calculate if it would impact a trade's PnL
    +            // Or you can calculate the trade size on keeping the quote currency constant
    +            if (!slice.MarginInterestRates.TryGetValue(symbol, out var dataPoint))
    +                continue;
    +            var interestRate = dataPoint.InterestRate;
    +            algorithm.Plot("Margin Interest Rate", symbol.ToString(), interestRate);
    +            // Short when margin interest rates are relatively low. Otherwise, long.
    +            var direction = interestRate <= lowInterestRate.Current.Value
    +                ? InsightDirection.Down
    +                : InsightDirection.Up;
    +            insights.Add(Insight.Price(symbol, TimeSpan.FromDays(1), direction));
    +            // Update the indicator.
    +            lowInterestRate.Update(slice.Time, interestRate);
             }
    +        return insights;
         }
    -}
    -
    -

    - Research Example -

    -

    - The following example lists crypto-currency pairs with the greatest dollar volume in the Bitfinex exchange: -

    -
    -
    var qb = new QuantBook();
    -
    -// Add Cryptocurrency pair
    -var symbol = qb.AddCrypto("BTCUSDT", market:Market.Bitfinex).Symbol;
    -
    -// Historical data
    -var history = qb.History(symbol, 30, Resolution.Daily);
    -foreach (var bar in history)
    -{
    -    Console.WriteLine($"{bar.EndTime} {bar}");
    -}
    -
    -// Add Crypto Universe Selection
    -IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    -{
    -    return universeDay
    -        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    -        .OrderByDescending(x => x.VolumeInUsd)
    -        .Take(5)
    -        .Select(x => x.Symbol);
    -}
    -var universe = qb.AddUniverse(CryptoUniverse.Bitfinex(UniverseSelectionFilter));
     
    -// Historical Universe data
    -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var universeDay in universeHistory)
    -{
    -    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    -    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
         {
    -        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            var symbol = security.Symbol;
    +            // Add an indicator to track the low of trailing margin interest rates.
    +            var min = new Minimum(10);
    +            _minBySymbol[symbol] = min;
    +            // Historical data
    +            var history = algorithm.History<MarginInterestRate>(symbol, 10, Resolution.Daily);
    +            foreach (var dataPoint in history)
    +            {
    +                min.Update(dataPoint.EndTime, dataPoint.InterestRate);
    +            }
    +        }
    +        foreach (var security in changes.RemovedSecurities)
    +        {
    +            _minBySymbol.Remove(security.Symbol);
    +        }
         }
     }
    -
    qb = QuantBook()
    -
    -# Add Cryptocurrency pair
    -symbol = qb.add_crypto("BTCUSDT", market=Market.BITFINEX).symbol
    -
    -# Historical data
    -history = qb.history(symbol, 30, Resolution.DAILY)
    -for (symbol, time), row in history.iterrows():
    -    print(f'{time} {symbol} {row.close}')
    -
    -# Add Crypto Universe Selection
    -def universe_selection_filter(universe_day):
    -    selected = sorted([x for x in universe_day
    -        if x.volume_in_usd and x.volume_in_usd > 10000],
    -        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    -    return [x.symbol for x in selected]
    -
    -universe = qb.add_universe(CryptoUniverse.bitfinex(universe_selection_filter))
    -
    -# Historical Universe data
    -history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (univere_symbol, time), universe_day in history.items():
    -    print(f'=== {time} ===')
    -    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    -        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    @@ -220843,76 +190215,22 @@

    Data Point Attributes

    - The Bitfinex Crypto Price dataset provides - - TradeBar - - , - - QuoteBar - - , - - Tick - - , and - - CryptoUniverse - - objects. -

    -

    - TradeBar Attributes -

    -

    - - TradeBar - - objects have the following attributes: -

    -
    -
    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - Tick Attributes -

    -

    - - Tick - - objects have the following attributes: -

    -
    -
    -

    - CryptoUniverse Attributes -

    -

    + The Binance Crypto Future Margin Rate dataset provides - CryptoUniverse + MarginInterestRate - objects have the following attributes: + objects, which have the following attributes:

    -
    +

     

    - +
    -
    -

    CoinAPI

    +
    +

    QuantConnect

    Bybit Crypto Future Price Data

    @@ -220920,7 +190238,7 @@

    Introduction

    - The Bybit Crypto Future Price Data by CoinAPI is for Cryptocurrency Futures price and volume data points. The data covers 631 Cryptocurrency pairs, starts in August 2020, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Bybit. + The Bybit Crypto Future Price Data is for Cryptocurrency Futures price and volume data points. The data covers 631 Cryptocurrency pairs, starts in August 2020, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Bybit.

    The @@ -220949,10 +190267,19 @@

    About the Provider

    - - CoinAPI + Bybit was co-founded by Ben Zhou in March 2018 with the goal to offer a professional platform where Crypto traders can find an ultra-fast matching engine, excellent customer service, and multilingual community support. Bybit provides access to trading Crypto and Crypto Futures for clients outside of + + excluded jurisdictions + + with low minimum deposits to set up an account. For more information about + + Crypto - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. + and + + fiat deposits + + , see the Bybit documentation. Bybit also provides Crypto staking, initial DEX offerings, and community airdrops.

    @@ -223781,10 +193108,10 @@

     

    - +
    -
    -

    CoinAPI

    +
    +

    QuantConnect

    Bybit Crypto Price Data

    @@ -223792,7 +193119,7 @@

    Introduction

    - The Bybit Crypto Price Data by CoinAPI is for Cryptocurrency price and volume data points. The data covers 956 Cryptocurrency pairs, starts in July 2017, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Bybit. + The Bybit Crypto Price Data is for Cryptocurrency price and volume data points. The data covers 956 Cryptocurrency pairs, starts in July 2017, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Bybit.

    For more information about the Bybit Crypto Price Data dataset, including CLI commands and pricing, see the @@ -223810,10 +193137,19 @@

    About the Provider

    - - CoinAPI + Bybit was co-founded by Ben Zhou in March 2018 with the goal to offer a professional platform where Crypto traders can find an ultra-fast matching engine, excellent customer service, and multilingual community support. Bybit provides access to trading Crypto and Crypto Futures for clients outside of + + excluded jurisdictions + + with low minimum deposits to set up an account. For more information about + + Crypto + + and + + fiat deposits - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. + , see the Bybit documentation. Bybit also provides Crypto staking, initial DEX offerings, and community airdrops.

    @@ -225981,1592 +195317,3837 @@

    Supported Assets

    LTCBTC
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +

    Example Applications

    + + +

    + The Bybit Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: +

    +
      +
    • + Buy and hold +
    • +
    • + Trading Cryptocurrency volatility and price action +
    • +
    • + Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys and holds Bitcoin through the Bybit exchange: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Set the account currency to USDT, since you can't trade with 
    +        # USD and the algorithm doesn't automatically convert USD & USDT
    +        # holdings.
    +        self.set_account_currency("USDT", 100_000)
    +        self.universe_settings.asynchronous = True
    +        # Bybit accepts both Cash and Margin account types. Select the
    +        # one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    +        # Add BTCUSDT data.
    +        self._btc = self.add_crypto("BTCUSDT", Resolution.MINUTE, Market.BYBIT)
    +        # Historical data
    +        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    +        # Add a Crypto universe that selects trading pairs on Bybit.
    +        universe = self.add_universe(CryptoUniverse.bybit(self._select_assets))
    +        # Historical Universe data
    +        universe_history = self.history(universe, 30, Resolution.DAILY)
    +        for (universe_symbol, time), universe_day in universe_history.items():
    +            for universe_item in universe_day:
    +                symbol = universe_item.symbol
    +                price = universe_item.close
    +
    +    def _select_assets(self, universe_day):
    +        # Filter for materially traded Crypto pairs with significant 
    +        # size and dollar volume, assuming higher capital flow in for 
    +        # higher return.
    +        return [universe_item.symbol for universe_item in universe_day
    +                if universe_item.volume >= 100 
    +                and universe_item.volume_in_usd > 10_000_000]
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Speculate-invest all available free cash on BTCUSDT, repecting 
    +        # the order quantity restrictions to avoid invalid orders.
    +        if self.portfolio.cash_book['BTC'].amount != 0:
    +            return
    +        # Define a buffer so that we can scale down the order size,
    +        # avoiding trading errors.
    +        buffer = max(
    +            BybitFeeModel.TAKER_NON_VIP_FEE, 
    +            self.settings.free_portfolio_value_percentage
    +        )
    +        quantity = (
    +            self.portfolio.cash_book['USDT'].amount
    +            / self._btc.ask_price
    +            * (1-buffer)
    +        )
    +        # Check if the quantity exceeds the minimum order size. On 
    +        # Bybit, the minimum order size is measured in the base
    +        # currency (BTC in this case).
    +        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    +            return
    +        self.market_order(self._btc, quantity)
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private Crypto _btc;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        // Set the account currency to USDT, since you can't trade with 
    +        // USD and the algorithm doesn't automatically convert USD & USDT
    +        // holdings.
    +        SetAccountCurrency("USDT", 100000);
    +        UniverseSettings.Asynchronous = true;
    +        // Bybit accepts both Cash and Margin account types. Select the
    +        // one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    +        // Add BTCUSDT data.
    +        _btc = AddCrypto("BTCUSDT", Resolution.Minute, Market.Bybit);   
    +        // Historical data
    +        var history = History(_btc.Symbol, 30, Resolution.Daily);
    +        // Add a Crypto universe that selects trading pairs on Bybit.
    +        var universe = AddUniverse(CryptoUniverse.Bybit(SelectAssets));
    +        // Historical Universe data
    +        var universeHistory = History(universe, 30, Resolution.Daily);
    +        foreach (var universeDay in universeHistory)
    +        {
    +            foreach (CryptoUniverse universeItem in universeDay)
    +            {
    +                var symbol = universeItem.Symbol;
    +                var price = universeItem.Close;
    +            }
    +        }
    +    }
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Filter for materially traded Crypto pairs with significant 
    +        // size and dollar volume, assuming higher capital flow in for 
    +        // higher return.
    +        return from universeItem in universeDay
    +                where universeItem.Volume >= 100m 
    +                && universeItem.VolumeInUsd > 10000000m
    +                select universeItem.Symbol;
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Speculate-invest all available free cash on BTCUSDT, repecting 
    +        // the order quantity restrictions to avoid invalid orders.
    +        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        {
    +            return;
    +        }
    +        // Define a buffer so that we can scale down the order size,
    +        // avoiding trading errors.
    +        var buffer = Math.Max(BybitFeeModel.TakerNonVIPFee, Settings.FreePortfolioValuePercentage);
    +        var quantity = Portfolio.CashBook["USDT"].Amount / _btc.AskPrice * (1-buffer);
    +        // Check if the quantity exceeds the minimum order size. On 
    +        // Bybit, the minimum order size is measured in the base 
    +        // currency (BTC in this case).
    +        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +        {
    +            return;
    +        }
    +        MarketOrder(_btc, quantity);
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of Crypto pairs on the Bybit exchange and then forms a equal-weighted portfolio of all the pairs in the universe: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Set Account Currency to Tether, since USD and USDT will not auto-convert and USD cannot be used to trade
    +        self.set_account_currency("USDT", 100000)
    +        self.settings.free_portfolio_value_percentage = 0.05
    +
    +        # Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    +
    +        # Warm up the security with the last known price to avoid conversion error
    +        self.settings.seed_initial_prices = True
    +        self.universe_settings.asynchronous = True
    +        self.universe_settings.resolution = Resolution.MINUTE
    +        # Add Crypto Universe Selection that select crypto pairs in Bybit exchange
    +        self.add_universe(CryptoUniverse.bybit(self.universe_selection_filter))
    +        # Get the pairs on Bybit that have USDT as the quote currency.
    +        self._market_pairs = [
    +            x.key.symbol 
    +            for x in self.symbol_properties_database.get_symbol_properties_list(Market.BYBIT) 
    +            if x.value.quote_currency == self.account_currency
    +        ]
    +        
    +        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(minutes = 20), 0.025, None))
    +        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    +    def universe_selection_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    +        # Select pairs where the quote currency is USDT.
    +        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    +        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    +        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    +        return [c.symbol for c in pairs]
    +
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = self.history(security.symbol, 30, Resolution.DAILY)
    +            self.debug(f"We got {len(history)} items from our history request")
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private List<string> _marketPairs;
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        Settings.FreePortfolioValuePercentage = 0.05m;
    +
    +        // Set Account Currency to Tether, since USD and USDT will not auto-convert and USD cannot be used to trade
    +        SetAccountCurrency("USDT", 100000);
    +        // Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    +
    +        // Warm up the security with the last known price to avoid conversion error
    +        Settings.SeedInitialPrices = true;
    +        UniverseSettings.Asynchronous = true;
    +        UniverseSettings.Resolution = Resolution.Minute;
    +        // Add Crypto Universe Selection that select crypto pairs in Bybit exchange
    +        AddUniverse(CryptoUniverse.Bybit(UniverseSelectionFilter));
    +        // Get the pairs on Bybit that have USDT as the quote currency.
    +        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Bybit)
    +            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    +            .Select(x => x.Key.Symbol)
    +            .ToList();
    +
    +        AddAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
    +        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +    }
    +
    +    private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Select pairs where the quote currency is USDT.
    +        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    +            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    +            .OrderBy(c => c.VolumeInUsd)
    +            .TakeLast(3)
    +            .Select(c => c.Symbol);
    +    }
    +
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach(var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = History(security.Symbol, 30, Resolution.Daily);
    +            Debug($"We got {history.Count()} items from our history request");
    +        }
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example lists crypto-currency pairs with the greatest dollar volume in the Bybit exchange: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add Cryptocurrency pair
    +var symbol = qb.AddCrypto("BTCUSDT", market:Market.Bybit).Symbol;
    +
    +// Historical data
    +var history = qb.History(symbol, 30, Resolution.Daily);
    +foreach (var bar in history)
    +{
    +    Console.WriteLine($"{bar.EndTime} {bar}");
    +}
    +
    +// Add Crypto Universe Selection
    +IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +{
    +    return universeDay
    +        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    +        .OrderByDescending(x => x.VolumeInUsd)
    +        .Take(5)
    +        .Select(x => x.Symbol);
    +}
    +var universe = qb.AddUniverse(CryptoUniverse.Bybit(UniverseSelectionFilter));
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var universeDay in universeHistory)
    +{
    +    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    +    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    +    {
    +        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add Cryptocurrency pair
    +symbol = qb.add_crypto("BTCUSDT", market=Market.BYBIT).symbol
    +
    +# Historical data
    +history = qb.history(symbol, 30, Resolution.DAILY)
    +for (symbol, time), row in history.iterrows():
    +    print(f'{time} {symbol} {row.close}')
    +
    +# Add Crypto Universe Selection
    +def universe_selection_filter(universe_day):
    +    selected = sorted([x for x in universe_day
    +        if x.volume_in_usd and x.volume_in_usd > 10000],
    +        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    +    return [x.symbol for x in selected]
    +
    +universe = qb.add_universe(CryptoUniverse.bybit(universe_selection_filter))
    +
    +# Historical Universe data
    +history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (univere_symbol, time), universe_day in history.items():
    +    print(f'=== {time} ===')
    +    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    +        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The Bybit Crypto Price dataset provides + + TradeBar + + , + + QuoteBar + + , + + Tick + + , and + + CryptoUniverse + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    +

    + CryptoUniverse Attributes +

    +

    + + CryptoUniverse + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    CFD Data

    +
    +
    +

    Introduction

    + + +

    + The CFD Data by QuantConnect serves 51 + + contracts for differences + + (CFD). The data starts as early as May 2002 and is delivered on any frequency from tick to daily. This dataset is created by QuantConnect processing raw tick data from OANDA. +

    +

    + CFD data does not include ask and bid sizes. +

    +

    + For more information about the CFD Data dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the CFD dataset: +

    +
    +
    self.xauusd = self.add_cfd("XAUUSD", Resolution.DAILY).symbol
    +
    _symbol = AddCfd("XAUUSD", Resolution.Daily).Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + Mixed, earliest starts May 2002 +
    + Asset Coverage + + 51 Contracts +
    + Data Density + + Dense +
    + Resolution + + Tick, Second, Minute, Hour, & Daily +
    + Timezone + + Mixed, in which the contract is listed* +
    + Market Hours + + + Always Open + + , except from Friday 5 PM EST to Sunday 5 PM EST. +
    + Index CFDs depends on the underlying market hour* +
    +

    + * E.g.: + + DE30EUR + + tracks DAX30 Index, which is listed in Europe/Berlin timezone. +

    + + + +

    Requesting Data

    + + +

    + To add CFD data to your algorithm, call the + + AddCfd + + + add_cfd + + method. Save a reference to the CFD + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class CfdAlgorithm (QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_account_currency('EUR');
    +
    +        self.set_start_date(2019, 2, 20)
    +        self.set_end_date(2019, 2, 21)
    +        self.set_cash('EUR', 100000)
    +
    +        self.de30eur = self.add_cfd('DE30EUR').symbol
    +
    +        self.set_benchmark(self.de30eur)
    +
    +
    public class CfdAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol;
    +
    +    public override void Initialize()
    +    {
    +        SetAccountCurrency("EUR");
    +
    +        SetStartDate(2019, 2, 20);
    +        SetEndDate(2019, 2, 21);
    +        SetCash("EUR", 100000);
    +
    +        _symbol = AddCfd("DE30EUR").Symbol;
    +
    +        SetBenchmark(_symbol);
    +    }
    +}
    +
    +

    + For more information about creating CFD subscriptions, see + + Requesting Data + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current CFD data, index the + + QuoteBars + + + quote_bars + + , or + + Ticks + + + ticks + + properties of the current + + + Slice + + + with the CFD + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    if self.de30eur in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.de30eur]
    +        self.log(f"{self.de30eur} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    if self.de30eur in slice.ticks:
    +        ticks = slice.ticks[self.de30eur]
    +        for tick in ticks:
    +            self.log(f"{self.de30eur} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    if (slice.QuoteBars.ContainsKey(_symbol))
    +    {
    +        var quoteBar = slice.QuoteBars[_symbol];
    +        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    if (slice.Ticks.ContainsKey(_symbol))
    +    {
    +        var ticks = slice.Ticks[_symbol];
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + You can also iterate through all of the data objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for symbol, quote_bar in slice.quote_bars.items():
    +        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    for symbol, ticks in slice.ticks.items():
    +        for tick in ticks:
    +            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.QuoteBars)
    +    {
    +        var symbol = kvp.Key;
    +        var quoteBar = kvp.Value;
    +        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    foreach (var kvp in slice.Ticks)
    +    {
    +        var symbol = kvp.Key;
    +        var ticks = kvp.Value;
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + For more information about accessing CFD data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + To get historical CFD data, call the + + History + + + history + + method with the CFD + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.de30eur, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](self.de30eur, 100, Resolution.MINUTE)
    +
    +# Tick objects
    +history_ticks = self.history[Tick](self.de30eur, timedelta(seconds=10), Resolution.TICK)
    +
    // QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    +
    +// Tick objects 
    +var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Remove Subscriptions

    + + +

    + To remove a CFD subscription, call the + + RemoveSecurity + + + remove_security + + method. +

    +
    +
    self.remove_security(self.de30eur)
    +
    RemoveSecurity(_symbol);
    +
    +

    + The + + RemoveSecurity + + + remove_security + + method cancels your open orders for the security and liquidates your holdings. +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available contracts: +

    +
    + + - - - - - - + + + - - - + + +
    + + + +

    Example Applications

    + + +

    + The CFD price data enables you to trade CFD assets in your algorithm. Examples include the following strategies: +

    +
      +
    • + Exploring the daily worldwide news cycles with CFDs that track international indices. +
    • +
    • + Trading price movements of commodities with no delivery of physical goods. For example, pairs trading between gold and silver, corn and wheat, brent and crude oil, etc. +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm implements a pairs trading strategy using Gold and Silver CFDs, XAUUSD and XAGUSD, respectively. When the spread is higher than one standard deviation above its mean, the algorithm buys the spread (buy XAUUSD and sell XAGUSD). When the spread is lower than one standard deviation below its mean, it sells the spread (buy XAGUSD and sell XAUUSD). +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class SMAPairsTrading(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +
    +        # Request gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    +        self.add_cfd('XAUUSD', Resolution.HOUR)
    +        self.add_cfd('XAGUSD', Resolution.HOUR)
    +
    +        # Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    +        self.pair = [ ]
    +        self.spread_mean = SimpleMovingAverage(500)
    +        self.spread_std = StandardDeviation(500)
    +        
    +    def on_data(self, slice: Slice) -> None:
    +        # Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    +        spread = self.pair[1].price - self.pair[0].price
    +        self.spread_mean.update(self.time, spread)
    +        self.spread_std.update(self.time, spread) 
    +        
    +        spread_mean = self.spread_mean.current.value
    +        upperthreshold = spread_mean  + self.spread_std.current.value
    +        lowerthreshold = spread_mean  - self.spread_std.current.value
    +
    +        # If the spread is higher than upper threshold, bet their spread series will revert to mean
    +        if spread > upperthreshold:
    +            self.set_holdings(self.pair[0].symbol, 1)
    +            self.set_holdings(self.pair[1].symbol, -1)
    +        elif spread < lowerthreshold:
    +            self.set_holdings(self.pair[0].symbol, -1)
    +            self.set_holdings(self.pair[1].symbol, 1)
    +        # Close positions if mean reverted
    +        elif (self.portfolio[self.pair[0].symbol].quantity > 0 and spread < spread_mean)\
    +        or (self.portfolio[self.pair[0].symbol].quantity < 0 and spread > spread_mean):
    +            self.liquidate()
    +    
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        self.pair = [x for x in changes.added_securities]
    +        
    +        #1. Call for 500 bars of history data for each symbol in the pair and save to the variable history
    +        history = self.history([x.symbol for x in self.pair], 500)
    +        #2. Unstack the Pandas data frame to reduce it to the history close price
    +        history = history.close.unstack(level=0)
    +        #3. Iterate through the history tuple and update the mean and standard deviation with historical data 
    +        for tuple in history.itertuples():
    +            self.spread_mean.update(tuple[0], tuple[2]-tuple[1])
    +            self.spread_std.update(tuple[0], tuple[2]-tuple[1])
    +
    +
    public class GoldSilverPairsTradingAlgorithm : QCAlgorithm
    +{
    +    // Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    +    private SimpleMovingAverage _spreadMean = new SimpleMovingAverage(500);
    +    private StandardDeviation _spreadStd = new StandardDeviation(500);
    +    private Security[] _pair = new Security[2];
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);  
    +
    +        // Request gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    +        AddCfd("XAUUSD", Resolution.Hour);
    +        AddCfd("XAGUSD", Resolution.Hour);
    +    }
    +
    +    public override void OnData(Slice slice) 
    +    {
    +        // Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    +        var spread = _pair[1].Price - _pair[0].Price;
    +        _spreadMean.Update(Time, spread);
    +        _spreadStd.Update(Time, spread);
    +        
    +        var upperthreshold = _spreadMean + _spreadStd;
    +        var lowerthreshold = _spreadMean - _spreadStd;
    +        
    +        // If the spread is higher than upper threshold, bet their spread series will revert to mean
    +        if (spread > upperthreshold)
    +        {
    +            SetHoldings(_pair[0].Symbol, 1);
    +            SetHoldings(_pair[1].Symbol, -1);
    +        }
    +        else if (spread < lowerthreshold)
    +        {
    +            SetHoldings(_pair[0].Symbol, -1);
    +            SetHoldings(_pair[1].Symbol, 1);
    +        }
    +        // Close positions if mean reverted
    +        else if ((Portfolio[_pair[0].Symbol].Quantity > 0m && spread < _spreadMean)
    +        || (Portfolio[_pair[0].Symbol].Quantity < 0m && spread > _spreadMean))
    +        {
    +            Liquidate();
    +        }
    +    }
    +    
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {    
    +        _pair = changes.AddedSecurities.ToArray();
    +        
    +        //1. Call for 500 days of history data for each symbol in the pair and save to the variable history
    +        var history = History(_pair.Select(x => x.Symbol), 500);
    +        
    +        //2. Iterate through the history tuple and update the mean and standard deviation with historical data 
    +        foreach(var slice in history)
    +        {
    +            var spread = slice[_pair[1].Symbol].Close - slice[_pair[0].Symbol].Close;
    +            _spreadMean.Update(slice.Time, spread);
    +            _spreadStd.Update(slice.Time, spread);
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm implements a pairs trading strategy using Gold and Silver CFDs, XAUUSD and XAGUSD, respectively. When the spread is higher than one standard deviation above its mean, the algorithm buys the spread (buy XAUUSD and sell XAGUSD). When the spread is lower than one standard deviation below its mean, it sells the spread (buy XAGUSD and sell XAUUSD). +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class GoldSilverPairsTradingAlgorithm (QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        
    +        self.universe_settings.resolution = Resolution.HOUR
    +        # Custom universe contains only gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    +        self.set_universe_selection(ManualUniverseSelectionModel
    +        (
    +            [ Symbol.create(x, SecurityType.CFD, Market.OANDA) for x in ["XAUUSD", "XAGUSD"] ]
    +        ))
    +        # Custom alpha model to emit trade insights based on the gold-sliver price spread
    +        self.add_alpha(PairsTradingAlphaModel())
    +        # Equal weighting trades assuming the spread is cointegrated by 1:1 ratio
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    +class PairsTradingAlphaModel(AlphaModel):
    +
    +    def __init__(self) -> None:
    +        # Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    +        self.pair = [ ]
    +        self.spread_mean = SimpleMovingAverage(500)
    +        self.spread_std = StandardDeviation(500)
    +        # Assume efficient mean reversal happens within 2 hours
    +        self.period = timedelta(hours=2)
    +        
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        # Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    +        spread = self.pair[1].price - self.pair[0].price
    +        self.spread_mean.update(algorithm.time, spread)
    +        self.spread_std.update(algorithm.time, spread) 
    +        
    +        upperthreshold = self.spread_mean.current.value + self.spread_std.current.value
    +        lowerthreshold = self.spread_mean.current.value - self.spread_std.current.value
    +
    +        # If the spread is higher than upper threshold, bet their spread series will revert to mean
    +        if spread > upperthreshold:
    +            return Insight.group(
    +                [
    +                    Insight.price(self.pair[0].symbol, self.period, InsightDirection.UP),
    +                    Insight.price(self.pair[1].symbol, self.period, InsightDirection.DOWN)
    +                ])
    +        elif spread < lowerthreshold:
    +            return Insight.group(
    +                [
    +                    Insight.price(self.pair[0].symbol, self.period, InsightDirection.DOWN),
    +                    Insight.price(self.pair[1].symbol, self.period, InsightDirection.UP)
    +                ])
    +
    +        return []
    +    
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        self.pair = [x for x in changes.added_securities]
    +        
    +        #1. Call for 500 bars of history data for each symbol in the pair and save to the variable history
    +        history = algorithm.history([x.symbol for x in self.pair], 500)
    +        #2. Unstack the Pandas data frame to reduce it to the history close price
    +        history = history.close.unstack(level=0)
    +        #3. Iterate through the history tuple and update the mean and standard deviation with historical data 
    +        for tuple in history.itertuples():
    +            self.spread_mean.update(tuple[0], tuple[2]-tuple[1])
    +            self.spread_std.update(tuple[0], tuple[2]-tuple[1])
    +
    +
    public class GoldSilverPairsTradingAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);  
    +
    +        UniverseSettings.Resolution = Resolution.Hour;
    +        // Custom universe contains only gold and sliver spot CFDs for trading their spread difference, assuming their spread series is cointegrated
    +        SetUniverseSelection(new ManualUniverseSelectionModel
    +        (
    +            new [] {"XAUUSD", "XAGUSD"}
    +                .Select(x => QuantConnect.Symbol.Create(x, SecurityType.Cfd, Market.Oanda))
    +        ));
    +        // Custom alpha model to emit trade insights based on the gold-sliver price spread
    +        AddAlpha(new PairsTradingAlphaModel());
    +        // Equal weighting trades assuming the spread is cointegrated by 1:1 ratio
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel()); 
    +    }
    +}
    +
    +public partial class PairsTradingAlphaModel : AlphaModel
    +{
    +    // Use 500-step mean and SD indicator on determine the spread relative difference for trading signal generation
    +    private SimpleMovingAverage _spreadMean = new SimpleMovingAverage(500);
    +    private StandardDeviation _spreadStd = new StandardDeviation(500);
    +    // Assume efficient mean reversal happens within 2 hours
    +    private TimeSpan _period = TimeSpan.FromHours(2);
    +    private Security[] _pair = new Security[2];
    +
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice) 
    +    {
    +        // Update the indicator with updated spread difference, such that the an updated cointegration threshold is calculated for trade inception
    +        var spread = _pair[1].Price - _pair[0].Price;
    +        _spreadMean.Update(algorithm.Time, spread);
    +        _spreadStd.Update(algorithm.Time, spread);
    +        
    +        var upperthreshold = _spreadMean + _spreadStd;
    +        var lowerthreshold = _spreadMean - _spreadStd;
    +
    +        // If the spread is higher than upper threshold, bet their spread series will revert to mean
    +        if (spread > upperthreshold)
    +        {
    +            return Insight.Group( 
    +                Insight.Price(_pair[0].Symbol, _period, InsightDirection.Up),
    +                Insight.Price(_pair[1].Symbol, _period, InsightDirection.Down)
    +            );
    +        }
    +        else if (spread < lowerthreshold)
    +        {
    +            return Insight.Group( 
    +                Insight.Price(_pair[0].Symbol, _period, InsightDirection.Down), 
    +                Insight.Price(_pair[1].Symbol, _period, InsightDirection.Up) 
    +            );
    +        }
    +
    +        return Enumerable.Empty<Insight>();
    +    }
    +    
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {    
    +        _pair = changes.AddedSecurities.ToArray();
    +        
    +        //1. Call for 500 days of history data for each symbol in the pair and save to the variable history
    +        var history = algorithm.History(_pair.Select(x => x.Symbol), 500);
    +        
    +        //2. Iterate through the history tuple and update the mean and standard deviation with historical data 
    +        foreach (var slice in history)
    +        {
    +            var spread = slice[_pair[1].Symbol].Close - slice[_pair[0].Symbol].Close;
    +            _spreadMean.Update(slice.Time, spread);
    +            _spreadStd.Update(slice.Time, spread);
    +        }
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The CFD dataset provides + + QuoteBar + + and + + Tick + + objects. +

    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    Cash Indices

    +
    +
    +

    Introduction

    + + +

    + The Cash Indices dataset by QuantConnect covers 125 US Indices and 3 International indices. The data starts on various dates from January 1998 and is delivered on any frequency from minute to daily. +

    +

    + For more information about the Cash Indices dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Live Data

    + + +

    + The Cash Indices dataset does not provide a live data feed. To receive Cash Indices' data in your live algorithm, you must add a brokerage or a third-party data provider (see + + Cloud Platform > Datasets + + ). +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the Cash Indices dataset: +

    +
    +
    self.vix = self.add_index("VIX", Resolution.DAILY).symbol
    +
    _symbol = AddIndex("VIX", Resolution.Daily).Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 1998 +
    + Coverage + + 125 US Indices and 3 International indices (HSI, SX5E and N225) +
    + Data Density + + Dense +
    + Resolution + + Minute, Hour, & Daily +
    + Timezone + + New York for US Indices, refer to + + Supported Assets + + below for International indices +
    + Market Hours + + + Regular Only + +
    + + + +

    Requesting Data

    + + +

    + To add Cash Indices data to your algorithm, call the + + AddIndex + + + add_index + + method. Save a reference to the Index + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class CashIndexAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000)
    +
    +        self.vix = self.add_index("VIX").symbol
    +
    +
    public class CashIndexAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        
    +        _symbol = AddIndex("VIX").Symbol;
    +    }
    +}
    +
    +

    + For more information about creating Index subscriptions, see + + Requesting Data + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current Cash Indices data, index the + + Bars + + + bars + + property of the current + + + Slice + + + with the Index + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    if self.vix in slice.bars:
    +        trade_bar = slice.bars[self.vix]
    +        self.log(f"{self.vix} close at {slice.time}: {trade_bar.close}")
    +
    public override void OnData(Slice slice)
    +{
    +    if (slice.Bars.ContainsKey(_symbol))
    +    {
    +        var tradeBar = slice.Bars[_symbol];
    +        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +}
    +
    +
    +

    + You can also iterate through all of the data objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for symbol, trade_bar in slice.bars.items():
    +        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.Bars)
    +    {
    +        var symbol = kvp.Key;
    +        var tradeBar = kvp.Value;
    +        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +}
    +
    +
    +

    + For more information about accessing Index data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + To get historical Cash Indices data, call the + + History + + + history + + method with the Index + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.vix, 100, Resolution.DAILY)
    +
    +# TradeBar objects
    +history_bars = self.history[TradeBar](self.vix, 100, Resolution.DAILY)
    +
    // TradeBar objects
    +var historyBars = History(_symbol, 100, Resolution.Daily);
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Remove Subscriptions

    + + +

    + To remove an Index subscription, call the + + RemoveSecurity + + + remove_security + + method. +

    +
    +
    self.remove_security(self.vix)
    +
    RemoveSecurity(_symbol);
    +
    + + + +

    Supported Indices

    + + +

    + US Cash Indices +

    +

    + The following table shows the US Cash indices with Index Option support: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Ticker + + Index + + Expiry + + Start Date +
    + VIX + + S&P500 + + 30 Days + + Jul 2003 +
    + SPX + + S&P500 + + - + + Jan 1998 +
    + NDX + + NASDAQ-100 + + - + + Jan 1998 +
    + RUT + + Russell 2000 + + - + + Jan 2008 +
    +
    + VIX - CBOE Volatility Index +
    +

    + The Cboe Volatility Index (VIX) is a real-time index that represents the market's expectations for the relative strength of near-term price changes of the S&P 500 Index (SPX). Because it's derived from the prices of SPX index Options with near-term expiration dates, it generates a 30-day forward projection of volatility. Volatility, or how fast prices change, is often seen as a way to gauge market sentiment, and in particular, the degree of fear among market participants. +

    +
    + SPX - S&P 500 Index +
    +

    + The S&P 500 Index, or the Standard & Poor's 500 Index, is a market-capitalization-weighted index of the 500 largest publicly-traded companies in the U.S. It is not an exact list of the top 500 U.S. companies by market capitalization because there are other criteria included in the index. The index is widely regarded as the best gauge of large-cap U.S. Equities. +

    +
    + NDX - Nasdaq 100 Index +
    +

    + The Nasdaq-100 Index is a modified market-capitalization-weighted index composed of securities issued by 100 of the largest non-financial companies listed on the Nasdaq Stock Market (Nasdaq). The index includes companies from various industries except for the financial industry, like commercial and investment banks. These non-financial sectors include retail, biotechnology, industrial, technology, health care, and others. +

    +
    + RUT - Russell 2000 Index +
    +

    + The Russell 2000 Index is a small-cap U.S. stock market index that makes up the smallest 2,000 stocks in the Russell Index. It was started by the Frank Russell Company in 1984. The index is maintained by FTSE Russell, a subsidiary of the London Stock Exchange Group (LSEG). +

    +
    + All US Cash Indices +
    + The following table shows all US Cash indices: +
    + + - - - - - - + + + - - - - -
    +

    + International Cash Indices +

    +

    + The following table shows the International Cash indices: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Ticker + + Index + + Start Date + + Time Zone + + Currency +
    + HSI + + Hang Seng Index + + Dec 2006 + + Asia/Hong Kong + + HKD +
    + SX5E + + EUREX EU STOXX + + Jul 2003 + + Europe/Berlin + + EUR +
    + N225 + + Nikkei 225 + + Jul 2003 + + Asia/Tokyo + + JPY +
    @@ -227574,321 +199155,235 @@

    Example Applications

    - The Bybit Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: + The Cash Indices enable you to incorporate popular indices into your trading algorithms. Examples include the following use cases:

    • - Buy and hold + Exploring the difference between the Index and the ETF that tracks it
    • - Trading Cryptocurrency volatility and price action + Using these indices as the underlying asset fo Index Options strategies
    • - Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation + Understanding the stock market's level of expected forward-looking volatility, also known as the "fear index". When the VIX starts moving higher, it tells you that traders are getting nervous. When the VIX starts moving lower, it tells you that traders are gaining confidence.

    Classic Algorithm Example

    - The following example algorithm buys and holds Bitcoin through the Bybit exchange: + The following example algorithm tracks the 80-day EMA and 200-day EMA of SPX. When the short EMA crosses above the long EMA, the algorithm buys SPY. Otherwise, it holds cash.

    -
    from AlgorithmImports import *
    +   
    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    +class IndexDataAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        # Set the account currency to USDT, since you can't trade with 
    -        # USD and the algorithm doesn't automatically convert USD & USDT
    -        # holdings.
    -        self.set_account_currency("USDT", 100_000)
    -        self.universe_settings.asynchronous = True
    -        # Bybit accepts both Cash and Margin account types. Select the
    -        # one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    -        # Add BTCUSDT data.
    -        self._btc = self.add_crypto("BTCUSDT", Resolution.MINUTE, Market.BYBIT)
    -        # Historical data
    -        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    -        # Add a Crypto universe that selects trading pairs on Bybit.
    -        universe = self.add_universe(CryptoUniverse.bybit(self._select_assets))
    -        # Historical Universe data
    -        universe_history = self.history(universe, 30, Resolution.DAILY)
    -        for (universe_symbol, time), universe_day in universe_history.items():
    -            for universe_item in universe_day:
    -                symbol = universe_item.symbol
    -                price = universe_item.close
    +        self.set_cash(100000)
     
    -    def _select_assets(self, universe_day):
    -        # Filter for materially traded Crypto pairs with significant 
    -        # size and dollar volume, assuming higher capital flow in for 
    -        # higher return.
    -        return [universe_item.symbol for universe_item in universe_day
    -                if universe_item.volume >= 100 
    -                and universe_item.volume_in_usd > 10_000_000]
    +        # Request SPY data as a trading vehicle for SPX
    +        self.spy = self.add_equity("SPY").symbol
    +
    +        # Request SPX data for trade signal generation
    +        spx = self.add_index("SPX").symbol
    +
    +        # Create short and long-term EMA indicators for trend estimation to trade
    +        self.ema_fast = self.EMA(spx, 80, Resolution.DAILY)
    +        self.ema_slow = self.EMA(spx, 200, Resolution.DAILY)
    +        self.set_warm_up(200, Resolution.DAILY)
    +
    +        # Historical data
    +        history = self.history(spx, 60, Resolution.DAILY)
    +        self.debug(f'We got {len(history.index)} items from our history request')
     
         def on_data(self, slice: Slice) -> None:
    -        # Speculate-invest all available free cash on BTCUSDT, repecting 
    -        # the order quantity restrictions to avoid invalid orders.
    -        if self.portfolio.cash_book['BTC'].amount != 0:
    -            return
    -        # Define a buffer so that we can scale down the order size,
    -        # avoiding trading errors.
    -        buffer = max(
    -            BybitFeeModel.TAKER_NON_VIP_FEE, 
    -            self.settings.free_portfolio_value_percentage
    -        )
    -        quantity = (
    -            self.portfolio.cash_book['USDT'].amount
    -            / self._btc.ask_price
    -            * (1-buffer)
    -        )
    -        # Check if the quantity exceeds the minimum order size. On 
    -        # Bybit, the minimum order size is measured in the base
    -        # currency (BTC in this case).
    -        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    +        # Trade signals required indicators to be ready
    +        if self.is_warming_up or not self.ema_slow.is_ready:
                 return
    -        self.market_order(self._btc, quantity)
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +
    +        # If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    +        if not self.portfolio.invested and self.ema_fast > self.ema_slow:
    +            self.set_holdings(self.spy, 1)
    +        # If it is the reverse, it indicates a downtrend, and we liquidate any position
    +        elif self.ema_fast < self.ema_slow:
    +            self.liquidate()
    +
    +
    public class IndexDataAlgorithm : QCAlgorithm
     {
    -    private Crypto _btc;
    -    
    +    private Symbol _spy;
    +    private ExponentialMovingAverage _emaSlow, _emaFast;
    +
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        // Set the account currency to USDT, since you can't trade with 
    -        // USD and the algorithm doesn't automatically convert USD & USDT
    -        // holdings.
    -        SetAccountCurrency("USDT", 100000);
    -        UniverseSettings.Asynchronous = true;
    -        // Bybit accepts both Cash and Margin account types. Select the
    -        // one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    -        // Add BTCUSDT data.
    -        _btc = AddCrypto("BTCUSDT", Resolution.Minute, Market.Bybit);   
    -        // Historical data
    -        var history = History(_btc.Symbol, 30, Resolution.Daily);
    -        // Add a Crypto universe that selects trading pairs on Bybit.
    -        var universe = AddUniverse(CryptoUniverse.Bybit(SelectAssets));
    -        // Historical Universe data
    -        var universeHistory = History(universe, 30, Resolution.Daily);
    -        foreach (var universeDay in universeHistory)
    -        {
    -            foreach (CryptoUniverse universeItem in universeDay)
    -            {
    -                var symbol = universeItem.Symbol;
    -                var price = universeItem.Close;
    -            }
    -        }
    -    }
    +        SetCash(1000000);
     
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    -    {
    -        // Filter for materially traded Crypto pairs with significant 
    -        // size and dollar volume, assuming higher capital flow in for 
    -        // higher return.
    -        return from universeItem in universeDay
    -                where universeItem.Volume >= 100m 
    -                && universeItem.VolumeInUsd > 10000000m
    -                select universeItem.Symbol;
    +        // Request SPY data as trading vehicle for SPX
    +        _spy = AddEquity("SPY").Symbol;
    +
    +        // Request SPX data for trade signal generation
    +        var spx = AddIndex("SPX").Symbol;
    +
    +        // Create short and long-term EMA indicators for trend estimation to trade
    +        _emaFast = EMA(spx, 80, Resolution.Daily);
    +        _emaSlow = EMA(spx, 200, Resolution.Daily);
    +        SetWarmUp(200, Resolution.Daily);
    +
    +        // Historical data
    +        var history = History(spx, 60, Resolution.Daily);
    +        Debug($"We got {history.Count()} items from our history request");
         }
     
         public override void OnData(Slice slice)
         {
    -        // Speculate-invest all available free cash on BTCUSDT, repecting 
    -        // the order quantity restrictions to avoid invalid orders.
    -        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        // Trade signals required indicators to be ready
    +        if (IsWarmingUp || !_emaSlow.IsReady)
             {
                 return;
             }
    -        // Define a buffer so that we can scale down the order size,
    -        // avoiding trading errors.
    -        var buffer = Math.Max(BybitFeeModel.TakerNonVIPFee, Settings.FreePortfolioValuePercentage);
    -        var quantity = Portfolio.CashBook["USDT"].Amount / _btc.AskPrice * (1-buffer);
    -        // Check if the quantity exceeds the minimum order size. On 
    -        // Bybit, the minimum order size is measured in the base 
    -        // currency (BTC in this case).
    -        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +
    +        // If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    +        if (!Portfolio.Invested && _emaFast > _emaSlow)
             {
    -            return;
    +            SetHoldings(_spy, 1);
    +        }
    +        // If it is the reverse, it indicates a downtrend, and we liquidate any position
    +        else if (_emaFast < _emaSlow)
    +        {
    +            Liquidate();
             }
    -        MarketOrder(_btc, quantity);
         }
    -}
    +}

    Framework Algorithm Example

    - The following example algorithm creates a dynamic universe of Crypto pairs on the Bybit exchange and then forms a equal-weighted portfolio of all the pairs in the universe: + The following example algorithm tracks the 80-day EMA and 200-day EMA of SPX. When the short EMA crosses above the long EMA, the algorithm buys SPY. Otherwise, it holds cash.

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    +class IndexDataAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        # Set Account Currency to Tether, since USD and USDT will not auto-convert and USD cannot be used to trade
    -        self.set_account_currency("USDT", 100000)
    -        self.settings.free_portfolio_value_percentage = 0.05
    +        self.set_cash(100000)
     
    -        # Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.BYBIT, AccountType.MARGIN)
    +        # Universe contains only SPY as a trading vehicle for SPX
    +        self.set_universe_selection(ManualUniverseSelectionModel
    +        (
    +            Symbol.create("SPY", SecurityType.EQUITY, Market.USA)
    +        ))
    +        # Custom alpha model that emits insights based on SPX index data
    +        self.set_alpha(SpxEmaCrossAlphaModel(self))
    +        # Equally investing can dissipate non-systematic risky event's capital concentration risk evenly
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(Expiry.END_OF_MONTH))
    +    
     
    -        # Warm up the security with the last known price to avoid conversion error
    -        self.settings.seed_initial_prices = True
    -        self.universe_settings.asynchronous = True
    -        self.universe_settings.resolution = Resolution.MINUTE
    -        # Add Crypto Universe Selection that select crypto pairs in Bybit exchange
    -        self.add_universe(CryptoUniverse.bybit(self.universe_selection_filter))
    -        # Get the pairs on Bybit that have USDT as the quote currency.
    -        self._market_pairs = [
    -            x.key.symbol 
    -            for x in self.symbol_properties_database.get_symbol_properties_list(Market.BYBIT) 
    -            if x.value.quote_currency == self.account_currency
    -        ]
    -        
    -        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(minutes = 20), 0.025, None))
    -        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +class SpxEmaCrossAlphaModel(AlphaModel):
     
    -    def universe_selection_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    -        # Select pairs where the quote currency is USDT.
    -        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    -        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    -        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    -        return [c.symbol for c in pairs]
    +    def __init__(self, algorithm: QCAlgorithm) -> None:
    +        # Request SPX data for trade signal generation
    +        spx = algorithm.add_index("SPX").symbol
     
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            # Historical data
    -            history = self.history(security.symbol, 30, Resolution.DAILY)
    -            self.debug(f"We got {len(history)} items from our history request")
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +        # Create short and long-term EMA indicators for trend estimation to trade
    +        self.ema_fast = algorithm.EMA(spx, 80, Resolution.DAILY)
    +        self.ema_slow = algorithm.EMA(spx, 200, Resolution.DAILY)
    +        algorithm.set_warm_up(200, Resolution.DAILY)
    +
    +        # Historical data
    +        history = algorithm.history(spx, 60, Resolution.DAILY)
    +        algorithm.debug(f'We got {len(history.index)} items from our history request')
    +    
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        # Trade signals required indicators to be ready
    +        if algorithm.is_warming_up or not self.ema_slow.is_ready:
    +            return []
    +
    +        # If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    +        if not algorithm.portfolio.invested and self.ema_fast > self.ema_slow:
    +            return [Insight.price(kvp.key, Expiry.END_OF_MONTH, InsightDirection.UP)
    +                for kvp in algorithm.active_securities if kvp.value.is_tradable]
    +        # If it is the reverse, it indicates downtrend, and we liquidate any position
    +        elif self.ema_fast < self.ema_slow:
    +            return [Insight.price(kvp.key, Expiry.END_OF_MONTH, InsightDirection.FLAT)
    +                for kvp in algorithm.active_securities if kvp.value.is_tradable]
    +            
    +        return []
    +
    +
    public class IndexDataAlgorithm : QCAlgorithm
     {
    -    private List<string> _marketPairs;
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        Settings.FreePortfolioValuePercentage = 0.05m;
    -
    -        // Set Account Currency to Tether, since USD and USDT will not auto-convert and USD cannot be used to trade
    -        SetAccountCurrency("USDT", 100000);
    -        // Bybit accepts both Cash and Margin account types, select the one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Bybit, AccountType.Margin);
    -
    -        // Warm up the security with the last known price to avoid conversion error
    -        Settings.SeedInitialPrices = true;
    -        UniverseSettings.Asynchronous = true;
    -        UniverseSettings.Resolution = Resolution.Minute;
    -        // Add Crypto Universe Selection that select crypto pairs in Bybit exchange
    -        AddUniverse(CryptoUniverse.Bybit(UniverseSelectionFilter));
    -        // Get the pairs on Bybit that have USDT as the quote currency.
    -        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Bybit)
    -            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    -            .Select(x => x.Key.Symbol)
    -            .ToList();
    +        SetCash(1000000);
     
    -        AddAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
    -        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +        // Universe contains only SPY as a trading vehicle for SPX
    +        SetUniverseSelection(new ManualUniverseSelectionModel
    +        (
    +            QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)
    +        ));
    +        // Custom alpha model that emits insights based on SPX index data
    +        SetAlpha(new SpxEmaCrossAlphaModel(this));
    +        // Equally invests can dissipate non-systematic risky event's capital concentration risk evenly
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(Expiry.EndOfMonth));
         }
    +}
     
    -    private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +public class SpxEmaCrossAlphaModel : AlphaModel
    +{
    +    private ExponentialMovingAverage _emaSlow, _emaFast;
    +
    +    public SpxEmaCrossAlphaModel(QCAlgorithm algorithm)
         {
    -        // Select pairs where the quote currency is USDT.
    -        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    -            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    -            .OrderBy(c => c.VolumeInUsd)
    -            .TakeLast(3)
    -            .Select(c => c.Symbol);
    +        // Request SPX data for trade signal generation
    +        var spx = algorithm.AddIndex("SPX").Symbol;
    +
    +        // Create short and long-term EMA indicators for trend estimation to trade
    +        _emaFast = algorithm.EMA(spx, 80, Resolution.Daily);
    +        _emaSlow = algorithm.EMA(spx, 200, Resolution.Daily);
    +        algorithm.SetWarmUp(200, Resolution.Daily);
    +
    +        // Historical data
    +        var history = algorithm.History(spx, 60, Resolution.Daily);
    +        algorithm.Debug($"We got {history.Count()} items from our history request");
         }
     
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
         {
    -        foreach(var security in changes.AddedSecurities)
    +        // Trade signals required indicators to be ready
    +        if (algorithm.IsWarmingUp || !_emaSlow.IsReady)
             {
    -            // Historical data
    -            var history = History(security.Symbol, 30, Resolution.Daily);
    -            Debug($"We got {history.Count()} items from our history request");
    +            return Enumerable.Empty<Insight>();
             }
    -    }
    -}
    -
    -

    - Research Example -

    -

    - The following example lists crypto-currency pairs with the greatest dollar volume in the Bybit exchange: -

    -
    -
    var qb = new QuantBook();
    -
    -// Add Cryptocurrency pair
    -var symbol = qb.AddCrypto("BTCUSDT", market:Market.Bybit).Symbol;
    -
    -// Historical data
    -var history = qb.History(symbol, 30, Resolution.Daily);
    -foreach (var bar in history)
    -{
    -    Console.WriteLine($"{bar.EndTime} {bar}");
    -}
     
    -// Add Crypto Universe Selection
    -IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    -{
    -    return universeDay
    -        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    -        .OrderByDescending(x => x.VolumeInUsd)
    -        .Take(5)
    -        .Select(x => x.Symbol);
    -}
    -var universe = qb.AddUniverse(CryptoUniverse.Bybit(UniverseSelectionFilter));
    +        // If short-term EMA is above long-term, it indicates an up trend, so we buy SPY
    +        if (!algorithm.Portfolio.Invested && _emaFast > _emaSlow)
    +        {
    +            return algorithm.ActiveSecurities
    +                .Where(kvp => kvp.Value.IsTradable)
    +                .Select(kvp => Insight.Price(kvp.Key, Expiry.EndOfMonth, InsightDirection.Up));
    +        }
    +        // If it is the reverse, it indicates downtrend, and we liquidate any position
    +        else if (_emaFast < _emaSlow)
    +        {
    +            return algorithm.ActiveSecurities
    +                .Where(kvp => kvp.Value.IsTradable)
    +                .Select(kvp => Insight.Price(kvp.Key, Expiry.EndOfMonth, InsightDirection.Flat));
    +        }
     
    -// Historical Universe data
    -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var universeDay in universeHistory)
    -{
    -    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    -    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    -    {
    -        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +        return Enumerable.Empty<Insight>();
         }
     }
    -
    qb = QuantBook()
    -
    -# Add Cryptocurrency pair
    -symbol = qb.add_crypto("BTCUSDT", market=Market.BYBIT).symbol
    -
    -# Historical data
    -history = qb.history(symbol, 30, Resolution.DAILY)
    -for (symbol, time), row in history.iterrows():
    -    print(f'{time} {symbol} {row.close}')
    -
    -# Add Crypto Universe Selection
    -def universe_selection_filter(universe_day):
    -    selected = sorted([x for x in universe_day
    -        if x.volume_in_usd and x.volume_in_usd > 10000],
    -        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    -    return [x.symbol for x in selected]
    -
    -universe = qb.add_universe(CryptoUniverse.bybit(universe_selection_filter))
    -
    -# Historical Universe data
    -history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (univere_symbol, time), universe_day in history.items():
    -    print(f'=== {time} ===')
    -    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    -        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    @@ -227897,23 +199392,11 @@

    Data Point Attributes

    - The Bybit Crypto Price dataset provides + The Cash Indices dataset provides TradeBar - , - - QuoteBar - - , - - Tick - - , and - - CryptoUniverse - - objects. + object.

    TradeBar Attributes @@ -227926,47 +199409,14 @@

    -

    - QuoteBar Attributes -

    -

    - - QuoteBar - - objects have the following attributes: -

    -
    -
    -

    - Tick Attributes -

    -

    - - Tick - - objects have the following attributes: -

    -
    -
    -

    - CryptoUniverse Attributes -

    -

    - - CryptoUniverse - - objects have the following attributes: -

    -
    -

     

    - +
    -
    -

    CoinAPI

    +
    +

    QuantConnect

    Coinbase Crypto Price Data

    @@ -227974,7 +199424,7 @@

    Introduction

    - The Coinbase Crypto Price Data by CoinAPI provides Cryptocurrency price and volume data points. The data covers 970 Cryptocurrency pairs, starts in January 2015, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Coinbase. + The Coinbase Crypto Price Data provides Cryptocurrency price and volume data points. The data covers 970 Cryptocurrency pairs, starts in January 2015, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on Coinbase.

    For more information about the Coinbase Crypto Price Data dataset, including CLI commands and pricing, see the @@ -227992,10 +199442,11 @@

    About the Provider

    - - CoinAPI + Coinbase was founded by Brian Armstrong and Fred Ehrsam in 2012 with the goal to "increase economic freedom in the world". Coinbase provides access to trading Crypto for clients in over + + 100 countries - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. + with no minimum deposit. Coinbase also provides a self-hosted Crypto wallet, a Visa debit rewards card, and Bitcoin collateral-backed lines of credit.

    @@ -231513,277 +202964,1280 @@

    Supported Assets

    - - VETUSDC - - - VGXEUR - - - VGXUSD - - - VGXUSDT - - - VOXELUSD - - - VOXELUSDC - + + VETUSDC + + + VGXEUR + + + VGXUSD + + + VGXUSDT + + + VOXELUSD + + + VOXELUSDC + + + + + VTHOUSD + + + VTHOUSDC + + + VVVUSD + + + VVVUSDC + + + WAMPLUSD + + + WAMPLUSDC + + + + + WAXLUSD + + + WAXLUSDC + + + WBTCBTC + + + WBTCUSD + + + WBTCUSDC + + + WCFGBTC + + + + + WCFGEUR + + + WCFGGBP + + + WCFGUSD + + + WCFGUSDC + + + WCFGUSDT + + + WELLUSD + + + + + WELLUSDC + + + WIFUSD + + + WIFUSDC + + + WLDUSD + + + WLDUSDC + + + WLUNABTC + + + + + WLUNAEUR + + + WLUNAGBP + + + WLUNAUSD + + + WLUNAUSDT + + + XCNUSD + + + XCNUSDC + + + + + XLMBTC + + + XLMEUR + + + XLMUSD + + + XLMUSDC + + + XLMUSDT + + + XRPBTC + + + + + XRPEUR + + + XRPGBP + + + XRPUSD + + + XRPUSDC + + + XRPUSDT + + + XTZBTC + + + + + XTZEUR + + + XTZGBP + + + XTZUSD + + + XTZUSDC + + + XYOBTC + + + XYOEUR + + + + + XYOUSD + + + XYOUSDC + + + XYOUSDT + + + YFIBTC + + + YFIIUSD + + + YFIUSD + + + + + YFIUSDC + + + ZECBTC + + + ZECUSD + + + ZECUSDC + + + ZENBTC + + + ZENUSD + + + + + ZENUSDC + + + ZENUSDT + + + ZETACHAINUSD + + + ZETACHAINUSDC + + + ZETAUSD + + + ZETAUSDC + + + + + ZKUSD + + + ZKUSDC + + + ZORAUSD + + + ZORAUSDC + + + ZROUSD + + + ZROUSDC + + + + + ZRXBTC + + + ZRXEUR + + + ZRXUSD + + + ZRXUSDC + + + + +
    + + + +

    Example Applications

    + + +

    + The Coinbase Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: +

    +
      +
    • + Buy and hold +
    • +
    • + Trading Cryptocurrency volatility and price action +
    • +
    • + Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys and holds Bitcoin through the Coinbase exchange: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.universe_settings.asynchronous = True
    +        self.set_cash(100_000)
    +        # Coinbase accepts Cash account type only. AccountType.MARGIN
    +        # results in an exception.
    +        self.set_brokerage_model(BrokerageName.COINBASE, AccountType.CASH)
    +        # Add BTCUSD data.
    +        self._btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.COINBASE)
    +        # Historical data
    +        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    +        # Add a Crypto universe that selects Crypto pairs on Coinbase.
    +        universe = self.add_universe(CryptoUniverse.coinbase(self._select_assets))
    +        # Historical Universe data
    +        universe_history = self.history(universe, 30, Resolution.DAILY)
    +        for (universe_symbol, time), universe_day in universe_history.items():
    +            for universe_item in universe_day:
    +                symbol = universe_item.symbol
    +                price = universe_item.close
    +
    +    def _select_assets(self, universe_day):
    +        # Filter for materially traded Crypto pairs with significant 
    +        # size and dollar volume, assuming higher capital flow in for 
    +        # higher return.
    +        return [universe_item.symbol for universe_item in universe_day
    +                if universe_item.volume >= 100 
    +                and universe_item.volume_in_usd > 10_000_000]
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Speculate-invest all available free cash on BTCUSD, repecting 
    +        # the order quantity restrictions to avoid invalid orders.
    +        if self.portfolio.cash_book['BTC'].amount != 0:
    +            return
    +        # Define a buffer so that we can scale down the order size,
    +        # avoiding trading errors.
    +        buffer = max(
    +            CoinbaseFeeModel.TAKER_ADVANCED_1, 
    +            self.settings.free_portfolio_value_percentage
    +        )
    +        quantity = (
    +            self.portfolio.cash_book['USD'].amount
    +            / self._btc.ask_price
    +            * (1-buffer)
    +        )
    +        # Check if the quantity exceeds the minimum order size. On 
    +        # Coinbase, the minimum order size is measured in the base 
    +        # currency (BTC in this case).
    +        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    +            return
    +        self.market_order(self._btc, quantity)
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private Crypto _btc;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        UniverseSettings.Asynchronous = true;
    +        SetCash(100000);
    +        // Coinbase accepts Cash account type only. AccountType.Margin
    +        // results in an exception.
    +        SetBrokerageModel(BrokerageName.Coinbase, AccountType.Cash);
    +        // Add BTCUSD data.
    +        _btc = AddCrypto("BTCUSD", Resolution.Minute, Market.Coinbase);   
    +        // Historical data
    +        var history = History(_btc.Symbol, 30, Resolution.Daily);
    +        // Add a Crypto universe that selects trading pairs on Coinbase.
    +        var universe = AddUniverse(CryptoUniverse.Coinbase(SelectAssets));
    +        // Historical Universe data
    +        var universeHistory = History(universe, 30, Resolution.Daily);
    +        foreach (var universeDay in universeHistory)
    +        {
    +            foreach (CryptoUniverse universeItem in universeDay)
    +            {
    +                var symbol = universeItem.Symbol;
    +                var price = universeItem.Close;
    +            }
    +        }
    +    }
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Filter for materially traded Crypto pairs with significant 
    +        // size and dollar volume, assuming higher capital flow in for 
    +        // higher return.
    +        return from universeItem in universeDay
    +                where universeItem.Volume >= 100m 
    +                && universeItem.VolumeInUsd > 10000000m
    +                select universeItem.Symbol;
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Speculate-invest all available free cash on BTCUSD, repecting 
    +        // the order quantity restrictions to avoid invalid orders.
    +        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        {
    +            return;
    +        }
    +        // Define a buffer so that we can scale down the order size,
    +        // avoiding trading errors.
    +        var buffer = Math.Max(CoinbaseFeeModel.TakerAdvanced1, Settings.FreePortfolioValuePercentage);
    +        var quantity = Portfolio.CashBook["USD"].Amount / _btc.AskPrice * (1-buffer);
    +        // Check if the quantity exceeds the minimum order size. On 
    +        // Coinbase, the minimum order size is measured in the base 
    +        // currency (BTC in this case).
    +        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +        {
    +            return;
    +        }
    +        MarketOrder(_btc, quantity);
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of Crypto pairs on the Coinbase exchange and then forms a equal-weighted portfolio of all the pairs in the universe: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 2, 1)
    +        self.set_cash(100000)
    +        self.settings.free_portfolio_value_percentage = 0.05
    +        # Warm up the security with the last known price to avoid conversion error
    +        self.settings.seed_initial_prices = True
    +        self.universe_settings.asynchronous = True
    +        self.universe_settings.resolution = Resolution.MINUTE
    +        # Add Crypto Universe Selection that select crypto pairs in Coinbase exchange
    +        self.add_universe(CryptoUniverse.coinbase(self._select_assets))
    +        # Get the pairs on Coinbase that have USD as the quote currency.
    +        self._market_pairs = [
    +            x.key.symbol 
    +            for x in self.symbol_properties_database.get_symbol_properties_list(Market.COINBASE) 
    +            if x.value.quote_currency == self.account_currency
    +        ]
    +        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(hours=4), 0.025, None))
    +        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    +    def _select_assets(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    +        # Select pairs where the quote currency is USD.
    +        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    +        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    +        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    +        return [c.symbol for c in pairs]
    +
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = self.history(security.symbol, 30, Resolution.DAILY)
    +            self.debug(f"We got {len(history)} items from our history request")
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private List<string> _marketPairs;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 2, 1);
    +        SetCash(100000);
    +        Settings.FreePortfolioValuePercentage = 0.05m;
    +        // Warm up the security with the last known price to avoid conversion error
    +        Settings.SeedInitialPrices = true;
    +        UniverseSettings.Asynchronous = true;
    +        UniverseSettings.Resolution = Resolution.Minute;
    +        // Add Crypto Universe Selection that select crypto pairs in Coinbase exchange
    +        AddUniverse(CryptoUniverse.Coinbase(SelectAssets));
    +        // Get the pairs on Coinbase that have USD as the quote currency.
    +        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Coinbase)
    +            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    +            .Select(x => x.Key.Symbol)
    +            .ToList();
    +        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(4), 0.025, null) );
    +        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +    }
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Select pairs where the quote currency is USD.
    +        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    +            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    +            .OrderBy(c => c.VolumeInUsd)
    +            .TakeLast(3)
    +            .Select(c => c.Symbol);
    +    }
    +
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach(var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = History(security.Symbol, 30, Resolution.Daily);
    +            Debug($"We got {history.Count()} items from our history request");
    +        }
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example lists crypto-currency pairs with the greatest dollar volume in the Coinbase exchange: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add Cryptocurrency pair
    +var symbol = qb.AddCrypto("BTCUSDT", market:Market.Coinbase).Symbol;
    +
    +// Historical data
    +var history = qb.History(symbol, 30, Resolution.Daily);
    +foreach (var bar in history)
    +{
    +    Console.WriteLine($"{bar.EndTime} {bar}");
    +}
    +
    +// Add Crypto Universe Selection
    +IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +{
    +    return universeDay
    +        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    +        .OrderByDescending(x => x.VolumeInUsd)
    +        .Take(5)
    +        .Select(x => x.Symbol);
    +}
    +var universe = qb.AddUniverse(CryptoUniverse.Coinbase(UniverseSelectionFilter));
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var universeDay in universeHistory)
    +{
    +    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    +    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    +    {
    +        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add Cryptocurrency pair
    +symbol = qb.add_crypto("BTCUSDT", market=Market.COINBASE).symbol
    +
    +# Historical data
    +history = qb.history(symbol, 30, Resolution.DAILY)
    +for (symbol, time), row in history.iterrows():
    +    print(f'{time} {symbol} {row.close}')
    +
    +# Add Crypto Universe Selection
    +def universe_selection_filter(universe_day):
    +    selected = sorted([x for x in universe_day
    +        if x.volume_in_usd and x.volume_in_usd > 10000],
    +        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    +    return [x.symbol for x in selected]
    +
    +universe = qb.add_universe(CryptoUniverse.coinbase(universe_selection_filter))
    +
    +# Historical Universe data
    +history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (univere_symbol, time), universe_day in history.items():
    +    print(f'=== {time} ===')
    +    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    +        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The Coinbase Crypto Price dataset provides + + TradeBar + + , + + QuoteBar + + , + + Tick + + , and + + CryptoUniverse + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    +

    + CryptoUniverse Attributes +

    +

    + + CryptoUniverse + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    FOREX Data

    +
    +
    +

    Introduction

    + + +

    + The FOREX Data by QuantConnect serves 71 + + foreign exchange + + (FOREX) pairs, starts on various dates from January 2007, and is delivered on any frequency from tick to daily. This dataset is created by QuantConnect processing raw tick data from OANDA. +

    +

    + FOREX data does not include ask and bid sizes. +

    +

    + For more information about the FOREX Data dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the FOREX dataset: +

    +
    +
    self.eurusd = self.add_forex("EURUSD", Resolution.DAILY).symbol
    +
    _symbol = AddForex("EURUSD", Resolution.Daily).Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2007 +
    + Asset Coverage + + 71 Currency pairs +
    + Data Density + + Dense +
    + Resolution + + Tick, Second, Minute, Hour, & Daily +
    + Timezone + + UTC +
    + Market Hours + + + Always Open + + , except from Friday 5 PM EST to Sunday 5 PM EST +
    + + + +

    Requesting Data

    + + +

    + To add FOREX data to your algorithm, call the + + AddForex + + + add_forex + + method. Save a reference to the Forex + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    +class ForexAlgorithm (QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2019, 2, 20)
    +        self.set_end_date(2019, 2, 21)
    +        self.set_cash(100000)
    +
    +        self.eurusd = self.add_forex('EURUSD', Resolution.MINUTE).symbol
    +
    +        self.set_benchmark(self.eurusd)
    +
    +
    public class ForexAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2019, 2, 20);
    +        SetEndDate(2019, 2, 21);
    +        SetCash(100000);
    +
    +        _symbol = AddForex("EURUSD", Resolution.Minute).Symbol;
    +
    +        SetBenchmark(_symbol);
    +    }
    +}
    +
    +

    + For more information about creating Forex subscriptions, see + + Requesting Data + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current Forex data, index the + + QuoteBars + + + quote_bars + + , or + + Ticks + + + ticks + + properties of the current + + + Slice + + + with the Forex + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    if self.eurusd in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.eurusd]
    +        self.log(f"{self.eurusd} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    if self.eurusd in slice.ticks:
    +        ticks = slice.ticks[self.eurusd]
    +        for tick in ticks:
    +            self.log(f"{self.eurusd} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    if (slice.QuoteBars.ContainsKey(_symbol))
    +    {
    +        var quoteBar = slice.QuoteBars[_symbol];
    +        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    if (slice.Ticks.ContainsKey(_symbol))
    +    {
    +        var ticks = slice.Ticks[_symbol];
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + You can also iterate through all of the data objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for symbol, quote_bar in slice.quote_bars.items():
    +        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    for symbol, ticks in slice.ticks.items():
    +        for tick in ticks:
    +            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.QuoteBars)
    +    {
    +        var symbol = kvp.Key;
    +        var quoteBar = kvp.Value;
    +        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    foreach (var kvp in slice.Ticks)
    +    {
    +        var symbol = kvp.Key;
    +        var ticks = kvp.Value;
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + For more information about accessing Forex data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + To get historical Forex data, call the + + History + + + history + + method with the Forex + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.eurusd, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](self.eurusd, 100, Resolution.MINUTE)
    +
    +# Tick objects
    +history_ticks = self.history[Tick](self.eurusd, timedelta(seconds=10), Resolution.TICK)
    +
    // QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    +
    +// Tick objects 
    +var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Remove Subscriptions

    + + +

    + To remove a Forex pair subscription, call the + + RemoveSecurity + + + remove_security + + method. +

    +
    +
    self.remove_security(self.eurusd)
    +
    RemoveSecurity(_symbol);
    +
    +

    + The + + RemoveSecurity + + + remove_security + + method cancels your open orders for the security and liquidates your holdings. +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available Forex pairs: +

    +
    + + + + + + - - - - - - - @@ -231796,382 +204250,1416 @@

    Example Applications

    - The Coinbase Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: + The FOREX price data enables you to trade currency pairs in the global market. Examples include the following strategies: +

    +
      +
    • + Exploring the impact that daily worldwide news cycles have on international currencies +
    • +
    • + Carry Trade: borrow from a lower interest currency pair to fund the purchase of a currency pair with a higher interest rate +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm implements a FOREX carry trade. It buys the FOREX pair of the country with the lowest interest rate and sells the FOREX pair of the country with the highest interest rate. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class ForexCarryTradeAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(25000)
    +        
    +        # We will use hard-coded interest rates for each base currency
    +        self.rates = {
    +            "USDAUD": 1.5,    # Australia
    +            "USDCAD": 0.5,    # Canada
    +            "USDCNY": 4.35,   # China
    +            "USDEUR": 0.0,    # Euro Area
    +            "USDINR": 6.5,    # India
    +            "USDJPY": -0.1,   # Japan
    +            "USDMXN": 4.25,   # Mexico
    +            "USDTRY": 7.5,    # Turkey
    +            "USDZAR": 7.0     # South Africa
    +        }
    +
    +        # Subscribe to forex data for trading
    +        for ticker in self.rates:
    +            self.add_forex(ticker, Resolution.DAILY)
    +
    +        # Use a month counter as variable to control rebalancing
    +        self.month = -1
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Monthly rebalance checker
    +        if self.month == self.time.month:
    +            return
    +        self.month = self.time.month
    +        
    +        # Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    +        sorted_rates = sorted(self.rates.items(), key = lambda x: x[1])
    +        self.set_holdings(sorted_rates[0][0], -0.5)
    +        self.set_holdings(sorted_rates[-1][0], 0.5)
    +
    +
    public class ForexCarryTradeAlgorithm : QCAlgorithm
    +{
    +    // Use a month counter as variable to control rebalancing
    +    private int _month = -1;
    +    private Dictionary<string, decimal> _rates;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(25000);
    +        
    +        // We will use hard-coded interest rates for each base currency
    +        _rates = new Dictionary<string, decimal>()
    +        {
    +            {"USDAUD", 1.5m},    // Australia
    +            {"USDCAD", 0.5m},    // Canada
    +            {"USDCNY", 4.35m},   // China
    +            {"USDEUR", 0.0m},    // Euro Area
    +            {"USDINR", 6.5m},    // India
    +            {"USDJPY", -0.1m},   // Japan
    +            {"USDMXN", 4.25m},   // Mexico
    +            {"USDTRY", 7.5m},    // Turkey
    +            {"USDZAR", 7.0m}     // South Africa
    +        };
    +
    +        // Subscribe to forex data for trading
    +        foreach (var ticker in _rates.Keys)
    +        {
    +            AddForex(ticker, Resolution.Daily);
    +        }
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Monthly rebalance checker
    +        if (_month == Time.Month) return;
    +        _month = Time.Month;
    +
    +        // Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    +        var sortedRates = (from kvp in _rates orderby kvp.Value ascending select kvp.Key).ToArray();
    +        SetHoldings(sortedRates[0], -0.5);
    +        SetHoldings(sortedRates[sortedRates.Length-1], 0.5);
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm implements a FOREX carry trade. It buys the FOREX pair of the country with the lowest interest rate and sells the FOREX pair of the country with the highest interest rate. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class ForexCarryTradeAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(25000)
    +        
    +        def to_symbol(ticker: str) -> Symbol:
    +            return Symbol.create(ticker, SecurityType.FOREX, Market.OANDA)
    +        
    +        # We will use hard-coded interest rates for each base currency
    +        rates = {
    +            to_symbol("USDAUD"): 1.5,    # Australia
    +            to_symbol("USDCAD"): 0.5,    # Canada
    +            to_symbol("USDCNY"): 4.35,   # China
    +            to_symbol("USDEUR"): 0.0,    # Euro Area
    +            to_symbol("USDINR"): 6.5,    # India
    +            to_symbol("USDJPY"): -0.1,   # Japan
    +            to_symbol("USDMXN"): 4.25,   # Mexico
    +            to_symbol("USDTRY"): 7.5,    # Turkey
    +            to_symbol("USDZAR"): 7.0     # South Africa
    +        }
    +        
    +        self.set_universe_selection(ManualUniverseSelectionModel(list(rates.keys())))
    +        # A custom alpha model to emit insight according to interest rate
    +        self.set_alpha(IntestRatesAlphaModel(rates))
    +        # Equal size to capitalize the monetary value of quote currency only based on interest rate difference
    +        # For dollar-neutral to save margin cost
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(Expiry.END_OF_MONTH))
    +
    +class IntestRatesAlphaModel(AlphaModel):
    +    def __init__(self, rates: float) -> None:
    +        self.rates = rates
    +        # Variable to control the rebalancing time
    +        self.month = -1
    +                
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        # Monthly rebalance
    +        if self.month == algorithm.time.month:
    +            return []
    +        self.month = algorithm.time.month
    +
    +        # # Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    +        sorted_rates = sorted(self.rates.items(), key = lambda x: x[1])
    +        return Insight.group(
    +            Insight.price(sorted_rates[0][0], Expiry.END_OF_MONTH, InsightDirection.UP),
    +            Insight.price(sorted_rates[-1][0], Expiry.END_OF_MONTH, InsightDirection.DOWN)
    +        )
    +
    +
    public class ForexCarryTradeAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(25000);
    +        
    +        Symbol toSymbol(string ticker)
    +        {
    +            return QuantConnect.Symbol.Create(ticker, SecurityType.Forex, Market.Oanda);
    +        }
    +        
    +        // We will use hard-coded interest rates for each base currency
    +        var rates = new Dictionary<Symbol, decimal>()
    +        {
    +            {toSymbol("USDAUD"), 1.5m},    // Australia
    +            {toSymbol("USDCAD"), 0.5m},    // Canada
    +            {toSymbol("USDCNY"), 4.35m},   // China
    +            {toSymbol("USDEUR"), 0.0m},    // Euro Area
    +            {toSymbol("USDINR"), 6.5m},    // India
    +            {toSymbol("USDJPY"), -0.1m},   // Japan
    +            {toSymbol("USDMXN"), 4.25m},   // Mexico
    +            {toSymbol("USDTRY"), 7.5m},    // Turkey
    +            {toSymbol("USDZAR"), 7.0m}     // South Africa
    +        };
    +
    +        SetUniverseSelection(new ManualUniverseSelectionModel(rates.Keys));
    +        // A custom alpha model to emit insight according to interest rate
    +        SetAlpha(new IntestRatesAlphaModel(rates));
    +        // Equal size to capitalize the monetary value of quote currency only based on interest rate difference
    +        // For dollar-neutral to save margin cost
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(Expiry.EndOfMonth));
    +    }
    +}
    +
    +public class IntestRatesAlphaModel : AlphaModel
    +{
    +    // Variable to control the rebalancing time
    +    private int _month = -1;
    +    private Dictionary<Symbol, decimal> _rates;
    +
    +    public IntestRatesAlphaModel(Dictionary<Symbol, decimal> rates)
    +    {
    +        _rates = rates;
    +    }
    +
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        // Monthly rebalance
    +        if (_month == algorithm.Time.Month)
    +        {
    +            return Enumerable.Empty<Insight>();
    +        }
    +        _month = algorithm.Time.Month;
    +
    +        // Long the pair with highest interest rate and sell the pair with the lowest to earn the max monetary inflation difference between the two
    +        var sortedRates = (from kvp in _rates orderby kvp.Value ascending select kvp.Key).ToArray();
    +        
    +        return Insight.Group(
    +            Insight.Price(sortedRates[0], Expiry.EndOfMonth, InsightDirection.Up),
    +            Insight.Price(sortedRates[sortedRates.Length-1], Expiry.EndOfMonth, InsightDirection.Down)
    +        );
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The FOREX dataset provides + + QuoteBar + + and + + Tick + + objects. +

    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    Fear and Greed

    +
    +
    +

    Introduction

    + + +

    + The Fear and Greed dataset by QuantConnect provides data points to quantify the degree of fear and greed in the US Equity market. The data starts in 2014 and is delivered on a daily frequency, delayed by two days. This dataset is created by aggregating seven indicators, including market volatility, stock market breadth, and put-call ratios. +

    +

    + For more information about the Fear and Greed dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the Fear and Greed dataset: +

    +
    +
    self._dataset_symbol = self.add_data(FearGreedIndex, 'FG').symbol
    +
    _datasetSymbol = AddData<FearGreedIndex>("FG").Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + July 2014 +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + + New York +
    +

    + The latest daily data points are about two days since the VIX and SPX prices are inputs into the index and their latest daily prices are also two days old. New data is available at 9 AM EST. +

    + + + +

    Requesting Data

    + + +

    + To add Fear and Greed data to your algorithm, call the + + AddData<FearGreedIndex> + + + add_data + + method. Save a reference to the dataset + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class FearAndGreedDataAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2019, 1, 1)
    +        self.set_end_date(2020, 6, 1)
    +        self.set_cash(100000)
    +
    +        self._symbol = self.add_equity("SPY", Resolution.DAILY).symbol
    +        self._dataset_symbol = self.add_data(FearGreedIndex, "FG").symbol
    +
    public class FearAndGreedDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol, _datasetSymbol;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2019, 1, 1);
    +        SetEndDate(2020, 6, 1);
    +        SetCash(100000);
    +        _symbol = AddEquity("SPY", Resolution.Daily).Symbol;
    +        _datasetSymbol = AddData<FearGreedIndex>("FG").Symbol;
    +    }
    +}
    +
    + + + +

    Accessing Data

    + + +

    + To get the current Fear and Greed data, index the current + + + Slice + + + with the dataset + + Symbol + + . + + Slice + + objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your dataset at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    if slice.contains_key(self._dataset_symbol):
    +        data_point = slice[self._dataset_symbol]
    +        self.log(f"{self._dataset_symbol} value at {slice.time}: {data_point.value}")
    +
    public override void OnData(Slice slice)
    +{
    +    if (slice.ContainsKey(_datasetSymbol))
    +    {
    +        var dataPoint = slice[_datasetSymbol];
    +        Log($"{_datasetSymbol} value at {slice.Time}: {dataPoint.Value}");
    +    }
    +}
    +
    +
    + + + +

    Historical Data

    + + +

    + To get historical Fear and Greed data, call the + + History + + + history + + method with the dataset + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self._dataset_symbol, 100, Resolution.DAILY)
    +
    +# Dataset objects
    +history = self.history[FearGreedIndex](self._dataset_symbol, 100, Resolution.DAILY)
    +
    var history = History<FearGreedIndex>(_datasetSymbol, 100, Resolution.Daily);
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Remove Subscription

    + + +

    + To remove a subscription to the Fear and Greed dataset, call the + + RemoveSecurity + + + remove_security + + method. +

    +
    +
    self.remove_security(self._dataset_symbol)
    +
    RemoveSecurity(_datasetSymbol);
    +
    + + + +

    Example Applications

    + + +

    + The Fear and Greed dataset quantifies the degree of fear and greed in the US Equity market. Example use cases include the following strategies:

    • - Buy and hold + Accumulate long-term positions when the market is fearful (the index is low).
    • - Trading Cryptocurrency volatility and price action + Short risky assets when the market is greedy.
    • - Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation + Trade + + butterfly Option strategies + + based on the market volatility indicator.

    Classic Algorithm Example

    - The following example algorithm buys and holds Bitcoin through the Coinbase exchange: + The following example algorithm buys SPY when the Fear and Greed index is less than 25 (extreme fear) and sells when it's above 75 (extreme greed).

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    +class FearAndGreedExampleAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        self.universe_settings.asynchronous = True
    -        self.set_cash(100_000)
    -        # Coinbase accepts Cash account type only. AccountType.MARGIN
    -        # results in an exception.
    -        self.set_brokerage_model(BrokerageName.COINBASE, AccountType.CASH)
    -        # Add BTCUSD data.
    -        self._btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.COINBASE)
    -        # Historical data
    -        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    -        # Add a Crypto universe that selects Crypto pairs on Coinbase.
    -        universe = self.add_universe(CryptoUniverse.coinbase(self._select_assets))
    -        # Historical Universe data
    -        universe_history = self.history(universe, 30, Resolution.DAILY)
    -        for (universe_symbol, time), universe_day in universe_history.items():
    -            for universe_item in universe_day:
    -                symbol = universe_item.symbol
    -                price = universe_item.close
    -
    -    def _select_assets(self, universe_day):
    -        # Filter for materially traded Crypto pairs with significant 
    -        # size and dollar volume, assuming higher capital flow in for 
    -        # higher return.
    -        return [universe_item.symbol for universe_item in universe_day
    -                if universe_item.volume >= 100 
    -                and universe_item.volume_in_usd > 10_000_000]
    +        self.set_cash(100000)
     
    -    def on_data(self, slice: Slice) -> None:
    -        # Speculate-invest all available free cash on BTCUSD, repecting 
    -        # the order quantity restrictions to avoid invalid orders.
    -        if self.portfolio.cash_book['BTC'].amount != 0:
    -            return
    -        # Define a buffer so that we can scale down the order size,
    -        # avoiding trading errors.
    -        buffer = max(
    -            CoinbaseFeeModel.TAKER_ADVANCED_1, 
    -            self.settings.free_portfolio_value_percentage
    -        )
    -        quantity = (
    -            self.portfolio.cash_book['USD'].amount
    -            / self._btc.ask_price
    -            * (1-buffer)
    -        )
    -        # Check if the quantity exceeds the minimum order size. On 
    -        # Coinbase, the minimum order size is measured in the base 
    -        # currency (BTC in this case).
    -        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    +        # Add the market index to trade.
    +        self._equity = self.add_equity('SPY', Resolution.DAILY)
    +        # Add the Fear and Greed dataset.
    +        self._dataset_symbol = self.add_data(FearGreedIndex, 'FG').symbol
    +    
    +    def on_data(self, data: Slice) -> None:
    +        # Wait until the Fear and Greed dataset has new data.
    +        if self._dataset_symbol not in data:
                 return
    -        self.market_order(self._btc, quantity)
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +        value = data[self._dataset_symbol].value
    +        # Buy when the market is fearful.
    +        if not self._equity.invested and value < 25:
    +            self.set_holdings(self._equity.symbol, 1)
    +        # Sell when the market is greedy.
    +        elif self._equity.invested and value > 75:
    +            self.liquidate()
    +
    public class FearAndGreedExampleAlgorithm : QCAlgorithm
     {
    -    private Crypto _btc;
    -    
    +    private Equity _equity;
    +    private Symbol _datasetSymbol;
    +
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        UniverseSettings.Asynchronous = true;
             SetCash(100000);
    -        // Coinbase accepts Cash account type only. AccountType.Margin
    -        // results in an exception.
    -        SetBrokerageModel(BrokerageName.Coinbase, AccountType.Cash);
    -        // Add BTCUSD data.
    -        _btc = AddCrypto("BTCUSD", Resolution.Minute, Market.Coinbase);   
    -        // Historical data
    -        var history = History(_btc.Symbol, 30, Resolution.Daily);
    -        // Add a Crypto universe that selects trading pairs on Coinbase.
    -        var universe = AddUniverse(CryptoUniverse.Coinbase(SelectAssets));
    -        // Historical Universe data
    -        var universeHistory = History(universe, 30, Resolution.Daily);
    -        foreach (var universeDay in universeHistory)
    -        {
    -            foreach (CryptoUniverse universeItem in universeDay)
    -            {
    -                var symbol = universeItem.Symbol;
    -                var price = universeItem.Close;
    -            }
    -        }
    -    }
     
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    -    {
    -        // Filter for materially traded Crypto pairs with significant 
    -        // size and dollar volume, assuming higher capital flow in for 
    -        // higher return.
    -        return from universeItem in universeDay
    -                where universeItem.Volume >= 100m 
    -                && universeItem.VolumeInUsd > 10000000m
    -                select universeItem.Symbol;
    +        // Add the market index to trade.
    +        _equity = AddEquity("SPY", Resolution.Daily);
    +        // Add the Fear and Greed dataset.
    +        _datasetSymbol = AddData<FearGreedIndex>("FG").Symbol;
         }
     
    -    public override void OnData(Slice slice)
    +    public override void OnData(Slice data)
         {
    -        // Speculate-invest all available free cash on BTCUSD, repecting 
    -        // the order quantity restrictions to avoid invalid orders.
    -        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        // Wait until the Fear and Greed dataset has new data
    +        if (!data.ContainsKey(_datasetSymbol))
             {
                 return;
             }
    -        // Define a buffer so that we can scale down the order size,
    -        // avoiding trading errors.
    -        var buffer = Math.Max(CoinbaseFeeModel.TakerAdvanced1, Settings.FreePortfolioValuePercentage);
    -        var quantity = Portfolio.CashBook["USD"].Amount / _btc.AskPrice * (1-buffer);
    -        // Check if the quantity exceeds the minimum order size. On 
    -        // Coinbase, the minimum order size is measured in the base 
    -        // currency (BTC in this case).
    -        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +        var value = data[_datasetSymbol].Value;
    +        // Buy when the market is fearful.
    +        if (!_equity.Invested && value < 25)
             {
    -            return;
    +            SetHoldings(_equity.Symbol, 1);
    +        }
    +        // Sell when the market is greedy.
    +        else if (_equity.Invested && value > 75)
    +        {
    +            Liquidate();
             }
    -        MarketOrder(_btc, quantity);
         }
     }

    - Framework Algorithm Example + Framework Example

    - The following example algorithm creates a dynamic universe of Crypto pairs on the Coinbase exchange and then forms a equal-weighted portfolio of all the pairs in the universe: + The following example algorithm buys SPY when the Fear and Greed index is less than 25 (extreme fear) and sells when it's above 75 (extreme greed).

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    +class FearAndGreedExampleAlgorithm(QCAlgorithm):
     
         def initialize(self) -> None:
    -        self.set_start_date(2020, 6, 1)
    -        self.set_end_date(2021, 2, 1)
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
             self.set_cash(100000)
    -        self.settings.free_portfolio_value_percentage = 0.05
    -        # Warm up the security with the last known price to avoid conversion error
    -        self.settings.seed_initial_prices = True
    -        self.universe_settings.asynchronous = True
    -        self.universe_settings.resolution = Resolution.MINUTE
    -        # Add Crypto Universe Selection that select crypto pairs in Coinbase exchange
    -        self.add_universe(CryptoUniverse.coinbase(self._select_assets))
    -        # Get the pairs on Coinbase that have USD as the quote currency.
    -        self._market_pairs = [
    -            x.key.symbol 
    -            for x in self.symbol_properties_database.get_symbol_properties_list(Market.COINBASE) 
    -            if x.value.quote_currency == self.account_currency
    -        ]
    -        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(hours=4), 0.025, None))
    -        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +
    +        # Trade SPY on a daily basis.
    +        self.universe_settings.resolution = Resolution.DAILY
    +        symbols = [Symbol.create('SPY', SecurityType.EQUITY, Market.USA)]
    +        self.add_universe_selection(ManualUniverseSelectionModel(symbols))
    +        # Add a custom Alpha model that emits insights based on the Fear and Greed dataset.
    +        self.add_alpha(FearAndGreedAlphaModel(self))
    +        # Set the equal weighted PCM so the algorithm places trades.
             self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
     
    -    def _select_assets(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    -        # Select pairs where the quote currency is USD.
    -        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    -        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    -        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    -        return [c.symbol for c in pairs]
     
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +# Define the custom alpha model.
    +class FearAndGreedAlphaModel(AlphaModel):
    +
    +    def __init__(self, algorithm):
    +        # Create a list to track the current universe.
    +        self._securities = []
    +        # Add the Fear and Greed dataset. 
    +        self._dataset_symbol = algorithm.add_data(FearGreedIndex, 'FG').symbol
    +
    +    def update(self, algorithm: QCAlgorithm, data: Slice) -> List[Insight]:
    +        # Wait until the Fear and Greed dataset has new data.
    +        if self._dataset_symbol not in data:
    +            return []
    +        # Wait until the Fear and Greed index is extreme.
    +        value = data[self._dataset_symbol].value
    +        if 25 <= value <= 75:
    +            return []
    +        insights = []
    +        for security in self._securities:
    +            # Buy when the market is fearful.
    +            if not security.invested and value < 25:
    +                direction = InsightDirection.UP
    +            # Sell when the market is greedy.
    +            elif security.invested and value > 75:
    +                direction = InsightDirection.FLAT
    +            else:
    +                continue
    +            insights.append(Insight.price(security.symbol, timedelta(2*365), direction))
    +        return insights
    +
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        # When assets enter the universe, save them.
             for security in changes.added_securities:
    -            # Historical data
    -            history = self.history(security.symbol, 30, Resolution.DAILY)
    -            self.debug(f"We got {len(history)} items from our history request")
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +            self._securities.append(security)
    +        # When assets leave the universe, remove them.
    +        for security in changes.removed_securities:
    +            if security in self._securities:
    +                self._securities.remove(security)
    +
    public class FearAndGreedExampleAlgorithm : QCAlgorithm
     {
    -    private List<string> _marketPairs;
    -    
         public override void Initialize()
         {
    -        SetStartDate(2020, 6, 1);
    -        SetEndDate(2021, 2, 1);
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
             SetCash(100000);
    -        Settings.FreePortfolioValuePercentage = 0.05m;
    -        // Warm up the security with the last known price to avoid conversion error
    -        Settings.SeedInitialPrices = true;
    -        UniverseSettings.Asynchronous = true;
    -        UniverseSettings.Resolution = Resolution.Minute;
    -        // Add Crypto Universe Selection that select crypto pairs in Coinbase exchange
    -        AddUniverse(CryptoUniverse.Coinbase(SelectAssets));
    -        // Get the pairs on Coinbase that have USD as the quote currency.
    -        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Coinbase)
    -            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    -            .Select(x => x.Key.Symbol)
    -            .ToList();
    -        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(4), 0.025, null) );
    -        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +
    +        // Trade SPY on a daily basis.
    +        UniverseSettings.Resolution = Resolution.Daily;
    +        var symbols = new[] { QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA) };
    +        AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
    +        // Add a custom Alpha model that emits insights based on the Fear and Greed dataset.
    +        AddAlpha(new FearAndGreedAlphaModel(this));
    +        // Set the equal weighted PCM so the algorithm places trades.
             SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
         }
    +}
     
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    +// Define the custom Alpha model.
    +public class FearAndGreedAlphaModel : AlphaModel
    +{
    +    // Create a list to track the current universe.
    +    private List<Security> _securities = new List<Security>();
    +    private Symbol _datasetSymbol;
    +
    +    public FearAndGreedAlphaModel(QCAlgorithm algorithm)
         {
    -        // Select pairs where the quote currency is USD.
    -        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    -            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    -            .OrderBy(c => c.VolumeInUsd)
    -            .TakeLast(3)
    -            .Select(c => c.Symbol);
    +        // Add the Fear and Greed dataset. 
    +        _datasetSymbol = algorithm.AddData<FearGreedIndex>("FG").Symbol;
         }
     
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
         {
    -        foreach(var security in changes.AddedSecurities)
    +        // Wait until the Fear and Greed dataset has new data.
    +        if (!data.ContainsKey(_datasetSymbol))
             {
    -            // Historical data
    -            var history = History(security.Symbol, 30, Resolution.Daily);
    -            Debug($"We got {history.Count()} items from our history request");
    +            return Enumerable.Empty<Insight>();
    +        }
    +        // Wait until the Fear and Greed index is extreme.
    +        var value = data[_datasetSymbol].Value;
    +        if (value >= 25 && value <= 75)
    +        {
    +            return Enumerable.Empty<Insight>();
    +        }
    +
    +        var insights = new List<Insight>();
    +        foreach (var security in _securities)
    +        {
    +            InsightDirection direction;
    +            // Buy when the market is fearful.
    +            if (!security.Invested && value < 25)
    +            {
    +                direction = InsightDirection.Up;
    +            }
    +            // Sell when the market is greedy.
    +            else if (security.Invested && value > 75)
    +            {
    +                direction = InsightDirection.Flat;
    +            }
    +            else
    +            {
    +                continue;
    +            }
    +            insights.Add(Insight.Price(security.Symbol, TimeSpan.FromDays(2 * 365), direction));
    +        }
    +        return insights;
    +    }
    +
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {
    +        // When assets enter the universe, save them.
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            _securities.Add(security);
    +        }
    +        // When assets leave the universe, remove them.
    +        foreach (var security in changes.RemovedSecurities)
    +        {
    +            _securities.Remove(security);
             }
         }
     }
    -

    - Research Example -

    + + + +

    Data Point Attributes

    + +

    - The following example lists crypto-currency pairs with the greatest dollar volume in the Coinbase exchange: + The Fear and Greed dataset provides + + FearGreedIndex + + objects, which have the following attributes:

    -
    -
    var qb = new QuantBook();
    +  
    +
    + + -// Add Cryptocurrency pair -var symbol = qb.AddCrypto("BTCUSDT", market:Market.Coinbase).Symbol; +

     

    + +
    +
    +

    QuantConnect

    +

    International Future Universe

    +
    +
    +

    Introduction

    + + +

    + The International Future Universe dataset by QuantConnect lists the available International Future contracts, their daily trading volume, and Open Interest. The data covers 4 contracts (DAX, FESX, HSI, and NKD), starts in July 1998, and is delivered on daily frequency. This dataset is created by monitoring the trading activity on the EUREX, HKFE, and CME. +

    +

    + This dataset depends on the + + US Futures Security Master + + dataset because the US Futures Security Master dataset contains information on symbol changes of the contracts. +

    +

    + This dataset + + does not + + contain market data. For market data, see + + International Futures by TickData + + and + + US Futures by AlgoSeek + + for NKD. +

    +

    + For more information about the International Future Universe dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + -// Historical data -var history = qb.History(symbol, 30, Resolution.Daily); -foreach (var bar in history) -{ - Console.WriteLine($"{bar.EndTime} {bar}"); -} +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + -// Add Crypto Universe Selection -IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay) -{ - return universeDay - .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m) - .OrderByDescending(x => x.VolumeInUsd) - .Take(5) - .Select(x => x.Symbol); -} -var universe = qb.AddUniverse(CryptoUniverse.Coinbase(UniverseSelectionFilter)); +

    Getting Started

    + + +

    + The International Futures Universe dataset provides data for contract filtering/selection: +

    +
    +
    hsi = self.add_future(Futures.Indices.HANG_SENG, Resolution.MINUTE)           # "HSI"
    +hsi.set_filter(0, 90)
    +dax = self.add_future(Futures.Indices.DAX, Resolution.MINUTE)                 # "DAX"
    +dax.set_filter(0, 90)
    +fesx = self.add_future(Futures.Indices.EURO_STOXX_50, Resolution.MINUTE)      # "FESX"
    +fesx.set_filter(0, 90)
    +nkd = self.add_future(Futures.Indices.NIKKEI_225_DOLLAR, Resolution.MINUTE)   # "NKD"
    +nkd.set_filter(0, 90)
    +
    var hsi= AddFuture(Futures.Indices.HangSeng, Resolution.Minute)           // "HSI";
    +hsi.SetFilter(0, 90);
    +var dax = AddFuture(Futures.Indices.Dax, Resolution.Minute)               // "DAX";
    +dax.SetFilter(0, 90);
    +var fesx = AddFuture(Futures.Indices.EuroStoxx50, Resolution.Minute)      // "FESX";
    +fesx.SetFilter(0, 90);
    +var nkd = AddFuture(Futures.Indices.Nikkei225Dollar, Resolution.Minute)   // "NKD";
    +nkd.SetFilter(0, 90);
    +
    + + -// Historical Universe data -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time); -foreach (var universeDay in universeHistory) +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + July 1998 (for details, see + + Supported Assets + + ) +
    + Coverage + + 4 Contracts +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + + Various (for details, see + + Supported Assets + + ) +
    + Market Hours + + + Regular and Extended + +
    + + + +

    Requesting Data

    + + +

    + To add International Future Universe data to your algorithm, call the + + AddFuture + + + add_future + + method. Save a reference to the Future object so you can access the data later in your algorithm. To define which contracts should be in your universe, specify the filter when requesting the Future data. +

    +

    + The + + AddFuture + + + add_future + + method provides a daily stream of Future chain data. To get the most recent daily chain, call the + + FuturesChain + + + futures_chain + + method with the underlying Future Symbol. The + + FuturesChain + + + futures_chain + + method returns data on all the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    class InternationalFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2013, 12, 20) 
    +        self.set_end_date(2014, 2, 20) 
    +        self.set_cash(1000000) 
    +        self.universe_settings.asynchronous = True
    +        self._future = self.add_future(Futures.Indices.HANG_SENG)
    +        # Set our contract filter for this Future chain.
    +        self._future.set_filter(lambda universe: universe.standards_only().front_month())
    +        # Get the entire Futures chain for the current day.
    +        chain = self.futures_chain(self._future.symbol, flatten=True).data_frame
    +
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
     {
    -    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    -    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    +    private Future _future;
    +        
    +    public override void Initialize()
         {
    -        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +        SetStartDate(2013, 12, 20);
    +        SetEndDate(2014, 2, 20);
    +        SetCash(1000000);
    +        UniverseSettings.Asynchronous = true;
    +        var future = AddFuture(Futures.Indices.HangSeng);
    +        // Set our contract filter for this Future chain.
    +        _future.SetFilter((universe) => universe.StandardsOnly().FrontMonth());
    +        // Get the entire Futures chain for the current day.
    +        var chain = FuturesChain(_future.Symbol);
         }
     }
    -
    qb = QuantBook()
    -
    -# Add Cryptocurrency pair
    -symbol = qb.add_crypto("BTCUSDT", market=Market.COINBASE).symbol
    -
    -# Historical data
    -history = qb.history(symbol, 30, Resolution.DAILY)
    -for (symbol, time), row in history.iterrows():
    -    print(f'{time} {symbol} {row.close}')
    -
    -# Add Crypto Universe Selection
    -def universe_selection_filter(universe_day):
    -    selected = sorted([x for x in universe_day
    -        if x.volume_in_usd and x.volume_in_usd > 10000],
    -        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    -    return [x.symbol for x in selected]
    -
    -universe = qb.add_universe(CryptoUniverse.coinbase(universe_selection_filter))
    -
    -# Historical Universe data
    -history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (univere_symbol, time), universe_day in history.items():
    -    print(f'=== {time} ===')
    -    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    -        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    +

    + For more information about creating Future Universes, see + + Futures + + . +

    -

    Data Point Attributes

    +

    Accessing Data

    - The Coinbase Crypto Price dataset provides - - TradeBar - - , - - QuoteBar + For information about accessing International Future Universe data, see + + Futures + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical International Future Universe data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical International Future Universe data in an algorithm, call the + + History<FutureUniverse> - , - - Tick + + history - , and + method with continuous Future - CryptoUniverse + Symbol - objects. + and a lookback period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. +

    +
    +
    # Add the Future and save a reference to it.
    +future = self.add_future(Futures.Indices.HANG_SENG)
    +
    +# DataFrame example where the columns are the FutureUniverse attributes:
    +history_df = self.history(FutureUniverse, future.symbol, 5, flatten=True)
    +
    +# Series example where the values are lists of FutureUniverse objects: 
    +history_series = self.history(FutureUniverse, future.symbol, 5, flatten=False)
    +
    +# FutureUniverse objects example:
    +history = self.history[FutureUniverse](future.symbol, 5)
    +
    // Add the Future and save a reference to it.
    +var future = AddFuture(Futures.Indices.HangSeng);
    +
    +// Get historical data.
    +var history = History<FutureUniverse>(future.Symbol, 5);
    +
    +

    + For more information about historical International Future Universe data in algorithms, see + + Contracts + + .

    - TradeBar Attributes + Historical Data In Research

    + To get historical International Future Universe data in the Research Environment, call the + + History<FutureUniverse> + + + history + + method with continuous Future - TradeBar + Symbol - objects have the following attributes: + and a time period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty.

    -
    +
    +
    # Add the Future and save a reference to it.
    +future = qb.add_future(Futures.Indices.HANG_SENG)
    +
    +# DataFrame example where the columns are the FutureUniverse attributes:
    +history_df = qb.history(FutureUniverse, future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1), flatten=True)
    +
    +# Series example where the values are lists of FutureUniverse objects: 
    +history_series = qb.history(FutureUniverse, future.symbol, 5, flatten=False)
    +
    +# FutureUniverse objects example:
    +history = qb.history[FutureUniverse](future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1))
    +
    // Add the Future and save a reference to it.
    +var future = qb.AddFuture(Futures.Indices.HangSeng);
    +
    +// Get historical data.
    +var history = qb.History<FutureUniverse>(future.Symbol, new DateTime(2025, 1, 1), new DateTime(2025, 4, 1));
    +

    + For more information about historical International Future Universe data in the Research Environment, see + + Daily Prices History + + . +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available Futures: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Ticker + + Future + + Start Date + + Time Zone + + Currency +
    + HSI + + Hang Seng Index Futures + + Jan 2010 + + Asia/Hong Kong + + HKD +
    + DAX + + German Index Futures + + Jan 2010 + + Europe/Berlin + + EUR +
    + FESX + + EURO STOXX 50 Index Futures + + Jul 1998 + + Europe/Berlin + + EUR +
    + NKD + + Nikkei 225 Index Futures + + Jan 2007 + + America/Chicago + + USD +
    + + + +

    Example Applications

    + + +

    + The International Futures Universe dataset enables you to design Futures strategies accurately. Examples include the following strategies: +

    +
      +
    • + Buying the Futures contract with the most open interest to reduce slippage and market impact +
    • +
    • + Trade speculation on an International Index +
    • +
    • + Trading bull calendar spreads to reduce volatility and margin requirements +
    • +

    - QuoteBar Attributes + Classic Algorithm Example

    + The following example algorithm uses the + + ZigZag indicator + + to determine the trend of Hang Seng Index. It then trades the Index with HSI Futures. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class InternationalFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Set the time zone to HKT to make it more comparable with the exchange.
    +        self.set_time_zone(TimeZones.HONG_KONG)
    +        # Set the account currency as HKD to trade HSI Futures.
    +        self.set_account_currency("HKD", 1000000)
    +        # Seed the last price of the contracts for filling.
    +        self.settings.seed_initial_prices = True
    +
    +        # Request HSI Futures to trade. 
    +        # Note that we will trade the contract with the highest open interest for liquidity.
    +        self.hsi_future = self.add_future(
    +            Futures.Indices.HANG_SENG,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
    +            contract_depth_offset=0
    +        )
    +        # Adds contracts that expiry within 90 days. We will trade the farthest contract
    +        self.hsi_future.set_filter(0,90)
    +        # Request the corresponding underlying Index for feeding indicator for trade signal generation.
    +        hsi_index = self.add_index("HSI").symbol
    +
    +        # Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    +        self._zz = self.zz(hsi_index, 0.15, 5, Resolution.DAILY)
    +        # Warm up indicator for immediate readiness to trade.
    +        self.warm_up_indicator(hsi_index, self._zz, Resolution.DAILY)
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    +        if self.is_market_open(self.hsi_future.symbol) and self._zz.is_ready:
    +            pivot = self._zz.pivot_type
    +            # If the last pivot point is a low point, the current trend is increasing after this low point.
    +            if pivot == PivotPointType.LOW:
    +                contracts = sorted([x.symbol for x in slice.future_chains.get(self.hsi_future.symbol)],
    +                    key=lambda x: x.id.date)
    +                self.set_holdings(contracts[-1], 0.2)
    +            # If the last pivot point is a high point, the current trend is decreasing after this high point.
    +            if pivot == PivotPointType.HIGH:
    +                contracts = sorted([x.symbol for x in slice.future_chains.get(self.hsi_future.symbol)],
    +                    key=lambda x: x.id.date)
    +                self.set_holdings(contracts[-1], -0.2)
    +
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    +{
    +    private Future _hsiFuture;
    +    private ZigZag _zz;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        // Set the time zone to HKT to make it more comparable with the exchange.
    +        SetTimeZone(TimeZones.HongKong);
    +        // Set the account currency as HKD to trade HSI Futures.
    +        SetAccountCurrency("HKD", 1000000);
    +
    +        // Seed the last price of the contracts for filling.
    +        Settings.SeedInitialPrices = true;
    +
    +        // Request HSI Futures to trade. 
    +        // Note that we will trade the contract with the highest open interest for liquidity.
    +        _hsiFuture = AddFuture(
    +            Futures.Indices.HangSeng,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.LastTradingDay,
    +            contractDepthOffset: 0
    +        );
    +        // Adds contracts that expiry within 90 days. We will trade the farthest contract
    +        _hsiFuture.SetFilter(0,90);
    +        // Request the corresponding underlying index for feeding indicators for trade signal generation.
    +        var hsiIndex = AddIndex("HSI").Symbol;
    +
    +        // Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    +        _zz = ZZ(hsiIndex, 0.15m, 5, Resolution.Daily);
    +        // Warm up indicator for immediate readiness to trade.
    +        WarmUpIndicator(hsiIndex, _zz, Resolution.Daily);
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    +        if (IsMarketOpen(_hsiFuture.Symbol) && _zz.IsReady)
    +        {
    +            var pivot = _zz.PivotType;
    +            FuturesChain chain;
    +            // If the last pivot point is low, the current trend is increasing after this low point.
    +            if (pivot == PivotPointType.Low && slice.FutureChains.TryGetValue(_hsiFuture.Symbol, out chain))
    +            {
    +                var contract = chain.OrderBy(x => x.Expiry).LastOrDefault()?.Symbol;                    
    +                SetHoldings(contract, 0.2m);
    +            }
    +            // If the last pivot point is high, the current trend decreases after this high point.
    +            if (pivot == PivotPointType.High && slice.FutureChains.TryGetValue(_hsiFuture.Symbol, out chain))
    +            {
    +                var contract = chain.OrderBy(x => x.Expiry).LastOrDefault()?.Symbol;                    
    +                SetHoldings(contract, -0.2m);
    +            }
    +        }
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The International Future Universe dataset provides - QuoteBar + FutureFilterUniverse - objects have the following attributes: + and + + FutureUniverse + + objects.

    -
    -

    - Tick Attributes + FutureFilterUniverse Attributes

    - Tick + FutureFilterUniverse objects have the following attributes:

    -
    +

    - CryptoUniverse Attributes + FutureUniverse Attributes

    - CryptoUniverse + FutureUniverse objects have the following attributes:

    -
    +

     

    - +
    -
    -

    CoinAPI

    +
    +

    QuantConnect

    Kraken Crypto Price Data

    @@ -232179,7 +205667,7 @@

    Introduction

    - The Kraken Crypto Price Data by CoinAPI provides Cryptocurrency price and volume data points. The data covers 1,262 Cryptocurrency pairs, starts in October 2013, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on the Cryptocurrency markets/exchanges supported by QuantConnect. + The Kraken Crypto Price Data provides Cryptocurrency price and volume data points. The data covers 1,262 Cryptocurrency pairs, starts in October 2013, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on the Cryptocurrency markets/exchanges supported by QuantConnect.

    For more information about the Kraken Crypto Price Data dataset, including CLI commands and pricing, see the @@ -232197,10 +205685,18 @@

    About the Provider

    - - CoinAPI + + Kraken + + was founded by Jesse Powell in 2011 with the goal to "accelerate the adoption of cryptocurrency so that you and the rest of the world can achieve financial freedom and inclusion". Kraken provides access to trading Crypto through spot and Futures markets for clients with a minimum deposit of around $0-$150 USD for + + currency + + and + + Crypto deposits - was founded by Artur Pietrzyk in 2016 with the goal of providing real-time and historical cryptocurrency market data, collected from hundreds of exchanges. CoinAPI provides access to Cryptocurrencies for traders, market makers, and developers building third-party applications. + . Kraken also provides staking services, educational content, and a developer grant program.

    @@ -236974,312 +210470,27982 @@

    Example Applications

    - The Kraken Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: + The Kraken Crypto Price dataset enables you to accurately design strategies for Cryptocurrencies. Examples include the following strategies: +

    +
      +
    • + Buy and hold +
    • +
    • + Trading Cryptocurrency volatility and price action +
    • +
    • + Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys and holds Bitcoin through the Kraken exchange: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.universe_settings.asynchronous = True
    +        self.set_cash(100_000)
    +        # Kraken accepts both Cash and Margin account types. Select the
    +        # one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.KRAKEN, AccountType.MARGIN)
    +        # Add BTCUSD data.
    +        self._btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.KRAKEN)
    +        # Historical data
    +        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    +        # Add a Crypto universe that selects Crypto pairs on Kraken.
    +        universe = self.add_universe(CryptoUniverse.kraken(self._select_assets))
    +        # Historical Universe data
    +        universe_history = self.history(universe, 30, Resolution.DAILY)
    +        for (universe_symbol, time), universe_day in universe_history.items():
    +            for universe_item in universe_day:
    +                symbol = universe_item.symbol
    +                price = universe_item.close
    +
    +    def _select_assets(self, universe_day):
    +        # Filter for materially traded Crypto pairs with significant 
    +        # size and dollar volume, assuming higher capital flow in for 
    +        # higher return.
    +        return [universe_item.symbol for universe_item in universe_day
    +                if universe_item.volume >= 100 
    +                and universe_item.volume_in_usd > 10_000_000]
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Speculate-invest all available free cash on BTCUSD, repecting 
    +        # the order quantity restrictions to avoid invalid orders.
    +        if self.portfolio.cash_book['BTC'].amount != 0:
    +            return
    +        # Define a buffer so that we can scale down the order size,
    +        # avoiding trading errors.
    +        buffer = max(
    +            KrakenFeeModel.TAKER_TIER_1_CRYPTO_FEE, 
    +            self.settings.free_portfolio_value_percentage
    +        )
    +        quantity = (
    +            self.portfolio.cash_book['USD'].amount
    +            / self._btc.ask_price
    +            * (1-buffer)
    +        )
    +        # Check if the quantity exceeds the minimum order size. On 
    +        # Kraken, the minimum order size is measured in the base
    +        # currency (BTC in this case).
    +        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    +            return
    +        self.market_order(self._btc, quantity)
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private Crypto _btc;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        UniverseSettings.Asynchronous = true;
    +        SetCash(100000);
    +        // Kraken accepts both Cash and Margin account types. Select the
    +        // one you need for the best reality modeling.
    +        SetBrokerageModel(BrokerageName.Kraken, AccountType.Margin);
    +        // Add BTCUSD data.
    +        _btc = AddCrypto("BTCUSD", Resolution.Minute, Market.Kraken);   
    +        // Historical data
    +        var history = History(_btc.Symbol, 30, Resolution.Daily);
    +        // Add a Crypto universe that selects trading pairs on Kraken.
    +        var universe = AddUniverse(CryptoUniverse.Kraken(SelectAssets));
    +        // Historical Universe data
    +        var universeHistory = History(universe, 30, Resolution.Daily);
    +        foreach (var universeDay in universeHistory)
    +        {
    +            foreach (CryptoUniverse universeItem in universeDay)
    +            {
    +                var symbol = universeItem.Symbol;
    +                var price = universeItem.Close;
    +            }
    +        }
    +    }
    +
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Filter for materially traded Crypto pairs with significant 
    +        // size and dollar volume, assuming higher capital flow in for 
    +        // higher return.
    +        return from universeItem in universeDay
    +                where universeItem.Volume >= 100m 
    +                && universeItem.VolumeInUsd > 10000000m
    +                select universeItem.Symbol;
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Speculate-invest all available free cash on BTCUSD, repecting 
    +        // the order quantity restrictions to avoid invalid orders.
    +        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        {
    +            return;
    +        }
    +        // Define a buffer so that we can scale down the order size,
    +        // avoiding trading errors.
    +        var buffer = Math.Max(KrakenFeeModel.TakerTier1CryptoFee, Settings.FreePortfolioValuePercentage);
    +        var quantity = Portfolio.CashBook["USD"].Amount / _btc.AskPrice * (1-buffer);
    +        // Check if the quantity exceeds the minimum order size. On 
    +        // Kraken, the minimum order size is measured in the base 
    +        // currency (BTC in this case).
    +        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +        {
    +            return;
    +        }
    +        MarketOrder(_btc, quantity);
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of Crypto pairs on the Kraken exchange and then forms a equal-weighted portfolio of all the pairs in the universe: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class CoinAPIDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        self.settings.free_portfolio_value_percentage = 0.05
    +
    +        # Kraken accepts both Cash and Margin type account, select the one you need for the best reality modeling.
    +        self.set_brokerage_model(BrokerageName.KRAKEN, AccountType.MARGIN)
    +
    +        # Warm up the security with the last known price to avoid conversion error
    +        self.settings.seed_initial_prices = True
    +        
    +        # Get the pairs on Kraken that have USD as the quote currency.
    +        self._market_pairs = [
    +            x.key.symbol 
    +            for x in self.symbol_properties_database.get_symbol_properties_list(Market.KRAKEN) 
    +            if x.value.quote_currency == self.account_currency
    +        ]
    +        # Add Crypto Universe Selection that select crypto pairs in Kraken exchange
    +        self.add_universe(CryptoUniverse.kraken(self.universe_selection_filter))
    +        
    +        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(hours=4), 0.025, None))
    +        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    +    def universe_selection_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    +        # Select pairs where the quote currency is USD.
    +        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    +        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    +        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    +        return [c.symbol for c in pairs]
    +
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = self.history(security.symbol, 30, Resolution.DAILY)
    +            self.debug(f"We got {len(history)} items from our history request")
    +
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +{
    +    private List<string> _marketPairs;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        Settings.FreePortfolioValuePercentage = 0.05m;
    +
    +        // Kraken accepts both Cash and Margin type account, select the one you need for the best reality modeling.            
    +        SetBrokerageModel(BrokerageName.Kraken, AccountType.Margin);
    +
    +        // Warm up the security with the last known price to avoid conversion error
    +        Settings.SeedInitialPrices = true;
    +        
    +        // Get the pairs on Kraken that have USD as the quote currency.
    +        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Kraken)
    +            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    +            .Select(x => x.Key.Symbol)
    +            .ToList();
    +        // Add Crypto Universe Selection that select crypto pairs in Kraken exchange
    +        AddUniverse(CryptoUniverse.Kraken(UniverseSelectionFilter));
    +    
    +        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(4), 0.025, null) );
    +        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +    }
    +
    +    private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +    {
    +        // Select pairs where the quote currency is USD.
    +        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    +            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    +            .OrderBy(c => c.VolumeInUsd)
    +            .TakeLast(3)
    +            .Select(c => c.Symbol);
    +    }
    +
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach(var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = History(security.Symbol, 30, Resolution.Daily);
    +            Debug($"We got {history.Count()} items from our history request");
    +        }
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example lists crypto-currency pairs with the greatest dollar volume in the Kraken exchange: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add Cryptocurrency pair
    +var symbol = qb.AddCrypto("BTCUSDT", market:Market.Kraken).Symbol;
    +
    +// Historical data
    +var history = qb.History(symbol, 30, Resolution.Daily);
    +foreach (var bar in history)
    +{
    +    Console.WriteLine($"{bar.EndTime} {bar}");
    +}
    +
    +// Add Crypto Universe Selection
    +IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    +{
    +    return universeDay
    +        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    +        .OrderByDescending(x => x.VolumeInUsd)
    +        .Take(5)
    +        .Select(x => x.Symbol);
    +}
    +var universe = qb.AddUniverse(CryptoUniverse.Kraken(UniverseSelectionFilter));
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var universeDay in universeHistory)
    +{
    +    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    +    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    +    {
    +        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add Cryptocurrency pair
    +symbol = qb.add_crypto("BTCUSDT", market=Market.KRAKEN).symbol
    +
    +# Historical data
    +history = qb.history(symbol, 30, Resolution.DAILY)
    +for (symbol, time), row in history.iterrows():
    +    print(f'{time} {symbol} {row.close}')
    +
    +# Add Crypto Universe Selection
    +def universe_selection_filter(universe_day):
    +    selected = sorted([x for x in universe_day
    +        if x.volume_in_usd and x.volume_in_usd > 10000],
    +        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    +    return [x.symbol for x in selected]
    +
    +universe = qb.add_universe(CryptoUniverse.kraken(universe_selection_filter))
    +
    +# Historical Universe data
    +history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (univere_symbol, time), universe_day in history.items():
    +    print(f'=== {time} ===')
    +    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    +        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The Kraken Crypto Price dataset provides + + TradeBar + + , + + QuoteBar + + , + + Tick + + , and + + CryptoUniverse + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    +

    + CryptoUniverse Attributes +

    +

    + + CryptoUniverse + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US ETF Constituents

    +
    +
    +

    Introduction

    + + +

    + The US ETF Constituents dataset by QuantConnect tracks the constituents and weighting of US Equities in 2,650 ETF listings. The data starts in June 2009 and is delivered on a daily basis (monthly basis before January 2015). This dataset is created by tracking the host ETF websites and can be delayed by up to 1 week. +

    +

    + This dataset depends on the + + US Equity Security Master + + dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. +

    +

    + For more information about the US ETF Constituents dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 160,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US ETF Constituents dataset: +

    +
    +
    def initialize(self) -> None:
    +    self.universe_settings.asynchronous = True
    +    # Use the following method for a Classic Algorithm
    +    self._universe = self.add_universe(self.universe.etf("SPY", Market.USA, self.universe_settings, self.etf_constituents_filter))
    +
    +    symbol = Symbol.create("SPY", SecurityType.EQUITY, Market.USA)
    +    # Use the following method for a Framework Algorithm
    +    self.add_universe_selection(ETFConstituentsUniverseSelectionModel(symbol, self.universe_settings, self.etf_constituents_filter))
    +
    +    def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    +        # Add all Symbols of the ETFConstituentUniverse
    +       return [x.symbol for x in constituents]
    +
    public override void Initialize()
    +{
    +    UniverseSettings.Asynchronous = true;
    +    // Use the following method for a Classic Algorithm
    +    _universe = AddUniverse(Universe.ETF("SPY", Market.USA, UniverseSettings, ETFConstituentsFilter));
    +
    +    var symbol = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
    +    // Use the following method for a Framework Algorithm
    +    AddUniverseSelection(new ETFConstituentsUniverseSelectionModel(symbol, UniverseSettings, ETFConstituentsFilter));
    +}
    +private IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable <ETFConstituentUniverse> constituents)
    +{
    +    // Add all Symbols of the ETFConstituentUniverse
    +    return constituents.Select(x => x.Symbol);
    +}
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + June 2009 +
    + Asset Coverage + + 2,650 US ETF Listings +
    + Data Density + + Dense +
    + Resolution + + Daily (Monthly before Jan 2015) +
    + Timezone + + New York +
    + + + +

    Requesting Data

    + + +

    + To add US ETF Constituents data to your algorithm, call the + + AddUniverse + + + add_universe + + and + + Universe.ETF + + + universe.etf + + methods. To select which constituents occupy the universe, provide the ETF + + Symbol + + and a selection function. +

    +
    +
    class ETFConstituentUniverseAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2018, 1, 1)
    +        self.set_end_date(2020, 8, 25)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        self._universe = self.add_universe(self.universe.etf("SPY", self.universe_settings, self.etf_constituents_filter))
    +
    public class ETFConstituentUniverseAlgorithm : QCAlgorithm
    +{
    +    private Universe _universe;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2018, 1, 1);
    +        SetEndDate(2020, 8, 25);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        _universe = AddUniverse(Universe.ETF("SPY", UniverseSettings, ETFConstituentsFilter));
    +    }
    +}
    +
    +
    +

    + For more information about universe settings, see + + Settings + + . +

    + + + +

    Accessing Data

    + + +

    + To access the US ETF Constituent data, use the + + ETFConstituentUniverse + + objects in your selection function. The data is available in daily resolution. The + + Symbol + + objects you return from your selection function defines the universe constituents. +

    +
    +
    def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    +    for c in constituents:
    +        self.debug(f'{c.end_time} :: {c.last_update} :: {c.weight} :: {c.shares_held} :: {c.market_value}')
    +    return [x.symbol for x in constituents]
    +
    +public IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentUniverse> constituents)
    +{
    +    foreach (var c in constituents)
    +    {
    +        Debug($"{c.EndTime} :: {c.LastUpdate} :: {c.Weight} :: {c.SharesHeld} :: {c.MarketValue}");
    +    }
    +
    +    return constituents.Select(c => c.Symbol);
    +}
    +
    +
    + + + +

    Historical Data

    + + +

    + You can get historical universe data in an algorithm and in the Research Environment. +

    +

    + Historical Universe Data in Algorithms +

    +

    + To get historical universe data in an algorithm, call the + + History + + + history + + method with the + + Universe + + object and the lookback period. If there is no data in the period you request, the history result is empty. +

    +
    +
    var history = History(_universe, 30, Resolution.Daily);
    +foreach (var constituents in history)
    +{
    +    foreach (ETFConstituentUniverse constituent in constituents)
    +    {
    +        Log($"{constituent.Symbol} weight at {constituent.EndTime}: {constituent.Weight}");
    +    }
    +}
    +
    # DataFrame example where the columns are the ETFConstituentUniverse attributes: 
    +df_history = self.history(self.universe, 30, Resolution.DAILY, flatten=True)
    +
    +# Series example where the values are lists of ETFConstituentUniverse objects: 
    +series_history = self.history(self.universe, 30, Resolution.DAILY)
    +for (universe_symbol, time), constituents in series_history.items():
    +    for constituent in constituents:
    +        self.log(f'{constituent.symbol} weight at {constituent.end_time}: {constituent.weight}')
    +
    +

    + Historical Universe Data in Research +

    +

    + To get historical universe data in research, call the + + UniverseHistory + + + universe_history + + method with the + + Universe + + object and the lookback period. The + + UniverseHistory + + + universe_history + + returns the filtered universe. If there is no data in the period you request, the history result is empty. +

    +
    +
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var constituents in universeHistory )
    +{
    +    foreach (ETFConstituentUniverse constituent in constituents)
    +    {
    +        Console.WriteLine($"{constituent.Symbol} weight at {constituent.EndTime}: {constituent.Weight}");
    +    }
    +}
    +
    # DataFrame example where the columns are the ETFConstituentUniverse attributes: 
    +df_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    +
    +# Series example where the values are lists of ETFConstituentUniverse objects: 
    +series_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (universe_symbol, time), constituents in series_history.items():
    +    for constituent in constituents:
    +       print(f"{constituent.symbol} weight at {constituent.end_time}: {constituent.weight}")
    +
    +

    + You can call the + + History + + + history + + method in Research. +

    + + + +

    Supported ETFs

    + + +

    + The following table shows the available ETFs: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Example Applications

    + + +

    + The ETF Constituents dataset provides an excellent source of tradable universes for strategies without selection bias. When you use an ETF universe, the original ETF can serve as an excellent benchmark for your strategy performance. Other use cases include the following: +

    +
      +
    • + Creating an index-tracking algorithm for customized passive portfolio management +
    • +
    • + Performing statistical arbitrage with the base ETF +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of the 10 largest US Equities in the SPY ETF. Each day, the algorithm forms a dollar-neutral and market-neutral portfolio by buying the 10 ETF constituents and shorting the SPY ETF. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class ETFConstituentUniverseAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        # Add the SPY to trade.
    +        self._spy = self.add_equity("SPY").symbol
    +        # Add an ETF constituents universe that selects the large caps 
    +        # in SPY. Save the universe object so you can get history
    +        # for the universe.
    +        universe = self.add_universe(
    +            self.universe.etf(
    +                self._spy, 
    +                universe_filter_func=self._select_assets
    +            )
    +        )
    +        # Get historical universe data.
    +        history = self.history(universe, 30, Resolution.DAILY, flatten=True)
    +        # Show an example of wrangling the historical data.
    +        etf_weights = history.weight.unstack(1)  
    +        # Create a dictionary to store the ETF weights each day.
    +        self._weight_by_symbol = {}
    +        # Add a Scheduled Event to rebalance the portfolio each day.
    +        self.schedule.on(
    +            self.date_rules.every_day(self._spy),
    +            self.time_rules.after_market_open(self._spy, 1),
    +            self._rebalance
    +        )
    +
    +    def _select_assets(
    +            self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    +        # Select the 10 largest stocks in the SPY.
    +        selected = sorted(
    +            [c for c in constituents if c.weight], 
    +            key=lambda c: c.weight
    +        )[-10:]
    +        # Save the weights for position sizing.
    +        self._weight_by_symbol = {c.symbol: c.weight for c in selected}
    +        # Return the selected assets.
    +        return list(self._weight_by_symbol.keys())
    +
    +    def _rebalance(self) -> None:
    +        # Create a long-short portfolio to earn the excess return of the 
    +        # top 10 weighted stocks from SPY.
    +        spy_weight = sum(self._weight_by_symbol.values())
    +        targets = [PortfolioTarget(self._spy, -0.5)]
    +        for symbol, weight in self._weight_by_symbol.items():
    +            targets.append(PortfolioTarget(symbol, 0.5*weight/spy_weight))
    +        # Liquidate the stocks that aren't in top 10.
    +        self.set_holdings(targets, True)
    +
    +
    public class ETFConstituentUniverseAlgorithm : QCAlgorithm
    +{ 
    +    private Symbol _spy;
    +    // Create a dictionary to store the ETF weights each day.
    +    private Dictionary<Symbol, decimal> _weightBySymbol = new();
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        // Add the SPY to trade.
    +        _spy = AddEquity("SPY").Symbol;
    +        // Add an ETF constituents universe that selects the large caps 
    +        // in SPY. Save the universe object so you can get history
    +        // for the universe.
    +        var universe = AddUniverse(Universe.ETF(_spy, universeFilterFunc: SelectAssets));
    +        // Get historical universe data.
    +        var history = History(universe, 30, Resolution.Daily);
    +        // Show an example of iterating through the historical data.
    +        foreach (var constituents in history)
    +        {
    +            var t = constituents.EndTime;
    +            foreach (ETFConstituentUniverse constituent in constituents)
    +            {
    +                var symbol = constituent.Symbol;
    +                var weight = constituent.Weight;
    +            }
    +        }
    +        // Add a Scheduled Event to rebalance the portfolio each day.
    +        Schedule.On(DateRules.EveryDay(_spy), TimeRules.AfterMarketOpen(_spy, 1), Rebalance);
    +    }
    +    
    +    private IEnumerable<Symbol> SelectAssets(IEnumerable<ETFConstituentUniverse> constituents)
    +    {
    +        // Select the 10 largest stocks in the SPY. 
    +        _weightBySymbol = constituents.OrderByDescending(c => c.Weight).Take(10)
    +            // Save the weights for position sizing.
    +            .ToDictionary(c => c.Symbol, c => c.Weight ?? 0m);
    +        // Return the selected assets.
    +        return _weightBySymbol.Keys;
    +    }
    +    
    +    private void Rebalance()
    +    {
    +        // Create a long-short portfolio to earn the excess return of the 
    +        // top 10 weighted stocks from SPY.
    +        var spyWeight = _weightBySymbol.Values.Sum();
    +        var targets = new List<PortfolioTarget>() { new PortfolioTarget(_spy, -0.5m) };
    +        foreach (var kvp in _weightBySymbol)
    +        {
    +            targets.Add(new PortfolioTarget(kvp.Key, 0.5m * kvp.Value / spyWeight));
    +        }
    +        // Liquidate the stocks that aren't in top 10.
    +        SetHoldings(targets, true);
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of the 10 largest US Equities in the SPY ETF. Each day, the algorithm forms a dollar-neutral and market-neutral portfolio by buying the 10 ETF constituents and shorting the SPY ETF. +

    +
    +
    class ETFConstituentUniverseFrameworkAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = False
    +        self.universe_settings.resolution = Resolution.MINUTE
    +        self.weight_by_symbol = {}
    +        
    +        # Add universe selection on SPY's constituents to select only from large cap stocks
    +        # Save the universe to access its members for historical data call
    +        spy = self.add_equity("SPY").symbol
    +        self.add_universe_selection(ETFConstituentsUniverseSelectionModel(spy, self.universe_settings, self.etf_constituents_filter))
    +
    +        # Add alpha model that set normalized weight as investment insight
    +        self.add_alpha(ETFConstituentsAlphaModel(self, spy))
    +
    +        # Set up portfolio construction model that invest by the insight weights
    +        pcm = InsightWeightingPortfolioConstructionModel()
    +        # Avoid excessive rebalance on insight changes
    +        pcm.rebalance_on_insight_changes = False
    +        self.set_portfolio_construction(pcm)
    +
    +        self.add_risk_management(NullRiskManagementModel())
    +
    +        self.set_execution(ImmediateExecutionModel())
    +
    +    def etf_constituents_filter(self, constituents: List[ETFConstituentUniverse]) -> List[Symbol]:
    +        # The top 10 weighted securities are considered better active selections
    +        # Save the weights for position sizing
    +        selected = sorted([c for c in constituents if c.weight],
    +            key=lambda c: c.weight, reverse=True)[:10]
    +        self.weight_by_symbol = {c.symbol: c.weight for c in selected}
    +
    +        return list(self.weight_by_symbol.keys())
    +
    +class ETFConstituentsAlphaModel(AlphaModel):
    +
    +    def __init__(self, algorithm: QCAlgorithm, etf: Symbol) -> None:
    +        self.algorithm = algorithm
    +        self.etf = etf
    +        self.day = -1
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        # Rebalance daily since selection is on daily basis
    +        if self.day == algorithm.time.day:
    +            return []
    +
    +        self.day = algorithm.time.day
    +
    +        insights = []
    +
    +        # Create a long-short portfolio to earn excess return of the top 10 weighted stocks from SPY
    +        etf_weight = sum(self.algorithm.weight_by_symbol.values())
    +        if etf_weight> 0:
    +            # Invest half the portfolio by normalized weights of the top 10 constituents
    +            for symbol, weight in self.algorithm.weight_by_symbol.items():
    +                if algorithm.securities.contains_key(symbol):
    +                    insights.append(Insight.price(symbol, Expiry.END_OF_DAY, InsightDirection.UP, weight=0.5*weight/etf_weight))
    +            
    +            # Short the other half with SPY, looking to profit from the active selection
    +            insights.append(Insight.price(self.etf, Expiry.END_OF_DAY, InsightDirection.DOWN, weight=0.5))
    +
    +        return insights
    +
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        # Liquidate the ones not in top 10 weights
    +        symbols = [x.symbol for x in changes.removed_securities if x.invested]
    +        algorithm.liquidate(symbols, tag='Removed From Universe')
    +
    public class ETFConstituentUniverseFrameworkAlgorithm : QCAlgorithm
    +{ 
    +    public Dictionary<Symbol, decimal> WeightBySymbol = [];
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = false;
    +        UniverseSettings.Resolution = Resolution.Minute;
    +
    +        // Add universe selection on SPY's constituents to select only from large cap stocks
    +        // Save the universe to access its members for historical data call
    +        var spy = AddEquity("SPY").Symbol;
    +        AddUniverseSelection(new ETFConstituentsUniverseSelectionModel(spy, UniverseSettings, ETFConstituentsFilter));
    +        
    +        // Add alpha model that set normalized weight as investment insight
    +        AddAlpha(new ETFConstituentsAlphaModel(this, spy));
    +
    +        // Set up portfolio construction model that invest by the insight weights
    +        SetPortfolioConstruction(new InsightWeightingPortfolioConstructionModel
    +        {
    +            // Avoid excessive rebalance on insight changes
    +            RebalanceOnInsightChanges = false
    +        });
    +        
    +        AddRiskManagement(new NullRiskManagementModel());
    +        
    +        SetExecution(new ImmediateExecutionModel());
    +    }
    +    
    +    private IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentUniverse> constituents)
    +    {
    +        // The top 10 weighted securities are considered better active selections
    +        // Save the weights for position sizing
    +        WeightBySymbol = constituents.Where(c=> c.Weight.HasValue).OrderByDescending(c => c.Weight).Take(10)
    +            .ToDictionary(c => c.Symbol, c => c.Weight.Value);
    +
    +        return WeightBySymbol.Keys;
    +    }
    +}
    +
    +public class ETFConstituentsAlphaModel : AlphaModel
    +{
    +    private int _day = -1;
    +    private Symbol _etf;
    +    private ETFConstituentUniverseFrameworkAlgorithm _algorithm;
    +    
    +    public ETFConstituentsAlphaModel(ETFConstituentUniverseFrameworkAlgorithm algorithm, Symbol etf)
    +    {
    +        _etf = etf;
    +        _algorithm = algorithm;
    +    }
    +    
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        // Rebalance daily since selection is on daily basis
    +        if (_day == algorithm.Time.Day)
    +        {
    +            return [];
    +        }
    +        
    +        _day = algorithm.Time.Day;
    +        
    +        var insights = new List<Insight>();
    +        
    +        // Create a long-short portfolio to earn excess return of the top 10 weighted stocks from SPY
    +        var etfWeight = (double)_algorithm.WeightBySymbol.Values.Sum();
    +        if (etfWeight > 0)
    +        {
    +            // Invest half the portfolio by normalized weights of the top 10 constituents
    +            foreach(var kvp in _algorithm.WeightBySymbol)
    +            {
    +                insights.Add(Insight.Price(kvp.Key, Expiry.EndOfDay, InsightDirection.Up, weight: (double)kvp.Value/etfWeight * 0.5));
    +            }
    +
    +            // Short the other half with SPY, looking to profit from the active selection
    +            insights.Add(Insight.Price(_etf, Expiry.EndOfDay, InsightDirection.Down, weight: 0.5));
    +        }
    +        
    +        return insights;
    +    }
    +    
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {
    +        // Liquidate the ones not in top 10 weights
    +        var symbols = changes.RemovedSecurities.Where(x => x.Invested).Select(x => x.Symbol);
    +        algorithm.Liquidate(symbols, tag: "Removed From Universe");
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example lists ETF constituents with the greatest weight in the SPY: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add the ETF
    +var symbol = qb.AddEquity("SPY").Symbol;
    +
    +// Add ETF Universe Selection
    +IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentUniverse> constituents)
    +{
    +    // Take the top 10 weighted constituents
    +    return constituents
    +        .OrderByDescending(c => c.Weight)
    +        .Take(10)
    +        .Select(c => c.Symbol);
    +}
    +
    +var universe = qb.AddUniverse(qb.Universe.ETF(spy, qb.UniverseSettings, ETFConstituentsFilter)); 
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var constituents in universeHistory )
    +{
    +    foreach (ETFConstituentUniverse constituent in constituents)
    +    {
    +        Console.WriteLine($"{constituent.Symbol} weight at {constituent.EndTime}: {constituent.Weight}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add the ETF
    +qb.spy = qb.add_equity("SPY").symbol
    +
    +# Add ETF Universe Selection
    +def etf_constituents_filter(constituents):
    +    # Take the top 10 weighted constituents
    +    selected = sorted([c for c in constituents if c.weight],
    +        key=lambda c: c.weight, reverse=True)[:10]
    +    return [c.symbol for c in selected]
    +
    +universe = qb.add_universe(qb.universe.etf(qb.spy, qb.universe_settings, etf_constituents_filter))
    +
    +# Historical Universe data
    +universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (universe_symbol, time), constituents in universe_history.items():
    +    for constituent in constituents:
    +        print(f"{constituent.symbol} weight at {constituent.end_time}: {constituent.weight}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The ETF Constituents dataset provides + + ETFConstituentUniverse + + objects, which have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Equities Short Availability

    +
    +
    +

    Introduction

    + + +

    + The US Equity Short Availability dataset provides the available shares for open short positions and their borrowing cost in the US Equity market. The data covers 10,500 US Equities, starts in January 2018, and is delivered on a daily frequency. This dataset is created using information from the exchanges. +

    +

    + This dataset depends on the + + US Equity Security Master + + dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. +

    +

    + For more information about the US Equities Short Availability dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippets demonstrate how to request data from the US Equities Short Availability dataset. +

    +

    + Interactive Brokers Data +

    +
    +
    security.set_shortable_provider(InteractiveBrokersShortableProvider())
    +
    security.SetShortableProvider(new InteractiveBrokersShortableProvider());
    +
    +

    + Axos Clearing Data +

    +
    +
    security.set_shortable_provider(LocalDiskShortableProvider("axos"))
    +
    security.SetShortableProvider(new LocalDiskShortableProvider("axos"));
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2018 +
    + Asset Coverage + + 10,500 US Equities +
    + Data Density + + Sparse +
    + Resolution + + Daily +
    + Timezone + + New York +
    + + + +

    Requesting Data

    + + +

    + To add US Equities Short Availability data to your algorithm, set the + + shortable provider + + of each US Equity in your algorithm. +

    +
    +
    class ShortAvailabilityDataAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2019, 1, 1)
    +        security = self.add_equity("AAPL")
    +        # Set shortable provider as IB
    +        security.set_shortable_provider(InteractiveBrokersShortableProvider())
    +        self._symbol = security.symbol
    +
    public class ShortAvailabilityDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2019, 1, 1);
    +        var security = AddEquity("AAPL");
    +        // Set shortable provider as IB
    +        security.SetShortableProvider(new InteractiveBrokersShortableProvider());
    +        _symbol = security.Symbol;
    +    }
    +}
    +
    + + + +

    Accessing Data

    + + +

    + To check how many shares are available for a security to short, call the + + ShortableQuantity + + + shortable_quantity + + method of the + + ShortableProvider + + + shortable_provider + +

    +
    +
    var shortableProvider = Securities[_symbol].ShortableProvider;
    +// Get the shortable quantity of the selected symbol at the selected time
    +var shortableQuantity = shortableProvider.ShortableQuantity(_symbol, Time);
    +
    +// Check if there are a certain quantity of shares available
    +var quantity = 100;
    +var isShortableQuantity = Shortable(_symbol, quantity);
    +
    shortable_provider = self.securities[self._symbol].shortable_provider
    +# Get the shortable quantity of the selected symbol at the selected time
    +shortable_quantity = shortable_provider.shortable_quantity(self._symbol, self.time)
    +
    +# Check if there are a certain quantity of shares available
    +quantity = 100;
    +is_shortable_quantity = self.shortable(self._symbol, quantity)
    +
    +

    + To check borrowing cost, call the + + FeeRate + + + fee_rate + + or + + RebateRate + + + rebate_rate + + method of the + + ShortableProvider + + + shortable_provider + +

    +
    +
    var feeRate = shortableProvider.FeeRate(_symbol, Time);
    +var rebateRate = shortableProvider.RebateRate(_symbol, Time);
    +
    fee_rate = shortable_provider.fee_rate(self._symbol, self.time);
    +rebate_rate = shortable_provider.rebate_rate(self._symbol, self.time);
    +
    + To get valid borrowing rates, use the + + InteractiveBrokersShortableProvider + + + . + + + + +

    Example Applications

    + + +

    + The US Equities Short Availability dataset enables you to accurately design strategies harnessing information about short availability. Examples include the following use cases: +

    +
      +
    • + Avoiding short orders that the brokerage will reject +
    • +
    • + Selecting securities based on how many shares are available to short +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm shorts GameStop every day there are shares available to short. If the algorithm receives a margin call, it liquidates the position and start again on the next day. +

    +
    +
    from AlgorithmImports import *
    +
    +class ShortAvailabilityDataAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1000)
    +        # Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    +        self.settings.seed_initial_prices = True
    +        self.add_security_initializer(self._custom_security_initializer)
    +
    +        self.equity = self.add_equity("GME")
    +
    +        # Set up daily rebalance scheduled event, since shortable quantity is updated daily
    +        self.schedule.on(
    +            self.date_rules.every_day(self.equity.symbol),
    +            self.time_rules.after_market_open(self.equity.symbol, 10),
    +            self.rebalance)
    +
    +    def rebalance(self) -> None:
    +        symbol = self.equity.symbol
    +        
    +        # You can obtain the shortable quantity to decide the submission of a short order
    +        shortable_quantity = self.equity.shortable_provider.shortable_quantity(symbol, self.time)
    +        if not shortable_quantity:
    +            shortable_quantity = 0
    +        # Fee and rebate rate is also available, such that you can calculate the expected return and decide if the margin is worthwhile
    +        self.plot('Total Shortable Quantity', symbol, shortable_quantity)
    +        self.plot('Borrowing Cost', "Fee Rate", self.equity.shortable_provider.fee_rate(symbol, self.time))
    +        self.plot('Borrowing Cost', "Rebate Rate", self.equity.shortable_provider.rebate_rate(symbol, self.time))
    +
    +        # Test whether we can short the desired quantity
    +        quantity = self.calculate_order_quantity(symbol, -1)
    +        if quantity and self.shortable(symbol, quantity):
    +            self.market_order(symbol, quantity)
    +
    +    def on_margin_call_warning(self) -> None:
    +        self.liquidate()
    +
    +    def _custom_security_initializer(self, security: Security) -> None:
    +        # Set the shortable provider as your broker for accurate short reality modeling
    +        security.set_shortable_provider(InteractiveBrokersShortableProvider())
    +
    public class ShortAvailabilityDataAlgorithm : QCAlgorithm
    +{
    +    private Equity _equity;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000);
    +        // Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    +        Settings.SeedInitialPrices = true;
    +        AddSecurityInitializer(security =>
    +        {
    +            // Set the shortable provider as your broker for accurate short reality modeling
    +            security.SetShortableProvider(new InteractiveBrokersShortableProvider());    
    +        });
    +        
    +        _equity = AddEquity("GME");
    +        
    +        // Set up daily rebalance scheduled event, since shortable quantity is updated daily
    +        Schedule.On(
    +            DateRules.EveryDay(_equity.Symbol),
    +            TimeRules.AfterMarketOpen(_equity.Symbol, 10),
    +            Rebalance);
    +    }
    +    
    +    public void Rebalance()
    +    {
    +        var symbol = _equity.Symbol;
    +
    +        // You can obtain the shortable quantity to decide the submission of a short order
    +        // Fee and rebate rate is also available, such that you can calculate the expected return and decide if the margin is worthwhile
    +        Plot("Total Shortable Quantity", symbol, _equity.ShortableProvider.ShortableQuantity(symbol, Time) ?? 0m);
    +        Plot("Borrowing Cost", "Fee Rate", _equity.ShortableProvider.FeeRate(symbol, Time));
    +        Plot("Borrowing Cost", "Rebate Rate", _equity.ShortableProvider.RebateRate(symbol, Time));
    +
    +        // Test whether we can short the desired quantity
    +        var quantity = CalculateOrderQuantity(symbol, -1m);
    +        if (quantity != 0 && Shortable(symbol, quantity))
    +        {
    +            MarketOrder(symbol, quantity);
    +        }
    +    }
    +
    +    public override void OnMarginCallWarning()
    +    {
    +        Liquidate();
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm shorts GameStop every day there are shares available to short. If the algorithm receives a margin call, it liquidates the position and start again on the next day. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class ShortAvailabilityDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1000)
    +        # Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    +        self.settings.seed_initial_prices = True
    +        self.add_security_initializer(self._custom_security_initializer)
    +
    +        self.set_universe_selection(ManualUniverseSelectionModel(
    +            [Symbol.create("GME", SecurityType.EQUITY, Market.USA)]))           
    +
    +        # Emit down-direction insights to short all securities in the universe            
    +        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.DOWN, timedelta(1)))
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +        self.set_execution(ShortableExecutionModel())
    +
    +    # On Margin Call, emit flat-direction insights to liquidate the positions
    +    def on_margin_call_warning(self) -> None:
    +        self.emit_insights([Insight.price(kvp.Key, timedelta(1), InsightDirection.FLAT)
    +            for kvp in self.securities if kvp.Value.invested])
    +
    +    def _custom_security_initializer(self, security: Security) -> None:
    +        # Set the shortable provider as IB
    +        security.set_shortable_provider(InteractiveBrokersShortableProvider())
    +
    +class ShortableExecutionModel(ExecutionModel):
    +    def __init__(self) -> None:
    +        self.targets_collection = PortfolioTargetCollection()
    +
    +    def execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None:
    +        '''Immediately submits orders for the specified portfolio targets.
    +        Args:
    +            algorithm: The algorithm instance
    +            targets: The portfolio targets to be ordered'''
    +
    +        # for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    +        self.targets_collection.add_range(targets)
    +        if self.targets_collection.count > 0:
    +            for target in self.targets_collection.order_by_margin_impact(algorithm):
    +                # calculate remaining quantity to be ordered
    +                quantity = OrderSizing.get_unordered_quantity(algorithm, target)
    +                # If the quantity is negative, ensure that the security is shortable
    +                if quantity > 0 or algorithm.shortable(target.symbol, quantity):
    +                    algorithm.market_order(target.symbol, quantity)
    +
    +            self.targets_collection.clear_fulfilled(algorithm)
    +
    public class ShortAvailabilityDataAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000);
    +        // Seed the security price as the last known price, such that the price data is immediately available at initial rebalance
    +        Settings.SeedInitialPrices = true;
    +        AddSecurityInitializer(security =>
    +        {
    +            // Set the shortable provider as your broker for accurate short reality modeling
    +            security.SetShortableProvider(new InteractiveBrokersShortableProvider());    
    +        });
    +
    +        SetUniverseSelection(new ManualUniverseSelectionModel(
    +            QuantConnect.Symbol.Create("GME", SecurityType.Equity, Market.USA)));            
    +        
    +        // Emit down-direction insights to short all securities in the universe            
    +        SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Down, TimeSpan.FromDays(1)));
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +        SetExecution(new ShortableExecutionModel());
    +    }
    +
    +    // On Margin Call, emit flat-direction insights to liquidate the positions
    +    public override void OnMarginCallWarning()
    +    {
    +        EmitInsights(Securities
    +            .Where(kvp => kvp.Value.Invested)
    +            .Select(kvp => Insight.Price(kvp.Key, TimeSpan.FromDays(1), InsightDirection.Flat))
    +            .ToArray());
    +    }
    +
    +    public class ShortableExecutionModel : ImmediateExecutionModel
    +    {
    +        private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
    +
    +        public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
    +        {
    +            _targetsCollection.AddRange(targets);
    +            // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    +            if (_targetsCollection.Count > 0)
    +            {
    +                foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
    +                {
    +                    // calculate remaining quantity to be ordered
    +                    var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);
    +                    // If the quantity is negative, ensure that the security is shortable
    +                    if (quantity > 0 || algorithm.Shortable(target.Symbol, quantity))
    +                    {
    +                        algorithm.MarketOrder(target.Symbol, quantity);
    +                    }
    +                }
    +
    +                _targetsCollection.ClearFulfilled(algorithm);
    +            }
    +        }
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Equities Short Availability data is a + + Symbol + + /decimal pair for + + ShortQuantity + + , + + FeeRate + + , + and + + RebateRate + + . +

    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Equity Coarse Universe

    +
    +
    +

    Introduction

    + + +

    + The US Equity Coarse Universe dataset by QuantConnect is a daily universe of all trading stocks in the US for a given day with the end of day price and volume. The data covers 30,000 US Equities in total, with approximately 8,000 Equities per day. The data starts in January 1998 and is delivered each trading day. This dataset is created by taking the closing auction price tick from the daily L1 trade and quote exchange dumps. +

    +

    + This dataset depends on the + + US Equities by AlgoSeek + + dataset because + + universe selection + + adds and removes market data subscriptions and on the + + US Equity Security Master + + dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. +

    +

    + QuantConnect/LEAN combines the data of this dataset with + + MorningStar Fundamental data + + in runtime. You can use this dataset in local development without the Morningstar counterpart. +

    +

    + For more information about the US Equity Coarse Universe dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Equity Coarse Universe dataset: +

    +
      +
    • + Direct Access using the Security object +
    • +
    +
    +
    equity = self.add_equity("IBM")
    +ibm_fundamental = equity.fundamentals
    +
    var equity = AddEquity("IBM");
    +var ibmFundamental = equity.Fundamentals;
    +
    +
      +
    • + Direct Access using the Symbol object +
    • +
    +
    +
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    +ibm_fundamental = self.fundamentals
    +
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    +var ibmFundamental = Fundamentals(ibm);
    +
    +
      +
    • + Universe Selection +
    • +
    +
    +
    def initialize(self) -> None:
    +    # Universe selection
    +    self._universe = self.add_universe(self.fundamental_filter_function)
    +
    +def fundamental_filter_function(self, fundamental: List[Fundamental]):
    +    # Sort all equities with price above $10 by dollar volume
    +    sorted_by_dollar_volume = sorted([f for f in fundamental if f.price > 10],
    +                                key=lambda f: f.dollar_volume, reverse=True)
    +    # Take the top 10
    +    return [f.symbol for f in sorted_by_dollar_volume[:10]]
    +
    public override void Initialize()
    +{
    +    // Universe selection
    +    _universe = AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    +}
    +
    +public override List<Symbol> FundamentalFilterFunction(List<Fundamental> fundamental)
    +{
    +    // Sort all equities with price above $10 by dollar volume, take the top 10
    +    return (from f in fundamental
    +            where f.Price > 10
    +            orderby f.DollarVolume descending
    +            select f.Symbol).Take(10);
    +}
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 1998 +
    + Asset Coverage + + 30,000 US Equities +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + + New York +
    +

    + This dataset doesn't include Over-the-Counter (OTC) stocks. +

    + + + +

    Requesting Data

    + + +

    + You don't need any special code to request US Coarse Fundamental Data. You can access the current and historical fundamental data for any of the US Equities that this dataset includes. +

    +
    +
    class CoarseFundamentalDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2021, 1, 1)
    +        self.set_end_date(2021, 7, 1)
    +        self.set_cash(100000) 
    +        self.universe_settings.asynchronous = True
    +
    +        # Option 1: Subscribe to individual US Equity assets
    +        self.add_equity("IBM")  
    +
    +        # Option 2A: Create a fundamental universe (classic version)
    +        self._universe = self.add_universe(self.fundamental_function)
    +
    +        # Option 2B: Create a fundamental universe (framework version)
    +        self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_function))
    +
    public class CoarseFundamentalDataAlgorithm : QCAlgorithm
    +{
    +    private Universe _universe;
    +    public override void Initialize()
    +    {
    +        SetStartDate(2021, 1, 1);
    +        SetEndDate(2021, 7, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        
    +        // Option 1: Subscribe to individual US Equity assets
    +        AddEquity("IBM");
    +
    +        // Option 2A: Create a fundamental universe (classic version)
    +        _universe = AddUniverse(FundamentalFilterFunction);
    +
    +        // Option 2B: Create a fundamental universe (framework version)
    +        AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    +    }
    +}
    +
    +

    + For more information about universe settings, see + + Settings + + . +

    + + + +

    Accessing Data

    + + +

    + If you add a + + fundamental universe + + to your algorithm, you can access fundamental data in the universe selection function. +

    +
    +
    def fundamental_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    +    sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume, reverse=True)[:3]
    +    for cf in sorted_by_dollar_volume:
    +        self.debug(f"{cf.end_time} :: {cf.symbol} : {cf.adjusted_price} :: {cf.dollar_volume}")
    +
    +    return [ x.symbol for x in sorted_by_dollar_volume]
    +
    public IEnumerable<Symbol> FundamentalFunction(IEnumerable<Fundamental> fundamental)
    +{
    +    var sortedByDollarVolume = fundamental
    +        .OrderByDescending(x => x.DollarVolume)
    +        .Take(3).ToList();
    +
    +    foreach (var cf in sortedByDollarVolume)
    +    {
    +        Debug($"{cf.EndTime} :: {cf.Symbol} : {cf.AdjustedPrice} :: {cf.DollarVolume}");
    +    }
    +
    +    return sortedByDollarVolume.Select(x => x.Symbol);
    +}
    +
    +

    + To get fundamental data for Equities in your algorithm, use the + + Fundamentals + + + fundamentals + + property of the + + Equity + + objects. The fundamental data represent the corporate fundamentals for the current algorithm time. +

    +
    +
    fundamentals = self.securities[symbol].fundamentals
    +
    var fundamentals = Securities[symbol].Fundamentals;
    +
    +

    + To get fundamental data for Equities, regardless of whether or not you have subscribed to them in your algorithm, call the + + Fundamentals + + + fundamentals + + method. If you pass one + + Symbol + + , the method returns a + + Fundamental + + object. If you pass a list of + + Symbol + + objects, the method returns a list of + + Fundamental + + objects. +

    +
    +
    // Single asset 
    +var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    +var ibmFundamental = Fundamentals(ibm);
    +
    +// Multiple assets
    +var nb = QuantConnect.Symbol.Create("NB", SecurityType.Equity, Market.USA);
    +var fundamentals = Fundamentals(new List<Symbol>{ nb, ibm }).ToList();
    +
    # Single asset
    +ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    +ibm_fundamental = self.fundamentals(ibm)
    +
    +# Multiple assets
    +nb = Symbol.create("NB", SecurityType.EQUITY, Market.USA)
    +fundamentals = self.fundamentals([ nb, ibm ])
    +
    + + + +

    Historical Data

    + + +

    + You can get historical fundamental data in an algorithm and in the Research Environment. +

    +

    + Historical Data in Algorithms +

    +

    + To get historical fundamental data in an algorithm, call the + + History + + + history + + method with + + Fundamental + + type and the Equity + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    +
    +// Fundamental objects
    +var fundamentalHistory = History<Fundamental>(ibm, TimeSpan.FromDays(30));
    +
    +// Fundamentals objects for all US Equities (including delisted companies)
    +var fundamentalsHistory = History<Fundamentals>(TimeSpan.FromDays(30));
    +
    +// Collection of Fundamental objects for all US Equities (including delisted companies)
    +var collectionHistory = History(_universe, 30, Resolution.Daily);
    +foreach (var fundamental in collectionHistory)
    +{
    +    // Cast to Fundamental is required
    +    var mostLiquid = fundamental.OfType<Fundamental>().OrderByDescending(x => x.DollarVolume).Take(5);
    +}
    +
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    +
    +# DataFrame of fundamental data for a given asset
    +df_history = self.history(Fundamental, ibm, timedelta(30), flatten=True)
    +
    +# Fundamental objects
    +fundamental_history = self.history[Fundamental](ibm, timedelta(30))
    +
    +# Fundamentals objects for all US Equities (including delisted companies)
    +fundamentals_history = self.history[Fundamentals](timedelta(30))
    +
    +# DataFrame of fundamental data for universe constituents
    +df_history = self.history(self._universe, 30, Resolution.DAILY, flatten=True)
    +
    +# Series of fundamental data for universe constituents
    +series_history = self.history(self._universe, 30, Resolution.DAILY)
    +for (universe_symbol, time), fundamental in series_history.items():
    +    most_liquid = sorted(fundamental, key=lambda x: x.dollar_volume)[-5:]
    +
    +

    + Historical Universe Data in Research +

    +

    + To get historical universe data in the Research Environment, call the + + UniverseHistory + + + universe_history + + method with the + + Universe + + object and the lookback period. This method returns the filtered universe. If there is no data in the period you request, the history result is empty. +

    +
    +
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var fundamentals in universeHistory)
    +{
    +    foreach (Fundamental fundamental in fundamentals)
    +    {
    +        Console.WriteLine($"{fundamental.Symbol} dollar volume at {fundamental.EndTime}: {fundamental.DollarVolume}");
    +    }
    +}
    +
    # DataFrame of fundamental data for universe constituents
    +df_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    +
    +# Series of fundamental data for universe constituents
    +series_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (universe_symbol, time), fundamentals in series_history.items():
    +    for fundamental in fundamentals:
    +        print(f"{fundamental.symbol} dollar volume at {fundamental.end_time}: {fundamental.dollar_volume}")
    +
    +

    + For more information about historical US Equity fundamental data, see + + Equity Fundamental Data + + . +

    + + + +

    Example Applications

    + + +

    + The US Equity Coarse Universe dataset enables you to accurately design a universe of US Equities. Examples include the following strategies: +

    +
      +
    • + Selecting securities with the largest dollar volume +
    • +
    • + Selecting securities within a specific price range +
    • +
    • + Selecting securities that have fundamental data available (together with + + MorningStar Fundamental data + + in + + Fundamental + + objects) +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of the three most liquid US Equities. Each time the universe changes, the algorithm forms an equal-weighted portfolio of the three companies. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class USEquityCoarseUniverseConstituentsDataAlgorithm(QCAlgorithm):
    +
    +    _number_of_symbols = 3
    +    _changes = None
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        # Set Asynchronous to True to improve speed performance.
    +        self.universe_settings.asynchronous = True
    +        # Add a universe of US Equities.
    +        universe = self.add_universe(self._select_assets)
    +        # Get historical data for the universe.
    +        history = self.history(universe, 30, Resolution.DAILY, flatten=True)
    +
    +    def _select_assets(self, fundamental: List[Fundamental]) -> List[Symbol]:
    +        # Select the top traded stocks, since they are the most popular 
    +        # with high capital flow.
    +        return [ 
    +            x.symbol for x in sorted(
    +                fundamental, key=lambda x: x.dollar_volume
    +            )[-self._number_of_symbols:] 
    +        ]
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # If we have no changes, do nothing.
    +        if not slice.bars or self._changes is None: 
    +            return
    +        # Liquidate removed securities, since they are not the most 
    +        # popular stocks.
    +        for security in self._changes.removed_securities:
    +            if security.invested:
    +                self.liquidate(security.symbol)
    +        # We want 1/N allocation for each security in our universe to
    +        # evenly dissipate risk.
    +        for security in self._changes.added_securities:
    +            self.set_holdings(security.symbol, 1 / self._number_of_symbols)
    +        self._changes = None
    +
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        self._changes = changes
    +
    +
    public class USEquityCoarseUniverseConstituentsDataAlgorithm : QCAlgorithm
    +{
    +    private int _numberOfSymbols = 3;
    +    private SecurityChanges _changes = SecurityChanges.None;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +    
    +        // Set Asynchronous to true to improve speed performance 
    +        UniverseSettings.Asynchronous = true;
    +        // Requesting data
    +        var universe = AddUniverse(SelectAssets);
    +        // Get historical data for the universe.
    +        var history = History(universe, 30, Resolution.Daily);
    +        foreach (var fundamentals in history)
    +        {
    +            // Iterate through each asset in the universe on this day 
    +            // and access its data point attributes.
    +            foreach (Fundamental f in fundamentals)
    +            {
    +                var symbol = f.Symbol;
    +                var t = f.EndTime;
    +                var dollarVolume = f.DollarVolume;
    +            }
    +        }
    +    }
    +
    +    public IEnumerable<Symbol> SelectAssets(IEnumerable<Fundamental> fundamental)
    +    {
    +        // Select the top traded stocks, since they are the most popular 
    +        // with high capital flow.
    +        return fundamental.OrderByDescending(x => x.DollarVolume)
    +            .Take(_numberOfSymbols).Select(x => x.Symbol);
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // If we have no changes, do nothing.
    +        if (slice.Bars.Count == 0 || _changes == SecurityChanges.None) return;
    +        // Liquidate removed securities, since they are not the most 
    +        // popular stocks.
    +        foreach (var security in _changes.RemovedSecurities)
    +        {
    +            if (security.Invested)
    +            {
    +                Liquidate(security.Symbol);
    +            }
    +        }
    +        // We want 1/N allocation for each security in our universe to
    +        // evenly dissipate risk.
    +        foreach (var security in _changes.AddedSecurities)
    +        {
    +            SetHoldings(security.Symbol, 1m / _numberOfSymbols);
    +        }
    +        _changes = SecurityChanges.None;
    +    }
    +    
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        _changes = changes;
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of the three most liquid US Equities and forms an equal-weighted portfolio with them. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class USEquityCoarseUniverseConstituentsDataAlgorithm(QCAlgorithm):
    +
    +    _number_of_symbols = 3
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +
    +        # Set Asynchronous to True to improve speed performance
    +        self.universe_settings.asynchronous = True
    +            
    +        # Requesting data
    +        self.set_universe_selection(
    +            FundamentalUniverseSelectionModel(self.fundamental_selection_function))
    +        
    +        # we want 1/N allocation in each security in our universe to evenly dissipate risk
    +        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(1)))
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +         
    +        self.add_risk_management(NullRiskManagementModel())
    +        
    +        self.set_execution(ImmediateExecutionModel())
    +
    +    def fundamental_selection_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    +        # Select the top traded stocks, since they are the most popular with high capital flow
    +        sorted_by_dollar_volume = sorted(fundamental, key=lambda x: x.dollar_volume, reverse=True)
    +        return [ x.symbol for x in sorted_by_dollar_volume[:self._number_of_symbols] ]
    +
    public class USEquityCoarseUniverseConstituentsDataAlgorithm : QCAlgorithm
    +{
    +    private int _numberOfSymbols = 3;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +
    +        // Set Asynchronous to true to improve speed performance
    +        UniverseSettings.Asynchronous = true;
    +
    +        // Requesting data
    +        SetUniverseSelection(
    +            new FundamentalUniverseSelectionModel(FundamentalSelectionFunction));
    +
    +        // we want 1/N allocation in each security in our universe to evenly dissipate risk
    +        SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)));
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +        
    +        AddRiskManagement(new NullRiskManagementModel());
    +        
    +        SetExecution(new ImmediateExecutionModel());
    +    }
    +
    +    public IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamental)
    +    {
    +        // Select the top traded stocks, since they are the most popular with high capital flow
    +        return fundamental.OrderByDescending(x => x.DollarVolume)
    +            .Take(_numberOfSymbols).Select(x => x.Symbol);
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example lists the three most liquid US Equities: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add Fundamental Universe Selection
    +IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamentals)
    +{
    +    return fundamentals.OrderByDescending(x => c.DollarVolume).Take(10).Select(x => c.Symbol);
    +}
    +
    +var universe = qb.AddUniverse(FundamentalSelectionFunction); 
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var fundamentals in universeHistory)
    +{
    +    foreach (Fundamental fundamental in fundamentals)
    +    {
    +        Console.WriteLine($"{fundamental.Symbol} dollar volume at {fundamental.EndTime}: {fundamental.DollarVolume}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add Fundamental Universe Selection
    +def fundamental_selection_function(fundamentals):
    +    selected = sorted(fundamentals, key=lambda x: x.dollar_volume, reverse=True)[:10]
    +    return [x.symbol for x in selected]
    +
    +universe = qb.add_universe(fundamental_selection_function)
    +
    +# Historical Universe data
    +universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (universe_symbol, time), fundamentals in universe_history.items():
    +    for fundamental in fundamentals:
    +        print(f"{fundamental.symbol} dollar volume at {fundamental.end_time}: {fundamental.dollar_volume}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Equity Coarse Universe dataset provides its data within + + Fundamental + + objects, which have the following . The attributes from + + market_cap + + + MarketCap + + to + + asset_classification + + + AssetClassification + + listed in the following widget are NaN until this dataset is combined with the + + MorningStar Fundamental + + dataset. +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Equity Option Universe

    +
    +
    +

    Introduction

    + + +

    + The US Equity Option Universe dataset by QuantConnect lists the available US Equity Options contracts and the current Implied Volatility and Greeks. The data covers 4,000 Symbols, starts in January 2012, and is delivered on a daily update frequency. To create this dataset, we use + + our implementation + + of the forward tree pricing model, which accounts for the interest rate, dividend payments, and daily closing prices. The values in this dataset are the same values you can get from daily + + indicators + + with mirror Options. +

    +

    + This dataset depends on the + + US Equity Security Master + + dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes of the underlying security. +

    +

    + This dataset + + does not + + contain market data. For market data, see + + US Equity Options by AlgoSeek + + . +

    +

    + For more information about the US Equity Option Universe dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Equity Options Universe dataset: +

    +
    +
    option = self.add_option("GOOG")
    +self.option_symbol = option.symbol
    +option.set_filter(lambda universe: universe.delta(0.4, 0.6))
    +
    var option = AddOption("GOOG");
    +_optionSymbol = option.Symbol;
    +option.SetFilter(universe => universe.delta(0.4m, 0.6m));
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2012 +
    + Asset Coverage + + 4,000 Symbols +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + + New York +
    + + + +

    Requesting Data

    + + +

    + To add US Equity Options Universe data to your algorithm, call the + + AddOption + + + add_option + + method. Save a reference to the Equity Option + + Symbol + + so you can access the data later in your algorithm. To define which contracts should be in your universe, call the + + SetFilter + + + set_filter + + method of the Option object. +

    +

    + The + + AddOption + + + add_option + + method provides a daily stream of Option chain data. To get the most recent daily chain, call the + + OptionChain + + + option_chain + + method with the underlying Equity Symbol. The + + OptionChain + + + option_chain + + method returns data on all the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    class USEquityOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        option = self.add_option("GOOG")
    +        self.option_symbol = option.symbol
    +        # Set our strike/expiry filter for this option chain
    +        option.set_filter(self._option_filter)
    +        # Get the entire Option chain for the current day.
    +        chain = self.option_chain(option.symbol.underlying, flatten=True).data_frame
    +
    +    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Contracts can be filtered by greeks, implied volatility, open interest:
    +        return universe \
    +            .delta(0.5, 1.5) \
    +            .gamma(0.0001, 0.0006) \
    +            .vega(0.01, 1.5) \
    +            .theta(-2.0, -0.5) \
    +            .rho(0.5, 3.0) \
    +            .implied_volatility(1, 3) \
    +            .open_interest(100,500)
    +
    +
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _optionSymbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        // Requesting data
    +        var option = AddOption("GOOG");
    +        _optionSymbol = option.Symbol;
    +        // Set our strike/expiry filter for this option chain
    +        option.SetFilter(OptionFilter);
    +        // Get the entire Option chain for the current day.
    +        var chain = OptionChain(option.Symbol.Underlying);
    +    }
    +
    +    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    +    {
    +        // Contracts can be filtered by greeks, implied volatility, open interest:
    +        return universe
    +            .Delta(0.5m, 1.5m)
    +            .Gamma(0.0001m, 0.0006m)
    +            .Vega(0.01m, 1.5m)
    +            .Theta(-2.0m, -0.5m)
    +            .Rho(0.5m, 3.0m)
    +            .ImpliedVolatility(1.0m, 3.0m)
    +            .OpenInterest(100, 500);
    +    }
    +}
    +
    +

    + The Equity resolution must be less than or equal to the Equity Option resolution. For example, if you set the Equity resolution to minute, then you must set the Equity Option resolution to minute, hour, or daily. +

    +

    + For more information about creating US Equity Option Universes, see + + Equity Options + + . +

    + + + +

    Accessing Data

    + + +

    + For information about accessing US Equity Options Universe data, see + + Equity Options + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Equity Options Universe data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Equity Options Universe data in an algorithm, call the + + History<OptionUniverse> + + + history + + method with the canonical Equity Option + + Symbol + + . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.option_symbol, timedelta(3), flatten=True)
    +
    +# OptionUniverse objects
    +history = self.history[OptionUniverse](self.option_symbol, timedelta(3))
    +
    // OptionUniverse objects 
    +var history = History<OptionUniverse>(_optionSymbol, TimeSpan.FromDays(3)).ToList();
    +
    +

    + For more information about historical Equity Options Universe data in algorithms, see + + Historical Data + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Equity Options Universe data in the Research Environment, call the + + History<OptionUniverse> + + + history + + method with the canonical Option + + Symbol + + . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    qb = QuantBook()
    +option = qb.add_option("GOOG")
    +history = qb.history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5), flatten=True)
    +
    var qb = new QuantBook();
    +var option = qb.AddOption("GOOG");
    +var history = qb.History<OptionUniverse>(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 6));
    +foreach (var chain in history)
    +{
    +    var endTime = chain.EndTime;
    +    var filteredContracts = chain.Data
    +        .Select(contract => contract as OptionUniverse)
    +        .Where(contract => contract.Greeks.Delta > 0.3m);
    +    foreach (var contract in filteredContracts)
    +    {
    +        var price = contract.Price;
    +        var iv = contract.ImpliedVolatility;
    +    }
    +}
    +
    +

    + For more information about historical Equity Options Universe data in the Research Environment, see + + Universes + + . +

    + + + +

    Supported Assets

    + + +

    + To view the supported assets in the US Equity Options Universe dataset, see the + + Data Explorer + + . +

    + + + +

    Example Applications

    + + +

    + The US Equity Options Universe dataset enables you to accurately design Option strategies. Examples include the following strategies: +

    +
      +
    • + Buying put Options to hedge against downward price movement in positive Equity positions +
    • +
    • + Exploiting arbitrage opportunities that arise when the price of Option contracts deviate from their theoretical value +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm subscribes to Google put options that fall within delta range between -1 and -0.95, open interest range between 10 and 1000, and expire within seven days. Within this Option chain, the algorithm holds the put Option contract that has the minimum delta (closest to -1) during market hour to hedge the underlying intra-day movement completely. It avoid volatility from sentiment and only earns from inter-day movement from longer-term factors. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. +

    +
    +
    from AlgorithmImports import *
    +
    +class USEquityOptionsUniverseAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(10000000)
    +
    +        # Asynchronous can use computational resources efficiently
    +        self.universe_settings.asynchronous = True
    +        # Subscribe to the underlying for the underlying position
    +        # Set the data normalization mode to raw for strike price comparability
    +        self.equity = self.add_equity("GOOG", data_normalization_mode=DataNormalizationMode.RAW).symbol
    +        # Requesting option data and filter for the hedge candidates
    +        option = self.add_option(self.equity)
    +        option.set_filter(self.option_filter)
    +        self.option_symbol = option.symbol
    +
    +        # Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    +        self.schedule.on(
    +            self.date_rules.every_day(self.equity),
    +            self.time_rules.after_market_open(self.equity, 1),
    +            self.buy_hedge_contract
    +        )
    +
    +        # Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    +        # Leave 2 minutes contingency to fill
    +        self.schedule.on(
    +            self.date_rules.every_day(self.equity),
    +            self.time_rules.before_market_close(self.equity, 2),
    +            self.sell_hedge_contract
    +        )
    +
    +        self.hedge = None
    +        
    +    def option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Select the contracts with delta very close to -1 and high open interest
    +        # This can effectively hedge most of the price change of the underlying and ensure the liquidity
    +        # Make sure the contract is expiring close for its tradbility
    +        return universe.puts_only().expiration(2, 7).delta(-1, -0.95).open_interest(10, 1000)
    +
    +    def buy_hedge_contract(self) -> None:
    +        chain = self.current_slice.option_chains.get(self.option_symbol)
    +        if chain:
    +            # Order the underlying if not hold, the order size should match the option contract
    +            # Order only if option chain data ready for hedging
    +            if not self.portfolio[self.equity].invested:
    +                self.market_order(self.equity, self.securities[self.option_symbol].symbol_properties.contract_multiplier)
    +
    +            # Get the contract with delta closest to -1 (lowest possible delta)
    +            contract = sorted(chain, key=lambda x: x.greeks.delta)[0]
    +            self.hedge = contract.symbol
    +            # Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    +            self.market_order(self.hedge, 1)
    +        
    +    def sell_hedge_contract(self) -> None:
    +        # Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    +        if self.hedge:
    +            self.liquidate(self.hedge)
    +            self.hedge = None
    +
    public class USEquityOptionsUniverseAlgorithm : QCAlgorithm
    +{
    +    private Symbol _equity, _optionSymbol, _hedge;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(10000000);
    +        // Asynchronous can use computational resources efficiently
    +        UniverseSettings.Asynchronous = true;
    +
    +        // Subscribe to the underlying for the underlying position
    +        // Set the data normalization mode to raw for strike price comparability
    +        _equity = AddEquity("GOOG", dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
    +        // Requesting option data and filter for the hedge candidates
    +        var option = AddOption(_equity);
    +        _optionSymbol = option.Symbol;
    +        option.SetFilter(OptionFilter);
    +
    +        // Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    +        Schedule.On(
    +            DateRules.EveryDay(_equity),
    +            TimeRules.AfterMarketOpen(_equity, 1),
    +            BuyHedgeContract
    +        );
    +
    +        // Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    +        // Leave 2 minutes contingency to fill
    +        Schedule.On(
    +            DateRules.EveryDay(_equity),
    +            TimeRules.BeforeMarketClose(_equity, 2),
    +            SellHedgeContract
    +        );
    +    }
    +
    +    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    +    {
    +        // Select the contracts with delta very close to -1 and high open interest
    +        // This can effectively hedge most of the price change of the underlying and ensure the liquidity
    +        // Make sure the contract is expiring close for its tradbility
    +        return universe
    +            .PutsOnly()
    +            .Expiration(2, 7)
    +            .Delta(-1m, -0.95m)
    +            .OpenInterest(10, 1000);
    +    }
    +
    +    private void BuyHedgeContract()
    +    {
    +        if (CurrentSlice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    +        {
    +            // Order the underlying if not hold, the order size should match the option contract
    +            // Order only if option chain data ready for hedging
    +            if (!Portfolio[_equity].Invested)
    +            {
    +                MarketOrder(_equity, Securities[_optionSymbol].SymbolProperties.ContractMultiplier);
    +            }
    +
    +            // Get the contract with delta closest to -1 (lowest possible delta)
    +            var contract = chain.MinBy(x => x.Greeks.Delta);
    +            _hedge = contract.Symbol;
    +            // Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    +            MarketOrder(_hedge, 1);
    +        }
    +    }
    +
    +    private void SellHedgeContract()
    +    {
    +        // Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    +        if (_hedge != null)
    +        {
    +            Liquidate(_hedge);
    +            _hedge = null;
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm demonstrating a Gamma Scalping strategy through framework algorithm. It filters NVDA options with expiration between 30 to 90 days and open interest between 50 and 1000, due to liquidity concern and lower Gamma fluctuation. Assuming a significant upward trend is expecting, it orders a long straddle strategy from the strike price with Delta-neutral and the highest Gamma to earn the highest profit from upward underlying movement. +

    +
    +
    from AlgorithmImports import *
    +
    +class USEquityOptionsUniverseFrameworkAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        # Asynchronous can use computational resources efficiently
    +        self.universe_settings.asynchronous = True
    +
    +        # Universe selection that select based on liquidity of the option contracts (by open interest)
    +        self.add_universe_selection(EquityOptionsUniverseSelectionModel())
    +        # Custom alpha model that use Delta and Gamma to signal insights
    +        self.add_alpha(OptionDeltaGammaAlphaModel())
    +        # To maintain long-short size equal, use a PCM that order a single contract
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +
    +class EquityOptionsUniverseSelectionModel(OptionUniverseSelectionModel):
    +    def __init__(self) -> None:
    +        # Daily update with the select_option_chain_symbols function
    +        super().__init__(timedelta(1), self.select_option_chain_symbols)
    +
    +    def select_option_chain_symbols(self, dt: datetime) -> List[Symbol]:
    +        # Select only NVDA options as our focus, which is a highly traded volatile equity with great upward momentum
    +        return [Symbol.create("NVDA", SecurityType.OPTION, Market.USA)]
    +
    +    def filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    +        # A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    +        return universe.expiration(30, 90).open_interest(50, 1000)
    +
    +class OptionDeltaGammaAlphaModel(AlphaModel):
    +    def __init__(self) -> None:
    +        # A day count variable to control the alpha model only trade once a day
    +        self._day = -1
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        insights = []
    +
    +        if self._day != slice.time.day:
    +            # We open position for each option underlying as separate bet
    +            for _, chain in slice.option_chains.items():
    +                # For theta-neutral, select the same expiry for both call and put
    +                expiry = min(x.expiry for x in chain)
    +                contracts = [x for x in chain if x.expiry == expiry]
    +
    +                # Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    +                delta_gamma_symbols = []
    +                strikes = set(x.strike for x in contracts if len([y for y in contracts if y.strike == x.strike]) == 2)
    +                for strike in strikes:
    +                    # Get both call and put for their aggregated delta and gamma
    +                    call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == strike, contracts))
    +                    put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == strike, contracts))
    +                    delta_gamma_symbols.append((call.greeks.delta + put.greeks.delta, call.greeks.gamma + put.greeks.gamma, call.symbol, put.symbol))
    +                
    +                if len(delta_gamma_symbols) == 0:
    +                    continue
    +
    +                # We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    +                # Less than 2d.p. difference is non-significant, which we can risk for better reward
    +                # Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    +                # Make sure the aggregated gamma to be positive to bet on large uptrend
    +                # So it will earn more when the price really go up higher and higher, but locally immune for small noise
    +                filtered = [item for item in delta_gamma_symbols if round(item[0], 2) <= 0.01 and item[1] > 0]
    +                if len(filtered) == 0:
    +                    continue
    +                selected = sorted(filtered, key=lambda x: x[1], reverse=True)[0]
    +
    +                # Provide trade signal and roll the day count to let the position stay for the whole day
    +                selected_call = selected[2]
    +                selected_put = selected[3]
    +                insights.extend([
    +                    Insight.price(selected_call, Expiry.END_OF_DAY, InsightDirection.UP),
    +                    Insight.price(selected_put, Expiry.END_OF_DAY, InsightDirection.UP)
    +                ])
    +                self._day = slice.time.day
    +        
    +        return insights
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                # Use a whole number target to order the exact number of share for size-matching
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class USEquityOptionsUniverseFrameworkAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        // Asynchronous can use computational resources efficiently
    +        UniverseSettings.Asynchronous = true;
    +
    +        // Universe selection that select based on liquidity of the option contracts (by open interest)
    +        AddUniverseSelection(new EquityOptionsUniverseSelectionModel());
    +        // Custom alpha model that use Delta and Gamma to signal insights
    +        AddAlpha(new OptionDeltaGammaAlphaModel());
    +        // To maintain long-short size equal, use a PCM that order a single contract
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}       
    +    
    +class EquityOptionsUniverseSelectionModel : OptionUniverseSelectionModel
    +{
    +    // Daily update with the SelectOptionChainSymbols function
    +    public EquityOptionsUniverseSelectionModel()
    +            : base(TimeSpan.FromDays(1), SelectOptionChainSymbols) {}
    +    
    +    private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
    +    {
    +        // Select only NVDA options as our focus, which is a highly traded volatile equity with great upward momentum
    +        return new[] {QuantConnect.Symbol.Create("NVDA", SecurityType.Option, Market.USA)};
    +    }
    +
    +    protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
    +    {
    +        // To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    +        // A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    +        return filter
    +            .Expiration(30, 90)
    +            .OpenInterest(50, 1000);
    +    }
    +}
    +    
    +class OptionDeltaGammaAlphaModel : AlphaModel
    +{
    +    // A day count variable to control the alpha model only trade once a day
    +    private int _day = -1;
    +
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = new List<Insight>();
    +        
    +        if (_day != slice.Time.Day)
    +        {
    +            // We open position for each option underlying as separate bet
    +            foreach (var kvp in slice.OptionChains)
    +            {
    +                var chain = kvp.Value;
    +
    +                // For theta-neutral, select the same expiry for both call and put
    +                var expiry = chain.Min(x => x.Expiry);
    +                var contracts = chain.Where(x => x.Expiry == expiry).ToList();
    +
    +                // Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    +                var deltaGammaSymbols = new List<(decimal, decimal, Symbol, Symbol)>();
    +                var strikes = contracts.Select(x => x.Strike)
    +                    .Where(x => contracts.Count(y => y.Strike == x) == 2)
    +                    .Distinct();
    +                foreach (var strike in strikes)
    +                {
    +                    // Get both call and put for their aggregated delta and gamma
    +                    var call = contracts.Single(x => x.Right == OptionRight.Call && x.Strike == strike);
    +                    var put = contracts.Single(x => x.Right == OptionRight.Put && x.Strike == strike);
    +                    deltaGammaSymbols.Add((call.Greeks.Delta + put.Greeks.Delta, call.Greeks.Gamma + put.Greeks.Gamma, call.Symbol, put.Symbol));
    +                }
    +
    +                if (deltaGammaSymbols.Count == 0)
    +                {
    +                    continue;
    +                }
    +
    +                // We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    +                // Less than 2d.p. difference is non-significant, which we can risk for better reward
    +                // Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    +                // Make sure the aggregated gamma to be positive to bet on large uptrend
    +                // So it will earn more when the price really go up higher and higher, but locally immune for small noise
    +                var filtered = deltaGammaSymbols.Where(item => Math.Round(item.Item1, 2) <= 0.01m && item.Item2 > 0).ToList();
    +                if (filtered.Count == 0)
    +                {
    +                    continue;
    +                }
    +                var selected = filtered.OrderByDescending(item => item.Item2).First();
    +
    +                // Provide trade signal and roll the day count to let the position stay for the whole day
    +                var selectedCall = selected.Item3;
    +                var selectedPut = selected.Item4;
    +                insights.AddRange(new[] {
    +                    Insight.Price(selectedCall, Expiry.EndOfDay, InsightDirection.Up),
    +                    Insight.Price(selectedPut, Expiry.EndOfDay, InsightDirection.Up)
    +                });
    +                _day = slice.Time.Day;
    +            }
    +        }
    +
    +        return insights;
    +    }
    +}
    +    
    +class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        var targets = new List<PortfolioTarget>();
    +        foreach (var insight in insights)
    +        {
    +            if (algorithm.Securities[insight.Symbol].IsTradable)
    +            {
    +                // Use a whole number target to order the exact number of share for size-matching
    +                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +            }
    +        }
    +        return targets;
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Equity Options Universe dataset provides + + OptionFilterUniverse + + , + + OptionUniverse + + , and + + OptionChain + + objects. +

    +

    + OptionFilterUniverse Attributes +

    +

    + + OptionFilterUniverse + + objects have the following attributes: +

    +
    +
    +

    + OptionUniverse Attributes +

    +

    + + OptionUniverse + + objects have the following attributes: +

    +
    +
    +

    + OptionChain Attributes +

    +

    + + OptionChain + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Equity Security Master

    +
    +
    +

    Introduction

    + + +

    + The US Equity Security Master dataset by QuantConnect tracks US Equity corporate actions, including splits, dividends, delistings, mergers, and ticker changes through history. The data covers approximately 27,500 US Equities, starts in January 1998, and is delivered on a daily update frequency. You can easily download and install the dataset with the LEAN CLI so it's ready to use by LEAN. LEAN automatically handles all corporate actions and passes them into your algorithm as + + events + + . +

    +

    + This is + + NOT + + the underlying Equity data ( + + US Equities + + dataset), which you need to purchase separately with a license from AlgoSeek. This security master dataset is required to purchase the US Equities or US Equities Options datasets. +

    +

    + For more information about the US Equity Security Master dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Data Summary

    + + +

    + Data is delivered as a daily updated zip archive of map and factor files. The data is designed to be used in the LEAN Engine and cannot be consumed another way. The following table shows the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 1998 +
    + Data Points + + Splits, Dividends, Mergers, IPO, & Delistings +
    + Asset Coverage + + 27,500 US Equities +
    + Resolution + + Daily +
    + Timezone + + New York +
    +

    + This is + + not + + the underlying Equity data ( + + US Equities + + dataset), which you need to purchase separately with a license from AlgoSeek. This security master dataset is required to purchase the US Equities or US Equities Options datasets. +

    + + + +

    Getting Started

    + + +

    + You don't need any special code to utilize the US Equity Security Master. It automatically loads when you + + request US Equities data + + . +

    + + + +

    Accessing Splits

    + + +

    + To get the current split data, index the + + Splits + + + splits + + property of the current + + + Slice + + + with the Equity + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Check if any splits for the symbol
    +    if slice.splits.contains_key(self._symbol):
    +        # If so, get the mapped split object
    +        split = slice.splits[self._symbol]
    +        split_type = {0: "Warning", 1: "SplitOccurred"}.get(split.type)
    +        self.log(f"Split: {split.symbol}\t{split.split_factor}\t{split.reference_price}\t{split_type}")
    +
    public override void OnData(Slice slice)
    +{
    +    // Check if any splits for the symbol
    +    if (slice.Splits.ContainsKey(_symbol))
    +    {
    +        // If so, get the mapped split object
    +        var split = slice.Splits[_symbol];
    +        Log($"Split: {split.Symbol}\t{split.SplitFactor}\t{split.ReferencePrice}\t{split.Type}");
    +    }
    +}
    +
    +

    + For more information about accessing splits, see + + Splits + + . +

    + + + +

    Accessing Dividends

    + + +

    + To get the current dividend data, index the + + Dividends + + + dividends + + property of the current + + Slice + + with the Equity + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Check if any dividend for the symbol
    +    if slice.dividends.contains_key(self._symbol):
    +        # If so, get the mapped dividend object
    +        dividend = slice.dividends[self._symbol]
    +        self.log(f'Dividend: {dividend.symbol}\t{dividend.distribution}\t{dividend.reference_price}')
    +
    public override void OnData(Slice slice)
    +{
    +    // Check if any dividend for the symbol
    +    if (slice.Dividends.ContainsKey(_symbol))
    +    {
    +        // If so, get the mapped dividend object
    +        var dividend = slice.Dividends[_symbol];
    +        Log($"Dividend: {dividend.Symbol}\t{dividend.Distribution}\t{dividend.ReferencePrice}");
    +    }
    +}
    +
    +

    + For more information about accessing dividends, see + + Dividends + + . +

    + + + +

    Accessing Delistings

    + + +

    + To get the current Delistings data, index the + + Delistings + + + delistings + + property of the current + + Slice + + with the Equity + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Check if any delisting for the symbol
    +    if slice.delistings.contains_key(self._symbol):
    +        # If so, get the mapped delisting object
    +        delisting = slice.delistings[self._symbol]
    +        delisting_type = {0: "Warning", 1: "Delisted"}.get(delisting.type)
    +        self.log(f'Delistings: {delisting_type}')
    +
    public override void OnData(Slice slice)
    +{
    +    // Check if any delisting for the symbol
    +    if (slice.Delistings.ContainsKey(_symbol))
    +    {
    +        // If so, get the mapped delisting object
    +        var delisting = slice.Delistings[_symbol];
    +        Log($"Delistings: {delisting.Type}");
    +    }
    +}
    +
    +

    + For more information about accessing delistings, see + + Delistings + + . +

    + + + +

    Accessing Symbol Change Events

    + + +

    + To get the current Symbol change events, index the + + SymbolChangedEvents + + + symbol_changed_events + + property of the current + + Slice + + with the Equity + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Check if any symbol change event for the symbol
    +    if slice.symbol_changed_events.contains_key(self._symbol):
    +        # If so, get the mapped SymbolChangeEvent object
    +        symbol_changed_event = slice.symbol_changed_events[self._symbol]
    +        self.log(f"Symbol changed: {symbol_changed_event.old_symbol} -> {symbol_changed_event.new_symbol}")
    +
    +
    +public override void OnData(Slice slice){
    +    // Check if any symbol change event for the symbol
    +    if (slice.SymbolChangedEvents.ContainsKey(_symbol))
    +    {
    +        // If so, get the mapped SymbolChangeEvent object
    +        var symbolChangedEvent = slice.SymbolChangedEvents[_symbol];
    +        Log($"Symbol changed: {symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.NewSymbol}");
    +    }
    +}
    +
    +

    + For more information about accessing Symbol change events, see + + Symbol Changes + + . +

    + + + +

    Historical Data

    + + +

    + To get historical US Equity Security Master data, call the + + History + + + history + + method with the data type and the Equity + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # Splits
    +split_history_df = self.history(Split, self._symbol, timedelta(5*365))
    +split_history = self.history[Split](self._symbol, timedelta(5*365))
    +
    +# Dividends
    +dividend_history_df = self.history(Dividend, self._symbol, timedelta(5*365))
    +dividend_history = self.history[Dividend](self._symbol, timedelta(5*365))
    +
    +# Symbol Changes
    +symbol_change_history_df = self.history(SymbolChangedEvent, self._symbol, timedelta(5*365))
    +symbol_change_history = self.history[SymbolChangedEvent](self._symbol, timedelta(5*365))
    +
    +# Delistings
    +delisting_history_df = self.history(Delisting, self._symbol, timedelta(5*365))
    +delisting_history = self.history[Delisting](self._symbol, timedelta(5*365))
    +
    // Splits
    +var splitHistory = History<Split>(_symbol, TimeSpan.FromDays(5*365));
    +
    +// Dividends 
    +var dividendHistory = History<Dividend>(_symbol, TimeSpan.FromDays(5*365));
    +
    +// Symbol Changes
    +var symbolChangeHistory = History<SymbolChangedEvent>(_symbol, TimeSpan.FromDays(5*365));
    +
    +// Delistings
    +var delistingHistory = History<Delisting>(_symbol, TimeSpan.FromDays(5*365));
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Live Trading Considerations

    + + +

    + In backtesting, corporate actions occurs at midnight (ET). In live trading, the live data for corporate actions arrives at 6/7 AM ET, so that's when they occur. +

    + + + +

    Supported Assets

    + + +

    + To view the supported assets in the US Equity Security Master dataset, see the + + Data Explorer + + . This dataset doesn't include Over-the-Counter (OTC) stocks. +

    + + + +

    Example Applications

    + + +

    + The US Security Master enables you to accurately design strategies harnessing any core corporate actions. Examples include the following strategies: +

    +
      +
    • + Post-dividend announcement trading strategies. +
    • +
    • + Trading on new Equities by monitoring for IPOs. +
    • +
    • + Harnessing split announcements for reverse-split announcement momentum. +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm logs the + + Split + + , + + Dividend + + , + + Delisting + + , and + + SymbolChangedEvent + + objects of Apple: +

    +
    +
    from AlgorithmImports import *
    +
    +class USEquitySecurityMasterAlgorithm (QCAlgorithm):
    +
    +    def initialize(self):
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1000000)
    +        
    +        self.equity = self.add_equity("AAPL", Resolution.DAILY).symbol
    +        
    +    def on_data(self, slice: Slice) -> None:
    +        # Accessing Data - Splits
    +        split = slice.splits.get(self.equity)
    +        if split:
    +            self.debug(f"{self.time} >> SPLIT >> {split.symbol} - {split.split_factor} - {self.portfolio.cash} - {self.portfolio[self.equity].price}")
    +        
    +        # Accessing Data - Dividends
    +        dividend = slice.dividends.get(self.equity)
    +        if dividend:
    +            self.debug(f"{self.time} >> DIVIDEND >> {dividend.symbol} - {dividend.distribution} - {self.portfolio.cash} - {self.portfolio[self.equity].price}")
    +
    +        # Accessing Data - Delisting
    +        delisting = slice.delistings.get(self.equity)
    +        if delisting:
    +            delistingType = {0: "Warning", 1: "Delisted"}.get(delisting.type)
    +            self.debug(f"{self.time} >> DELISTING >> {delisting.symbol} - {delistingType}")
    +            
    +        # Accessing Data - Symbol Changed Event
    +        symbolChangedEvent = slice.symbol_changed_events.get(self.equity)
    +        if symbolChangedEvent:
    +            self.debug(f"{self.time} >> SYMBOL CHANGED >> {symbolChangedEvent.old_symbol} -> {symbolChangedEvent.new_symbol}")
    +
    +
    public class USEquitySecurityMasterAlgorithm : QCAlgorithm
    +{
    +    private Symbol _equity;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000000);
    +        
    +        _equity = AddEquity("AAPL", Resolution.Daily).Symbol;
    +    }
    +    
    +    public override void OnData(Slice slice)
    +    {
    +        // Accessing Data - Splits
    +        if (slice.Splits.ContainsKey(_equity))
    +        {
    +            var split = slice.Splits[_equity];
    +            Debug($"Split: {split.Symbol}\t{split.SplitFactor}\t{split.ReferencePrice}\t{split.Type}");
    +        }
    +        
    +        // Accessing Data - Dividends
    +        if (slice.Dividends.ContainsKey(_equity))
    +        {
    +            var dividend = slice.Dividends[_equity];
    +            Log($"Dividend: {dividend.Symbol}\t{dividend.Distribution}\t{dividend.ReferencePrice}");
    +        }
    +        
    +        // Accessing Data - Delisting
    +        if (slice.Delistings.ContainsKey(_equity))
    +        {
    +            var delisting = slice.Delistings[_equity];
    +            Log($"Delistings: {delisting.Type}");
    +        }
    +        
    +        // Accessing Data - Symbol Changed Event
    +        if (slice.SymbolChangedEvents.ContainsKey(_equity))
    +        {
    +            var symbolChangedEvent = slice.SymbolChangedEvents[_equity];
    +            Log($"Symbol changed: {symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.NewSymbol}");
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following algorithm demonstrates the payments for cash dividends in backtesting. When the data normalization mode is + + Raw + + , your portfolio receives cash dividends. +

    +
    +
    from AlgorithmImports import *
    +
    +class PaymentAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +
    +        # this will use the Tradier Brokerage open order split behavior
    +        # forward split will modify open order to maintain order value
    +        # reverse split open orders will be canceled
    +        self.set_brokerage_model(BrokerageName.TRADIER_BROKERAGE)
    +
    +        self.universe_settings.resolution = Resolution.DAILY
    +        self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
    +        
    +        # MSFT: Splits and Dividends
    +        # GOOG: Symbol Changed Event
    +        # AAA.1: Delisting
    +        
    +        self.set_universe_selection(ManualUniverseSelectionModel(
    +            Symbol.create("MSFT", SecurityType.EQUITY, Market.USA)))
    +
    +        self.set_alpha(PaymentAlphaModel())
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +        self.set_execution(BracketExecutionModel())
    +            
    +class PaymentAlphaModel(AlphaModel):
    +
    +    symbol = Symbol.EMPTY
    +    
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        # Accessing Data - Splits
    +        split = slice.splits.get(self.symbol)
    +        if split:
    +            algorithm.debug(f"{algorithm.time} >> SPLIT >> {split.symbol} - {split.split_factor} - {algorithm.portfolio.cash} - {algorithm.portfolio[self.symbol].price}")
    +
    +        # Accessing Data - Dividends
    +        dividend = slice.dividends.get(self.symbol)
    +        if dividend:
    +            algorithm.debug(f"{algorithm.time} >> DIVIDEND >> {dividend.symbol} - {dividend.distribution} - {algorithm.portfolio.cash} - {algorithm.portfolio[self.symbol].price}")
    +
    +        # Accessing Data - Delistings
    +        delisting = slice.delistings.get(self.symbol)
    +        if delisting:
    +            delistingType = {0: "Warning", 1: "Delisted"}.get(delisting.type)
    +            algorithm.debug(f"{algorithm.time} >> DELISTING >> {delisting.symbol} - {delistingType}")
    +
    +        # Accessing Data - Symbol Changed Events
    +        symbolChangedEvent = slice.symbol_changed_events.get(self.symbol)
    +        if symbolChangedEvent:
    +            algorithm.debug(f"{algorithm.time} >> SYMBOL CHANGED >> {symbolChangedEvent.old_symbol} -> {symbolChangedEvent.new_symbol}")
    +
    +        bar = slice.bars.get(self.symbol)
    +        return [Insight.price(self.symbol, timedelta(1), InsightDirection.UP)] if bar else []
    +
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        self.symbol = list(changes.added_securities)[0].symbol
    +
    +class BracketExecutionModel(ExecutionModel):
    +    
    +    def __init__(self) -> None:
    +        '''Initializes a new instance of the ImmediateExecutionModel class'''
    +        self.targets_collection = PortfolioTargetCollection()
    +
    +    def execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None:
    +
    +        # for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    +        self.targets_collection.add_range(targets)
    +        if self.targets_collection.count > 0:
    +            for target in self.targets_collection.order_by_margin_impact(algorithm):
    +                # calculate remaining quantity to be ordered
    +                quantity = OrderSizing.get_unordered_quantity(algorithm, target)
    +                if quantity != 0 and algorithm.transactions.orders_count == 0:
    +                    bar = algorithm.securities[target.symbol].get_last_data()
    +                    algorithm.market_order(target.symbol, quantity)
    +                    # place some orders that won't fill, when the split comes in they'll get modified to reflect the split
    +                    algorithm.stop_market_order(target.symbol, -quantity, bar.low/2)
    +                    algorithm.limit_order(target.symbol, -quantity, bar.high*2)
    +
    +            self.targets_collection.clear_fulfilled(algorithm)
    +
    +
    public class PaymentsAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +            
    +        // this will use the Tradier Brokerage open order split behavior
    +        // forward split will modify open order to maintain order value
    +        // reverse split open orders will be canceled
    +        SetBrokerageModel(BrokerageName.TradierBrokerage);
    +        
    +        UniverseSettings.Resolution = Resolution.Daily;
    +        UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
    +        
    +        // MSFT: Splits and Dividends
    +        // GOOG: Symbol Changed Event
    +        // AAA.1: Delisting
    +        SetUniverseSelection(new ManualUniverseSelectionModel(
    +            QuantConnect.Symbol.Create("MSFT", SecurityType.Equity, Market.USA)));
    +
    +        SetAlpha(new PaymentAlphaModel());
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +        SetExecution(new BracketExecutionModel());
    +    }
    +}
    +
    +public class PaymentAlphaModel : AlphaModel
    +{
    +    private Symbol _symbol = Symbol.Empty;
    +    
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        // Accessing Data - Splits
    +        if (slice.Splits.ContainsKey(_symbol))
    +        {
    +            var split = slice.Splits[_symbol];
    +            algorithm.Debug($"{split.Time.ToIso8601Invariant()} >> SPLIT >> {split.Symbol} - " +
    +                $"{split.SplitFactor.ToStringInvariant()} - " +
    +                $"{algorithm.Portfolio.Cash.ToStringInvariant()} - " +
    +                $"{algorithm.Portfolio[_symbol].Quantity.ToStringInvariant()}");
    +        }
    +        
    +        // Accessing Data - Dividends
    +        if (slice.Dividends.ContainsKey(_symbol))
    +        {
    +            var dividend = slice.Dividends[_symbol];
    +            algorithm.Debug($"{dividend.Time.ToStringInvariant("o")} >> DIVIDEND >> {dividend.Symbol} - " +
    +                $"{dividend.Distribution.ToStringInvariant("C")} - {algorithm.Portfolio.Cash} - " +
    +                $"{algorithm.Portfolio[_symbol].Price.ToStringInvariant("C")}");
    +        }
    +
    +        // Accessing Data - Delisting
    +        if (slice.Delistings.ContainsKey(_symbol))
    +        {
    +            var delisting = slice.Delistings[_symbol];
    +            algorithm.Debug($"{delisting.Time.ToStringInvariant("o")} >> DELISTING >> {delisting.Type}");
    +        }
    +
    +        // Accessing Data - Symbol Changed Event
    +        if (slice.SymbolChangedEvents.ContainsKey(_symbol))
    +        {
    +            var symbolChangedEvent = slice.SymbolChangedEvents[_symbol];
    +            algorithm.Debug($"{symbolChangedEvent.Time.ToStringInvariant("o")} >> Symbol Changed Event >> " +
    +                $"{symbolChangedEvent.OldSymbol} -> {symbolChangedEvent.OldSymbol}");
    +        }
    +        
    +        return slice.Bars.ContainsKey(_symbol)
    +            ? new [] { Insight.Price(_symbol, TimeSpan.FromDays(1), InsightDirection.Up) }
    +            : Enumerable.Empty<Insight>();
    +    }
    +    
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {
    +        _symbol = changes.AddedSecurities.First().Symbol;
    +    }
    +}
    +
    +public class BracketExecutionModel : ExecutionModel
    +{
    +    private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
    +
    +    public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
    +    {
    +        _targetsCollection.AddRange(targets);
    +        // for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
    +        if (_targetsCollection.Count > 0)
    +        {
    +            foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
    +            {
    +                // calculate remaining quantity to be ordered
    +                var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);
    +                if (quantity != 0 && algorithm.Transactions.OrdersCount == 0)
    +                {
    +                    var bar = algorithm.Securities[target.Symbol].GetLastData() as TradeBar;
    +                    algorithm.MarketOrder(target.Symbol, quantity);
    +                    // place some orders that won't fill, when the split comes in they'll get modified to reflect the split
    +                    algorithm.StopMarketOrder(target.Symbol, -quantity, bar.Low/2);
    +                    algorithm.LimitOrder(target.Symbol, -quantity, bar.High*2);
    +                }
    +            }
    +
    +            _targetsCollection.ClearFulfilled(algorithm);
    +        }
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Equity Security Master dataset provides + + Split + + , + + Dividend + + , + + Delisting + + , and + + SymbolChangedEvent + + objects. +

    +

    + Split Attributes +

    +

    + When a split or merger occurs, we pass the previous + + Symbol + + data into your algorithm. + + Split + + objects have the following attributes: +

    +
    +
    +

    + Dividend Attributes +

    +

    + Dividend events are triggered on the payment date. + + Dividend + + objects have the following attributes: +

    +
    +
    +

    + Delisting Attributes +

    +

    + When a security is delisted, we notify your algorithm. + + Delisting + + objects have the following attributes: +

    +
    +
    +

    + SymbolChangedEvent Attributes +

    +

    + When a security changes their ticker, we notify your algorithm. + + SymbolChangedEvent + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Future Option Universe

    +
    +
    +

    Introduction

    + + +

    + The US Future Option Universe dataset by QuantConnect lists the available US Future Options contracts and the current open interest. The data covers 15 Monthly Future contracts, starts in January 2012, and is delivered on a daily update frequency. This dataset is created by monitoring the trading activity on the CME, CBOT, NYMEX, and COMEX markets. +

    +

    + The US Future Option Universe dataset depends on the + + US Future Universe + + dataset because the US Future Universe dataset contains the universe of underlying Futures contracts. + This dataset also depends on the + + US Futures Security Master + + dataset because the US Futures Security Master dataset contains information on symbol changes of the contracts. +

    +

    + This dataset + + does not + + contain market data. For market data, see + + US Future Options by AlgoSeek + + . +

    +

    + For more information about the US Future Option Universe dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Future Options Universe dataset: +

    +
    +
    future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    +future.set_filter(0, 90)
    +self.add_future_option(future.symbol, lambda universe: universe.strikes(-1, 1))
    +
    var future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    +future.SetFilter(0, 90);
    +AddFutureOption(future.Symbol, universe => universe.Strikes(-1, 1));
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2012 +
    + Asset Coverage + + 15 Monthly Future Contracts. Standard expires only. No weeklies or 0DTE contracts. +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + + New York +
    + Market Hours + + + Regular and Extended + +
    + + + +

    Requesting Data

    + + +

    + To add US Future Options Universe data to your algorithm, call the + + AddFutureOption + + + add_future_option + + method. To define which contracts should be in your universe, specify the filter when requesting the Future Option data. +

    +

    + The + + AddFutureOption + + + add_future_option + + method provides a daily stream of Option chain data. To get the most recent daily chain, call the + + OptionChain + + + option_chain + + method with the underlying Future Symbol. The + + OptionChain + + + option_chain + + method returns data on all the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    class USFutureOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        
    +        self.future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    +        self.future.set_filter(0, 90)
    +        # Set our strike/expiry filter for this option chain
    +        self.add_future_option(self.future.symbol, self._option_filter)
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Get the entire Option chain for the current day.
    +        symbol = Symbol.create_canonical_option(self.future.mapped)
    +        chain = self.option_chain(symbol, flatten=True).data_frame
    +
    +    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Contracts can be filtered by strike, and expiration
    +        return universe.strikes(-1, 1)
    +
    public class USFutureOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Future _future;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        
    +        _future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    +        _future.SetFilter(0, 90);
    +        // Set our strike/expiry filter for this option chain
    +        AddFutureOption(_future.Symbol, OptionFilter);
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol.
    +        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_future.Mapped);
    +        // Get the entire Option chain for the current day.
    +        var chain = OptionChain(symbol);
    +    }
    +
    +    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    +    {
    +        // Contracts can be filtered by strike, and expiration
    +        return universe.Strikes(-1, 1);
    +    }
    +}
    +
    +

    + The Future resolution must be less than or equal to the Future Option resolution. For example, if you set the Future resolution to minute, then you must set the Future Option resolution to minute, hour, or daily. +

    +

    + For more information about creating US Future Option universes, see + + Future Options + + . +

    + + + +

    Accessing Data

    + + +

    + For information about accessing US Future Options Universe data, see + + Future Options + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Future Options Universe data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Future Options Universe data in an algorithm, call the + + History<OptionUniverse> + + + history + + method with the canonical mapped Future Option + + Symbol + + . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty. +

    +
    +
    future_option_symbol = Symbol.create_canonical_option(self.future.mapped)
    +# DataFrame
    +history_df = self.history(future_option_symbol, timedelta(10), flatten=True)
    +# OptionUniverse objects
    +history = self.history[OptionUniverse](future_option_symbol, timedelta(10))
    +
    var futureOptionSymbol = QuantConnect.Symbol.CreateCanonicalOption(_future.Mapped);
    +var history = History<OptionUniverse>(futureOptionSymbol, TimeSpan.FromDays(10)).ToList();
    +
    +

    + For more information about historical US Future Options Universe data in algorithms, see + + Historical Data + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Future Options Universe data in the Research Environment, call the + + History<OptionUniverse> + + + history + + method with the canonical Option + + Symbol + + . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    qb = QuantBook()
    +future = qb.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    +future.set_filter(0, 90)
    +symbol = Symbol.create_canonical_option(future.mapped)
    +history = qb.history(symbol, datetime(2020, 6, 1), datetime(2020, 6, 5), flatten=True)
    +
    var qb = new QuantBook();
    +var future = qb.AddFuture(Futures.Metals.Gold, Resolution.Minute);
    +var symbol = QuantConnect.Symbol.CreateCanonicalOption(future.Mapped);
    +var history = qb.History<OptionUniverse>(symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 6));
    +foreach (var chain in history)
    +{
    +    var endTime = chain.EndTime;
    +    var filteredContracts = chain.Data
    +        .Select(contract => contract as OptionUniverse)
    +        .Where(contract => contract.Greeks.Delta > 0.3m);
    +    foreach (var contract in filteredContracts)
    +    {
    +        var price = contract.Price;
    +        var iv = contract.ImpliedVolatility;
    +    }
    +}
    +
    +

    + For more information about historical Future Options Universe data in the Research Environment, see + + Universes + + . +

    + + + +

    Supported Assets

    + + +

    + The following list shows the available (15) Futures Options: +

    +
      +
    • + + Futures.Energy.CrudeOilWTI + + + Futures.Energy.CRUDE_OIL_WTI + + : Crude Oil WTI Futures (NYMEX: LO | Underlying: CL) +
    • +
    • + + Futures.Energy.Gasoline + + + Futures.Energy.GASOLINE + + : Gasoline RBOB Futures (NYMEX: OB | Underlying: RB) +
    • +
    • + + Futures.Energy.HeatingOil + + + Futures.Energy.HEATING_OIL + + : Heating Oil Futures (NYMEX: OH | Underlying: HO) +
    • +
    • + + Futures.Energy.NaturalGas + + + Futures.Energy.NATURAL_GAS + + : Natural Gas Futures (NYMEX: ON | Underlying: NG) +
    • +
    • + + Futures.Financials.Y10TreasuryNote + + + Futures.Financials.Y_10_TREASURY_NOTE + + : 10Y U.S. Treasury Note Futures (CBOT: OZN | Underlying: ZN) +
    • +
    • + + Futures.Financials.Y2TreasuryNote + + + Futures.Financials.Y_2_TREASURY_NOTE + + : 2Y U.S. Treasury Note Futures (CBOT: OZT | Underlying: ZT) +
    • +
    • + + Futures.Financials.Y30TreasuryBond + + + Futures.Financials.Y_30_TREASURY_BOND + + : 30Y U.S. Treasury Bond Futures (CBOT: OZB | Underlying: ZB) +
    • +
    • + + Futures.Grains.Corn + + + Futures.Grains.CORN + + : Corn Futures (CBOT: OZC | Underlying: ZC) +
    • +
    • + + Futures.Grains.Soybeans + + + Futures.Grains.SOYBEANS + + : Soybeans Futures (CBOT: OZS | Underlying: ZS) +
    • +
    • + + Futures.Grains.Wheat + + + Futures.Grains.WHEAT + + : Default wheat contract is SRWWheat (CBOT: OZW | Underlying: ZW) +
    • +
    • + + Futures.Indices.NASDAQ100EMini + + + Futures.Indices.NASDAQ_100_E_MINI + + : E-mini NASDAQ 100 Futures (CME: NQ) +
    • +
    • + + Futures.Indices.SP500EMini + + + Futures.Indices.SP_500_E_MINI + + : E-mini S&P 500 Futures (CME: ES) +
    • +
    • + + Futures.Metals.Copper + + + Futures.Metals.COPPER + + : Copper Futures (COMEX: HXE | Underlying: HG) +
    • +
    • + + Futures.Metals.Gold + + + Futures.Metals.GOLD + + : Gold Futures (COMEX: OG | Underlying: GC) +
    • +
    • + + Futures.Metals.Silver + + + Futures.Metals.SILVER + + : Silver Futures (COMEX: SO | Underlying: SI) +
    • +
    + + + +

    Example Applications

    + + +

    + The US Future Options dataset enables you to accurately design Future Option strategies. Examples include the following strategies: +

    +
      +
    • + Selling out of the money Future Option contracts to collect the premium that the Option buyer pays +
    • +
    • + Buying put Options to hedge against downward price movement in Future contracts you bought +
    • +
    • + Exploiting arbitrage opportunities that arise when the price of Option contracts deviate from their theoretical value +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example demonstrates a bull call spread Option strategy using universe filtering. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class FutureOptionAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Filter the underlying continuous Futures to narrow the FOP spectrum.
    +        self.underlying = self.add_future(Futures.Indices.SP_500_E_MINI,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +            contract_depth_offset=0)
    +        self.underlying.set_filter(0, 182)
    +        # Use CallSpread filter to obtain the 2 best-matched contracts that forms a call spread.
    +        # It simplifies from further filtering and reduce computation on redundant subscription.
    +        self.add_future_option(self.underlying.symbol, lambda u: u.call_spread(5, 5, -5))
    +    
    +    def on_data(self, slice: Slice) -> None:
    +        if self.portfolio.invested:
    +            return
    +        # Create canonical symbol for the mapped future contract, since we need that to access the option chain.
    +        symbol = Symbol.create_canonical_option(self.underlying.mapped)
    +    
    +        # Get option chain data for the mapped future only.
    +        # It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present.
    +        chain = slice.option_chains.get(symbol)
    +        if not chain or len(list(chain)) < 2:
    +            return
    +            
    +        # Separate the contracts by strike, as we need to access their strike.
    +        expiry = min([x.expiry for x in chain])
    +        sorted_by_strike = sorted([x.strike for x in chain])
    +        itm_strike = sorted_by_strike[0]
    +        otm_strike = sorted_by_strike[-1]
    +        
    +        # Use abstraction method to order a bull call spread to avoid manual error.
    +        option_strategy = OptionStrategies.bull_call_spread(symbol, itm_strike, otm_strike, expiry)
    +        self.buy(option_strategy, 1)
    +
    public class FutureOptionAlgorithm : QCAlgorithm
    +{
    +    private Future _underlying;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        // Filter the underlying continuous Futures to narrow the FOP spectrum.
    +        _underlying = AddFuture(Futures.Indices.SP500EMini,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.OpenInterest,
    +            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +            contractDepthOffset: 0);
    +        _underlying.SetFilter(0, 182);
    +        // Use CallSpread filter to obtain the 2 best-matched contracts that forms a call spread.
    +        // It simplifies from further filtering and reduce computation on redundant subscription.
    +        AddFutureOption(_underlying.Symbol, (u) => u.CallSpread(5, 5, -5));
    +    }
    +    
    +    public override void OnData(Slice slice)
    +    {
    +        if (Portfolio.Invested)
    +            return;
    +
    +        // Create canonical symbol for the mapped future contract, since we need that to access the option chain.
    +        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_underlying.Mapped);
    +    
    +        // Get option chain data for the mapped future only.
    +        // It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present.
    +        if (!slice.OptionChains.TryGetValue(symbol, out var chain) || chain.Count() < 2)
    +            return;
    +    
    +        // Separate the contracts by strike, as we need to access their strike.
    +        var expiry = chain.Min(x => x.Expiry);
    +        var itmStrike = chain.Min(x => x.Strike);
    +        var otmStrike = chain.Max(x => x.Strike);
    +    
    +        // Use abstraction method to order a bull call spread to avoid manual error.
    +        var optionStrategy = OptionStrategies.BullCallSpread(symbol, itmStrike, otmStrike, expiry);
    +        Buy(optionStrategy, 1);
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Future Options Universe dataset provides + + OptionFilterUniverse + + and + + OptionUniverse + + objects. +

    +

    + OptionFilterUniverse Attributes +

    +

    + + OptionFilterUniverse + + objects have the following attributes: +

    +
    +
    +

    + OptionUniverse Attributes +

    +

    + + OptionUniverse + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Future Universe

    +
    +
    +

    Introduction

    + + +

    + The US Future Universe dataset by QuantConnect lists the available US Future contracts, their daily trading volume, and Open Interest. The data covers the 157 most liquid contracts, starts in May 2009, and is delivered on daily frequency. This dataset is created by monitoring the trading activity on the CFE, CBOT, CME, COMEX, NYMEX, and ICE + + * + + . +

    +

    + This dataset depends on the + + US Futures Security Master + + dataset because the US Futures Security Master dataset contains information on symbol changes of the contracts. +

    +

    + This dataset + + does not + + contain market data. For market data, see + + US Futures by AlgoSeek + + . +

    +

    + For more information about the US Future Universe dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Future Universe dataset: +

    +
    +
    future = self.add_future(Futures.Metals.GOLD)
    +future.set_filter(0, 90)
    +
    var future = AddFuture(Futures.Metals.Gold);
    +future.SetFilter(0, 90);
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + May 2009 +
    + Asset Coverage + + 157 Futures +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + +
      +
    • + Chicago (CFE, CME or CBOT) +
    • +
    • + New York (ICE, NYMEX or COMEX) +
    • +
    +
    + Market Hours + + + Regular and Extended + +
    + + + +

    Requesting Data

    + + +

    + To add US Future Universe data to your algorithm, call the + + AddFuture + + + add_future + + method. Save a reference to the Future object so you can access the data later in your algorithm. To define which contracts should be in your universe, specify the filter when requesting the Future data. +

    +

    + The + + AddFuture + + + add_future + + method provides a daily stream of Future chain data. To get the most recent daily chain, call the + + FuturesChain + + + futures_chain + + method with the underlying Future Symbol. The + + FuturesChain + + + futures_chain + + method returns data on all the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    class USFutureDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        self._future = self.add_future(Futures.Metals.GOLD)
    +        # Set our contract filter for this Future chain.
    +        self._future.set_filter(lambda universe: universe.standards_only().front_month())
    +        # Get the entire Futures chain for the current day.
    +        chain = self.futures_chain(self._future.symbol, flatten=True).data_frame
    +
    public class USFutureDataAlgorithm : QCAlgorithm
    +{
    +    private Future _future;
    +        
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        _future = AddFuture(Futures.Metals.Gold);
    +        // Set our contract filter for this Future chain.
    +        _future.SetFilter((universe) => universe.StandardsOnly().FrontMonth());
    +        // Get the entire Futures chain for the current day.
    +        var chain = FuturesChain(_future.Symbol);
    +    }
    +}
    +
    +

    + For more information about creating US Future universes, see + + Futures + + . +

    + + + +

    Accessing Data

    + + +

    + For information about accessing US Future Universe data, see + + Futures + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Future Universe data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Future Universe data in an algorithm, call the + + History<FutureUniverse> + + + history + + method with continuous Future + + Symbol + + and a lookback period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. +

    +
    +
    # Add the Future and save a reference to it.
    +future = self.add_future(Futures.Metals.GOLD)
    +
    +# DataFrame example where the columns are the FutureUniverse attributes:
    +history_df = self.history(FutureUniverse, future.symbol, 5, flatten=True)
    +
    +# Series example where the values are lists of FutureUniverse objects: 
    +history_series = self.history(FutureUniverse, future.symbol, 5, flatten=False)
    +
    +# FutureUniverse objects example:
    +history = self.history[FutureUniverse](future.symbol, 5)
    +
    // Add the Future and save a reference to it.
    +var future = AddFuture(Futures.Metals.Gold);
    +
    +// Get historical data.
    +var history = History<FutureUniverse>(future.Symbol, 5);
    +
    +

    + For more information about historical US Future Universe data in algorithms, see + + Contracts + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Future Universe data in the Research Environment, call the + + History<FutureUniverse> + + + history + + method with continuous Future + + Symbol + + and a time period. This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter. If there is no data for the period you requested, the history result is empty. +

    +
    +
    # Add the Future and save a reference to it.
    +future = qb.add_future(Futures.Metals.GOLD)
    +
    +# DataFrame example where the columns are the FutureUniverse attributes:
    +history_df = qb.history(FutureUniverse, future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1), flatten=True)
    +
    +# Series example where the values are lists of FutureUniverse objects: 
    +history_series = qb.history(FutureUniverse, future.symbol, 5, flatten=False)
    +
    +# FutureUniverse objects example:
    +history = qb.history[FutureUniverse](future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1))
    +
    // Add the Future and save a reference to it.
    +var future = qb.AddFuture(Futures.Metals.Gold);
    +
    +// Get historical data.
    +var history = qb.History<FutureUniverse>(future.Symbol, new DateTime(2025, 1, 1), new DateTime(2025, 4, 1));
    +
    +

    + For more information about historical US Future Universe data in the Research Environment, see + + Daily Prices History + + . +

    + + + +

    Supported Assets

    + + +

    + The following list shows the available (157) Futures: +

    +
      +
    • + + Futures.Currencies.AUD + + : Australian Dollar Futures (CME: 6A) +
    • +
    • + + Futures.Currencies.AUDCAD + + : Australian Dollar/Canadian Dollar Futures (CME: ACD) +
    • +
    • + + Futures.Currencies.AUDJPY + + : Australian Dollar/Japanese Yen Futures (CME: AJY) +
    • +
    • + + Futures.Currencies.AUDNZD + + : Australian Dollar/New Zealand Dollar Futures (CME: ANE) +
    • +
    • + + Futures.Currencies.BRL + + : Brazillian Real Futures (CME: 6L) +
    • +
    • + + Futures.Currencies.BTC + + : Bitcoin Futures (CME: BTC) +
    • +
    • + + Futures.Currencies.BTICMicroBTC + + + Futures.Currencies.BTIC_MICRO_BTC + + : BTIC on Micro Bitcoin Futures (CME: MIB) +
    • +
    • + + Futures.Currencies.BTICMicroEther + + + Futures.Currencies.BTIC_MICRO_ETHER + + : BTIC on Micro Ether Futures (CME: MRB) +
    • +
    • + + Futures.Currencies.CAD + + : Canadian Dollar Futures (CME: 6C) +
    • +
    • + + Futures.Currencies.CADJPY + + : Canadian Dollar/Japanese Yen Futures (CME: CJY) +
    • +
    • + + Futures.Currencies.CHF + + : Swiss Franc Futures (CME: 6S) +
    • +
    • + + Futures.Currencies.ETH + + : Ether Futures (CME: ETH) +
    • +
    • + + Futures.Currencies.EUR + + : Euro FX Futures (CME: 6E) +
    • +
    • + + Futures.Currencies.EURAUD + + : Euro/Australian Dollar Futures (CME: EAD) +
    • +
    • + + Futures.Currencies.EURCAD + + : Euro/Canadian Dollar Futures (CME: ECD) +
    • +
    • + + Futures.Currencies.EuroFXEmini + + + Futures.Currencies.EURO_FX_EMINI + + : E-mini Euro FX Futures (CME: E7) +
    • +
    • + + Futures.Currencies.EURSEK + + : Euro/Swedish Krona Futures (CME: ESK) +
    • +
    • + + Futures.Currencies.GBP + + : British Pound Futures (CME: 6B) +
    • +
    • + + Futures.Currencies.JapaneseYenEmini + + + Futures.Currencies.JAPANESE_YEN_EMINI + + : E-mini Japanese Yen Futures (CME: J7) +
    • +
    • + + Futures.Currencies.JPY + + : Japanese Yen Futures (CME: 6J) +
    • +
    • + + Futures.Currencies.MicroAUD + + + Futures.Currencies.MICRO_AUD + + : Micro AUD/USD Futures (CME: M6A) +
    • +
    • + + Futures.Currencies.MicroBTC + + + Futures.Currencies.MICRO_BTC + + : Micro Bitcoin Futures (CME: MBT) +
    • +
    • + + Futures.Currencies.MicroCAD + + + Futures.Currencies.MICRO_CAD + + : Micro USD/CAD Futures (CME: M6C) +
    • +
    • + + Futures.Currencies.MicroCADUSD + + + Futures.Currencies.MICRO_CADUSD + + : Micro CAD/USD Futures (CME: MCD) +
    • +
    • + + Futures.Currencies.MicroCHF + + + Futures.Currencies.MICRO_CHF + + : Micro CHF/USD Futures (CME: MSF) +
    • +
    • + + Futures.Currencies.MicroEther + + + Futures.Currencies.MICRO_ETHER + + : Micro Ether Futures (CME: MET) +
    • +
    • + + Futures.Currencies.MicroEUR + + + Futures.Currencies.MICRO_EUR + + : Micro EUR/USD Futures (CME: M6E) +
    • +
    • + + Futures.Currencies.MicroGBP + + + Futures.Currencies.MICRO_GBP + + : Micro GBP/USD Futures (CME: M6B) +
    • +
    • + + Futures.Currencies.MicroINRUSD + + + Futures.Currencies.MICRO_INRUSD + + : Micro INR/USD Futures (CME: MIR) +
    • +
    • + + Futures.Currencies.MicroJPY + + + Futures.Currencies.MICRO_JPY + + : Micro JPY/USD Futures (CME: MJY) +
    • +
    • + + Futures.Currencies.MicroUSDCHF + + + Futures.Currencies.MICRO_USDCHF + + : Micro USD/CHF Futures (CME: M6S) +
    • +
    • + + Futures.Currencies.MicroUSDCNH + + + Futures.Currencies.MICRO_USDCNH + + : Micro USD/CNH Futures (CME: MNH) +
    • +
    • + + Futures.Currencies.MicroUSDJPY + + + Futures.Currencies.MICRO_USDJPY + + : Micro USD/JPY Futures (CME: M6J) +
    • +
    • + + Futures.Currencies.MXN + + : Mexican Peso Futures (CME: 6M) +
    • +
    • + + Futures.Currencies.NZD + + : New Zealand Dollar Futures (CME: 6N) +
    • +
    • + + Futures.Currencies.RUB + + : Russian Ruble Futures (CME: 6R) +
    • +
    • + + Futures.Currencies.StandardSizeUSDOffshoreRMBCNH + + + Futures.Currencies.STANDARD_SIZE_USD_OFFSHORE_RMBCNH + + : Standard-Size USD/Offshore RMB (CNH) Futures (CME: CNH) +
    • +
    • + + Futures.Currencies.ZAR + + : South African Rand Futures (CME: 6Z) +
    • +
    • + + Futures.Energy.ArgusLLSvsWTIArgusTradeMonth + + + Futures.Energy.ARGUS_LL_SVS_WTI_ARGUS_TRADE_MONTH + + : Argus LLS vs. WTI (Argus) Trade Month Futures (NYMEX: AE5) +
    • +
    • + + Futures.Energy.ArgusPropaneFarEastIndex + + + Futures.Energy.ARGUS_PROPANE_FAR_EAST_INDEX + + : Argus Propane Far East Index Futures (NYMEX: A7E) +
    • +
    • + + Futures.Energy.ArgusPropaneSaudiAramco + + + Futures.Energy.ARGUS_PROPANE_SAUDI_ARAMCO + + : Argus Propane (Saudi Aramco) Futures (NYMEX: A9N) +
    • +
    • + + Futures.Energy.BrentCrudeOilVsDubaiCrudeOilPlatts + + + Futures.Energy.BRENT_CRUDE_OIL_VS_DUBAI_CRUDE_OIL_PLATTS + + : Brent Crude Oil vs. Dubai Crude Oil (Platts) Futures (NYMEX: ADB) +
    • +
    • + + Futures.Energy.BrentLastDayFinancial + + + Futures.Energy.BRENT_LAST_DAY_FINANCIAL + + : Brent Last Day Financial Futures (NYMEX: BZ) +
    • +
    • + + Futures.Energy.ChicagoEthanolPlatts + + + Futures.Energy.CHICAGO_ETHANOL_PLATTS + + : Chicago Ethaanol (Platts) Futures (NYMEX: CU) +
    • +
    • + + Futures.Energy.ConwayPropaneOPIS + + + Futures.Energy.CONWAY_PROPANE_OPIS + + : Conway Propane (OPIS) Futures (NYMEX: A8K) +
    • +
    • + + Futures.Energy.CrudeOilWTI + + + Futures.Energy.CRUDE_OIL_WTI + + : Crude Oil WTI Futures (NYMEX: CL) +
    • +
    • + + Futures.Energy.DubaiCrudeOilPlattsFinancial + + + Futures.Energy.DUBAI_CRUDE_OIL_PLATTS_FINANCIAL + + : Dubai Crude Oil (Platts) Financial Futures (NYMEX: DCB) +
    • +
    • + + Futures.Energy.EastWestGasolineSpreadPlattsArgus + + + Futures.Energy.EAST_WEST_GASOLINE_SPREAD_PLATTS_ARGUS + + : East-West Gasoline Spread (Platts-Argus) Futures (NYMEX: EWG) +
    • +
    • + + Futures.Energy.EastWestNaphthaJapanCFvsCargoesCIFNWESpreadPlatts + + + Futures.Energy.EAST_WEST_NAPHTHA_JAPAN_C_FVS_CARGOES_CIFNWE_SPREAD_PLATTS + + : East-West Naphtha: Japan C&F vs. Cargoes CIF NWE Spread (Platts) Futures (NYMEX: EWN) +
    • +
    • + + Futures.Energy.Ethanol + + + Futures.Energy.ETHANOL + + : Ethanol Futures (CBOT: EH) +
    • +
    • + + Futures.Energy.EthanolT2FOBRdamIncludingDutyPlatts + + + Futures.Energy.ETHANOL_T_2_FOB_RDAM_INCLUDING_DUTY_PLATTS + + : Ethanol T2 FOB Rdam Including Duty (Platts) Futures (NYMEX: AZ1) +
    • +
    • + + Futures.Energy.EuropeanNaphthaPlattsCrackSpread + + + Futures.Energy.EUROPEAN_NAPHTHA_PLATTS_CRACK_SPREAD + + : European Naphtha (Platts) Crack Spread Futures (NYMEX: EN) +
    • +
    • + + Futures.Energy.EuropeanPropaneCIFARAArgus + + + Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS + + : European Propane CIF ARA (Argus) Futures (NYMEX: APS) +
    • +
    • + + Futures.Energy.EuropeanPropaneCIFARAArgusVsNaphthaCargoesCIFNWEPlatts + + + Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS_VS_NAPHTHA_CARGOES_CIFNWE_PLATTS + + : European Propane CIF ARA (Argus) vs. Naphtha Cargoes CIF NWE (Platts) Futures (NYMEX: EPN) +
    • +
    • + + Futures.Energy.FreightRouteTC14Baltic + + + Futures.Energy.FREIGHT_ROUTE_TC_14_BALTIC + + : Freight Route TC14 (Baltic) Futures (NYMEX: FRC) +
    • +
    • + + Futures.Energy.Gasoline + + + Futures.Energy.GASOLINE + + : Gasoline RBOB Futures (NYMEX: RB) +
    • +
    • + + Futures.Energy.GasolineEurobobOxyNWEBargesArgus + + + Futures.Energy.GASOLINE_EUROBOB_OXY_NWE_BARGES_ARGUS + + : Gasoline Euro-bob Oxy NWE Barges (Argus) Futures (NYMEX: B7H) +
    • +
    • + + Futures.Energy.GroupThreeSuboctaneGasolinePlattsVsRBOB + + + Futures.Energy.GROUP_THREE_SUBOCTANE_GASOLINE_PLATTS_VS_RBOB + + : Group Three Sub-octane Gasoliine (Platts) vs. RBOB Futures (NYMEX: AA8) +
    • +
    • + + Futures.Energy.GroupThreeULSDPlattsVsNYHarborULSD + + + Futures.Energy.GROUP_THREE_ULSD_PLATTS_VS_NY_HARBOR_ULSD + + : Group Three ULSD (Platts) vs. NY Harbor ULSD Futures (NYMEX: AA6) +
    • +
    • + + Futures.Energy.GulfCoastCBOBGasolineA2PlattsVsRBOBGasoline + + + Futures.Energy.GULF_COAST_CBOB_GASOLINE_A_2_PLATTS_VS_RBOB_GASOLINE + + : Gulf Coast CBOB Gasoline A2 (Platts) vs. RBOB Gasoline Futures (NYMEX: CRB) +
    • +
    • + + Futures.Energy.GulfCoastHSFOPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.GULF_COAST_HSFO_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : Gulf Coast HSFO (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: GCU) +
    • +
    • + + Futures.Energy.HeatingOil + + + Futures.Energy.HEATING_OIL + + : Heating Oil Futures (NYMEX: HO) +
    • +
    • + + Futures.Energy.LosAngelesCARBOBGasolineOPISvsRBOBGasoline + + + Futures.Energy.LOS_ANGELES_CARBOB_GASOLINE_OPI_SVS_RBOB_GASOLINE + + : Los Angeles CARBOB Gasoline (OPIS) vs. RBOB Gasoline Futures (NYMEX: AJL) +
    • +
    • + + Futures.Energy.LosAngelesCARBDieselOPISvsNYHarborULSD + + + Futures.Energy.LOS_ANGELES_CARB_DIESEL_OPI_SVS_NY_HARBOR_ULSD + + : Los Angeles CARB Diesel (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AKL) +
    • +
    • + + Futures.Energy.LosAngelesJetOPISvsNYHarborULSD + + + Futures.Energy.LOS_ANGELES_JET_OPI_SVS_NY_HARBOR_ULSD + + : Los Angeles Jet (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AJS) +
    • +
    • + + Futures.Energy.MarsArgusVsWTIFinancial + + + Futures.Energy.MARS_ARGUS_VS_WTI_FINANCIAL + + : Mars (Argus) vs. WTI Financial Futures (NYMEX: AYX) +
    • +
    • + + Futures.Energy.MarsArgusVsWTITradeMonth + + + Futures.Energy.MARS_ARGUS_VS_WTI_TRADE_MONTH + + : Mars (Argus) vs. WTI Trade Month Futures (NYMEX: AYV) +
    • +
    • + + Futures.Energy.MicroCrudeOilWTI + + + Futures.Energy.MICRO_CRUDE_OIL_WTI + + : Micro WTI Crude Oil Futures (NYMEX: MCL) +
    • +
    • + + Futures.Energy.MicroEuropeanFOBRdamMarineFuelZeroPointFivePercentBargesPlatts + + + Futures.Energy.MICRO_EUROPEAN_FOB_RDAM_MARINE_FUEL_ZERO_POINT_FIVE_PERCENT_BARGES_PLATTS + + : Micro European FOB Rdam Marine Fuel 0.5% Barges (Platts) Futures (NYMEX: R5O) +
    • +
    • + + Futures.Energy.MicroEuropeanThreePointFivePercentOilBargesFOBRdamPlatts + + + Futures.Energy.MICRO_EUROPEAN_THREE_POINT_FIVE_PERCENT_OIL_BARGES_FOB_RDAM_PLATTS + + : Micro European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: MEF) +
    • +
    • + + Futures.Energy.MicroGasoilZeroPointOnePercentBargesFOBARAPlatts + + + Futures.Energy.MICRO_GASOIL_ZERO_POINT_ONE_PERCENT_BARGES_FOBARA_PLATTS + + : Micro Gasoil 0.1% Barges FOB ARA (Platts) Futures (NYMEX: M1B) +
    • +
    • + + Futures.Energy.MicroSingaporeFOBMarineFuelZeroPointFivePercetPlatts + + + Futures.Energy.MICRO_SINGAPORE_FOB_MARINE_FUEL_ZERO_POINT_FIVE_PERCET_PLATTS + + : Micro Singapore FOB Marine Fuel 0.5% (Platts) Futures (NYMEX: S5O) +
    • +
    • + + Futures.Energy.MicroSingaporeFuelOil380CSTPlatts + + + Futures.Energy.MICRO_SINGAPORE_FUEL_OIL_380_CST_PLATTS + + : Micro Singapore Fuel Oil 380CST (Platts) Futures (NYMEX: MAF) +
    • +
    • + + Futures.Energy.MiniEuropeanThreePointPercentFiveFuelOilBargesPlatts + + + Futures.Energy.MINI_EUROPEAN_THREE_POINT_PERCENT_FIVE_FUEL_OIL_BARGES_PLATTS + + : Mini European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: A0D) +
    • +
    • + + Futures.Energy.MiniSingaporeFuelOil180CstPlatts + + + Futures.Energy.MINI_SINGAPORE_FUEL_OIL_180_CST_PLATTS + + : Mini Singapore Fuel Oil 180 cst (Platts) Futures (NYMEX: A0F) +
    • +
    • + + Futures.Energy.MontBelvieuEthaneOPIS + + + Futures.Energy.MONT_BELVIEU_ETHANE_OPIS + + : Mont Belvieu Ethane (OPIS) Futures (NYMEX: AC0) +
    • +
    • + + Futures.Energy.MontBelvieuLDHPropaneOPIS + + + Futures.Energy.MONT_BELVIEU_LDH_PROPANE_OPIS + + : Mont Belvieu LDH Propane (OPIS) Futures (NYMEX: B0) +
    • +
    • + + Futures.Energy.MontBelvieuNaturalGasolineOPIS + + + Futures.Energy.MONT_BELVIEU_NATURAL_GASOLINE_OPIS + + : Mont Belvieu Natural Gasoline (OPIS) Futures (NYMEX: A7Q) +
    • +
    • + + Futures.Energy.MontBelvieuNormalButaneOPIS + + + Futures.Energy.MONT_BELVIEU_NORMAL_BUTANE_OPIS + + : Mont Belvieu Normal Butane (OPIS) Futures (NYMEX: AD0) +
    • +
    • + + Futures.Energy.NaturalGas + + + Futures.Energy.NATURAL_GAS + + : Natural Gas Futures (NYMEX: NG) +
    • +
    • + + Futures.Energy.NaturalGasHenryHubLastDayFinancial + + + Futures.Energy.NATURAL_GAS_HENRY_HUB_LAST_DAY_FINANCIAL + + : Natural Gas (Henry Hub) Last-day Financial Futures (NYMEX: HH) +
    • +
    • + + Futures.Energy.NaturalGasHenryHubPenultimateFinancial + + + Futures.Energy.NATURAL_GAS_HENRY_HUB_PENULTIMATE_FINANCIAL + + : Natural Gas (Henry Hub) Penultimate Financial Futures (NYMEX: HP) +
    • +
    • + + Futures.Energy.OnePercentFuelOilCargoesFOBNWEPlattsVsThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.ONE_PERCENT_FUEL_OIL_CARGOES_FOBNWE_PLATTS_VS_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : 1% Fuel Oil Cargoes FOB NWE (Platts) vs. 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: FSS) +
    • +
    • + + Futures.Energy.PremiumUnleadedGasoline10ppmFOBMEDPlatts + + + Futures.Energy.PREMIUM_UNLEADED_GASOLINE_10_PPM_FOBMED_PLATTS + + : Premium Unleaded Gasoline 10 ppm FOB MED (Platts) Futures (NYMEX: A3G) +
    • +
    • + + Futures.Energy.PropaneNonLDHMontBelvieuOPIS + + + Futures.Energy.PROPANE_NON_LDH_MONT_BELVIEU_OPIS + + : Propane Non-LDH Mont Belvieu (OPIS) Futures (NYMEX: A1R) +
    • +
    • + + Futures.Energy.RBOBGasolineCrackSpread + + + Futures.Energy.RBOB_GASOLINE_CRACK_SPREAD + + : RBOB Gasoline Crack Spread Futures (NYMEX: ARE) +
    • +
    • + + Futures.Energy.RBOBGasolineVsEurobobOxyNWEBargesArgusThreeHundredFiftyThousandGallons + + + Futures.Energy.RBOB_GASOLINE_VS_EUROBOB_OXY_NWE_BARGES_ARGUS_THREE_HUNDRED_FIFTY_THOUSAND_GALLONS + + : RBOB Gasoline vs. Euro-bob Oxy NWE Barges (Argus) (350,000 gallons) Futures (NYMEX: EXR) +
    • +
    • + + Futures.Energy.SingaporeFuelOil380cstPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.SINGAPORE_FUEL_OIL_380_CST_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : Singapore Fuel Oil 380 cst (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: EVC) +
    • +
    • + + Futures.Energy.SingaporeGasoilPlattsVsLowSulphurGasoilFutures + + + Futures.Energy.SINGAPORE_GASOIL_PLATTS_VS_LOW_SULPHUR_GASOIL_FUTURES + + : Singapore Gasoil (Platts) vs. Low Sulphur Gasoil Futures (NYMEX: AGA) +
    • +
    • + + Futures.Energy.SingaporeMogas92UnleadedPlattsBrentCrackSpread + + + Futures.Energy.SINGAPORE_MOGAS_92_UNLEADED_PLATTS_BRENT_CRACK_SPREAD + + : Singapore Mogas 92 Unleaded (Platts) Brent Crack Spread Futures (NYMEX: D1N) +
    • +
    • + + Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread + + + Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD + + : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread Futures (NYMEX: FO) +
    • +
    • + + Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread1000mt + + + Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD_1000_MT + + : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread (1000mt) Futures (NYMEX: BOO) +
    • +
    • + + Futures.Energy.WTIBrentFinancial + + + Futures.Energy.WTI_BRENT_FINANCIAL + + : WTI-Brent Financial Futures (NYMEX: BK) +
    • +
    • + + Futures.Energy.WTIFinancial + + + Futures.Energy.WTI_FINANCIAL + + : WTI Financial Futures (NYMEX: CSX) +
    • +
    • + + Futures.Energy.WTIHoustonArgusVsWTITradeMonth + + + Futures.Energy.WTI_HOUSTON_ARGUS_VS_WTI_TRADE_MONTH + + : WTI Houston (Argus) vs. WTI Trade Month Futures (NYMEX: HTT) +
    • +
    • + + Futures.Energy.WTIHoustonCrudeOil + + + Futures.Energy.WTI_HOUSTON_CRUDE_OIL + + : WTI Houston Crude Oil Futures (NYMEX: HCL) +
    • +
    • + + Futures.Financials.EuroDollar + + + Futures.Financials.EURO_DOLLAR + + : EuroDollar Futures (CME: GE) +
    • +
    • + + Futures.Financials.FiveYearUSDMACSwap + + + Futures.Financials.FIVE_YEAR_USDMAC_SWAP + + : 5-Year USD MAC Swap Futures (CBOT: F1U) +
    • +
    • + + Futures.Financials.MicroY10TreasuryNote + + + Futures.Financials.MICRO_Y_10_TREASURY_NOTE + + : Micro 10-Year Yield Futures (CBOT: 10Y) +
    • +
    • + + Futures.Financials.MicroY2TreasuryBond + + + Futures.Financials.MICRO_Y_2_TREASURY_BOND + + : Micro 2-Year Yield Futures (CBOT: 2YY) +
    • +
    • + + Futures.Financials.MicroY30TreasuryBond + + + Futures.Financials.MICRO_Y_30_TREASURY_BOND + + : Micro 30-Year Yield Futures (CBOT: 30Y) +
    • +
    • + + Futures.Financials.MicroY5TreasuryBond + + + Futures.Financials.MICRO_Y_5_TREASURY_BOND + + : Micro 5-Year Yield Futures (CBOT: 5YY) +
    • +
    • + + Futures.Financials.UltraTenYearUSTreasuryNote + + + Futures.Financials.ULTRA_TEN_YEAR_US_TREASURY_NOTE + + : Ultra 10-Year U.S. Treasury Note Futures (CBOT: TN) +
    • +
    • + + Futures.Financials.UltraUSTreasuryBond + + + Futures.Financials.ULTRA_US_TREASURY_BOND + + : Ultra U.S. Treasury Bond Futures (CBOT: UB) +
    • +
    • + + Futures.Financials.Y10TreasuryNote + + + Futures.Financials.Y_10_TREASURY_NOTE + + : 10Y U.S. Treasury Note Futures (CBOT: ZN) +
    • +
    • + + Futures.Financials.Y2TreasuryNote + + + Futures.Financials.Y_2_TREASURY_NOTE + + : 2Y U.S. Treasury Note Futures (CBOT: ZT) +
    • +
    • + + Futures.Financials.Y30TreasuryBond + + + Futures.Financials.Y_30_TREASURY_BOND + + : 30Y U.S. Treasury Bond Futures (CBOT: ZB) +
    • +
    • + + Futures.Financials.Y5TreasuryNote + + + Futures.Financials.Y_5_TREASURY_NOTE + + : 5Y U.S. Treasury Note Futures (CBOT: ZF) +
    • +
    • + + Futures.Forestry.Lumber + + + Futures.Forestry.LUMBER + + : Lumber Futures (CME: LBR) +
    • +
    • + + Futures.Forestry.RandomLengthLumber + + + Futures.Forestry.RANDOM_LENGTH_LUMBER + + : Random Length Lumber Futures (CME: LBS) +
    • +
    • + + Futures.Grains.BlackSeaCornFinanciallySettledPlatts + + + Futures.Grains.BLACK_SEA_CORN_FINANCIALLY_SETTLED_PLATTS + + : Black Sea Corn Financially Settled (Platts) Futures (CBOT: BCF) +
    • +
    • + + Futures.Grains.BlackSeaWheatFinanciallySettledPlatts + + + Futures.Grains.BLACK_SEA_WHEAT_FINANCIALLY_SETTLED_PLATTS + + : Black Sea Wheat Financially Settled (Platts) Futures (CBOT: BWF) +
    • +
    • + + Futures.Grains.Corn + + + Futures.Grains.CORN + + : Corn Futures (CBOT: ZC) +
    • +
    • + + Futures.Grains.HRWWheat + + + Futures.Grains.HRW_WHEAT + + : KC HRW Wheat Futures (CBOT: KE) +
    • +
    • + + Futures.Grains.Oats + + + Futures.Grains.OATS + + : Oats Futures (CBOT: ZO) +
    • +
    • + + Futures.Grains.Soybeans + + + Futures.Grains.SOYBEANS + + : Soybeans Futures (CBOT: ZS) +
    • +
    • + + Futures.Grains.SoybeanMeal + + + Futures.Grains.SOYBEAN_MEAL + + : Soybean Meal Futures (CBOT: ZM) +
    • +
    • + + Futures.Grains.SoybeanOil + + + Futures.Grains.SOYBEAN_OIL + + : Soybean Oil Futures (CBOT: ZL) +
    • +
    • + + Futures.Grains.Wheat + + + Futures.Grains.WHEAT + + : Default wheat contract is SRWWheat (CBOT: ZW) +
    • +
    • + + Futures.Indices.BloombergCommodityIndex + + + Futures.Indices.BLOOMBERG_COMMODITY_INDEX + + : Bloomberg Commodity Index Futures (CBOT: AW) +
    • +
    • + + Futures.Indices.Dow30EMini + + + Futures.Indices.DOW_30_E_MINI + + : E-mini Dow Indu 30 Futures (CBOT: YM) +
    • +
    • + + Futures.Indices.DowJonesRealEstate + + + Futures.Indices.DOW_JONES_REAL_ESTATE + + : Dow Jones Real Estate futures on CME (CME: RX) +
    • +
    • + + Futures.Indices.FTSEEmergingEmini + + + Futures.Indices.FTSE_EMERGING_EMINI + + : E-mini FTSE Emerging Index Futures (CME: EI) +
    • +
    • + + Futures.Indices.MicroDow30EMini + + + Futures.Indices.MICRO_DOW_30_E_MINI + + : Micro E-mini Dow Jones Industrial Average Index Futures (CBOT: MYM) +
    • +
    • + + Futures.Indices.MicroNASDAQ100EMini + + + Futures.Indices.MICRO_NASDAQ_100_E_MINI + + : Micro E-mini Nasdaq-100 Index Futures (CME: MNQ) +
    • +
    • + + Futures.Indices.MicroRussell2000EMini + + + Futures.Indices.MICRO_RUSSELL_2000_E_MINI + + : Micro E-mini Russell 2000 Index Futures (CME: M2K) +
    • +
    • + + Futures.Indices.MicroSP500EMini + + + Futures.Indices.MICRO_SP_500_E_MINI + + : Micro E-mini S&P 500 Index Futures (CME: MES) +
    • +
    • + + Futures.Indices.NASDAQ100BiotechnologyEMini + + + Futures.Indices.NASDAQ_100_BIOTECHNOLOGY_E_MINI + + : E-mini Nasdaq-100 Biotechnology Index Futures (CME: BIO) +
    • +
    • + + Futures.Indices.NASDAQ100EMini + + + Futures.Indices.NASDAQ_100_E_MINI + + : E-mini NASDAQ 100 Futures (CME: NQ) +
    • +
    • + + Futures.Indices.Nikkei225Dollar + + + Futures.Indices.NIKKEI_225_DOLLAR + + : Nikkei-225 Dollar Futures (CME: NKD) +
    • +
    • + + Futures.Indices.Nikkei225YenCME + + + Futures.Indices.NIKKEI_225_YEN_CME + + : Nikkei-225 Yen denominated Futures on CME (CME: NIY) +
    • +
    • + + Futures.Indices.Russell1000EMini + + + Futures.Indices.RUSSELL_1000_E_MINI + + : E-mini Russell 1000 futures on CME (CME: RS1) +
    • +
    • + + Futures.Indices.Russell2000EMini + + + Futures.Indices.RUSSELL_2000_E_MINI + + : E-mini Russell 2000 Futures (CME: RTY) +
    • +
    • + + Futures.Indices.SPGSCICommodity + + + Futures.Indices.SPGSCI_COMMODITY + + : S&P-GSCI Commodity Index Futures (CME: GD) +
    • +
    • + + Futures.Indices.SP400MidCapEmini + + + Futures.Indices.SP_400_MID_CAP_EMINI + + : E-mini S&P MidCap 400 Futures (CME: EMD) +
    • +
    • + + Futures.Indices.SP500AnnualDividendIndex + + + Futures.Indices.SP_500_ANNUAL_DIVIDEND_INDEX + + : (CME: SDA) +
    • +
    • + + Futures.Indices.SP500EMini + + + Futures.Indices.SP_500_E_MINI + + : E-mini S&P 500 Futures (CME: ES) +
    • +
    • + + Futures.Indices.TOPIXYEN + + : YEN Denominated Topix Index Futures on CME (CME: TPY) +
    • +
    • + + Futures.Indices.USDDenominatedIbovespa + + + Futures.Indices.USD_DENOMINATED_IBOVESPA + + : USD-Denominated Ibovespa Index Futures (CME: IBV) +
    • +
    • + + Futures.Indices.VIX + + : CBOE Volatility Index Futures (CFE: VX) +
    • +
    • + + Futures.Meats.FeederCattle + + + Futures.Meats.FEEDER_CATTLE + + : Feeder Cattle Futures (CME: GF) +
    • +
    • + + Futures.Meats.LeanHogs + + + Futures.Meats.LEAN_HOGS + + : Lean Hogs Futures (CME: HE) +
    • +
    • + + Futures.Meats.LiveCattle + + + Futures.Meats.LIVE_CATTLE + + : Live Cattle Futures (CME: LE) +
    • +
    • + + Futures.Metals.AluminiumEuropeanPremiumDutyPaidMetalBulletin + + + Futures.Metals.ALUMINIUM_EUROPEAN_PREMIUM_DUTY_PAID_METAL_BULLETIN + + : Aluminium European Premium Duty-Paid (Metal Bulletin) Futures (COMEX: EDP) +
    • +
    • + + Futures.Metals.AluminumMWUSTransactionPremiumPlatts25MT + + + Futures.Metals.ALUMINUM_MWUS_TRANSACTION_PREMIUM_PLATTS_25_MT + + : Aluminum MW U.S. Transaction Premium Platts (25MT) Futures (COMEX: AUP) +
    • +
    • + + Futures.Metals.Copper + + + Futures.Metals.COPPER + + : Copper Futures (COMEX: HG) +
    • +
    • + + Futures.Metals.Gold + + + Futures.Metals.GOLD + + : Gold Futures (COMEX: GC) +
    • +
    • + + Futures.Metals.MicroGold + + + Futures.Metals.MICRO_GOLD + + : Micro Gold Futures (COMEX: MGC) +
    • +
    • + + Futures.Metals.MicroGoldTAS + + + Futures.Metals.MICRO_GOLD_TAS + + : Micro Gold TAS Futures (COMEX: MGT) +
    • +
    • + + Futures.Metals.MicroPalladium + + + Futures.Metals.MICRO_PALLADIUM + + : Micro Palladium Futures (NYMEX: PAM) +
    • +
    • + + Futures.Metals.MicroSilver + + + Futures.Metals.MICRO_SILVER + + : Micro Silver Futures (COMEX: SIL) +
    • +
    • + + Futures.Metals.Palladium + + + Futures.Metals.PALLADIUM + + : Palladium Futures (NYMEX: PA) +
    • +
    • + + Futures.Metals.Platinum + + + Futures.Metals.PLATINUM + + : Platinum Futures (NYMEX: PL) +
    • +
    • + + Futures.Metals.Silver + + + Futures.Metals.SILVER + + : Silver Futures (COMEX: SI) +
    • +
    • + + Futures.Metals.USMidwestDomesticHotRolledCoilSteelCRUIndex + + + Futures.Metals.US_MIDWEST_DOMESTIC_HOT_ROLLED_COIL_STEEL_CRU_INDEX + + : U.S. Midwest Domestic Hot-Rolled Coil Steel (CRU) Index Futures (NYMEX: HRC) +
    • +
    • + + Futures.Softs.Sugar11 + + + Futures.Softs.SUGAR_11 + + : Sugar #11 Futures ICE (ICE: SB) +
    • +
    • + + Futures.Softs.Sugar11CME + + + Futures.Softs.SUGAR_11_CME + + : Sugar #11 Futures CME (NYMEX: YO) +
    • +
    + + + +

    Example Applications

    + + +

    + The US Future Universe dataset enables you to accurately design Futures strategies. Examples include the following strategies: +

    +
      +
    • + Buying the Futures contract with the most open interest to reduce slippage and market impact +
    • +
    • + Trading bull calendar spreads to reduce volatility and margin requirements +
    • +
    • + Trading bull calendar spreads to speculate contango +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm selects and buys the front-month Mini Gold Futures contract and sells the front-month Micro Gold Futures contract. When the front-month contract changes, the algorithm rebalances the portfolio. +

    +
    +
    from AlgorithmImports import *
    +
    +class USFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1000000) 
    +        self.universe_settings.asynchronous = True
    +        # Requesting data on gold and micro-gold contracts.
    +        # Filter the universe to trade only the contracts expiring within 90 days to ensure liquidity.
    +        self.mini_gold = self.add_future(Futures.Metals.GOLD) 
    +        self.mini_gold.set_filter(0, 90)
    +        
    +        self.micro_gold = self.add_future(Futures.Metals.MICRO_GOLD) 
    +        self.micro_gold.set_filter(0, 90)
    +        
    +        # Save a cache of the mapped symbol to trade.
    +        self.contract = {self.mini_gold.symbol: None, self.micro_gold.symbol: None}
    +    
    +    def on_data(self, slice: Slice) -> None:
    +        for symbol, chain in slice.future_chains.items():
    +            if symbol in self.contract:
    +                # Select the contract with the greatest open interest to trade with the most efficiency.
    +                most_liquid_contract = sorted(chain, key=lambda contract: contract.open_interest, reverse=True)[0]
    +                
    +                if self.contract[symbol] is None or most_liquid_contract.symbol != self.contract[symbol].symbol:
    +                    # Liquidate any unmapped contracts.
    +                    if self.contract[symbol] is not None:
    +                        self.liquidate(self.contract[symbol].symbol)
    +                    self.contract[symbol] = most_liquid_contract
    +                    
    +                    # Buy mini-gold and short micro-gold contracts as planned.
    +                    if symbol == self.mini_gold.symbol:
    +                        self.market_order(self.contract[symbol].symbol, 1)
    +                    elif symbol == self.micro_gold.symbol:
    +                        self.market_order(self.contract[symbol].symbol, -1)
    +
    public class USFuturesDataAlgorithm : QCAlgorithm
    +{
    +    private Future _miniGold;
    +    private Future _microGold;
    +    // Save a cache of the mapped symbol to trade.
    +    private Dictionary<Symbol, FuturesContract?> _contract = new ();
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000000);
    +        UniverseSettings.Asynchronous = true;
    +
    +        // Requesting data on gold and micro-gold contracts.
    +        // Filter the universe to trade only the contracts expiring within 90 days to ensure liquidity.
    +        _miniGold = AddFuture(Futures.Metals.Gold);
    +        _miniGold.SetFilter(0, 90);
    +        _contract.Add(_miniGold.Symbol, null);
    +        
    +        _microGold = AddFuture(Futures.Metals.MicroGold);
    +        _microGold.SetFilter(0, 90);
    +        _contract.Add(_microGold.Symbol, null);
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        foreach (var (symbol, chain) in slice.FutureChains)
    +        {
    +            if (_contract.ContainsKey(symbol))
    +            {
    +                // Select the contract with the greatest open interest to trade with the most efficiency.
    +                var mostLiquidContract = chain.OrderBy(x => x.OpenInterest).Last();
    +                
    +                if (_contract[symbol] == null || mostLiquidContract.Symbol != _contract[symbol].Symbol)
    +                {
    +                    // Liquidate any unmapped contracts.
    +                    if (_contract[symbol] != null)
    +                    {
    +                        Liquidate(_contract[symbol].Symbol);
    +                    }
    +                    _contract[symbol] = mostLiquidContract;
    +
    +                    // Buy mini-gold and short micro-gold contracts as planned.
    +                    if (symbol == _miniGold.Symbol)
    +                    {
    +                        MarketOrder(_contract[symbol].Symbol, 1);
    +                    }
    +                    else if (symbol == _microGold.Symbol)
    +                    {
    +                        MarketOrder(_contract[symbol].Symbol, -1);
    +                    }
    +                }
    +            }
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm selects and buys the front-month Mini Gold Futures contract and sells the front-month Micro Gold Futures contract. When the front-month contract changes, the algorithm rebalances the portfolio. +

    +
    +
    from AlgorithmImports import *
    +
    +class USFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        # Set up an universe selection model that selects the front month contract
    +        self.set_universe_selection(FrontMonthFutureUniverseSelectionModel())
    +        self.add_alpha(ConstantFuturesAlphaModel())
    +        # A portfolio construction model that only order a single share per insight signal
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +        
    +class FrontMonthFutureUniverseSelectionModel(FutureUniverseSelectionModel):
    +    def __init__(self,) -> None:
    +        # Daily updating with select_future_chain_symbols function
    +        super().__init__(timedelta(1), self.select_future_chain_symbols)
    +
    +    def select_future_chain_symbols(self, utcTime: datetime) -> List[Symbol]:
    +        # Select gold and micro gold contracts for the strategy need
    +        future_pairs = [
    +            (Futures.Metals.GOLD, Market.COMEX),
    +            (Futures.Metals.MICRO_GOLD, Market.COMEX)
    +        ]
    +        return [Symbol.create(pair[0], SecurityType.FUTURE, pair[1]) for pair in future_pairs]
    +
    +    def filter(self, filter: FutureFilterUniverse) -> FutureFilterUniverse:
    +        # Filter only front month contract for liquidity and most informed information
    +        return filter.front_month().only_apply_filter_at_market_open()
    +
    +class ConstantFuturesAlphaModel(AlphaModel):
    +    # Long gold and short micro gold in this strategy
    +    long_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX)
    +    short_symbol = Symbol.create(Futures.Metals.MICRO_GOLD, SecurityType.FUTURE, Market.COMEX)
    +        
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        if algorithm.portfolio.invested:
    +            return []
    +        
    +        insights = []
    +        # For both gold and micro gold, select the front month contract (only contract) in the chain
    +        for kvp in slice.future_chains:
    +            chain = [contract for contract in kvp.Value]
    +            contract = chain[0]
    +            
    +            # Long gold and short micro gold as planned
    +            if kvp.Key == self.long_symbol:
    +                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.UP))
    +            elif kvp.Key == self.short_symbol:
    +                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.DOWN))
    +        
    +        return insights
    +        
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    +            algorithm.debug(f"We got {len(history)} from our history request for {security.symbol}")
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                # Single share only using integer portfolio target
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class USFuturesDataAlgorithm : QCAlgorithm
    +{        
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000000);
    +        UniverseSettings.Asynchronous = true;
    +        // Set up an universe selection model that selects the front month contract
    +        SetUniverseSelection(new FrontMonthFutureUniverseSelectionModel());
    +        SetAlpha(new ConstantFuturesAlphaModel());
    +        // A portfolio construction model that only order a single share per insight signal
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}
    +    
    +class FrontMonthFutureUniverseSelectionModel : FutureUniverseSelectionModel
    +{
    +    // Daily updating with select_future_chain_symbols function
    +    public FrontMonthFutureUniverseSelectionModel()
    +        : base(TimeSpan.FromDays(1), SelectFutureChainSymbols) {}
    +
    +    private static IEnumerable<Symbol> SelectFutureChainSymbols(DateTime utcTime)
    +    {
    +        //Select gold and micro gold contracts for the strategy need
    +        return new List<Symbol> {
    +            QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX),
    +            QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX)
    +        };
    +    }
    +
    +    protected override FutureFilterUniverse Filter(FutureFilterUniverse filter)
    +    {
    +        // Filter only front month contract for liquidity and most informed information
    +        return filter.FrontMonth().OnlyApplyFilterAtMarketOpen();
    +    }
    +}
    +
    +
    +class ConstantFuturesAlphaModel : AlphaModel
    +{
    +    // Long gold and short micro gold in this strategy
    +    private Symbol 
    +        _longSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX), 
    +        _shortSymbol = QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX);
    +    
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = new List<Insight>();
    +
    +        if (algorithm.Portfolio.Invested)
    +        {
    +            return insights;
    +        }
    +        
    +        // For both gold and micro gold, select the front month contract (only contract) in the chain
    +        foreach (var kvp in slice.FutureChains)
    +        {
    +            var symbol = kvp.Key;
    +            var chain = kvp.Value;
    +            var contract = chain.First();
    +            
    +            // Long gold and short micro gold as planned
    +            if (symbol == _longSymbol)
    +            {
    +                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Up));
    +            }
    +            else if (symbol == _shortSymbol)
    +            {
    +                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Down));
    +            }
    +        }
    +
    +        return insights;
    +    }
    +    
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = algorithm.History(security.Symbol, 100, Resolution.Minute);
    +            algorithm.Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    +        }
    +    }
    +}
    +    
    +    
    +class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        var targets = new List<PortfolioTarget>();
    +        foreach (var insight in insights)
    +        {
    +            if (algorithm.Securities[insight.Symbol].IsTradable)
    +            {
    +                // Single share only using integer portfolio target
    +                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +            }
    +        }
    +        return targets;
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Future Universe dataset provides + + FutureFilterUniverse + + and + + FutureUniverse + + objects. +

    +

    + FutureFilterUniverse Attributes +

    +

    + + FutureFilterUniverse + + objects have the following attributes: +

    +
    +
    +

    + FutureUniverse Attributes +

    +

    + + FutureUniverse + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Futures Security Master

    +
    +
    +

    Introduction

    + + +

    + The US Futures Security Master dataset by QuantConnect provides mapping reference data for the most liquid contracts of the CME Group exchanges, calculated with popular rolling techniques. The data covers 157 root Future contracts, starts in May 2009, and is delivered on a daily frequency with a zip file with all the contract mappings. This dataset is created by daily processing of the US historical Future chains. +

    +

    + This dataset, paired with the US Futures dataset, supports the following rolling techniques: forward panama canal, backwards panama canal, and backwards ratio. You can set the specific rolling date to occur on the last trading day, first day month, or the day when the contract with the greatest open interest changes. +

    +

    + VIX Futures don't support continous contract rolling with open interest. +

    +

    + This is + + NOT + + the underlying Futures data ( + + US Futures + + dataset), which you need to purchase separately with a license from AlgoSeek. This security master dataset is required to purchase the US Futures or US Future Options datasets. +

    +

    + For more information about the US Futures Security Master dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + You don't need any special code to utilize the US Futures Security Master. It automatically loads when you + + request US Futures data + + . +

    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + May 2009 +
    + Asset Coverage + + 157 Liquid Futures +
    + Data Density + + Regular +
    + Resolution + + Daily +
    +

    + VIX Futures don't support continous contract rolling with open interest. +

    + + + +

    Key Concept

    + + +

    + The US Futures Security Master lets you to construct continuous Futures, allowing the access of normalized historical data of the underlying assets, as well as trading the “lead” Future contracts for those assets. +

    +

    + Continuous Futures refer to sets of rolling lead Future contracts during their actively trading periods. Since Future contracts expire at their maturities, to analyze the historical price of a Future and to apply technical indicators, you need the continuous Future price series. +

    +

    + To access the continuous Future, use the Future's + + Symbol + + + symbol + + property. +

    +
    +
    # Set the data normalization mode and data mapping mode to select the contract as the continuous contract with price adjustment for smooth price series
    +future = self.add_future(Futures.Energy.CRUDE_OIL_WTI,
    +    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +    data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +    contract_depth_offset=0)
    +self.continuous_contract_symbol = future.symbol
    +
    // Set the data normalization mode and data mapping mode to select the contract as the continuous contract with price adjustment for smooth price series
    +var future = AddFuture(Futures.Energy.CrudeOilWTI,
    +    dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +    dataMappingMode: DataMappingMode.OpenInterest,
    +    contractDepthOffset: 0
    +);
    +_continuousFutureSymbol = future.Symbol;
    +
    +

    + The + + dataNormalizationMode + + and + + dataMappingMode + + arguments makes the transition of the underlying contracts seemless. However, the Future + + Symbol + + doesn't map to an underlying Future contract. It works fine to trade within backtests, but could be subjected to friction costs during live trading since the order price could be a normalized price. For more information about this topic, see the + + Live Trading Considerations + + section. +

    + + + +

    Data Normalization Modes

    + + +

    + The data normalization mode defines how the price series of two contracts are stitched together when the contract rollovers occur. The + + DataNormalizatoinMode + + enumeration has the following members available for continuous contracts: +

    +
    +
    +

    + If you use a data normalization mode that's not in the preceding list, LEAN automatically converts it to + + DataNormalizationMode.BackwardsRatio + + . +

    + + + +

    Data Mapping Modes

    + + +

    + The data mapping mode defines when contract rollovers occur. The + + DataMappingMode + + enumeration has the following members: +

    +
    +
    +

    + VIX Futures don't support continous contract rolling with + + DataMappingMode.OpenInterest + + + DataMappingMode.OPEN_INTEREST + + and + + DataMappingMode.OpenInterestAnnuak + + + DataMappingMode.OPEN_INTEREST_ANNUAL + + . +

    + + + +

    Tracking Contract Changes

    + + +

    + As the contracts roll over, the + + Mapped + + + mapped + + property of the + + Future + + object references the next contract in the series and you receive a + + SymbolChangedEvent + + . To get the current + + Symbol + + change events, index the + + SymbolChangedEvents + + + symbol_changed_events + + property of the current + + + Slice + + + with the continuous Futures + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your Future at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Get Symbol Change Event of the Continuous Future (change in mapped contract)
    +    changed_event = slice.symbol_changed_events.get(self.continuous_future_symbol)
    +    if changed_event:
    +        old_symbol = changed_event.old_symbol
    +        new_symbol = self.add_future_contract(changed_event.new_symbol).symbol
    +        tag = f"Rollover - Symbol changed at {self.time}: {old_symbol} -> {new_symbol}"
    +        quantity = self.portfolio[old_symbol].quantity
    +
    +        # Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    +        self.liquidate(old_symbol, tag = tag)
    +        if quantity != 0: self.market_order(new_symbol, quantity, tag = tag)
    +        self.log(tag)
    +
    public override void OnData(Slice slice)
    +{
    +    // Get Symbol Change Event of the Continuous Future (change in mapped contract)
    +    if (slice.SymbolChangedEvents.TryGetValue(_continuousFutureSymbol, out var changedEvent))
    +    {
    +        var oldSymbol = changedEvent.OldSymbol;
    +        var newSymbol = AddFutureContract(changedEvent.NewSymbol).Symbol;
    +        var tag = $"Rollover - Symbol changed at {Time}: {oldSymbol} -> {newSymbol}";
    +        var quantity = Portfolio[oldSymbol].Quantity;
    +        // Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    +        Liquidate(oldSymbol, tag: tag);
    +        if (quantity != 0) MarketOrder(newSymbol, quantity, tag: tag);
    +        Log(tag);
    +    }
    +}
    +
    +

    + + SymbolChangedEvent + + objects have the following attributes: +

    +
    +
    + + + +

    Live Trading Considerations

    + + +

    + You can trade continuous Futures, but the continuous Future + + Symbol + + doesn't map to a single underlying Future contract. Instead, it represents a set of rolling contracts. Thus, the prices could be frictional during a contract rollover, which could be catastrophic in live trading! For live trading, you should place your orders directly on the underlying contracts. To get the current underlying contract in the continuous Future series, use the + + Mapped + + + mapped + + property. +

    +
    +
    # Get the mapped symbol
    +current_contract = self.continuous_contract.mapped
    +self.buy(current_contract, 1)
    +
    // Get the mapped symbol
    +var currentContract = _continuousContract.Mapped;
    +Buy(currentContract, 1);
    +
    + + + +

    Data Format

    + + +

    + If you download the files in the US Futures Security Master, you get a factor file and a map file for each of the exchanges with supported continuous Futures. To view the files, see the + + \data\future\<exchange_name> + + directory under your LEAN CLI base directory. +

    +

    + For the factor file, it is a + + .zip + + collection of REST API styled + + .csv + + files for each Future + + Symbol + + , including the date, scaling factors for each type of data normalization and the data mapping mode that indicates the Symbol changing event is on that day for that mapping mode. The following line is an example line in the + + .csv + + file: +

    + + {"Date":"2009-10-31T00:00:00","BackwardsRatioScale":[0.9914163090128755364806866953,1.0,1.0],"BackwardsPanamaCanalScale":[-2.0,0.0,0.0],"ForwardPanamaCanalScale":[0.0,0.0,0.0],"DataMappingMode":1} + +
    +

    + For the map file, it is a + + .zip + + collection of + + .csv + + files for each Future + + Symbol + + , including the date, new underlying contract Symbol, the exchange code, and the data mapping mode that indicates the Symbol changing event is on that day for that mapping mode. The following line is an example line in the + + .csv + + file: +

    + + 20091130,aw uii3j0m6zbj9,CBOT,1 + + + + +

    Historical Data

    + + +

    + You can get historical US Future Security Master data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Future Security Master data in an algorithm, call the + + History<SymbolChangedEvent> + + + history + + method with continuous Future + + Symbol + + and a lookback period. This method returns the old and new contract of each rollover. If there is no data for the period you requested, the history result is empty. +

    +
    +
    # Add the Future and define its rollover settings.
    +future = self.add_future(
    +    Futures.Indices.SP_500_E_MINI,
    +    data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +    contract_depth_offset=0
    +)
    +
    +# DataFrame example where the columns are the SymbolChangedEvent attributes:
    +history_df = self.history(SymbolChangedEvent, future.symbol, timedelta(365))
    +
    +# SymbolChangedEvent objects example:
    +history = self.history[SymbolChangedEvent](future.symbol, timedelta(365))
    +
    // Add the Future and define its rollover settings.
    +var future = AddFuture(
    +    Futures.Indices.SP500EMini,
    +    dataMappingMode: DataMappingMode.OpenInterest,
    +    dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +    contractDepthOffset: 0
    +);
    +
    +// Get historical data.
    +var history = History<SymbolChangedEvent>(future.Symbol, TimeSpan.FromDays(365));
    +
    +

    + For more information about historical US Future Security Master data in algorithms, see + + Symbol Changes + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Future Security Master data in the Research Environment, call the + + History<SymbolChangedEvent> + + + history + + method with continuous Future + + Symbol + + and a time period. This method returns the old and new contract of each rollover. If there is no data for the period you requested, the history result is empty. +

    +
    +
    # Add the Future and define its rollover settings.
    +future = qb.add_future(
    +    Futures.Indices.SP_500_E_MINI,
    +    data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +    contract_depth_offset=0
    +)
    +
    +# DataFrame example where the columns are the SymbolChangedEvent attributes:
    +history_df = qb.history(SymbolChangedEvent, future.symbol, datetime(2023, 1, 1), datetime(2025, 1, 1))
    +
    +# SymbolChangedEvent objects example:
    +history = qb.history[SymbolChangedEvent](future.symbol, datetime(2023, 1, 1), datetime(2025, 1, 1))
    +
    // Add the Future and define its rollover settings.
    +var future = qb.AddFuture(
    +    Futures.Indices.SP500EMini,
    +    dataMappingMode: DataMappingMode.OpenInterest,
    +    dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +    contractDepthOffset: 0
    +);
    +
    +// Get historical data.
    +var history = qb.History<SymbolChangedEvent>(future.Symbol, new DateTime(2023, 1, 1), new DateTime(2025, 1, 1));
    +
    +

    + For more information about historical US Future Security Master data in the Research Environment, see + + Symbol Changes History + + . +

    + + + +

    Supported Assets

    + + +

    + The following list shows the available (157) Futures: +

    +
      +
    • + + Futures.Currencies.AUD + + : Australian Dollar Futures (CME: 6A) +
    • +
    • + + Futures.Currencies.AUDCAD + + : Australian Dollar/Canadian Dollar Futures (CME: ACD) +
    • +
    • + + Futures.Currencies.AUDJPY + + : Australian Dollar/Japanese Yen Futures (CME: AJY) +
    • +
    • + + Futures.Currencies.AUDNZD + + : Australian Dollar/New Zealand Dollar Futures (CME: ANE) +
    • +
    • + + Futures.Currencies.BRL + + : Brazillian Real Futures (CME: 6L) +
    • +
    • + + Futures.Currencies.BTC + + : Bitcoin Futures (CME: BTC) +
    • +
    • + + Futures.Currencies.BTICMicroBTC + + + Futures.Currencies.BTIC_MICRO_BTC + + : BTIC on Micro Bitcoin Futures (CME: MIB) +
    • +
    • + + Futures.Currencies.BTICMicroEther + + + Futures.Currencies.BTIC_MICRO_ETHER + + : BTIC on Micro Ether Futures (CME: MRB) +
    • +
    • + + Futures.Currencies.CAD + + : Canadian Dollar Futures (CME: 6C) +
    • +
    • + + Futures.Currencies.CADJPY + + : Canadian Dollar/Japanese Yen Futures (CME: CJY) +
    • +
    • + + Futures.Currencies.CHF + + : Swiss Franc Futures (CME: 6S) +
    • +
    • + + Futures.Currencies.ETH + + : Ether Futures (CME: ETH) +
    • +
    • + + Futures.Currencies.EUR + + : Euro FX Futures (CME: 6E) +
    • +
    • + + Futures.Currencies.EURAUD + + : Euro/Australian Dollar Futures (CME: EAD) +
    • +
    • + + Futures.Currencies.EURCAD + + : Euro/Canadian Dollar Futures (CME: ECD) +
    • +
    • + + Futures.Currencies.EuroFXEmini + + + Futures.Currencies.EURO_FX_EMINI + + : E-mini Euro FX Futures (CME: E7) +
    • +
    • + + Futures.Currencies.EURSEK + + : Euro/Swedish Krona Futures (CME: ESK) +
    • +
    • + + Futures.Currencies.GBP + + : British Pound Futures (CME: 6B) +
    • +
    • + + Futures.Currencies.JapaneseYenEmini + + + Futures.Currencies.JAPANESE_YEN_EMINI + + : E-mini Japanese Yen Futures (CME: J7) +
    • +
    • + + Futures.Currencies.JPY + + : Japanese Yen Futures (CME: 6J) +
    • +
    • + + Futures.Currencies.MicroAUD + + + Futures.Currencies.MICRO_AUD + + : Micro AUD/USD Futures (CME: M6A) +
    • +
    • + + Futures.Currencies.MicroBTC + + + Futures.Currencies.MICRO_BTC + + : Micro Bitcoin Futures (CME: MBT) +
    • +
    • + + Futures.Currencies.MicroCAD + + + Futures.Currencies.MICRO_CAD + + : Micro USD/CAD Futures (CME: M6C) +
    • +
    • + + Futures.Currencies.MicroCADUSD + + + Futures.Currencies.MICRO_CADUSD + + : Micro CAD/USD Futures (CME: MCD) +
    • +
    • + + Futures.Currencies.MicroCHF + + + Futures.Currencies.MICRO_CHF + + : Micro CHF/USD Futures (CME: MSF) +
    • +
    • + + Futures.Currencies.MicroEther + + + Futures.Currencies.MICRO_ETHER + + : Micro Ether Futures (CME: MET) +
    • +
    • + + Futures.Currencies.MicroEUR + + + Futures.Currencies.MICRO_EUR + + : Micro EUR/USD Futures (CME: M6E) +
    • +
    • + + Futures.Currencies.MicroGBP + + + Futures.Currencies.MICRO_GBP + + : Micro GBP/USD Futures (CME: M6B) +
    • +
    • + + Futures.Currencies.MicroINRUSD + + + Futures.Currencies.MICRO_INRUSD + + : Micro INR/USD Futures (CME: MIR) +
    • +
    • + + Futures.Currencies.MicroJPY + + + Futures.Currencies.MICRO_JPY + + : Micro JPY/USD Futures (CME: MJY) +
    • +
    • + + Futures.Currencies.MicroUSDCHF + + + Futures.Currencies.MICRO_USDCHF + + : Micro USD/CHF Futures (CME: M6S) +
    • +
    • + + Futures.Currencies.MicroUSDCNH + + + Futures.Currencies.MICRO_USDCNH + + : Micro USD/CNH Futures (CME: MNH) +
    • +
    • + + Futures.Currencies.MicroUSDJPY + + + Futures.Currencies.MICRO_USDJPY + + : Micro USD/JPY Futures (CME: M6J) +
    • +
    • + + Futures.Currencies.MXN + + : Mexican Peso Futures (CME: 6M) +
    • +
    • + + Futures.Currencies.NZD + + : New Zealand Dollar Futures (CME: 6N) +
    • +
    • + + Futures.Currencies.RUB + + : Russian Ruble Futures (CME: 6R) +
    • +
    • + + Futures.Currencies.StandardSizeUSDOffshoreRMBCNH + + + Futures.Currencies.STANDARD_SIZE_USD_OFFSHORE_RMBCNH + + : Standard-Size USD/Offshore RMB (CNH) Futures (CME: CNH) +
    • +
    • + + Futures.Currencies.ZAR + + : South African Rand Futures (CME: 6Z) +
    • +
    • + + Futures.Energy.ArgusLLSvsWTIArgusTradeMonth + + + Futures.Energy.ARGUS_LL_SVS_WTI_ARGUS_TRADE_MONTH + + : Argus LLS vs. WTI (Argus) Trade Month Futures (NYMEX: AE5) +
    • +
    • + + Futures.Energy.ArgusPropaneFarEastIndex + + + Futures.Energy.ARGUS_PROPANE_FAR_EAST_INDEX + + : Argus Propane Far East Index Futures (NYMEX: A7E) +
    • +
    • + + Futures.Energy.ArgusPropaneSaudiAramco + + + Futures.Energy.ARGUS_PROPANE_SAUDI_ARAMCO + + : Argus Propane (Saudi Aramco) Futures (NYMEX: A9N) +
    • +
    • + + Futures.Energy.BrentCrudeOilVsDubaiCrudeOilPlatts + + + Futures.Energy.BRENT_CRUDE_OIL_VS_DUBAI_CRUDE_OIL_PLATTS + + : Brent Crude Oil vs. Dubai Crude Oil (Platts) Futures (NYMEX: ADB) +
    • +
    • + + Futures.Energy.BrentLastDayFinancial + + + Futures.Energy.BRENT_LAST_DAY_FINANCIAL + + : Brent Last Day Financial Futures (NYMEX: BZ) +
    • +
    • + + Futures.Energy.ChicagoEthanolPlatts + + + Futures.Energy.CHICAGO_ETHANOL_PLATTS + + : Chicago Ethaanol (Platts) Futures (NYMEX: CU) +
    • +
    • + + Futures.Energy.ConwayPropaneOPIS + + + Futures.Energy.CONWAY_PROPANE_OPIS + + : Conway Propane (OPIS) Futures (NYMEX: A8K) +
    • +
    • + + Futures.Energy.CrudeOilWTI + + + Futures.Energy.CRUDE_OIL_WTI + + : Crude Oil WTI Futures (NYMEX: CL) +
    • +
    • + + Futures.Energy.DubaiCrudeOilPlattsFinancial + + + Futures.Energy.DUBAI_CRUDE_OIL_PLATTS_FINANCIAL + + : Dubai Crude Oil (Platts) Financial Futures (NYMEX: DCB) +
    • +
    • + + Futures.Energy.EastWestGasolineSpreadPlattsArgus + + + Futures.Energy.EAST_WEST_GASOLINE_SPREAD_PLATTS_ARGUS + + : East-West Gasoline Spread (Platts-Argus) Futures (NYMEX: EWG) +
    • +
    • + + Futures.Energy.EastWestNaphthaJapanCFvsCargoesCIFNWESpreadPlatts + + + Futures.Energy.EAST_WEST_NAPHTHA_JAPAN_C_FVS_CARGOES_CIFNWE_SPREAD_PLATTS + + : East-West Naphtha: Japan C&F vs. Cargoes CIF NWE Spread (Platts) Futures (NYMEX: EWN) +
    • +
    • + + Futures.Energy.Ethanol + + + Futures.Energy.ETHANOL + + : Ethanol Futures (CBOT: EH) +
    • +
    • + + Futures.Energy.EthanolT2FOBRdamIncludingDutyPlatts + + + Futures.Energy.ETHANOL_T_2_FOB_RDAM_INCLUDING_DUTY_PLATTS + + : Ethanol T2 FOB Rdam Including Duty (Platts) Futures (NYMEX: AZ1) +
    • +
    • + + Futures.Energy.EuropeanNaphthaPlattsCrackSpread + + + Futures.Energy.EUROPEAN_NAPHTHA_PLATTS_CRACK_SPREAD + + : European Naphtha (Platts) Crack Spread Futures (NYMEX: EN) +
    • +
    • + + Futures.Energy.EuropeanPropaneCIFARAArgus + + + Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS + + : European Propane CIF ARA (Argus) Futures (NYMEX: APS) +
    • +
    • + + Futures.Energy.EuropeanPropaneCIFARAArgusVsNaphthaCargoesCIFNWEPlatts + + + Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS_VS_NAPHTHA_CARGOES_CIFNWE_PLATTS + + : European Propane CIF ARA (Argus) vs. Naphtha Cargoes CIF NWE (Platts) Futures (NYMEX: EPN) +
    • +
    • + + Futures.Energy.FreightRouteTC14Baltic + + + Futures.Energy.FREIGHT_ROUTE_TC_14_BALTIC + + : Freight Route TC14 (Baltic) Futures (NYMEX: FRC) +
    • +
    • + + Futures.Energy.Gasoline + + + Futures.Energy.GASOLINE + + : Gasoline RBOB Futures (NYMEX: RB) +
    • +
    • + + Futures.Energy.GasolineEurobobOxyNWEBargesArgus + + + Futures.Energy.GASOLINE_EUROBOB_OXY_NWE_BARGES_ARGUS + + : Gasoline Euro-bob Oxy NWE Barges (Argus) Futures (NYMEX: B7H) +
    • +
    • + + Futures.Energy.GroupThreeSuboctaneGasolinePlattsVsRBOB + + + Futures.Energy.GROUP_THREE_SUBOCTANE_GASOLINE_PLATTS_VS_RBOB + + : Group Three Sub-octane Gasoliine (Platts) vs. RBOB Futures (NYMEX: AA8) +
    • +
    • + + Futures.Energy.GroupThreeULSDPlattsVsNYHarborULSD + + + Futures.Energy.GROUP_THREE_ULSD_PLATTS_VS_NY_HARBOR_ULSD + + : Group Three ULSD (Platts) vs. NY Harbor ULSD Futures (NYMEX: AA6) +
    • +
    • + + Futures.Energy.GulfCoastCBOBGasolineA2PlattsVsRBOBGasoline + + + Futures.Energy.GULF_COAST_CBOB_GASOLINE_A_2_PLATTS_VS_RBOB_GASOLINE + + : Gulf Coast CBOB Gasoline A2 (Platts) vs. RBOB Gasoline Futures (NYMEX: CRB) +
    • +
    • + + Futures.Energy.GulfCoastHSFOPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.GULF_COAST_HSFO_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : Gulf Coast HSFO (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: GCU) +
    • +
    • + + Futures.Energy.HeatingOil + + + Futures.Energy.HEATING_OIL + + : Heating Oil Futures (NYMEX: HO) +
    • +
    • + + Futures.Energy.LosAngelesCARBOBGasolineOPISvsRBOBGasoline + + + Futures.Energy.LOS_ANGELES_CARBOB_GASOLINE_OPI_SVS_RBOB_GASOLINE + + : Los Angeles CARBOB Gasoline (OPIS) vs. RBOB Gasoline Futures (NYMEX: AJL) +
    • +
    • + + Futures.Energy.LosAngelesCARBDieselOPISvsNYHarborULSD + + + Futures.Energy.LOS_ANGELES_CARB_DIESEL_OPI_SVS_NY_HARBOR_ULSD + + : Los Angeles CARB Diesel (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AKL) +
    • +
    • + + Futures.Energy.LosAngelesJetOPISvsNYHarborULSD + + + Futures.Energy.LOS_ANGELES_JET_OPI_SVS_NY_HARBOR_ULSD + + : Los Angeles Jet (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AJS) +
    • +
    • + + Futures.Energy.MarsArgusVsWTIFinancial + + + Futures.Energy.MARS_ARGUS_VS_WTI_FINANCIAL + + : Mars (Argus) vs. WTI Financial Futures (NYMEX: AYX) +
    • +
    • + + Futures.Energy.MarsArgusVsWTITradeMonth + + + Futures.Energy.MARS_ARGUS_VS_WTI_TRADE_MONTH + + : Mars (Argus) vs. WTI Trade Month Futures (NYMEX: AYV) +
    • +
    • + + Futures.Energy.MicroCrudeOilWTI + + + Futures.Energy.MICRO_CRUDE_OIL_WTI + + : Micro WTI Crude Oil Futures (NYMEX: MCL) +
    • +
    • + + Futures.Energy.MicroEuropeanFOBRdamMarineFuelZeroPointFivePercentBargesPlatts + + + Futures.Energy.MICRO_EUROPEAN_FOB_RDAM_MARINE_FUEL_ZERO_POINT_FIVE_PERCENT_BARGES_PLATTS + + : Micro European FOB Rdam Marine Fuel 0.5% Barges (Platts) Futures (NYMEX: R5O) +
    • +
    • + + Futures.Energy.MicroEuropeanThreePointFivePercentOilBargesFOBRdamPlatts + + + Futures.Energy.MICRO_EUROPEAN_THREE_POINT_FIVE_PERCENT_OIL_BARGES_FOB_RDAM_PLATTS + + : Micro European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: MEF) +
    • +
    • + + Futures.Energy.MicroGasoilZeroPointOnePercentBargesFOBARAPlatts + + + Futures.Energy.MICRO_GASOIL_ZERO_POINT_ONE_PERCENT_BARGES_FOBARA_PLATTS + + : Micro Gasoil 0.1% Barges FOB ARA (Platts) Futures (NYMEX: M1B) +
    • +
    • + + Futures.Energy.MicroSingaporeFOBMarineFuelZeroPointFivePercetPlatts + + + Futures.Energy.MICRO_SINGAPORE_FOB_MARINE_FUEL_ZERO_POINT_FIVE_PERCET_PLATTS + + : Micro Singapore FOB Marine Fuel 0.5% (Platts) Futures (NYMEX: S5O) +
    • +
    • + + Futures.Energy.MicroSingaporeFuelOil380CSTPlatts + + + Futures.Energy.MICRO_SINGAPORE_FUEL_OIL_380_CST_PLATTS + + : Micro Singapore Fuel Oil 380CST (Platts) Futures (NYMEX: MAF) +
    • +
    • + + Futures.Energy.MiniEuropeanThreePointPercentFiveFuelOilBargesPlatts + + + Futures.Energy.MINI_EUROPEAN_THREE_POINT_PERCENT_FIVE_FUEL_OIL_BARGES_PLATTS + + : Mini European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: A0D) +
    • +
    • + + Futures.Energy.MiniSingaporeFuelOil180CstPlatts + + + Futures.Energy.MINI_SINGAPORE_FUEL_OIL_180_CST_PLATTS + + : Mini Singapore Fuel Oil 180 cst (Platts) Futures (NYMEX: A0F) +
    • +
    • + + Futures.Energy.MontBelvieuEthaneOPIS + + + Futures.Energy.MONT_BELVIEU_ETHANE_OPIS + + : Mont Belvieu Ethane (OPIS) Futures (NYMEX: AC0) +
    • +
    • + + Futures.Energy.MontBelvieuLDHPropaneOPIS + + + Futures.Energy.MONT_BELVIEU_LDH_PROPANE_OPIS + + : Mont Belvieu LDH Propane (OPIS) Futures (NYMEX: B0) +
    • +
    • + + Futures.Energy.MontBelvieuNaturalGasolineOPIS + + + Futures.Energy.MONT_BELVIEU_NATURAL_GASOLINE_OPIS + + : Mont Belvieu Natural Gasoline (OPIS) Futures (NYMEX: A7Q) +
    • +
    • + + Futures.Energy.MontBelvieuNormalButaneOPIS + + + Futures.Energy.MONT_BELVIEU_NORMAL_BUTANE_OPIS + + : Mont Belvieu Normal Butane (OPIS) Futures (NYMEX: AD0) +
    • +
    • + + Futures.Energy.NaturalGas + + + Futures.Energy.NATURAL_GAS + + : Natural Gas Futures (NYMEX: NG) +
    • +
    • + + Futures.Energy.NaturalGasHenryHubLastDayFinancial + + + Futures.Energy.NATURAL_GAS_HENRY_HUB_LAST_DAY_FINANCIAL + + : Natural Gas (Henry Hub) Last-day Financial Futures (NYMEX: HH) +
    • +
    • + + Futures.Energy.NaturalGasHenryHubPenultimateFinancial + + + Futures.Energy.NATURAL_GAS_HENRY_HUB_PENULTIMATE_FINANCIAL + + : Natural Gas (Henry Hub) Penultimate Financial Futures (NYMEX: HP) +
    • +
    • + + Futures.Energy.OnePercentFuelOilCargoesFOBNWEPlattsVsThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.ONE_PERCENT_FUEL_OIL_CARGOES_FOBNWE_PLATTS_VS_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : 1% Fuel Oil Cargoes FOB NWE (Platts) vs. 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: FSS) +
    • +
    • + + Futures.Energy.PremiumUnleadedGasoline10ppmFOBMEDPlatts + + + Futures.Energy.PREMIUM_UNLEADED_GASOLINE_10_PPM_FOBMED_PLATTS + + : Premium Unleaded Gasoline 10 ppm FOB MED (Platts) Futures (NYMEX: A3G) +
    • +
    • + + Futures.Energy.PropaneNonLDHMontBelvieuOPIS + + + Futures.Energy.PROPANE_NON_LDH_MONT_BELVIEU_OPIS + + : Propane Non-LDH Mont Belvieu (OPIS) Futures (NYMEX: A1R) +
    • +
    • + + Futures.Energy.RBOBGasolineCrackSpread + + + Futures.Energy.RBOB_GASOLINE_CRACK_SPREAD + + : RBOB Gasoline Crack Spread Futures (NYMEX: ARE) +
    • +
    • + + Futures.Energy.RBOBGasolineVsEurobobOxyNWEBargesArgusThreeHundredFiftyThousandGallons + + + Futures.Energy.RBOB_GASOLINE_VS_EUROBOB_OXY_NWE_BARGES_ARGUS_THREE_HUNDRED_FIFTY_THOUSAND_GALLONS + + : RBOB Gasoline vs. Euro-bob Oxy NWE Barges (Argus) (350,000 gallons) Futures (NYMEX: EXR) +
    • +
    • + + Futures.Energy.SingaporeFuelOil380cstPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.SINGAPORE_FUEL_OIL_380_CST_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : Singapore Fuel Oil 380 cst (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: EVC) +
    • +
    • + + Futures.Energy.SingaporeGasoilPlattsVsLowSulphurGasoilFutures + + + Futures.Energy.SINGAPORE_GASOIL_PLATTS_VS_LOW_SULPHUR_GASOIL_FUTURES + + : Singapore Gasoil (Platts) vs. Low Sulphur Gasoil Futures (NYMEX: AGA) +
    • +
    • + + Futures.Energy.SingaporeMogas92UnleadedPlattsBrentCrackSpread + + + Futures.Energy.SINGAPORE_MOGAS_92_UNLEADED_PLATTS_BRENT_CRACK_SPREAD + + : Singapore Mogas 92 Unleaded (Platts) Brent Crack Spread Futures (NYMEX: D1N) +
    • +
    • + + Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread + + + Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD + + : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread Futures (NYMEX: FO) +
    • +
    • + + Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread1000mt + + + Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD_1000_MT + + : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread (1000mt) Futures (NYMEX: BOO) +
    • +
    • + + Futures.Energy.WTIBrentFinancial + + + Futures.Energy.WTI_BRENT_FINANCIAL + + : WTI-Brent Financial Futures (NYMEX: BK) +
    • +
    • + + Futures.Energy.WTIFinancial + + + Futures.Energy.WTI_FINANCIAL + + : WTI Financial Futures (NYMEX: CSX) +
    • +
    • + + Futures.Energy.WTIHoustonArgusVsWTITradeMonth + + + Futures.Energy.WTI_HOUSTON_ARGUS_VS_WTI_TRADE_MONTH + + : WTI Houston (Argus) vs. WTI Trade Month Futures (NYMEX: HTT) +
    • +
    • + + Futures.Energy.WTIHoustonCrudeOil + + + Futures.Energy.WTI_HOUSTON_CRUDE_OIL + + : WTI Houston Crude Oil Futures (NYMEX: HCL) +
    • +
    • + + Futures.Financials.EuroDollar + + + Futures.Financials.EURO_DOLLAR + + : EuroDollar Futures (CME: GE) +
    • +
    • + + Futures.Financials.FiveYearUSDMACSwap + + + Futures.Financials.FIVE_YEAR_USDMAC_SWAP + + : 5-Year USD MAC Swap Futures (CBOT: F1U) +
    • +
    • + + Futures.Financials.MicroY10TreasuryNote + + + Futures.Financials.MICRO_Y_10_TREASURY_NOTE + + : Micro 10-Year Yield Futures (CBOT: 10Y) +
    • +
    • + + Futures.Financials.MicroY2TreasuryBond + + + Futures.Financials.MICRO_Y_2_TREASURY_BOND + + : Micro 2-Year Yield Futures (CBOT: 2YY) +
    • +
    • + + Futures.Financials.MicroY30TreasuryBond + + + Futures.Financials.MICRO_Y_30_TREASURY_BOND + + : Micro 30-Year Yield Futures (CBOT: 30Y) +
    • +
    • + + Futures.Financials.MicroY5TreasuryBond + + + Futures.Financials.MICRO_Y_5_TREASURY_BOND + + : Micro 5-Year Yield Futures (CBOT: 5YY) +
    • +
    • + + Futures.Financials.UltraTenYearUSTreasuryNote + + + Futures.Financials.ULTRA_TEN_YEAR_US_TREASURY_NOTE + + : Ultra 10-Year U.S. Treasury Note Futures (CBOT: TN) +
    • +
    • + + Futures.Financials.UltraUSTreasuryBond + + + Futures.Financials.ULTRA_US_TREASURY_BOND + + : Ultra U.S. Treasury Bond Futures (CBOT: UB) +
    • +
    • + + Futures.Financials.Y10TreasuryNote + + + Futures.Financials.Y_10_TREASURY_NOTE + + : 10Y U.S. Treasury Note Futures (CBOT: ZN) +
    • +
    • + + Futures.Financials.Y2TreasuryNote + + + Futures.Financials.Y_2_TREASURY_NOTE + + : 2Y U.S. Treasury Note Futures (CBOT: ZT) +
    • +
    • + + Futures.Financials.Y30TreasuryBond + + + Futures.Financials.Y_30_TREASURY_BOND + + : 30Y U.S. Treasury Bond Futures (CBOT: ZB) +
    • +
    • + + Futures.Financials.Y5TreasuryNote + + + Futures.Financials.Y_5_TREASURY_NOTE + + : 5Y U.S. Treasury Note Futures (CBOT: ZF) +
    • +
    • + + Futures.Forestry.Lumber + + + Futures.Forestry.LUMBER + + : Lumber Futures (CME: LBR) +
    • +
    • + + Futures.Forestry.RandomLengthLumber + + + Futures.Forestry.RANDOM_LENGTH_LUMBER + + : Random Length Lumber Futures (CME: LBS) +
    • +
    • + + Futures.Grains.BlackSeaCornFinanciallySettledPlatts + + + Futures.Grains.BLACK_SEA_CORN_FINANCIALLY_SETTLED_PLATTS + + : Black Sea Corn Financially Settled (Platts) Futures (CBOT: BCF) +
    • +
    • + + Futures.Grains.BlackSeaWheatFinanciallySettledPlatts + + + Futures.Grains.BLACK_SEA_WHEAT_FINANCIALLY_SETTLED_PLATTS + + : Black Sea Wheat Financially Settled (Platts) Futures (CBOT: BWF) +
    • +
    • + + Futures.Grains.Corn + + + Futures.Grains.CORN + + : Corn Futures (CBOT: ZC) +
    • +
    • + + Futures.Grains.HRWWheat + + + Futures.Grains.HRW_WHEAT + + : KC HRW Wheat Futures (CBOT: KE) +
    • +
    • + + Futures.Grains.Oats + + + Futures.Grains.OATS + + : Oats Futures (CBOT: ZO) +
    • +
    • + + Futures.Grains.Soybeans + + + Futures.Grains.SOYBEANS + + : Soybeans Futures (CBOT: ZS) +
    • +
    • + + Futures.Grains.SoybeanMeal + + + Futures.Grains.SOYBEAN_MEAL + + : Soybean Meal Futures (CBOT: ZM) +
    • +
    • + + Futures.Grains.SoybeanOil + + + Futures.Grains.SOYBEAN_OIL + + : Soybean Oil Futures (CBOT: ZL) +
    • +
    • + + Futures.Grains.Wheat + + + Futures.Grains.WHEAT + + : Default wheat contract is SRWWheat (CBOT: ZW) +
    • +
    • + + Futures.Indices.BloombergCommodityIndex + + + Futures.Indices.BLOOMBERG_COMMODITY_INDEX + + : Bloomberg Commodity Index Futures (CBOT: AW) +
    • +
    • + + Futures.Indices.Dow30EMini + + + Futures.Indices.DOW_30_E_MINI + + : E-mini Dow Indu 30 Futures (CBOT: YM) +
    • +
    • + + Futures.Indices.DowJonesRealEstate + + + Futures.Indices.DOW_JONES_REAL_ESTATE + + : Dow Jones Real Estate futures on CME (CME: RX) +
    • +
    • + + Futures.Indices.FTSEEmergingEmini + + + Futures.Indices.FTSE_EMERGING_EMINI + + : E-mini FTSE Emerging Index Futures (CME: EI) +
    • +
    • + + Futures.Indices.MicroDow30EMini + + + Futures.Indices.MICRO_DOW_30_E_MINI + + : Micro E-mini Dow Jones Industrial Average Index Futures (CBOT: MYM) +
    • +
    • + + Futures.Indices.MicroNASDAQ100EMini + + + Futures.Indices.MICRO_NASDAQ_100_E_MINI + + : Micro E-mini Nasdaq-100 Index Futures (CME: MNQ) +
    • +
    • + + Futures.Indices.MicroRussell2000EMini + + + Futures.Indices.MICRO_RUSSELL_2000_E_MINI + + : Micro E-mini Russell 2000 Index Futures (CME: M2K) +
    • +
    • + + Futures.Indices.MicroSP500EMini + + + Futures.Indices.MICRO_SP_500_E_MINI + + : Micro E-mini S&P 500 Index Futures (CME: MES) +
    • +
    • + + Futures.Indices.NASDAQ100BiotechnologyEMini + + + Futures.Indices.NASDAQ_100_BIOTECHNOLOGY_E_MINI + + : E-mini Nasdaq-100 Biotechnology Index Futures (CME: BIO) +
    • +
    • + + Futures.Indices.NASDAQ100EMini + + + Futures.Indices.NASDAQ_100_E_MINI + + : E-mini NASDAQ 100 Futures (CME: NQ) +
    • +
    • + + Futures.Indices.Nikkei225Dollar + + + Futures.Indices.NIKKEI_225_DOLLAR + + : Nikkei-225 Dollar Futures (CME: NKD) +
    • +
    • + + Futures.Indices.Nikkei225YenCME + + + Futures.Indices.NIKKEI_225_YEN_CME + + : Nikkei-225 Yen denominated Futures on CME (CME: NIY) +
    • +
    • + + Futures.Indices.Russell1000EMini + + + Futures.Indices.RUSSELL_1000_E_MINI + + : E-mini Russell 1000 futures on CME (CME: RS1) +
    • +
    • + + Futures.Indices.Russell2000EMini + + + Futures.Indices.RUSSELL_2000_E_MINI + + : E-mini Russell 2000 Futures (CME: RTY) +
    • +
    • + + Futures.Indices.SPGSCICommodity + + + Futures.Indices.SPGSCI_COMMODITY + + : S&P-GSCI Commodity Index Futures (CME: GD) +
    • +
    • + + Futures.Indices.SP400MidCapEmini + + + Futures.Indices.SP_400_MID_CAP_EMINI + + : E-mini S&P MidCap 400 Futures (CME: EMD) +
    • +
    • + + Futures.Indices.SP500AnnualDividendIndex + + + Futures.Indices.SP_500_ANNUAL_DIVIDEND_INDEX + + : (CME: SDA) +
    • +
    • + + Futures.Indices.SP500EMini + + + Futures.Indices.SP_500_E_MINI + + : E-mini S&P 500 Futures (CME: ES) +
    • +
    • + + Futures.Indices.TOPIXYEN + + : YEN Denominated Topix Index Futures on CME (CME: TPY) +
    • +
    • + + Futures.Indices.USDDenominatedIbovespa + + + Futures.Indices.USD_DENOMINATED_IBOVESPA + + : USD-Denominated Ibovespa Index Futures (CME: IBV) +
    • +
    • + + Futures.Indices.VIX + + : CBOE Volatility Index Futures (CFE: VX) +
    • +
    • + + Futures.Meats.FeederCattle + + + Futures.Meats.FEEDER_CATTLE + + : Feeder Cattle Futures (CME: GF) +
    • +
    • + + Futures.Meats.LeanHogs + + + Futures.Meats.LEAN_HOGS + + : Lean Hogs Futures (CME: HE) +
    • +
    • + + Futures.Meats.LiveCattle + + + Futures.Meats.LIVE_CATTLE + + : Live Cattle Futures (CME: LE) +
    • +
    • + + Futures.Metals.AluminiumEuropeanPremiumDutyPaidMetalBulletin + + + Futures.Metals.ALUMINIUM_EUROPEAN_PREMIUM_DUTY_PAID_METAL_BULLETIN + + : Aluminium European Premium Duty-Paid (Metal Bulletin) Futures (COMEX: EDP) +
    • +
    • + + Futures.Metals.AluminumMWUSTransactionPremiumPlatts25MT + + + Futures.Metals.ALUMINUM_MWUS_TRANSACTION_PREMIUM_PLATTS_25_MT + + : Aluminum MW U.S. Transaction Premium Platts (25MT) Futures (COMEX: AUP) +
    • +
    • + + Futures.Metals.Copper + + + Futures.Metals.COPPER + + : Copper Futures (COMEX: HG) +
    • +
    • + + Futures.Metals.Gold + + + Futures.Metals.GOLD + + : Gold Futures (COMEX: GC) +
    • +
    • + + Futures.Metals.MicroGold + + + Futures.Metals.MICRO_GOLD + + : Micro Gold Futures (COMEX: MGC) +
    • +
    • + + Futures.Metals.MicroGoldTAS + + + Futures.Metals.MICRO_GOLD_TAS + + : Micro Gold TAS Futures (COMEX: MGT) +
    • +
    • + + Futures.Metals.MicroPalladium + + + Futures.Metals.MICRO_PALLADIUM + + : Micro Palladium Futures (NYMEX: PAM) +
    • +
    • + + Futures.Metals.MicroSilver + + + Futures.Metals.MICRO_SILVER + + : Micro Silver Futures (COMEX: SIL) +
    • +
    • + + Futures.Metals.Palladium + + + Futures.Metals.PALLADIUM + + : Palladium Futures (NYMEX: PA) +
    • +
    • + + Futures.Metals.Platinum + + + Futures.Metals.PLATINUM + + : Platinum Futures (NYMEX: PL) +
    • +
    • + + Futures.Metals.Silver + + + Futures.Metals.SILVER + + : Silver Futures (COMEX: SI) +
    • +
    • + + Futures.Metals.USMidwestDomesticHotRolledCoilSteelCRUIndex + + + Futures.Metals.US_MIDWEST_DOMESTIC_HOT_ROLLED_COIL_STEEL_CRU_INDEX + + : U.S. Midwest Domestic Hot-Rolled Coil Steel (CRU) Index Futures (NYMEX: HRC) +
    • +
    • + + Futures.Softs.Sugar11 + + + Futures.Softs.SUGAR_11 + + : Sugar #11 Futures ICE (ICE: SB) +
    • +
    • + + Futures.Softs.Sugar11CME + + + Futures.Softs.SUGAR_11_CME + + : Sugar #11 Futures CME (NYMEX: YO) +
    • +
    + + + +

    Example Applications

    + + +

    + The US Futures Security Master enables you to design strategies harnessing continuous Futures contracts. Examples include the following strategies: +

    +
      +
    • + Trading cyclical patterns in commodity Futures. +
    • +
    • + Buying gold Futures as an inflation hedge with automatic contract roll-overs. +
    • +
    • + Detecting arbitrage opportunities between index Futures and Equities. +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys the continuous Future contract for Crude Oil when its price rises above its simple moving average. When its price drops below its simple moving average, the algorithm sells the continuous contract. Each time the continuous Future contract rolls over, the algorithm logs the event. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class USFuturesSecurityMasterDataClassicAlgorithm(QCAlgorithm):
    +    # Define a threshold for the SMA cross.
    +    _threshold = 0.01
    +    
    +    def initialize(self) -> None:
    +        self.set_cash(1000000)
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        # Seed the price of each asset with its last known price to 
    +        # avoid trading errors.
    +        self.settings.seed_initial_prices = True
    +        # Add a Future. Set the continuous contract mapping criteria to
    +        # the contract with highest open interest to provide the best 
    +        # price information for trend estimation.
    +        self._future = self.add_future(
    +            Futures.Energy.CRUDE_OIL_WTI,
    +            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +            contract_depth_offset=0
    +        )                      
    +        # Historical data: Get the contract rollovers for the trailing 
    +        # year.
    +        history = self.history(
    +            SymbolChangedEvent, self._future.symbol, timedelta(365)
    +        )
    +        # Set up an SMA indicator for to estimate the trend direction.
    +        self._sma = self.sma(self._future.symbol, 10, Resolution.DAILY)
    +        # Warm up the SMA indicator so we can trade right away.
    +        self.warm_up_indicator(self._future.symbol, self._sma)
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Wait until we have the latest TradeBar and the indicator is 
    +        # ready.
    +        if not (self._future.symbol in slice.bars and self._sma.is_ready):
    +            return
    +        contract = self.portfolio[self._future.mapped]
    +        # Long during an uptrend.
    +        if (not contract.is_long and 
    +            self._future.price > self._sma.current.value * (1+self._threshold)):
    +            quantity = 1
    +        # Short during an downtrend.
    +        elif (not contract.is_short and 
    +            self._future.price < self._sma.current.value * (1-self._threshold)):
    +            quantity = -1
    +        else:
    +            return
    +        self.market_order(self._future.mapped, quantity - contract.quantity)
    +
    +    def on_symbol_changed_events(self, symbol_changed_events):
    +        for symbol, changed_event in symbol_changed_events.items():
    +            old_symbol = changed_event.old_symbol
    +            new_symbol = changed_event.new_symbol
    +            # The quantity to roll over should be consistent.
    +            quantity = self.portfolio[old_symbol].quantity
    +            if not quantity:
    +                continue
    +            # Rolling over: Liquidate the old mapped contract and switch
    +            # to the new mapped contract.
    +            tag = f"Rollover: {old_symbol} -> {new_symbol}"
    +            self.liquidate(old_symbol, tag=tag)
    +            self.market_order(new_symbol, quantity, tag=tag)
    +
    public class USFuturesSecurityMasterDataClassicAlgorithm  : QCAlgorithm
    +{
    +    private Future _future;
    +    // Define a threshold for the SMA cross.
    +    private decimal _threshold = 0.01m;
    +    private SimpleMovingAverage _sma;
    +    
    +    public override void Initialize()
    +    {
    +        SetCash(1000000);
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        // Seed the price of each asset with its last known price to 
    +        // avoid trading errors.
    +        Settings.SeedInitialPrices = true;
    +        // Add a Future. Set the continuous contract mapping criteria to
    +        // the contract with highest open interest to provide the best 
    +        // price information for trend estimation.
    +        _future = AddFuture(
    +            Futures.Energy.CrudeOilWTI,
    +            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +            dataMappingMode: DataMappingMode.OpenInterest,
    +            contractDepthOffset: 0
    +        );
    +        // Historical data: Get the contract rollovers for the trailing 
    +        // year.
    +        var history = History<SymbolChangedEvent>(_future.Symbol, TimeSpan.FromDays(365));
    +        foreach (var symbolChangedEvent in history)
    +        {
    +            var t = symbolChangedEvent.EndTime;
    +            var oldSymbol = symbolChangedEvent.OldSymbol;
    +            var newSymbol = symbolChangedEvent.NewSymbol;
    +        }
    +        // Set up an SMA indicator for to estimate the trend direction.
    +        _sma = SMA(_future.Symbol, 10, Resolution.Daily);
    +        // Warm up the SMA indicator so we can trade right away.
    +        WarmUpIndicator(_future.Symbol, _sma);
    +    }
    +    
    +    public override void OnData(Slice slice)
    +    {       
    +        // Wait until we have the latest TradeBar and the indicator is 
    +        // ready.
    +        if (!(slice.Bars.ContainsKey(_future.Symbol) && _sma.IsReady))
    +        {
    +            return;
    +        }
    +        var contract = Portfolio[_future.Mapped];
    +        int quantity;
    +        // Long during an uptrend.
    +        if (!contract.IsLong && _future.Price > _sma.Current.Value * (1+_threshold))
    +        {
    +            quantity = 1;
    +        }
    +        // Short during an downtrend.
    +        else if (!contract.IsShort && _future.Price < _sma.Current.Value * (1-_threshold))
    +        {
    +            quantity = -1;
    +        }
    +        else
    +        {
    +            return;
    +        }
    +        MarketOrder(_future.Mapped, quantity - contract.Quantity);
    +    }
    +
    +    public override void OnSymbolChangedEvents(SymbolChangedEvents symbolChangedEvents)
    +    {
    +        foreach (var (symbol, changedEvent) in symbolChangedEvents)
    +        {
    +            var oldSymbol = changedEvent.OldSymbol;
    +            var newSymbol = changedEvent.NewSymbol;
    +            // The quantity to roll over should be consistent.
    +            var quantity = Portfolio[oldSymbol].Quantity;
    +            if (quantity == 0)
    +            {
    +                continue;
    +            }
    +            // Rolling over: Liquidate the old mapped contract and switch 
    +            // to the new mapped contract.
    +            var tag = $"Rollover: {oldSymbol} -> {newSymbol}";
    +            Liquidate(oldSymbol, tag: tag);
    +            MarketOrder(newSymbol, quantity, tag: tag);
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm buys the continuous Future contract for Crude Oil when its price rises above its simple moving average. When its price drops below its simple moving average, the algorithm sells the continuous contract. Each time the contract rolls over, the algorithm logs the event. +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class USFuturesSecurityMasterDataFrameworkAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_cash(1000000)
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +
    +        # Setting the continuous contract mapping criteria, the contract with highest open interest provide the best price information for trend estimation
    +        self.add_future(Futures.Energies.CRUDE_OIL_WTI,
    +                       data_normalization_mode = DataNormalizationMode.BACKWARDS_RATIO,
    +                       data_mapping_mode = DataMappingMode.OPEN_INTEREST,
    +                       contract_depth_offset = 0)
    +        self.add_alpha(ContinuousFuturesAlphaModel())
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +
    +class ContinuousFuturesAlphaModel(AlphaModel):
    +    # 1% margin to reassure trend direction
    +    threshold = 0.01
    +    symbol = None
    +    continuous_contract = None
    +    
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        insights = []
    +        # Check if contract data available, since all trades are based on that only
    +        if self.continuous_contract_symbol is None or self.continuous_contract is None:
    +            return insights 
    +        
    +        # Up-to-date handling of switching the mapped contract for trade liquidity
    +        for symbol, changed_event in slice.symbol_changed_events.items():
    +            old_symbol = changed_event.old_symbol
    +            if algorithm.insights.has_active_insights(old_symbol, algorithm.utc_time):
    +                new_symbol = changed_event.new_symbol
    +                tag = f"Rollover - Symbol changed at {algorithm.time}: {old_symbol} -> {new_symbol}"
    +                last_insight = sorted(algorithm.insights[old_symbol], key=lambda x: x.close_time_utc)[-1]
    +                insights.append(Insight.price(new_symbol, last_insight.close_time_utc, last_insight.direction, tag= tag))
    +                algorithm.insights.clear([old_symbol])
    +                algorithm.log(tag)
    +         
    +        mapped_symbol = self.continuous_contract.mapped
    +        # Make sure trade decisions are based on newly received data
    +        if not slice.bars.contains_key(self.continuous_contract_symbol) or not self.sma.is_ready or not mapped_symbol:
    +            return insights 
    +        
    +        direction = None
    +        # Long if trend up by threshold to follow the trend
    +        if slice.bars[self.continuous_contract_symbol].price > self.sma.current.value * (1+self.threshold) and not algorithm.portfolio[mapped_symbol].is_long:
    +            direction = InsightDirection.UP
    +        # Short if trend down by threshold to follow the trend
    +        elif slice.bars[self.continuous_contract_symbol].price < self.sma.current.value * (1-self.threshold) and not algorithm.portfolio[mapped_symbol].is_short:
    +            direction = InsightDirection.DOWN
    +        
    +        if direction:
    +            insights.append(Insight.price(mapped_symbol, timedelta(days=14), direction))
    +        
    +        return insights
    +        
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            symbol = security.symbol
    +            # Set up SMA indicator for trend direction estimator, only for the canonical symbol
    +            if symbol.is_canonical():
    +                self.continuous_contract = security
    +                self.continuous_contract_symbol = symbol
    +                self.sma = algorithm.SMA(self.continuous_contract_symbol, 10, Resolution.DAILY)
    +            
    +                # Historical data
    +                history = algorithm.history(symbol, 60*24*10, Resolution.MINUTE)
    +                algorithm.debug(f"We got {len(history)} from our history request for {symbol}")
    +                
    +                if history.empty:
    +                    continue
    +                # Warm up the SMA indicator for its readiness for immediate use
    +                for time, row in history.droplevel(0).loc[self.continuous_contract_symbol].iterrows():
    +                    self.sma.update(IndicatorDataPoint(time, row.close))
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class USFuturesSecurityMasterDataFrameworkAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetCash(1000000);
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +
    +        // Setting the continuous contract mapping criteria, the contract with highest open interest provide the best price information for trend estimation
    +        AddFuture(Futures.Energies.CrudeOilWTI,
    +            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +            dataMappingMode: DataMappingMode.OpenInterest,
    +            contractDepthOffset: 0
    +        );
    +        AddAlpha(new ContinuousFuturesAlphaModel());
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +    
    +    class ContinuousFuturesAlphaModel : AlphaModel
    +    {
    +        private Future _continuousContract;
    +        private Symbol _symbol;
    +        // 1% margin to reassure trend direction
    +        private decimal _threshold = 0.01m;
    +        private SimpleMovingAverage _sma;
    +    
    +        public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +        {
    +            var insights = new List<Insight>();
    +            
    +            //  Check if contract data available, since all trades are based on that only
    +            if (_symbol == null || _continuousContract == null)
    +            {
    +                return insights;
    +            }
    +            
    +            // Up-to-date handling of switching the mapped contract for trade liquidity
    +            foreach (var (symbol, changedEvent) in slice.SymbolChangedEvents)
    +            {
    +                var oldSymbol = changedEvent.OldSymbol;
    +                if (algorithm.Insights.HasActiveInsights(oldSymbol, algorithm.UtcTime))
    +                {
    +                    var newSymbol = changedEvent.NewSymbol;
    +                    var tag = $"Rollover - Symbol changed at {algorithm.Time}: {oldSymbol} -> {newSymbol}";
    +                    var lastInsight = algorithm.Insights[oldSymbol].OrderBy(x => x.CloseTimeUtc).LastOrDefault();
    +                    insights.Add(Insight.Price(newSymbol, lastInsight.CloseTimeUtc, lastInsight.Direction, tag: tag));
    +                    algorithm.Insights.Clear(new Symbol[] { oldSymbol });
    +                    algorithm.Log(tag);
    +                }
    +            }
    +            
    +            var mappedSymbol = _continuousContract.Mapped;
    +            // Make sure trade decisions are based on newly received data
    +            if (!slice.Bars.ContainsKey(_symbol) || !_sma.IsReady || mappedSymbol == null)
    +            {
    +                return insights;
    +            }
    +            
    +            // Long if trend up by threshold to follow the trend
    +            if (slice.Bars[_symbol].Price > _sma.Current.Value * (1+_threshold) && !algorithm.Portfolio[mappedSymbol].IsLong)
    +            {
    +                insights.Add(Insight.Price(mappedSymbol, TimeSpan.FromDays(14), InsightDirection.Up));
    +            }
    +            // Short if trend down by threshold to follow the trend
    +            else if (slice.Bars[_symbol].Price < _sma.Current.Value * (1-_threshold) && !algorithm.Portfolio[mappedSymbol].IsShort)
    +            {
    +                insights.Add(Insight.Price(mappedSymbol, TimeSpan.FromDays(14), InsightDirection.Down));
    +            }
    +            
    +            return insights;
    +        }
    +    
    +        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +        {
    +            foreach (var security in changes.AddedSecurities)
    +            {
    +                var symbol = security.Symbol;
    +                // Set up SMA indicator for trend direction estimator, only for the canonical symbol
    +                if (symbol.IsCanonical())
    +                {
    +                    _continuousContract = (Future)security;
    +                    _symbol = symbol;
    +                    _sma = algorithm.SMA(_symbol, 10, Resolution.Daily);
    +                    
    +                    // Historical data 
    +                    var history = algorithm.History(symbol, 60*24*10, Resolution.Minute);
    +                    algorithm.Debug($"We got {history.Count()} from our history request for {symbol}");
    +                    
    +                    // Warm up the SMA indicator for its readiness for immediate use
    +                    foreach (var bar in history)
    +                    {
    +                        _sma.Update(new IndicatorDataPoint(bar.Time, bar.Close));
    +                    }
    +                }
    +            }
    +        }
    +    }
    +    
    +    class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +    {
    +        public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +        {
    +            var targets = new List<PortfolioTarget>();
    +            foreach (var insight in insights)
    +            {
    +                if (algorithm.Securities[insight.Symbol].IsTradable)
    +                {
    +                    targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +                }
    +            }
    +            return targets;
    +        }
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Futures Security Master dataset provides + + SymbolChangedEvent + + objects, which have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    QuantConnect

    +

    US Index Option Universe

    +
    +
    +

    Introduction

    + + +

    + The US Index Option Universe dataset by QuantConnect lists the available US Index Options contracts and the current Implied Volatility and Greeks. The data covers European Option contracts for 3 US Indices: SPX, VIX, and NDX. It starts in January 2012 and is delivered on a daily update frequency. To create this dataset, we use + + our implementation + + of the forward tree pricing model, which accounts for the interest rate, dividend payments, and daily closing prices. The values in this dataset are the same values you can get from daily + + indicators + + with mirror Options. +

    +

    + This dataset + + does not + + contain market data. For market data, see + + US Index Options by AlgoSeek + + . +

    +

    + For more information about the US Index Option Universe dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Index Options Universe dataset: +

    +
    +
    option = self.add_index_option('VIX')
    +option.set_filter(lambda universe: universe.delta(0.4, 0.6))
    +self.option_symbol = option.symbol
    +
    var option = AddIndexOption("VIX");
    +option.SetFilter(universe => universe.delta(0.4m, 0.6m));
    +_optionSymbol = option.Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2012 +
    + Asset Coverage + + 7 Index Options +
    + Data Density + + Dense +
    + Resolution + + Daily +
    + Timezone + + New York +
    + + + +

    Specification Over Time

    + + +

    + According to the SPX Options + + contract specification + + , some SPX contracts expire every month and SPXW contracts expires every day. Before 2021, you could only trade SPX contracts with the following expiration dates: +

    +
      +
    • + Expires within the next 4 months +
    • +
    • + Expires in September within the next 14 months +
    • +
    • + Expires in January, March, or June within the next 2 years +
    • +
    • + Expires in December within the next 3 years +
    • +
    +

    + During this time, SPXW didn't have 0DTE every day. +

    +

    + + Sources + + : +
    + - + + Cboe Options Exchange to List Three Long-Dated SPX Options Expirations, Beginning November 1, 2021 + +
    + - + + S&P 500 Weekly Options Now Expire Five Days a Week + +

    + + + +

    Requesting Data

    + + +

    + To add US Index Options Universe data to your algorithm, call the + + AddIndexOption + + + add_index_option + + method. Save a reference to the Index Option + + Symbol + + so you can access the data later in your algorithm. To define which contracts should be in your universe, call the + + SetFilter + + + set_filter + + method of the + + IndexOption + + object. +

    +

    + The + + AddIndexOption + + + add_index_option + + method provides a daily stream of Option chain data. To get the most recent daily chain, call the + + OptionChain + + + option_chain + + method with the canonical Index Option Symbol. The + + OptionChain + + + option_chain + + method returns data on all the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    class IndexOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2021, 1, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(1_000_000)
    +        self.universe_settings.asynchronous = True
    +        self.index_symbol = self.add_index('VIX').symbol
    +        
    +        standard_option = self.add_index_option(self.index_symbol)
    +        standard_option.set_filter(self._option_filter)
    +        self.standard_option_symbol = standard_option.symbol
    +        standard_chain = self.option_chain(standard_option.symbol, flatten=True).data_frame
    +
    +        weekly_option = self.add_index_option(self.index_symbol, "VIXW")
    +        weekly_option.set_filter(self._option_filter)
    +        self.weekly_option_symbol = weekly_option.symbol
    +        weekly_chain = self.option_chain(weekly_option.symbol, flatten=True).data_frame
    +        weekly_chain = weekly_chain[
    +            weekly_chain.index.map(lambda symbol: not IndexOptionSymbol.is_standard(symbol))
    +        ]
    +        
    +
    +    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Contracts can be filtered by greeks, implied volatility, open interest:
    +        return universe \
    +            .delta(0.5, 1.5) \
    +            .gamma(0.0001, 0.0006) \
    +            .vega(0.01, 1.5) \
    +            .theta(-2.0, -0.5) \
    +            .rho(0.5, 3.0) \
    +            .implied_volatility(1, 3) \
    +            .open_interest(100,500)
    +
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _indexSymbol, _standardOptionSymbol, _weeklyOptionSymbol;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2021, 1, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        _indexSymbol = AddIndex("VIX").Symbol;
    +
    +        var standardOption = AddIndexOption(_indexSymbol);
    +        standardOption.SetFilter(OptionFilter);
    +        _standardOptionSymbol = standardOption.Symbol;
    +        var standardChain = OptionChain(_standardOptionSymbol);
    +
    +        var weeklyOption = AddIndexOption(_indexSymbol, "VIXW");
    +        weeklyOption.SetFilter(OptionFilter);
    +        _weeklyOptionSymbol = weeklyOption.Symbol;
    +        var weeklyChain = OptionChain(_weeklyOptionSymbol)
    +            .Where(contract => !IndexOptionSymbol.IsStandard(contract.Symbol));
    +    }
    +
    +    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    +    {
    +        // Contracts can be filtered by greeks, implied volatility, open interest:
    +        return universe
    +            .Delta(0.5m, 1.5m)
    +            .Gamma(0.0001m, 0.0006m)
    +            .Vega(0.01m, 1.5m)
    +            .Theta(-2.0m, -0.5m)
    +            .Rho(0.5m, 3.0m)
    +            .ImpliedVolatility(1.0m, 3.0m)
    +            .OpenInterest(100, 500);
    +    }
    +}
    +
    +

    + The Index resolution must be less than or equal to the Index Option resolution. For example, if you set the Index resolution to minute, then you must set the Index Option resolution to minute, hour, or daily. +

    +

    + For more information about creating US Index Option subscriptions, see + + Index Options + + . +

    + + + +

    Accessing Data

    + + +

    + For information about accessing US Equity Options data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Index Options data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Index Options Universe data in an algorithm, call the + + History<OptionUniverse> + + + history + + method with the canonical Index Option + + Symbol + + . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.standard_option_symbol, timedelta(3))
    +
    +# OptionUniverse objects
    +history = self.history[OptionUniverse](self.standard_option_symbol, timedelta(3))
    +
    // OptionUniverse objects 
    +var history = History<OptionUniverse>(_standardOptionSymbol, TimeSpan.FromDays(3)).ToList();
    +
    +

    + For more information about Index Options Universe data in algorithms, see + + Historical Data + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Index Options Universe data in the Research Environment, call the + + History<OptionUniverse> + + + history + + method with the canonical Option + + Symbol + + . This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. +

    +
    +
    qb = QuantBook()
    +index_symbol = qb.add_index('VIX').symbol
    +option = qb.add_index_option(index_symbol) # or qb.add_index_option(index_symbol, "VIXW")
    +history = qb.history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    +
    var qb = new QuantBook();
    +var indexSymbol = qb.AddIndex("VIX").Symbol;
    +var option = qb.AddIndexOption(indexSymbol); // or qb.AddIndexOption(indexSymbol, "VIXW");
    +var history = qb.History<OptionUniverse>(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 6));
    +foreach (var chain in history)
    +{
    +    var endTime = chain.EndTime;
    +    var filteredContracts = chain.Data
    +        .Select(contract => contract as OptionUniverse)
    +        .Where(contract => contract.Greeks.Delta > 0.3m);
    +    foreach (var contract in filteredContracts)
    +    {
    +        var price = contract.Price;
    +        var iv = contract.ImpliedVolatility;
    +    }
    +}
    +
    +

    + For more information about historical Index Options Universe data in the Research Environment, see + + Universes + + . +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available Index Options: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Underlying Index + + Underlying Ticker + + Target Ticker + + Standard Contracts + + Weekly Contracts + + Tradable on Expiry Day +
    + NASDAQ-100 + + NDX + + + green check + + +
    + NASDAQ-100 + + NDX + + NDXP + + green check + + + green check +
    + NASDAQ-100 + + NDX + + NQX + + green check + + green check + + green check +
    + Russell 2000 + + RUT + + + green check + + +
    + Russell 2000 + + RUT + + RUTW + + + green check + + green check +
    + S&P500 + + SPX + + + green check + + +
    + S&P500 + + SPX + + SPXW + + + green check + + green check +
    + S&P500 + + VIX + + + green check + + +
    + S&P500 + + VIX + + VIXW + + + green check + +
    +

    + For more information about each underlying Index, see + + Supported Indices + + . +

    + + + +

    Example Applications

    + + +

    + The US Index Options Universe dataset enables you to accurately design strategies for Index Options. Examples include the following strategies: +

    +
      +
    • + Buying VIX call Options to hedge against upcoming volatility +
    • +
    • + Buying VIX put Options to capture the natural downward price movement in the VIX index +
    • +
    • + Buying SPX put Options to protect against downward price movement in the S&P 500 +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm subscribes to SPX put options that fall within delta range between -1 and -0.95, open interest range between 10 and 1000, and expire within seven days. Within this Option chain, the algorithm holds the put Option contract that has the minimum delta (closest to -1) during market hour to hedge the underlying intra-day movement completely. It avoid volatility from sentiment and only earns from inter-day movement from longer-term factors. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. +

    +
    +
    from AlgorithmImports import *
    +
    +class IndexOptionsUniverseAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(10000000)
    +
    +        # Asynchronous can use computational resources efficiently
    +        self.universe_settings.asynchronous = True
    +        # Subscribe to the underlying for the underlying position
    +        # Set the data normalization mode to raw for strike price comparability
    +        self.index = self.add_index("SPX").symbol
    +        # Requesting option data and filter for the hedge candidates
    +        option = self.add_index_option(self.index)
    +        option.set_filter(self.option_filter)
    +        self.option_symbol = option.symbol
    +
    +        # Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    +        self.schedule.on(
    +            self.date_rules.every_day(self.index),
    +            self.time_rules.after_market_open(self.index, 1),
    +            self.buy_hedge_contract
    +        )
    +
    +        # Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    +        # Leave 2 minutes contingency to fill
    +        self.schedule.on(
    +            self.date_rules.every_day(self.index),
    +            self.time_rules.before_market_close(self.index, 2),
    +            self.sell_hedge_contract
    +        )
    +
    +        self.hedge = None
    +        
    +    def option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Select the contracts with delta very close to -1 and high open interest
    +        # This can effectively hedge most of the price change of the underlying and ensure the liquidity
    +        # Make sure the contract is expiring close for its tradbility
    +        return universe.puts_only().expiration(2, 7).delta(-1, -0.95).open_interest(10, 1000)
    +
    +    def buy_hedge_contract(self) -> None:
    +        chain = self.current_slice.option_chains.get(self.option_symbol)
    +        if chain:
    +            # Order the underlying if not hold, the order size should match the option contract
    +            # Order only if option chain data ready for hedging
    +            if not self.portfolio[self.index].invested:
    +                self.market_order(self.index, self.securities[self.option_symbol].symbol_properties.contract_multiplier)
    +
    +            # Get the contract with delta closest to -1 (lowest possible delta)
    +            contract = sorted(chain, key=lambda x: x.greeks.delta)[0]
    +            self.hedge = contract.symbol
    +            # Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    +            self.market_order(self.hedge, 1)
    +        
    +    def sell_hedge_contract(self) -> None:
    +        # Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    +        if self.hedge:
    +            self.liquidate(self.hedge)
    +            self.hedge = None
    +
    public class IndexOptionsUniverseAlgorithm : QCAlgorithm
    +{
    +    private Symbol _index, _optionSymbol, _hedge;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(10000000);
    +        // Asynchronous can use computational resources efficiently
    +        UniverseSettings.Asynchronous = true;
    +
    +        // Subscribe to the underlying for the underlying position
    +        // Set the data normalization mode to raw for strike price comparability
    +        _index = AddIndex("SPX").Symbol;
    +        // Requesting option data and filter for the hedge candidates
    +        var option = AddIndexOption(_index);
    +        _optionSymbol = option.Symbol;
    +        option.SetFilter(OptionFilter);
    +
    +        // Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
    +        Schedule.On(
    +            DateRules.EveryDay(_index),
    +            TimeRules.AfterMarketOpen(_index, 1),
    +            BuyHedgeContract
    +        );
    +
    +        // Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
    +        // Leave 2 minutes contingency to fill
    +        Schedule.On(
    +            DateRules.EveryDay(_index),
    +            TimeRules.BeforeMarketClose(_index, 2),
    +            SellHedgeContract
    +        );
    +    }
    +
    +    private OptionFilterUniverse OptionFilter(OptionFilterUniverse universe)
    +    {
    +        // Select the contracts with delta very close to -1 and high open interest
    +        // This can effectively hedge most of the price change of the underlying and ensure the liquidity
    +        // Make sure the contract is expiring close for its tradbility
    +        return universe
    +            .PutsOnly()
    +            .Expiration(2, 7)
    +            .Delta(-1m, -0.95m)
    +            .OpenInterest(10, 1000);
    +    }
    +
    +    private void BuyHedgeContract()
    +    {
    +        if (CurrentSlice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    +        {
    +            // Order the underlying if not hold, the order size should match the option contract
    +            // Order only if option chain data ready for hedging
    +            if (!Portfolio[_index].Invested)
    +            {
    +                MarketOrder(_index, Securities[_optionSymbol].SymbolProperties.ContractMultiplier);
    +            }
    +
    +            // Get the contract with delta closest to -1 (lowest possible delta)
    +            var contract = chain.MinBy(x => x.Greeks.Delta);
    +            _hedge = contract.Symbol;
    +            // Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
    +            MarketOrder(_hedge, 1);
    +        }
    +    }
    +
    +    private void SellHedgeContract()
    +    {
    +        // Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
    +        if (_hedge != null)
    +        {
    +            Liquidate(_hedge);
    +            _hedge = null;
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm demonstrating a Gamma Scalping strategy through framework algorithm. It filters SPX options with expiration between 30 to 90 days and open interest between 50 and 1000, due to liquidity concern and lower Gamma fluctuation. Assuming a significant upward trend is expecting, it orders a long straddle strategy from the strike price with Delta-neutral and the highest Gamma to earn the highest profit from upward underlying movement. +

    +
    +
    from AlgorithmImports import *
    +
    +class IndexOptionsUniverseFrameworkAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 12, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1000000)
    +        # Asynchronous can use computational resources efficiently
    +        self.universe_settings.asynchronous = True
    +
    +        # Universe selection that select based on liquidity of the option contracts (by open interest)
    +        self.add_universe_selection(IndexOptionsUniverseSelectionModel())
    +        # Custom alpha model that use Delta and Gamma to signal insights
    +        self.add_alpha(OptionDeltaGammaAlphaModel())
    +        # To maintain long-short size equal, use a PCM that order a single contract
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +
    +class IndexOptionsUniverseSelectionModel(OptionUniverseSelectionModel):
    +    def __init__(self) -> None:
    +        # Daily update with the select_option_chain_symbols function
    +        super().__init__(timedelta(1), self.select_option_chain_symbols)
    +
    +    def select_option_chain_symbols(self, dt: datetime) -> List[Symbol]:
    +        # Select only SPX options as our focus, which is a highly traded volatile index with great upward momentum
    +        return [Symbol.create("SPX", SecurityType.INDEX_OPTION, Market.USA)]
    +
    +    def filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    +        # A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    +        return universe.expiration(30, 90).open_interest(50, 1000)
    +
    +class OptionDeltaGammaAlphaModel(AlphaModel):
    +    def __init__(self) -> None:
    +        # A day count variable to control the alpha model only trade once a day
    +        self._day = -1
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        insights = []
    +
    +        if self._day != slice.time.day:
    +            # We open position for each option underlying as separate bet
    +            for _, chain in slice.option_chains.items():
    +                # For theta-neutral, select the same expiry for both call and put
    +                expiry = min(x.expiry for x in chain)
    +                contracts = [x for x in chain if x.expiry == expiry]
    +
    +                # Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    +                delta_gamma_symbols = []
    +                strikes = set(x.strike for x in contracts if len([y for y in contracts if y.strike == x.strike]) == 2)
    +                for strike in strikes:
    +                    # Get both call and put for their aggregated delta and gamma
    +                    call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == strike, contracts))
    +                    put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == strike, contracts))
    +                    delta_gamma_symbols.append((call.greeks.delta + put.greeks.delta, call.greeks.gamma + put.greeks.gamma, call.symbol, put.symbol))
    +                
    +                if len(delta_gamma_symbols) == 0:
    +                    continue
    +
    +                # We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    +                # Less than 2d.p. difference is non-significant, which we can risk for better reward
    +                # Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    +                # Make sure the aggregated gamma to be positive to bet on large uptrend
    +                # So it will earn more when the price really go up higher and higher, but locally immune for small noise
    +                filtered = [item for item in delta_gamma_symbols if round(item[0], 2) <= 0.01 and item[1] > 0]
    +                if len(filtered) == 0:
    +                    continue
    +                selected = sorted(filtered, key=lambda x: x[1])[0]
    +
    +                # Provide trade signal and roll the day count to let the position stay for the whole day
    +                selected_call = selected[2]
    +                selected_put = selected[3]
    +                insights.extend([
    +                    Insight.price(selected_call, Expiry.END_OF_DAY, InsightDirection.UP),
    +                    Insight.price(selected_put, Expiry.END_OF_DAY, InsightDirection.UP)
    +                ])
    +                self._day = slice.time.day
    +        
    +        return insights
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                # Use a whole number target to order the exact number of share for size-matching
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class IndexOptionsUniverseFrameworkAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 12, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000000);
    +        // Asynchronous can use computational resources efficiently
    +        UniverseSettings.Asynchronous = true;
    +
    +        // Universe selection that select based on liquidity of the option contracts (by open interest)
    +        AddUniverseSelection(new IndexOptionsUniverseSelectionModel());
    +        // Custom alpha model that use Delta and Gamma to signal insights
    +        AddAlpha(new OptionDeltaGammaAlphaModel());
    +        // To maintain long-short size equal, use a PCM that order a single contract
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}       
    +    
    +class IndexOptionsUniverseSelectionModel : OptionUniverseSelectionModel
    +{
    +    // Daily update with the SelectOptionChainSymbols function
    +    public IndexOptionsUniverseSelectionModel()
    +            : base(TimeSpan.FromDays(1), SelectOptionChainSymbols) {}
    +    
    +    private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
    +    {
    +        // Select only SPX options as our focus, which is a highly traded volatile index with great upward momentum
    +        return new[] {QuantConnect.Symbol.Create("SPX", SecurityType.IndexOption, Market.USA)};
    +    }
    +
    +    protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
    +    {
    +        // To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
    +        // A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
    +        return filter
    +            .Expiration(30, 90)
    +            .OpenInterest(50, 1000);
    +    }
    +}
    +    
    +class OptionDeltaGammaAlphaModel : AlphaModel
    +{
    +    // A day count variable to control the alpha model only trade once a day
    +    private int _day = -1;
    +
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = new List<Insight>();
    +        
    +        if (_day != slice.Time.Day)
    +        {
    +            // We open position for each option underlying as separate bet
    +            foreach (var kvp in slice.OptionChains)
    +            {
    +                var chain = kvp.Value;
    +
    +                // For theta-neutral, select the same expiry for both call and put
    +                var expiry = chain.Min(x => x.Expiry);
    +                var contracts = chain.Where(x => x.Expiry == expiry).ToList();
    +
    +                // Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
    +                var deltaGammaSymbols = new List<(decimal, decimal, Symbol, Symbol)>();
    +                var strikes = contracts.Select(x => x.Strike)
    +                    .Where(x => contracts.Count(y => y.Strike == x) == 2)
    +                    .Distinct();
    +                foreach (var strike in strikes)
    +                {
    +                    // Get both call and put for their aggregated delta and gamma
    +                    var call = contracts.Single(x => x.Right == OptionRight.Call && x.Strike == strike);
    +                    var put = contracts.Single(x => x.Right == OptionRight.Put && x.Strike == strike);
    +                    deltaGammaSymbols.Add((call.Greeks.Delta + put.Greeks.Delta, call.Greeks.Gamma + put.Greeks.Gamma, call.Symbol, put.Symbol));
    +                }
    +
    +                if (deltaGammaSymbols.Count == 0)
    +                {
    +                    continue;
    +                }
    +
    +                // We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
    +                // Less than 2d.p. difference is non-significant, which we can risk for better reward
    +                // Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
    +                // Make sure the aggregated gamma to be positive to bet on large uptrend
    +                // So it will earn more when the price really go up higher and higher, but locally immune for small noise
    +                var filtered = deltaGammaSymbols.Where(item => Math.Round(item.Item1, 2) <= 0.01m && item.Item2 > 0).ToList();
    +                if (filtered.Count == 0)
    +                {
    +                    continue;
    +                }
    +                var selected = filtered.OrderByDescending(item => item.Item2).First();
    +
    +                // Provide trade signal and roll the day count to let the position stay for the whole day
    +                var selectedCall = selected.Item3;
    +                var selectedPut = selected.Item4;
    +                insights.AddRange(new[] {
    +                    Insight.Price(selectedCall, Expiry.EndOfDay, InsightDirection.Up),
    +                    Insight.Price(selectedPut, Expiry.EndOfDay, InsightDirection.Up)
    +                });
    +                _day = slice.Time.Day;
    +            }
    +        }
    +
    +        return insights;
    +    }
    +}
    +    
    +class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        var targets = new List<PortfolioTarget>();
    +        foreach (var insight in insights)
    +        {
    +            if (algorithm.Securities[insight.Symbol].IsTradable)
    +            {
    +                // Use a whole number target to order the exact number of share for size-matching
    +                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +            }
    +        }
    +        return targets;
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Index Options Universe dataset provides + + OptionFilterUniverse + + , + + OptionUniverse + + , and + + OptionChain + + objects. +

    +

    + OptionFilterUniverse Attributes +

    +

    + + OptionFilterUniverse + + objects have the following attributes: +

    +
    +
    +

    + OptionUniverse Attributes +

    +

    + + OptionUniverse + + objects have the following attributes: +

    +
    +
    +

    + OptionChain Attributes +

    +

    + + OptionChain + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    Datasets

    +

    AlgoSeek

    +
    +
    + + +
    +
    +

    + AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit + + algoseek.com + + . +

    +
    + +
    + + + +

     

    + +
    +
    +

    AlgoSeek

    +

    US Equities

    +
    +
    +

    Introduction

    + + +

    + The US Equities dataset by AlgoSeek is survivorship bias-free daily coverage of every stock traded in the US Securities Information Processors (SIP) CTA/UTP feed since 1998. The dataset covers approximately 27,500 securities, starts in January 1998, and is delivered in any resolution from tick to daily. The Data is collected from the full SIP feed via our Equinix co-located servers, including all trades and quotes published to every exchange as well as FINRA. Over-the-Counter (OTC) trades are not included. +

    +

    + This dataset depends on the + + US Equity Security Master + + dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. +

    +

    + For more information about the US Equities dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit + + algoseek.com + + . +

    + + + +

    Getting Started

    + + +

    + AlgoSeek is the default US Equities dataset on QuantConnect. The following snippet demonstrates how to request data from the US Equities dataset: +

    +
    +
    self.aapl = self.add_equity("AAPL", Resolution.DAILY).symbol
    +
    _aapl = AddEquity("AAPL", Resolution.Daily).Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 1998 +
    + Asset Coverage + + 27,500 US Equities +
    + Data Density + + Dense +
    + Resolution + + Tick, Second, Minute, Hourly, & Daily +
    + Timezone + + New York +
    + Market Hours + + + Regular and Extended + +
    + + + +

    Requesting Data

    + + +

    + To add US Equities data to your algorithm, call the + + AddEquity + + + add_equity + + method. Save a reference to the Equity + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class USEquityDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2018, 1, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000) 
    +        # Subscribe to AAPL data
    +        self.aapl = self.add_equity("AAPL", Resolution.MINUTE).symbol
    +
    public class USEquityDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol; 
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2018, 1, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        // Subscribe to AAPL data
    +        _symbol = AddEquity("AAPL", Resolution.Minute).Symbol;
    +    }
    +}
    +
    +

    + For more information about creating US Equity subscriptions, see + + Requesting Data + + or + + US Equity Universes + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current US Equities data, index the + + Bars + + + bars + + , + + QuoteBars + + + quote_bars + + , or + + Ticks + + + ticks + + properties of the current + + + Slice + + + with the Equity + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Access data: TradeBar data
    +    if self.aapl in slice.bars:
    +        trade_bar = slice.bars[self.aapl]
    +        self.log(f"{self.aapl} close at {slice.time}: {trade_bar.close}")
    +
    +    # Access data: QuoteBar data
    +    if self.aapl in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.aapl]
    +        self.log(f"{self.aapl} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    # Access data: Ticks data
    +    if self.aapl in slice.ticks:
    +        ticks = slice.ticks[self.aapl]
    +        for tick in ticks:
    +            self.log(f"{self.aapl} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    // Access data: TradeBar data
    +    if (slice.Bars.ContainsKey(_symbol))
    +    {
    +        var tradeBar = slice.Bars[_symbol];
    +        Log($"{_symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
    +    // Access data: QuoteBar data
    +    if (slice.QuoteBars.ContainsKey(_symbol))
    +    {
    +        var quoteBar = slice.QuoteBars[_symbol];
    +        Log($"{_symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    // Access data: Ticks data
    +    if (slice.Ticks.ContainsKey(_symbol))
    +    {
    +        var ticks = slice.Ticks[_symbol];
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{_symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + You can also iterate through all of the data objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Iterate all TradeBar received
    +    for symbol, trade_bar in slice.bars.items():
    +        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    +
    +    # Iterate all QuoteBar received
    +    for symbol, quote_bar in slice.quote_bars.items():
    +        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    # Iterate all Ticks received
    +    for symbol, ticks in slice.ticks.items():
    +        for tick in ticks:
    +            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    // Iterate all TradeBar received
    +    foreach (var kvp in slice.Bars)
    +    {
    +        var symbol = kvp.Key;
    +        var tradeBar = kvp.Value;
    +        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
    +    // Iterate all QuoteBar received
    +    foreach (var kvp in slice.QuoteBars)
    +    {
    +        var symbol = kvp.Key;
    +        var quoteBar = kvp.Value;
    +        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    // Iterate all Ticks received
    +    foreach (var kvp in slice.Ticks)
    +    {
    +        var symbol = kvp.Key;
    +        var ticks = kvp.Value;
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + For more information about accessing US Equities data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + To get historical US Equity data, call the + + History + + + history + + method with the Equity + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame
    +history_df = self.history(self.aapl, 100, Resolution.DAILY)
    +
    +# TradeBar objects
    +history_trade_bars = self.history[TradeBar](self.aapl, 100, Resolution.DAILY)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](self.aapl, 100, Resolution.MINUTE)
    +
    +# Tick objects
    +history_ticks = self.history[Tick](self.aapl, timedelta(seconds=10), Resolution.TICK)
    +
    // TradeBar objects 
    +var historyTradeBars = History(_symbol, 100, Resolution.Daily);
    +
    +// QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(_symbol, 100, Resolution.Minute);
    +
    +// Tick objects 
    +var historyTicks = History<Tick>(_symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +
    +

    + For more information about historical data, see + + History Requests + + . +

    + + + +

    Universe Selection

    + + +

    + To select a universe of US Equities, see + + Equity Universes + + . +

    + + + +

    Remove Subscriptions

    + + +

    + To unsubscribe from a US Equity that you added with the + + AddEquity + + + add_equity + + method, call the + + RemoveSecurity + + + remove_security + + method. +

    +
    +
    self.remove_security(self.aapl)
    +
    RemoveSecurity(_symbol);
    +
    +

    + The + + RemoveSecurity + + + remove_security + + method cancels your open orders for the security and liquidates your holdings. +

    + + + +

    Supported Assets

    + + +

    + To view the supported assets in the US Equities dataset, see the + + Data Explorer + + . This dataset doesn't include Over-the-Counter (OTC) stocks. +

    + + + +

    Example Applications

    + + +

    + The US Equities dataset enables you to accurately design Equity trading strategies. Examples include the following strategies: +

    +
      +
    • + Momentum strategies using historical returns on the premise that the momentum will continue +
    • +
    • + Value strategies using fundamental factors on the premise that the price of undervalued securities will rise +
    • +
    • + Factor investing with periodic rebalancing +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys and holds Apple stock: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class USEquityDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        
    +        # Requesting single equity data, since we only trade AAPL
    +        self.aapl = self.add_equity("AAPL", Resolution.DAILY).symbol
    +        
    +        # Historical data
    +        history = self.history(self.aapl, 60, Resolution.DAILY)
    +        self.debug(f"We got {len(history)} items from our history request")
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Check if the current slice containing AAPL and if we hold any position
    +        # As we make use of the most updated price data to decide the order size
    +        if slice.contains_key(self.aapl) and slice[self.aapl] is not None and not self.portfolio.invested:
    +            self.set_holdings(self.aapl, 1)
    +
    public class USEquityDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _symbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +
    +        // Requesting single equity data, since we only trade AAPL
    +        _symbol = AddEquity("AAPL", Resolution.Daily).Symbol;
    +        
    +        // Historical data
    +        var history = History(_symbol, 60, Resolution.Daily);
    +        Debug($"We got {history.Count()} items from our history request");
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Check if the current slice containing AAPL and if we hold any position
    +        // As we make use of the most updated price data to decide the order size
    +        if (slice.ContainsKey(_symbol) && slice[_symbol] != null && !Portfolio.Invested)
    +        {
    +            SetHoldings(_symbol, 1);
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm buys and holds Apple stock: +

    +
    +
    from AlgorithmImports import *
    +
    +
    +class USEquityDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        
    +        self.universe_settings.resolution = Resolution.DAILY
    +        # To select only AAPL, use a manual selection universe
    +        symbols = [Symbol.create("AAPL", SecurityType.EQUITY, Market.USA)]
    +        self.add_universe_selection(ManualUniverseSelectionModel(symbols))    
    +        
    +        # Constant investment signal
    +        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(days=7), 0.025, None))
    +        
    +        # Invest in all members equally
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    public class USEquityDataAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        
    +        UniverseSettings.Resolution = Resolution.Daily;
    +        // To select only AAPL, use a manual selection universe
    +        var symbols = new[] {QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)};
    +        AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
    +        
    +        // Constant investment signal
    +        AddAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(7), 0.025, null));
    +
    +        // Invest in all members equally
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Equities dataset provides + + TradeBar + + , + + QuoteBar + + , and + + Tick + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + Tick Attributes +

    +

    + + Tick + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    AlgoSeek

    +

    US Equity Options

    +
    +
    +

    Introduction

    + + +

    + The US Equity Options data by AlgoSeek provides Option data, including prices, strikes, expires, and open interest. The data covers 4,000 Symbols, starts in January 2012, and is delivered on a minute frequency. This dataset is created by monitoring Options Price Reporting Authority (OPRA) data feed, which consolidates last sale and quotation information originating from the national securities exchanges that have been approved by the Securities and Exchange Commission. +

    +

    + This dataset depends on the following datasets: +

    + +

    + For more information about the US Equity Options dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + + AlgoSeek + + was in 2014 with the goal of providing the highest quality, most accurate, ready-to-use data in the financial data industry. AlgoSeek provides access to Equities, ETFs, ETNs, Equity Indices, Equity Options, Futures, and Future Options for quantitative firms and traders. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Equity Options dataset: +

    +
    +
    option = self.add_option("GOOG")
    +self.option_symbol = option.symbol
    +option.set_filter(-2, +2, 0, 180)
    +
    var option = AddOption("GOOG");
    +_optionSymbol = option.Symbol;
    +option.SetFilter(-2, +2, 0, 180);
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2012* +
    + Asset Coverage + + 4,000 Symbols +
    + Data Density + + Dense +
    + Resolution + + Minute, Hourly, & Daily +
    + Timezone + + New York +
    + Market Hours + + + Regular Only + +
    +

    + * Some data is available before this date. In 2012, AlgoSeek started to fetch data from 48 OPRA channels instead of 24, increasing the quality of the data. +

    + + + +

    Requesting Data

    + + +

    + To add US Equity Options data to your algorithm, call the + + AddOption + + + add_option + + method. Save a reference to the Equity Option + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class USEquityOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 6, 1)
    +        self.set_end_date(2021, 6, 1)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        # Request GOOG option data
    +        option = self.add_option("GOOG")
    +        self.option_symbol = option.symbol
    +        # Set our strike/expiry filter for this option chain
    +        option.set_filter(-2, +2, 0, 180)
    +
    +
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _optionSymbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 6, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        // Request GOOG option data
    +        var option = AddOption("GOOG");
    +        _optionSymbol = option.Symbol;
    +        // Set our strike/expiry filter for this option chain
    +        option.SetFilter(-2, +2, 0, 180);
    +    }
    +}
    +
    +

    + The Equity resolution must be less than or equal to the Equity Option resolution. For example, if you set the Equity resolution to minute, then you must set the Equity Option resolution to minute, hour, or daily. +

    +

    + For more information about creating US Equity Option subscriptions, see + + Requesting Data + + or + + Equity Options Universes + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current US Equity Options data, index the + + OptionChains + + + option_chains + + property of the current + + + Slice + + + with the canonical Equity Option + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your Index Option at every time step. To avoid issues, call the + + Get + + + get + + method. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Get the wanted option chain with the canonical symbol
    +    chain = slice.option_chains.get(self.option_symbol)
    +    if chain:
    +        # Iterate the option contracts in chain
    +        for contract in chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    +
    public override void OnData(Slice slice)
    +{
    +    // Get the wanted option chain with the canonical symbol
    +    if (slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    +    {
    +        // Iterate the option contracts in chain
    +        foreach (var contract in chain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + You can also iterate through all of the + + OptionChain + + objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Iterate all option chains of all symbols
    +    for canonical_symbol, chain in slice.option_chains.items():
    +        # Iterate the option contracts in chain
    +        for contract in chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    +
    public override void OnData(Slice slice)
    +{
    +    // Iterate all option chains of all symbols
    +    foreach (var kvp in slice.OptionChains)
    +    {
    +        var canonicalSymbol = kvp.Key;
    +        var chain = kvp.Value;
    +        // Iterate the option contracts in chain
    +        foreach (var contract in chain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + For more information about accessing US Equity Options data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Equity Options data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Equity Options data in an algorithm, call the + + History + + + history + + method with the Equity Option contract + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame of trade and quote data
    +history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    +
    +# DataFrame of open interest data
    +history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE)
    +
    +# TradeBar objects
    +history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    +
    +# OpenInterest objects
    +history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
    +
    // TradeBar objects 
    +var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    +
    +// QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    +
    +// OpenInterest objects
    +var historyOpenInterest = History<OpenInterest>(contract.Symbol, 100, Resolution.Minute);
    +
    +

    + For more information about historical data in algorithms, see + + History Requests + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Equity Options data in the Research Environment, call the + + History + + + history + + or + + OptionHistory + + + option_history + + method. The + + History + + + history + + method returns the price, volume, and open interest history for some given Option contract(s). The + + OptionHistory + + + option_history + + method returns the price and volume history for the contracts that pass your daily universe filter. +

    +
    +
    qb = QuantBook()
    +option = qb.add_option("GOOG") 
    +option.set_filter(-2, 2, 0, 90)
    +history = qb.option_history(option.symbol.underlying, datetime(2020, 6, 1), datetime(2020, 6, 5))
    +history_df = history.data_frame
    +expiries = history.get_expiry_dates() 
    +strikes = history.get_strikes()
    +
    var qb = new QuantBook();
    +var option = qb.AddOption("GOOG");
    +option.SetFilter(-2, 2, 0, 90);
    +var history = qb.OptionHistory(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    +
    +var contracts = history
    +    .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys))
    +    .Distinct().ToList();
    +var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    +var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
    +
    +

    + To get historical data for arbitrary US Equity Option contracts instead of just the that pass your universe filter, call the + + History + + + history + + method like you would in an algorithm, but on the + + QuantBook + + object. For more information about historical data in the Research Environment, see + + Key Concepts + + . +

    +

    + Historical Greeks and IV Data +

    +

    + To get historical data for the Greeks and implied volatility of Equity Options, see the + + US Equity Option Universe + + dataset. +

    + + + +

    Supported Assets

    + + +

    + To view the supported assets in the US Equity Options dataset, see the + + Data Explorer + + . +

    + + + +

    Example Applications

    + + +

    + The US Equity Options dataset enables you to accurately design Option strategies. Examples include the following strategies: +

    +
      +
    • + Buying put Options to hedge against downward price movement in positive Equity positions +
    • +
    • + Exploiting arbitrage opportunities that arise when the price of Option contracts deviates from their theoretical value +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm subscribes to Google Options that fall within two strikes of the underlying stock price and expire within seven days. Within this Option chain, the algorithm buys the call Option contract that has the furthest expiry and has its strike price closest to the underlying stock price. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. +

    +
    +
    from AlgorithmImports import *
    +
    +class USEquityOptionsDataAlgorithm(QCAlgorithm):
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        # Requesting data
    +        self.underlying = self.add_equity("GOOG").symbol
    +        option = self.add_option("GOOG")
    +        self.option_symbol = option.symbol
    +        # To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    +        # -2/+2 strike buffer is given for small price change
    +        option.set_filter(lambda u: u.calls_only().strikes(-2, +2).expiration(0, 6))
    +        
    +        self.contract = None
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # If the Option contract is exercised, close the underlying position.
    +        if self.portfolio[self.underlying].invested:
    +            self.liquidate(self.underlying)
    +        # If the Option contract expires, rollover to the next contract.
    +        if self.contract and not self.portfolio[self.contract.symbol].invested:
    +            self.contract = None
    +        # Select with the lastest option chain data only
    +        chain = slice.option_chains.get(self.option_symbol)
    +        if not self.contract and chain:
    +            # Select the call contracts with the furthest expiration (week end)
    +            furthest_expiry = max([c.expiry for c in chain])
    +            furthest_expiry_calls = [contract for contract in chain if contract.expiry == furthest_expiry]
    +            # Get the ATM call for speculate trade with low cost and limited loss
    +            self.contract = sorted(furthest_expiry_calls, key = lambda x: abs(chain.underlying.price - x.strike))[0]
    +            self.market_order(self.contract.symbol, 1)
    +            
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = self.history(security.symbol, 10, Resolution.MINUTE)
    +            self.debug(f"We got {len(history)} from our history request for {security.symbol}")
    +
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _underlying, _optionSymbol;
    +    private OptionContract? _contract = null;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        // Requesting data
    +        _underlying = AddEquity("GOOG").Symbol;
    +        var option = AddOption("GOOG");
    +        _optionSymbol = option.Symbol;
    +        // To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    +        // -2/+2 strike buffer is given for small price change
    +        option.SetFilter((u) => u.CallsOnly().Strikes(-2, +2).Expiration(0, 7));
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // If the Option contract is exercised, close the underlying position.
    +        if (Portfolio[_underlying].Invested)
    +        {
    +            Liquidate(_underlying);
    +        }
    +        // If the Option contract expires, rollover to the next contract.
    +        if (_contract != null && !Portfolio[_contract.Symbol].Invested)
    +        {
    +            _contract = null;
    +        }
    +        // Select with the lastest option chain data only
    +        if (_contract == null && slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    +        {
    +            // Select the call contracts with the furthest expiration (week end)
    +            var furthestExpiry = chain.Max(c => c.Expiry);
    +            var furthestExpiryCalls = chain.Where(c => c.Expiry == furthestExpiry);
    +            // Get the ATM call for speculate trade with low cost and limited loss
    +            _contract = furthestExpiryCalls.OrderByDescending(x => Math.Abs(chain.Underlying.Price - x.Strike)).Last();
    +            MarketOrder(_contract.Symbol, 1);
    +        }
    +    }
    +    
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = History(security.Symbol, 100, Resolution.Minute);
    +            Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm buys a call Option contract for Google that falls within one strike of the underlying stock price and expires within seven days. When the contract expires, the algorithm rolls over to the next contract that meets this criteria. +

    +
    +
    from AlgorithmImports import *
    +
    +class USEquityOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        # Requesting data
    +        self.set_universe_selection(EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel())
    +        
    +        self.set_alpha(ConstantOptionsAlphaModel())
    +
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +        
    +        
    +class EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel(OptionUniverseSelectionModel):
    +
    +    def __init__(self) -> None:
    +        # Daily update with the select_option_chain_symbols function
    +        super().__init__(timedelta(1), self.select_option_chain_symbols)
    +
    +    def select_option_chain_symbols(self, utcTime: datetime) -> List[Symbol]:
    +        # Always select only GOOG options as our focus
    +        return [ Symbol.create("GOOG", SecurityType.OPTION, Market.USA) ]
    +
    +    def filter(self, filter: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    +        # -1/+1 strike buffer is given for small price change
    +        return (filter.calls_only()
    +                      .strikes(-1, -1)
    +                      .expiration(0, 7))  
    +        
    +
    +class ConstantOptionsAlphaModel(AlphaModel):
    +
    +    underlying = None
    +    contract = None
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        
    +        insights = []
    +        
    +        # Liquidate the underlying if the option is being exercised/assigned
    +        if algorithm.portfolio[self.underlying].invested:
    +            insights.append(Insight.price(self.underlying, timedelta(days=7), InsightDirection.FLAT))
    +
    +        if self.contract is not None and algorithm.portfolio[self.contract.symbol].invested:
    +            return insights
    +
    +        # Get the ATM call for speculate trade with low cost and limited loss that expires at week end
    +        for kvp in slice.option_chains:
    +            chain = kvp.Value
    +            expiry = max(x.expiry for x in chain)
    +            self.contract = sorted([x for x in chain if x.expiry == expiry],
    +                                               key=lambda x: abs(x.strike - x.underlying_last_price))[0]
    +            insights.append(Insight.price(self.contract.symbol, self.contract.expiry + timedelta(days=1), InsightDirection.UP))
    +        
    +        return insights
    +        
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            if security.type == SecurityType.EQUITY:
    +                self.underlying = security.symbol
    +            else:
    +                # Historical data
    +                history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    +                algorithm.debug(f"We got {len(history)} from our history request for {security.symbol}")
    +
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class USEquityOptionsDataAlgorithm : QCAlgorithm
    +{        
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        // Requesting data
    +        SetUniverseSelection(new EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel());
    +        
    +        SetAlpha(new ConstantOptionsAlphaModel());
    +        
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}   
    +    
    +class EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel : OptionUniverseSelectionModel
    +{
    +    // Daily update with the SelectOptionChainSymbols function
    +    public EarliestExpiringWeeklyAtTheMoneyCallOptionUniverseSelectionModel()
    +            : base(TimeSpan.FromDays(1), SelectOptionChainSymbols) {}
    +    
    +    private static IEnumerable<Symbol> SelectOptionChainSymbols(DateTime utcTime)
    +    {
    +        // Select only GOOG options as our focus
    +        return new[] {QuantConnect.Symbol.Create("GOOG", SecurityType.Option, Market.USA)};
    +    }
    +
    +    protected override OptionFilterUniverse Filter(OptionFilterUniverse filter)
    +    {
    +        // To speculate trade the underlying with a low cost, filter for the ATM calls that expiring in the current week
    +        // -2/+2 strike buffer is given for small price change
    +        return filter.CallsOnly()
    +            .Strikes(-1, -1)
    +            .Expiration(0, 7);
    +    }
    +}
    +    
    +class ConstantOptionsAlphaModel : AlphaModel
    +{ 
    +    private Symbol? _underlying = null;
    +    private OptionContract? _contract = null;
    +    
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = new List<Insight>();
    +        
    +        // Liquidate the underlying if the option is being exercised/assigned
    +        if (algorithm.Portfolio[_underlying].Invested)
    +        {
    +            insights.Add(Insight.Price(_underlying, TimeSpan.FromDays(7), InsightDirection.Flat));
    +        }
    +            
    +        if (_contract != null && algorithm.Portfolio[_contract.Symbol].Invested)
    +        {
    +            return insights;
    +        }
    +        
    +        // Get the ATM call for speculate trade with low cost and limited loss that expires at week end
    +        foreach (var kvp in slice.OptionChains)
    +        {
    +            var chain = kvp.Value;
    +            var expiry = chain.Max(x => x.Expiry);
    +            _contract = chain.Where(x => x.Expiry == expiry)
    +                .OrderBy(x => Math.Abs(x.Strike - x.UnderlyingLastPrice))
    +                .First();
    +            insights.Add(Insight.Price(_contract.Symbol, _contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Up));
    +        }    
    +        return insights;
    +    }
    +
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            if (security.Type == SecurityType.Equity)
    +            {
    +                _underlying = security.Symbol;
    +            }
    +            else {
    +                // Historical data
    +                var history = algorithm.History(security.Symbol, 100, Resolution.Minute);
    +                algorithm.Debug($"We got {history.Count()} from our history request for {security.Symbol}");    
    +            }
    +        }
    +    }
    +}
    +    
    +    
    +class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        var targets = new List<PortfolioTarget>();
    +        foreach (var insight in insights)
    +        {
    +            if (algorithm.Securities[insight.Symbol].IsTradable)
    +            {
    +                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +            }
    +        }
    +        return targets;
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Equity Options dataset provides + + TradeBar + + , + + QuoteBar + + , and + + OpenInterest + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + OpenInterest Attributes +

    +

    + + OpenInterest + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    AlgoSeek

    +

    US Future Options

    +
    +
    +

    Introduction

    + + +

    + The US Future Options dataset by AlgoSeek provides Option data on US Future contracts, including prices, strikes, and expires. The data covers 15 Monthly Future contracts, starts in January 2012, and is delivered on a minute frequency. This dataset is created by monitoring the trading activity on the CME, CBOT, NYMEX, and COMEX markets. +

    +

    + This dataset depends on the following datasets: +

    + +

    + For more information about the US Future Options dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering equities, futures, options, cash forex, and cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit + + algoseek.com + + . +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Future Options dataset: +

    +
    +
    future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    +future.set_filter(0, 90)
    +self.add_future_option(future.symbol, lambda universe: universe.strikes(-5, +5))
    +
    var future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    +future.SetFilter(0, 90);
    +AddFutureOption(future.Symbol, universe => universe.Strikes(-5, +5));
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2012 +
    + Asset Coverage + + 15 Monthly Future Contracts. Standard expires only*. +
    + Data Density + + Dense +
    + Resolution + + Minute, Hourly, & Daily +
    + Timezone + + New York +
    + Market Hours + + + Regular and Extended + +
    + * No weeklies or 0DTE contracts. + + + +

    Requesting Data

    + + +

    + To add US Future Options data to your algorithm, call the + + AddFutureOption + + + add_future_option + + method. +

    +
    +
    class FutureOptionDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2020, 1, 28)
    +        self.set_end_date(2020, 6, 1)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE)
    +        future.set_filter(0, 90)
    +        self.add_future_option(future.symbol, lambda universe: universe.strikes(-5, +5))
    +
    public class FutureOptionDataAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2020, 1, 28);
    +        SetEndDate(2020, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        var future = AddFuture(Futures.Metals.Gold, Resolution.Minute);
    +        future.SetFilter(0, 90);
    +        AddFutureOption(future.Symbol, universe => universe.Strikes(-5, +5));
    +    }
    +}
    +
    +

    + The Future resolution must be less than or equal to the Future Option resolution. For example, if you set the Future resolution to minute, then the Future Option resolution must be minute, hour, or daily. +

    +

    + For more information about creating Future Options subscriptions, see + + Requesting Data + + or + + Future Options Universes + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current Future Options data, iterate through the + + OptionChains + + + option_chains + + property of the current + + + Slice + + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your Future Options at every time step. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for canonical_fop_symbol, chain in slice.option_chains.items():
    +        for contract in chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.OptionChains)
    +    {
    +        var canonicalFOPSymbol = kvp.Key;
    +        var chain = kvp.Value;
    +        foreach (var contract in chain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + You can also iterate through the + + FuturesChains + + + futures_chains + + in the current + + Slice + + first. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for continuous_future_symbol, futures_chain in slice.futures_chains.items():
    +        # Select a Future Contract and create its canonical FOP Symbol
    +        futures_contract = [contract for contract in futures_chain][0]
    +        canonical_fop_symbol = Symbol.create_canonical_option(futures_contract.symbol)
    +        option_chain = slice.option_chains.get(canonical_fop_symbol)
    +        if option_chain:
    +            for fop_contract in option_chain:
    +                 self.log(f"{fop_contract.symbol} price at {slice.time}: {fop_contract.last_price}")
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.FuturesChains)
    +    {
    +        var continuousContractSymbol = kvp.Key;
    +        var futuresChain = kvp.Value;
    +        
    +        // Select a Future Contract and create its canonical FOP Symbol
    +        var futuresContract = futuresChain.First();
    +        var canonicalFOPSymbol = QuantConnect.Symbol.CreateCanonicalOption(futuresContract.Symbol);
    +        if (slice.OptionChains.TryGetValue(canonicalFOPSymbol, out var optionChain))
    +        {
    +            foreach (var fopContract in optionChain)
    +            {
    +                Log($"{fopContract.Symbol} price at {slice.Time}: {fopContract.LastPrice}");
    +            }
    +        }
    +    }
    +}
    +
    +

    + For more information about accessing Future Options data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Future Options data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Future Options data in an algorithm, call the + + History + + + history + + method with the Future Option contract + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame of trade and quote data
    +history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    +
    +# DataFrame of open interest data
    +history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE)
    +
    +# TradeBar objects
    +history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    +
    +# OpenInterest objects
    +history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
    +
    +
    // TradeBar objects 
    +var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    +
    +// QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    +
    +// OpenInterest objects 
    +var historyOpenInterest = History<OpenInterest >(contract.Symbol, 100, Resolution.Minute);
    +
    +

    + For more information about historical data in algorithms, see + + History Requests + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Future Options data in the Research Environment, call the + + History + + + history + + or + + OptionHistory + + + option_history + + method. The + + History + + + history + + method returns the price, volume, and open interest history for some given Future Option contract(s). The + + OptionHistory + + + option_history + + method returns the price and volume history for the contracts that pass your daily universe filter. +

    +
    +
    qb = QuantBook()
    +future = qb.add_future(Futures.Indices.SP_500_E_MINI)
    +start_date = datetime(2024, 1, 2)
    +future_contract_symbol = sorted(
    +    qb.future_chain_provider.get_future_contract_list(future.symbol, start_date), 
    +    key=lambda s: s.id.date
    +)[0]
    +history = qb.option_history(
    +    future_contract_symbol, start_date, future_contract_symbol.id.date, Resolution.HOUR
    +)
    +history_df = history.data_frame
    +expiries = history.get_expiry_dates()
    +strikes = history.get_strikes()
    +
    var qb = new QuantBook();
    +var future = qb.AddFuture(Futures.Indices.SP500EMini);
    +var startDate = new DateTime(2024, 1, 2);
    +var futureContractSymbol = qb.FutureChainProvider.GetFutureContractList(future.Symbol, startDate)
    +    .OrderBy(x => x.ID.Date)
    +    .First();
    +var history = qb.OptionHistory(
    +    futureContractSymbol, startDate, futureContractSymbol.ID.Date, Resolution.Hour
    +);
    +
    +var contracts = history
    +    .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys))
    +    .Distinct().ToList();
    +var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    +var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
    +
    +

    + To get historical data for arbitrary US Equity Option contracts instead of just the that pass your universe filter, call the + + History + + + history + + method like you would in an algorithm, but on the + + QuantBook + + object. For more information about historical data in the Research Environment, see + + Key Concepts + + . +

    + + + +

    Supported Assets

    + + +

    + The following list shows the available (15) Futures Options: +

    +
      +
    • + + Futures.Energy.CrudeOilWTI + + + Futures.Energy.CRUDE_OIL_WTI + + : Crude Oil WTI Futures (NYMEX: LO | Underlying: CL) +
    • +
    • + + Futures.Energy.Gasoline + + + Futures.Energy.GASOLINE + + : Gasoline RBOB Futures (NYMEX: OB | Underlying: RB) +
    • +
    • + + Futures.Energy.HeatingOil + + + Futures.Energy.HEATING_OIL + + : Heating Oil Futures (NYMEX: OH | Underlying: HO) +
    • +
    • + + Futures.Energy.NaturalGas + + + Futures.Energy.NATURAL_GAS + + : Natural Gas Futures (NYMEX: ON | Underlying: NG) +
    • +
    • + + Futures.Financials.Y10TreasuryNote + + + Futures.Financials.Y_10_TREASURY_NOTE + + : 10Y U.S. Treasury Note Futures (CBOT: OZN | Underlying: ZN) +
    • +
    • + + Futures.Financials.Y2TreasuryNote + + + Futures.Financials.Y_2_TREASURY_NOTE + + : 2Y U.S. Treasury Note Futures (CBOT: OZT | Underlying: ZT) +
    • +
    • + + Futures.Financials.Y30TreasuryBond + + + Futures.Financials.Y_30_TREASURY_BOND + + : 30Y U.S. Treasury Bond Futures (CBOT: OZB | Underlying: ZB) +
    • +
    • + + Futures.Grains.Corn + + + Futures.Grains.CORN + + : Corn Futures (CBOT: OZC | Underlying: ZC) +
    • +
    • + + Futures.Grains.Soybeans + + + Futures.Grains.SOYBEANS + + : Soybeans Futures (CBOT: OZS | Underlying: ZS) +
    • +
    • + + Futures.Grains.Wheat + + + Futures.Grains.WHEAT + + : Default wheat contract is SRWWheat (CBOT: OZW | Underlying: ZW) +
    • +
    • + + Futures.Indices.NASDAQ100EMini + + + Futures.Indices.NASDAQ_100_E_MINI + + : E-mini NASDAQ 100 Futures (CME: NQ) +
    • +
    • + + Futures.Indices.SP500EMini + + + Futures.Indices.SP_500_E_MINI + + : E-mini S&P 500 Futures (CME: ES) +
    • +
    • + + Futures.Metals.Copper + + + Futures.Metals.COPPER + + : Copper Futures (COMEX: HXE | Underlying: HG) +
    • +
    • + + Futures.Metals.Gold + + + Futures.Metals.GOLD + + : Gold Futures (COMEX: OG | Underlying: GC) +
    • +
    • + + Futures.Metals.Silver + + + Futures.Metals.SILVER + + : Silver Futures (COMEX: SO | Underlying: SI) +
    • +
    + + + +

    Example Applications

    + + +

    + The US Future Options dataset enables you to accurately design Future Option strategies. Examples include the following strategies: +

    +
      +
    • + Selling out of the money Future Option contracts to collect the premium that the Option buyer pays +
    • +
    • + Buying put Options to hedge against downward price movement in Future contracts you bought +
    • +
    • + Exploiting arbitrage opportunities that arise when the price of Option contracts deviates from their theoretical value +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example demonstrates a weekly-renewing + + covered call + + strategy to collect credit of selling the option. It filters the ATM call contract that expires within the current week at week start using + + SetFilter + + filtering function. +

    +
    +
    from AlgorithmImports import *
    +
    +class FutureOptionExampleAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(5_000_000)
    +        # Subscribe the underlying since the updated price is needed for filtering
    +        self.underlying = self.add_future(Futures.Indices.SP_500_E_MINI,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +            contract_depth_offset=0)
    +        # Filter the underlying continuous Futures to narrow the FOP spectrum
    +        self.underlying.set_filter(0, 182)
    +        # Filter for the current-week-expiring calls to formulate a covered call that expires at the end of week
    +        self.add_future_option(self.underlying.symbol, lambda u: u.calls_only().expiration(0, 5))
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol
    +        symbol = Symbol.create_canonical_option(self.underlying.mapped)
    +
    +        # Get option chain data for the mapped future, as both the underlying and FOP have the highest liquidity among all other contracts
    +        chain = slice.option_chains.get(symbol)
    +        if not self.portfolio.invested and chain:
    +            # Obtain the ATM call that expires at the end of week, such that both underlying and the FOP expires the same time
    +            expiry = max(x.expiry for x in chain)
    +            atm_call = sorted([x for x in chain if x.expiry == expiry],
    +                key=lambda x: abs(x.strike - x.underlying_last_price))[0]
    +
    +            # Use abstraction method to order a covered call to avoid manual error
    +            option_strategy = OptionStrategies.covered_call(symbol, atm_call.strike,expiry)
    +            self.buy(option_strategy, 1)
    +        
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            if security.type == SecurityType.FUTURE_OPTION:
    +                # Historical data
    +                history = self.history(security.symbol, 10, Resolution.MINUTE)
    +
    public class FutureOptionExampleAlgorithm : QCAlgorithm
    +{
    +    private Future _underlying;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(5000000);
    +        // Subscribe the underlying since the updated price is needed for filtering
    +        _underlying = AddFuture(Futures.Indices.SP500EMini,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.OpenInterest,
    +            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +            contractDepthOffset: 0);
    +        // Filter the underlying continuous Futures to narrow the FOP spectrum
    +        _underlying.SetFilter(0, 182);
    +        // Filter for the current-week-expiring calls to formulate a covered call that expires at the end of week
    +        AddFutureOption(_underlying.Symbol, (u) => u.CallsOnly().Expiration(0, 5));
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol
    +        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_underlying.Mapped);
    +
    +        // Get option chain data for the mapped future, as both the underlying and FOP have the highest liquidity among all other contracts
    +        if (!Portfolio.Invested && 
    +            slice.OptionChains.TryGetValue(symbol, out var chain))
    +        {
    +            // Obtain the ATM call that expires at the end of week, such that both underlying and the FOP expires the same time
    +            var expiry = chain.Max(x => x.Expiry);
    +            var atmCall = chain.Where(x => x.Expiry == expiry)
    +                .OrderBy(x => Math.Abs(x.Strike - x.UnderlyingLastPrice))
    +                .First();
    +
    +            // Use abstraction method to order a covered call to avoid manual error
    +            var optionStrategy = OptionStrategies.CoveredCall(symbol, atmCall.Strike, expiry);
    +            Buy(optionStrategy, 1);
    +        }
    +    }
    +
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            if (security.Type == SecurityType.FutureOption)
    +            {
    +                // Historical data
    +                var history = History(security.Symbol, 10, Resolution.Minute);
    +            }
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example demonstrates a daily renewing speculation trade on upward movement of Gold with FOP using algorithm framework. Using FOP, traders can achieve lower cost to get similar absolute profit, given the FOP is selected to be deep ITM with high Delta value. +

    +
    +
    from AlgorithmImports import *
    +
    +class USFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        # Override an option universe selection model to select the FOPs
    +        self.set_universe_selection(GoldFOPUniverseSelectionModel(self))
    +        # Handle the FOP trading logic in an alpha model
    +        self.add_alpha(ConstantFutureOptionsAlphaModel())
    +        # To order a single contract per insight, use a custom portfolio construction model
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +        
    +
    +class GoldFOPUniverseSelectionModel(OptionUniverseSelectionModel):
    +
    +    # Daily renewed universe since option contract list is updated on a daily basis
    +    def __init__(self, algorithm) -> None:
    +        self._algorithm = algorithm
    +        super().__init__(timedelta(1), self.select_fop_symbols)
    +
    +    def select_fop_symbols(self, utc_time: datetime) -> List[Symbol]:
    +        #  Create the underlying symbol to get the FOP contracts later
    +        future_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX)
    +        # Get all gold FOP contracts of the front month gold contract expiring within 3 months, since their liquidity is the highest
    +        future_contract_list = self._algorithm.future_chain_provider.get_future_contract_list(future_symbol, self._algorithm.time)
    +        return [Symbol.create_canonical_option(x) for x in future_contract_list 
    +                    if x.id.date <= self._algorithm.time + timedelta(90)]
    +
    +    def filter(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Filter for the ATM calls that expires latest (same expiry as the underlying)
    +        # +/-5 strike range buffer for price movement
    +        return option_filter_universe.back_month().strikes(-5, +5).calls_only()
    +
    +
    +class ConstantFutureOptionsAlphaModel(AlphaModel):
    +
    +    # A dictionary to cache the mapped FOP of the underlying Future for filtering wanted option chain data and check if invested
    +    option_contract_by_future_underlying_contract = {}
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        insights = []
    +
    +        for kvp in slice.option_chains:
    +            # Liquidate underlying Future contract after Option assignment
    +            underlying_future_contract = kvp.key.underlying
    +            if algorithm.portfolio[underlying_future_contract].invested:
    +                algorithm.insights.cancel([underlying_future_contract])
    +                del self.option_contract_by_future_underlying_contract[underlying_future_contract]
    +
    +            # Do not repeatly invest in the same underlying's FOP
    +            chain = [contract for contract in kvp.value if algorithm.securities[contract.symbol].is_tradable]
    +            if not chain or underlying_future_contract in self.option_contract_by_future_underlying_contract:
    +                continue
    +            
    +            # Select the Option contract with the lowest strike price to speculate trade the underlying with lowest cost and highest delta
    +            contract = sorted(chain, key=lambda x: x.strike)[0]
    +            insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(1), InsightDirection.UP))
    +            self.option_contract_by_future_underlying_contract[underlying_future_contract] = contract
    +        
    +        return insights
    +
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                # Use integer target to create a portfolio target to trade a single contract
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class FutureOptionDataAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        // Override an option universe selection model to select the FOPs
    +        AddUniverseSelection(new GoldFOPUniverseSelectionModel(this));
    +        // Handle the FOP trading logic in an alpha model
    +        SetAlpha(new ConstantFutureOptionsAlphaModel());
    +        // To order a single contract per insight, use a custom portfolio construction model
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}
    +
    +public class GoldFOPUniverseSelectionModel : OptionUniverseSelectionModel
    +{
    +    // Daily renewed universe since option contract list is updated on a daily basis
    +    public GoldFOPUniverseSelectionModel(QCAlgorithm algorithm)
    +        : base(TimeSpan.FromDays(1), _ => OptionChainSymbolSelector(algorithm, _))
    +    {
    +    }
    +
    +    private static IEnumerable<Symbol> OptionChainSymbolSelector(QCAlgorithm algorithm, DateTime utcTime)
    +    {
    +        // Create the underlying symbol to get the FOP contracts later
    +        var futureSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX);
    +        // Get all gold FOP contracts of the front month gold contract expiring within 3 months, since their liquidity is the highest
    +        return algorithm.FutureChainProvider.GetFutureContractList(futureSymbol, algorithm.Time)
    +            .Where(futureContractSymbol => futureContractSymbol.ID.Date <= algorithm.Time + TimeSpan.FromDays(90))
    +            .Select(futureContractSymbol => QuantConnect.Symbol.CreateCanonicalOption(futureContractSymbol));
    +    }
    +
    +    protected override OptionFilterUniverse Filter(OptionFilterUniverse optionFilterUniverse)
    +    {
    +        // Filter for the ATM calls that expires latest (same expiry as the underlying)
    +        // +/-5 strike range buffer for price movement
    +        return optionFilterUniverse.BackMonth().Strikes(-5, +5).CallsOnly();
    +    }
    +}
    +
    +
    +class ConstantFutureOptionsAlphaModel : AlphaModel
    +{
    +    // A dictionary to cache the mapped FOP of the underlying Future for filtering wanted option chain data and check if invested
    +    private Dictionary<Symbol, OptionContract> optionContractByUnderlyingFutureContract = new Dictionary<Symbol, OptionContract>();
    +    
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = new List<Insight>();
    +        
    +        foreach (var kvp in slice.OptionChains)
    +        {
    +            // Liquidate underlying Future contract after Option assignment
    +            var underlyingFutureContract = kvp.Key.Underlying;
    +            if (algorithm.Portfolio[underlyingFutureContract].Invested)
    +            {
    +                algorithm.Insights.Cancel(new[] { underlyingFutureContract });
    +                optionContractByUnderlyingFutureContract.Remove(underlyingFutureContract);
    +            }
    +            
    +            // Do not repeatly invest in the same underlying's FOP
    +            var chain = kvp.Value.Where(contract => algorithm.Securities[contract.Symbol].IsTradable);
    +            if (chain.Count() == 0 || optionContractByUnderlyingFutureContract.ContainsKey(underlyingFutureContract))
    +            {
    +                continue;
    +            }
    +
    +            // Select the Option contract with the lowest strike price to speculate trade the underlying with lowest cost and highest delta
    +            var contract = chain.MinBy(contract => contract.Strike);
    +            insights.Add(Insight.Price(contract.Symbol, contract.Expiry.AddDays(1), InsightDirection.Up));
    +            optionContractByUnderlyingFutureContract.Add(kvp.Key.Underlying, contract);
    +        }            
    +        return insights;
    +    }
    +}
    +
    +
    +class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        var targets = new List<PortfolioTarget>();
    +        foreach (var insight in insights)
    +        {
    +            if (algorithm.Securities[insight.Symbol].IsTradable)
    +            {
    +                // Use integer target to create a portfolio target to trade a single contract
    +                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +            }
    +        }
    +        return targets;
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Future Options dataset provides + + TradeBar + + , + + QuoteBar + + , and + + OpenInterest + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + OpenInterest Attributes +

    +

    + + OpenInterest + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    AlgoSeek

    +

    US Futures

    +
    +
    +

    Introduction

    + + +

    + The US Futures dataset by AlgoSeek provides Futures data, including price, volume, open interest, and expiry. The data covers the 157 most liquid contracts, starts in May 2009, and is delivered on any frequency from tick to daily. This dataset is created by monitoring the trading activity on the CFE + + * + + , CBOT, CME, COMEX, NYMEX, and ICE + + * + + . +

    +

    + This dataset also depends on the + + US Futures Security Master + + because the US Futures Security Master dataset contains information to construct continuous Futures. +

    +

    + For more information about the US Futures dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering equities, futures, options, cash forex, and cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit + + algoseek.com + + . +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Futures dataset: +

    +
    +
    future = self.add_future(Futures.Metals.GOLD)
    +future.set_filter(0, 90)
    +
    var future = AddFuture(Futures.Metals.Gold);
    +future.SetFilter(0, 90);
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + May 2009 +
    + Asset Coverage + + 157 Futures +
    + Data Density + + Dense +
    + Resolution + + Tick, Second, Minute, Hour, & Daily +
    + Timezone + +
      +
    • + Chicago (CFE, CME or CBOT) +
    • +
    • + New York (ICE, NYMEX or COMEX) +
    • +
    +
    + Market Hours + + + Regular and Extended + +
    +

    + This dataset only includes Sugar (SB) from the ICE exchange. +

    +

    + This data provider doesn't include a live data feed for the CFE market (VIX). +

    +

    + LBS (Random Length Lumber) was deprecated for LBR (Lumber). +

    + + + +

    Volume Discrepancies

    + + +

    + The volume of the daily trade bars from this dataset is different from the daily volume that CME and other platforms like Yahoo Finance report because the CME includes pit trades in their daily volume calculation. In contrast, the volume of the daily trade bars in this dataset (from AlgoSeek) doesn't include pit trades because pit trades are over-the-counter, which algorithms can't trade. +

    +

    + Another discrepancy occurs from the start and end times of the daily bars. Daily bars from the CME and Yahoo Finance span from 5 PM Central Time (CT) to 4 PM CT on the following day. In contrast, QuantConnect consolidates daily bars from from 12 AM Eastern Time (ET) to 12 AM ET the following day. Therefore, to calculate the daily volume in the same way that CME does (excluding the pit trades), sum the volume of intraday bars that span 5 PM CT to 4 PM CT on the following day. For an example implementation, see + + Examples + + . +

    + + + +

    Requesting Data

    + + +

    + To add US Futures data to your algorithm, call the + + AddFuture + + + add_future + + method. Save a reference to the Future so you can access the data later in your algorithm. +

    +
    +
    class USFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2013, 12, 20) 
    +        self.set_end_date(2014, 2, 20) 
    +        self.set_cash(1000000) 
    +        self.universe_settings.asynchronous = True
    +        # Request Gold Future data
    +        future = self.add_future(Futures.Metals.GOLD) 
    +        # Set filter to obtain the contracts expire within 90 days
    +        future.set_filter(0, 90)
    +        self.future_symbol = future.symbol
    +
    public class USFuturesDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _futureSymbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2013, 12, 20);
    +        SetEndDate(2014, 2, 20);
    +        SetCash(1000000);
    +        UniverseSettings.Asynchronous = true;
    +        // Request Gold Future data
    +        var future = AddFuture(Futures.Metals.Gold);
    +        // Set filter to obtain the contracts expire within 90 days
    +        future.SetFilter(0, 90);
    +        _futureSymbol = future.Symbol;
    +    }
    +}
    +
    +
    +

    + For more information about creating Future subscriptions, see + + Requesting Data + + or + + Futures Universes + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current US Futures data, index the + + Bars + + + bars + + , + + QuoteBars + + + quote_bars + + , or + + Ticks + + + ticks + + properties of the current + + + Slice + + + with the Future + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your security at every time step. To avoid issues, check if the + + Slice + + contains the data you want before you index it. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Access data: TradeBar data
    +    if self.future_symbol in slice.bars:
    +        trade_bar = slice.bars[self.future_symbol]
    +        self.log(f"{self.future_symbol} close at {slice.time}: {trade_bar.close}")
    +
    +    # Access data: QuoteBar data
    +    if self.future_symbol in slice.quote_bars:
    +        quote_bar = slice.quote_bars[self.future_symbol]
    +        self.log(f"{self.future_symbol} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    # Access data: Ticks data
    +    if self.future_symbol in slice.ticks:
    +        ticks = slice.ticks[self.future_symbol]
    +        for tick in ticks:
    +            self.log(f"{self.future_symbol} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    // Access data: TradeBar data
    +    if (slice.Bars.TryGetValue(_futureSymbol, out var tradeBar))
    +    {
    +        Log($"{_futureSymbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
    +    // Access data: QuoteBar data
    +    if (slice.QuoteBars.TryGetValue(_futureSymbol, out var quoteBar))
    +    {
    +        Log($"{_futureSymbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    // Access data: Ticks data
    +    if (slice.Ticks.TryGetValue(_futureSymbol, out var ticks))
    +    {
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{_futureSymbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + You can also iterate through all of the data objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Iterate all TradeBar received
    +    for symbol, trade_bar in slice.bars.items():
    +        self.log(f"{symbol} close at {slice.time}: {trade_bar.close}")
    +
    +    # Iterate all QuoteBar received
    +    for symbol, quote_bar in slice.quote_bars.items():
    +        self.log(f"{symbol} bid at {slice.time}: {quote_bar.bid.close}")
    +
    +    # Iterate all Ticks received
    +    for symbol, ticks in slice.ticks.items():
    +        for tick in ticks:
    +            self.log(f"{symbol} price at {slice.time}: {tick.price}")
    +
    public override void OnData(Slice slice)
    +{
    +    // Iterate all TradeBar received
    +    foreach (var kvp in slice.Bars)
    +    {
    +        var symbol = kvp.Key;
    +        var tradeBar = kvp.Value;
    +        Log($"{symbol} price at {slice.Time}: {tradeBar.Close}");
    +    }
    +
    +    // Iterate all QuoteBar received
    +    foreach (var kvp in slice.QuoteBars)
    +    {
    +        var symbol = kvp.Key;
    +        var quoteBar = kvp.Value;
    +        Log($"{symbol} bid at {slice.Time}: {quoteBar.Bid.Close}");
    +    }
    +
    +    // Iterate all Ticks received
    +    foreach (var kvp in slice.Ticks)
    +    {
    +        var symbol = kvp.Key;
    +        var ticks = kvp.Value;
    +        foreach (var tick in ticks)
    +        {
    +            Log($"{symbol} price at {slice.Time}: {tick.Price}");
    +        }
    +    }
    +}
    +
    +
    +

    + For more information about accessing US Futures data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Futures data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Futures data in an algorithm, call the + + History + + + history + + method with the canonical Futures + + Symbol + + or a Futures contract + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame objects
    +contract_history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    +continuous_history_df = self.history(self.future_symbol,
    +    start=self.time - timedelta(days=15), 
    +    end=self.time, 
    +    resolution=Resolution.MINUTE, 
    +    fill_forward=False, 
    +    extended_market_hours=False,
    +    data_mapping_mode=DataMappingMode.OPEN_INTEREST, 
    +    data_normalization_mode=DataNormalizationMode.RAW, 
    +    contract_depth_offset=0)
    +
    +# TradeBar objects
    +contract_history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    +continous_history_trade_bars = self.history[TradeBar](self.future_symbol, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +contract_history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    +continous_history_quote_bars = self.history[QuoteBar](self.future_symbol, 100, Resolution.MINUTE)
    +
    +# Tick objects
    +contract_history_ticks = self.history[Tick](contract.symbol, timedelta(seconds=10), Resolution.TICK)
    +continous_history_ticks = self.history[Tick](self.future_symbol, timedelta(seconds=10), Resolution.TICK)
    +
    // TradeBar objects
    +var contractHistoryTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    +var continuousHistoryTradeBars = History(
    +    symbols: new[] {_futureSymbol}, 
    +    start: Time - TimeSpan.FromDays(15),
    +    end: Time,
    +    resolution: Resolution.Minute,
    +    fillForward: false,
    +    extendedMarketHours: false,
    +    dataMappingMode: DataMappingMode.OpenInterest,
    +    dataNormalizationMode: DataNormalizationMode.Raw,
    +    contractDepthOffset: 0);
    +
    +// QuoteBar objects
    +var contractHistoryQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    +var continuousHistoryQuoteBars = History<QuoteBar>(_futureSymbol, 100, Resolution.Minute);
    +
    +// Tick objects
    +var contractHistoryTicks = History<Tick>(contract.Symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +var continuousHistoryTicks = History<Tick>(_futureSymbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +
    +

    + For more information about historical data in algorithms, see + + History Requests + + . For more information about the price adjustments for continuous contracts, see + + Continous Contracts + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Futures data in the Research Environment for an entire Futures chain, call the + + FutureHistory + + + future_history + + method with the canonical Future + + Symbol + + . +

    +
    +
    qb = QuantBook()
    +future = qb.add_future(Futures.Metals.GOLD) 
    +future.set_filter(0, 90)
    +history = qb.future_history(future.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    +history_df = history.data_frame
    +all_history = history.get_all_data()
    +expiries = history.get_expiry_dates()
    +
    var qb = new QuantBook();
    +var future = qb.AddFuture(Futures.Metals.Gold);
    +future.SetFilter(0, 90);
    +var history = qb.FutureHistory(future.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    +    
    +var contracts = history.SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys)).Distinct().ToList();
    +var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    +
    +

    + To get historical data for a single US Futures contract or the continuous Futures contract, call the + + History + + + history + + method like you would in an algorithm but on the + + QuantBook + + object. For more information about historical data in the Research Environment, see + + Futures + + . +

    + + + +

    Supported Assets

    + + +

    + The following list shows the available (157) Futures: +

    +
      +
    • + + Futures.Currencies.AUD + + : Australian Dollar Futures (CME: 6A) +
    • +
    • + + Futures.Currencies.AUDCAD + + : Australian Dollar/Canadian Dollar Futures (CME: ACD) +
    • +
    • + + Futures.Currencies.AUDJPY + + : Australian Dollar/Japanese Yen Futures (CME: AJY) +
    • +
    • + + Futures.Currencies.AUDNZD + + : Australian Dollar/New Zealand Dollar Futures (CME: ANE) +
    • +
    • + + Futures.Currencies.BRL + + : Brazillian Real Futures (CME: 6L) +
    • +
    • + + Futures.Currencies.BTC + + : Bitcoin Futures (CME: BTC) +
    • +
    • + + Futures.Currencies.BTICMicroBTC + + + Futures.Currencies.BTIC_MICRO_BTC + + : BTIC on Micro Bitcoin Futures (CME: MIB) +
    • +
    • + + Futures.Currencies.BTICMicroEther + + + Futures.Currencies.BTIC_MICRO_ETHER + + : BTIC on Micro Ether Futures (CME: MRB) +
    • +
    • + + Futures.Currencies.CAD + + : Canadian Dollar Futures (CME: 6C) +
    • +
    • + + Futures.Currencies.CADJPY + + : Canadian Dollar/Japanese Yen Futures (CME: CJY) +
    • +
    • + + Futures.Currencies.CHF + + : Swiss Franc Futures (CME: 6S) +
    • +
    • + + Futures.Currencies.ETH + + : Ether Futures (CME: ETH) +
    • +
    • + + Futures.Currencies.EUR + + : Euro FX Futures (CME: 6E) +
    • +
    • + + Futures.Currencies.EURAUD + + : Euro/Australian Dollar Futures (CME: EAD) +
    • +
    • + + Futures.Currencies.EURCAD + + : Euro/Canadian Dollar Futures (CME: ECD) +
    • +
    • + + Futures.Currencies.EuroFXEmini + + + Futures.Currencies.EURO_FX_EMINI + + : E-mini Euro FX Futures (CME: E7) +
    • +
    • + + Futures.Currencies.EURSEK + + : Euro/Swedish Krona Futures (CME: ESK) +
    • +
    • + + Futures.Currencies.GBP + + : British Pound Futures (CME: 6B) +
    • +
    • + + Futures.Currencies.JapaneseYenEmini + + + Futures.Currencies.JAPANESE_YEN_EMINI + + : E-mini Japanese Yen Futures (CME: J7) +
    • +
    • + + Futures.Currencies.JPY + + : Japanese Yen Futures (CME: 6J) +
    • +
    • + + Futures.Currencies.MicroAUD + + + Futures.Currencies.MICRO_AUD + + : Micro AUD/USD Futures (CME: M6A) +
    • +
    • + + Futures.Currencies.MicroBTC + + + Futures.Currencies.MICRO_BTC + + : Micro Bitcoin Futures (CME: MBT) +
    • +
    • + + Futures.Currencies.MicroCAD + + + Futures.Currencies.MICRO_CAD + + : Micro USD/CAD Futures (CME: M6C) +
    • +
    • + + Futures.Currencies.MicroCADUSD + + + Futures.Currencies.MICRO_CADUSD + + : Micro CAD/USD Futures (CME: MCD) +
    • +
    • + + Futures.Currencies.MicroCHF + + + Futures.Currencies.MICRO_CHF + + : Micro CHF/USD Futures (CME: MSF) +
    • +
    • + + Futures.Currencies.MicroEther + + + Futures.Currencies.MICRO_ETHER + + : Micro Ether Futures (CME: MET) +
    • +
    • + + Futures.Currencies.MicroEUR + + + Futures.Currencies.MICRO_EUR + + : Micro EUR/USD Futures (CME: M6E) +
    • +
    • + + Futures.Currencies.MicroGBP + + + Futures.Currencies.MICRO_GBP + + : Micro GBP/USD Futures (CME: M6B) +
    • +
    • + + Futures.Currencies.MicroINRUSD + + + Futures.Currencies.MICRO_INRUSD + + : Micro INR/USD Futures (CME: MIR) +
    • +
    • + + Futures.Currencies.MicroJPY + + + Futures.Currencies.MICRO_JPY + + : Micro JPY/USD Futures (CME: MJY) +
    • +
    • + + Futures.Currencies.MicroUSDCHF + + + Futures.Currencies.MICRO_USDCHF + + : Micro USD/CHF Futures (CME: M6S) +
    • +
    • + + Futures.Currencies.MicroUSDCNH + + + Futures.Currencies.MICRO_USDCNH + + : Micro USD/CNH Futures (CME: MNH) +
    • +
    • + + Futures.Currencies.MicroUSDJPY + + + Futures.Currencies.MICRO_USDJPY + + : Micro USD/JPY Futures (CME: M6J) +
    • +
    • + + Futures.Currencies.MXN + + : Mexican Peso Futures (CME: 6M) +
    • +
    • + + Futures.Currencies.NZD + + : New Zealand Dollar Futures (CME: 6N) +
    • +
    • + + Futures.Currencies.RUB + + : Russian Ruble Futures (CME: 6R) +
    • +
    • + + Futures.Currencies.StandardSizeUSDOffshoreRMBCNH + + + Futures.Currencies.STANDARD_SIZE_USD_OFFSHORE_RMBCNH + + : Standard-Size USD/Offshore RMB (CNH) Futures (CME: CNH) +
    • +
    • + + Futures.Currencies.ZAR + + : South African Rand Futures (CME: 6Z) +
    • +
    • + + Futures.Energy.ArgusLLSvsWTIArgusTradeMonth + + + Futures.Energy.ARGUS_LL_SVS_WTI_ARGUS_TRADE_MONTH + + : Argus LLS vs. WTI (Argus) Trade Month Futures (NYMEX: AE5) +
    • +
    • + + Futures.Energy.ArgusPropaneFarEastIndex + + + Futures.Energy.ARGUS_PROPANE_FAR_EAST_INDEX + + : Argus Propane Far East Index Futures (NYMEX: A7E) +
    • +
    • + + Futures.Energy.ArgusPropaneSaudiAramco + + + Futures.Energy.ARGUS_PROPANE_SAUDI_ARAMCO + + : Argus Propane (Saudi Aramco) Futures (NYMEX: A9N) +
    • +
    • + + Futures.Energy.BrentCrudeOilVsDubaiCrudeOilPlatts + + + Futures.Energy.BRENT_CRUDE_OIL_VS_DUBAI_CRUDE_OIL_PLATTS + + : Brent Crude Oil vs. Dubai Crude Oil (Platts) Futures (NYMEX: ADB) +
    • +
    • + + Futures.Energy.BrentLastDayFinancial + + + Futures.Energy.BRENT_LAST_DAY_FINANCIAL + + : Brent Last Day Financial Futures (NYMEX: BZ) +
    • +
    • + + Futures.Energy.ChicagoEthanolPlatts + + + Futures.Energy.CHICAGO_ETHANOL_PLATTS + + : Chicago Ethaanol (Platts) Futures (NYMEX: CU) +
    • +
    • + + Futures.Energy.ConwayPropaneOPIS + + + Futures.Energy.CONWAY_PROPANE_OPIS + + : Conway Propane (OPIS) Futures (NYMEX: A8K) +
    • +
    • + + Futures.Energy.CrudeOilWTI + + + Futures.Energy.CRUDE_OIL_WTI + + : Crude Oil WTI Futures (NYMEX: CL) +
    • +
    • + + Futures.Energy.DubaiCrudeOilPlattsFinancial + + + Futures.Energy.DUBAI_CRUDE_OIL_PLATTS_FINANCIAL + + : Dubai Crude Oil (Platts) Financial Futures (NYMEX: DCB) +
    • +
    • + + Futures.Energy.EastWestGasolineSpreadPlattsArgus + + + Futures.Energy.EAST_WEST_GASOLINE_SPREAD_PLATTS_ARGUS + + : East-West Gasoline Spread (Platts-Argus) Futures (NYMEX: EWG) +
    • +
    • + + Futures.Energy.EastWestNaphthaJapanCFvsCargoesCIFNWESpreadPlatts + + + Futures.Energy.EAST_WEST_NAPHTHA_JAPAN_C_FVS_CARGOES_CIFNWE_SPREAD_PLATTS + + : East-West Naphtha: Japan C&F vs. Cargoes CIF NWE Spread (Platts) Futures (NYMEX: EWN) +
    • +
    • + + Futures.Energy.Ethanol + + + Futures.Energy.ETHANOL + + : Ethanol Futures (CBOT: EH) +
    • +
    • + + Futures.Energy.EthanolT2FOBRdamIncludingDutyPlatts + + + Futures.Energy.ETHANOL_T_2_FOB_RDAM_INCLUDING_DUTY_PLATTS + + : Ethanol T2 FOB Rdam Including Duty (Platts) Futures (NYMEX: AZ1) +
    • +
    • + + Futures.Energy.EuropeanNaphthaPlattsCrackSpread + + + Futures.Energy.EUROPEAN_NAPHTHA_PLATTS_CRACK_SPREAD + + : European Naphtha (Platts) Crack Spread Futures (NYMEX: EN) +
    • +
    • + + Futures.Energy.EuropeanPropaneCIFARAArgus + + + Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS + + : European Propane CIF ARA (Argus) Futures (NYMEX: APS) +
    • +
    • + + Futures.Energy.EuropeanPropaneCIFARAArgusVsNaphthaCargoesCIFNWEPlatts + + + Futures.Energy.EUROPEAN_PROPANE_CIFARA_ARGUS_VS_NAPHTHA_CARGOES_CIFNWE_PLATTS + + : European Propane CIF ARA (Argus) vs. Naphtha Cargoes CIF NWE (Platts) Futures (NYMEX: EPN) +
    • +
    • + + Futures.Energy.FreightRouteTC14Baltic + + + Futures.Energy.FREIGHT_ROUTE_TC_14_BALTIC + + : Freight Route TC14 (Baltic) Futures (NYMEX: FRC) +
    • +
    • + + Futures.Energy.Gasoline + + + Futures.Energy.GASOLINE + + : Gasoline RBOB Futures (NYMEX: RB) +
    • +
    • + + Futures.Energy.GasolineEurobobOxyNWEBargesArgus + + + Futures.Energy.GASOLINE_EUROBOB_OXY_NWE_BARGES_ARGUS + + : Gasoline Euro-bob Oxy NWE Barges (Argus) Futures (NYMEX: B7H) +
    • +
    • + + Futures.Energy.GroupThreeSuboctaneGasolinePlattsVsRBOB + + + Futures.Energy.GROUP_THREE_SUBOCTANE_GASOLINE_PLATTS_VS_RBOB + + : Group Three Sub-octane Gasoliine (Platts) vs. RBOB Futures (NYMEX: AA8) +
    • +
    • + + Futures.Energy.GroupThreeULSDPlattsVsNYHarborULSD + + + Futures.Energy.GROUP_THREE_ULSD_PLATTS_VS_NY_HARBOR_ULSD + + : Group Three ULSD (Platts) vs. NY Harbor ULSD Futures (NYMEX: AA6) +
    • +
    • + + Futures.Energy.GulfCoastCBOBGasolineA2PlattsVsRBOBGasoline + + + Futures.Energy.GULF_COAST_CBOB_GASOLINE_A_2_PLATTS_VS_RBOB_GASOLINE + + : Gulf Coast CBOB Gasoline A2 (Platts) vs. RBOB Gasoline Futures (NYMEX: CRB) +
    • +
    • + + Futures.Energy.GulfCoastHSFOPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.GULF_COAST_HSFO_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : Gulf Coast HSFO (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: GCU) +
    • +
    • + + Futures.Energy.HeatingOil + + + Futures.Energy.HEATING_OIL + + : Heating Oil Futures (NYMEX: HO) +
    • +
    • + + Futures.Energy.LosAngelesCARBOBGasolineOPISvsRBOBGasoline + + + Futures.Energy.LOS_ANGELES_CARBOB_GASOLINE_OPI_SVS_RBOB_GASOLINE + + : Los Angeles CARBOB Gasoline (OPIS) vs. RBOB Gasoline Futures (NYMEX: AJL) +
    • +
    • + + Futures.Energy.LosAngelesCARBDieselOPISvsNYHarborULSD + + + Futures.Energy.LOS_ANGELES_CARB_DIESEL_OPI_SVS_NY_HARBOR_ULSD + + : Los Angeles CARB Diesel (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AKL) +
    • +
    • + + Futures.Energy.LosAngelesJetOPISvsNYHarborULSD + + + Futures.Energy.LOS_ANGELES_JET_OPI_SVS_NY_HARBOR_ULSD + + : Los Angeles Jet (OPIS) vs. NY Harbor ULSD Futures (NYMEX: AJS) +
    • +
    • + + Futures.Energy.MarsArgusVsWTIFinancial + + + Futures.Energy.MARS_ARGUS_VS_WTI_FINANCIAL + + : Mars (Argus) vs. WTI Financial Futures (NYMEX: AYX) +
    • +
    • + + Futures.Energy.MarsArgusVsWTITradeMonth + + + Futures.Energy.MARS_ARGUS_VS_WTI_TRADE_MONTH + + : Mars (Argus) vs. WTI Trade Month Futures (NYMEX: AYV) +
    • +
    • + + Futures.Energy.MicroCrudeOilWTI + + + Futures.Energy.MICRO_CRUDE_OIL_WTI + + : Micro WTI Crude Oil Futures (NYMEX: MCL) +
    • +
    • + + Futures.Energy.MicroEuropeanFOBRdamMarineFuelZeroPointFivePercentBargesPlatts + + + Futures.Energy.MICRO_EUROPEAN_FOB_RDAM_MARINE_FUEL_ZERO_POINT_FIVE_PERCENT_BARGES_PLATTS + + : Micro European FOB Rdam Marine Fuel 0.5% Barges (Platts) Futures (NYMEX: R5O) +
    • +
    • + + Futures.Energy.MicroEuropeanThreePointFivePercentOilBargesFOBRdamPlatts + + + Futures.Energy.MICRO_EUROPEAN_THREE_POINT_FIVE_PERCENT_OIL_BARGES_FOB_RDAM_PLATTS + + : Micro European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: MEF) +
    • +
    • + + Futures.Energy.MicroGasoilZeroPointOnePercentBargesFOBARAPlatts + + + Futures.Energy.MICRO_GASOIL_ZERO_POINT_ONE_PERCENT_BARGES_FOBARA_PLATTS + + : Micro Gasoil 0.1% Barges FOB ARA (Platts) Futures (NYMEX: M1B) +
    • +
    • + + Futures.Energy.MicroSingaporeFOBMarineFuelZeroPointFivePercetPlatts + + + Futures.Energy.MICRO_SINGAPORE_FOB_MARINE_FUEL_ZERO_POINT_FIVE_PERCET_PLATTS + + : Micro Singapore FOB Marine Fuel 0.5% (Platts) Futures (NYMEX: S5O) +
    • +
    • + + Futures.Energy.MicroSingaporeFuelOil380CSTPlatts + + + Futures.Energy.MICRO_SINGAPORE_FUEL_OIL_380_CST_PLATTS + + : Micro Singapore Fuel Oil 380CST (Platts) Futures (NYMEX: MAF) +
    • +
    • + + Futures.Energy.MiniEuropeanThreePointPercentFiveFuelOilBargesPlatts + + + Futures.Energy.MINI_EUROPEAN_THREE_POINT_PERCENT_FIVE_FUEL_OIL_BARGES_PLATTS + + : Mini European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: A0D) +
    • +
    • + + Futures.Energy.MiniSingaporeFuelOil180CstPlatts + + + Futures.Energy.MINI_SINGAPORE_FUEL_OIL_180_CST_PLATTS + + : Mini Singapore Fuel Oil 180 cst (Platts) Futures (NYMEX: A0F) +
    • +
    • + + Futures.Energy.MontBelvieuEthaneOPIS + + + Futures.Energy.MONT_BELVIEU_ETHANE_OPIS + + : Mont Belvieu Ethane (OPIS) Futures (NYMEX: AC0) +
    • +
    • + + Futures.Energy.MontBelvieuLDHPropaneOPIS + + + Futures.Energy.MONT_BELVIEU_LDH_PROPANE_OPIS + + : Mont Belvieu LDH Propane (OPIS) Futures (NYMEX: B0) +
    • +
    • + + Futures.Energy.MontBelvieuNaturalGasolineOPIS + + + Futures.Energy.MONT_BELVIEU_NATURAL_GASOLINE_OPIS + + : Mont Belvieu Natural Gasoline (OPIS) Futures (NYMEX: A7Q) +
    • +
    • + + Futures.Energy.MontBelvieuNormalButaneOPIS + + + Futures.Energy.MONT_BELVIEU_NORMAL_BUTANE_OPIS + + : Mont Belvieu Normal Butane (OPIS) Futures (NYMEX: AD0) +
    • +
    • + + Futures.Energy.NaturalGas + + + Futures.Energy.NATURAL_GAS + + : Natural Gas Futures (NYMEX: NG) +
    • +
    • + + Futures.Energy.NaturalGasHenryHubLastDayFinancial + + + Futures.Energy.NATURAL_GAS_HENRY_HUB_LAST_DAY_FINANCIAL + + : Natural Gas (Henry Hub) Last-day Financial Futures (NYMEX: HH) +
    • +
    • + + Futures.Energy.NaturalGasHenryHubPenultimateFinancial + + + Futures.Energy.NATURAL_GAS_HENRY_HUB_PENULTIMATE_FINANCIAL + + : Natural Gas (Henry Hub) Penultimate Financial Futures (NYMEX: HP) +
    • +
    • + + Futures.Energy.OnePercentFuelOilCargoesFOBNWEPlattsVsThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.ONE_PERCENT_FUEL_OIL_CARGOES_FOBNWE_PLATTS_VS_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : 1% Fuel Oil Cargoes FOB NWE (Platts) vs. 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: FSS) +
    • +
    • + + Futures.Energy.PremiumUnleadedGasoline10ppmFOBMEDPlatts + + + Futures.Energy.PREMIUM_UNLEADED_GASOLINE_10_PPM_FOBMED_PLATTS + + : Premium Unleaded Gasoline 10 ppm FOB MED (Platts) Futures (NYMEX: A3G) +
    • +
    • + + Futures.Energy.PropaneNonLDHMontBelvieuOPIS + + + Futures.Energy.PROPANE_NON_LDH_MONT_BELVIEU_OPIS + + : Propane Non-LDH Mont Belvieu (OPIS) Futures (NYMEX: A1R) +
    • +
    • + + Futures.Energy.RBOBGasolineCrackSpread + + + Futures.Energy.RBOB_GASOLINE_CRACK_SPREAD + + : RBOB Gasoline Crack Spread Futures (NYMEX: ARE) +
    • +
    • + + Futures.Energy.RBOBGasolineVsEurobobOxyNWEBargesArgusThreeHundredFiftyThousandGallons + + + Futures.Energy.RBOB_GASOLINE_VS_EUROBOB_OXY_NWE_BARGES_ARGUS_THREE_HUNDRED_FIFTY_THOUSAND_GALLONS + + : RBOB Gasoline vs. Euro-bob Oxy NWE Barges (Argus) (350,000 gallons) Futures (NYMEX: EXR) +
    • +
    • + + Futures.Energy.SingaporeFuelOil380cstPlattsVsEuropeanThreePointFivePercentFuelOilBargesFOBRdamPlatts + + + Futures.Energy.SINGAPORE_FUEL_OIL_380_CST_PLATTS_VS_EUROPEAN_THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS + + : Singapore Fuel Oil 380 cst (Platts) vs. European 3.5% Fuel Oil Barges FOB Rdam (Platts) Futures (NYMEX: EVC) +
    • +
    • + + Futures.Energy.SingaporeGasoilPlattsVsLowSulphurGasoilFutures + + + Futures.Energy.SINGAPORE_GASOIL_PLATTS_VS_LOW_SULPHUR_GASOIL_FUTURES + + : Singapore Gasoil (Platts) vs. Low Sulphur Gasoil Futures (NYMEX: AGA) +
    • +
    • + + Futures.Energy.SingaporeMogas92UnleadedPlattsBrentCrackSpread + + + Futures.Energy.SINGAPORE_MOGAS_92_UNLEADED_PLATTS_BRENT_CRACK_SPREAD + + : Singapore Mogas 92 Unleaded (Platts) Brent Crack Spread Futures (NYMEX: D1N) +
    • +
    • + + Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread + + + Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD + + : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread Futures (NYMEX: FO) +
    • +
    • + + Futures.Energy.ThreePointFivePercentFuelOilBargesFOBRdamPlattsCrackSpread1000mt + + + Futures.Energy.THREE_POINT_FIVE_PERCENT_FUEL_OIL_BARGES_FOB_RDAM_PLATTS_CRACK_SPREAD_1000_MT + + : 3.5% Fuel Oil Barges FOB Rdam (Platts) Crack Spread (1000mt) Futures (NYMEX: BOO) +
    • +
    • + + Futures.Energy.WTIBrentFinancial + + + Futures.Energy.WTI_BRENT_FINANCIAL + + : WTI-Brent Financial Futures (NYMEX: BK) +
    • +
    • + + Futures.Energy.WTIFinancial + + + Futures.Energy.WTI_FINANCIAL + + : WTI Financial Futures (NYMEX: CSX) +
    • +
    • + + Futures.Energy.WTIHoustonArgusVsWTITradeMonth + + + Futures.Energy.WTI_HOUSTON_ARGUS_VS_WTI_TRADE_MONTH + + : WTI Houston (Argus) vs. WTI Trade Month Futures (NYMEX: HTT) +
    • +
    • + + Futures.Energy.WTIHoustonCrudeOil + + + Futures.Energy.WTI_HOUSTON_CRUDE_OIL + + : WTI Houston Crude Oil Futures (NYMEX: HCL) +
    • +
    • + + Futures.Financials.EuroDollar + + + Futures.Financials.EURO_DOLLAR + + : EuroDollar Futures (CME: GE) +
    • +
    • + + Futures.Financials.FiveYearUSDMACSwap + + + Futures.Financials.FIVE_YEAR_USDMAC_SWAP + + : 5-Year USD MAC Swap Futures (CBOT: F1U) +
    • +
    • + + Futures.Financials.MicroY10TreasuryNote + + + Futures.Financials.MICRO_Y_10_TREASURY_NOTE + + : Micro 10-Year Yield Futures (CBOT: 10Y) +
    • +
    • + + Futures.Financials.MicroY2TreasuryBond + + + Futures.Financials.MICRO_Y_2_TREASURY_BOND + + : Micro 2-Year Yield Futures (CBOT: 2YY) +
    • +
    • + + Futures.Financials.MicroY30TreasuryBond + + + Futures.Financials.MICRO_Y_30_TREASURY_BOND + + : Micro 30-Year Yield Futures (CBOT: 30Y) +
    • +
    • + + Futures.Financials.MicroY5TreasuryBond + + + Futures.Financials.MICRO_Y_5_TREASURY_BOND + + : Micro 5-Year Yield Futures (CBOT: 5YY) +
    • +
    • + + Futures.Financials.UltraTenYearUSTreasuryNote + + + Futures.Financials.ULTRA_TEN_YEAR_US_TREASURY_NOTE + + : Ultra 10-Year U.S. Treasury Note Futures (CBOT: TN) +
    • +
    • + + Futures.Financials.UltraUSTreasuryBond + + + Futures.Financials.ULTRA_US_TREASURY_BOND + + : Ultra U.S. Treasury Bond Futures (CBOT: UB) +
    • +
    • + + Futures.Financials.Y10TreasuryNote + + + Futures.Financials.Y_10_TREASURY_NOTE + + : 10Y U.S. Treasury Note Futures (CBOT: ZN) +
    • +
    • + + Futures.Financials.Y2TreasuryNote + + + Futures.Financials.Y_2_TREASURY_NOTE + + : 2Y U.S. Treasury Note Futures (CBOT: ZT) +
    • +
    • + + Futures.Financials.Y30TreasuryBond + + + Futures.Financials.Y_30_TREASURY_BOND + + : 30Y U.S. Treasury Bond Futures (CBOT: ZB) +
    • +
    • + + Futures.Financials.Y5TreasuryNote + + + Futures.Financials.Y_5_TREASURY_NOTE + + : 5Y U.S. Treasury Note Futures (CBOT: ZF) +
    • +
    • + + Futures.Forestry.Lumber + + + Futures.Forestry.LUMBER + + : Lumber Futures (CME: LBR) +
    • +
    • + + Futures.Forestry.RandomLengthLumber + + + Futures.Forestry.RANDOM_LENGTH_LUMBER + + : Random Length Lumber Futures (CME: LBS) +
    • +
    • + + Futures.Grains.BlackSeaCornFinanciallySettledPlatts + + + Futures.Grains.BLACK_SEA_CORN_FINANCIALLY_SETTLED_PLATTS + + : Black Sea Corn Financially Settled (Platts) Futures (CBOT: BCF) +
    • +
    • + + Futures.Grains.BlackSeaWheatFinanciallySettledPlatts + + + Futures.Grains.BLACK_SEA_WHEAT_FINANCIALLY_SETTLED_PLATTS + + : Black Sea Wheat Financially Settled (Platts) Futures (CBOT: BWF) +
    • +
    • + + Futures.Grains.Corn + + + Futures.Grains.CORN + + : Corn Futures (CBOT: ZC) +
    • +
    • + + Futures.Grains.HRWWheat + + + Futures.Grains.HRW_WHEAT + + : KC HRW Wheat Futures (CBOT: KE) +
    • +
    • + + Futures.Grains.Oats + + + Futures.Grains.OATS + + : Oats Futures (CBOT: ZO) +
    • +
    • + + Futures.Grains.Soybeans + + + Futures.Grains.SOYBEANS + + : Soybeans Futures (CBOT: ZS) +
    • +
    • + + Futures.Grains.SoybeanMeal + + + Futures.Grains.SOYBEAN_MEAL + + : Soybean Meal Futures (CBOT: ZM) +
    • +
    • + + Futures.Grains.SoybeanOil + + + Futures.Grains.SOYBEAN_OIL + + : Soybean Oil Futures (CBOT: ZL) +
    • +
    • + + Futures.Grains.Wheat + + + Futures.Grains.WHEAT + + : Default wheat contract is SRWWheat (CBOT: ZW) +
    • +
    • + + Futures.Indices.BloombergCommodityIndex + + + Futures.Indices.BLOOMBERG_COMMODITY_INDEX + + : Bloomberg Commodity Index Futures (CBOT: AW) +
    • +
    • + + Futures.Indices.Dow30EMini + + + Futures.Indices.DOW_30_E_MINI + + : E-mini Dow Indu 30 Futures (CBOT: YM) +
    • +
    • + + Futures.Indices.DowJonesRealEstate + + + Futures.Indices.DOW_JONES_REAL_ESTATE + + : Dow Jones Real Estate futures on CME (CME: RX) +
    • +
    • + + Futures.Indices.FTSEEmergingEmini + + + Futures.Indices.FTSE_EMERGING_EMINI + + : E-mini FTSE Emerging Index Futures (CME: EI) +
    • +
    • + + Futures.Indices.MicroDow30EMini + + + Futures.Indices.MICRO_DOW_30_E_MINI + + : Micro E-mini Dow Jones Industrial Average Index Futures (CBOT: MYM) +
    • +
    • + + Futures.Indices.MicroNASDAQ100EMini + + + Futures.Indices.MICRO_NASDAQ_100_E_MINI + + : Micro E-mini Nasdaq-100 Index Futures (CME: MNQ) +
    • +
    • + + Futures.Indices.MicroRussell2000EMini + + + Futures.Indices.MICRO_RUSSELL_2000_E_MINI + + : Micro E-mini Russell 2000 Index Futures (CME: M2K) +
    • +
    • + + Futures.Indices.MicroSP500EMini + + + Futures.Indices.MICRO_SP_500_E_MINI + + : Micro E-mini S&P 500 Index Futures (CME: MES) +
    • +
    • + + Futures.Indices.NASDAQ100BiotechnologyEMini + + + Futures.Indices.NASDAQ_100_BIOTECHNOLOGY_E_MINI + + : E-mini Nasdaq-100 Biotechnology Index Futures (CME: BIO) +
    • +
    • + + Futures.Indices.NASDAQ100EMini + + + Futures.Indices.NASDAQ_100_E_MINI + + : E-mini NASDAQ 100 Futures (CME: NQ) +
    • +
    • + + Futures.Indices.Nikkei225Dollar + + + Futures.Indices.NIKKEI_225_DOLLAR + + : Nikkei-225 Dollar Futures (CME: NKD) +
    • +
    • + + Futures.Indices.Nikkei225YenCME + + + Futures.Indices.NIKKEI_225_YEN_CME + + : Nikkei-225 Yen denominated Futures on CME (CME: NIY) +
    • +
    • + + Futures.Indices.Russell1000EMini + + + Futures.Indices.RUSSELL_1000_E_MINI + + : E-mini Russell 1000 futures on CME (CME: RS1) +
    • +
    • + + Futures.Indices.Russell2000EMini + + + Futures.Indices.RUSSELL_2000_E_MINI + + : E-mini Russell 2000 Futures (CME: RTY) +
    • +
    • + + Futures.Indices.SPGSCICommodity + + + Futures.Indices.SPGSCI_COMMODITY + + : S&P-GSCI Commodity Index Futures (CME: GD) +
    • +
    • + + Futures.Indices.SP400MidCapEmini + + + Futures.Indices.SP_400_MID_CAP_EMINI + + : E-mini S&P MidCap 400 Futures (CME: EMD) +
    • +
    • + + Futures.Indices.SP500AnnualDividendIndex + + + Futures.Indices.SP_500_ANNUAL_DIVIDEND_INDEX + + : (CME: SDA) +
    • +
    • + + Futures.Indices.SP500EMini + + + Futures.Indices.SP_500_E_MINI + + : E-mini S&P 500 Futures (CME: ES) +
    • +
    • + + Futures.Indices.TOPIXYEN + + : YEN Denominated Topix Index Futures on CME (CME: TPY) +
    • +
    • + + Futures.Indices.USDDenominatedIbovespa + + + Futures.Indices.USD_DENOMINATED_IBOVESPA + + : USD-Denominated Ibovespa Index Futures (CME: IBV) +
    • +
    • + + Futures.Indices.VIX + + : CBOE Volatility Index Futures (CFE: VX) +
    • +
    • + + Futures.Meats.FeederCattle + + + Futures.Meats.FEEDER_CATTLE + + : Feeder Cattle Futures (CME: GF) +
    • +
    • + + Futures.Meats.LeanHogs + + + Futures.Meats.LEAN_HOGS + + : Lean Hogs Futures (CME: HE) +
    • +
    • + + Futures.Meats.LiveCattle + + + Futures.Meats.LIVE_CATTLE + + : Live Cattle Futures (CME: LE) +
    • +
    • + + Futures.Metals.AluminiumEuropeanPremiumDutyPaidMetalBulletin + + + Futures.Metals.ALUMINIUM_EUROPEAN_PREMIUM_DUTY_PAID_METAL_BULLETIN + + : Aluminium European Premium Duty-Paid (Metal Bulletin) Futures (COMEX: EDP) +
    • +
    • + + Futures.Metals.AluminumMWUSTransactionPremiumPlatts25MT + + + Futures.Metals.ALUMINUM_MWUS_TRANSACTION_PREMIUM_PLATTS_25_MT + + : Aluminum MW U.S. Transaction Premium Platts (25MT) Futures (COMEX: AUP) +
    • +
    • + + Futures.Metals.Copper + + + Futures.Metals.COPPER + + : Copper Futures (COMEX: HG) +
    • +
    • + + Futures.Metals.Gold + + + Futures.Metals.GOLD + + : Gold Futures (COMEX: GC) +
    • +
    • + + Futures.Metals.MicroGold + + + Futures.Metals.MICRO_GOLD + + : Micro Gold Futures (COMEX: MGC) +
    • +
    • + + Futures.Metals.MicroGoldTAS + + + Futures.Metals.MICRO_GOLD_TAS + + : Micro Gold TAS Futures (COMEX: MGT) +
    • +
    • + + Futures.Metals.MicroPalladium + + + Futures.Metals.MICRO_PALLADIUM + + : Micro Palladium Futures (NYMEX: PAM) +
    • +
    • + + Futures.Metals.MicroSilver + + + Futures.Metals.MICRO_SILVER + + : Micro Silver Futures (COMEX: SIL) +
    • +
    • + + Futures.Metals.Palladium + + + Futures.Metals.PALLADIUM + + : Palladium Futures (NYMEX: PA) +
    • +
    • + + Futures.Metals.Platinum + + + Futures.Metals.PLATINUM + + : Platinum Futures (NYMEX: PL) +
    • +
    • + + Futures.Metals.Silver + + + Futures.Metals.SILVER + + : Silver Futures (COMEX: SI) +
    • +
    • + + Futures.Metals.USMidwestDomesticHotRolledCoilSteelCRUIndex + + + Futures.Metals.US_MIDWEST_DOMESTIC_HOT_ROLLED_COIL_STEEL_CRU_INDEX + + : U.S. Midwest Domestic Hot-Rolled Coil Steel (CRU) Index Futures (NYMEX: HRC) +
    • +
    • + + Futures.Softs.Sugar11 + + + Futures.Softs.SUGAR_11 + + : Sugar #11 Futures ICE (ICE: SB) +
    • +
    • + + Futures.Softs.Sugar11CME + + + Futures.Softs.SUGAR_11_CME + + : Sugar #11 Futures CME (NYMEX: YO) +
    • +
    + + + +

    Example Applications

    + + +

    + The US Futures dataset enables you to accurately design Futures strategies. Examples include the following strategies: +

    +
      +
    • + Buying the Futures contract with the most open interest to reduce slippage and market impact +
    • +
    • + Trading bull calendar spreads to reduce volatility and margin requirements +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys the Mini Gold Futures contract with the greatest open interest and sells the Micro Gold Futures contract with the greatest open interest. When the open interest of a different contract exceeds the open interest of a contract in the portfolio, the algorithm rebalances the portfolio. +

    +
    +
    from AlgorithmImports import *
    +
    +class USFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(1000000)
    +        # Setting the continuous contract mapping criteria for both Gold and Micro Gold contracts, since we want to order the highest liquidity contracts
    +        self.settings.seed_initial_prices = True
    +        self.gold = self.add_future(Futures.Metals.GOLD,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +            contract_depth_offset=0)
    +        self.micro_gold = self.add_future(Futures.Metals.MICRO_GOLD,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
    +            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
    +            contract_depth_offset=0)
    +        # The contract multiplier is cached in the Security symbol_properties property from the symbol properties database
    +        self.gold_multiplier = self.gold.symbol_properties.contract_multiplier
    +        self.micro_gold_multiplier = self.micro_gold.symbol_properties.contract_multiplier
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # Make sure to calculate the order size by the most updated price data of both contracts
    +        if not self.portfolio.invested and self.gold.symbol in slice.bars and self.micro_gold.symbol in slice.bars:
    +            # Calculate the order size for $500k
    +            # Get the quotient after dividing the contract multiplier since the order size must be whole number
    +            gold_quantity = 500000 / slice.bars[self.gold.symbol].close // self.gold_multiplier
    +            micro_gold_quantity = 500000 / slice.bars[self.micro_gold.symbol].close // self.micro_gold_multiplier
    +
    +            self.market_order(self.gold.mapped, gold_quantity)
    +            self.market_order(self.micro_gold.mapped, micro_gold_quantity)
    +                
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = self.history(security.symbol, 10, Resolution.MINUTE)
    +            self.debug(f"We got {len(history)} from our history request for {security.symbol}")
    +
    public class USFuturesDataAlgorithm : QCAlgorithm
    +{
    +    private Future _gold, _microGold;
    +    private decimal _goldMulitplier, _microGoldMulitplier;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000000);
    +        // Setting the continuous contract mapping criteria for both Gold and Micro Gold contracts, since we want to order the highest liquidity contracts
    +        Settings.SeedInitialPrices = true;
    +        _gold = AddFuture(Futures.Metals.Gold,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.OpenInterest,
    +            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +            contractDepthOffset: 0);
    +        _microGold = AddFuture(Futures.Metals.MicroGold,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.OpenInterest,
    +            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
    +            contractDepthOffset: 0);
    +        // The contract multiplier is cached in the Security SymbolProperties property from the symbol properties database
    +        _goldMulitplier = _gold.SymbolProperties.ContractMultiplier;
    +        _microGoldMulitplier = _microGold.SymbolProperties.ContractMultiplier;
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // Make sure to calculate the order size by the most updated price data of both contracts
    +        if (!Portfolio.Invested && slice.Bars.ContainsKey(_gold.Symbol) && slice.Bars.ContainsKey(_microGold.Symbol))
    +        {
    +            // Calculate the order size for $500k
    +            // Get the quotient after dividing the contract multiplier since the order size must be whole number
    +            var goldQuantity = Math.Floor(500000m / slice.Bars[_gold.Symbol].Close / _goldMulitplier);
    +            var microGoldQuantity = Math.Floor(500000m / slice.Bars[_microGold.Symbol].Close / _microGoldMulitplier);
    +
    +            MarketOrder(_gold.Mapped, goldQuantity);
    +            MarketOrder(_microGold.Mapped, microGoldQuantity);
    +        }
    +    }
    +    
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = History(security.Symbol, 100, Resolution.Minute);
    +            Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm buys the front-month Mini Gold Futures contract and sells the front-month Micro Gold Futures contract. When the front-month contract changes, the algorithm rebalances the portfolio. +

    +
    +
    from AlgorithmImports import *
    +
    +class USFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000)
    +        self.universe_settings.asynchronous = True
    +        # Set up an universe selection model that selects the front month contract
    +        self.set_universe_selection(FrontMonthFutureUniverseSelectionModel())
    +        self.add_alpha(ConstantFuturesAlphaModel())
    +        # A portfolio construction model that only order a single share per insight signal
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +        
    +class FrontMonthFutureUniverseSelectionModel(FutureUniverseSelectionModel):
    +    def __init__(self,) -> None:
    +        # Daily updating with select_future_chain_symbols function
    +        super().__init__(timedelta(1), self.select_future_chain_symbols)
    +
    +    def select_future_chain_symbols(self, utcTime: datetime) -> List[Symbol]:
    +        # Select gold and micro gold contracts for the strategy need
    +        future_pairs = [
    +            (Futures.Metals.GOLD, Market.COMEX),
    +            (Futures.Metals.MICRO_GOLD, Market.COMEX)
    +        ]
    +        return [Symbol.create(pair[0], SecurityType.FUTURE, pair[1]) for pair in future_pairs]
    +
    +    def filter(self, filter: FutureFilterUniverse) -> FutureFilterUniverse:
    +        # Filter only front month contract for liquidity and most informed information
    +        return filter.front_month().only_apply_filter_at_market_open()
    +
    +class ConstantFuturesAlphaModel(AlphaModel):
    +    # Long gold and short micro gold in this strategy
    +    long_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX)
    +    short_symbol = Symbol.create(Futures.Metals.MICRO_GOLD, SecurityType.FUTURE, Market.COMEX)
    +        
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        if algorithm.portfolio.invested:
    +            return []
    +        
    +        insights = []
    +        # For both gold and micro gold, select the front month contract (only contract) in the chain
    +        for symbol, contracts in slice.future_chains.items():
    +            chain = [contract for contract in contracts]
    +            contract = chain[0]
    +            
    +            # Long gold and short micro gold as planned
    +            if symbol == self.long_symbol:
    +                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.UP))
    +            elif symbol == self.short_symbol:
    +                insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(days=1), InsightDirection.DOWN))
    +        
    +        return insights
    +        
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            # Historical data
    +            history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    +            algorithm.debug(f"We got {len(history)} from our history request for {security.symbol}")
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        targets = []
    +        for insight in insights:
    +            if algorithm.securities[insight.symbol].is_tradable:
    +                # Single share only using integer portfolio target
    +                targets.append(PortfolioTarget(insight.symbol, insight.direction))
    +        return targets
    +
    public class USFuturesDataAlgorithm : QCAlgorithm
    +{        
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(1000000);
    +        UniverseSettings.Asynchronous = true;
    +        // Set up an universe selection model that selects the front month contract
    +        SetUniverseSelection(new FrontMonthFutureUniverseSelectionModel());
    +        SetAlpha(new ConstantFuturesAlphaModel());
    +        // A portfolio construction model that only order a single share per insight signal
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}
    +    
    +class FrontMonthFutureUniverseSelectionModel : FutureUniverseSelectionModel
    +{
    +    // Daily updating with select_future_chain_symbols function
    +    public FrontMonthFutureUniverseSelectionModel()
    +        : base(TimeSpan.FromDays(1), SelectFutureChainSymbols) {}
    +
    +    private static IEnumerable<Symbol> SelectFutureChainSymbols(DateTime utcTime)
    +    {
    +        //Select gold and micro gold contracts for the strategy need
    +        return new List<Symbol> {
    +            QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX),
    +            QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX)
    +        };
    +    }
    +
    +    protected override FutureFilterUniverse Filter(FutureFilterUniverse filter)
    +    {
    +        // Filter only front month contract for liquidity and most informed information
    +        return filter.FrontMonth().OnlyApplyFilterAtMarketOpen();
    +    }
    +}
    +
    +
    +class ConstantFuturesAlphaModel : AlphaModel
    +{
    +    // Long gold and short micro gold in this strategy
    +    private Symbol 
    +        _longSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX), 
    +        _shortSymbol = QuantConnect.Symbol.Create(Futures.Metals.MicroGold, SecurityType.Future, Market.COMEX);
    +    
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = new List<Insight>();
    +
    +        if (algorithm.Portfolio.Invested)
    +        {
    +            return insights;
    +        }
    +        
    +        // For both gold and micro gold, select the front month contract (only contract) in the chain
    +        foreach (var kvp in slice.FutureChains)
    +        {
    +            var symbol = kvp.Key;
    +            var chain = kvp.Value;
    +            var contract = chain.First();
    +            
    +            // Long gold and short micro gold as planned
    +            if (symbol == _longSymbol)
    +            {
    +                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Up));
    +            }
    +            else if (symbol == _shortSymbol)
    +            {
    +                insights.Add(Insight.Price(contract.Symbol, contract.Expiry + TimeSpan.FromDays(1), InsightDirection.Down));
    +            }
    +        }
    +
    +        return insights;
    +    }
    +    
    +    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            // Historical data
    +            var history = algorithm.History(security.Symbol, 100, Resolution.Minute);
    +            algorithm.Debug($"We got {history.Count()} from our history request for {security.Symbol}");
    +        }
    +    }
    +}
    +    
    +    
    +class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        var targets = new List<PortfolioTarget>();
    +        foreach (var insight in insights)
    +        {
    +            if (algorithm.Securities[insight.Symbol].IsTradable)
    +            {
    +                // Single share only using integer portfolio target
    +                targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction));
    +            }
    +        }
    +        return targets;
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Futures dataset provides + + FuturesChain + + , + + Future + + , and + + OpenInterest + + objects. To configure the continuous Future settings, use the + + DataNormalizationMode + + and + + DataMappingMode + + enumerations. +

    +

    + DataNormalizationMode Values +

    +

    + The + + DataNormalizationMode + + enumeration has the following values: +

    +
    +
    +

    + DataMappingMode Values +

    +

    + The + + DataMappingMode + + enumeration has the following values: +

    +
    +
    +

    + Future Attributes +

    +

    + + Future + + objects have the following attributes: +

    +
    +
    +

    + FuturesChain Attributes +

    +

    + + FuturesChain + + objects have the following attributes: +

    +
    +
    +

    + OpenInterest Attributes +

    +

    + + OpenInterest + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    AlgoSeek

    +

    US Index Options

    +
    +
    +

    Introduction

    + + +

    + The US Index Options dataset by AlgoSeek provides Option data, including prices, strikes, expires, and open interest. The data covers European Option contracts for 3 US Indices: SPX, VIX, and NDX. It starts from January 2012 and is delivered on minute resolution. This dataset is created by monitoring the Options Price Reporting Authority (OPRA) data feed, which consolidates last sale and quotation information originating from the national securities exchanges that have been approved by the Securities and Exchange Commission. +

    +

    + The US Index Options dataset depends on the + + US Index Option Universe + + dataset because the US Index Options Universe dataset contains information on the available contracts, including their daily Greeks and implied volatility values. +

    +

    + For more information about the US Index Options dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit + + algoseek.com + + . +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the US Index Options dataset: +

    +
    +
    self.index_symbol = self.add_index('VIX').symbol
    +option = self.add_index_option(self.index_symbol)
    +option.set_filter(-2, 2, 0, 90)
    +self.option_symbol = option.symbol
    +
    _indexSymbol = AddIndex("VIX").Symbol;
    +var option = AddIndexOption(_indexSymbol);
    +option.SetFilter(-2, 2, 0, 90);
    +_optionSymbol = option.Symbol;
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 2012 +
    + Asset Coverage + + 7 Index Options +
    + Data Density + + Regular +
    + Resolution + + Minute, Hourly, & Daily +
    + Timezone + + New York +
    + Market Hours + + + Regular Only + +
    + + + +

    Specification Over Time

    + + +

    + According to the SPX Options + + contract specification + + , some SPX contracts expire every month and SPXW contracts expires every day. Before 2021, you could only trade SPX contracts with the following expiration dates: +

    +
      +
    • + Expires within the next 4 months +
    • +
    • + Expires in September within the next 14 months +
    • +
    • + Expires in January, March, or June within the next 2 years +
    • +
    • + Expires in December within the next 3 years +
    • +
    +

    + During this time, SPXW didn't have 0DTE every day. +

    +

    + + Sources + + : +
    + - + + Cboe Options Exchange to List Three Long-Dated SPX Options Expirations, Beginning November 1, 2021 + +
    + - + + S&P 500 Weekly Options Now Expire Five Days a Week + +

    + + + +

    Requesting Data

    + + +

    + To add US Index Options data to your algorithm, call the + + AddIndexOption + + + add_index_option + + method. Save a reference to the Index Option + + Symbol + + so you can access the data later in your algorithm. +

    +
    +
    class IndexOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2021, 1, 1);
    +        self.set_end_date(2021, 6, 1);
    +        self.set_cash(1000000);
    +        self.universe_settings.asynchronous = True
    +        self.index_symbol = self.add_index('VIX').symbol
    +        
    +        standard_option = self.add_index_option(self.index_symbol)
    +        standard_option.set_filter(-2, 2, 0, 90)
    +        self.standard_option_symbol = standard_option.symbol
    +
    +        weekly_option = self.add_index_option(self.index_symbol, "VIXW")
    +        weekly_option.set_filter(-2, 2, 0, 90)
    +        self.weekly_option_symbol = weekly_option.symbol
    +
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _indexSymbol, _standardOptionSymbol, _weeklyOptionSymbol;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2021, 1, 1);
    +        SetEndDate(2021, 6, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        _indexSymbol = AddIndex("VIX").Symbol;
    +
    +        var standardOption = AddIndexOption(_indexSymbol);
    +        standardOption.SetFilter(-2, 2, 0, 90);
    +        _standardOptionSymbol = standardOption.Symbol;
    +
    +        var weeklyOption = AddIndexOption(_indexSymbol, "VIXW");
    +        weeklyOption.SetFilter(-2, 2, 0, 90);
    +        _weeklyOptionSymbol = weeklyOption.Symbol;
    +    }
    +}
    +
    +

    + The Index resolution must be less than or equal to the Index Option resolution. For example, if you set the Index resolution to minute, then you must set the Index Option resolution to minute, hour, or daily. +

    +

    + For more information about creating US Index Option subscriptions, see + + Requesting Data + + or + + Index Options Universes + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current US Index Options data, index the + + OptionChains + + + option_chains + + property of the current + + + Slice + + + with the canonical Index Option + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your Index Option at every time step. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    standard_chain = slice.option_chains.get(self.standard_option_symbol)
    +    if standard_chain:
    +        for contract in standard_chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    +    weekly_chain = slice.option_chains.get(self.weekly_option_symbol)
    +    if weekly_chain:
    +        for contract in weekly_chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    public override void OnData(Slice slice)
    +{
    +    if (slice.OptionChains.ContainsKey(_standardOptionSymbol))
    +    {
    +        var standardChain = slice.OptionChains[_standardOptionSymbol];
    +        foreach (var contract in standardChain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +
    +    if (slice.OptionChains.ContainsKey(_weeklyOptionSymbol))
    +    {
    +        var weeklyChain = slice.OptionChains[_weeklyOptionSymbol];
    +        foreach (var contract in weeklyChain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + You can also iterate through all of the + + OptionChain + + objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    for canonical_symbol, chain in slice.option_chains.items():
    +        for contract in chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    +
    public override void OnData(Slice slice)
    +{
    +    foreach (var kvp in slice.OptionChains)
    +    {
    +        var canonicalSymbol = kvp.Key;
    +        var chain = kvp.Value;
    +        foreach (var contract in chain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + For more information about accessing US Index Options data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical US Index Options data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical US Index Options data in an algorithm, call the + + History + + + history + + method with the Index Option contract + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame of trade and quote data
    +history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    +
    +# DataFrame of open interest data
    +history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE)
    +
    +# TradeBar objects
    +history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    +
    +# OpenInterest objects
    +history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
    +
    // TradeBar objects 
    +var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    +
    +// QuoteBar objects 
    +var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    +
    +// OpenInterest objects
    +var historyOpenInterest = History<OpenInterest>(contract.Symbol, 100, Resolution.Minute);
    +
    +

    + For more information about historical data in algorithms, see + + History Requests + + . +

    +

    + Historical Data In Research +

    +

    + To get historical US Index Options data in the Research Environment, call the + + History + + + history + + or + + OptionHistory + + + option_history + + method. The + + History + + + history + + method returns the price, volume, and open interest history for some given Option contract(s). The + + OptionHistory + + + option_history + + method returns the price and volume history for the contracts that pass your daily universe filter. +

    +
    +
    qb = QuantBook()
    +index_symbol = qb.add_index('VIX').symbol
    +option = qb.add_index_option(index_symbol) # or qb.add_index_option(index_symbol, "VIXW")
    +option.set_filter(-2, 2, 0, 90)
    +history = qb.option_history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    +history_df = history.data_frame
    +expiries = history.get_expiry_dates() 
    +strikes = history.get_strikes()
    +
    var qb = new QuantBook();
    +var indexSymbol = qb.AddIndex("VIX").Symbol;
    +var option = qb.AddIndexOption(indexSymbol); // or qb.AddIndexOption(indexSymbol, "VIXW");
    +option.SetFilter(-2, 2, 0, 90);
    +var history = qb.OptionHistory(option.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    +
    +var contracts = history
    +    .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys))
    +    .Distinct().ToList();
    +var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    +var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
    +
    +

    + To get historical data for arbitrary US Index Option contracts instead of just the that pass your universe filter, call the + + History + + + history + + method like you would in an algorithm, but on the + + QuantBook + + object. For more information about historical data in the Research Environment, see + + Key Concepts + + . +

    +

    + Historical Greeks and IV Data +

    +

    + To get historical data for the Greeks and implied volatility of Index Options, see the + + US Index Option Universe + + dataset. +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available Index Options: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Underlying Index + + Underlying Ticker + + Target Ticker + + Standard Contracts + + Weekly Contracts + + Tradable on Expiry Day +
    + NASDAQ-100 + + NDX + + + green check + + +
    + NASDAQ-100 + + NDX + + NDXP + + green check + + + green check +
    + NASDAQ-100 + + NDX + + NQX + + green check + + green check + + green check +
    + Russell 2000 + + RUT + + + green check + + +
    + Russell 2000 + + RUT + + RUTW + + + green check + + green check +
    + S&P500 + + SPX + + + green check + + +
    + S&P500 + + SPX + + SPXW + + + green check + + green check +
    + S&P500 + + VIX + + + green check + + +
    + S&P500 + + VIX + + VIXW + + + green check + +
    +

    + For more information about each underlying Index, see + + Supported Indices + + . +

    + + + +

    Example Applications

    + + +

    + The US Index Options dataset enables you to accurately design strategies for Index Options. Examples include the following strategies: +

    +
      +
    • + Buying VIX call Options to hedge against upcoming volatility +
    • +
    • + Buying VIX put Options to capture the natural downward price movement in the VIX index +
    • +
    • + Buying SPX put Options to protect against downward price movement in the S&P 500 +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm buys the VIX Index Option Bull Call Spread with the furthest expiration: +

    +
    +
    from AlgorithmImports import *
    +
    +class IndexOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(200000)
    +        # Asynchronous can use computational resources efficiently
    +        self.universe_settings.asynchronous = True
    +        # Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    +        option = self.add_index_option("SPX")
    +        option.set_filter(lambda u: u.calls_only().strikes(-2, +2).expiration(0, 180))
    +        self.option_symbol = option.symbol
    +
    +    def on_data(self, slice: Slice) -> None:
    +        if not self.portfolio.invested and self.is_market_open(self.option_symbol):
    +            # Make sure getting the updated VIX option chain
    +            chain = slice.option_chains.get(self.option_symbol)
    +            if chain:
    +                expiry = max([c.expiry for c in chain])
    +                call_contracts = sorted([c for c in chain if c.expiry == expiry],
    +                    key=lambda c: c.strike)
    +                
    +                # Need 2 contracts to form a call spread
    +                if len(call_contracts) < 2:
    +                    return
    +                
    +                # Obtain 2 call contracts with different strike price to form the call spread
    +                longCall, shortCall = call_contracts[0:2]
    +                
    +                # Use all the buying power, but need to ensure the order size of the long and short call are the same
    +                quantity = min([
    +                    abs(self.calculate_order_quantity(shortCall.symbol, -1)),
    +                    abs(self.calculate_order_quantity(longCall.symbol, 1))])
    +                if not quantity:
    +                    return
    +
    +                # Bull call spread consists of long a lower-strike call and short a higher-strike call
    +                self.market_order(shortCall.symbol, -quantity)
    +                self.market_order(longCall.symbol, quantity)
    +                
    +                expected_margin_usage = max((longCall.strike - shortCall.strike) * self.securities[longCall.symbol].symbol_properties.contract_multiplier * quantity, 0)
    +                if expected_margin_usage != self.portfolio.total_margin_used:
    +                    raise Exception("Unexpect margin used!")
    +
    +
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            if security.type == SecurityType.INDEX_OPTION:
    +                # Historical data
    +                history = self.history(security.symbol, 10, Resolution.MINUTE)
    +
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _optionSymbol;
    +
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(200000);
    +        // Asynchronous can use computational resources efficiently
    +        UniverseSettings.Asynchronous = true;
    +        // Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    +        var option = AddIndexOption("SPX");
    +        option.SetFilter((u) => u.CallsOnly().Strikes(-2, +2).Expiration(0, 180));
    +        _optionSymbol = option.Symbol;
    +    }
    +    
    +    public override void OnData(Slice slice)
    +    {
    +        if (!Portfolio.Invested && IsMarketOpen(_optionSymbol))
    +        {
    +            // Make sure getting the updated VIX option chain
    +            if (slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
    +            {
    +                var expiry = chain.Max(x => x.Expiry);
    +                var callContracts = chain
    +                    .Where(x => x.Expiry == expiry)
    +                    .OrderBy(x => x.Strike)
    +                    .ToList();
    +
    +                // Need 2 contracts to form a call spread
    +                if (callContracts.Count < 2)
    +                {
    +                    return;
    +                }
    +
    +                // Obtain 2 call contracts with different strike price to form the call spread
    +                var longCall = callContracts.First();
    +                var shortCall = callContracts.First(contract => contract.Strike > longCall.Strike);
    +
    +                // Use all the buying power, but need to ensure the order size of the long and short call are the same
    +                var quantity = new[] {
    +                    CalculateOrderQuantity(shortCall.Symbol, -1m),
    +                    CalculateOrderQuantity(longCall.Symbol, 1m) }
    +                    .Min(x=> Math.Abs(x));
    +                if (quantity == 0) return;
    +
    +                // Bull call spread consists of long a lower-strike call and short a higher-strike call
    +                MarketOrder(shortCall.Symbol, -quantity);
    +                MarketOrder(longCall.Symbol, quantity);
    +
    +                var expectedMarginUsage = Math.Max((longCall.Strike - shortCall.Strike) * Securities[longCall.Symbol].SymbolProperties.ContractMultiplier * quantity, 0);
    +                if (expectedMarginUsage != Portfolio.TotalMarginUsed)
    +                {
    +                    throw new Exception("Unexpect margin used!");
    +                }
    +            }
    +        }
    +    }
    +
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        foreach (var security in changes.AddedSecurities)
    +        {
    +            if (security.Type == SecurityType.IndexOption)
    +            {
    +                // Historical data
    +                var history = History(security.Symbol, 10, Resolution.Minute);
    +            }
    +        }
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm buys the VIX Index Option Bull Call Spread with the furthest expiration: +

    +
    +
    from AlgorithmImports import *
    +
    +class IndexOptionsDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(200000)
    +        self.universe_settings.asynchronous = True
    +        self.set_universe_selection(VIXIndexOptionUniverseSelectionModel())
    +
    +        self.set_alpha(BullCallSpreadAlphaModel())
    +
    +        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())
    +
    +
    +class VIXIndexOptionUniverseSelectionModel(OptionUniverseSelectionModel):
    +
    +    def __init__(self):
    +        super().__init__(timedelta(1), self.option_chain_symbol_selector)
    +    
    +    def option_chain_symbol_selector(self, utc_time: datetime) -> List[Symbol]:
    +        # Only interest in VIX options
    +        return [Symbol.create("VIX", SecurityType.INDEX_OPTION, Market.USA)]
    +
    +    def filter(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
    +        # Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    +        return option_filter_universe.calls_only().strikes(-2, +2).expiration(0, 180)
    +
    +
    +class BullCallSpreadAlphaModel(AlphaModel):
    +
    +    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
    +        if algorithm.portfolio.invested:
    +            return []
    +            
    +        for canonical_symbol, chain in slice.option_chains.items():
    +            if not chain:
    +                return []
    +            # Bull call spread legs are having the same expiry                  
    +            expiry = max([c.expiry for c in chain])
    +            call_contracts = sorted([c for c in chain if c.expiry == expiry],
    +                key=lambda c: c.strike)
    +
    +            # Need 2 contracts to form a call spread
    +            if len(call_contracts) < 2:
    +                return []
    +
    +            # Obtain 2 call contracts with different strike price to form the call spread
    +            long_call, short_call = call_contracts[0:2]
    +            
    +            # Bull call spread consists of long a lower-strike call and short a higher-strike call
    +            return Insight.group(
    +                [
    +                    Insight.price(long_call.symbol, expiry + timedelta(1), InsightDirection.UP),
    +                    Insight.price(short_call.symbol, expiry + timedelta(1), InsightDirection.DOWN)
    +                ])
    +        return []
    +        
    +    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
    +        for security in changes.added_securities:
    +            if security.type == SecurityType.INDEX_OPTION:
    +                # Historical data
    +                history = algorithm.history(security.symbol, 10, Resolution.MINUTE)
    +
    +
    +class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    +
    +    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
    +        if not insights:
    +            return []
    +        # Only a single contract toi ensure both legs size is equal
    +        quantity = min([abs(algorithm.calculate_order_quantity(i.symbol, int(i.direction)))
    +            for i in insights])
    +    
    +        return [PortfolioTarget(i.symbol, quantity * int(i.direction))
    +            for i in insights]
    +
    public class IndexOptionsDataAlgorithm : QCAlgorithm
    +{
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(200000);
    +        UniverseSettings.Asynchronous = true;
    +        SetUniverseSelection(new VIXIndexOptionUniverseSelectionModel());
    +
    +        SetAlpha(new BullCallSpreadAlphaModel());
    +
    +        SetPortfolioConstruction(new SingleSharePortfolioConstructionModel());
    +    }
    +}
    +
    +public class VIXIndexOptionUniverseSelectionModel : OptionUniverseSelectionModel
    +{
    +    // Only interest in VIX options
    +    public VIXIndexOptionUniverseSelectionModel()
    +        : base(TimeSpan.FromDays(1), 
    +            _ => new[] {QuantConnect.Symbol.Create("VIX", SecurityType.IndexOption, Market.USA)})
    +    {
    +    }
    +
    +    protected override OptionFilterUniverse Filter(OptionFilterUniverse optionFilterUniverse)
    +    {
    +        // Filter to get ATM calls expiring in 180 days to form the Bull Call Spread
    +        return optionFilterUniverse.CallsOnly().Strikes(-2, +2).Expiration(0, 180);
    +    }
    +}
    +
    +public class BullCallSpreadAlphaModel : AlphaModel
    +{
    +    public BullCallSpreadAlphaModel()
    +    {
    +    }
    +
    +    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    {
    +        var insights = Enumerable.Empty<Insight>();
    +        if (algorithm.Portfolio.Invested)
    +        {
    +            return insights;
    +        }
    +            
    +        foreach (var kvp in slice.OptionChains)
    +        {
    +            var canoncialSymbol = kvp.Key;
    +            var chain = kvp.Value;
    +            if (chain.IsNullOrEmpty())
    +            {
    +                return insights;
    +            }
    +            // Bull call spread legs are having the same expiry
    +            var expiry = chain.Max(contract => contract.Expiry);
    +            var callContracts = chain
    +                .Where(contract => contract.Expiry == expiry)
    +                .OrderBy(x => x.Strike)
    +                .ToList();
    +
    +            // Need 2 contracts to form a call spread
    +            if (callContracts.Count < 2)
    +            {
    +                return insights;
    +            }
    +
    +            // Obtain 2 call contracts with different strike price to form the call spread
    +            var longCall = callContracts.First();
    +            var shortCall = callContracts.First(contract => contract.Strike > longCall.Strike);
    +
    +            // Bull call spread consists of long a lower-strike call and short a higher-strike call
    +            return Insight.Group(
    +                Insight.Price(longCall.Symbol, expiry.AddDays(1), InsightDirection.Up),
    +                Insight.Price(shortCall.Symbol, expiry.AddDays(1), InsightDirection.Down));
    +        }
    +        return insights;
    +    }
    +}
    +    
    +public class SingleSharePortfolioConstructionModel : PortfolioConstructionModel
    +{
    +    public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
    +    {
    +        if (insights.Count() == 0)
    +        {
    +            return Enumerable.Empty<PortfolioTarget>();
    +        }
    +        // Only a single contract toi ensure both legs size is equal
    +        var quantity = insights
    +            .Select(i => Math.Abs(algorithm.CalculateOrderQuantity(i.Symbol, (decimal)i.Direction)))
    +            .Min();
    +
    +        return insights.Select(i => new PortfolioTarget(i.Symbol, quantity * (decimal)i.Direction));
    +    }
    +}
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Index Options dataset provides + + TradeBar + + , + + QuoteBar + + , and + + OpenInterest + + objects. +

    +

    + TradeBar Attributes +

    +

    + + TradeBar + + objects have the following attributes: +

    +
    +
    +

    + QuoteBar Attributes +

    +

    + + QuoteBar + + objects have the following attributes: +

    +
    +
    +

    + OpenInterest Attributes +

    +

    + + OpenInterest + + objects have the following attributes: +

    +
    +
    + + + +

     

    + +
    +
    +

    Datasets

    +

    Morningstar

    +
    +
    + + +
    +
    +

    + Morningstar was founded by Joe Mansueto in 1984 with the goal of empowering investors by connecting people to the investing information and tools they need. Morningstar provides access extensive line of products and services for individual investors, financial advisors, asset managers, and retirement plan providers. Morningstar provides data on approximately 525,000 investment offerings including stocks, mutual funds, and similar vehicles, along with real-time global market data on nearly 18 million equities, indexes, futures, options, commodities, and precious metals, in addition to foreign exchange and Treasury markets. Morningstar also offers investment management services through its investment advisory subsidiaries, with $244 billion in assets under advisement or management as of 2021. +

    +
    + +
    + + + +

     

    + +
    +
    +

    Morningstar

    +

    US Fundamental Data

    +
    +
    +

    Introduction

    + + +

    + The US Fundamental Data by Morningstar tracks US Equity fundamentals. The data covers 8,000 US Equities, starts in January 1998, and is delivered on a daily frequency. The data does not include ETFs, ADRs, or OTC equities. This dataset is created by using a combination of string matching, Regular Expressions, and Machine Learning to gather the fundamental data published by companies. +

    +

    + For older symbols, the file date is approximated 45 days after the as of date. When a filing date is present on the Morningstar data, it is used. As we are a quant platform, all the data is loaded using "As Original Reported" figures. If there was a mistake reporting the figure, this will not be fixed later. The market typically responds quickly to these initially reported figures. Data is available for multiple periods depending on the property. Periods available include: 1 mo, 2 mo, 3 mo, 6 mo, 9 mo, 12 mo, 1 Yr, 2 Yr, 3 Yr, and 5 Yr. Morningstar symbols cover the NYSE, NASDAQ, AMEX, and BATS exchanges. +

    +

    + In live trading, Morningstar data is delivered to your algorithm at approximately 6 am each day. The majority of the fundamental data update occurs once per month. This includes updates to all of the key information for each security Morningstar supports. On top of this monthly update, there are daily updates of the financial ratios. +

    +

    + As Morningstar data arrives, it updates the master copy and is passed into your algorithm, similar to how TradeBars are fill-forwarded in your data feed. If there have been no updates for a day, you'll receive the same fundamental data. +

    +

    + This dataset depends on the + + US Equity Security Master + + dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes. +

    +

    + QuantConnect/LEAN combines the data of this dataset with + + US Coarse Universe + + data in runtime. +

    +

    + For more information about the US Fundamental Data dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + Morningstar was founded by Joe Mansueto in 1984 with the goal of empowering investors by connecting people to the investing information and tools they need. Morningstar provides access extensive line of products and services for individual investors, financial advisors, asset managers, and retirement plan providers. Morningstar provides data on approximately 525,000 investment offerings including stocks, mutual funds, and similar vehicles, along with real-time global market data on nearly 18 million equities, indexes, futures, options, commodities, and precious metals, in addition to foreign exchange and Treasury markets. Morningstar also offers investment management services through its investment advisory subsidiaries, with $244 billion in assets under advisement or management as of 2021. +

    + + + +

    Getting Started

    + + +

    + The following snippets demonstrate how to request data from the US Fundamental dataset: +

    +
      +
    • + Direct Access using the Security object +
    • +
    +
    +
    equity = self.add_equity("IBM")
    +ibm_fundamental = equity.fundamentals
    +
    var equity = AddEquity("IBM");
    +var ibmFundamental = equity.Fundamentals;
    +
    +
      +
    • + Direct Access using the Symbol object +
    • +
    +
    +
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    +ibm_fundamental = self.fundamentals(ibm)
    +
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    +var ibmFundamental = Fundamentals(ibm);
    +
    +
      +
    • + Universe Selection +
    • +
    +
    +
    def initialize(self) -> None:
    +    self._universe = self.add_universe(self.fundamental_filter_function)
    +
    +def fundamental_filter_function(self, fundamental: List[Fundamental]):
    +    filtered = [f for f in fundamental if f.has_fundamental_data and f.price > 10 and not np.isnan(f.valuation_ratios.pe_ratio)]
    +    sorted_by_pe_ratio = sorted(filtered, key=lambda f: f.valuation_ratios.pe_ratio)
    +    return [f.symbol for f in sorted_by_pe_ratio[:10]]
    +
    public override void Initialize()
    +{
    +    _universe = AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    +}
    +
    +public override List<Symbol> FundamentalFilterFunction(List<Fundamental> fundamental)
    +{
    +    return (from f in fundamental
    +            where f.HasFundamentalData && f.Price > 10 && !Double.IsNaN(f.ValuationRatios.PERatio)
    +            orderby f.ValuationRatios.PERatio
    +            select f.Symbol).Take(10);
    +}
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + January 1998 +
    + Asset Coverage + + 8,000 US Equities + + * + +
    + Corporate Indicators / Tracked Fields + + 900 Fields +
    + Data Density + + Sparse +
    + Resolution + + Daily +
    + Timezone + + New York +
    + + * + + The data does not include ETFs, ADRs, or OTC equities. + + + +

    Requesting Data

    + + +

    + You don't need any special code to request US Fundamental Data. You can access the current and historical fundamental data for any of the US Equities that this dataset includes. +

    +
    +
    class MorningStarDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2021, 1, 1)
    +        self.set_end_date(2021, 7, 1)
    +        self.set_cash(100000) 
    +        self.universe_settings.asynchronous = True
    +
    +        # Option 1: Subscribe to individual US Equity assets
    +        self.add_equity("IBM")        
    +
    +        # Option 2A: Create a fundamental universe (classic version)
    +        self._universe = self.add_universe(self.fundamental_function)
    +
    +        # Option 2B: Create a fundamental universe (framework version)
    +        self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_function))
    +
    public class MorningStarDataAlgorithm : QCAlgorithm
    +{
    +    private Universe _universe;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2021, 1, 1);
    +        SetEndDate(2021, 7, 1);
    +        SetCash(100000);
    +        UniverseSettings.Asynchronous = true;
    +        
    +        // Option 1: Subscribe to individual US Equity assets
    +        AddEquity("IBM");
    +
    +        // Option 2A: Create a fundamental universe (classic version)
    +        _universe = AddUniverse(FundamentalFilterFunction);
    +
    +        // Option 2B: Create a fundamental universe (framework version)
    +        AddUniverseSelection(new FundamentalUniverseSelectionModel(FundamentalFilterFunction));
    +    }
    +}
    +
    +

    + For more information about universe settings, see + + Settings + + . +

    + + + +

    Accessing Data

    + + +

    + If you add a + + fundamental universe + + to your algorithm, you can access fundamental data in the universe selection function. +

    +
    +
    def fundamental_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    +    return [f.symbol for f in fundamental if f.price > 10 and f.valuation_ratios.pe_ratio > 30]
    +
    public IEnumerable<Symbol> FundamentalFunction(IEnumerable<Fundamental> fundamental)
    +{
    +    return fundamental.Where(f => f.Price > 10 && f.ValuationRatios.PERatios > 30).Select(f => f.Symbol);
    +}
    +
    +

    + To get fundamental data for Equities in your algorithm, use the + + Fundamentals + + + fundamentals + + property of the + + Equity + + objects. The fundamental data represent the corporate fundamentals for the current algorithm time. +

    +
    +
    fundamentals = self.securities[symbol].fundamentals
    +
    var fundamentals = Securities[symbol].Fundamentals;
    +
    +

    + To get fundamental data for Equities, regardless of whether or not you have subscribed to them in your algorithm, call the + + Fundamentals + + + fundamentals + + method. If you pass one + + Symbol + + , the method returns a + + Fundamental + + object. If you pass a list of + + Symbol + + objects, the method returns a list of + + Fundamental + + objects. +

    +
    +
    // Single asset 
    +var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    +var ibmFundamental = Fundamentals(ibm);
    +
    +// Multiple assets
    +var nb = QuantConnect.Symbol.Create("NB", SecurityType.Equity, Market.USA);
    +var fundamentals = Fundamentals(new List<Symbol>{ nb, ibm }).ToList();
    +
    # Single asset
    +ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    +ibm_fundamental = self.fundamentals(ibm)
    +
    +# Multiple assets
    +nb = Symbol.create("NB", SecurityType.EQUITY, Market.USA)
    +fundamentals = self.fundamentals([ nb, ibm ])
    +
    + + + +

    Historical Data

    + + +

    + You can get historical fundamental data in an algorithm and in the Research Environment. +

    +

    + Historical Data in Algorithms +

    +

    + To get historical fundamental data in an algorithm, call the + + History + + + history + + method with + + Fundamental + + type and the Equity + + Symbol + + or the + + Universe + + object. If there is no data in the period you request, the history result is empty. +

    +
    +
    var ibm = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    +
    +// Fundamental objects
    +var fundamentalHistory = History<Fundamental>(ibm, TimeSpan.FromDays(30));
    +
    +// Fundamentals objects for all US Equities (including delisted companies)
    +var fundamentalsHistory = History<Fundamentals>(TimeSpan.FromDays(30));
    +
    +// Collection of Fundamental objects for all US Equities (including delisted companies)
    +var collectionHistory = History(_universe, 30, Resolution.Daily);
    +foreach (var fundamental in collectionHistory)
    +{
    +    // Cast to Fundamental is required
    +    var highestMarketCap = fundamental.OfType<Fundamental>().OrderByDescending(x => x.MarketCap).Take(5);
    +}
    +
    ibm = Symbol.create("IBM", SecurityType.EQUITY, Market.USA)
    +
    +# DataFrame object where the columns are the Fundamental attributes
    +asset_df_history = self.history(Fundamental, ibm, timedelta(30), flatten=True)
    +
    +# Fundamental objects
    +fundamental_history= self.history[Fundamental](ibm, timedelta(30))
    +
    +# Fundamentals objects for all US Equities (including delisted companies)
    +fundamentals_history = self.history[Fundamentals](timedelta(30))
    +
    +# Multi-index Series objects where the values are lists of Fundamental objects
    +series_history = self.history(self.universe, 30, Resolution.DAILY)
    +for (universe_symbol, time), fundamentals in series_history.items():
    +    highest_market_cap = sorted(fundamentals, key=lambda x: x.market_cap)[-5:]
    +
    +

    + Historical Data in the Research Environment +

    +

    + To get historical data in the Research Environment, call any of the preceding methods or call the + + UniverseHistory + + + universe_history + + method with the + + Universe + + object, a start date, and an end date. This method returns the filtered universe. Alternatively, call the + + GetFundamental + + + get_fundamental + + method with the Equity + + Symbol + + , a + + Fundamental + + property, a start date, and an end date. If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame object where the columns are the Fundamental attributes
    +universe_history_df = qb.universe_history(universe, qb.time-timedelta(30), qb.time, flatten=True)
    +
    +# Multi-index Series objects where the values are lists of Fundamental objects
    +universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (universe_symbol, time), fundamentals in universe_history.items():
    +    for fundamental in fundamentals:
    +        print(f"{fundamental.symbol} market cap at {fundamental.end_time}: {fundamental.market_cap}")
    +
    +# DataFrame of a single Fundamental attribute
    +history = qb.get_fundamental(symbol, "ValuationRatios.pe_ratios", datetime(2021, 1, 1), datetime(2021, 7, 1))
    +
    var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var fundamentals in universeHistory)
    +{
    +    foreach (Fundamental fundamental in fundamentals)
    +    {
    +        Console.WriteLine($"{fundamental.Symbol} market cap at {fundamental.EndTime}: {fundamental.MarketCap}");
    +    }
    +}
    +
    +var history = qb.GetFundamental(symbol, "ValuationRatios.PERatios", new DateTime(2021, 1, 1), new DateTime(2021, 7, 1));
    +
    +

    + For more information about historical US Equity fundamental data, see + + Equity Fundamental Data + + . +

    + + + +

    Example Applications

    + + +

    + The US Fundamentals dataset enables you to design strategies harnessing fundamental data points. Examples include the following strategies: +

    +
      +
    • + Ranking a universe of securities by a value factor like the + + Piotroski F-score + + and buying a subset of the universe with the best factor ranking +
    • +
    • + Using the Morningstar asset classification to target specific industries or to ensure your strategy is diversified across several sectors +
    • +
    • + Trading securities that recently performed an IPO +
    • +
    +

    + Classic Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of US Equities. The first stage filter selects the 100 most liquid US Equities and the second stage filter selects the 10 assets with the greatest PE ratio. The algorithm then forms an equal-weighted portfolio with the 10 assets in the universe. +

    +
    +
    from AlgorithmImports import *
    +
    +class MorningStarDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000) 
    +        # Seed the price of each asset with its last known price to avoid trading errors.
    +        self.settings.seed_initial_prices = True
    +        self.universe_settings.resolution = Resolution.DAILY
    +        self.universe_size = 10
    +        # Add universe selection to filter with fundamental data
    +        self.add_universe(self.fundamental_selection_function)
    +        
    +    def fundamental_selection_function(self, fundamental: List[Fundamental]) -> List[Symbol]:
    +        # Make sure fundamental data and PE ratio available 
    +        # To avoid penny stocks with high volatility, set price above $1
    +        selected = [f for f in fundamental if f.has_fundamental_data and f.price > 1 and not np.isnan(f.valuation_ratios.pe_ratio)]
    +        # Filter the top 100 high dollar volume equities to ensure liquidity
    +        sorted_by_dollar_volume = sorted(selected, key=lambda f: f.dollar_volume, reverse=True)[:100]
    +        # Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    +        sorted_by_pe_ratio = sorted(sorted_by_dollar_volume, key=lambda f: f.valuation_ratios.pe_ratio, reverse=True)[:self.universe_size]
    +        return [ f.symbol for f in sorted_by_pe_ratio ]
    +        
    +
    +    def on_data(self, slice: Slice) -> None:
    +        # if we have no changes, do nothing
    +        if self._changes is None or not slice.bars: return
    +
    +        # liquidate removed securities, as not being the most popular stocks anymore
    +        for security in self._changes.removed_securities:
    +            if security.invested:
    +                self.liquidate(security.symbol)
    +
    +        # we want 1/N allocation in each security in our universe to evenly dissipate risk
    +        for security in self._changes.added_securities:
    +            self.set_holdings(security.symbol, 1 / self.universe_size)
    +
    +        self._changes = None
    +           
    +    def on_securities_changed(self, changes: SecurityChanges) -> None:
    +        self._changes = changes
    +
    +
    public class MorningStarDataAlgorithm : QCAlgorithm
    +{
    +    private int _universeSize = 10;
    +    private SecurityChanges _changes = SecurityChanges.None;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        // Seed the price of each asset with its last known price to avoid trading errors.
    +        Settings.SeedInitialPrices = true;
    +        // Requesting data
    +        UniverseSettings.Resolution = Resolution.Daily;
    +        // Add universe selection to filter with fundamental data
    +        AddUniverse(FundamentalSelectionFunction);
    +    }
    +
    +    public IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamental)
    +    {
    +        // Make sure fundamental data and PE ratio available 
    +        // To avoid penny stocks with high volatility, set price above $1
    +        // Filter the top 100 high dollar volume equities to ensure liquidity
    +        // Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    +        return fundamental
    +            .Where(x => x.HasFundamentalData && x.Price > 1 && !Double.IsNaN(x.ValuationRatios.PERatio))
    +            .OrderByDescending(x => x.DollarVolume)
    +            .Take(100)
    +            .OrderByDescending(x => x.ValuationRatios.PERatio)
    +            .Take(_universeSize)
    +            .Select(x => x.Symbol);
    +    }
    +
    +    public override void OnData(Slice slice)
    +    {
    +        // if we have no changes, do nothing
    +        if (_changes == SecurityChanges.None || slice.Bars.Count == 0) return;
    +
    +        // liquidate removed securities, as not being the most popular stocks anymore
    +        foreach (var security in _changes.RemovedSecurities)
    +        {
    +            if (security.Invested)
    +            {
    +                Liquidate(security.Symbol);
    +            }
    +        }
    +
    +        // we want 1/N allocation in each security in our universe to evenly dissipate risk
    +        foreach (var security in _changes.AddedSecurities)
    +        {
    +            SetHoldings(security.Symbol, 1m / _universeSize);
    +        }
    +
    +        _changes = SecurityChanges.None;
    +    }
    +    
    +    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    {
    +        _changes = changes;
    +    }
    +}
    +
    +

    + Framework Algorithm Example +

    +

    + The following example algorithm creates a dynamic universe of US Equities. The first stage filter selects the 100 most liquid US Equities and the second stage filter selects the 10 assets with the greatest PE ratio. The algorithm then forms an equal-weighted portfolio with the 10 assets in the universe. +

    +
    +
    from AlgorithmImports import *
    +
    +class MorningStarDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2024, 9, 1)
    +        self.set_end_date(2024, 12, 31)
    +        self.set_cash(100000) 
    +
    +        # Add universe selection to filter with fundamental data
    +        self.universe_settings.resolution = Resolution.DAILY
    +        self.set_universe_selection(CustomFundamentalUniverseSelectionModel())
    +
    +        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(1)))
    +
    +        # we want 1/N allocation in each security in our universe to evenly dissipate risk
    +        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +
    +        self.add_risk_management(NullRiskManagementModel())
    +
    +        self.set_execution(ImmediateExecutionModel())
    +
    +
    +class CustomFundamentalUniverseSelectionModel(FundamentalUniverseSelectionModel):
    +
    +    def select(self, algorithm: QCAlgorithm, fundamental: List[Fundamental]) -> List[Symbol]:
    +        # Make sure fundamental data and PE ratio available 
    +        # To avoid penny stocks with high volatility, set price above $1
    +        # Filter the top 100 high dollar volume equities to ensure liquidity
    +        sorted_by_dollar_volume = sorted([x for x in fundamental if x.price > 1 and not np.isnan(x.valuation_ratios.pe_ratio)],
    +            key=lambda x: x.dollar_volume, reverse=True)[:100]
    +        # Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    +        sorted_by_pe_ratio = sorted(sorted_by_dollar_volume, key=lambda x: x.valuation_ratios.pe_ratio, reverse=True)[:10]
    +
    +        # Take the top entries from our sorted collection
    +        return [ x.symbol for x in sorted_by_pe_ratio ]
    +
    public class MorningStarDataAlgorithm : QCAlgorithm
    +{        
    +    public override void Initialize()
    +    {
    +        SetStartDate(2024, 9, 1);
    +        SetEndDate(2024, 12, 31);
    +        SetCash(100000);
    +        
    +        // Add universe selection to filter with fundamental data
    +        UniverseSettings.Resolution = Resolution.Daily;
    +        AddUniverseSelection(new CustomFundamentalUniverseSelectionModel());
    +        
    +        SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1)));
    +
    +        // we want 1/N allocation in each security in our universe to evenly dissipate risk
    +        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +        
    +        AddRiskManagement(new NullRiskManagementModel());
    +        
    +        SetExecution(new ImmediateExecutionModel());
    +    }
    +}
    +
    +public class CustomFundamentalUniverseSelectionModel : FundamentalUniverseSelectionModel
    +{
    +    public override IEnumerable<Symbol> Select(QCAlgorithm algorithm, IEnumerable<Fundamental> fundamental)
    +    {
    +        return fundamental
    +            // Make sure fundamental data and PE ratio available 
    +            // To avoid penny stocks with high volatility, set price above $1
    +            .Where(x => x.HasFundamentalData && x.Price > 1 && !Double.IsNaN(x.ValuationRatios.PERatio))
    +            // Filter the top 100 high dollar volume equities to ensure liquidity
    +            .OrderByDescending(x => x.DollarVolume)
    +            .Take(100)
    +            // Get the top 10 PE Ratio stocks to follow speculations of a large number of capital
    +            .OrderByDescending(x => x.ValuationRatios.PERatio)
    +            .Take(10)
    +            .Select(x => x.Symbol);
    +    }
    +}
    +
    +

    + Research Example +

    +

    + The following example selects the 100 most liquid US Equities and lists the 10 assets with the greatest PE ratio.: +

    +
    +
    var qb = new QuantBook();
    +
    +// Add Fundamental Universe Selection
    +IEnumerable<Symbol> FundamentalSelectionFunction(IEnumerable<Fundamental> fundamentals)
    +{
    +    return fundamentals
    +        .Where(x => !Double.IsNaN(x.ValuationRatios.PERatio))
    +        .OrderByDescending(x => x.DollarVolume).Take(100)
    +        .OrderByDescending(x => x.ValuationRatios.PERatio).Take(10)
    +        .Select(x => x.Symbol);
    +}
    +
    +var universe = qb.AddUniverse(FundamentalSelectionFunction); 
    +
    +// Historical Universe data
    +var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    +foreach (var fundamentals in universeHistory)
    +{
    +    foreach (Fundamental fundamental in fundamentals)
    +    {
    +        Console.WriteLine($"{fundamental.Symbol} PE ratio at {fundamental.EndTime}: {fundamental.ValuationRatios.PERatio}");
    +    }
    +}
    +
    qb = QuantBook()
    +
    +# Add Fundamental Universe Selection
    +def fundamental_selection_function(fundamentals):
    +    selected = [f for f in fundamentals if not np.isnan(f.valuation_ratios.pe_ratio)]
    +    sorted_by_dollar_volume = sorted(selected, key=lambda f: f.dollar_volume, reverse=True)[:100]
    +
    +    sorted_by_pe_ratio = sorted(sorted_by_dollar_volume,
    +        key=lambda f: f.valuation_ratios.pe_ratio, reverse=True)[:10]
    +    return [ f.symbol for f in sorted_by_pe_ratio ]
    +
    +universe = qb.add_universe(fundamental_selection_function)
    +
    +# Historical Universe data
    +universe_history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    +for (universe_symbol, time), fundamentals in universe_history.items():
    +    for fundamental in fundamentals:
    +        print(f"{fundamental.symbol} PE ratio volume at {fundamental.end_time}: {fundamental.valuation_ratios.pe_ratio}")
    +
    + + + +

    Data Point Attributes

    + + +

    + The US Fundamentals dataset provides + + Fundamental + + objects. To filter + + Fundamental + + objects, you can use one of the enumeration helpers. +

    +

    + Fundamental Attributes +

    +

    + + Fundamental + + objects have the following attributes: +

    +
    +
    +

    + MorningstarSectorCode Enumeration +

    +

    + Sectors are large super categories of data. To access the sector of an Equity, use the + + MorningstarSectorCode + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Technology);
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.asset_classification.morningstar_sector_code == MorningstarSectorCode.TECHNOLOGY]
    +
    +

    + The + + MorningstarSectorCode + + enumeration has the following members: +

    +
    +
    +

    + MorningstarIndustryGroupCode Enumeration +

    +

    + Industry groups are clusters of related industries that tie together. To access the industry group of an Equity, use the + + MorningstarIndustryGroupCode + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.AssetClassification.MorningstarIndustryGroupCode == MorningstarIndustryGroupCode.ApplicationSoftware);
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.asset_classification.morningstar_industry_group_code == MorningstarIndustryGroupCode.APPLICATION_SOFTWARE]
    +
    +

    + The + + MorningstarIndustryGroupCode + + enumeration has the following members: +

    +
    +
    +

    + MorningstarIndustryCode Enumeration +

    +

    + Industries are the finest classification level available and are the individual industries according to the Morningstar classification system. To access the industry group of an Equity, use the + + MorningstarIndustryCode + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.AssetClassification.MorningstarIndustryCode == MorningstarIndustryCode.SoftwareApplication);
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.asset_classification.morningstar_industry_code == MorningstarIndustryCode.SOFTWARE_APPLICATION]
    +
    +

    + The + + MorningstarIndustryCode + + enumeration has the following members: +

    +
    +
    +

    + StockType Enumeration +

    +

    + The Stock Type classification groups companies according to the underlying fundamentals of their business. It answers the question: "If I buy this stock, what kind of company am I buying?" The emphasis is on income statement, balance sheet, and cash-flow data—not price data or valuation multiples. To access the stock type of an Equity, use the + + StockType + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.AssetClassification.StockType == StockType.AggressiveGrowth);
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.asset_classification.stock_type == StockType.AGGRESSIVE_GROWTH]
    +
    +

    + The + + StockType + + enumeration has the following members: +

    +
    +
    +

    + StyleBox Enumeration +

    +

    + The Morningstar Equity Style Box is a grid that provides a graphical representation of the investment style of stocks and portfolios. It classifies securities according to market capitalization (vertical axis) and value-growth scores (horizontal axis). For stocks, the central column represents the core style. To access the style box of an Equity, use the + + StyleBox + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.AssetClassification.StyleBox == StyleBox.LargeValue);
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.asset_classification.style_box == StyleBox.LARGE_VALUE]
    +
    +

    + The + + StyleBox + + enumeration has the following members: +

    +
    +
    +

    + MorningstarEconomySphereCode Enumeration +

    +

    + Sectors are consolidated into three major economic spheres or Super Sectors: Cyclical, Defensive, and Sensitive. To access the economy sphere (Super Sector) of an Equity, use the + + MorningstarEconomySphereCode + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.AssetClassification.MorningstarEconomySphereCode == MorningstarEconomySphereCode.Cyclical);
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.asset_classification.morningstar_economy_sphere_code == MorningstarEconomySphereCode.CYCLICAL]
    +
    +

    + The + + MorningstarEconomySphereCode + + enumeration has the following members: +

    +
    +
    +

    + Exchange ID Values +

    +

    + The exchange ID represents the exchange that lists the Equity. To access the exchange ID of an Equity, use the + + PrimaryExchangeID + + property. +

    +
    +
    filteredFundamentals = fundamental.Where(x =>
    +    x.CompanyReference.PrimaryExchangeID == "NAS");
    +
    filtered_fundamentals = [x for x in fundamental
    +    if x.company_reference.primary_exchange_id == "NAS"]
    +
    +

    + The exchanges are represented by the following string values: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + String Representation + + Exchange +
    + NYS + + New York Stock Exchange (NYSE) +
    + NAS + + NASDAQ +
    + ASE + + American Stock Exchange (AMEX) +
    + TSE + + Tokyo Stock Exchange +
    + AMS + + Amsterdam Internet Exchange +
    + SGO + + Santiago Stock Exchange +
    + XMAD + + Madrid Stock Exchange +
    + ASX + + Australian Securities Exchange +
    + BVMF + + B3 (stock exchange) +
    + LON + + London Stock Exchange +
    + TKS + + Istanbul Stock Exchange Settlement and Custody Bank +
    + SHG + + Shanghai Exchange +
    + LIM + + Lima Stock Exchange +
    + FRA + + Frankfurt Stock Exchange +
    + JSE + + Johannesburg Stock Exchange +
    + MIL + + Milan Stock Exchange +
    + TAE + + Tel Aviv Stock Exchange +
    + STO + + Stockholm Stock Exchange +
    + ETR + + Deutsche Boerse Xetra Core +
    + PAR + + Paris Stock Exchange +
    + BUE + + Buenos Aires Stock Exchange +
    + KRX + + Korea Exchange +
    + SWX + + SIX Swiss Exchange +
    + PINX + + Pink Sheets (OTC) +
    + CSE + + Canadian Securities Exchange +
    + PHS + + Philippine Stock Exchange +
    + MEX + + Mexican Stock Exchange +
    + TAI + + Taiwan Stock Exchange +
    + IDX + + Indonesia Stock Exchange +
    + OSL + + Oslo Stock Exchange +
    + BOG + + Colombia Stock Exchange +
    + NSE + + National Stock Exchange of India +
    + HEL + + Nasdaq Helsinki +
    + MISX + + Moscow Exchange +
    + HKG + + Hong Kong Stock Exchange +
    + IST + + Istanbul Stock Exchange +
    + BOM + + Bombay Stock Exchange +
    + TSX + + Toronto Stock Exchange +
    + BRU + + Brussels Stock Exchange +
    + BATS + + BATS Global Markets +
    + ARCX + + NYSE Arca +
    + GREY + + Grey Market (OTC) +
    + DUS + + Dusseldorf Stock Exchange +
    + BER + + Berlin Stock Exchange +
    + ROCO + + Taipei Exchange +
    + CNQ + + Canadian Trading and Quotation System Inc. +
    + BSP + + Bangko Sentral ng Pilipinas +
    + NEOE + + NEO Exchange +
    + + + +

     

    + +
    +
    +

    Datasets

    +

    TickData

    +
    +
    + + +
    +
    +

    + + TickData + + was founded by a futures broker and a programmer in 1984 as the first company in the world to offer historical tick-by-tick prices on the futures and index markets. TickData provides access to comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cash Indices. +

    +
    + +
    + + + +

     

    + +
    +
    +

    TickData

    +

    International Futures

    +
    +
    +

    Introduction

    + + +

    + The International Futures dataset by TickData provides Futures data, including price, volume, open interest, and expiry. The data covers the 4 contracts, DAX, FESX, HSI, and NKD, starting in July 1998 and is delivered on any frequency from tick to daily. This dataset is created by TickData, which negotiates directly with exchanges for their official archive and partners with real-time data providers with direct exchange connections and multiple redundant ticker plants. +

    +

    + This dataset also depends on the + + US Futures Security Master + + because the US Futures Security Master dataset contains information to construct continuous Futures. +

    +

    + For more information about the International Futures dataset, including CLI commands and pricing, see the + + dataset listing + + . +

    +

    +

    + + + +

    About the Provider

    + + +

    + + TickData + + was founded by a futures broker and a programmer in 1984 as the first company in the world to offer historical tick-by-tick prices on the futures and index markets. TickData provides access to comprehensive and detailed market data and analytics products in the financial industry covering Equities, Futures, Options, cash FOREX, and Cash Indices. +

    + + + +

    Getting Started

    + + +

    + The following snippet demonstrates how to request data from the International Futures dataset: +

    +
    +
    hsi = self.add_future(Futures.Indices.HANG_SENG, Resolution.MINUTE).symbol           # "HSI"
    +dax = self.add_future(Futures.Indices.DAX, Resolution.MINUTE).symbol                 # "DAX"
    +fesx = self.add_future(Futures.Indices.EURO_STOXX_50, Resolution.MINUTE).symbol      # "FESX"
    +nkd = self.add_future(Futures.Indices.NIKKEI_225_DOLLAR, Resolution.MINUTE).symbol   # "NKD"
    +
    var hsi= AddFuture(Futures.Indices.HangSeng, Resolution.Minute).Symbol           // "HSI";
    +var dax = AddFuture(Futures.Indices.Dax, Resolution.Minute).Symbol               // "DAX";
    +var fesx = AddFuture(Futures.Indices.EuroStoxx50, Resolution.Minute).Symbol      // "FESX";
    +var nkd = AddFuture(Futures.Indices.Nikkei225Dollar, Resolution.Minute).Symbol   // "NKD";
    +
    + + + +

    Data Summary

    + + +

    + The following table describes the dataset properties: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Property + + Value +
    + Start Date + + July 1998, see + + Supported Assets + + below for details +
    + Coverage + + 4 Contracts +
    + Data Density + + Dense +
    + Resolution + + Minute, Hour, & Daily +
    + Timezone + + Various, refer to + + Supported Assets + + below +
    + Market Hours + + + Regular and Extended + +
    + + + +

    Volume Discrepancies

    + + + For Futures contracts trading in the US, for example, NKD, see + + US Futures + + . + + + +

    Requesting Data

    + + +

    + To add International Futures data to your algorithm, call the + + AddFuture + + + add_future + + method. Save a reference to the Future so you can access the data later in your algorithm. +

    +
    +
    class InternationalFuturesDataAlgorithm(QCAlgorithm):
    +
    +    def initialize(self) -> None:
    +        self.set_start_date(2013, 12, 20) 
    +        self.set_end_date(2014, 2, 20) 
    +        self.set_cash(1000000) 
    +        self.universe_settings.asynchronous = True
    +        # Request Hang Seng Index Futures data
    +        future = self.add_future(Futures.Indices.HANG_SENG) 
    +        # Set filter to obtain the contracts expire within 90 days
    +        future.set_filter(0, 90)
    +        self.future_symbol = future.symbol
    +
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
    +{
    +    private Symbol _futureSymbol;
    +    
    +    public override void Initialize()
    +    {
    +        SetStartDate(2013, 12, 20);
    +        SetEndDate(2014, 2, 20);
    +        SetCash(1000000);
    +        UniverseSettings.Asynchronous = true;
    +        // Request Hang Seng Index Futures data
    +        var future = AddFuture(Futures.Indices.HangSeng);
    +        // Set filter to obtain the contracts expire within 90 days
    +        future.SetFilter(0, 90);
    +        _futureSymbol = future.Symbol;
    +    }
    +}
    +
    +

    + For more information about creating Future subscriptions, see + + Requesting Data + + or + + Futures Universes + + . +

    + + + +

    Accessing Data

    + + +

    + To get the current International Futures data, index the + + FuturesChains + + + futures_chains + + property of the current + + + Slice + + + with the canonical Futures + + Symbol + + . Slice objects deliver unique events to your algorithm as they happen, but the + + Slice + + may not contain data for your Future at every time step. +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Get future chain of the canonical symbol
    +    chain = slice.futures_chains.get(self.future_symbol)
    +    if chain:
    +        # Iterate each contract in the future chain
    +        for contract in chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    +
    public override void OnData(Slice slice)
    +{
    +    // Get future chain of the canonical symbol
    +    if (slice.FuturesChains.TryGetValue(_futureSymbol, out var chain))
    +    {
    +        // Iterate each contract in the future chain
    +        foreach (var contract in chain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + You can also iterate through all of the + + FuturesChain + + objects in the current + + Slice + + . +

    +
    +
    def on_data(self, slice: Slice) -> None:
    +    # Iterate all future chains
    +    for canonical_symbol, chain in slice.futures_chains.items():
    +        # Iterate each contract in the future chain
    +        for contract in chain:
    +            self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
    +
    public override void OnData(Slice slice)
    +{
    +    // Iterate all future chains
    +    foreach (var kvp in slice.FuturesChains)
    +    {
    +        var canonicalSymbol = kvp.Key;
    +        var chain = kvp.Value;
    +        // Iterate each contract in the future chain
    +        foreach (var contract in chain)
    +        {
    +            Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}");
    +        }
    +    }
    +}
    +
    +

    + For more information about accessing Futures data, see + + Handling Data + + . +

    + + + +

    Historical Data

    + + +

    + You can get historical International Futures data in an algorithm and the Research Environment. +

    +

    + Historical Data In Algorithms +

    +

    + To get historical International Futures data in an algorithm, call the + + History + + + history + + method with the canonical Futures + + Symbol + + or a Futures contract + + Symbol + + . If there is no data in the period you request, the history result is empty. +

    +
    +
    # DataFrame objects
    +contract_history_df = self.history(contract.symbol, 100, Resolution.MINUTE)
    +continuous_history_df = self.history(self.future_symbol,
    +    start=self.time - timedelta(days=15), 
    +    end=self.time, 
    +    resolution=Resolution.MINUTE, 
    +    fill_forward=False, 
    +    extended_market_hours=False,
    +    data_mapping_mode=DataMappingMode.OPEN_INTEREST, 
    +    data_normalization_mode=DataNormalizationMode.RAW, 
    +    contract_depth_offset=0)
    +
    +# TradeBar objects
    +contract_history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE)
    +continous_history_trade_bars = self.history[TradeBar](self.future_symbol, 100, Resolution.MINUTE)
    +
    +# QuoteBar objects
    +contract_history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE)
    +continous_history_quote_bars = self.history[QuoteBar](self.future_symbol, 100, Resolution.MINUTE)
    +
    +# Tick objects
    +contract_history_ticks = self.history[Tick](contract.symbol, timedelta(seconds=10), Resolution.TICK)
    +continous_history_ticks = self.history[Tick](self.future_symbol, timedelta(seconds=10), Resolution.TICK)
    +
    // TradeBar objects
    +var contractHistoryTradeBars = History(contract.Symbol, 100, Resolution.Minute);
    +var continuousHistoryTradeBars = History(
    +    symbols: new[] {_futureSymbol}, 
    +    start: Time - TimeSpan.FromDays(15),
    +    end: Time,
    +    resolution: Resolution.Minute,
    +    fillForward: false,
    +    extendedMarketHours: false,
    +    dataMappingMode: DataMappingMode.OpenInterest,
    +    dataNormalizationMode: DataNormalizationMode.Raw,
    +    contractDepthOffset: 0);
    +
    +// QuoteBar objects
    +var contractHistoryQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute);
    +var continuousHistoryQuoteBars = History<QuoteBar>(_futureSymbol, 100, Resolution.Minute);
    +
    +// Tick objects
    +var contractHistoryTicks = History<Tick>(contract.Symbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +var continuousHistoryTicks = History<Tick>(_futureSymbol, TimeSpan.FromSeconds(10), Resolution.Tick);
    +
    +

    + For more information about historical data in algorithms, see + + History Requests + + . For more information about the price adjustments for continuous contracts, see + + Continous Contracts + + . +

    +

    + Historical Data In Research +

    +

    + To get historical International Futures data in the Research Environment for an entire Futures chain, call the + + FutureHistory + + + future_history + + method with the canonical Future + + Symbol + + . +

    +
    +
    qb = QuantBook()
    +future = qb.add_future(Futures.Indices.HANG_SENG) 
    +future.set_filter(0, 90)
    +history = qb.future_history(future.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5))
    +history_df = history.data_frame
    +all_history = history.get_all_data()
    +expiries = history.get_expiry_dates()
    +
    var qb = new QuantBook();
    +var future = qb.AddFuture(Futures.Indices.HangSeng);
    +future.SetFilter(0, 90);
    +var history = qb.FutureHistory(future.Symbol, new DateTime(2020, 6, 1), new DateTime(2020, 6, 5));
    +    
    +var contracts = history.SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys)).Distinct().ToList();
    +var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList();
    +
    +

    + To get historical data for a single International Futures contract or the continuous Futures contract, call the + + History + + + history + + method like you would in an algorithm but on the + + QuantBook + + object. For more information about historical data in the Research Environment, see + + Futures + + . +

    + + + +

    Supported Assets

    + + +

    + The following table shows the available Futures: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Ticker + + Future + + Start Date + + Time Zone + + Currency +
    + HSI + + Hang Seng Index Futures + + Jan 2010 + + Asia/Hong Kong + + HKD +
    + DAX + + German Index Futures + + Jan 2010 + + Europe/Berlin + + EUR +
    + FESX + + EURO STOXX 50 Index Futures + + Jul 1998 + + Europe/Berlin + + EUR +
    + NKD + + Nikkei 225 Index Futures + + Jan 2007 + + America/Chicago + + USD +
    + + + +

    Example Applications

    + + +

    + The International Futures dataset enables you to design Futures strategies accurately. Examples include the following strategies:

    • - Buy and hold + Buying the Futures contract with the most open interest to reduce slippage and market impact
    • - Trading Cryptocurrency volatility and price action + Trade speculation on an International Index
    • - Allocating a small portion of your portfolio to Cryptocurrencies to hedge against inflation + Trading bull calendar spreads to reduce volatility and margin requirements

    - Classic Algorithm Example + Classic Algorithm Example -- HSI Futures

    - The following example algorithm buys and holds Bitcoin through the Kraken exchange: + The following example algorithm uses + + ZigZag + + to determine the trend of Hang Seng Index. To trade the Indices, we make use of the HSI Futures.

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    -
    +class InternationalFuturesDataAlgorithm(QCAlgorithm):
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        self.universe_settings.asynchronous = True
    -        self.set_cash(100_000)
    -        # Kraken accepts both Cash and Margin account types. Select the
    -        # one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.KRAKEN, AccountType.MARGIN)
    -        # Add BTCUSD data.
    -        self._btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.KRAKEN)
    -        # Historical data
    -        history = self.history(self._btc.symbol, 30, Resolution.DAILY)
    -        # Add a Crypto universe that selects Crypto pairs on Kraken.
    -        universe = self.add_universe(CryptoUniverse.kraken(self._select_assets))
    -        # Historical Universe data
    -        universe_history = self.history(universe, 30, Resolution.DAILY)
    -        for (universe_symbol, time), universe_day in universe_history.items():
    -            for universe_item in universe_day:
    -                symbol = universe_item.symbol
    -                price = universe_item.close
    +        # Set the time zone to HKT to make it more comparable with the exchange.
    +        self.set_time_zone(TimeZones.HONG_KONG)
    +        # Set the account currency as HKD to trade HSI Futures.
    +        self.set_account_currency("HKD", 1000000)
    +        # Seed the last price of the contracts for filling.
    +        self.settings.seed_initial_prices = True
     
    -    def _select_assets(self, universe_day):
    -        # Filter for materially traded Crypto pairs with significant 
    -        # size and dollar volume, assuming higher capital flow in for 
    -        # higher return.
    -        return [universe_item.symbol for universe_item in universe_day
    -                if universe_item.volume >= 100 
    -                and universe_item.volume_in_usd > 10_000_000]
    +        # Request HSI Futures to trade. 
    +        # Note that we will trade the contract with the highest open interest for liquidity.
    +        self.hsi_future = self.add_future(
    +            Futures.Indices.HANG_SENG,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
    +            contract_depth_offset=0
    +        )
    +        # Request the corresponding underlying Index for feeding indicator for trade signal generation.
    +        hsi_index = self.add_index("HSI").symbol
    +
    +        # Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    +        self._zz = self.zz(hsi_index, 0.15, 5, Resolution.DAILY)
    +        # Warm up indicator for immediate readiness to trade.
    +        self.warm_up_indicator(hsi_index, self._zz, Resolution.DAILY)
     
         def on_data(self, slice: Slice) -> None:
    -        # Speculate-invest all available free cash on BTCUSD, repecting 
    -        # the order quantity restrictions to avoid invalid orders.
    -        if self.portfolio.cash_book['BTC'].amount != 0:
    -            return
    -        # Define a buffer so that we can scale down the order size,
    -        # avoiding trading errors.
    -        buffer = max(
    -            KrakenFeeModel.TAKER_TIER_1_CRYPTO_FEE, 
    -            self.settings.free_portfolio_value_percentage
    -        )
    -        quantity = (
    -            self.portfolio.cash_book['USD'].amount
    -            / self._btc.ask_price
    -            * (1-buffer)
    -        )
    -        # Check if the quantity exceeds the minimum order size. On 
    -        # Kraken, the minimum order size is measured in the base
    -        # currency (BTC in this case).
    -        if abs(quantity) < self._btc.symbol_properties.minimum_order_size:
    -            return
    -        self.market_order(self._btc, quantity)
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +        # Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    +        if self.is_market_open(self.hsi_future.symbol) and self._zz.is_ready:
    +            pivot = self._zz.pivot_type
    +            # If the last pivot point is a low point, the current trend is increasing after this low point.
    +            if pivot == PivotPointType.LOW and not self.portfolio[self.hsi_future.symbol].is_long:
    +                self.set_holdings(self.hsi_future.mapped, 0.2)
    +            # If the last pivot point is a high point, the current trend is decreasing after this high point.
    +            elif pivot == PivotPointType.HIGH and not self.portfolio[self.hsi_future.symbol].is_short:
    +                self.set_holdings(self.hsi_future.mapped, -0.2)
    +
    +        # Handle rollover in case the current mapped contract changes.
    +        for _, changed_event in slice.symbol_changed_events.items():
    +            old_symbol = changed_event.old_symbol
    +            new_symbol = self.add_future_contract(changed_event.new_symbol).symbol
    +            quantity = self.portfolio[old_symbol].quantity
    +            # Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    +            self.liquidate(old_symbol)
    +            if quantity != 0:
    +                self.market_order(new_symbol, quantity)
    +
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
     {
    -    private Crypto _btc;
    -    
    +    private Future _hsiFuture;
    +    private ZigZag _zz;
    +
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        UniverseSettings.Asynchronous = true;
    -        SetCash(100000);
    -        // Kraken accepts both Cash and Margin account types. Select the
    -        // one you need for the best reality modeling.
    -        SetBrokerageModel(BrokerageName.Kraken, AccountType.Margin);
    -        // Add BTCUSD data.
    -        _btc = AddCrypto("BTCUSD", Resolution.Minute, Market.Kraken);   
    -        // Historical data
    -        var history = History(_btc.Symbol, 30, Resolution.Daily);
    -        // Add a Crypto universe that selects trading pairs on Kraken.
    -        var universe = AddUniverse(CryptoUniverse.Kraken(SelectAssets));
    -        // Historical Universe data
    -        var universeHistory = History(universe, 30, Resolution.Daily);
    -        foreach (var universeDay in universeHistory)
    -        {
    -            foreach (CryptoUniverse universeItem in universeDay)
    -            {
    -                var symbol = universeItem.Symbol;
    -                var price = universeItem.Close;
    -            }
    -        }
    -    }
    +        // Set the time zone to HKT to make it more comparable with the exchange.
    +        SetTimeZone(TimeZones.HongKong);
    +        // Set the account currency as HKD to trade HSI Futures.
    +        SetAccountCurrency("HKD", 1000000);
     
    -    private IEnumerable<Symbol> SelectAssets(IEnumerable<CryptoUniverse> universeDay)
    -    {
    -        // Filter for materially traded Crypto pairs with significant 
    -        // size and dollar volume, assuming higher capital flow in for 
    -        // higher return.
    -        return from universeItem in universeDay
    -                where universeItem.Volume >= 100m 
    -                && universeItem.VolumeInUsd > 10000000m
    -                select universeItem.Symbol;
    +        // Seed the last price of the contracts for filling.
    +        Settings.SeedInitialPrices = true;
    +
    +        // Request HSI Futures to trade. 
    +        // Note that we will trade the contract with the highest open interest for liquidity.
    +        _hsiFuture = AddFuture(
    +            Futures.Indices.HangSeng,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.LastTradingDay,
    +            contractDepthOffset: 0
    +        );
    +        // Request the corresponding underlying index for feeding indicators for trade signal generation.
    +        var hsiIndex = AddIndex("HSI").Symbol;
    +
    +        // Create a ZigZag indicator to trade Hang Seng Index price pivot points.
    +        _zz = ZZ(hsiIndex, 0.15m, 5, Resolution.Daily);
    +        // Warm up indicator for immediate readiness to trade.
    +        WarmUpIndicator(hsiIndex, _zz, Resolution.Daily);
         }
     
         public override void OnData(Slice slice)
         {
    -        // Speculate-invest all available free cash on BTCUSD, repecting 
    -        // the order quantity restrictions to avoid invalid orders.
    -        if (Portfolio.CashBook["BTC"].Amount != 0)
    +        // Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    +        if (IsMarketOpen(_hsiFuture.Symbol) && _zz.IsReady)
             {
    -            return;
    +            var pivot = _zz.PivotType;
    +            // If the last pivot point is low, the current trend is increasing after this low point.
    +            if (pivot == PivotPointType.Low && !Portfolio[_hsiFuture.Symbol].IsLong)
    +            {
    +                SetHoldings(_hsiFuture.Mapped, 0.2m);
    +            }
    +            // If the last pivot point is high, the current trend decreases after this high point.
    +            else if (pivot == PivotPointType.High && !Portfolio[_hsiFuture.Symbol].IsShort)
    +            {
    +                SetHoldings(_hsiFuture.Mapped, -0.2m);
    +            }
             }
    -        // Define a buffer so that we can scale down the order size,
    -        // avoiding trading errors.
    -        var buffer = Math.Max(KrakenFeeModel.TakerTier1CryptoFee, Settings.FreePortfolioValuePercentage);
    -        var quantity = Portfolio.CashBook["USD"].Amount / _btc.AskPrice * (1-buffer);
    -        // Check if the quantity exceeds the minimum order size. On 
    -        // Kraken, the minimum order size is measured in the base 
    -        // currency (BTC in this case).
    -        if (Math.Abs(quantity) < _btc.SymbolProperties.MinimumOrderSize)
    +
    +        // Handle rollover in case the current mapped contract changes.
    +        foreach (var (_, changedEvent) in slice.SymbolChangedEvents)
             {
    -            return;
    +            var oldSymbol = changedEvent.OldSymbol;
    +            var newSymbol = AddFutureContract(changedEvent.NewSymbol).Symbol;
    +            var quantity = Portfolio[oldSymbol].Quantity;
    +            // Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    +            Liquidate(oldSymbol);
    +            if (quantity != 0)
    +            {
    +                MarketOrder(newSymbol, quantity);
    +            }
             }
    -        MarketOrder(_btc, quantity);
         }
     }

    - Framework Algorithm Example + Classic Algorithm Example -- FESX Futures

    - The following example algorithm creates a dynamic universe of Crypto pairs on the Kraken exchange and then forms a equal-weighted portfolio of all the pairs in the universe: + The following example algorithm uses the + + MACD + + indicator to determine the trend of the EuroStoxx50 Index. To trade the Index, we make use of the FESX Futures.

    from AlgorithmImports import *
     
     
    -class CoinAPIDataAlgorithm(QCAlgorithm):
    -
    +class InternationalFuturesDataAlgorithm(QCAlgorithm):
         def initialize(self) -> None:
             self.set_start_date(2024, 9, 1)
             self.set_end_date(2024, 12, 31)
    -        self.set_cash(100000)
    -        self.settings.free_portfolio_value_percentage = 0.05
    +        # Set the time zone to Berlin to make it more comparable with the exchange.
    +        self.set_time_zone(TimeZones.BERLIN)
    +        # Set the account currency as EUR to trade FSX Futures.
    +        self.set_account_currency("EUR", 1000000)
    +        # Seed the last price of the contracts for filling.
    +        self.settings.seed_initial_prices = True
     
    -        # Kraken accepts both Cash and Margin type account, select the one you need for the best reality modeling.
    -        self.set_brokerage_model(BrokerageName.KRAKEN, AccountType.MARGIN)
    +        # Request FESX Futures to trade. 
    +        # Note that we will trade the contract with the highest open interest for liquidity.
    +        self.fesx_future = self.add_future(
    +            Futures.Indices.EURO_STOXX_50,
    +            extended_market_hours=True,
    +            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
    +            contract_depth_offset=0
    +        )
    +        # Request the corresponding underlying Index for feeding indicator for trade signal generation.
    +        fesx_index = self.add_index("SX5E").symbol
     
    -        # Warm up the security with the last known price to avoid conversion error
    -        self.settings.seed_initial_prices = True
    -        
    -        # Get the pairs on Kraken that have USD as the quote currency.
    -        self._market_pairs = [
    -            x.key.symbol 
    -            for x in self.symbol_properties_database.get_symbol_properties_list(Market.KRAKEN) 
    -            if x.value.quote_currency == self.account_currency
    -        ]
    -        # Add Crypto Universe Selection that select crypto pairs in Kraken exchange
    -        self.add_universe(CryptoUniverse.kraken(self.universe_selection_filter))
    -        
    -        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(hours=4), 0.025, None))
    -        # Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    -        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
    +        # Create a MACD indicator to trade EuroStoxx trend changes on the fast-slow term trend convergence.
    +        self._macd = self.macd(fesx_index, 12, 26, 9, resolution=Resolution.DAILY)
    +        # Warm up indicator for immediate readiness to trade.
    +        self.warm_up_indicator(fesx_index, self._macd, Resolution.DAILY)
     
    -    def universe_selection_filter(self, universe_day: List[CryptoUniverse]) -> List[Symbol]:
    -        # Select pairs where the quote currency is USD.
    -        pairs = [c for c in universe_day if c.symbol.value in self._market_pairs]
    -        # Filter for materially traded crypto pairs with significant dollar volume, assuming higher capital flow in for higher return.
    -        pairs = sorted(pairs, key=lambda c: c.volume_in_usd)[-3:]      
    -        return [c.symbol for c in pairs]
    +    def on_data(self, slice: Slice) -> None:
    +        # Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    +        if self.is_market_open(self.fesx_future.symbol) and self._macd.is_ready:
    +            # To identify a sensitive change in trend, use the change in the histogram value of the MACD.
    +            histogram = self._macd.histogram
    +            histogram_chg = histogram.current.value - histogram.previous.value
    +            # Positive histogram value increasing means the fast trend is rising faster than the slow trend, indicating a strong uptrend.
    +            if histogram_chg > 0 and histogram.current.value > 0 and not self.portfolio[self.fesx_future.symbol].is_long:
    +                self.set_holdings(self.fesx_future.mapped, 0.2)
    +            # Negative histogram value decreasing means the slow trend is dropping faster than the fast trend, indicating a strong downtrend.
    +            elif histogram_chg < 0 and histogram.current.value < 0 and not self.portfolio[self.fesx_future.symbol].is_short:
    +                self.set_holdings(self.fesx_future.mapped, -0.2)
     
    -    def on_securities_changed(self, changes: SecurityChanges) -> None:
    -        for security in changes.added_securities:
    -            # Historical data
    -            history = self.history(security.symbol, 30, Resolution.DAILY)
    -            self.debug(f"We got {len(history)} items from our history request")
    -
    public class CoinAPIDataAlgorithm : QCAlgorithm
    +        # Handle rollover in case the current mapped contract changes.
    +        for _, changed_event in slice.symbol_changed_events.items():
    +            old_symbol = changed_event.old_symbol
    +            new_symbol = self.add_future_contract(changed_event.new_symbol).symbol
    +            quantity = self.portfolio[old_symbol].quantity
    +            # Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    +            self.liquidate(old_symbol)
    +            if quantity != 0:
    +                self.market_order(new_symbol, quantity)
    +
    public class InternationalFuturesDataAlgorithm : QCAlgorithm
     {
    -    private List<string> _marketPairs;
    -    
    +    private Future _fesxFuture;
    +    private MovingAverageConvergenceDivergence _macd;
    +
         public override void Initialize()
         {
             SetStartDate(2024, 9, 1);
             SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        Settings.FreePortfolioValuePercentage = 0.05m;
    -
    -        // Kraken accepts both Cash and Margin type account, select the one you need for the best reality modeling.            
    -        SetBrokerageModel(BrokerageName.Kraken, AccountType.Margin);
    -
    -        // Warm up the security with the last known price to avoid conversion error
    +        // Set the time zone to Berlin to make it more comparable with the exchange.
    +        SetTimeZone(TimeZones.Berlin);
    +        // Set the account currency as EUR to trade FSX Futures.
    +        SetAccountCurrency("EUR", 1000000);
    +        // Seed the last price of the contracts for filling.
             Settings.SeedInitialPrices = true;
    -        
    -        // Get the pairs on Kraken that have USD as the quote currency.
    -        _marketPairs = SymbolPropertiesDatabase.GetSymbolPropertiesList(Market.Kraken)
    -            .Where(x => x.Value.QuoteCurrency == AccountCurrency)
    -            .Select(x => x.Key.Symbol)
    -            .ToList();
    -        // Add Crypto Universe Selection that select crypto pairs in Kraken exchange
    -        AddUniverse(CryptoUniverse.Kraken(UniverseSelectionFilter));
    -    
    -        AddAlpha( new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromHours(4), 0.025, null) );
    -        // Equally invest to evenly dissipate the capital concentration risk of inidividual crypto pair
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -    }
     
    -    private IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    -    {
    -        // Select pairs where the quote currency is USD.
    -        return universeDay.Where(c => _marketPairs.Contains(c.Symbol.Value))
    -            // Filter for materially traded crypto pairs with significant size and dollar volume, assuming higher capital flow in for higher return
    -            .OrderBy(c => c.VolumeInUsd)
    -            .TakeLast(3)
    -            .Select(c => c.Symbol);
    +        // Request FESX Futures to trade. 
    +        // Note that we will trade the contract with the highest open interest for liquidity.
    +        _fesxFuture = AddFuture(
    +            Futures.Indices.EuroStoxx50,
    +            extendedMarketHours: true,
    +            dataMappingMode: DataMappingMode.LastTradingDay,
    +            contractDepthOffset: 0
    +        );
    +        // Request the corresponding underlying Index for feeding indicator for trade signal generation.
    +        var fesxIndex = AddIndex("SX5E").Symbol;
    +
    +        // Create a MACD indicator to trade EuroStoxx trend changes on the fast-slow term trend convergence.
    +        _macd = MACD(fesxIndex, 12, 26, 9, resolution: Resolution.Daily);
    +        // Warm up indicator for immediate readiness to trade.
    +        WarmUpIndicator(fesxIndex, _macd, Resolution.Daily);
         }
     
    -    public override void OnSecuritiesChanged(SecurityChanges changes)
    +    public override void OnData(Slice slice)
         {
    -        foreach(var security in changes.AddedSecurities)
    +        // Only place trade if the Future contracts is in market opening hours to avoid stale fills.
    +        if (IsMarketOpen(_fesxFuture.Symbol) && _macd.IsReady)
             {
    -            // Historical data
    -            var history = History(security.Symbol, 30, Resolution.Daily);
    -            Debug($"We got {history.Count()} items from our history request");
    +            // To identify a sensitive change in trend, use the change in the histogram value of the MACD.
    +            var histogram = _macd.Histogram;
    +            var histogramChg = histogram - histogram.Previous;
    +            // Positive histogram value increasing means the fast trend is rising faster than the slow trend, indicating a strong uptrend.
    +            if (histogramChg > 0 && histogram > 0 && !Portfolio[_fesxFuture.Symbol].IsLong)
    +            {
    +                SetHoldings(_fesxFuture.Mapped, 0.2m);
    +            }
    +            // Negative histogram value decreasing means the slow trend is dropping faster than the fast trend, indicating a strong downtrend.
    +            else if (histogramChg < 0 && histogram < 0 && !Portfolio[_fesxFuture.Symbol].IsShort)
    +            {
    +                SetHoldings(_fesxFuture.Mapped, -0.2m);
    +            }
             }
    -    }
    -}
    -
    -

    - Research Example -

    -

    - The following example lists crypto-currency pairs with the greatest dollar volume in the Kraken exchange: -

    -
    -
    var qb = new QuantBook();
    -
    -// Add Cryptocurrency pair
    -var symbol = qb.AddCrypto("BTCUSDT", market:Market.Kraken).Symbol;
    -
    -// Historical data
    -var history = qb.History(symbol, 30, Resolution.Daily);
    -foreach (var bar in history)
    -{
    -    Console.WriteLine($"{bar.EndTime} {bar}");
    -}
    -
    -// Add Crypto Universe Selection
    -IEnumerable<Symbol> UniverseSelectionFilter(IEnumerable<CryptoUniverse> universeDay)
    -{
    -    return universeDay
    -        .Where(x => x.VolumeInUsd != null && x.VolumeInUsd > 10000m)
    -        .OrderByDescending(x => x.VolumeInUsd)
    -        .Take(5)
    -        .Select(x => x.Symbol);
    -}
    -var universe = qb.AddUniverse(CryptoUniverse.Kraken(UniverseSelectionFilter));
     
    -// Historical Universe data
    -var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-30), qb.Time);
    -foreach (var universeDay in universeHistory)
    -{
    -    Console.WriteLine($"=== {universeDay.First().EndTime} ===");
    -    foreach (CryptoUniverse universeItem in universeDay.OrderByDescending(x => x.VolumeInUsd))
    -    {
    -        Console.WriteLine($"{universeItem.Symbol}: {universeItem.VolumeInUsd}");
    +        // Handle rollover in case the current mapped contract changes.
    +        foreach (var (_, changedEvent) in slice.SymbolChangedEvents)
    +        {
    +            var oldSymbol = changedEvent.OldSymbol;
    +            var newSymbol = AddFutureContract(changedEvent.NewSymbol).Symbol;
    +            var quantity = Portfolio[oldSymbol].Quantity;
    +            // Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
    +            Liquidate(oldSymbol);
    +            if (quantity != 0)
    +            {
    +                MarketOrder(newSymbol, quantity);
    +            }
    +        }
         }
     }
    -
    qb = QuantBook()
    -
    -# Add Cryptocurrency pair
    -symbol = qb.add_crypto("BTCUSDT", market=Market.KRAKEN).symbol
    -
    -# Historical data
    -history = qb.history(symbol, 30, Resolution.DAILY)
    -for (symbol, time), row in history.iterrows():
    -    print(f'{time} {symbol} {row.close}')
    -
    -# Add Crypto Universe Selection
    -def universe_selection_filter(universe_day):
    -    selected = sorted([x for x in universe_day
    -        if x.volume_in_usd and x.volume_in_usd > 10000],
    -        key=lambda x: x.volume_in_usd, reverse=True)[:5]
    -    return [x.symbol for x in selected]
    -
    -universe = qb.add_universe(CryptoUniverse.kraken(universe_selection_filter))
    -
    -# Historical Universe data
    -history = qb.universe_history(universe, qb.time-timedelta(30), qb.time)
    -for (univere_symbol, time), universe_day in history.items():
    -    print(f'=== {time} ===')
    -    for universe_item in sorted(universe_day, key=lambda x: x.volume_in_usd, reverse=True):
    -        print(f"{universe_item.symbol}: {universe_item.volume_in_usd}")
    @@ -237288,67 +238454,84 @@

    Data Point Attributes

    - The Kraken Crypto Price dataset provides + The International Futures dataset provides - TradeBar + Future , - QuoteBar + FuturesChain - , + , and - Tick + OpenInterest - , and + objects. To configure the continuous Future settings, use the - CryptoUniverse + DataNormalizationMode - objects. + and + + DataMappingMode + + enumerations.

    - TradeBar Attributes + Future Attributes

    - TradeBar + Future objects have the following attributes:

    -
    +

    - QuoteBar Attributes + FuturesChain Attributes

    - QuoteBar + FuturesChain objects have the following attributes:

    -
    +

    - Tick Attributes + OpenInterest Attributes

    - Tick + OpenInterest objects have the following attributes:

    -
    +

    - CryptoUniverse Attributes + DataNormalizationMode Values

    + The - CryptoUniverse + DataNormalizationMode - objects have the following attributes: + enumeration has the following values:

    -
    +
    +
    +

    + DataMappingMode Values +

    +

    + The + + DataMappingMode + + enumeration has the following values: +

    +
    @@ -237356,7 +238539,7 @@

     

    -
    +

    Datasets

    Benzinga

    @@ -237372,7 +238555,7 @@

    Benzinga

    + for security in changes.removed_securities: + if security in self._securities: + # Unsubscribe from Benzinga news feed for this security to release computational resources + algorithm.remove_security(security.benzinga_data) + self._securities.remove(security)
    using System.Text.RegularExpressions;
     
    -public class BenzingaNewsDataAlgorithm : QCAlgorithm
    +
    +namespace QuantConnect.Algorithm.CSharp
     {
    -    public override void Initialize()
    +    public class BenzingaNewsDataAlgorithm : QCAlgorithm
         {
    -        SetStartDate(2024, 9, 1);
    -        SetEndDate(2024, 12, 31);
    -        SetCash(100000);
    -        
    -        AddUniverseSelection(
    -            new ManualUniverseSelectionModel(
    -                QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)
    -        ));
    -        
    -        AddAlpha(new BenzingaAlphaModel());
    -        
    -        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    -        
    -        AddRiskManagement(new NullRiskManagementModel());
    -        
    -        SetExecution(new ImmediateExecutionModel());
    +        public override void Initialize()
    +        {
    +            SetStartDate(2024, 9, 1);
    +            SetEndDate(2024, 12, 31);
    +            SetCash(100000);
    +            
    +            AddUniverseSelection(
    +                new ManualUniverseSelectionModel(
    +                    QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA)
    +            ));
    +            
    +            AddAlpha(new BenzingaAlphaModel());
    +            
    +            SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
    +            
    +            AddRiskManagement(new NullRiskManagementModel());
    +            
    +            SetExecution(new ImmediateExecutionModel());
    +        }
         }
    -}
     
    -public class BenzingaAlphaModel : AlphaModel
    -{
    -    private Dictionary<Symbol, SymbolData> _symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
    -    // A custom word-score map for calculating the total sentiment score
    -    private Dictionary<string, int> _wordScores = new Dictionary<string, int>(){
    -        {"good", 1}, {"great", 1}, {"best", 1}, {"growth", 1},
    -        {"bad", -1}, {"terrible", -1}, {"worst", -1}, {"loss", -1}
    -    };
    -
    -    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    +    public class BenzingaAlphaModel : AlphaModel
         {
    -        var insights = new List<Insight>();
    -        
    -        foreach (var kvp in _symbolDataBySymbol)
    +        private List< Security>  _securities = [];
    +        // A custom word-score map for calculating the total sentiment score
    +        private readonly Dictionary< string, int>  _wordScores = new(){
    +            {"good", 1}, {"great", 1}, {"best", 1}, {"growth", 1},
    +            {"bad", -1}, {"terrible", -1}, {"worst", -1}, {"loss", -1}
    +        };
    +
    +        public override IEnumerable< Insight>  Update(QCAlgorithm algorithm, Slice slice)
             {
    -            var symbol = kvp.Key;
    -            var symbolData = kvp.Value;
    -            
    -            if (slice.ContainsKey(symbolData.benzingaSymbol))
    -            {
    -                // Assign a sentiment score to the news article by specific word appearance scoring
    -                var contentWords = slice[symbolData.benzingaSymbol].Contents.ToLower();
    +            var insights = new List< Insight> ();
    +
    +            foreach (var (benzingaSymbol, newsItem) in slice.Get< BenzingaNews> ())
    +            {               
    +                var security = algorithm.Securities[benzingaSymbol.Underlying];
    +                var contentWords = newsItem.Contents.ToLower();
                     var score = 0;
    +
                     foreach (var entry in _wordScores)
                     {
    -                    score += (Regex.Matches(contentWords, entry.Key).Count * entry.Value);
    +                    score += Regex.Matches(contentWords, entry.Key).Count * entry.Value;
                     }
    -                symbolData.targetDirection = score > 0 ? InsightDirection.Up : InsightDirection.Flat;
    -            }
    -            
    -            
    -            // Ensure we have security data in the current Slice to avoid stale filling
    -            if (!(slice.ContainsKey(symbol) && slice[symbol] != null && !slice[symbol].IsFillForward))
    -            {
    -                continue;
    +                var targetDirection = score >  0 ? InsightDirection.Up : InsightDirection.Flat;
    +                security.Set("TargetDirection", targetDirection);
                 }
                 
    -            // Buy or sell if the sentiment has changed from our current holdings
    -            if (symbolData.currentDirection != symbolData.targetDirection)
    +            // Generate insights based on direction changes
    +            foreach (var security in _securities)
                 {
    -                insights.Add(Insight.Price(symbol, TimeSpan.FromDays(14), symbolData.targetDirection));
    -                symbolData.currentDirection = symbolData.targetDirection;
    +                if (!(slice.ContainsKey(security)  &&  slice[security] != null  &&  !slice[security].IsFillForward)) continue;
    +                
    +                var targetDirection = security.Get< InsightDirection> ("TargetDirection");
    +                
    +                // Buy or sell if the sentiment has changed from our current holdings
    +                if (security.Get< InsightDirection> ("CurrentDirection") != targetDirection)
    +                {
    +                    insights.Add(Insight.Price(security, TimeSpan.FromDays(14), targetDirection));
    +                    security.Set("CurrentDirection", targetDirection);
    +                }
                 }
    +            return insights;
             }
    -        return insights;
    -    }
     
    -    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    -    {
    -        foreach (var security in changes.AddedSecurities)
    +        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
             {
    -            var symbol = security.Symbol;
    -            _symbolDataBySymbol.Add(symbol, new SymbolData(algorithm, symbol));
    -        }
    +            foreach (var security in changes.AddedSecurities)
    +            {
    +                // Requesting data to obtain the updated news for sentiment score calculation
    +                var benzingaSymbol = algorithm.AddData< BenzingaNews> (security.Symbol).Symbol;
    +                security.Set("CurrentDirection", InsightDirection.Flat);
    +                security.Set("TargetDirection", InsightDirection.Flat);
     
    -        foreach (var security in changes.RemovedSecurities)
    -        {
    -            var symbol = security.Symbol;
    -            if (_symbolDataBySymbol.ContainsKey(symbol))
    +                // Historical data
    +                var history = algorithm.History< BenzingaNews> (benzingaSymbol, 14, Resolution.Daily);
    +                algorithm.Debug($"We got {history.Count()} items from our history request");
    +                _securities.Add(security);
    +                security.Set("BenzingaSymbol", benzingaSymbol);
    +            }
    +
    +            foreach (var security in changes.RemovedSecurities)
                 {
    -                _symbolDataBySymbol[symbol].dispose();
    -                _symbolDataBySymbol.Remove(symbol);
    +                if (_securities.Contains(security))
    +                {
    +                    algorithm.RemoveSecurity(security.Get< Symbol> ("BenzingaSymbol"));
    +                    _securities.Remove(security);
    +                }
                 }
             }
         }
    -}
    -
    -
    -public class SymbolData
    -{
    -    private QCAlgorithm _algorithm;
    -    public Symbol benzingaSymbol;
    -    public InsightDirection currentDirection = InsightDirection.Flat;
    -    public InsightDirection targetDirection = InsightDirection.Flat;
    -    
    -    
    -    public SymbolData(QCAlgorithm algorithm, Symbol symbol)
    -    {
    -        _algorithm = algorithm;
    -        
    -        // Requesting data to obtain the updated news for sentiment score calculation
    -        benzingaSymbol = algorithm.AddData<BenzingaNews>(symbol).Symbol;
    -        
    -        // Historical data
    -        var history = algorithm.History<BenzingaNews>(benzingaSymbol, 14, Resolution.Daily);
    -        algorithm.Debug($"We got {history.Count()} items from our history request");
    -    }
    -    
    -    public void dispose()
    -    {
    -        // Unsubscribe from the Benzinga feed for this security to release computational resources
    -        _algorithm.RemoveSecurity(benzingaSymbol);
    -    }
     }
    @@ -238033,7 +239187,7 @@

    Data Point Attributes

     

    -
    +

    Datasets

    Blockchain

    @@ -238052,7 +239206,7 @@

    Blockchain