/*
* 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 QuantConnect.Securities;
using QLNet;
namespace QuantConnect
{
///
/// Class represents trading calendar, populated with variety of events relevant to currently trading instruments
///
public class TradingCalendar
{
private readonly MarketHoursDatabase _marketHoursDatabase;
private readonly SecurityManager _securityManager;
///
/// Initialize a new instance.
///
/// SecurityManager for this calendar
/// MarketHoursDatabase for this calendar
public TradingCalendar(SecurityManager securityManager, MarketHoursDatabase marketHoursDatabase)
{
_securityManager = securityManager;
_marketHoursDatabase = marketHoursDatabase;
}
///
/// Method returns that contains trading events associated with today's date
///
/// Populated instance of
public TradingDay GetTradingDay()
{
var today = _securityManager.UtcTime.Date;
return GetTradingDay(today);
}
///
/// Method returns that contains trading events associated with the given date
///
/// Populated instance of
public TradingDay GetTradingDay(DateTime day)
{
return GetTradingDays(day, day).First();
}
///
/// Method returns that contains trading events associated with the range of dates
///
/// Start date of the range (inclusive)
/// End date of the range (inclusive)
/// >Populated list of
public IEnumerable GetTradingDays(DateTime start, DateTime end)
{
return PopulateTradingDays(start, end);
}
///
/// Method returns of the specified type () that contains trading events associated with the range of dates
///
/// Type of the events
/// Start date of the range (inclusive)
/// End date of the range (inclusive)
/// >Populated list of
public IEnumerable GetDaysByType(TradingDayType type, DateTime start, DateTime end)
{
Func typeFilter = day =>
{
switch (type)
{
case TradingDayType.BusinessDay:
return day.BusinessDay;
case TradingDayType.PublicHoliday:
return day.PublicHoliday;
case TradingDayType.Weekend:
return day.Weekend;
case TradingDayType.OptionExpiration:
return day.OptionExpirations.Any();
case TradingDayType.FutureExpiration:
return day.FutureExpirations.Any();
case TradingDayType.FutureRoll:
return day.FutureRolls.Any();
case TradingDayType.SymbolDelisting:
return day.SymbolDelistings.Any();
case TradingDayType.EquityDividends:
return day.EquityDividends.Any();
};
return false;
};
return GetTradingDays(start, end).Where(typeFilter);
}
private IEnumerable PopulateTradingDays(DateTime start, DateTime end)
{
var symbols = _securityManager.Keys;
var holidays = new HashSet();
foreach (var symbol in symbols)
{
var entry = _marketHoursDatabase.GetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType);
foreach (var holiday in entry.ExchangeHours.Holidays)
{
holidays.Add(holiday.Date);
}
}
var qlCalendar = new UnitedStates();
var options = symbols.Where(x => x.ID.SecurityType.IsOption()).ToList();
var futures = symbols.Where(x => x.ID.SecurityType == SecurityType.Future).ToList();
var totalDays = (int)(end.Date.AddDays(1.0) - start.Date).TotalDays;
if (totalDays < 0)
{
throw new ArgumentException($"TradingCalendar.PopulateTradingDays(): {Messages.TradingCalendar.InvalidTotalDays(totalDays)}");
}
foreach (var dayIdx in Enumerable.Range(0, totalDays))
{
var currentDate = start.Date.AddDays(dayIdx);
var publicHoliday = holidays.Contains(currentDate) || !qlCalendar.isBusinessDay(currentDate);
var weekend = currentDate.DayOfWeek == DayOfWeek.Sunday ||
currentDate.DayOfWeek == DayOfWeek.Saturday;
var businessDay = !publicHoliday && !weekend;
yield return
new TradingDay
{
Date = currentDate,
PublicHoliday = publicHoliday,
Weekend = weekend,
BusinessDay = businessDay,
OptionExpirations = options.Where(x => x.ID.Date.Date == currentDate),
FutureExpirations = futures.Where(x => x.ID.Date.Date == currentDate)
};
}
}
}
}