Files
quantconnect--lean/Tests/Common/TimeTests.cs
Michael Handschuh 86157cd5e7 Manually create US equity security exchange hours
Travis was having issues loading the market-hours-database.json and ended
up constantly using the always open exchange hours.
2018-08-07 15:02:44 -04:00

195 lines
8.9 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 NodaTime;
using NUnit.Framework;
using QuantConnect.Securities;
using QuantConnect.Tests.Common.Securities;
namespace QuantConnect.Tests.Common
{
[TestFixture]
public class TimeTests
{
[Test]
public void UnixTimeStampSecondsToDateTimeHasSubMillisecondPrecision()
{
const double stamp = 1520711961.00055;
var expected = new DateTime(2018, 3, 10, 19, 59, 21, 0).AddTicks(5500);
var time = Time.UnixTimeStampToDateTime(stamp);
Assert.AreEqual(expected, time);
}
[Test]
public void UnixTimeStampMillisecondsToDateTimeHasSubMillisecondPrecision()
{
const double stamp = 1520711961000.55;
var expected = new DateTime(2018, 3, 10, 19, 59, 21, 0).AddTicks(5500);
var time = Time.UnixMillisecondTimeStampToDateTime(stamp);
Assert.AreEqual(expected, time);
}
[Test]
public void GetStartTimeForTradeBarsRoundsDown()
{
// 2015.09.01 @ noon
var end = new DateTime(2015, 09, 01, 12, 0, 1);
var barSize = TimeSpan.FromMinutes(1);
var hours = SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork);
var start = Time.GetStartTimeForTradeBars(hours, end, barSize, 1, false);
// round down and back up a single bar
Assert.AreEqual(end.RoundDown(barSize).Subtract(barSize), start);
}
[Test]
public void GetStartTimeForTradeBarsHandlesOverNight()
{
// 2015.09.01 @ noon
var end = new DateTime(2015, 09, 01, 12, 0, 0);
var barSize = TimeSpan.FromHours(1);
var hours = SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours();
var start = Time.GetStartTimeForTradeBars(hours, end, barSize, 7, false);
// from noon, back up to 9am (3 hours) then skip night, so from 4pm, back up to noon, 4 more hours
Assert.AreEqual(end.AddDays(-1), start);
}
[Test]
public void GetStartTimeForTradeBarsHandlesWeekends()
{
// 2015.09.01 @ noon
var end = new DateTime(2015, 09, 01, 12, 0, 0);
var expectedStart = new DateTime(2015, 08, 21);
var barSize = TimeSpan.FromDays(1);
var hours = SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours();
var start = Time.GetStartTimeForTradeBars(hours, end, barSize, 7, false);
// from noon, back up to 9am (3 hours) then skip night, so from 4pm, back up to noon, 4 more hours
Assert.AreEqual(expectedStart, start);
}
[Test]
public void EachTradeableDayInTimeZoneIsSameForEqualTimeZones()
{
var start = new DateTime(2010, 01, 01);
var end = new DateTime(2016, 02, 12);
var entry = MarketHoursDatabase.FromDataFolder().ExchangeHoursListing.First().Value;
var expected = Time.EachTradeableDay(entry.ExchangeHours, start, end);
var actual = Time.EachTradeableDayInTimeZone(entry.ExchangeHours, start, end, entry.ExchangeHours.TimeZone, true);
CollectionAssert.AreEqual(expected, actual);
}
[Test]
public void EachTradeableDayInTimeZoneWithOffsetPlus12()
{
var start = new DateTime(2016, 2, 11);
var end = new DateTime(2016, 2, 12);
var equityExchange = SecurityExchangeHours.AlwaysOpen(DateTimeZone.ForOffset(Offset.FromHours(-5)));
var dataTimeZone = DateTimeZone.ForOffset(Offset.FromHours(7));
// given this arrangement we should still start on the same date and end a day late
var expected = new[] {start, end, end.AddDays(1)};
var actual = Time.EachTradeableDayInTimeZone(equityExchange, start, end, dataTimeZone, true);
CollectionAssert.AreEqual(expected, actual);
}
[Test]
public void EachTradeableDayInTimeZoneWithOffsetMinus12()
{
var start = new DateTime(2016, 2, 11);
var end = new DateTime(2016, 2, 12);
var exchange = SecurityExchangeHours.AlwaysOpen(DateTimeZone.ForOffset(Offset.FromHours(5)));
var dataTimeZone = DateTimeZone.ForOffset(Offset.FromHours(-7));
// given this arrangement we should still start a day early but still end on the same date
var expected = new[] {start.AddDays(-1), start, end};
var actual = Time.EachTradeableDayInTimeZone(exchange, start, end, dataTimeZone, true);
CollectionAssert.AreEqual(expected, actual);
}
[Test]
public void EachTradeableDayInTimeZoneWithOffset25()
{
var start = new DateTime(2016, 2, 11);
var end = new DateTime(2016, 2, 12);
var exchange = SecurityExchangeHours.AlwaysOpen(DateTimeZone.ForOffset(Offset.FromHours(12)));
var dataTimeZone = DateTimeZone.ForOffset(Offset.FromHours(-13));
// given this arrangement we should still start a day early but still end on the same date
var expected = new[] {start.AddDays(-2), start.AddDays(-1), start};
var actual = Time.EachTradeableDayInTimeZone(exchange, start, end, dataTimeZone, true);
CollectionAssert.AreEqual(expected, actual);
}
[Test]
public void MultipliesTimeSpans()
{
var interval = TimeSpan.FromSeconds(1);
var expected = TimeSpan.FromSeconds(5);
var actual = interval.Multiply(5d);
Assert.AreEqual(expected, actual);
}
[Test]
[TestCase(2, 7, 3)]
[TestCase(2, 4, 2)]
[TestCase(6, 7, 1)]
public void GetNumberOfTradeBarsForIntervalUsingDailyStepSize(int startDay, int endDay, int expected)
{
var start = new DateTime(2018, 08, startDay);
var end = new DateTime(2018, 08, endDay);
var exchangeHours = CreateUsEquitySecurityExchangeHours();
var actual = Time.GetNumberOfTradeBarsInInterval(exchangeHours, start, end, Time.OneDay);
Assert.AreEqual(expected, actual);
}
[Test]
[TestCase(2, 7, 21)]
[TestCase(2, 4, 14)]
[TestCase(6, 7, 07)]
public void GetNumberOfTradeBarsForIntervalUsingHourlyStepSize(int startDay, int endDay, int expected)
{
var start = new DateTime(2018, 08, startDay);
var end = new DateTime(2018, 08, endDay);
var exchangeHours = CreateUsEquitySecurityExchangeHours();
var actual = Time.GetNumberOfTradeBarsInInterval(exchangeHours, start, end, Time.OneHour);
Assert.AreEqual(expected, actual);
}
private static readonly TimeSpan USEquityPreOpen = new TimeSpan(4, 0, 0);
private static readonly TimeSpan USEquityOpen = new TimeSpan(9, 30, 0);
private static readonly TimeSpan USEquityClose = new TimeSpan(16, 0, 0);
private static readonly TimeSpan USEquityPostClose = new TimeSpan(20, 0, 0);
private static SecurityExchangeHours CreateUsEquitySecurityExchangeHours()
{
var sunday = LocalMarketHours.ClosedAllDay(DayOfWeek.Sunday);
var monday = new LocalMarketHours(DayOfWeek.Monday, USEquityPreOpen, USEquityOpen, USEquityClose, USEquityPostClose);
var tuesday = new LocalMarketHours(DayOfWeek.Tuesday, USEquityPreOpen, USEquityOpen, USEquityClose, USEquityPostClose);
var wednesday = new LocalMarketHours(DayOfWeek.Wednesday, USEquityPreOpen, USEquityOpen, USEquityClose, USEquityPostClose);
var thursday = new LocalMarketHours(DayOfWeek.Thursday, USEquityPreOpen, USEquityOpen, USEquityClose, USEquityPostClose);
var friday = new LocalMarketHours(DayOfWeek.Friday, USEquityPreOpen, USEquityOpen, USEquityClose, USEquityPostClose);
var saturday = LocalMarketHours.ClosedAllDay(DayOfWeek.Saturday);
var earlyCloses = new Dictionary<DateTime, TimeSpan>();
return new SecurityExchangeHours(TimeZones.NewYork, USHoliday.Dates.Select(x => x.Date), new[]
{
sunday, monday, tuesday, wednesday, thursday, friday, saturday
}.ToDictionary(x => x.DayOfWeek), earlyCloses);
}
}
}