Files
quantconnect--lean/Tests/Algorithm/AlgorithmAddDataTests.cs
T

219 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using NodaTime;
using NUnit.Framework;
using QuantConnect.Algorithm;
using QuantConnect.AlgorithmFactory.Python.Wrappers;
using QuantConnect.Configuration;
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
using QuantConnect.Packets;
using QuantConnect.Securities;
using QuantConnect.Util;
using Bitcoin = QuantConnect.Algorithm.CSharp.LiveTradingFeaturesAlgorithm.Bitcoin;
using HistoryRequest = QuantConnect.Data.HistoryRequest;
namespace QuantConnect.Tests.Algorithm
{
[TestFixture]
public class AlgorithmAddDataTests
{
[Test]
public void DefaultDataFeeds_CanBeOverwritten_Successfully()
{
Config.Set("security-data-feeds", "{ Forex: [\"Trade\"] }");
var algo = new QCAlgorithm();
// forex defult - should be tradebar
var forexTrade = algo.AddForex("EURUSD");
Assert.IsTrue(forexTrade.Subscriptions.Count() == 1);
Assert.IsTrue(GetMatchingSubscription(forexTrade, typeof(QuoteBar)) != null);
// Change
var dataFeedsConfigString = Config.Get("security-data-feeds");
Dictionary<SecurityType, List<TickType>> dataFeeds = new Dictionary<SecurityType, List<TickType>>();
if (dataFeedsConfigString != string.Empty)
{
dataFeeds = JsonConvert.DeserializeObject<Dictionary<SecurityType, List<TickType>>>(dataFeedsConfigString);
}
algo.SetAvailableDataTypes(dataFeeds);
// new forex - should be quotebar
var forexQuote = algo.AddForex("EURUSD");
Assert.IsTrue(forexQuote.Subscriptions.Count() == 1);
Assert.IsTrue(GetMatchingSubscription(forexQuote, typeof(TradeBar)) != null);
}
[Test]
public void DefaultDataFeeds_AreAdded_Successfully()
{
var algo = new QCAlgorithm();
// forex
var forex = algo.AddSecurity(SecurityType.Forex, "eurusd");
Assert.IsTrue(forex.Subscriptions.Count() == 1);
Assert.IsTrue(GetMatchingSubscription(forex, typeof(QuoteBar)) != null);
// equity
var equity = algo.AddSecurity(SecurityType.Equity, "goog");
Assert.IsTrue(equity.Subscriptions.Count() == 1);
Assert.IsTrue(GetMatchingSubscription(equity, typeof(TradeBar)) != null);
// option
var option = algo.AddSecurity(SecurityType.Option, "goog");
Assert.IsTrue(option.Subscriptions.Count() == 1);
Assert.IsTrue(GetMatchingSubscription(option, typeof(ZipEntryName)) != null);
// cfd
var cfd = algo.AddSecurity(SecurityType.Cfd, "abc");
Assert.IsTrue(cfd.Subscriptions.Count() == 1);
Assert.IsTrue(GetMatchingSubscription(cfd, typeof(QuoteBar)) != null);
// future
var future = algo.AddSecurity(SecurityType.Future, "ES");
Assert.IsTrue(future.Subscriptions.Count() == 1);
Assert.IsTrue(future.Subscriptions.FirstOrDefault(x => typeof(ZipEntryName).IsAssignableFrom(x.Type)) != null);
// Crypto
var crypto = algo.AddSecurity(SecurityType.Crypto, "btcusd", Resolution.Daily);
Assert.IsTrue(crypto.Subscriptions.Count() == 2);
Assert.IsTrue(GetMatchingSubscription(crypto, typeof(QuoteBar)) != null);
Assert.IsTrue(GetMatchingSubscription(crypto, typeof(TradeBar)) != null);
}
[Test]
public void CustomDataTypes_AreAddedToSubscriptions_Successfully()
{
var qcAlgorithm = new QCAlgorithm();
// Add a bitcoin subscription
qcAlgorithm.AddData<Bitcoin>("BTC");
var bitcoinSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.FirstOrDefault(x => x.Type == typeof(Bitcoin));
Assert.AreEqual(bitcoinSubscription.Type, typeof(Bitcoin));
// Add a quandl subscription
qcAlgorithm.AddData<Quandl>("EURCAD");
var quandlSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.FirstOrDefault(x => x.Type == typeof(Quandl));
Assert.AreEqual(quandlSubscription.Type, typeof(Quandl));
}
[Test]
public void OnEndOfTimeStepSeedsUnderlyingSecuritiesThatHaveNoData()
{
var qcAlgorithm = new QCAlgorithm();
qcAlgorithm.SetLiveMode(true);
var testHistoryProvider = new TestHistoryProvider();
qcAlgorithm.HistoryProvider = testHistoryProvider;
var option = qcAlgorithm.AddSecurity(SecurityType.Option, testHistoryProvider.underlyingSymbol);
var option2 = qcAlgorithm.AddSecurity(SecurityType.Option, testHistoryProvider.underlyingSymbol2);
Assert.IsFalse(qcAlgorithm.Securities.ContainsKey(option.Symbol.Underlying));
Assert.IsFalse(qcAlgorithm.Securities.ContainsKey(option2.Symbol.Underlying));
qcAlgorithm.OnEndOfTimeStep();
var data = qcAlgorithm.Securities[testHistoryProvider.underlyingSymbol].GetLastData();
var data2 = qcAlgorithm.Securities[testHistoryProvider.underlyingSymbol2].GetLastData();
Assert.IsNotNull(data);
Assert.IsNotNull(data2);
Assert.AreEqual(data.Price, 2);
Assert.AreEqual(data2.Price, 3);
}
[Test, Ignore]
public void PythonCustomDataTypes_AreAddedToSubscriptions_Successfully()
{
var pythonPath = new System.IO.DirectoryInfo("RegressionAlgorithms");
Environment.SetEnvironmentVariable("PYTHONPATH", pythonPath.FullName);
var qcAlgorithm = new AlgorithmPythonWrapper("Test_CustomDataAlgorithm");
// Initialize contains the statements:
// self.AddData(Nifty, "NIFTY")
// self.AddData(QuandlFuture, "SCF/CME_CL1_ON", Resolution.Daily)
qcAlgorithm.Initialize();
var niftySubscription = qcAlgorithm.SubscriptionManager.Subscriptions.FirstOrDefault(x => x.Symbol.Value == "NIFTY");
Assert.IsNotNull(niftySubscription);
var niftyFactory = (BaseData)ObjectActivator.GetActivator(niftySubscription.Type).Invoke(new object[] { niftySubscription.Type });
Assert.DoesNotThrow(() => niftyFactory.GetSource(niftySubscription, DateTime.UtcNow, false));
var quandlSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.FirstOrDefault(x => x.Symbol.Value == "SCF/CME_CL1_ON");
Assert.IsNotNull(quandlSubscription);
var quandlFactory = (BaseData)ObjectActivator.GetActivator(quandlSubscription.Type).Invoke(new object[] { quandlSubscription.Type });
Assert.DoesNotThrow(() => quandlFactory.GetSource(quandlSubscription, DateTime.UtcNow, false));
}
[Test, Ignore]
public void PythonCustomDataTypes_AreAddedToConsolidator_Successfully()
{
var pythonPath = new System.IO.DirectoryInfo("RegressionAlgorithms");
Environment.SetEnvironmentVariable("PYTHONPATH", pythonPath.FullName);
var qcAlgorithm = new AlgorithmPythonWrapper("Test_CustomDataAlgorithm");
// Initialize contains the statements:
// self.AddData(Nifty, "NIFTY")
// self.AddData(QuandlFuture, "SCF/CME_CL1_ON", Resolution.Daily)
qcAlgorithm.Initialize();
var niftyConsolidator = new DynamicDataConsolidator(TimeSpan.FromDays(2));
Assert.DoesNotThrow(() => qcAlgorithm.SubscriptionManager.AddConsolidator("NIFTY", niftyConsolidator));
var quandlConsolidator = new DynamicDataConsolidator(TimeSpan.FromDays(2));
Assert.DoesNotThrow(() => qcAlgorithm.SubscriptionManager.AddConsolidator("SCF/CME_CL1_ON", quandlConsolidator));
}
private static SubscriptionDataConfig GetMatchingSubscription(Security security, Type type)
{
// find a subscription matchin the requested type with a higher resolution than requested
return (from sub in security.Subscriptions.OrderByDescending(s => s.Resolution)
where type.IsAssignableFrom(sub.Type)
select sub).FirstOrDefault();
}
private class TestHistoryProvider : IHistoryProvider
{
public string underlyingSymbol = "GOOG";
public string underlyingSymbol2 = "AAPL";
public int DataPointCount { get; }
public void Initialize(AlgorithmNodePacket job, IDataProvider dataProvider, IDataCacheProvider dataCacheProvider,
IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, Action<int> statusUpdate)
{
throw new NotImplementedException();
}
public IEnumerable<Slice> GetHistory(IEnumerable<HistoryRequest> requests, DateTimeZone sliceTimeZone)
{
var now = DateTime.UtcNow;
var tradeBar1 = new TradeBar(now, underlyingSymbol, 1, 1, 1, 1, 1, TimeSpan.FromDays(1));
var tradeBar2 = new TradeBar(now, underlyingSymbol2, 3, 3, 3, 3, 3, TimeSpan.FromDays(1));
var slice1 = new Slice(now, new List<BaseData> { tradeBar1, tradeBar2 },
new TradeBars(now), new QuoteBars(),
new Ticks(), new OptionChains(),
new FuturesChains(), new Splits(),
new Dividends(now), new Delistings(),
new SymbolChangedEvents());
var tradeBar1_2 = new TradeBar(now, underlyingSymbol, 2, 2, 2, 2, 2, TimeSpan.FromDays(1));
var slice2 = new Slice(now, new List<BaseData> { tradeBar1_2 },
new TradeBars(now), new QuoteBars(),
new Ticks(), new OptionChains(),
new FuturesChains(), new Splits(),
new Dividends(now), new Delistings(),
new SymbolChangedEvents());
return new[] { slice1, slice2 };
}
}
}
}