chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IUniverseSelectionModel"/> that combines multiple universe
|
||||
/// selection models into a single model.
|
||||
/// </summary>
|
||||
public class CompositeUniverseSelectionModel : UniverseSelectionModel
|
||||
{
|
||||
private readonly List<IUniverseSelectionModel> _universeSelectionModels = new List<IUniverseSelectionModel>();
|
||||
private bool _alreadyCalledCreateUniverses;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeUniverseSelectionModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="universeSelectionModels">The individual universe selection models defining this composite model</param>
|
||||
public CompositeUniverseSelectionModel(params IUniverseSelectionModel[] universeSelectionModels)
|
||||
{
|
||||
if (universeSelectionModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 universe selection model for the CompositeUniverseSelectionModel");
|
||||
}
|
||||
|
||||
_universeSelectionModels.AddRange(universeSelectionModels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeUniverseSelectionModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="universeSelectionModels">The individual universe selection models defining this composite model</param>
|
||||
public CompositeUniverseSelectionModel(params PyObject[] universeSelectionModels)
|
||||
{
|
||||
if (universeSelectionModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 universe selection model for the CompositeUniverseSelectionModel");
|
||||
}
|
||||
|
||||
foreach (var pyUniverseSelectionModel in universeSelectionModels)
|
||||
{
|
||||
AddUniverseSelection(pyUniverseSelectionModel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="IUniverseSelectionModel"/>
|
||||
/// </summary>
|
||||
/// <param name="universeSelectionModel">The universe selection model to add</param>
|
||||
public void AddUniverseSelection(IUniverseSelectionModel universeSelectionModel)
|
||||
{
|
||||
_universeSelectionModels.Add(universeSelectionModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="IUniverseSelectionModel"/>
|
||||
/// </summary>
|
||||
/// <param name="pyUniverseSelectionModel">The universe selection model to add</param>
|
||||
public void AddUniverseSelection(PyObject pyUniverseSelectionModel)
|
||||
{
|
||||
IUniverseSelectionModel selectionModel;
|
||||
if (!pyUniverseSelectionModel.TryConvert(out selectionModel))
|
||||
{
|
||||
selectionModel = new UniverseSelectionModelPythonWrapper(pyUniverseSelectionModel);
|
||||
}
|
||||
_universeSelectionModels.Add(selectionModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
|
||||
/// </summary>
|
||||
public override DateTime GetNextRefreshTimeUtc()
|
||||
{
|
||||
return _universeSelectionModels.Min(model => model.GetNextRefreshTimeUtc());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance to create universes for</param>
|
||||
/// <returns>The universes to be used by the algorithm</returns>
|
||||
public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
foreach (var universeSelectionModel in _universeSelectionModels)
|
||||
{
|
||||
var selectionRefreshTime = universeSelectionModel.GetNextRefreshTimeUtc();
|
||||
var refreshTime = algorithm.UtcTime >= selectionRefreshTime;
|
||||
if (!_alreadyCalledCreateUniverses // first initial call
|
||||
|| refreshTime
|
||||
|| selectionRefreshTime == DateTime.MaxValue)
|
||||
{
|
||||
foreach (var universe in universeSelectionModel.CreateUniverses(algorithm))
|
||||
{
|
||||
yield return universe;
|
||||
}
|
||||
}
|
||||
}
|
||||
_alreadyCalledCreateUniverses = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a universe as a set of dynamically set symbols.
|
||||
/// </summary>
|
||||
public class CustomUniverse : UserDefinedUniverse
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="CustomUniverse"/>
|
||||
/// </summary>
|
||||
public CustomUniverse(SubscriptionDataConfig configuration,
|
||||
UniverseSettings universeSettings,
|
||||
TimeSpan interval,
|
||||
Func<DateTime, IEnumerable<string>> selector)
|
||||
: base(configuration, universeSettings, interval, selector)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the subscription requests to be added for the specified security
|
||||
/// </summary>
|
||||
/// <param name="security">The security to get subscriptions for</param>
|
||||
/// <param name="currentTimeUtc">The current time in utc. This is the frontier time of the algorithm</param>
|
||||
/// <param name="maximumEndTimeUtc">The max end time</param>
|
||||
/// <param name="subscriptionService">Instance which implements <see cref="ISubscriptionDataConfigService"/> interface</param>
|
||||
/// <returns>All subscriptions required by this security</returns>
|
||||
public override IEnumerable<SubscriptionRequest> GetSubscriptionRequests(Security security, DateTime currentTimeUtc, DateTime maximumEndTimeUtc,
|
||||
ISubscriptionDataConfigService subscriptionService)
|
||||
{
|
||||
// CustomUniverse will return any existing SDC for the symbol, else will create new, using universe settings.
|
||||
var existingSubscriptionDataConfigs = subscriptionService.GetSubscriptionDataConfigs(security.Symbol);
|
||||
|
||||
if (existingSubscriptionDataConfigs.Any())
|
||||
{
|
||||
return existingSubscriptionDataConfigs.Select(
|
||||
config => new SubscriptionRequest(isUniverseSubscription: false,
|
||||
universe: this,
|
||||
security: security,
|
||||
configuration: config,
|
||||
startTimeUtc: currentTimeUtc,
|
||||
endTimeUtc: maximumEndTimeUtc));
|
||||
}
|
||||
return base.GetSubscriptionRequests(security, currentTimeUtc, maximumEndTimeUtc, subscriptionService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IUniverseSelectionModel"/> that simply
|
||||
/// subscribes to the specified set of symbols
|
||||
/// </summary>
|
||||
public class CustomUniverseSelectionModel : UniverseSelectionModel
|
||||
{
|
||||
private static readonly MarketHoursDatabase MarketHours = MarketHoursDatabase.FromDataFolder();
|
||||
private readonly Symbol _symbol;
|
||||
private readonly Func<DateTime, IEnumerable<string>> _selector;
|
||||
private readonly UniverseSettings _universeSettings;
|
||||
private readonly TimeSpan _interval;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CustomUniverseSelectionModel"/> class
|
||||
/// for <see cref="Market.USA"/> and <see cref="SecurityType.Equity"/>
|
||||
/// using the algorithm's universe settings
|
||||
/// </summary>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
public CustomUniverseSelectionModel(string name, Func<DateTime, IEnumerable<string>> selector)
|
||||
: this(SecurityType.Equity, name, Market.USA, selector, null, Time.OneDay)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CustomUniverseSelectionModel"/> class
|
||||
/// for <see cref="Market.USA"/> and <see cref="SecurityType.Equity"/>
|
||||
/// using the algorithm's universe settings
|
||||
/// </summary>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
public CustomUniverseSelectionModel(string name, PyObject selector)
|
||||
: this(SecurityType.Equity, name, Market.USA, selector, null, Time.OneDay)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CustomUniverseSelectionModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="securityType">The security type of the universe</param>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="market">The market of the universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
/// <param name="universeSettings">The settings used when adding symbols to the algorithm, specify null to use algorithm.UniverseSettings</param>
|
||||
/// <param name="interval">The interval at which selection should be performed</param>
|
||||
public CustomUniverseSelectionModel(SecurityType securityType, string name, string market, Func<DateTime, IEnumerable<string>> selector, UniverseSettings universeSettings, TimeSpan interval)
|
||||
{
|
||||
_interval = interval;
|
||||
_selector = selector;
|
||||
_universeSettings = universeSettings;
|
||||
_symbol = Symbol.Create($"{name}-{securityType}-{market}", securityType, market);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CustomUniverseSelectionModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="securityType">The security type of the universe</param>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="market">The market of the universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
/// <param name="universeSettings">The settings used when adding symbols to the algorithm, specify null to use algorithm.UniverseSettings</param>
|
||||
/// <param name="interval">The interval at which selection should be performed</param>
|
||||
public CustomUniverseSelectionModel(SecurityType securityType, string name, string market, PyObject selector, UniverseSettings universeSettings, TimeSpan interval)
|
||||
: this(
|
||||
securityType,
|
||||
name,
|
||||
market,
|
||||
selector.SafeAs<Func<DateTime, object>>().ConvertToUniverseSelectionStringDelegate(),
|
||||
universeSettings,
|
||||
interval
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm. Called at algorithm start.
|
||||
/// </summary>
|
||||
/// <returns>The universes defined by this model</returns>
|
||||
public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
var universeSettings = _universeSettings ?? algorithm.UniverseSettings;
|
||||
var entry = MarketHours.GetEntry(_symbol.ID.Market, (string)null, _symbol.SecurityType);
|
||||
|
||||
var config = new SubscriptionDataConfig(
|
||||
universeSettings.Resolution == Resolution.Tick ? typeof(Tick) : typeof(TradeBar),
|
||||
_symbol,
|
||||
universeSettings.Resolution,
|
||||
entry.DataTimeZone,
|
||||
entry.ExchangeHours.TimeZone,
|
||||
universeSettings.FillForward,
|
||||
universeSettings.ExtendedMarketHours,
|
||||
true
|
||||
);
|
||||
|
||||
yield return new CustomUniverse(config, universeSettings, _interval, dt => Select(algorithm, dt));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="algorithm"></param>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IEnumerable<string> Select(QCAlgorithm algorithm, DateTime date)
|
||||
{
|
||||
// Check if this method was overridden in Python
|
||||
if (TryInvokePythonOverride(nameof(Select), out IEnumerable<string> result, algorithm, date))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_selector == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(_selector));
|
||||
}
|
||||
|
||||
return _selector(date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current object
|
||||
/// </summary>
|
||||
public override string ToString() => _symbol.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm framework model that defines the universes to be used by an algorithm
|
||||
/// </summary>
|
||||
public interface IUniverseSelectionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
|
||||
/// </summary>
|
||||
DateTime GetNextRefreshTimeUtc();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance to create universes for</param>
|
||||
/// <returns>The universes to be used by the algorithm</returns>
|
||||
IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a universe as a set of manually set symbols. This differs from <see cref="UserDefinedUniverse"/>
|
||||
/// in that these securities were not added via AddSecurity.
|
||||
/// </summary>
|
||||
/// <remarks>Incompatible with multiple <see cref="Universe"/> selecting the same <see cref="Symbol"/>.
|
||||
/// with different <see cref="SubscriptionDataConfig"/>. More information <see cref="GetSubscriptionRequests"/></remarks>
|
||||
public class ManualUniverse : UserDefinedUniverse
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ManualUniverse"/>
|
||||
/// </summary>
|
||||
public ManualUniverse(SubscriptionDataConfig configuration,
|
||||
UniverseSettings universeSettings,
|
||||
IEnumerable<Symbol> symbols)
|
||||
: base(configuration, universeSettings, Time.MaxTimeSpan, symbols)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ManualUniverse"/>
|
||||
/// </summary>
|
||||
public ManualUniverse(SubscriptionDataConfig configuration,
|
||||
UniverseSettings universeSettings,
|
||||
Symbol[] symbols)
|
||||
: base(configuration, universeSettings, Time.MaxTimeSpan, symbols)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the subscription requests to be added for the specified security
|
||||
/// </summary>
|
||||
/// <param name="security">The security to get subscriptions for</param>
|
||||
/// <param name="currentTimeUtc">The current time in utc. This is the frontier time of the algorithm</param>
|
||||
/// <param name="maximumEndTimeUtc">The max end time</param>
|
||||
/// <param name="subscriptionService">Instance which implements <see cref="ISubscriptionDataConfigService"/> interface</param>
|
||||
/// <returns>All subscriptions required by this security</returns>
|
||||
public override IEnumerable<SubscriptionRequest> GetSubscriptionRequests(Security security, DateTime currentTimeUtc, DateTime maximumEndTimeUtc,
|
||||
ISubscriptionDataConfigService subscriptionService)
|
||||
{
|
||||
// ManualUniverse will return any existing SDC for the symbol, else will create new, using universe settings.
|
||||
// This is for maintaining existing behavior and preventing breaking changes: Specifically motivated
|
||||
// by usages of Algorithm.Securities.Keys as constructor parameter of the ManualUniverseSelectionModel.
|
||||
// Symbols at Algorithm.Securities.Keys added by Addxxx() calls will already be added by the UserDefinedUniverse.
|
||||
|
||||
var existingSubscriptionDataConfigs = subscriptionService.GetSubscriptionDataConfigs(security.Symbol);
|
||||
|
||||
if (existingSubscriptionDataConfigs.Any())
|
||||
{
|
||||
return existingSubscriptionDataConfigs.Select(
|
||||
config => new SubscriptionRequest(isUniverseSubscription: false,
|
||||
universe: this,
|
||||
security: security,
|
||||
configuration: config,
|
||||
startTimeUtc: currentTimeUtc,
|
||||
endTimeUtc: maximumEndTimeUtc));
|
||||
}
|
||||
return base.GetSubscriptionRequests(security, currentTimeUtc, maximumEndTimeUtc, subscriptionService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Securities;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IUniverseSelectionModel"/> that simply
|
||||
/// subscribes to the specified set of symbols
|
||||
/// </summary>
|
||||
public class ManualUniverseSelectionModel : UniverseSelectionModel
|
||||
{
|
||||
private static readonly MarketHoursDatabase MarketHours = MarketHoursDatabase.FromDataFolder();
|
||||
|
||||
private readonly IReadOnlyList<Symbol> _symbols;
|
||||
private readonly UniverseSettings _universeSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManualUniverseSelectionModel"/> class using the algorithm's
|
||||
/// security initializer and universe settings
|
||||
/// </summary>
|
||||
public ManualUniverseSelectionModel()
|
||||
: this(Enumerable.Empty<Symbol>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManualUniverseSelectionModel"/> class using the algorithm's
|
||||
/// security initializer and universe settings
|
||||
/// </summary>
|
||||
/// <param name="symbols">The symbols to subscribe to.
|
||||
/// Should not send in symbols at <see cref="QCAlgorithm.Securities"/> since those will be managed by the <see cref="UserDefinedUniverse"/></param>
|
||||
public ManualUniverseSelectionModel(IEnumerable<Symbol> symbols)
|
||||
: this(symbols.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManualUniverseSelectionModel"/> class using the algorithm's
|
||||
/// security initializer and universe settings
|
||||
/// </summary>
|
||||
/// <param name="symbols">The symbols to subscribe to
|
||||
/// Should not send in symbols at <see cref="QCAlgorithm.Securities"/> since those will be managed by the <see cref="UserDefinedUniverse"/></param>
|
||||
public ManualUniverseSelectionModel(params Symbol[] symbols)
|
||||
: this (symbols?.AsEnumerable(), null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManualUniverseSelectionModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="symbols">The symbols to subscribe to
|
||||
/// Should not send in symbols at <see cref="QCAlgorithm.Securities"/> since those will be managed by the <see cref="UserDefinedUniverse"/></param>
|
||||
/// <param name="universeSettings">The settings used when adding symbols to the algorithm, specify null to use algorithm.UniverseSettings</param>
|
||||
public ManualUniverseSelectionModel(IEnumerable<Symbol> symbols, UniverseSettings universeSettings)
|
||||
{
|
||||
if (symbols == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(symbols));
|
||||
}
|
||||
|
||||
_symbols = symbols.Where(s => !s.IsCanonical()).ToList();
|
||||
_universeSettings = universeSettings;
|
||||
|
||||
foreach (var symbol in _symbols)
|
||||
{
|
||||
SymbolCache.Set(symbol.Value, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm.
|
||||
/// Called at algorithm start.
|
||||
/// </summary>
|
||||
/// <returns>The universes defined by this model</returns>
|
||||
public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
var universeSettings = _universeSettings ?? algorithm.UniverseSettings;
|
||||
var resolution = universeSettings.Resolution;
|
||||
var type = resolution == Resolution.Tick ? typeof(Tick) : typeof(TradeBar);
|
||||
|
||||
// universe per security type/market
|
||||
foreach (var grp in _symbols.GroupBy(s => new { s.ID.Market, s.SecurityType }))
|
||||
{
|
||||
MarketHoursDatabase.Entry entry;
|
||||
|
||||
var market = grp.Key.Market;
|
||||
var securityType = grp.Key.SecurityType;
|
||||
var hashCode = 1;
|
||||
foreach (var symbol in grp)
|
||||
{
|
||||
hashCode = hashCode * 31 + symbol.GetHashCode();
|
||||
}
|
||||
var universeSymbol = Symbol.Create($"manual-universe-selection-model-{securityType}-{market}-{hashCode}", securityType, market);
|
||||
if (securityType == SecurityType.Base)
|
||||
{
|
||||
// add an entry for this custom universe symbol -- we don't really know the time zone for sure,
|
||||
// but we set it to TimeZones.NewYork in AddData, also, since this is a manual universe, the time
|
||||
// zone doesn't actually matter since this universe specifically doesn't do anything with data.
|
||||
var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(universeSymbol);
|
||||
var alwaysOpen = SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork);
|
||||
entry = MarketHours.SetEntry(market, symbolString, securityType, alwaysOpen, TimeZones.NewYork);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = MarketHours.GetEntry(market, (string) null, securityType);
|
||||
}
|
||||
|
||||
var config = new SubscriptionDataConfig(type, universeSymbol, resolution, entry.DataTimeZone, entry.ExchangeHours.TimeZone, false, false, true);
|
||||
yield return new ManualUniverse(config, universeSettings, grp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
# 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.
|
||||
|
||||
from AlgorithmImports import *
|
||||
from clr import GetClrType as typeof
|
||||
|
||||
from Selection.UniverseSelectionModel import UniverseSelectionModel
|
||||
from itertools import groupby
|
||||
|
||||
class ManualUniverseSelectionModel(UniverseSelectionModel):
|
||||
'''Provides an implementation of IUniverseSelectionModel that simply subscribes to the specified set of symbols'''
|
||||
|
||||
def __init__(self, symbols = list(), universe_settings = None):
|
||||
self.marketHours = MarketHoursDatabase.from_data_folder()
|
||||
self.symbols = symbols
|
||||
self.universe_settings = universe_settings
|
||||
|
||||
for symbol in symbols:
|
||||
SymbolCache.set(symbol.Value, symbol)
|
||||
|
||||
def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:
|
||||
'''Creates the universes for this algorithm. Called once after IAlgorithm.Initialize
|
||||
Args:
|
||||
algorithm: The algorithm instance to create universes for</param>
|
||||
Returns:
|
||||
The universes to be used by the algorithm'''
|
||||
universe_settings = self.universe_settings \
|
||||
if self.universe_settings is not None else algorithm.universe_settings
|
||||
|
||||
resolution = universe_settings.resolution
|
||||
type = typeof(Tick) if resolution == Resolution.TICK else typeof(TradeBar)
|
||||
|
||||
universes = list()
|
||||
|
||||
# universe per security type/market
|
||||
self.symbols = sorted(self.symbols, key=lambda s: (s.id.market, s.security_type))
|
||||
for key, grp in groupby(self.symbols, lambda s: (s.id.market, s.security_type)):
|
||||
|
||||
market = key[0]
|
||||
security_type = key[1]
|
||||
universe_symbol = Symbol.create(f"manual-universe-selection-model-{security_type}-{market}", security_type, market)
|
||||
|
||||
if security_type == SecurityType.BASE:
|
||||
# add an entry for this custom universe symbol -- we don't really know the time zone for sure,
|
||||
# but we set it to TimeZones.NewYork in AddData, also, since this is a manual universe, the time
|
||||
# zone doesn't actually matter since this universe specifically doesn't do anything with data.
|
||||
symbol_string = MarketHoursDatabase.get_database_symbol_key(universe_symbol)
|
||||
always_open = SecurityExchangeHours.always_open(TimeZones.NEW_YORK)
|
||||
entry = self.marketHours.set_entry(market, symbol_string, security_type, always_open, TimeZones.NEW_YORK)
|
||||
else:
|
||||
entry = self.marketHours.get_entry(market, None, security_type)
|
||||
|
||||
config = SubscriptionDataConfig(type, universe_symbol, resolution, entry.data_time_zone, entry.exchange_hours.time_zone, False, False, True)
|
||||
universes.append( ManualUniverse(config, universe_settings, list(grp)))
|
||||
|
||||
return universes
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a null implementation of <see cref="IUniverseSelectionModel"/>
|
||||
/// </summary>
|
||||
public class NullUniverseSelectionModel : UniverseSelectionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm.
|
||||
/// Called at algorithm start.
|
||||
/// </summary>
|
||||
/// <returns>The universes defined by this model</returns>
|
||||
public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Securities.Future;
|
||||
using Python.Runtime;
|
||||
|
||||
namespace QuantConnect.Algorithm.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// This universe selection model will chain to the security changes of a given <see cref="Universe"/> selection
|
||||
/// output and create a new <see cref="OptionChainUniverse"/> for each of them
|
||||
/// </summary>
|
||||
public class OptionChainedUniverseSelectionModel : UniverseSelectionModel
|
||||
{
|
||||
private DateTime _nextRefreshTimeUtc;
|
||||
private IEnumerable<Symbol> _currentSymbols;
|
||||
private readonly UniverseSettings _universeSettings;
|
||||
private readonly Func<OptionFilterUniverse, OptionFilterUniverse> _optionFilter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
|
||||
/// </summary>
|
||||
public override DateTime GetNextRefreshTimeUtc() => _nextRefreshTimeUtc;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="OptionChainedUniverseSelectionModel"/>
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe we want to chain to</param>
|
||||
/// <param name="optionFilter">The option filter universe to use</param>
|
||||
/// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
|
||||
public OptionChainedUniverseSelectionModel(Universe universe,
|
||||
Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter,
|
||||
UniverseSettings universeSettings = null)
|
||||
{
|
||||
_optionFilter = optionFilter;
|
||||
_universeSettings = universeSettings;
|
||||
_nextRefreshTimeUtc = DateTime.MaxValue;
|
||||
|
||||
_currentSymbols = Enumerable.Empty<Symbol>();
|
||||
universe.SelectionChanged += (sender, args) =>
|
||||
{
|
||||
// the universe we were watching changed, this will trigger a call to CreateUniverses
|
||||
_nextRefreshTimeUtc = DateTime.MinValue;
|
||||
|
||||
// We must create the new option Symbol using the CreateOption(Symbol, ...) overload.
|
||||
// Otherwise, we'll end up loading equity data for the selected Symbol, which won't
|
||||
// work whenever we're loading options data for any non-equity underlying asset class.
|
||||
_currentSymbols = ((Universe.SelectionEventArgs)args).CurrentSelection
|
||||
.Select(symbol => Symbol.CreateOption(
|
||||
symbol,
|
||||
symbol.ID.Market,
|
||||
symbol.SecurityType.DefaultOptionStyle(),
|
||||
default(OptionRight),
|
||||
0m,
|
||||
SecurityIdentifier.DefaultDate))
|
||||
.ToList();
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="OptionChainedUniverseSelectionModel"/>
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe we want to chain to</param>
|
||||
/// <param name="optionFilter">The python option filter universe to use</param>
|
||||
/// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
|
||||
public OptionChainedUniverseSelectionModel(Universe universe,
|
||||
PyObject optionFilter,
|
||||
UniverseSettings universeSettings = null): this(universe, ConvertOptionFilter(optionFilter), universeSettings)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance to create universes for</param>
|
||||
/// <returns>The universes to be used by the algorithm</returns>
|
||||
public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
_nextRefreshTimeUtc = DateTime.MaxValue;
|
||||
|
||||
foreach (var optionSymbol in _currentSymbols)
|
||||
{
|
||||
yield return algorithm.CreateOptionChain(optionSymbol, _optionFilter, _universeSettings);
|
||||
}
|
||||
}
|
||||
|
||||
private static Func<OptionFilterUniverse, OptionFilterUniverse> ConvertOptionFilter(PyObject optionFilter)
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
return optionFilter.SafeAs<Func<OptionFilterUniverse, OptionFilterUniverse>>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// This universe will hold single option contracts and their underlying, managing removals and additions
|
||||
/// </summary>
|
||||
public class OptionContractUniverse : UserDefinedUniverse
|
||||
{
|
||||
private readonly HashSet<Symbol> _symbols;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty instance
|
||||
/// </summary>
|
||||
/// <param name="configuration">The universe configuration to use</param>
|
||||
/// <param name="universeSettings">The universe settings to use</param>
|
||||
public OptionContractUniverse(SubscriptionDataConfig configuration, UniverseSettings universeSettings)
|
||||
: base(AdjustUniverseConfiguration(configuration), universeSettings, Time.EndOfTimeTimeSpan,
|
||||
// Argument isn't used since we override 'SelectSymbols'
|
||||
Enumerable.Empty<Symbol>())
|
||||
{
|
||||
_symbols = new HashSet<Symbol>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the symbols defined by the user for this universe
|
||||
/// </summary>
|
||||
/// <param name="utcTime">The current utc time</param>
|
||||
/// <param name="data">The symbols to remain in the universe</param>
|
||||
/// <returns>The data that passes the filter</returns>
|
||||
public override IEnumerable<Symbol> SelectSymbols(DateTime utcTime, BaseDataCollection data)
|
||||
{
|
||||
return _symbols;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event invocator for the <see cref="UserDefinedUniverse.CollectionChanged"/> event
|
||||
/// </summary>
|
||||
/// <param name="e">The notify collection changed event arguments</param>
|
||||
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
var removedSymbol = (Symbol)e.OldItems[0];
|
||||
_symbols.Remove(removedSymbol);
|
||||
|
||||
// the option has been removed! This can happen when the user manually removed the option contract we remove the underlying
|
||||
// but only if there isn't any other option selected using the same underlying!
|
||||
if (removedSymbol.SecurityType.IsOption()
|
||||
&& !_symbols.Any(symbol => symbol.SecurityType.IsOption() && symbol.Underlying == removedSymbol.Underlying))
|
||||
{
|
||||
Remove(removedSymbol.Underlying);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
// QCAlgorithm.AddOptionContract will add both underlying and option contract
|
||||
_symbols.Add((Symbol)e.NewItems[0]);
|
||||
}
|
||||
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a user defined universe symbol
|
||||
/// </summary>
|
||||
/// <param name="market">The market</param>
|
||||
/// <param name="securityType">The underlying option security type</param>
|
||||
/// <returns>A symbol for user defined universe of the specified security type and market</returns>
|
||||
public static Symbol CreateSymbol(string market, SecurityType securityType)
|
||||
{
|
||||
var ticker = $"qc-universe-optioncontract-{securityType.SecurityTypeToLower()}-{market.ToLowerInvariant()}";
|
||||
var underlying = Symbol.Create(ticker, securityType, market);
|
||||
var sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlying.ID, market, 0, 0, 0);
|
||||
|
||||
return new Symbol(sid, ticker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the configuration of the universe is what we want
|
||||
/// </summary>
|
||||
private static SubscriptionDataConfig AdjustUniverseConfiguration(SubscriptionDataConfig input)
|
||||
{
|
||||
return new SubscriptionDataConfig(input, fillForward: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for universe selection models.
|
||||
/// </summary>
|
||||
public class UniverseSelectionModel : BasePythonWrapper<UniverseSelectionModel>, IUniverseSelectionModel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UniverseSelectionModel"/> class.
|
||||
/// </summary>
|
||||
public UniverseSelectionModel()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
|
||||
/// </summary>
|
||||
public virtual DateTime GetNextRefreshTimeUtc()
|
||||
{
|
||||
return DateTime.MaxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance to create universes for</param>
|
||||
/// <returns>The universes to be used by the algorithm</returns>
|
||||
public virtual IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
throw new NotImplementedException("Types deriving from 'UniverseSelectionModel' must implement the 'IEnumerable<Universe> CreateUniverses(QCAlgorithm) method.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# 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.
|
||||
|
||||
from AlgorithmImports import *
|
||||
|
||||
class UniverseSelectionModel:
|
||||
'''Provides a base class for universe selection models.'''
|
||||
|
||||
def get_next_refresh_time_utc(self) -> datetime:
|
||||
'''Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.'''
|
||||
if hasattr(self, "GetNextRefreshTimeUtc") and callable(self.GetNextRefreshTimeUtc):
|
||||
return self.GetNextRefreshTimeUtc()
|
||||
return datetime.max
|
||||
|
||||
def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:
|
||||
'''Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
|
||||
Args:
|
||||
algorithm: The algorithm instance to create universes for</param>
|
||||
Returns:
|
||||
The universes to be used by the algorithm'''
|
||||
if hasattr(self, "CreateUniverses") and callable(self.CreateUniverses):
|
||||
return self.CreateUniverses(algorithm)
|
||||
raise NotImplementedError("Types deriving from 'UniverseSelectionModel' must implement the 'def CreateUniverses(QCAlgorithm) method.")
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 Python.Runtime;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Selection
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IUniverseSelectionModel"/> that wraps a <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
public class UniverseSelectionModelPythonWrapper : UniverseSelectionModel
|
||||
{
|
||||
private readonly bool _modelHasGetNextRefreshTime;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
|
||||
/// </summary>
|
||||
public override DateTime GetNextRefreshTimeUtc()
|
||||
{
|
||||
if (!_modelHasGetNextRefreshTime)
|
||||
{
|
||||
return DateTime.MaxValue;
|
||||
}
|
||||
|
||||
return InvokeMethod<DateTime>(nameof(GetNextRefreshTimeUtc));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for initialising the <see cref="IUniverseSelectionModel"/> class with wrapped <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
/// <param name="model">Model defining universes for the algorithm</param>
|
||||
public UniverseSelectionModelPythonWrapper(PyObject model)
|
||||
{
|
||||
SetPythonInstance(model, false);
|
||||
using (Py.GIL())
|
||||
{
|
||||
_modelHasGetNextRefreshTime = HasAttr(nameof(IUniverseSelectionModel.GetNextRefreshTimeUtc));
|
||||
|
||||
foreach (var attributeName in new[] { "CreateUniverses" })
|
||||
{
|
||||
if (!HasAttr(attributeName))
|
||||
{
|
||||
throw new NotImplementedException($"UniverseSelectionModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
|
||||
}
|
||||
}
|
||||
|
||||
var methodName = nameof(SetPythonInstance);
|
||||
if (HasAttr(methodName))
|
||||
{
|
||||
InvokeMethod(methodName, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance to create universes for</param>
|
||||
/// <returns>The universes to be used by the algorithm</returns>
|
||||
public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
|
||||
{
|
||||
return InvokeMethodAndEnumerate<Universe>(nameof(CreateUniverses), algorithm);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user