Custom Universes
CSV Format Example
Define Custom Types
To define a custom data type, inherit the PythonData
class and override the GetSource and Reader methods.
class StockDataSource(PythonData): def get_source(self, config: SubscriptionDataConfig, date: datetime, is_live: bool) -> SubscriptionDataSource: if not is_live: return SubscriptionDataSource("<custom_universe_key>", SubscriptionTransportMedium.OBJECT_STORE, FileFormat.CSV) return SubscriptionDataSource("https://raw.githubusercontent.com/QuantConnect/Documentation/master/Resources/datasets/custom-data/csv-universe-example.csv", SubscriptionTransportMedium.REMOTE_FILE, FileFormat.CSV) def reader(self, config: SubscriptionDataConfig, line: str, date: datetime, is_live: bool) -> BaseData: if not (line.strip() and line[0].isdigit()): return None stocks = StockDataSource() stocks.symbol = config.symbol try: csv = line.split(',') stocks.time = datetime.strptime(csv[0], "%Y%m%d") stocks.end_time = stocks.time + timedelta(days=1) stocks["Symbols"] = csv[1:] except ValueError: # Do nothing return None return stocks
Receive Custom Data
As your data reader reads your custom data file, LEAN adds the data points into a List[StockDataSource])
object it passes to your algorithm's filter function. Your filter function needs to return a list of Symbol
or str
object. LEAN automatically subscribes to these new assets and adds them to your algorithm.
class MyAlgorithm(QCAlgorithm): def _filter_function(self, data: List[StockDataSource]) -> List[str]: symbols = [] for item in data: for symbol in item["Symbols"]: symbols.append(symbol) return symbols
If you add custom properties to your data object in the reader
method, LEAN adds them as members to the data object in your filter method. 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:
-
and.
characters are replaced with whitespace.- The first letter is capitalized.
- 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 your filter method through the Somepropertyname
member of your data object.