Lean  $LEAN_TAG$
OpenInterestConsolidator.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 using Python.Runtime;
19 
21 {
22  /// <summary>
23  /// Type capable of consolidating open interest
24  /// </summary>
25  public class OpenInterestConsolidator : PeriodCountConsolidatorBase<Tick, OpenInterest>
26  {
27  private bool _hourOrDailyConsolidation;
28  // Keep track of the last input to detect hour or date change
29  private Tick _lastInput;
30 
31  /// <summary>
32  /// Create a new OpenInterestConsolidator for the desired resolution
33  /// </summary>
34  /// <param name="resolution">The resolution desired</param>
35  /// <returns>A consolidator that produces data on the resolution interval</returns>
37  {
38  return new OpenInterestConsolidator(resolution.ToTimeSpan());
39  }
40 
41  /// <summary>
42  /// Creates a consolidator to produce a new 'OpenInterest' representing the period
43  /// </summary>
44  /// <param name="period">The minimum span of time before emitting a consolidated bar</param>
45  public OpenInterestConsolidator(TimeSpan period)
46  : base(period)
47  {
48  _hourOrDailyConsolidation = period >= Time.OneHour;
49  }
50 
51  /// <summary>
52  /// Creates a consolidator to produce a new 'OpenInterest' representing the last count pieces of data
53  /// </summary>
54  /// <param name="maxCount">The number of pieces to accept before emitting a consolidated bar</param>
55  public OpenInterestConsolidator(int maxCount)
56  : base(maxCount)
57  {
58  }
59 
60  /// <summary>
61  /// Creates a consolidator to produce a new 'OpenInterest' representing the last count pieces of data or the period, whichever comes first
62  /// </summary>
63  /// <param name="maxCount">The number of pieces to accept before emitting a consolidated bar</param>
64  /// <param name="period">The minimum span of time before emitting a consolidated bar</param>
65  public OpenInterestConsolidator(int maxCount, TimeSpan period)
66  : base(maxCount, period)
67  {
68  }
69 
70  /// <summary>
71  /// Creates a consolidator to produce a new 'OpenInterest'
72  /// </summary>
73  /// <param name="func">Func that defines the start time of a consolidated data</param>
74  public OpenInterestConsolidator(Func<DateTime, CalendarInfo> func)
75  : base(func)
76  {
77  }
78 
79  /// <summary>
80  /// Creates a consolidator to produce a new 'OpenInterest'
81  /// </summary>
82  /// <param name="pyfuncobj">Python function object that defines the start time of a consolidated data</param>
83  public OpenInterestConsolidator(PyObject pyfuncobj)
84  : base(pyfuncobj)
85  {
86  }
87 
88 
89  /// <summary>
90  /// Determines whether or not the specified data should be processed
91  /// </summary>
92  /// <param name="data">The data to check</param>
93  /// <returns>True if the consolidator should process this data, false otherwise</returns>
94  protected override bool ShouldProcess(Tick data)
95  {
96  return data.TickType == TickType.OpenInterest;
97  }
98 
99  /// <summary>
100  /// Aggregates the new 'data' into the 'workingBar'. The 'workingBar' will be
101  /// null following the event firing
102  /// </summary>
103  /// <param name="workingBar">The bar we're building, null if the event was just fired and we're starting a new OI bar</param>
104  /// <param name="data">The new data</param>
105  protected override void AggregateBar(ref OpenInterest workingBar, Tick data)
106  {
107  if (workingBar == null)
108  {
109  workingBar = new OpenInterest
110  {
111  Symbol = data.Symbol,
112  Time = _hourOrDailyConsolidation ? data.EndTime : GetRoundedBarTime(data),
113  Value = data.Value
114  };
115 
116  }
117  else
118  {
119  //Update the working bar
120  workingBar.Value = data.Value;
121 
122  // If we are consolidating hourly or daily, we need to update the time of the working bar
123  // for the end time to match the last data point time
124  if (_hourOrDailyConsolidation)
125  {
126  workingBar.Time = data.EndTime;
127  }
128  }
129  }
130 
131  /// <summary>
132  /// Updates this consolidator with the specified data. This method is
133  /// responsible for raising the DataConsolidated event.
134  /// It will check for date or hour change and force consolidation if needed.
135  /// </summary>
136  /// <param name="data">The new data for the consolidator</param>
137  public override void Update(Tick data)
138  {
139  if (_lastInput != null &&
140  _hourOrDailyConsolidation &&
141  // Detect hour or date change
142  ((Period == Time.OneHour && data.EndTime.Hour != _lastInput.EndTime.Hour) ||
143  (Period == Time.OneDay && data.EndTime.Date != _lastInput.EndTime.Date)))
144  {
145  // Date or hour change, force consolidation, no need to wait for the whole period to pass.
146  // Force consolidation by scanning at a time after the end of the period
147  Scan(_lastInput.EndTime.Add(Period.Value + Time.OneSecond));
148  }
149 
150  base.Update(data);
151  _lastInput = data;
152  }
153  }
154 }