United States Patent and Trademark Office

Patent Maintenance

Introduction

The Patent Maintenance dataset by the United States Patent and Trademark Office (USPTO) tracks the patent renewals and lapses of US-listed companies. The data covers 2,896 US Equities, starts in April 1985, and is delivered on a weekly frequency. This dataset is created by combining the USPTO maintenance fee records with PatentsView assignee data and mapping each patent owner to its ticker.

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 Patent Maintenance dataset, including CLI commands and pricing, see the dataset listing.

About the Provider

The United States Patent and Trademark Office is the agency of the US Department of Commerce that grants patents and registers trademarks. Its mission is to promote innovation by protecting the intellectual property of inventors and businesses.

Getting Started

The following snippet demonstrates how to request data from the USPTO Patent Maintenance dataset:

ibm = self.add_equity("IBM", Resolution.DAILY).symbol
self._patents = self.add_data(USPTOPatentMaintenance, ibm).symbol
var ibm = AddEquity("IBM", Resolution.Daily).Symbol;
_patents = AddData<USPTOPatentMaintenance>(ibm).Symbol;

Data Summary

The following table describes the dataset properties:

PropertyValue
Start DateApril 1985
Asset Coverage*2,896 US Equities
Data DensitySparse
ResolutionDaily**
TimezoneNew York

* The coverage includes all assets since the start date. It increases over time.

** Weekly data we fetch daily.

Requesting Data

To add USPTO Patent Maintenance 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 USPTOPatentMaintenanceAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2020, 1, 1)
        self.set_end_date(2021, 1, 1)

        ibm = self.add_equity("IBM", Resolution.DAILY).symbol
        self._patents = self.add_data(USPTOPatentMaintenance, ibm).symbol
public class USPTOPatentMaintenanceAlgorithm : QCAlgorithm
{
    private Symbol _patents;

    public override void Initialize()
    {
        SetStartDate(2020, 1, 1);
        SetEndDate(2021, 1, 1);

        var ibm = AddEquity("IBM", Resolution.Daily).Symbol;
        _patents = AddData<USPTOPatentMaintenance>(ibm).Symbol;
    }
}

Accessing Data

To get the current USPTO Patent Maintenance 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._patents):
        data_point = slice[self._patents]
        self.log(f"{self._patents} expired patents at {slice.time}: {data_point.patents_expired}")
public override void OnData(Slice slice)
{
    if (slice.ContainsKey(_patents))
    {
        var dataPoint = slice[_patents];
        Log($"{_patents} expired patents at {slice.Time}: {dataPoint.PatentsExpired}");
    }
}

To iterate through all of the dataset objects in the current Slice, call the Getget method.

def on_data(self, slice: Slice) -> None:
    for dataset_symbol, data_point in slice.get(USPTOPatentMaintenance).items():
        self.log(f"{dataset_symbol} expired patents at {slice.time}: {data_point.patents_expired}")
public override void OnData(Slice slice)
{
    foreach (var kvp in slice.Get<USPTOPatentMaintenance>())
    {
        var datasetSymbol = kvp.Key;
        var dataPoint = kvp.Value;
        Log($"{datasetSymbol} expired patents at {slice.Time}: {dataPoint.PatentsExpired}");
    }
}

Historical Data

To get historical USPTO Patent Maintenance 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._patents, 100, Resolution.DAILY)

# Dataset objects
history_bars = self.history[USPTOPatentMaintenance](self._patents, 100, Resolution.DAILY)
var history = History<USPTOPatentMaintenance>(_patents, 100, Resolution.Daily);

For more information about historical data, see History Requests.

Universe Selection

To select a dynamic universe of US Equities based on USPTO Patent Maintenance data, call the AddUniverseadd_universe method with the USPTOPatentMaintenanceUniverse class and a selection function.

def initialize(self) -> None:
    self.universe_settings.resolution = Resolution.DAILY
    self.add_universe(USPTOPatentMaintenanceUniverse, self.universe_selection)

def universe_selection(self, data: List[USPTOPatentMaintenanceUniverse]) -> List[Symbol]:
    renewing = [d for d in data if d.net_maintenance_change is not None and d.net_maintenance_change > 0]
    renewing.sort(key=lambda d: d.net_maintenance_change, reverse=True)
    return [d.symbol for d in renewing[:10]]
UniverseSettings.Resolution = Resolution.Daily;
AddUniverse<USPTOPatentMaintenanceUniverse>(data =>
{
    return data
        .OfType<USPTOPatentMaintenanceUniverse>()
        .Where(d => d.NetMaintenanceChange.HasValue && d.NetMaintenanceChange.Value > 0)
        .OrderByDescending(d => d.NetMaintenanceChange.Value)
        .Take(10)
        .Select(d => d.Symbol);
});

For more information about dynamic universes, see Universes.

Remove Subscriptions

To remove your subscription to USPTO Patent Maintenance data, call the RemoveSecurityremove_security method.

self.remove_security(self._patents)
RemoveSecurity(_patents);

If you subscribe to USPTO Patent Maintenance 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 Patent Maintenance dataset enables you to follow how companies manage the patents they already own. Examples include the following strategies:

  • Ranking companies by patent renewals against patent lapses
  • Detecting a company that suddenly starts letting many of its patents lapse
  • Comparing the lapse rate of a company against its sector peers

Classic Algorithm Example

The following example algorithm buys IBM when its net patent maintenance change rises above its trailing 13-week average. When the change falls below that average, it liquidates the position.

from AlgorithmImports import *
from QuantConnect.DataSource import *

class USPTOAlgorithm(QCAlgorithm):
    '''Example algorithm that trades IBM on its patent maintenance activity.'''

    def initialize(self) -> None:
        self.set_start_date(2020, 1, 1)
        self.set_end_date(2021, 1, 1)
        self.set_cash(100000)

        self._ibm = self.add_equity("IBM", Resolution.DAILY).symbol

        # Add the USPTO patent maintenance data for IBM.
        self._patents = self.add_data(USPTOPatentMaintenance, self._ibm).symbol

        # Track the last 13 weekly net maintenance changes.
        self._net = RollingWindow(13)

    def on_data(self, slice: Slice) -> None:
        points = slice.get(USPTOPatentMaintenance)
        if self._patents not in points:
            return

        point = points[self._patents]
        self.debug(f"{self.time:%Y-%m-%d} expired: {point.patents_expired}, "
                   f"renewed 12yr: {point.maintenance_paid_twelfth_year}")

        if point.net_maintenance_change is None:
            return

        if self._net.is_ready:
            # Buy above the trailing average and liquidate below it.
            average = sum(self._net) / self._net.count
            if point.net_maintenance_change > average and not self.portfolio[self._ibm].invested:
                self.set_holdings(self._ibm, 1)
            elif point.net_maintenance_change < average and self.portfolio[self._ibm].invested:
                self.liquidate(self._ibm)

        self._net.add(point.net_maintenance_change)

    def on_order_event(self, order_event: OrderEvent) -> None:
        if order_event.status == OrderStatus.FILLED:
            self.debug(f"{self.time} - Filled: {order_event.symbol} {order_event.fill_quantity}")
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Algorithm;
using QuantConnect.DataSource;
using QuantConnect.Indicators;

/// <summary>
/// Example algorithm that trades IBM on its patent maintenance activity.
/// </summary>
public class USPTOAlgorithm : QCAlgorithm
{
    private Symbol _ibm;
    private Symbol _patents;
    private RollingWindow<decimal> _net;

    /// <summary>
    /// Initialise the data and resolution required, as well as the cash and start-end dates.
    /// </summary>
    public override void Initialize()
    {
        SetStartDate(2020, 1, 1);
        SetEndDate(2021, 1, 1);
        SetCash(100000);

        _ibm = AddEquity("IBM", Resolution.Daily).Symbol;

        // Add the USPTO patent maintenance data for IBM.
        _patents = AddData<USPTOPatentMaintenance>(_ibm).Symbol;

        // Track the last 13 weekly net maintenance changes.
        _net = new RollingWindow<decimal>(13);
    }

    /// <summary>
    /// Trade IBM on each new patent maintenance data point.
    /// </summary>
    /// <param name="slice">Slice object keyed by symbol containing the data</param>
    public override void OnData(Slice slice)
    {
        var points = slice.Get<USPTOPatentMaintenance>();
        if (!points.ContainsKey(_patents))
        {
            return;
        }

        var point = points[_patents];
        Debug($"{Time:yyyy-MM-dd} expired: {point.PatentsExpired}, renewed 12yr: {point.MaintenancePaidTwelfthYear}");

        if (!point.NetMaintenanceChange.HasValue)
        {
            return;
        }

        if (_net.IsReady)
        {
            // Buy above the trailing average and liquidate below it.
            var total = 0m;
            foreach (var value in _net)
            {
                total += value;
            }

            var average = total / _net.Count;
            if (point.NetMaintenanceChange.Value > average && !Portfolio[_ibm].Invested)
            {
                SetHoldings(_ibm, 1);
            }
            else if (point.NetMaintenanceChange.Value < average && Portfolio[_ibm].Invested)
            {
                Liquidate(_ibm);
            }
        }

        _net.Add(point.NetMaintenanceChange.Value);
    }

    /// <summary>
    /// Log each order fill.
    /// </summary>
    /// <param name="orderEvent">Order event details</param>
    public override void OnOrderEvent(OrderEvent orderEvent)
    {
        if (orderEvent.Status.IsFill())
        {
            Debug($"{Time} - Filled: {orderEvent.Symbol} {orderEvent.FillQuantity}");
        }
    }
}

Data Point Attributes

The USPTO Patent Maintenance dataset provides USPTOPatentMaintenance and USPTOPatentMaintenanceUniverse objects.

USPTOPatentMaintenance

USPTOPatentMaintenance objects have the following attributes:

USPTOPatentMaintenanceUniverse

USPTOPatentMaintenanceUniverse 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: