---
title: "Object Store"
description: "The Object Store is an organization-specific file system that you can use in your algorithms to save, read, and delete data."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/object-store
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/object-store.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/29%20Object%20Store
modified: 2026-10-29
index: https://www.quantconnect.com/llms.txt
---

# Object Store

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Object Store

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## 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.

```python
for kvp in self.object_store:
    key = kvp.key
    value = kvp.value
```

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

```python
for key in self.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`.
   ```python
   string_sample = "My string"
   ```
2. Create a `Bytes` object.
   ```python
   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. To avoid slowing down your backtests, save data once in the `on_end_of_algorithm` event handler. In live trading, you can save data more frequently like at the end of a `train` method or after universe selection.

If you run algorithms in QuantConnect Cloud, you need [storage create permissions](https://www.quantconnect.com/docs/v2/cloud-platform/organizations/members.md#09-Permissions) to save data in the Object Store.

If you don't have data to store, [create some sample data](https://www.quantconnect.com/docs/v2/writing-algorithms/object-store.md#03-Create-Sample-Data).

You can save `Bytes` and `string` objects in the Object Store. To store data, you need to provide a key. If you provide a key that is already in the Object Store, it will overwrite the data at that location. To avoid overwriting objects from other projects in your organization, prefix the key with your project ID. You can find the project ID in the URL of your browser when you open a project. For example, the ID of the project at `quantconnect.com/project/12345` is 12345.

### Strings

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

```python
save_successful = self.object_store.save(f"{self.project_id}/string_key", string_sample)
```

### Bytes

To save a `Bytes` object, call the `save_bytes` method.

```python
save_successful = self.object_store.save_bytes(f"{self.project_id}/bytes_key", bytes_sample)
```

## Read Data

Read data from the Object Store to import algorithm variables between deployments, import data from the Research Environment, or load trained machine learning models. 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.

```python
if self.object_store.contains_key(key):
    # Read data
```

### Strings

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

```python
string_data = self.object_store.read(f"{self.project_id}/string_key")
```

### Bytes

To read a `Bytes` object, call the `read_bytes` method.

```python
byte_data = self.object_store.read_bytes(f"{self.project_id}/bytes_key")
```

## Delete Data

Delete objects in the Object Store to remove objects that you no longer need. If you run algorithms in QuantConnect Cloud, you need [storage delete permissions](https://www.quantconnect.com/docs/v2/cloud-platform/organizations/members.md#09-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.

```python
if self.object_store.contains_key(key):
    self.object_store.delete(key)
```

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

```python
for kvp in self.object_store:
    self.object_store.delete(kvp.key)
```

## Cache Data

When you write to or read from the Object Store, the algorithm caches the data. The cache speeds up the algorithm 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.
   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.

```python
self.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.

```python
file_path = self.object_store.get_file_path(key)
```

## Storage Quotas

If you run algorithms locally, you can store as much data as your hardware will allow. If you run algorithms in QuantConnect Cloud, you need a [paid organization](https://www.quantconnect.com/docs/v2/cloud-platform/object-store.md#05-Storage-Sizes) to access the Object Store and you must stay within your storage quota. To find your storage quota programmatically, use the `max_size` attribute for storage size and `max_files` attribute for the maximum number of files.

```python
max_size = self.object_store.max_size
max_files = self.object_store.max_files
```

If you need more storage space, [edit your storage plan](https://www.quantconnect.com/docs/v2/cloud-platform/object-store.md#07-Edit-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.
   ```python
   spy = self.add_equity("SPY").symbol
   df = self.history(self.securities.keys, 360, Resolution.DAILY)
   ```
2. Get the file path for a specific key in the Object Store.
   ```python
   file_path = self.object_store.get_file_path("df_to_csv")
   ```
3. Call the [to_csv](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html) method to save the DataFrame in the Object Store as a CSV file.
   ```python
   df.to_csv(file_path)   # File size: 32721 bytes
   ```
4. Call the [read_csv](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html) method to load the CSV file from the Object Store.
   ```python
   reread = pd.read_csv(file_path)
   ```

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

- [XML](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_xml.html)
  ```python
  file_path = self.object_store.get_file_path("df_to_xml")
  df.to_xml(file_path)   # File size: 87816 bytes
  reread = pd.read_xml(file_path)
  ```
- [JSON](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_json.html)
  ```python
  file_path = self.object_store.get_file_path("df_to_json")
  df.to_json(file_path)   # File size: 125250 bytes
  reread = pd.read_json(file_path)
  ```
- [Parquet](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_parquet.html)
  ```python
  file_path = self.object_store.get_file_path("df_to_parquet")
  df.to_parquet(file_path)   # File size: 23996 bytes
  reread = pd.read_parquet(file_path)
  ```
- [Pickle](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_pickle.html)
  ```python
  file_path = self.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](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/supported-indicators/simple-moving-average.md) indicator that's generated during a backtest.

1. Create a algorithm, add a data subscription, and add a simple moving average indicator.
   ```python
   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.
2. Save the indicator data as `string` in `self._content`.
   ```python
   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'
   ```
3. In the [OnEndOfAlgorithm](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/event-handlers.md#15-End-Of-Algorithm-Events) method, save the indicator data to the Object Store.
   ```python
   def on_end_of_algorithm(self):
       self.object_store.save('sma_values_python', self._content)
   ```
4. [Open the Research Environment](https://www.quantconnect.com/docs/v2/research-environment/key-concepts/getting-started.md#03-Open-Notebooks) and create a `QuantBook`.
   ```python
   qb = QuantBook()
   ```
5. Read the indicator data from the Object Store.
   ```python
   content = qb.object_store.read("sma_values_python")
   ```
   The key you provide must be the same key you used to save the object.
6. Convert the data to a pandas object and create a chart.
   ```python
   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()
   ```

```python
class ObjectStoreChartingAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)
        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)
```

## Example for Logging

You can use the Object Store to log order data from your backtests and live algorithms, then analyze it in the Research Environment. The following example demonstrates how to log orders from an [Exponential Moving Average](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/supported-indicators/exponential-moving-average.md) (EMA) cross strategy to a text file in the Object Store.

1. Create an algorithm, add a daily equity subscription, and create two EMA indicators.
   ```python
   class ObjectStoreLoggingAlgorithm(QCAlgorithm):
       def initialize(self):
           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)
           # Add a header row.
           self._content = 'Time,Symbol,Price,Quantity,Tag\n'
   ```
   The algorithm saves `self._content` to the Object Store at the end of the backtest.
2. In the `on_data` method, place market orders when the EMAs cross.
   ```python
   def on_data(self, data: Slice):
       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}')
   ```
3. In the `on_order_event` method, log each fill to the content string.
   ```python
   def on_order_event(self, order_event: OrderEvent):
       if order_event.status != OrderStatus.FILLED:
           return

       self._content += (
           f'{order_event.utc_time.strftime("%Y-%m-%d")},'
           f'{order_event.symbol},'
           f'{order_event.fill_price},'
           f'{order_event.fill_quantity},'
           f'{order_event.ticket.tag}\n'
       )
   ```
4. In the [OnEndOfAlgorithm](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/event-handlers.md#15-End-Of-Algorithm-Events) method, save the content to the Object Store.
   ```python
   def on_end_of_algorithm(self):
       key = f'{self.project_id}-{self.algorithm_id}.txt'
       self.object_store.save(key, self._content)
       self.log(f'Saved order log to Object Store: {key}')
   ```
5. [Open the Research Environment](https://www.quantconnect.com/docs/v2/research-environment/key-concepts/getting-started.md#03-Open-Notebooks) and create a `QuantBook`.
   ```python
   qb = QuantBook()
   ```
6. Read the data from the Object Store.
   ```python
   # Replace the key with the one from your backtest log.
   content = qb.object_store.read("<project-id>-<algorithm-id>.txt")
   ```
   The key you provide must be the same key you used to save the object. Check the backtest log for the exact key.
7. Split the content into lines.
   ```python
   lines = content.strip().split('\n')
   # Display the header.
   print(lines[0])
   ```
8. Display the first few rows (head) and last few rows (tail).
   ```python
   # Show the first 5 data rows.
   for line in lines[1:6]:
       print(line)

   # Show the last 5 data rows.
   for line in lines[-5:]:
       print(line)
   ```
9. Search for all rows tagged as "BUY".
   ```python
   # Filter lines that contain "BUY".
   buy_orders = [line for line in lines[1:] if 'BUY' in line]
   for line in buy_orders:
       print(line)
   ```

```python
class ObjectStoreLoggingAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 1, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)

        self._symbol = self.add_equity("SPY", Resolution.DAILY).symbol
        # Create short and long EMA indicators.
        self._ema_short = self.ema(self._symbol, 10)
        self._ema_long = self.ema(self._symbol, 30)
        # Add a header row.
        self._content = 'Time,Symbol,Price,Quantity,Tag\n'

    def on_data(self, data: Slice) -> None:
        if not self._ema_short.is_ready or not self._ema_long.is_ready:
            return

        # Place a market order when the EMAs cross.
        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}')

    def on_order_event(self, order_event: OrderEvent) -> None:
        if order_event.status != OrderStatus.FILLED:
            return

        # Log each fill as a row.
        self._content += (
            f'{order_event.utc_time.strftime("%Y-%m-%d")},'
            f'{order_event.symbol},'
            f'{order_event.fill_price},'
            f'{order_event.fill_quantity},'
            f'{order_event.ticket.tag}\n'
        )

    def on_end_of_algorithm(self) -> None:
        # Save the order log to the Object Store.
        key = f'{self.project_id}-{self.algorithm_id}.txt'
        self.object_store.save(key, self._content)
        self.log(f'Saved order log to Object Store: {key}')
```

## Example of Custom Data

Follow these steps to use the Object Store as a data source for [custom data](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/key-concepts.md):

1. Create a custom data class that defines a storage key and implements the [`get_source`](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/key-concepts.md#04-Set-Data-Sources) method.
   ```python
   class Bitstamp(PythonData):
       KEY = 'bitstampusd.csv'
       def get_source(self, config, date, isLiveMode):
           return SubscriptionDataSource(Bitstamp.KEY, SubscriptionTransportMedium.OBJECT_STORE)
   ```
2. Create an algorithm that [downloads data from an external source](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/bulk-downloads.md) and [saves it to the Object Store](https://www.quantconnect.com/docs/v2/writing-algorithms/object-store.md#04-Save-Data).
   ```python
   class ObjectStoreCustomDataAlgorithm(QCAlgorithm):
       def initialize(self):
           if not self.object_store.contains_key(Bitstamp.KEY):
               url = "https://raw.githubusercontent.com/QuantConnect/Documentation/master/Resources/datasets/custom-data/bitstampusd.csv"
               content = self.download(url)
               self.object_store.save(Bitstamp.KEY, content)
   ```
3. Call the `add_data` method to [subscribe to the custom type](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/custom-securities/key-concepts.md#05-Create-Subscriptions).
   ```python
   class ObjectStoreCustomDataAlgorithm(QCAlgorithm):
       def initialize(self):
           self.custom_data_symbol = self.add_data(Bitstamp, "BTC").symbol
   ```
4. Implement the `Reader reader` method for the custom data class.
   ```python
   class Bitstamp(PythonData):
       def reader(self, config, line, date, isLiveMode):
           # Example Line Format:
           # Date      Open   High    Low     Close   Volume (BTC)    Volume (Currency)   Weighted Price
           # 2011-09-13 5.8    6.0     5.65    5.97    58.37138238,    346.0973893944      5.929230648356
           if not line[0].isdigit():
               return None

           coin = Bitstamp()
           coin.symbol = config.symbol
           data = line.split(',')

           # If value is zero, return None
           coin.value = float(data[4])
           if coin.value == 0:
               return None

           coin.time = datetime.strptime(data[0], "%Y-%m-%d")
           coin.end_time = coin.time + timedelta(1)
           coin["Open"] = float(data[1])
           coin["High"] = float(data[2])
           coin["Low"] = float(data[3])
           coin["Close"] = coin.value
           coin["VolumeBTC"] = float(data[5])
           coin["VolumeUSD"] = float(data[6])
           coin["WeightedPrice"] = float(data[7])
           return coin
   ```
5. To confirm your algorithm is receiving the custom data, [request some historical data](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/history-requests.md), then [log](https://www.quantconnect.com/docs/v2/writing-algorithms/logging.md) and [plot](https://www.quantconnect.com/docs/v2/writing-algorithms/charting.md) the data from the `Slice` object.
   ```python
   class ObjectStoreCustomDataAlgorithm(QCAlgorithm):
       def initialize(self):
           history = self.history(Bitstamp, self.custom_data_symbol, 200, Resolution.DAILY)
           self.debug(f"We got {len(history)} items from historical data request of {self.custom_data_symbol}.")
       def on_data(self, slice):
           data = slice.get(Bitstamp).get( self.custom_data_symbol)
           if not data:
               return

           self.log(f'{data.end_time}: Close: {data.close}')
           self.plot(self.custom_data_symbol, 'Price', data.close)
   ```

The following algorithm provides a full example of a sourcing custom data from the Object Store:

```python
class ObjectStoreCustomDataAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2012, 9, 13)
        self.set_end_date(2021, 6, 20)
        self.set_cash(100000)

        # Load the custom data from ObjectStore.
        if not self.object_store.contains_key(Bitstamp.KEY):
            url = "https://raw.githubusercontent.com/QuantConnect/Documentation/master/Resources/datasets/custom-data/bitstampusd.csv"
            content = self.download(url)
            self.object_store.save(Bitstamp.KEY, content)

        # Request custom data for plotting.
        # Define the symbol and "type" of our generic data.
        self.custom_data_symbol = self.add_data(Bitstamp, "BTC").symbol

        # Example historical call.
        history = self.history(Bitstamp, self.custom_data_symbol, 200, Resolution.DAILY)
        self.debug(f"We got {len(history)} items from historical data request of {self.custom_data_symbol}.")

    def on_data(self, slice: Slice) -> None:
        # Plot on updated data.
        data = slice.get(Bitstamp).get(self.custom_data_symbol)
        if not data:
            return

        self.log(f'{data.end_time}: Close: {data.close}')
        self.plot(self.custom_data_symbol, 'Price', data.close)

class Bitstamp(PythonData):
    KEY = 'bitstampusd.csv'
    def get_source(self, config, date, isLiveMode):
        # Load data from object store.
        return SubscriptionDataSource(Bitstamp.KEY, SubscriptionTransportMedium.OBJECT_STORE)

    def reader(self, config, line, date, isLiveMode):
        # Example Line Format:
        # Date      Open   High    Low     Close   Volume (BTC)    Volume (Currency)   Weighted Price
        # 2011-09-13 5.8    6.0     5.65    5.97    58.37138238,    346.0973893944      5.929230648356
        if not line[0].isdigit():
            return None

        coin = Bitstamp()
        coin.symbol = config.symbol
        data = line.split(',')

        # If value is zero, return None
        coin.value = float(data[4])
        if coin.value == 0:
            return None

        coin.time = datetime.strptime(data[0], "%Y-%m-%d")
        coin.end_time = coin.time + timedelta(1)
        coin["Open"] = float(data[1])
        coin["High"] = float(data[2])
        coin["Low"] = float(data[3])
        coin["Close"] = coin.value
        coin["VolumeBTC"] = float(data[5])
        coin["VolumeUSD"] = float(data[6])
        coin["WeightedPrice"] = float(data[7])
        return coin
```

## Preserve Insights Between Deployments

Follow these steps to use the Object Store to preserve the algorithm state across live deployments:

1. Create an algorithm that defines a storage key and adds insights to the [Insight Manager](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/insight-manager.md).
   ```python
   class ObjectStoreChartingAlgorithm(QCAlgorithm):
       def initialize(self):
           self.insight_key = f"{self.project_id}/insights"
           self.set_universe_selection(ManualUniverseSelectionModel([ Symbol.create("SPY", SecurityType.EQUITY, Market.USA) ]))
           self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(5), 0.025, None))
   ```
2. At the top of the algorithm file, add the following imports:
   ```python
   from Newtonsoft.Json import JsonConvert
   from System.Collections.Generic import List
   ```
   `Insight` objects are C# objects, so you need the preceding C# libraries to serialize and deserialize them.
3. In the [on_end_of_algorithm](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/event-handlers.md#15-End-Of-Algorithm-Events) event handler of the algorithm, [get the Insight objects](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/insight-manager.md#04-Get-Insights) and save them in the Object Store as a JSON object.
   ```python
   def on_end_of_algorithm(self):
       insights = self.insights.get_insights(lambda x: x.is_active(self.utc_time))
       content = ','.join([JsonConvert.SerializeObject(x) for x in insights])
       self.object_store.save(self.insight_key, f'[{content}]')
   ```
4. At the bottom of the `initialize` method, read the Insight objects from the Object Store and [add them to the Insight Manager](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/insight-manager.md#11-Add-Insights-to-Self-Managed-Insight-Collections).
   ```python
   if self.object_store.contains_key(self.insight_key):
       insights = JsonConvert.DeserializeObject[List[Insight]](
           self.object_store.read(self.insights_key)
       )
       self.insights.add_range(insights)
   ```

The following algorithm provides a full example of preserving the Insight state between deployments:

```python
from Newtonsoft.Json import JsonConvert
from System.Collections.Generic import List

class ObjectStoreInsightsAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.universe_settings.resolution = Resolution.DAILY

        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)

        self.insights_key = f"{self.project_id}/insights"

        # Read the file with the insights
        if self.object_store.contains_key(self.insights_key):
            # Load cached JSON key value pair from object store, then add to algorithm insights.
            insights = JsonConvert.DeserializeObject[List[Insight]](
                self.object_store.read(self.insights_key)
            )
            self.log(f"Read {len(insights)} insight(s) from the Object Store")
            self.insights.add_range(insights)

            # Delete the key to reuse it
            self.object_store.delete(self.insights_key)

        self.set_universe_selection(ManualUniverseSelectionModel([ Symbol.create("SPY", SecurityType.EQUITY, Market.USA) ]))
        self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(5), 0.025, None))
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(Resolution.DAILY))

    def on_end_of_algorithm(self) -> None:
        # Get all active insights.
        insights = self.insights.get_insights(lambda x: x.is_active(self.utc_time))
        # If we want to save all insights (expired and active), we can use
        # insights = self.insights.get_insights(lambda x: True)
        self.log(f"Save {len(insights)} insight(s) to the Object Store.")
        content = ','.join([JsonConvert.SerializeObject(x) for x in insights])
        self.object_store.save(self.insights_key, f'[{content}]')
```

## Live Trading Considerations

If you update the Object Store from outside of your live trading node and then try to read the new content from inside your live trading algorithm, you may not get the new content because [the Object Store caches data](https://www.quantconnect.com/docs/v2/writing-algorithms/object-store.md#07-Cache-Data) to speed up execution. To ensure you get the latest value for a specific key in the Object Store, clear the cache and then [read the data](https://www.quantconnect.com/docs/v2/writing-algorithms/object-store.md#05-Read-Data).

```python
self.object_store.clear()
if self.object_store.contains_key(key):
    value = self.object_store.read(key)
```

## Special Folders

Your organization's Object Store includes a reserved `.assistant` folder that the [QuantConnect AI agents](https://www.quantconnect.com/docs/v2/ai-assistance/agents.md) read. It holds the custom [skills](https://www.quantconnect.com/docs/v2/ai-assistance/agents.md#14-Custom-Skills), [memories](https://www.quantconnect.com/docs/v2/ai-assistance/agents.md#15-Custom-Memories), and [templates](https://www.quantconnect.com/docs/v2/ai-assistance/agents.md#16-Custom-Templates) that let the agents apply your own expertise, remember each project's context, and start new projects from your own scaffolds.

The `.assistant` folder contains the following subfolders:

| Subfolder | Purpose |
| --- | --- |
| `skills` | Reusable instructions and conventions the agents apply. |
| `memories` | Facts the agents remember about each project, in one `<project_id> / memory.md` file per project. |
| `templates` | Your own project scaffolds for the agents to initialize for new projects. |

These files are shared across your organization. For information on uploading files to the Object Store, see the documentation for the [Algorithm Lab](https://www.quantconnect.com/docs/v2/cloud-platform/object-store.md#03-Upload-Files), [CLI](https://www.quantconnect.com/docs/v2/lean-cli/object-store.md#03-Cloud-Storage), or [API](https://www.quantconnect.com/docs/v2/cloud-platform/api-reference/object-store-management/upload-object-store-files.md).
