/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Indicators; using System; using QuantConnect.Securities; using NodaTime; using System.Collections.Generic; using System.Reflection.Emit; using System.Reflection; using QuantConnect.Python; using Python.Runtime; using QuantConnect.Data.UniverseSelection; using QuantConnect.Data.Fundamental; namespace QuantConnect.Algorithm { public partial class QCAlgorithm { /// /// AddData a new user defined data source, requiring only the minimum config options. /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time) /// /// Data source type /// Key/Symbol for data /// Resolution of the data /// Generic type T must implement base data public void AddData(PyObject type, string symbol, Resolution resolution = Resolution.Minute) { AddData(type, symbol, Resolution.Minute, TimeZones.NewYork, false, 1m); } /// /// AddData a new user defined data source, requiring only the minimum config options. /// /// Data source type /// Key/Symbol for data /// Resolution of the Data Required /// Specifies the time zone of the raw data /// When no data available on a tradebar, return the last data that was generated /// Custom leverage per security public void AddData(PyObject type, string symbol, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m) { var objectType = CreateType(type.Repr().Split('.')[1].Replace("\'>", "")); AddData(objectType, symbol, resolution, timeZone, fillDataForward, leverage); } /// /// AddData a new user defined data source, requiring only the minimum config options. /// /// Data source type /// Key/Symbol for data /// Resolution of the Data Required /// Specifies the time zone of the raw data /// When no data available on a tradebar, return the last data that was generated /// Custom leverage per security public void AddData(Type T, string symbol, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m) { var marketHoursDbEntry = _marketHoursDatabase.GetEntry(Market.USA, symbol, SecurityType.Base, timeZone); //Add this to the data-feed subscriptions var symbolObject = new Symbol(SecurityIdentifier.GenerateBase(symbol, Market.USA), symbol); var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(Market.USA, symbol, SecurityType.Base, CashBook.AccountCurrency); //Add this new generic data as a tradeable security: var security = SecurityManager.CreateSecurity(new List() { T }, Portfolio, SubscriptionManager, marketHoursDbEntry.ExchangeHours, marketHoursDbEntry.DataTimeZone, symbolProperties, SecurityInitializer, symbolObject, resolution, fillDataForward, leverage, true, false, true, LiveMode); AddToUserDefinedUniverse(security); } /// /// Creates a new universe and adds it to the algorithm. This is for coarse fundamental US Equity data and /// will be executed on day changes in the NewYork time zone ( /// /// Defines an initial coarse selection public void AddUniverse(PyObject pycoarse) { var coarse = ToFunc(pycoarse); AddUniverse(coarse); } /// /// Creates a new universe and adds it to the algorithm. This is for coarse and fine fundamental US Equity data and /// will be executed on day changes in the NewYork time zone ( /// /// Defines an initial coarse selection /// Defines a more detailed selection with access to more data public void AddUniverse(PyObject pycoarse, PyObject pyfine) { var coarse = ToFunc(pycoarse); var fine = ToFunc(pyfine); AddUniverse(coarse, fine); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution = null) { RegisterIndicator(symbol, indicator, resolution); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution = null) { RegisterIndicator(symbol, indicator, resolution); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution, Func selector) { RegisterIndicator(symbol, indicator, resolution, selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution, Func selector) { RegisterIndicator(symbol, indicator, resolution, selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, TimeSpan? resolution, Func selector) { RegisterIndicator(symbol, indicator, resolution, selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, TimeSpan? resolution, Func selector) { RegisterIndicator(symbol, indicator, resolution, selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The consolidator to receive raw subscription data /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, IDataConsolidator consolidator, Func selector) { RegisterIndicator(symbol, indicator, consolidator, selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The consolidator to receive raw subscription data /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, IDataConsolidator consolidator, Func selector) { RegisterIndicator(symbol, indicator, consolidator, selector); } /// /// Plots the value of each indicator on the chart /// /// The chart's name /// The indicatorsto plot /// public void Plot(string chart, params IndicatorBase[] indicators) { Plot(chart, indicators); } /// /// Plots the value of each indicator on the chart /// /// The chart's name /// The indicatorsto plot /// public void Plot(string chart, params IndicatorBase[] indicators) { Plot(chart, indicators); } /// /// Plots the value of each indicator on the chart /// /// The chart's name /// The indicatorsto plot /// public void Plot(string chart, params IndicatorBase[] indicators) { Plot(chart, indicators); } /// /// Automatically plots each indicator when a new value is available /// public void PlotIndicator(string chart, params IndicatorBase[] indicators) { PlotIndicator(chart, indicators); } /// /// Automatically plots each indicator when a new value is available /// public void PlotIndicator(string chart, params IndicatorBase[] indicators) { PlotIndicator(chart, indicators); } /// /// Automatically plots each indicator when a new value is available /// public void PlotIndicator(string chart, params IndicatorBase[] indicators) { PlotIndicator(chart, indicators); } /// /// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true /// public void PlotIndicator(string chart, bool waitForReady, params IndicatorBase[] indicators) { PlotIndicator(chart, waitForReady, indicators); } /// /// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true /// public void PlotIndicator(string chart, bool waitForReady, params IndicatorBase[] indicators) { PlotIndicator(chart, waitForReady, indicators); } /// /// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true /// public void PlotIndicator(string chart, bool waitForReady, params IndicatorBase[] indicators) { PlotIndicator(chart, waitForReady, indicators); } /// /// Creates a type with a given name /// /// Name of the new type /// Type object private Type CreateType(string typeName) { var an = new AssemblyName(typeName); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); return moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, typeof(PythonData)) .CreateType(); } /// /// Encapsulates a python method with a /// /// The data type /// The python method /// A that encapsulates the python method private Func, IEnumerable> ToFunc(PyObject pyObject) { var testMod = "from clr import AddReference\n" + "AddReference(\"System\")\n" + "AddReference(\"System.Collections\")\n" + "AddReference(\"QuantConnect.Common\")\n" + "from System import Func\n" + "from System.Collections.Generic import IEnumerable\n" + "from QuantConnect import Symbol\n" + "from QuantConnect.Data.Fundamental import FineFundamental\n" + "from QuantConnect.Data.UniverseSelection import CoarseFundamental\n" + "def to_func(pyobject, type):\n" + " return Func[IEnumerable[type], IEnumerable[Symbol]](pyobject)"; using (Py.GIL()) { dynamic toFunc = PythonEngine.ModuleFromString("x", testMod).GetAttr("to_func"); return toFunc(pyObject, typeof(T)) .AsManagedObject(typeof(Func, IEnumerable>)); } } } }