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;
925 public PyObject
History(PyObject tickers,
int periods,
Resolution? resolution =
null,
bool? fillForward =
null,
927 int? contractDepthOffset =
null,
bool flatten =
false)
929 if (tickers.TryConvert<
Universe>(out var universe))
931 resolution ??= universe.Configuration.Resolution;
932 var requests = CreateBarCountHistoryRequests(
new[] { universe.Symbol }, universe.DataType, periods, resolution, fillForward, extendedMarketHours,
933 dataMappingMode, dataNormalizationMode, contractDepthOffset);
937 if (tickers.TryCreateType(out var type))
939 var requests = CreateBarCountHistoryRequests(
Securities.
Keys, type, periods, resolution, fillForward, extendedMarketHours,
940 dataMappingMode, dataNormalizationMode, contractDepthOffset);
944 var symbols = tickers.ConvertToSymbolEnumerable().ToArray();
948 History(symbols, periods, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset),
972 public PyObject
History(PyObject tickers, TimeSpan span,
Resolution? resolution =
null,
bool? fillForward =
null,
974 int? contractDepthOffset =
null,
bool flatten =
false)
976 return History(tickers,
Time - span,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
977 contractDepthOffset, flatten);
999 public PyObject
History(PyObject tickers, DateTime start, DateTime end,
Resolution? resolution =
null,
bool? fillForward =
null,
1001 int? contractDepthOffset =
null,
bool flatten =
false)
1003 if (tickers.TryConvert<
Universe>(out var universe))
1005 resolution ??= universe.Configuration.Resolution;
1006 var requests =
CreateDateRangeHistoryRequests(
new[] { universe.Symbol }, universe.DataType, start, end, resolution, fillForward, extendedMarketHours,
1007 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1011 if (tickers.TryCreateType(out var type))
1014 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1018 var symbols = tickers.ConvertToSymbolEnumerable().ToArray();
1022 History(symbols, start, end, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset),
1047 public PyObject
History(PyObject type, PyObject tickers, DateTime start, DateTime end,
Resolution? resolution =
null,
1048 bool? fillForward =
null,
bool? extendedMarketHours =
null,
DataMappingMode? dataMappingMode =
null,
1049 DataNormalizationMode? dataNormalizationMode =
null,
int? contractDepthOffset =
null,
bool flatten =
false)
1051 var symbols = tickers.ConvertToSymbolEnumerable().ToArray();
1052 var requestedType = type.CreateType();
1054 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1079 public PyObject
History(PyObject type, PyObject tickers,
int periods,
Resolution? resolution =
null,
bool? fillForward =
null,
1081 int? contractDepthOffset =
null,
bool flatten =
false)
1083 var symbols = tickers.ConvertToSymbolEnumerable().ToArray();
1084 var requestedType = type.CreateType();
1085 CheckPeriodBasedHistoryRequestResolution(symbols, resolution, requestedType);
1087 var requests = CreateBarCountHistoryRequests(symbols, requestedType, periods, resolution, fillForward, extendedMarketHours,
1088 dataMappingMode, dataNormalizationMode, contractDepthOffset);
1113 public PyObject
History(PyObject type, PyObject tickers, TimeSpan span,
Resolution? resolution =
null,
bool? fillForward =
null,
1115 int? contractDepthOffset =
null,
bool flatten =
false)
1117 return History(type, tickers,
Time - span,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
1118 contractDepthOffset, flatten);
1141 public PyObject
History(PyObject type,
Symbol symbol, DateTime start, DateTime end,
Resolution? resolution =
null,
bool? fillForward =
null,
1143 int? contractDepthOffset =
null,
bool flatten =
false)
1145 return History(type.CreateType(), symbol, start, end, resolution, fillForward, extendedMarketHours, dataMappingMode,
1146 dataNormalizationMode, contractDepthOffset, flatten);
1168 private PyObject
History(Type type,
Symbol symbol, DateTime start, DateTime end,
Resolution? resolution,
bool? fillForward,
1170 int? contractDepthOffset,
bool flatten)
1173 extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
1174 if (requests.IsNullOrEmpty())
1176 throw new ArgumentException($
"No history data could be fetched. " +
1177 $
"This could be due to the specified security not being of the requested type. Symbol: {symbol} Requested Type: {type.Name}");
1203 [DocumentationAttribute(HistoricalData)]
1206 int? contractDepthOffset =
null,
bool flatten =
false)
1208 var managedType = type.CreateType();
1209 resolution = GetResolution(symbol, resolution, managedType);
1210 CheckPeriodBasedHistoryRequestResolution(
new[] { symbol }, resolution, managedType);
1212 var marketHours = GetMarketHours(symbol, managedType);
1213 var start = _historyRequestFactory.
GetStartTimeAlgoTz(symbol, periods, resolution.
Value, marketHours.ExchangeHours,
1214 marketHours.DataTimeZone, managedType, extendedMarketHours);
1215 return History(managedType, symbol, start,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
1216 contractDepthOffset, flatten);
1241 int? contractDepthOffset =
null,
bool flatten =
false)
1243 return History(type, symbol,
Time - span,
Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
1244 contractDepthOffset, flatten);
1259 var pyBenchmark =
PythonUtil.ToFunc<DateTime, decimal>(benchmark);
1260 if (pyBenchmark !=
null)
1278 if (!model.TryConvert(out brokerageModel))
1324 if (securityInitializer1 !=
null)
1342 public string Download(
string address, PyObject headers) =>
Download(address, headers,
null,
null);
1355 public string Download(
string address, PyObject headers,
string userName,
string password)
1357 var dict =
new Dictionary<string, string>();
1359 if (headers !=
null)
1365 if (PyDict.IsDictType(headers))
1367 using var iterator = headers.GetIterator();
1368 foreach (PyObject pyKey
in iterator)
1370 var key = (string)pyKey.AsManagedObject(typeof(
string));
1371 var value = (string)headers.GetItem(pyKey).AsManagedObject(typeof(
string));
1372 dict.Add(key, value);
1377 throw new ArgumentException($
"QCAlgorithm.Fetch(): Invalid argument. {headers.Repr()} is not a dict");
1381 return Download(address, dict, userName, password);
1393 Debug(message.ToSafeString());
1405 Error(message.ToSafeString());
1415 public void Log(PyObject message)
1417 Log(message.ToSafeString());
1427 Quit(message.ToSafeString());
1440 return Consolidate(symbol, period,
null, handler);
1455 var type = GetSubscription(symbol, tickType).
Type;
1459 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<TradeBar>>());
1464 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<QuoteBar>>());
1467 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<BaseData>>());
1480 return Consolidate(symbol, period,
null, handler);
1495 var type = GetSubscription(symbol, tickType).
Type;
1499 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<TradeBar>>());
1504 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<QuoteBar>>());
1507 return Consolidate(symbol, period, tickType, handler.ConvertToDelegate<Action<BaseData>>());
1520 return Consolidate(symbol, calendar,
null, handler);
1531 return Schedule.TrainingNow(trainingCode);
1544 return Schedule.Training(dateRule, timeRule, trainingCode);
1559 var type = GetSubscription(symbol, tickType).
Type;
1563 return Consolidate(symbol, calendar, tickType, handler.ConvertToDelegate<Action<TradeBar>>());
1568 return Consolidate(symbol, calendar, tickType, handler.ConvertToDelegate<Action<QuoteBar>>());
1571 return Consolidate(symbol, calendar, tickType, handler.ConvertToDelegate<Action<BaseData>>());
1586 var symbols = symbol.ConvertToSymbolEnumerable();
1589 return IndicatorHistory(indicatorDataPoint, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
1593 return IndicatorHistory(indicatorBar, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
1597 return IndicatorHistory(indicatorTradeBar, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
1599 return IndicatorHistory(WrapPythonIndicator(indicator), symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
1630 var symbols = symbol.ConvertToSymbolEnumerable();
1633 return IndicatorHistory(indicatorDataPoint, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
1637 return IndicatorHistory(indicatorBar, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
1641 return IndicatorHistory(indicatorTradeBar, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
1643 return IndicatorHistory(WrapPythonIndicator(indicator), symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
1657 return IndicatorHistory(indicatorDataPoint, history, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
1661 return IndicatorHistory(indicatorBar, history, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
1665 return IndicatorHistory(indicatorTradeBar, history, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
1667 return IndicatorHistory(WrapPythonIndicator(indicator), history, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
1678 public List<OrderTicket>
Liquidate(PyObject symbols,
bool asynchronous =
false,
string tag =
"Liquidated",
IOrderProperties orderProperties =
null)
1680 return Liquidate(symbols.ConvertToSymbolEnumerable(), asynchronous, tag, orderProperties);
1696 return commandWrapper.Run(
this);
1716 return OptionChains(symbols.ConvertToSymbolEnumerable(), flatten);
1724 public string Link(PyObject command)
1726 using var _ = Py.GIL();
1729 using var pyType = command.GetPythonType();
1732 var payload = JsonConvert.DeserializeObject<Dictionary<string, object>>(strResult);
1733 return CommandLink(wrappedType.Name, payload);
1741 private Type GetIndicatorBaseType(Type type)
1743 if (type.BaseType == typeof(
object))
1747 return GetIndicatorBaseType(type.BaseType);
1754 private dynamic[] GetIndicatorArray(PyObject first, PyObject second =
null, PyObject third =
null, PyObject fourth =
null)
1758 var array =
new[] {first, second, third, fourth}
1762 if (x ==
null)
return null;
1765 return x.GetPythonType().TryConvert(out type)
1766 ? x.AsManagedObject(type)
1767 : WrapPythonIndicator(x);
1771 var types = array.Where(x => x !=
null).Select(x => GetIndicatorBaseType(x.GetType())).Distinct();
1773 if (types.Count() > 1)
1775 throw new Exception(
"QCAlgorithm.GetIndicatorArray(). All indicators must be of the same type: data point, bar or tradebar.");
1791 if (!_pythonIndicators.TryGetValue(pyObject.Handle, out pythonIndicator))
1793 pyObject.TryConvert(out pythonIndicator);
1796 if (pythonIndicator ==
null)
1802 _pythonIndicators.Add(pyObject.Handle, pythonIndicator);
1805 return pythonIndicator;
1811 protected PyObject
GetDataFrame(IEnumerable<Slice> data,
bool flatten, Type dataType =
null)
1814 return flatten ? history : TryCleanupCollectionDataFrame(dataType, history);
1824 return flatten ? history : TryCleanupCollectionDataFrame(typeof(
T), history);
1827 private IEnumerable<T> RemoveMemoizing<T>(IEnumerable<T> data)
1830 if (memoizingEnumerable !=
null)
1834 memoizingEnumerable.
Enabled =
false;
1839 private PyObject TryCleanupCollectionDataFrame(Type dataType, PyObject history)
1845 dynamic dynamic = history;
1850 using var columns =
new PySequence(dynamic.columns);
1851 using var dataKey =
"data".ToPython();
1852 if (columns.Contains(dataKey))
1854 history = dynamic[
"data"];
1858 dynamic.index = dynamic.index.droplevel(
"symbol");