Lean  $LEAN_TAG$
SecurityExchange.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using NodaTime;
18 using System.Linq;
19 using QuantConnect.Util;
20 using System.Collections.Generic;
21 
23 {
24  /// <summary>
25  /// Base exchange class providing information and helper tools for reading the current exchange situation
26  /// </summary>
27  public class SecurityExchange
28  {
29  private LocalTimeKeeper _timeProvider;
30 
31  /// <summary>
32  /// Gets the <see cref="SecurityExchangeHours"/> for this exchange
33  /// </summary>
34  public SecurityExchangeHours Hours { get; private set; }
35 
36  /// <summary>
37  /// Gets the time zone for this exchange
38  /// </summary>
39  public DateTimeZone TimeZone => Hours.TimeZone;
40 
41  /// <summary>
42  /// Number of trading days per year for this security. By default the market is open 365 days per year.
43  /// </summary>
44  /// <remarks>Used for performance statistics to calculate sharpe ratio accurately</remarks>
45  public virtual int TradingDaysPerYear => 365;
46 
47  /// <summary>
48  /// Time from the most recent data
49  /// </summary>
50  public DateTime LocalTime => _timeProvider.LocalTime;
51 
52  /// <summary>
53  /// Boolean property for quickly testing if the exchange is open.
54  /// </summary>
55  public bool ExchangeOpen => Hours.IsOpen(LocalTime, false);
56 
57  /// <summary>
58  /// Boolean property for quickly testing if the exchange is 10 minutes away from closing.
59  /// </summary>
60  public bool ClosingSoon => IsClosingSoon(minutesToClose:10);
61 
62  /// <summary>
63  /// Initializes a new instance of the <see cref="SecurityExchange"/> class using the specified
64  /// exchange hours to determine open/close times
65  /// </summary>
66  /// <param name="exchangeHours">Contains the weekly exchange schedule plus holidays</param>
68  {
69  Hours = exchangeHours;
70  }
71 
72  /// <summary>
73  /// Set the current datetime in terms of the exchange's local time zone
74  /// </summary>
75  /// <param name="timeProvider">Most recent data tick</param>
77  {
78  _timeProvider = timeProvider;
79  }
80 
81  /// <summary>
82  /// Check if the *date* is open.
83  /// </summary>
84  /// <remarks>This is useful for first checking the date list, and then the market hours to save CPU cycles</remarks>
85  /// <param name="dateToCheck">Date to check</param>
86  /// <param name="extendedMarketHours">True to consider days with extended market hours only as open</param>
87  /// <returns>Return true if the exchange is open for this date</returns>
88  public bool DateIsOpen(DateTime dateToCheck, bool extendedMarketHours = false)
89  {
90  return Hours.IsDateOpen(dateToCheck, extendedMarketHours);
91  }
92 
93  /// <summary>
94  /// Check if this DateTime is open.
95  /// </summary>
96  /// <param name="dateTime">DateTime to check</param>
97  /// <returns>Boolean true if the market is open</returns>
98  public bool DateTimeIsOpen(DateTime dateTime)
99  {
100  return Hours.IsOpen(dateTime, false);
101  }
102 
103  /// <summary>
104  /// Determines if the exchange was open at any time between start and stop
105  /// </summary>
106  public bool IsOpenDuringBar(DateTime barStartTime, DateTime barEndTime, bool isExtendedMarketHours)
107  {
108  return Hours.IsOpen(barStartTime, barEndTime, isExtendedMarketHours);
109  }
110 
111  /// <summary>
112  /// Determines if the exchange is going to close in the next provided minutes
113  /// </summary>
114  /// <param name="minutesToClose">Minutes to close to check</param>
115  /// <returns>Returns true if the exchange is going to close in the next provided minutes</returns>
116  public bool IsClosingSoon(int minutesToClose)
117  {
118  return !Hours.IsOpen(LocalTime.AddMinutes(minutesToClose), false);
119  }
120 
121  /// <summary>
122  /// Sets the regular market hours for the specified days If no days are specified then
123  /// all days will be updated.
124  /// </summary>
125  /// <param name="marketHoursSegments">Specifies each segment of the market hours, such as premarket/market/postmark</param>
126  /// <param name="days">The days of the week to set these times for</param>
127  public void SetMarketHours(IEnumerable<MarketHoursSegment> marketHoursSegments, params DayOfWeek[] days)
128  {
129  if (days.IsNullOrEmpty()) days = Enum.GetValues(typeof(DayOfWeek)).OfType<DayOfWeek>().ToArray();
130 
131  var marketHours = Hours.MarketHours.ToDictionary();
132  marketHoursSegments = marketHoursSegments as IList<MarketHoursSegment> ?? marketHoursSegments.ToList();
133  foreach (var day in days)
134  {
135  marketHours[day] = new LocalMarketHours(day, marketHoursSegments);
136  }
137 
138  // create a new exchange hours instance for the new hours
140  }
141  }
142 }