---
title: "CSV Format Example"
description: "This page explains how to import custom data of a single security sourced in CSV format."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/custom-securities/csv-format-example
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/custom-securities/csv-format-example.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/16%20Importing%20Data/02%20Streaming%20Data/02%20Custom%20Securities/02%20CSV%20Format%20Example
modified: 2026-10-28
index: https://www.quantconnect.com/llms.txt
---

# CSV Format Example

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Importing Data > Streaming Data > Custom Securities > CSV Format Example

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

## Introduction

This page explains how to import custom data of a single security sourced in `CSV` format.

## Data Format

The following snippet shows an example `CSV` file:

```
Date,Open,High,Low,Close,SharesTraded,Tur11er(Rs.Cr)
1997-01-01,905.2,941.4,905.2,939.55,38948210,978.21
1997-01-02,941.95,944,925.05,927.05,49118380,1150.42
1997-01-03,924.3,932.6,919.55,931.65,35263845,866.74
...
2014-07-24,7796.25,7835.65,7771.65,7830.6,117608370,6271.45
2014-07-25,7828.2,7840.95,7748.6,7790.45,153936037,7827.61
2014-07-28,7792.9,7799.9,7722.65,7748.7,116534670,6107.78
```

The data in the file must be in chronological order.

## Define Custom Types

To define a custom data type, inherit the `PythonData` class and override the [GetSource](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/key-concepts.md#04-Set-Data-Sources) and [Reader](https://www.quantconnect.com/docs/v2/writing-algorithms/importing-data/streaming-data/key-concepts.md#05-Parse-Custom-Data) methods.

```python
class MyCustomDataType(PythonData):

    def get_source(self,
         config: SubscriptionDataConfig,
         date: datetime,
         is_live: bool) -> SubscriptionDataSource:

        if not is_live:
            return SubscriptionDataSource("<custom_data_key>", SubscriptionTransportMedium.OBJECT_STORE, FileFormat.CSV)
        return SubscriptionDataSource("https://raw.githubusercontent.com/QuantConnect/Documentation/master/Resources/datasets/custom-data/csv-data-example.csv", SubscriptionTransportMedium.REMOTE_FILE)

    def reader(self,
         config: SubscriptionDataConfig,
         line: str,
         date: datetime,
         is_live: bool) -> BaseData:

        if not (line.strip()):
            return None

        index = MyCustomDataType()
        index.symbol = config.symbol

        try:
            data = line.split(',')
            index.time = datetime.strptime(data[0], "%Y-%m-%d")
            index.end_time = index.time + timedelta(days=1)
            index.value = data[4]
            index["open"] = float(data[1])
            index["high"] = float(data[2])
            index["low"] = float(data[3])
            index["close"] = float(data[4])

        except ValueError:
            # Do nothing
            return None

        return index
```

## Create Subscriptions

To create a subscription for the custom type, in the `initialize` method, call the `add_data` method. The `add_data` method returns a `Security` object, which contains a `Symbol`. Save a reference to the `symbol` so you can use it in `on_data` to access the security data in the `Slice`.

```python
class MyAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self._symbol = self.add_data(MyCustomDataType, "MyCustomDataType", Resolution.DAILY).symbol
```

The `add_data` method creates a subscription for a single custom data asset and adds it to your **user-defined** universe.

## Receive Custom Data

As your data reader reads your custom data file, LEAN adds the data points in the `Slice` it passes to your algorithm's `on_data` method. To collect the custom data, use the `symbol` or name of your custom data subscription. You can access the `value` and custom properties of your custom data class from the `Slice`. To access the custom properties, pass the property name to the `get_property` method.

```python
class MyAlgorithm(QCAlgorithm):
    def on_data(self, slice: Slice) -> None:
        if slice.contains_key(self._symbol):
            custom_data = slice[self._symbol]
            close = custom_data.close
```

If you add custom properties to your data object in the `reader` method, LEAN adds them as members to the data object in the `Slice`. To ensure the property names you add in the `reader` method follow the convention of member names, LEAN applies the following changes to the property names you provide in the `reader` method:

1. `-` and `.` characters are replaced with whitespace.
2. The first letter is capitalized.
3. Whitespace characters are removed.

For example, if you set a property name in the `reader` method to `['some-property.name']`, you can access it in the `on_data` method through the `Somepropertyname` member of your data object.

## Demonstration Algorithms

- [BubbleAlgorithm.py](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/BubbleAlgorithm.py) (Python)
- [CustomDataNIFTYAlgorithm.py](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/CustomDataNIFTYAlgorithm.py) (Python)
- [DescendingCustomDataObjectStoreRegressionAlgorithm.py](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/DescendingCustomDataObjectStoreRegressionAlgorithm.py) (Python)
