Skip to content

Commit

Permalink
Move unit tests to algorithm history tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonabreul committed Feb 26, 2025
1 parent 4d5d0c1 commit db8b7c9
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 99 deletions.
100 changes: 100 additions & 0 deletions Tests/Algorithm/AlgorithmHistoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<List<PythonData>>() as List<PythonData>;
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<List<PythonData>>() as List<PythonData>;
Assert.IsNotEmpty(history);
}
}

public class CustomUniverseData : BaseDataCollection
{
public decimal Weight { get; private set; }
Expand Down
99 changes: 0 additions & 99 deletions Tests/Research/QuantBookHistoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
using QuantConnect.Research;
using QuantConnect.Logging;
using QuantConnect.Data.Fundamental;
using QuantConnect.Python;

namespace QuantConnect.Tests.Research
{
Expand Down Expand Up @@ -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<List<PythonData>>() as List<PythonData>;
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<List<PythonData>>() as List<PythonData>;
Assert.IsNotEmpty(history);
}
}
}
}

0 comments on commit db8b7c9

Please sign in to comment.