23 using System.Collections.Generic;
29 using Newtonsoft.Json;
39 public partial class QCAlgorithm
41 private readonly Dictionary<IntPtr, PythonIndicator> _pythonIndicators =
new Dictionary<IntPtr, PythonIndicator>();
69 return AddData(type, ticker, resolution,
null,
false, 1m);
93 return AddData(type, underlying, resolution,
null,
false, 1m);
109 public Security AddData(PyObject type,
string ticker,
Resolution? resolution, DateTimeZone timeZone,
bool fillForward =
false, decimal leverage = 1.0m)
111 return AddData(type.CreateType(), ticker, resolution, timeZone, fillForward, leverage);
137 return AddData(type.CreateType(), underlying, resolution, timeZone, fillForward, leverage);
153 public Security AddData(Type dataType,
string ticker,
Resolution? resolution, DateTimeZone timeZone,
bool fillForward =
false, decimal leverage = 1.0m)
156 var baseInstance = dataType.GetBaseDataInstance();
157 if (!baseInstance.RequiresMapping())
162 return AddDataImpl(dataType, symbol, resolution, timeZone, fillForward, leverage);
168 throw new InvalidOperationException($
"The custom data type {dataType.Name} requires mapping, but the provided ticker is not in the cache. " +
169 $
"Please add this custom data type using a Symbol or perform this call after " +
170 $
"a Security has been added using AddEquity, AddForex, AddCfd, AddCrypto, AddFuture, AddOption or AddSecurity. " +
171 $
"An example use case can be found in CustomDataAddDataRegressionAlgorithm");
174 return AddData(dataType, underlying, resolution, timeZone, fillForward, leverage);
198 public Security AddData(Type dataType,
Symbol underlying,
Resolution? resolution =
null, DateTimeZone timeZone =
null,
bool fillForward =
false, decimal leverage = 1.0m)
201 return AddDataImpl(dataType, symbol, resolution, timeZone, fillForward, leverage);
221 var dataType = type.CreateType();
225 SetDatabaseEntries(key, properties, exchangeHours);
228 return AddData(dataType, ticker, resolution,
null, fillForward, leverage);
241 Func<OptionFilterUniverse, OptionFilterUniverse> optionFilterUniverse;
242 if (!optionFilter.TryConvertToDelegate(out optionFilterUniverse))
244 throw new ArgumentException(
"Option contract universe filter provided is not a function");
262 private Security AddDataImpl(Type dataType,
Symbol symbol,
Resolution? resolution, DateTimeZone timeZone,
bool fillForward, decimal leverage)
267 if (timeZone !=
null)
280 extendedMarketHours:
true);
283 return AddToUserDefinedUniverse(security,
new List<SubscriptionDataConfig> { config });
291 [DocumentationAttribute(Universes)]
294 Func<IEnumerable<Fundamental>,
object> fundamentalSelector;
297 if (pyObject.TryCreateType(out var type))
302 else if(pyObject.TryConvert(out universe))
306 else if (pyObject.TryConvert(out universe, allowPythonDerivative:
true))
310 else if (pyObject.TryConvertToDelegate(out fundamentalSelector))
318 throw new ArgumentException($
"QCAlgorithm.AddUniverse: {pyObject.Repr()} is not a valid argument.");
332 Func<IEnumerable<CoarseFundamental>,
object> coarseFunc;
333 Func<IEnumerable<FineFundamental>,
object> fineFunc;
345 if (pyfine.TryConvertToDelegate(out coarseFunc))
347 return AddUniverse(dateRule, coarseFunc.ConvertToUniverseSelectionSymbolDelegate());
350 catch (InvalidCastException)
355 if (pyObject.TryCreateType(out var type))
359 else if (pyObject.TryConvert(out
Universe universe) && pyfine.TryConvertToDelegate(out fineFunc))
361 return AddUniverse(universe, fineFunc.ConvertToUniverseSelectionSymbolDelegate());
363 else if (pyObject.TryConvertToDelegate(out coarseFunc) && pyfine.TryConvertToDelegate(out fineFunc))
365 return AddUniverse(coarseFunc.ConvertToUniverseSelectionSymbolDelegate(),
366 fineFunc.ConvertToUniverseSelectionSymbolDelegate());
372 throw new ArgumentException($
"QCAlgorithm.AddUniverse: {pyObject.Repr()} or {pyfine.Repr()} is not a valid argument.");
387 var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
388 return AddUniverse(name, resolution, selector.ConvertToUniverseSelectionStringDelegate());
400 var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
401 return AddUniverse(name, selector.ConvertToUniverseSelectionStringDelegate());
416 var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
417 return AddUniverse(securityType, name, resolution, market, universeSettings, selector.ConvertToUniverseSelectionStringDelegate());
431 return AddUniverse(
T.CreateType(),
null, name,
null,
null,
null, selector);
446 return AddUniverse(
T.CreateType(),
null, name, resolution,
null,
null, selector);
462 return AddUniverse(
T.CreateType(),
null, name, resolution,
null, universeSettings, selector);
477 return AddUniverse(
T.CreateType(),
null, name,
null,
null, universeSettings, selector);
493 return AddUniverse(
T.CreateType(), securityType, name, resolution, market,
null, selector);
509 return AddUniverse(
T.CreateType(), securityType, name, resolution, market, universeSettings, selector);
525 if (market.IsNullOrEmpty())
530 Func<IEnumerable<BaseData>, IEnumerable<Symbol>> wrappedSelector =
null;
531 if (pySelector !=
null)
533 var selector = pySelector.ConvertToDelegate<Func<IEnumerable<IBaseData>,
object>>();
534 wrappedSelector = baseDatas =>
536 var result = selector(baseDatas);
541 return ((
object[])result).Select(x => x is
Symbol symbol ? symbol :
QuantConnect.
Symbol.
Create((
string)x, securityType.Value, market, baseDataType: dataType));
544 return AddUniverseSymbolSelector(dataType, name, resolution, market, universeSettings, wrappedSelector);
556 Func<OptionFilterUniverse, OptionFilterUniverse> convertedOptionChain;
559 if (universe.TryConvert(out universeToChain) && optionFilter.TryConvertToDelegate(out convertedOptionChain))
567 throw new ArgumentException($
"QCAlgorithm.AddChainedEquityOptionUniverseSelectionModel: {universe.Repr()} or {optionFilter.Repr()} is not a valid argument.");
616 if (pyObject.TryConvert(out dataConsolidator))
635 TimeSpan? timeSpan = pyObject.As<TimeSpan>();
636 if (timeSpan !=
default(TimeSpan))
644 throw new ArgumentException(
"Invalid third argument, should be either a valid consolidator or timedelta object. The following exception was thrown: ", e);
669 if (indicator.TryConvert(out indicatorDataPoint))
671 RegisterIndicator(symbol, indicatorDataPoint, consolidator, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
674 else if (indicator.TryConvert(out indicatorDataBar))
676 RegisterIndicator(symbol, indicatorDataBar, consolidator, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
679 else if (indicator.TryConvert(out indicatorTradeBar))
681 RegisterIndicator(symbol, indicatorTradeBar, consolidator, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
685 RegisterIndicator(symbol, WrapPythonIndicator(indicator), consolidator, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
703 WarmUpIndicator(symbol, indicatorDataPoint, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
708 WarmUpIndicator(symbol, indicatorDataBar, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
713 WarmUpIndicator(symbol, indicatorTradeBar, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
717 WarmUpIndicator(symbol, WrapPythonIndicator(indicator), resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
733 WarmUpIndicator(symbol, indicatorDataPoint, period, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
738 WarmUpIndicator(symbol, indicatorDataBar, period, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
743 WarmUpIndicator(symbol, indicatorTradeBar, period, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
747 WarmUpIndicator(symbol, WrapPythonIndicator(indicator), period, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
757 public void Plot(
string series, PyObject pyObject)
763 Plot(series, indicator);
769 var value = (((dynamic)pyObject).Value as PyObject).GetAndDispose<decimal>();
774 var pythonType = pyObject.GetPythonType().Repr();
775 throw new ArgumentException($
"QCAlgorithm.Plot(): The last argument should be a QuantConnect Indicator object, {pythonType} was provided.");
793 Plot(chart,
new[] { first, second, third, fourth }.Where(x => x !=
null).ToArray());
808 Plot(chart,
new[] { first, second, third, fourth }.Where(x => x !=
null).ToArray());
823 Plot(chart,
new[] { first, second, third, fourth }.Where(x => x !=
null).ToArray());
831 public void PlotIndicator(
string chart, PyObject first, PyObject second =
null, PyObject third =
null, PyObject fourth =
null)
833 var array = GetIndicatorArray(first, second, third, fourth);
834 PlotIndicator(chart, array[0], array[1], array[2], array[3]);
842 public void PlotIndicator(
string chart,
bool waitForReady, PyObject first, PyObject second =
null, PyObject third =
null, PyObject fourth =
null)
844 var array = GetIndicatorArray(first, second, third, fourth);
845 PlotIndicator(chart, waitForReady, array[0], array[1], array[2], array[3]);
860 var resolution = GetSubscription(symbol).
Resolution;
882 return filteredIdentity;
898 var name = $
"{symbol}({fieldName ?? "close
"}_{resolution.ToStringInvariant(null)})";
903 return filteredIdentity;
921 public PyObject
History(PyObject tickers,
int periods,
Resolution? resolution =
null,
bool? fillForward =
null,
923 int? contractDepthOffset =
null)
925 if (tickers.TryConvert<
Universe>(out var universe))
927 resolution ??= universe.Configuration.Resolution;
928 var requests = CreateBarCountHistoryRequests(
new[] { universe.Symbol }, universe.DataType, periods, resolution, fillForward, extendedMarketHours,
929 dataMappingMode, dataNormalizationMode, contractDepthOffset);
933 if (tickers.TryCreateType(out var type))
935 var requests = CreateBarCountHistoryRequests(
Securities.
Keys, type, periods, resolution, fillForward, extendedMarketHours,
936 dataMappingMode, dataNormalizationMode, contractDepthOffset);
940 var symbols = tickers.ConvertToSymbolEnumerable().ToArray();
941 var dataType =
Extensions.GetCustomDataTypeFromSymbols(symbols);
943 return GetDataFrame(
History(symbols, periods, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
944 contractDepthOffset), dataType);
962 public PyObject
History(PyObject tickers, TimeSpan span,
Resolution? resolution =
null,
bool? fillForward =
null,
964 int? contractDepthOffset =
null)
966 return History(tickers,
Time - span,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
984 public PyObject
History(PyObject tickers, DateTime start, DateTime end,
Resolution? resolution =
null,
bool? fillForward =
null,
986 int? contractDepthOffset =
null)
988 if (tickers.TryConvert<
Universe>(out var universe))
990 resolution ??= universe.Configuration.Resolution;
991 var requests =
CreateDateRangeHistoryRequests(
new[] { universe.Symbol }, universe.DataType, start, end, resolution, fillForward, extendedMarketHours,
992 dataMappingMode, dataNormalizationMode, contractDepthOffset);
996 if (tickers.TryCreateType(out var type))
999 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1003 var symbols = tickers.ConvertToSymbolEnumerable().ToArray();
1004 var dataType =
Extensions.GetCustomDataTypeFromSymbols(symbols);
1006 return GetDataFrame(
History(symbols, start, end, resolution, fillForward, extendedMarketHours, dataMappingMode,
1007 dataNormalizationMode, contractDepthOffset), dataType);
1026 public PyObject
History(PyObject type, PyObject tickers, DateTime start, DateTime end,
Resolution? resolution =
null,
1027 bool? fillForward =
null,
bool? extendedMarketHours =
null,
DataMappingMode? dataMappingMode =
null,
1030 var symbols = tickers.ConvertToSymbolEnumerable();
1031 var requestedType = type.CreateType();
1033 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1054 public PyObject
History(PyObject type, PyObject tickers,
int periods,
Resolution? resolution =
null,
bool? fillForward =
null,
1056 int? contractDepthOffset =
null)
1058 var symbols = tickers.ConvertToSymbolEnumerable();
1059 var requestedType = type.CreateType();
1060 CheckPeriodBasedHistoryRequestResolution(symbols, resolution, requestedType);
1062 var requests = CreateBarCountHistoryRequests(symbols, requestedType, periods, resolution, fillForward, extendedMarketHours,
1063 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1084 public PyObject
History(PyObject type, PyObject tickers, TimeSpan span,
Resolution? resolution =
null,
bool? fillForward =
null,
1086 int? contractDepthOffset =
null)
1088 return History(type, tickers,
Time - span,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
1089 contractDepthOffset);
1108 public PyObject
History(PyObject type,
Symbol symbol, DateTime start, DateTime end,
Resolution? resolution =
null,
bool? fillForward =
null,
1110 int? contractDepthOffset =
null)
1112 return History(type.CreateType(), symbol, start, end, resolution, fillForward, extendedMarketHours, dataMappingMode,
1113 dataNormalizationMode, contractDepthOffset);
1131 private PyObject
History(Type type,
Symbol symbol, DateTime start, DateTime end,
Resolution? resolution,
bool? fillForward,
1133 int? contractDepthOffset)
1136 extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
1137 if (requests.IsNullOrEmpty())
1139 throw new ArgumentException($
"No history data could be fetched. " +
1140 $
"This could be due to the specified security not being of the requested type. Symbol: {symbol} Requested Type: {type.Name}");
1162 [DocumentationAttribute(HistoricalData)]
1165 int? contractDepthOffset =
null)
1167 var managedType = type.CreateType();
1168 resolution = GetResolution(symbol, resolution, managedType);
1169 CheckPeriodBasedHistoryRequestResolution(
new[] { symbol }, resolution, managedType);
1171 var marketHours = GetMarketHours(symbol, managedType);
1172 var start = _historyRequestFactory.
GetStartTimeAlgoTz(symbol, periods, resolution.
Value, marketHours.ExchangeHours,
1173 marketHours.DataTimeZone, managedType, extendedMarketHours);
1174 return History(managedType, symbol, start,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
1175 contractDepthOffset);
1196 int? contractDepthOffset =
null)
1198 return History(type, symbol,
Time - span,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
1199 contractDepthOffset);
1214 var pyBenchmark =
PythonUtil.ToFunc<DateTime, decimal>(benchmark);
1215 if (pyBenchmark !=
null)
1233 if (!model.TryConvert(out brokerageModel))
1279 if (securityInitializer1 !=
null)
1297 public string Download(
string address, PyObject headers) =>
Download(address, headers,
null,
null);
1310 public string Download(
string address, PyObject headers,
string userName,
string password)
1312 var dict =
new Dictionary<string, string>();
1314 if (headers !=
null)
1320 if (PyDict.IsDictType(headers))
1322 using var iterator = headers.GetIterator();
1323 foreach (PyObject pyKey
in iterator)
1325 var key = (string)pyKey.AsManagedObject(typeof(
string));
1326 var value = (string)headers.GetItem(pyKey).AsManagedObject(typeof(
string));
1327 dict.Add(key, value);
1332 throw new ArgumentException($
"QCAlgorithm.Fetch(): Invalid argument. {headers.Repr()} is not a dict");
1336 return Download(address, dict, userName, password);
1348 Debug(message.ToSafeString());
1360 Error(message.ToSafeString());
1370 public void Log(PyObject message)
1372 Log(message.ToSafeString());
1382 Quit(message.ToSafeString());
1395 return Consolidate(symbol, period,
null, handler);
1410 var type = GetSubscription(symbol, tickType).
Type;
1414 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<TradeBar>>());
1419 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<QuoteBar>>());
1422 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<BaseData>>());
1435 return Consolidate(symbol, period,
null, handler);
1450 var type = GetSubscription(symbol, tickType).
Type;
1454 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<TradeBar>>());
1459 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<QuoteBar>>());
1462 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<BaseData>>());
1475 return Consolidate(symbol, calendar,
null, handler);
1486 return Schedule.TrainingNow(trainingCode);
1499 return Schedule.Training(dateRule, timeRule, trainingCode);
1514 var type = GetSubscription(symbol, tickType).
Type;
1518 return Consolidate(symbol, calendar, tickType, handler.ConvertToDelegate<Action<TradeBar>>());
1523 return Consolidate(symbol, calendar, tickType, handler.ConvertToDelegate<Action<QuoteBar>>());
1526 return Consolidate(symbol, calendar, tickType, handler.ConvertToDelegate<Action<BaseData>>());
1541 var symbols = symbol.ConvertToSymbolEnumerable();
1544 return IndicatorHistory(indicatorDataPoint, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
1548 return IndicatorHistory(indicatorBar, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
1552 return IndicatorHistory(indicatorTradeBar, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
1554 return IndicatorHistory(WrapPythonIndicator(indicator), symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
1585 var symbols = symbol.ConvertToSymbolEnumerable();
1588 return IndicatorHistory(indicatorDataPoint, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
1592 return IndicatorHistory(indicatorBar, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
1596 return IndicatorHistory(indicatorTradeBar, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
1598 return IndicatorHistory(WrapPythonIndicator(indicator), symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
1612 return IndicatorHistory(indicatorDataPoint, history, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
1616 return IndicatorHistory(indicatorBar, history, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
1620 return IndicatorHistory(indicatorTradeBar, history, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
1622 return IndicatorHistory(WrapPythonIndicator(indicator), history, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
1633 public List<OrderTicket>
Liquidate(PyObject symbols,
bool asynchronous =
false,
string tag =
"Liquidated",
IOrderProperties orderProperties =
null)
1635 return Liquidate(symbols.ConvertToSymbolEnumerable(), asynchronous, tag, orderProperties);
1651 return commandWrapper.Run(
this);
1667 return OptionChains(symbols.ConvertToSymbolEnumerable());
1675 public string Link(PyObject command)
1677 using var _ = Py.GIL();
1680 using var pyType = command.GetPythonType();
1683 var payload = JsonConvert.DeserializeObject<Dictionary<string, object>>(strResult);
1684 return CommandLink(wrappedType.Name, payload);
1692 private Type GetIndicatorBaseType(Type type)
1694 if (type.BaseType == typeof(
object))
1698 return GetIndicatorBaseType(type.BaseType);
1705 private dynamic[] GetIndicatorArray(PyObject first, PyObject second =
null, PyObject third =
null, PyObject fourth =
null)
1709 var array =
new[] {first, second, third, fourth}
1713 if (x ==
null)
return null;
1716 return x.GetPythonType().TryConvert(out type)
1717 ? x.AsManagedObject(type)
1718 : WrapPythonIndicator(x);
1722 var types = array.Where(x => x !=
null).Select(x => GetIndicatorBaseType(x.GetType())).Distinct();
1724 if (types.Count() > 1)
1726 throw new Exception(
"QCAlgorithm.GetIndicatorArray(). All indicators must be of the same type: data point, bar or tradebar.");
1742 if (!_pythonIndicators.TryGetValue(pyObject.Handle, out pythonIndicator))
1744 pyObject.TryConvert(out pythonIndicator);
1747 if (pythonIndicator ==
null)
1753 _pythonIndicators.Add(pyObject.Handle, pythonIndicator);
1756 return pythonIndicator;
1762 protected PyObject
GetDataFrame(IEnumerable<Slice> data, Type dataType =
null)
1765 return TryCleanupCollectionDataFrame(dataType, history);
1775 return TryCleanupCollectionDataFrame(typeof(
T), history);
1778 private IEnumerable<T> RemoveMemoizing<T>(IEnumerable<T> data)
1781 if (memoizingEnumerable !=
null)
1785 memoizingEnumerable.
Enabled =
false;
1790 private PyObject TryCleanupCollectionDataFrame(Type dataType, PyObject history)
1796 dynamic dynamic = history;
1801 using var columns =
new PySequence(dynamic.columns);
1802 using var dataKey =
"data".ToPython();
1803 if (columns.Contains(dataKey))
1805 history = dynamic[
"data"];
1809 dynamic.index = dynamic.index.droplevel(
"symbol");