Requesting and Validating History for Custom Market Data
Summary
This example demonstrates how to request historical bars for a custom data type in an algorithmic trading engine. It registers an hourly custom-data subscription, requests 48 hours of history, and checks that results include expected OHLC fields and a custom property. It repeats the request using a list of symbols and verifies that the multi-symbol form returns the same number of records.
The custom reader parses comma-separated rows, assigns timestamps and price values, and attaches a string property to each data point. The example raises assertions when history is empty, requests disagree, or required fields are missing. It is an API usage and data-validation example rather than a trading strategy: it provides no market analysis, performance evidence, or guidance on signal design, and depends on the external data source and its format.
Key ideas
- A custom data reader can parse external rows into timestamped price records.
- The history interface supports requests for one symbol or a list of symbols.
- Assertions can verify that historical data contains required price fields and custom properties.
- This example tests data retrieval behavior rather than a trade strategy.
Tags
Full text
# CustomDataTypeHistoryAlgorithm
# CustomDataTypeHistoryAlgorithm
## Source (Apache-2.0)
```python
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
### <summary>
### </summary>
class CustomDataTypeHistoryAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2017, 8, 20)
self.set_end_date(2017, 8, 20)
self._symbol = self.add_data(CustomDataType, "CustomDataType", Resolution.HOUR).symbol
history = list(self.history[CustomDataType](self._symbol, 48, Resolution.HOUR))
if len(history) == 0:
raise AssertionError("History request returned no data")
self._assert_history_data(history)
history2 = list(self.history[CustomDataType]([self._symbol], 48, Resolution.HOUR))
if len(history2) != len(history):
raise AssertionError("History requests returned different data")
self._assert_history_data([y.values()[0] for y in history2])
def _assert_history_data(self, history: List[PythonData]) -> None:
expected_keys = ['open', 'close', 'high', 'low', 'some_property']
if any(any(not x[key] for key in expected_keys)
or x["some_property"] != "some property value"
for x in history):
raise AssertionError("History request returned data without the expected properties")
class CustomDataType(PythonData):
def get_source(self, config: SubscriptionDataConfig, date: datetime, is_live: bool) -> SubscriptionDataSource:
source = "https://www.dl.dropboxusercontent.com/s/d83xvd7mm9fzpk0/path_to_my_csv_data.csv?dl=0"
return SubscriptionDataSource(source, SubscriptionTransportMedium.REMOTE_FILE)
def reader(self, config: SubscriptionDataConfig, line: str, date: datetime, is_live: bool) -> BaseData:
if not (line.strip()):
return None
data = line.split(',')
obj_data = CustomDataType()
obj_data.symbol = config.symbol
try:
obj_data.time = datetime.strptime(data[0], '%Y-%m-%d %H:%M:%S') + timedelta(hours=20)
obj_data["open"] = float(data[1])
obj_data["high"] = float(data[2])
obj_data["low"] = float(data[3])
obj_data["close"] = float(data[4])
obj_data.value = obj_data["close"]
# property for asserting the correct data is fetched
obj_data["some_property"] = "some property value"
except ValueError:
return None
return obj_data
```Shown in full with attribution under the source's licence. Licence: Apache-2.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.