diff --git a/Tests/Algorithm/AlgorithmHistoryTests.cs b/Tests/Algorithm/AlgorithmHistoryTests.cs index 19ced9506b1a..0845b89e7c39 100644 --- a/Tests/Algorithm/AlgorithmHistoryTests.cs +++ b/Tests/Algorithm/AlgorithmHistoryTests.cs @@ -3455,6 +3455,106 @@ def get_universe_history(algorithm, flatten): } } + [Test] + public void PythonCustomUniverseHistoryCanBeFetchedUsingCSharpApi() + { + var algorithm = GetAlgorithm(new DateTime(2018, 6, 1)); + + using (Py.GIL()) + { + var testModule = PyModule.FromString("PythonCustomUniverseHistoryCanBeFetchedUsingCSharpApi", + @" +from AlgorithmImports import * + + +class StockDataSource(PythonData): + + def get_source(self, config: SubscriptionDataConfig, date: datetime, is_live: bool) -> SubscriptionDataSource: + source = ""../../TestData/daily-stock-picker-backtest.csv"" + return SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, 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 + +def universe_selector(data): + return [x.symbol for x in data] + +def add_universe(algorithm): + return algorithm.add_universe(StockDataSource, ""universe-stock-data-source"", Resolution.DAILY, universe_selector) + +def get_history(algorithm, universe): + return list(algorithm.history[StockDataSource](universe.symbol, datetime(2018, 1, 1), datetime(2018, 6, 1), Resolution.DAILY)) +"); + + dynamic getUniverse = testModule.GetAttr("add_universe"); + dynamic getHistory = testModule.GetAttr("get_history"); + + var universe = getUniverse(algorithm); + var history = getHistory(algorithm, universe).As>() as List; + Assert.IsNotEmpty(history); + } + } + + [Test] + public void PythonCustomDataHistoryCanBeFetchedUsingCSharpApi() + { + var algorithm = GetAlgorithm(new DateTime(2013, 10, 8)); + + using (Py.GIL()) + { + var testModule = PyModule.FromString("PythonCustomDataHistoryCanBeFetchedUsingCSharpApi", + @" +from AlgorithmImports import * +from QuantConnect.Tests import * + +class MyCustomDataType(PythonData): + + def get_source(self, config: SubscriptionDataConfig, date: datetime, is_live: bool) -> SubscriptionDataSource: + fileName = LeanData.GenerateZipFileName(Symbols.SPY, date, Resolution.MINUTE, config.TickType) + source = f'{Globals.DataFolder}equity/usa/minute/spy/{fileName}' + return SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv) + + def reader(self, config: SubscriptionDataConfig, line: str, date: datetime, is_live: bool) -> BaseData: + data = line.split(',') + result = MyCustomDataType() + result.DataType = MarketDataType.Base + result.Symbol = config.Symbol + result.Time = date + timedelta(milliseconds=int(data[0])) + result.Value = 1 + + return result + +def add_data(algorithm): + return algorithm.add_data(MyCustomDataType, ""MyCustomDataType"", Resolution.DAILY) + +def get_history(algorithm, security): + return list(algorithm.history[MyCustomDataType](security.symbol, datetime(2013, 10, 7), datetime(2013, 10, 8), Resolution.MINUTE)) +"); + + dynamic getCustomSecurity = testModule.GetAttr("add_data"); + dynamic getHistory = testModule.GetAttr("get_history"); + + var security = getCustomSecurity(algorithm); + var history = getHistory(algorithm, security).As>() as List; + Assert.IsNotEmpty(history); + } + } + public class CustomUniverseData : BaseDataCollection { public decimal Weight { get; private set; } diff --git a/Tests/Research/QuantBookHistoryTests.cs b/Tests/Research/QuantBookHistoryTests.cs index e3d06f0f3030..2d358bd59ad9 100644 --- a/Tests/Research/QuantBookHistoryTests.cs +++ b/Tests/Research/QuantBookHistoryTests.cs @@ -22,7 +22,6 @@ using QuantConnect.Research; using QuantConnect.Logging; using QuantConnect.Data.Fundamental; -using QuantConnect.Python; namespace QuantConnect.Tests.Research { @@ -686,103 +685,5 @@ def getHistory(): Assert.IsFalse(pyHistory.HasAttr("data")); } } - - [Test] - public void CustomPythonUniverseHistoryCanBeFetchedUsingCSharpApi() - { - using (Py.GIL()) - { - var testModule = PyModule.FromString("CustomPythonUniverseHistoryCanBeFetchedUsingCSharpApi", - @" -from AlgorithmImports import * - - -class StockDataSource(PythonData): - - def get_source(self, config: SubscriptionDataConfig, date: datetime, is_live: bool) -> SubscriptionDataSource: - source = ""../../TestData/daily-stock-picker-backtest.csv"" - return SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, 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 - -def universe_selector(data): - return [x.symbol for x in data] - -def add_universe(qb): - return qb.add_universe(StockDataSource, ""universe-stock-data-source"", Resolution.DAILY, universe_selector) - -def get_history(qb, universe): - return list(qb.history[StockDataSource](universe.symbol, datetime(2018, 1, 1), datetime(2018, 6, 1), Resolution.DAILY)) -"); - - dynamic getUniverse = testModule.GetAttr("add_universe"); - dynamic getHistory = testModule.GetAttr("get_history"); - - var qb = new QuantBook(); - var universe = getUniverse(qb); - var history = getHistory(qb, universe).As>() as List; - Assert.IsNotEmpty(history); - } - } - - [Test] - public void CustomPythonDataHistoryCanBeFetchedUsingCSharpApi() - { - using (Py.GIL()) - { - var testModule = PyModule.FromString("CustomPythonDataHistoryCanBeFetchedUsingCSharpApi", - @" -from AlgorithmImports import * -from QuantConnect.Tests import * - -class MyCustomDataType(PythonData): - - def get_source(self, config: SubscriptionDataConfig, date: datetime, is_live: bool) -> SubscriptionDataSource: - fileName = LeanData.GenerateZipFileName(Symbols.SPY, date, Resolution.MINUTE, config.TickType) - source = f'{Globals.DataFolder}equity/usa/minute/spy/{fileName}' - return SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Csv) - - def reader(self, config: SubscriptionDataConfig, line: str, date: datetime, is_live: bool) -> BaseData: - data = line.split(',') - result = MyCustomDataType() - result.DataType = MarketDataType.Base - result.Symbol = config.Symbol - result.Time = date + timedelta(milliseconds=int(data[0])) - result.Value = 1 - - return result - -def add_data(qb): - return qb.add_data(MyCustomDataType, ""MyCustomDataType"", Resolution.DAILY) - -def get_history(qb, security): - return list(qb.history[MyCustomDataType](security.symbol, datetime(2013, 10, 7), datetime(2013, 10, 8), Resolution.MINUTE)) -"); - - dynamic getCustomSecurity = testModule.GetAttr("add_data"); - dynamic getHistory = testModule.GetAttr("get_history"); - - var qb = new QuantBook(); - var security = getCustomSecurity(qb); - var history = getHistory(qb, security).As>() as List; - Assert.IsNotEmpty(history); - } - } } }