/* * 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. * */ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; using QuantConnect.Algorithm; using QuantConnect.Brokerages; using QuantConnect.Data; using QuantConnect.Data.Auxiliary; using QuantConnect.Data.Market; using QuantConnect.Data.UniverseSelection; using QuantConnect.Lean.Engine.DataFeeds; using QuantConnect.Lean.Engine.Results; using QuantConnect.Packets; using QuantConnect.Securities; using QuantConnect.Tests.Common.Securities; namespace QuantConnect.Tests.Engine { [TestFixture] public class RealTimePriceUpdateTests { private TestableLiveTradingDataFeed _liveTradingDataFeed; private SecurityExchangeHours _exchangeHours; private SubscriptionDataConfig _config; [TestFixtureSetUp] public void Setup() { var sunday = new LocalMarketHours(DayOfWeek.Sunday, new TimeSpan(17, 0, 0), TimeSpan.FromTicks(Time.OneDay.Ticks - 1)); var monday = LocalMarketHours.OpenAllDay(DayOfWeek.Monday); var tuesday = LocalMarketHours.OpenAllDay(DayOfWeek.Tuesday); var wednesday = LocalMarketHours.OpenAllDay(DayOfWeek.Wednesday); var thursday = LocalMarketHours.OpenAllDay(DayOfWeek.Thursday); var friday = new LocalMarketHours(DayOfWeek.Friday, TimeSpan.Zero, new TimeSpan(17, 0, 0)); var earlyCloses = new Dictionary(); _exchangeHours = new SecurityExchangeHours(TimeZones.NewYork, USHoliday.Dates.Select(x => x.Date), new[] { sunday, monday, tuesday, wednesday, thursday, friday }.ToDictionary(x => x.DayOfWeek), earlyCloses); _liveTradingDataFeed = new TestableLiveTradingDataFeed(); var jobPacket = new LiveNodePacket() { DeployId = "", Brokerage = BrokerageName.OandaBrokerage.ToString(), DataQueueHandler = "LiveDataQueue" }; var algo = new TestAlgorithm(); var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var symbolPropertiesDataBase = SymbolPropertiesDatabase.FromDataFolder(); var dataManager = new DataManager(_liveTradingDataFeed, new UniverseSelection( algo, new SecurityService(algo.Portfolio.CashBook, marketHoursDatabase, symbolPropertiesDataBase, algo)), algo, algo.TimeKeeper, marketHoursDatabase, true); algo.SubscriptionManager.SetDataManager(dataManager); var synchronizer = new LiveSynchronizer(); synchronizer.Initialize(algo, dataManager); _liveTradingDataFeed.Initialize(algo, jobPacket, new LiveTradingResultHandler(), new LocalDiskMapFileProvider(), null, new DefaultDataProvider(), dataManager, synchronizer); algo.Initialize(); _config = SecurityTests.CreateTradeBarConfig(); } /// /// Test algorithm which doesn't consume any feeds for simple testing. /// private class TestAlgorithm : QCAlgorithm { public override void Initialize() { SetBenchmark(time => 0); } } [TestFixtureTearDown] public void TearDown() { _liveTradingDataFeed.Exit(); } [Test] public void NullSubscriptions_DoNotIndicateRealTimePriceUpdates() { Assert.IsFalse(_liveTradingDataFeed.UpdateRealTimePrice(null, new TimeZoneOffsetProviderNeverOpen(), _exchangeHours)); } [Test] public void ClosedExchanges_DoNotIndicateRealTimePriceUpdates() { var security = new Security( Symbols.AAPL, _exchangeHours, new Cash("USA", 100m, 1m), SymbolProperties.GetDefault("USA"), ErrorCurrencyConverter.Instance ); var subscriptionRequest = new SubscriptionRequest(false, null, security, _config, DateTime.MinValue, DateTime.MaxValue); var subscription = new Subscription(subscriptionRequest, null, new TimeZoneOffsetProviderNeverOpen()); Assert.IsFalse(_liveTradingDataFeed.UpdateRealTimePrice(subscription, new TimeZoneOffsetProviderNeverOpen(), _exchangeHours)); } [Test] public void OpenExchanges_DoIndicateRealTimePriceUpdates() { var security = new Security( Symbols.AAPL, _exchangeHours, new Cash("USA", 100m, 1m), SymbolProperties.GetDefault("USA"), ErrorCurrencyConverter.Instance ); var subscriptionRequest = new SubscriptionRequest(false, null, security, _config, DateTime.MinValue, DateTime.MaxValue); var subscription = new Subscription(subscriptionRequest, null, new TimeZoneOffsetProviderNeverOpen()); Assert.IsTrue(_liveTradingDataFeed.UpdateRealTimePrice(subscription, new TimeZoneOffsetProviderAlwaysOpen(), _exchangeHours)); } class TestableLiveTradingDataFeed : LiveTradingDataFeed { public bool UpdateRealTimePrice( Subscription subscription, TimeZoneOffsetProvider timeZoneOffsetProvider, SecurityExchangeHours exchangeHours) { return UpdateSubscriptionRealTimePrice(subscription, timeZoneOffsetProvider, exchangeHours, new Tick()); } } class TimeZoneOffsetProviderNeverOpen : TimeZoneOffsetProvider { public TimeZoneOffsetProviderNeverOpen() : base(TimeZones.NewYork, DateTime.Parse("1/1/2016"), DateTime.Parse("1/1/2018")) { } public override DateTime ConvertFromUtc(DateTime utcTime) { // return a date that's always closed for equities return new DateTime(2017, 3, 18, 23, 0, 0); } } class TimeZoneOffsetProviderAlwaysOpen : TimeZoneOffsetProvider { public TimeZoneOffsetProviderAlwaysOpen() : base(TimeZones.NewYork, DateTime.Parse("1/1/2016"), DateTime.Parse("1/1/2018")) { } public override DateTime ConvertFromUtc(DateTime utcTime) { // return a date that's always open for equities return new DateTime(2017, 3, 20, 13, 0, 0); } } } }