Lean  $LEAN_TAG$
PythonSlice.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;
17 using QuantConnect.Data;
20 using System.Collections.Generic;
21 
22 namespace QuantConnect.Python
23 {
24  /// <summary>
25  /// Provides a data structure for all of an algorithm's data at a single time step
26  /// </summary>
27  public class PythonSlice : Slice
28  {
29  private readonly Slice _slice;
30  private static readonly PyObject _converter;
31 
32  static PythonSlice()
33  {
34  using (Py.GIL())
35  {
36  // Python Data class: Converts custom data (PythonData) into a python object'''
37  _converter = PyModule.FromString("converter",
38  "class Data(object):\n" +
39  " def __init__(self, data):\n" +
40  " self.data = data\n" +
41  " members = [attr for attr in dir(data) if not callable(attr) and not attr.startswith(\"__\")]\n" +
42  " for member in members:\n" +
43  " setattr(self, member, getattr(data, member))\n" +
44  " for kvp in data.GetStorageDictionary():\n" +
45  " name = kvp.Key.replace('-',' ').replace('.',' ').title().replace(' ', '')\n" +
46  " value = kvp.Value if isinstance(kvp.Value, float) else kvp.Value\n" +
47  " setattr(self, name, value)\n" +
48 
49  " def __str__(self):\n" +
50  " return self.data.ToString()");
51  }
52  }
53 
54  /// <summary>
55  /// Initializes a new instance of the <see cref="PythonSlice"/> class
56  /// </summary>
57  /// <param name="slice">slice object to wrap</param>
58  public PythonSlice(Slice slice)
59  : base(slice)
60  {
61  _slice = slice;
62  }
63 
64  /// <summary>
65  /// Gets the data of the specified symbol and type.
66  /// </summary>
67  /// <param name="type">The type of data we seek</param>
68  /// <param name="symbol">The specific symbol was seek</param>
69  /// <returns>The data for the requested symbol</returns>
70  public dynamic Get(PyObject type, Symbol symbol)
71  {
72  return GetImpl(type.CreateType(), _slice)[symbol];
73  }
74 
75  /// <summary>
76  /// Gets the data of the specified symbol and type.
77  /// </summary>
78  /// <param name="type">The type of data we seek</param>
79  /// <returns>The data for the requested symbol</returns>
80  public PyObject Get(PyObject type)
81  {
82  var result = GetImpl(type.CreateType(), _slice) as object;
83  using (Py.GIL())
84  {
85  return result.ToPython();
86  }
87  }
88 
89  /// <summary>
90  /// Gets the number of symbols held in this slice
91  /// </summary>
92  public override int Count
93  {
94  get { return _slice.Count; }
95  }
96 
97  /// <summary>
98  /// Gets all the symbols in this slice
99  /// </summary>
100  public override IReadOnlyList<Symbol> Keys
101  {
102  get { return _slice.Keys; }
103  }
104 
105  /// <summary>
106  /// Gets a list of all the data in this slice
107  /// </summary>
108  public override IReadOnlyList<BaseData> Values
109  {
110  get { return _slice.Values; }
111  }
112 
113  /// <summary>
114  /// Gets the data corresponding to the specified symbol. If the requested data
115  /// is of <see cref="MarketDataType.Tick"/>, then a <see cref="List{Tick}"/> will
116  /// be returned, otherwise, it will be the subscribed type, for example, <see cref="TradeBar"/>
117  /// or event <see cref="UnlinkedData"/> for custom data.
118  /// </summary>
119  /// <param name="symbol">The data's symbols</param>
120  /// <returns>The data for the specified symbol</returns>
121  public override dynamic this[Symbol symbol]
122  {
123  get
124  {
125  var data = _slice[symbol];
126 
127  var dynamicData = data as DynamicData;
128  if (dynamicData != null)
129  {
130  try
131  {
132  using (Py.GIL())
133  {
134  return _converter.InvokeMethod("Data", new[] { dynamicData.ToPython() });
135  }
136  }
137  catch
138  {
139  // NOP
140  }
141  }
142  return data;
143  }
144  }
145 
146  /// <summary>
147  /// Determines whether this instance contains data for the specified symbol
148  /// </summary>
149  /// <param name="symbol">The symbol we seek data for</param>
150  /// <returns>True if this instance contains data for the symbol, false otherwise</returns>
151  public override bool ContainsKey(Symbol symbol)
152  {
153  return _slice.ContainsKey(symbol);
154  }
155 
156  /// <summary>
157  /// Gets the data associated with the specified symbol
158  /// </summary>
159  /// <param name="symbol">The symbol we want data for</param>
160  /// <param name="data">The data for the specifed symbol, or null if no data was found</param>
161  /// <returns>True if data was found, false otherwise</returns>
162  public override bool TryGetValue(Symbol symbol, out dynamic data)
163  {
164  return _slice.TryGetValue(symbol, out data);
165  }
166  }
167 }