Lean  $LEAN_TAG$
IsolatorLimitResultProvider.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;
18 
19 namespace QuantConnect
20 {
21  /// <summary>
22  /// Provides access to the <see cref="NullIsolatorLimitResultProvider"/> and extension methods supporting <see cref="ScheduledEvent"/>
23  /// </summary>
24  public static class IsolatorLimitResultProvider
25  {
26  /// <summary>
27  /// Provides access to a null implementation of <see cref="IIsolatorLimitResultProvider"/>
28  /// </summary>
29  public static readonly IIsolatorLimitResultProvider Null = new NullIsolatorLimitResultProvider();
30 
31  /// <summary>
32  /// Convenience method for invoking a scheduled event's Scan method inside the <see cref="IsolatorLimitResultProvider"/>
33  /// </summary>
34  public static void Consume(
35  this IIsolatorLimitResultProvider isolatorLimitProvider,
36  ScheduledEvent scheduledEvent,
37  DateTime scanTimeUtc,
38  TimeMonitor timeMonitor
39  )
40  {
41  // perform initial filtering to prevent starting a task when not necessary
42  if (scheduledEvent.NextEventUtcTime > scanTimeUtc)
43  {
44  return;
45  }
46 
47  var timeProvider = RealTimeProvider.Instance;
48  isolatorLimitProvider.Consume(timeProvider, () => scheduledEvent.Scan(scanTimeUtc), timeMonitor);
49  }
50 
51  /// <summary>
52  /// Executes the provided code block and while the code block is running, continually consume from
53  /// the limit result provided one token each minute. This function allows the code to run for the
54  /// first full minute without requesting additional time from the provider. Following that, every
55  /// minute an additional one minute will be requested from the provider.
56  /// </summary>
57  /// <remarks>
58  /// This method exists to support scheduled events, and as such, intercepts any errors raised via the
59  /// provided code and wraps them in a <see cref="ScheduledEventException"/>. If in the future this is
60  /// usable elsewhere, consider refactoring to handle the errors in a different fashion.
61  /// </remarks>
62  public static void Consume(
63  this IIsolatorLimitResultProvider isolatorLimitProvider,
64  ITimeProvider timeProvider,
65  Action code,
66  TimeMonitor timeMonitor
67  )
68  {
69  var consumer = new TimeConsumer
70  {
71  IsolatorLimitProvider = isolatorLimitProvider,
72  TimeProvider = timeProvider
73  };
74  timeMonitor.Add(consumer);
75  code();
76  consumer.Finished = true;
77  }
78 
79 
80  private sealed class NullIsolatorLimitResultProvider : IIsolatorLimitResultProvider
81  {
82  private static readonly IsolatorLimitResult OK = new IsolatorLimitResult(TimeSpan.Zero, string.Empty);
83 
84  public void RequestAdditionalTime(int minutes) { }
85  public IsolatorLimitResult IsWithinLimit() { return OK; }
86  public bool TryRequestAdditionalTime(int minutes) { return true; }
87  }
88  }
89 }