181 lines
7.2 KiB
C#
181 lines
7.2 KiB
C#
/*
|
|
* 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<DateTime, TimeSpan>();
|
|
_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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test algorithm which doesn't consume any feeds for simple testing.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|