22 using System.Collections.Generic;
32 private static dynamic _pandas;
33 private static PyObject _concat;
42 var pandas = Py.Import(
"pandas");
45 _concat = pandas.GetAttr(
"concat");
55 public PyObject
GetDataFrame(IEnumerable<Slice> data, Type dataType =
null)
58 var sliceDataDict =
new Dictionary<SecurityIdentifier, PandasData>();
61 var requestedTick = dataType ==
null || dataType == typeof(
Tick) || dataType == typeof(
OpenInterest);
62 var requestedTradeBar = dataType ==
null || dataType == typeof(
TradeBar);
63 var requestedQuoteBar = dataType ==
null || dataType == typeof(
QuoteBar);
65 foreach (var slice
in data)
67 AddSliceDataTypeDataToDict(slice, requestedTick, requestedTradeBar, requestedQuoteBar, sliceDataDict, ref maxLevels, dataType);
70 return CreateDataFrame(sliceDataDict, maxLevels);
80 public PyObject
GetDataFrame<T>(IEnumerable<T> data,
bool symbolOnlyIndex =
false)
83 var pandasDataBySymbol =
new Dictionary<SecurityIdentifier, PandasData>();
85 foreach (var datum
in data)
87 var pandasData = GetPandasDataValue(pandasDataBySymbol, datum.Symbol, datum, ref maxLevels);
88 pandasData.Add(datum);
95 return CreateDataFrame(pandasDataBySymbol,
97 maxLevels: symbolOnlyIndex ? 1 : 2,
101 filterMissingValueColumns: pandasDataBySymbol.Count <= 1);
113 var pyDict =
new PyDict();
115 foreach (var kvp
in data)
117 AddSeriesToPyDict(kvp.Key, kvp.Value, pyDict);
120 return MakeIndicatorDataFrame(pyDict);
133 using var inputPythonType = data.GetPythonType();
134 var inputTypeStr = inputPythonType.ToString();
135 var targetTypeStr = nameof(PyDict);
136 PyObject currentKvp =
null;
140 using var pyDictData =
new PyDict(data);
141 using var seriesPyDict =
new PyDict();
143 targetTypeStr = $
"{nameof(String)}: {nameof(List<IndicatorDataPoint>)}";
145 foreach (var kvp
in pyDictData.Items())
148 AddSeriesToPyDict(kvp[0].As<string>(), kvp[1].As<List<IndicatorDataPoint>>(), seriesPyDict);
151 return MakeIndicatorDataFrame(seriesPyDict);
155 if (currentKvp !=
null)
157 inputTypeStr = $
"{currentKvp[0].GetPythonType()}: {currentKvp[1].GetPythonType()}";
178 return _pandas.Repr();
185 private static PyObject CreateDataFrame(Dictionary<SecurityIdentifier, PandasData> dataBySymbol,
int maxLevels = 2,
bool sort =
true,
186 bool filterMissingValueColumns =
true)
190 if (dataBySymbol.Count == 0)
192 return _pandas.DataFrame();
195 var dataFrames = dataBySymbol.Select(x => x.Value.ToPandasDataFrame(maxLevels, filterMissingValueColumns));
198 foreach (var df
in dataFrames)
219 public static PyObject
ConcatDataFrames(IEnumerable<PyObject> dataFrames, IEnumerable<object> keys =
null, IEnumerable<string> names =
null,
220 bool sort =
true,
bool dropna =
true)
224 var dataFramesList = dataFrames.ToList();
225 if (dataFramesList.Count == 0)
227 return _pandas.DataFrame();
230 using var pyDataFrames = dataFramesList.ToPyListUnSafe();
231 using var kwargs = Py.kw(
"sort", sort);
232 PyList pyKeys =
null;
233 PyList pyNames =
null;
235 if (keys !=
null && names !=
null)
237 pyKeys = keys.ToPyListUnSafe();
238 pyNames = names.ToPyListUnSafe();
239 kwargs.SetItem(
"keys", pyKeys);
240 kwargs.SetItem(
"names", pyNames);
243 var result = _concat.Invoke(
new[] { pyDataFrames }, kwargs);
248 using var dropnaKwargs = Py.kw(
"axis", 1,
"inplace",
true,
"how",
"all");
249 result.GetAttr(
"dropna").Invoke(Array.Empty<PyObject>(), dropnaKwargs);
266 private void AddSeriesToPyDict(
string key, List<IndicatorDataPoint> points, PyDict pyDict)
268 var index =
new List<DateTime>();
269 var values =
new List<double>();
271 foreach (var point
in points)
273 index.Add(point.EndTime);
274 values.Add((
double) point.Value);
276 pyDict.SetItem(key.ToLowerInvariant(), _pandas.Series(values, index));
284 private PyObject MakeIndicatorDataFrame(PyDict pyDict)
286 return _pandas.DataFrame(pyDict, columns: pyDict.Keys().Select(x => x.As<
string>().ToLowerInvariant()).OrderBy(x => x));
293 private PandasData GetPandasDataValue(IDictionary<SecurityIdentifier, PandasData> sliceDataDict, Symbol symbol,
object data, ref
int maxLevels)
296 if (!sliceDataDict.TryGetValue(symbol.ID, out value))
298 sliceDataDict[symbol.ID] = value =
new PandasData(data);
299 maxLevels = Math.Max(maxLevels, value.Levels);
308 private void AddSliceDataTypeDataToDict(
Slice slice,
bool requestedTick,
bool requestedTradeBar,
bool requestedQuoteBar, IDictionary<SecurityIdentifier, PandasData> sliceDataDict, ref
int maxLevels, Type dataType =
null)
310 HashSet<SecurityIdentifier> _addedData =
null;
312 for (
int i = 0; i < slice.
AllData.Count; i++)
314 var baseData = slice.
AllData[i];
315 var value = GetPandasDataValue(sliceDataDict, baseData.Symbol, baseData, ref maxLevels);
317 if (value.IsCustomData)
323 var tick = requestedTick ? baseData as
Tick :
null;
326 if (!requestedTradeBar && !requestedQuoteBar && dataType !=
null && baseData.GetType().IsAssignableTo(dataType))
334 if (requestedTradeBar && requestedQuoteBar)
336 _addedData ??=
new();
337 if (!_addedData.Add(baseData.Symbol.ID))
345 var tradeBar = requestedTradeBar ? baseData as
TradeBar :
null;
346 if (tradeBar !=
null)
352 quoteBar = requestedQuoteBar ? baseData as
QuoteBar :
null;
353 if (quoteBar !=
null)
358 value.Add(tradeBar, quoteBar);