Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Feed

A Feed represents a source of (financial) events that can be (re-)played to feed a run() with data. Although the most common type of events are those containing market data, other types of events are also possible. For example, events containing news items or social media posts could also be represented as a feed.

The feed is the driver of the run-loop: it produces the Event objects that all the other components react to.

A Feed is also one of the main components that you swap when moving through the 4 stages of strategy development:

StageBrokerFeed
Back TestingSimBrokerHistorical data
Forward TestingSimBrokerReal-time data
Paper TradingReal broker (paper account)Real-time data
Live TradingReal broker (real account)Real-time data

Feed API

The Feed interface itself is deliberately small and consists of just two abstract methods.

feed = rq.feeds.YahooFeed("MSFT", "AAPL", start_date="2020-01-01")
print(feed.assets())
[Stock(symbol='AAPL', currency='USD'), Stock(symbol='MSFT', currency='USD')]

Because a feed is an iterator of events, you can also play it manually. This is useful for debugging or for writing your own custom run-loop.

for event in feed.play():
    print(event.time, len(event.items))
    break
2020-01-02 05:00:00+00:00 2

Convenience methods

Most built-in feeds extend HistoricFeed, which adds a number of convenient helper methods on top of the Feed interface:

Feeds that keep everything in memory (like YahooFeed and CSVFeed) extend InMemoryFeed and additionally provide:

print(feed.timeframe())
print(feed.symbols())
[2020-01-02 05:00:00 ― 2026-08-13 04:00:00]
['MSFT', 'AAPL']

Historic Feeds

Historic feeds contain data that was recorded in the past and can be replayed for back testing. Roboquant ships with several built-in historic feeds, each with its own trade-offs in terms of data source, speed, and memory usage:

FeedDescriptionPrice Items
YahooFeedHistoric data retrieved from Yahoo FinanceBar
CSVFeedHistoric data parsed from one or more CSV filesBar
ParquetFeedHistoric data stored in a single Parquet fileBar, Trade, Quote
SQLFeedHistoric data stored in an SQLite databaseBar, Quote
RandomWalkSynthetic data generated by a random-walk modelBar, Trade, Quote

YahooFeed

YahooFeed retrieves historic market data from Yahoo Finance. It is free to use and does not require an API key. By default it retrieves daily bars, but you can specify a different interval.

feed = rq.feeds.YahooFeed("TSLA", "MSFT", start_date="2015-01-01", interval="1d")

There is also a convenience factory method us_stocks_10() that returns a feed with 10 large US stocks (MSFT, NVDA, AAPL, AMZN, META, GOOGL, AVGO, JPM, XOM, TSLA). Handy for quick experiments, but note that this selection has a strong survivor bias.

feed = rq.feeds.YahooFeed.us_stocks_10(start_date="2020-01-01")

CSVFeed

CSVFeed parses one or more CSV files with historic market data. By default it expects the Yahoo Finance column layout, but this can be customized via the columns parameter. The symbol is derived from the filename.

feed = rq.feeds.CSVFeed("path/to/csv/dir")

There are also ready-made class methods for specific formats, such as stooq_us_daily(), stooq_us_intraday(), and yahoo(). An optional asset_filter allows you to load only a subset of the assets in the files.

ParquetFeed

ParquetFeed reads historic data from a single Parquet file. Parquet provides a good balance between speed, memory usage, and disk usage, which makes it a great option to store large volumes of historic market data for back testing. It supports a mix of Bar, Trade, and Quote price items.

Use the record() method to copy data from any other feed into a ParquetFeed:

from roboquant.feeds.parquetfeed import ParquetFeed

feed = rq.feeds.YahooFeed("MSFT", "AAPL", start_date="2020-01-01")
target = ParquetFeed("data.parquet")
target.record(feed)

A demo file with 10 years of data for 10 popular US stocks is available through us_stocks_10(). This is included for demo purposes and should not be relied upon for serious back testing.

SQLFeed

SQLFeed supports recording price items from another feed and then playing them back during a run. Under the hood, the data is stored in an SQLite database. The schema is created automatically when the first item is recorded, and it differs for Bar and Quote items, so you can only store one type of price item in a single database.

feed = rq.feeds.SQLFeed("my_data.db", price_type="bar")

Use the record() method to copy data from another feed into the database. For large databases, you can call create_index() after all data has been recorded to speed up queries for specific timeframes (e.g. in walk-forward back tests).

RandomWalk

RandomWalk is a synthetic feed that simulates a random walk of prices. It can generate Bar, Trade, or Quote price items and is very useful for testing and for building examples without needing an internet connection.

feed = rq.feeds.RandomWalk(n_symbols=5, n_prices=1_000, price_type="trade")
assets = feed.assets()
feed.plot(assets[0], plot_volume=False);
<Figure size 2400x1350 with 1 Axes>

Feed Transformations

Feeds can be wrapped by other feeds to transform the data they produce. This is a powerful way to adapt a data source to the needs of a strategy.

BarAggregatorFeed

BarAggregatorFeed aggregates the Trade or Quote items of another feed into Bar items of a given frequency. When trades are selected, the actual trade prices and volumes are used. When quotes are selected, the midpoint prices are used and volumes are not available.

trades = rq.feeds.RandomWalk(n_symbols=2, n_prices=10_000, price_type="trade")
bars = rq.feeds.BarAggregatorFeed(trades, frequency="15m", price_type="trade")

TimeGroupingFeed

TimeGroupingFeed groups events that occur closely after each other into a single event. It uses the timestamps of the events to determine if they are close, based on a configurable timeout. This can be useful to reduce the number of events when working with a chatty data source.

trades = rq.feeds.RandomWalk(n_symbols=2, n_prices=10_000, price_type="trade")
feed = rq.feeds.TimeGroupingFeed(trades, timeout=5.0)

Live Feeds

For forward testing, paper trading, and live trading you need a feed that produces real-time data instead of replaying historic data. The abstract LiveFeed base class implements this and provides two guarantees for the events it publishes:

Live feeds are typically paired with a live broker. Concrete implementations for specific brokers (e.g. Alpaca) can be found in the roboquant.third_party module.