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  /// <returns>Return true if the exchange is open for this date</returns>
87  public bool DateIsOpen(DateTime dateToCheck)
88  {
89  return Hours.IsDateOpen(dateToCheck);
90  }
91 
92  /// <summary>
93  /// Check if this DateTime is open.
94  /// </summary>
95  /// <param name="dateTime">DateTime to check</param>
96  /// <returns>Boolean true if the market is open</returns>
97  public bool DateTimeIsOpen(DateTime dateTime)
98  {
99  return Hours.IsOpen(dateTime, false);
100  }
101 
102  /// <summary>
103  /// Determines if the exchange was open at any time between start and stop
104  /// </summary>
105  public bool IsOpenDuringBar(DateTime barStartTime, DateTime barEndTime, bool isExtendedMarketHours)
106  {
107  return Hours.IsOpen(barStartTime, barEndTime, isExtendedMarketHours);
108  }
109 
110  /// <summary>
111  /// Determines if the exchange is going to close in the next provided minutes
112  /// </summary>
113  /// <param name="minutesToClose">Minutes to close to check</param>
114  /// <returns>Returns true if the exchange is going to close in the next provided minutes</returns>
115  public bool IsClosingSoon(int minutesToClose)
116  {
117  return !Hours.IsOpen(LocalTime.AddMinutes(minutesToClose), false);
118  }
119 
120  /// <summary>
121  /// Sets the regular market hours for the specified days If no days are specified then
122  /// all days will be updated.
123  /// </summary>
124  /// <param name="marketHoursSegments">Specifies each segment of the market hours, such as premarket/market/postmark</param>
125  /// <param name="days">The days of the week to set these times for</param>
126  public void SetMarketHours(IEnumerable<MarketHoursSegment> marketHoursSegments, params DayOfWeek[] days)
127  {
128  if (days.IsNullOrEmpty()) days = Enum.GetValues(typeof(DayOfWeek)).OfType<DayOfWeek>().ToArray();
129 
130  var marketHours = Hours.MarketHours.ToDictionary();
131  marketHoursSegments = marketHoursSegments as IList<MarketHoursSegment> ?? marketHoursSegments.ToList();
132  foreach (var day in days)
133  {
134  marketHours[day] = new LocalMarketHours(day, marketHoursSegments);
135  }
136 
137  // create a new exchange hours instance for the new hours
139  }
140  }
141 }