Lean  $LEAN_TAG$
UniverseSelectionModelPythonWrapper.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 Python.Runtime;
18 using System;
19 using System.Collections.Generic;
21 using QuantConnect.Python;
22 
24 {
25  /// <summary>
26  /// Provides an implementation of <see cref="IUniverseSelectionModel"/> that wraps a <see cref="PyObject"/> object
27  /// </summary>
29  {
30  private readonly BasePythonWrapper<UniverseSelectionModel> _model;
31  private readonly bool _modelHasGetNextRefreshTime;
32 
33  /// <summary>
34  /// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
35  /// </summary>
36  public override DateTime GetNextRefreshTimeUtc()
37  {
38  if (!_modelHasGetNextRefreshTime)
39  {
40  return DateTime.MaxValue;
41  }
42 
43  return _model.InvokeMethod<DateTime>(nameof(GetNextRefreshTimeUtc));
44  }
45 
46  /// <summary>
47  /// Constructor for initialising the <see cref="IUniverseSelectionModel"/> class with wrapped <see cref="PyObject"/> object
48  /// </summary>
49  /// <param name="model">Model defining universes for the algorithm</param>
50  public UniverseSelectionModelPythonWrapper(PyObject model)
51  {
52  _model = new BasePythonWrapper<UniverseSelectionModel>(model, false);
53  using (Py.GIL())
54  {
55  _modelHasGetNextRefreshTime = _model.HasAttr(nameof(IUniverseSelectionModel.GetNextRefreshTimeUtc));
56 
57  foreach (var attributeName in new[] { "CreateUniverses" })
58  {
59  if (!_model.HasAttr(attributeName))
60  {
61  throw new NotImplementedException($"UniverseSelectionModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
62  }
63  }
64  }
65  }
66 
67  /// <summary>
68  /// Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
69  /// </summary>
70  /// <param name="algorithm">The algorithm instance to create universes for</param>
71  /// <returns>The universes to be used by the algorithm</returns>
72  public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
73  {
74  using (Py.GIL())
75  {
76  var universes = _model.InvokeMethod(nameof(CreateUniverses), algorithm);
77  var iterator = universes.GetIterator();
78  foreach (PyObject universe in iterator)
79  {
80  yield return universe.GetAndDispose<Universe>();
81  }
82  iterator.Dispose();
83  universes.Dispose();
84  }
85  }
86  }
87 }