book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

Research Environment

Object Store

Introduction

The Object Store is a file system that you can use in your algorithms to save, read, and delete data. The Object Store is organization-specific, so you can save or read data from the same Object Store in all of your organization's projects. The Object Store works like a key-value storage system where you can store regular strings, JSON encoded strings, XML encoded strings, and bytes. You can access the data you store in the Object Store from backtests, the Research Environment, and live algorithms.

Get All Stored Data

To get all of the keys and values in the Object Store, iterate through the object_store property.

Select Language:
for kvp in qb.object_store:
    key = kvp.key
    value = kvp.value

To iterate through just the keys in the Object Store, iterate through the keys property.

Select Language:
for key in qb.object_store.keys:
    continue

Create Sample Data

You need some data to store data in the Object Store.

Follow these steps to create some sample data:

  1. Create a string.
  2. Select Language:
    string_sample = "My string"
  3. Create a Bytes object.
  4. Select Language:
    bytes_sample = str.encode("My String")

Save Data

The Object Store saves objects under a key-value system. If you save objects in backtests, you can access them from the Research Environment.

If you run algorithms in QuantConnect Cloud, you need storage create permissions to save data in the Object Store.

If you don't have data to store, create some sample data.

You can save Bytes and string objects in the Object Store.

Strings

To save a string object, call the save or save_string method.

Select Language:
save_successful = qb.object_store.save(f"{qb.project_id}/string_key", string_sample)

Bytes

To save a Bytes object (for example, zipped data), call the save_bytes method.

Select Language:
save_successful = qb.object_store.save_bytes(f"{qb.project_id}/bytes_key", bytes_sample)

zipped_data_sample = Compression.zip_bytes(bytes(string_sample, "utf-8"), "data")
zip_save_successful = qb.object_store.save_bytes(f"{qb.project_id}/bytesKey.zip", zipped_data_sample)

Read Data

To read data from the Object Store, you need to provide the key you used to store the object.

You can load Bytes and string objects from the Object Store.

Before you read data from the Object Store, check if the key exists.

Select Language:
if qb.object_store.contains_key(key):
    # Read data

Strings

To read a string object, call the read or read_string method.

Select Language:
string_data = qb.object_store.read(f"{qb.project_id}/string_key")

Bytes

To read a Bytes object, call the read_bytes method.

Select Language:
byte_data = qb.object_store.read_bytes(f"{qb.project_id}/bytes_key")

Delete Data

Delete objects in the Object Store to remove objects that you no longer need. If you use the Research Environment in QuantConnect Cloud, you need storage delete permissions to delete data from the Object Store.

To delete objects from the Object Store, call the delete method. Before you delete data, check if the key exists. If you try to delete an object with a key that doesn't exist in the Object Store, the method raises an exception.

Select Language:
if qb.object_store.contains_key(key):
    qb.object_store.delete(key)

To delete all of the content in the Object Store, iterate through all the stored data.

Select Language:
for kvp in qb.object_store:
    qb.object_store.delete(kvp.key)

Cache Data

When you write to or read from the Object Store, the notebook caches the data. The cache speeds up the notebook execution because if you try to read the Object Store data again with the same key, it returns the cached data instead of downloading the data again. The cache speeds up execution, but it can cause problems if you are trying to share data between two nodes under the same Object Store key. For example, consider the following scenario:

  1. You open project A and save data under the key 123.
  2. You open project B and save new data under the same key 123.
  3. In project A, you read the Object Store data under the key 123, expecting the data from project B, but you get the original data you saved in step #1 instead.
  4. You get the data from step 1 instead of step 2 because the cache contains the data from step 1.

To clear the cache, call the Clear method.

Select Language:
qb.object_store.clear()

Get File Path

To get the file path for a specific key in the Object Store, call the get_file_path method. If the key you pass to the method doesn't already exist in the Object Store, it's added to the Object Store.

Select Language:
file_path = qb.object_store.get_file_path(key)

Storage Quotas

If you use the Research Environment locally, you can store as much data as your hardware will allow. If you use the Research Environment in QuantConnect Cloud, you must stay within your storage quota. If you need more storage space, edit your storage plan.

Example for DataFrames

Follow these steps to create a DataFrame, save it into the Object Store, and load it from the Object Store:

  1. Get some historical data.
  2. Select Language:
    spy = qb.add_equity("SPY").symbol
    df = qb.history(qb.securities.keys, 360, Resolution.DAILY)
  3. Get the file path for a specific key in the Object Store.
  4. Select Language:
    file_path = qb.object_store.get_file_path("df_to_csv")
  5. Call the to_csv method to save the DataFrame in the Object Store as a CSV file.
  6. Select Language:
    df.to_csv(file_path)   # File size: 32721 bytes
  7. Call the read_csv method to load the CSV file from the Object Store.
  8. Select Language:
    reread = pd.read_csv(file_path)

pandas supports saving and loading DataFrame objects in the following additional formats:

  • XML
  • file_path = qb.object_store.get_file_path("df_to_xml")
    df.to_xml(file_path)   # File size: 87816 bytes
    reread = pd.read_xml(file_path)
  • JSON
  • file_path = qb.object_store.get_file_path("df_to_json")
    df.to_json(file_path)   # File size: 125250 bytes
    reread = pd.read_json(file_path)
  • Parquet
  • file_path = qb.object_store.get_file_path("df_to_parquet")
    df.to_parquet(file_path)   # File size: 23996 bytes
    reread = pd.read_parquet(file_path)
  • Pickle
  • file_path = qb.object_store.get_file_path("df_to_pickle")
    df.to_pickle(file_path)   # File size: 19868 bytes
    reread = pd.read_pickle(file_path)

Example for Plotting

You can use the Object Store to plot data from your backtests and live algorithm in the Research Environment. The following example demonstrates how to plot a Simple Moving Average indicator that's generated during a backtest.

  1. Create a algorithm, add a data subscription, and add a simple moving average indicator.
  2. Select Language:
    class ObjectStoreChartingAlgorithm(QCAlgorithm):
        def initialize(self):
            self.add_equity("SPY")
        
            self.content = ''
            self._sma = self.sma("SPY", 22)

    The algorithm will save self.content to the Object Store.

  3. Save the indicator data as string in self.content.
  4. Select Language:
    def on_data(self, data: Slice):
        self.plot('SMA', 'Value', self.sma.current.value)
        self.content += f'{self.sma.current.end_time},{self.sma.current.value}\n'
  5. In the OnEndOfAlgorithm method, save the indicator data to the Object Store.
  6. Select Language:
    def on_end_of_algorithm(self):
        self.object_store.save('sma_values_python', self.content)
  7. Open the Research Environment and create a QuantBook.
  8. Select Language:
    qb = QuantBook()
  9. Read the indicator data from the Object Store.
  10. Select Language:
    content = qb.object_store.read("sma_values_python")

    The key you provide must be the same key you used to save the object.

  11. Convert the data to a pandas object and create a chart.
  12. data = {}
    for line in content.split('\n'):
        csv = line.split(',')
        if len(csv) > 1:
            data[csv[0]] = float(csv[1])
    
    series = pd.Series(data, index=data.keys())
    series.plot()
Select Language:
class ObjectStoreChartingAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2023, 1, 1)  # Set Start Date
        self.set_cash(100000)           # Set Strategy Cash
        self.add_equity("SPY", Resolution.MINUTE)
        
        self.content = ''
        # Create SMA indicator for referencing.
        self.sma = self.SMA("SPY", 22)
        
    def on_data(self, data: Slice) -> None:
        # Cache the indicator data point to save it.
        self.content += f'{self.sma.current.end_time},{self.sma.current.value}\n'

    def on_end_of_algorithm(self) -> None:
        # Save the indicator values to object store for logging.
        self.object_store.save('sma_values_python', self.content)

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: