QuantConnect

Spectral Tick Flow Signal

Introduction

The QuantConnect Spectral Tick-Flow Signal dataset provides daily signals for US Equities based on a proprietary Fourier transform-like algorithm applied to US Equity tick data. The dataset is designed to summarize recurring intraday trade-flow patterns and potential execution-flow activity into a compact set of fields that can be used for screening, ranking, and research across a large-cap US Equity universe.

The data covers 500 US Equities across S&P 500 constituents and SPY, starts in June 2009, and is delivered on a daily frequency. Each data point is linked to a US Equity and represents one security for one trading day. The dataset also includes a daily universe file, enabling algorithms to rank or filter the full cross-section without manually subscribing to every symbol.

The headline score is ExecutionScore, a non-negative value that reflects the strength of the detected execution-flow signal for a security on a given day. Larger values indicate stronger signal activity relative to other securities or dates. The SignatureCount field can be used to distinguish confirmed signal events from lower-confidence observations.

Typical use is to request the daily cross-section, rank securities by ExecutionScore or related fields, and use the results as an input to a long-only, long-short, market-neutral, or risk-management strategy.

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 Spectral Tick Flow Signal 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 Spectral Tick-Flow Signal dataset:

self._equity = self.add_equity("AAPL", Resolution.DAILY)
self.dataset_symbol = self.add_data(SpectralTickFlowSignal, self._equity).symbol
_equity = AddEquity("AAPL", Resolution.Daily).Symbol;
_datasetSymbol = AddData<SpectralTickFlowSignal>(_equity).Symbol;

Data Summary

The following table describes the dataset properties:

PropertyValue
Start DateJune 2009
Asset Coverage*500 US Equities (S&P 500 constituents and SPY)
Data DensitySparse
ResolutionDaily
TimezoneEST

The coverage includes S&P 500 constituents and SPY over the dataset history. The universe changes over time with constituent membership.

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.

Requesting Data

To add Spectral Tick-Flow Signal data to your algorithm, call the AddDataadd_data method. Save a reference to the dataset Symbol so you can access the data later in your algorithm.

class SpectralTickFlowSignalDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2026, 6, 16)
        self.set_end_date(2026, 6, 24)
        self.set_cash(100000)
        self._equity = self.add_equity("AAPL", Resolution.DAILY)
        self._dataset_symbol = self.add_data(SpectralTickFlowSignal, self._equity).symbol
public class SpectralTickFlowSignalDataAlgorithm : QCAlgorithm
{
    private Symbol _symbol, _datasetSymbol;

    public override void Initialize()
    {
        SetStartDate(2026, 6, 16);
        SetEndDate(2026, 6, 24);
        SetCash(100000);
        _equity = AddEquity("AAPL", Resolution.Daily).Symbol;
        _datasetSymbol = AddData<SpectralTickFlowSignal>(_equity).Symbol;
    }
}

Accessing Data

To add Spectral Tick-Flow Signal data to your algorithm, call the AddDataadd_data method. Save a reference to the dataset Symbol so you can access the data later in your algorithm.

class SpectralTickFlowSignalDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2026, 6, 16)
        self.set_end_date(2026, 6, 24)
        self.set_cash(100000)
        self._equity = self.add_equity("AAPL", Resolution.DAILY)
        self._dataset_symbol = self.add_data(SpectralTickFlowSignal, self._equity).symbol
public class SpectralTickFlowSignalDataAlgorithm : QCAlgorithm
{
    private Symbol _equity, _datasetSymbol;

    public override void Initialize()
    {
        SetStartDate(2026, 6, 16);
        SetEndDate(2026, 6, 24);
        SetCash(100000);
        _equity = AddEquity("AAPL", Resolution.Daily).Symbol;
        _datasetSymbol = AddData<SpectralTickFlowSignal>(_equity).Symbol;
    }
}

Historical Data

To get historical Spectral Tick-Flow Signal data, call the Historyhistory 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_bars = self.history[SpectralTickFlowSignal](self._dataset_symbol, 100, Resolution.DAILY)
var history = History<SpectralTickFlowSignal>(_datasetSymbol, 100, Resolution.Daily);

For more information about historical data, see History Requests.

Universe Selection

To select a dynamic universe of US Equities based on Spectral Tick-Flow Signal data, call the AddUniverseadd_universe method with the SpectralTickFlowSignalUniverse class and a selection function. Each daily universe file delivers the full cross-section, so you can rank or filter every covered name by any signal field, for example, the names with the strongest confirmed algorithmic-execution intensity.

def initialize(self) -> None:
    self.universe_settings.resolution = Resolution.DAILY
    self._universe = self.add_universe(SpectralTickFlowSignalUniverse, self._select_assets)

def _select_assets(self, alt_coarse: List[SpectralTickFlowSignalUniverse]) -> List[Symbol]:
    confirmed = [d for d in alt_coarse if d.signature_count > 0]
    return [d.symbol for d in sorted(confirmed, key=lambda d: d.execution_score)[-10:]]
private Universe _universe;
public override void Initialize()
{
    UniverseSettings.Resolution = Resolution.Daily;
    _universe = AddUniverse<SpectralTickFlowSignalUniverse>(altCoarse =>
    {
        return altCoarse
            .OfType<SpectralTickFlowSignalUniverse>()
            .Where(d => d.SignatureCount > 0)
            .OrderBy(d => d.ExecutionScore)
            .TakeLast(10)
            .Select(d => d.Symbol);
    });
}

Remove Subscriptions

To remove a subscription, call the RemoveSecurityremove_security method.

self.remove_security(self.dataset_symbol)
RemoveSecurity(_datasetSymbol);

If you subscribe to Spectral Tick-Flow Signal data for assets in a dynamic universe, remove the dataset subscription when the asset leaves your universe. To view a common design pattern, see Track Security Changes.

Example Applications

The QuantConnect Spectral Tick-Flow Signal dataset enables you to test strategies using daily tick-flow signals provided by QuantConnect. Examples include the following strategies:

  • Ranking a large-cap US Equity universe by each security's ExecutionScore
  • Buying securities with the strongest detected execution-flow activity
  • Building a market-neutral strategy based on the top N and bottom N securities in the daily signal universe
  • Using tick-flow signal strength as a filter, confirmation variable, or position-sizing input in an existing Equity strategy

Classic Algorithm Example

The following example algorithm buys Apple when its Spectral Tick-Flow Signal ExecutionScore clears a threshold, signaling active algorithmic-execution flow. Otherwise, it remains in cash.

from AlgorithmImports import *


class SpectralTickFlowSignalAlgorithm(QCAlgorithm):
    execution_score_threshold = 15

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)
        # AAPL is both the traded security and the equity the custom signal is linked to.
        self._aapl = self.add_equity("AAPL", Resolution.DAILY)
        self.dataset_symbol = self.add_data(SpectralTickFlowSignal, self._aapl).symbol

    def on_data(self, data: Slice) -> None:
        # Require current signal and equity data to avoid stale fills.
        if self.dataset_symbol not in data:
            return
        # Hold AAPL on strong algorithmic-execution intensity, otherwise stand aside.
        execution_score = data[self.dataset_symbol].execution_score
        target_holdings = 1 if execution_score > self.execution_score_threshold else 0
        if target_holdings != self.portfolio.invested:
            self.set_holdings(self._aapl, target_holdings)
public class SpectralTickFlowSignalAlgorithm : QCAlgorithm
{
    private Equity _aapl;
    private Symbol _datasetSymbol;
    private const decimal ExecutionScoreThreshold = 15m;

    public override void Initialize()
    {
        SetStartDate(2024, 9, 1);
        SetEndDate(2024, 12, 31);
        SetCash(100000);
        // AAPL is both the traded security and the equity the custom signal is linked to.
        _aapl = AddEquity("AAPL", Resolution.Daily);
        _datasetSymbol = AddData<SpectralTickFlowSignal>(_aapl.Symbol).Symbol;
    }

    public override void OnData(Slice slice)
    {
        // Require current signal and equity data to avoid stale fills.
        if (!slice.ContainsKey(_datasetSymbol))
        {
            return;
        }
        // Hold AAPL on strong algorithmic-execution intensity, otherwise stand aside.
        decimal executionScore = slice[_datasetSymbol].ExecutionScore;
        var targetHoldings = executionScore > ExecutionScoreThreshold ? 1 : 0;
        if (targetHoldings == 1 != Portfolio.Invested)
        {
            SetHoldings(_aapl.Symbol, targetHoldings);
        }
    }
}

Framework Algorithm Example

The following example algorithm creates a dynamic universe of US Equities that have a confirmed algorithmic-execution signature. It then buys the subset of Equities with the strongest execution intensity and forms an equal-weighted portfolio.

from AlgorithmImports import *


class SpectralTickFlowSignalAlgorithm(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.seed_initial_prices = True
        self.universe_settings.resolution = Resolution.DAILY
        # Filter to the confirmed execution signatures with the strongest intensity.
        self.add_universe(SpectralTickFlowSignalUniverse, self.universe_selection)
        self.add_alpha(SpectralTickFlowSignalAlphaModel())
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())
        self.add_risk_management(NullRiskManagementModel())
        self.set_execution(ImmediateExecutionModel())

    def universe_selection(self, alt_coarse: List[SpectralTickFlowSignalUniverse]) -> List[Symbol]:
        # Keep only confirmed execution signatures, ranked by intensity.
        confirmed = [d for d in alt_coarse if d.signature_count > 0]
        return [d.symbol for d in sorted(confirmed, key=lambda d: d.execution_score)[-50:]]


class SpectralTickFlowSignalAlphaModel(AlphaModel):
    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
        insights = []
        for dataset_symbol, data_point in slice.get(SpectralTickFlowSignal).items():
            security = algorithm.securities[dataset_symbol.underlying]
            # Buy names with a confirmed execution signature, liquidate otherwise.
            target_direction = InsightDirection.UP if data_point.signature_count > 0 else InsightDirection.FLAT
            if security.price and target_direction == InsightDirection.UP and not security.invested:
                insights.append(Insight.price(security, timedelta(7), target_direction))
        return insights

    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
        for security in changes.added_securities:
            # Subscribe to the daily signal feed for the added equity.
            dataset = algorithm.add_data(SpectralTickFlowSignal, security, Resolution.DAILY)
            security.dataset_symbol = dataset.symbol
        for security in changes.removed_securities:
            # Unsubscribe from the Spectral Tick-Flow Signal feed.
            algorithm.remove_security(security.dataset_symbol)
public class SpectralTickFlowSignalAlgorithm : QCAlgorithm
{
    public override void Initialize()
    {
        SetStartDate(2024, 9, 1);
        SetEndDate(2024, 12, 31);
        SetCash(100000);
        Settings.SeedInitialPrices = true;
        UniverseSettings.Resolution = Resolution.Daily;
        // Filter to the confirmed execution signatures with the strongest intensity.
        AddUniverse<SpectralTickFlowSignalUniverse>(altCoarse => altCoarse
            .Select(d => d as SpectralTickFlowSignalUniverse)
            .Where(d => d.SignatureCount > 0)
            .OrderBy(d => d.ExecutionScore)
            .TakeLast(50)
            .Select(d => d.Symbol)
        );
        AddAlpha(new SpectralTickFlowSignalAlphaModel());
        SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
        AddRiskManagement(new NullRiskManagementModel());
        SetExecution(new ImmediateExecutionModel());
    }
}


public class SpectralTickFlowSignalAlphaModel : AlphaModel
{
    public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
    {
        var insights = new List<Insight>();
        foreach (var (datasetSymbol, dataPoint) in slice.Get<SpectralTickFlowSignal>())
        {
            var security = algorithm.Securities[datasetSymbol.Underlying];
            // Buy names with a confirmed execution signature, liquidate otherwise.
            var targetDirection = dataPoint.SignatureCount > 0 ? InsightDirection.Up : InsightDirection.Flat;
            if (security.Price != 0 && targetDirection == InsightDirection.Up && !security.Holdings.Invested)
            {
                insights.Add(Insight.Price(security.Symbol, TimeSpan.FromDays(7), targetDirection));
            }
        }
        return insights;
    }

    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    {
        foreach (var security in changes.AddedSecurities)
        {
            // Subscribe to the daily signal feed for the added equity.
            var dataset = algorithm.AddData<SpectralTickFlowSignal>(security.Symbol, Resolution.Daily);
            security.Set("DatasetSymbol", dataset.Symbol);
        }
        foreach (var security in changes.RemovedSecurities)
        {
            // Unsubscribe from the Spectral Tick-Flow Signal feed.
            algorithm.RemoveSecurity(security.Get<Symbol>("DatasetSymbol"));
        }
    }
}

Research Example

The following example lists US Equities with confirmed algorithmic-execution signatures, ranked by execution intensity.

#r "../QuantConnect.DataSource.SpectralTickFlowSignal.dll"
using QuantConnect.DataSource;

var qb = new QuantBook();

// Requesting data
var aapl = qb.AddEquity("AAPL", Resolution.Daily).Symbol;
var symbol = qb.AddData<SpectralTickFlowSignal>(aapl).Symbol;

// Historical data
var history = qb.History<SpectralTickFlowSignal>(symbol, 30, Resolution.Daily);
foreach (SpectralTickFlowSignal signal in history)
{
    Console.WriteLine($"{signal} at {signal.EndTime}");
}

// Add Universe Selection
IEnumerable<Symbol> UniverseSelection(IEnumerable<BaseData> altCoarse)
{
    return (from d in altCoarse.OfType<SpectralTickFlowSignalUniverse>()
        where d.SignatureCount > 0
        orderby d.ExecutionScore descending select d.Symbol).Take(10);
}
var universe = qb.AddUniverse<SpectralTickFlowSignalUniverse>(UniverseSelection);

// Historical Universe data
var universeHistory = qb.UniverseHistory(universe, qb.Time.AddDays(-5), qb.Time);
foreach (var signals in universeHistory)
{
    foreach (SpectralTickFlowSignalUniverse signal in signals)
    {
        Console.WriteLine($"{signal.Symbol} execution score at {signal.EndTime}: {signal.ExecutionScore}");
    }
}
qb = QuantBook()

# Requesting Data
aapl = qb.add_equity("AAPL", Resolution.DAILY)
symbol = qb.add_data(SpectralTickFlowSignal, aapl).symbol

# Historical data
history = qb.history(SpectralTickFlowSignal, symbol, 30, Resolution.DAILY)
for (symbol, time), row in history.iterrows():
    print(f"{symbol} execution score at {time}: {row['execution_score']}")

# Add Universe Selection
def universe_selection(alt_coarse: List[SpectralTickFlowSignalUniverse]) -> List[Symbol]:
    confirmed = [d for d in alt_coarse if d.signature_count > 0]
    return [d.symbol for d in sorted(confirmed, key=lambda d: d.execution_score, reverse=True)[:10]]

universe = qb.add_universe(SpectralTickFlowSignalUniverse, universe_selection)

# Historical Universe data
universe_history = qb.universe_history(universe, qb.time-timedelta(5), qb.time)
for (_, time), signals in universe_history.items():
    for signal in signals:
        print(f"{signal.symbol} execution score at {signal.end_time}: {signal.execution_score}")

Data Point Attributes

The Spectral Tick-Flow Signal dataset provides SpectralTickFlowSignal and SpectralTickFlowSignalUniverse objects.

SpectralTickFlowSignal Attributes

SpectralTickFlowSignal objects have the following attributes:

SpectralTickFlowSignalUniverse Attributes

SpectralTickFlowSignalUniverse objects have the following attributes:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: