Lean  $LEAN_TAG$
FixedIntervalRefillStrategy.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 
19 {
20  /// <summary>
21  /// Provides a refill strategy that has a constant, quantized refill rate.
22  /// For example, after 1 minute passes add 5 units. If 59 seconds has passed, it will add zero unit,
23  /// but if 2 minutes have passed, then 10 units would be added.
24  /// </summary>
26  {
27  private readonly object _sync = new object();
28 
29  private long _nextRefillTimeTicks;
30 
31  private readonly long _refillAmount;
32  private readonly long _refillIntervalTicks;
33  private readonly ITimeProvider _timeProvider;
34 
35  /// <summary>
36  /// Initializes a new instance of the <see cref="FixedIntervalRefillStrategy"/> class.
37  /// </summary>
38  /// <param name="timeProvider">Provides the current time used for determining how much time has elapsed
39  /// between invocations of the refill method</param>
40  /// <param name="refillAmount">Defines the constant number of tokens to be made available for consumption
41  /// each time the provided <paramref name="refillInterval"/> has passed</param>
42  /// <param name="refillInterval">The amount of time that must pass before adding the specified <paramref name="refillAmount"/>
43  /// back to the bucket</param>
44  public FixedIntervalRefillStrategy(ITimeProvider timeProvider, long refillAmount, TimeSpan refillInterval)
45  {
46  _timeProvider = timeProvider;
47  _refillAmount = refillAmount;
48  _refillIntervalTicks = refillInterval.Ticks;
49  _nextRefillTimeTicks = _timeProvider.GetUtcNow().Ticks + _refillIntervalTicks;
50  }
51 
52  /// <summary>
53  /// Computes the number of new tokens made available to the bucket for consumption by determining the
54  /// number of time intervals that have passed and multiplying by the number of tokens to refill for
55  /// each time interval.
56  /// </summary>
57  public long Refill()
58  {
59  lock (_sync)
60  {
61  var currentTimeTicks = _timeProvider.GetUtcNow().Ticks;
62  if (currentTimeTicks < _nextRefillTimeTicks)
63  {
64  return 0L;
65  }
66 
67  // determine number of time increments that have passed
68  var deltaTimeTicks = currentTimeTicks - _nextRefillTimeTicks;
69  var intervalsElapsed = 1 + Math.Max(deltaTimeTicks / _refillIntervalTicks, 0);
70 
71  // update next refill time as quantized via the number of passed intervals
72  _nextRefillTimeTicks += _refillIntervalTicks * intervalsElapsed;
73 
74  // refill by the tokens per interval times the number of intervals elapsed
75  return _refillAmount * intervalsElapsed;
76  }
77  }
78  }
79 }