chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for alpha models.
|
||||
/// </summary>
|
||||
public class AlphaModel : BasePythonWrapper<AlphaModel>, IAlphaModel, INamedModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a name for a framework model
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize new <see cref="AlphaModel"/>
|
||||
/// </summary>
|
||||
public AlphaModel()
|
||||
{
|
||||
Name = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this alpha model with the latest data from the algorithm.
|
||||
/// This is called each time the algorithm receives data for subscribed securities
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="data">The new data available</param>
|
||||
/// <returns>The new insights generated</returns>
|
||||
public virtual IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
throw new NotImplementedException("Types deriving from 'AlphaModel' must implement the 'IEnumerable<Insight> Update(QCAlgorithm, Slice) method.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public virtual void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for alpha models
|
||||
/// </summary>
|
||||
public static class AlphaModelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the alpha model
|
||||
/// </summary>
|
||||
public static string GetModelName(this IAlphaModel model)
|
||||
{
|
||||
var namedModel = model as INamedModel;
|
||||
if (namedModel != null)
|
||||
{
|
||||
return namedModel.Name;
|
||||
}
|
||||
|
||||
return model.GetType().Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IAlphaModel"/> that wraps a <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
public class AlphaModelPythonWrapper : AlphaModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a name for a framework model
|
||||
/// </summary>
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
// if the model defines a Name property then use that
|
||||
if (HasAttr(nameof(Name)))
|
||||
{
|
||||
return GetProperty<string>(nameof(Name));
|
||||
}
|
||||
|
||||
// if the model does not define a name property, use the python type name
|
||||
return GetProperty(" __class__").GetAttr("__name__").GetAndDispose<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for initialising the <see cref="IAlphaModel"/> class with wrapped <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
/// <param name="model">>Model that generates alpha</param>
|
||||
public AlphaModelPythonWrapper(PyObject model)
|
||||
{
|
||||
SetPythonInstance(model, false);
|
||||
foreach (var attributeName in new[] { "Update", "OnSecuritiesChanged" })
|
||||
{
|
||||
if (!HasAttr(attributeName))
|
||||
{
|
||||
throw new NotImplementedException($"IAlphaModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
|
||||
}
|
||||
}
|
||||
|
||||
var methodName = nameof(SetPythonInstance);
|
||||
if (HasAttr(methodName))
|
||||
{
|
||||
InvokeMethod(methodName, model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this alpha model with the latest data from the algorithm.
|
||||
/// This is called each time the algorithm receives data for subscribed securities
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="data">The new data available</param>
|
||||
/// <returns>The new insights generated</returns>
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
return InvokeMethodAndEnumerate<Insight>(nameof(Update), algorithm, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
InvokeVoidMethod(nameof(OnSecuritiesChanged), algorithm, changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.UniverseSelection;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IAlphaModel"/> that combines multiple alpha
|
||||
/// models into a single alpha model and properly sets each insights 'SourceModel' property.
|
||||
/// </summary>
|
||||
public class CompositeAlphaModel : AlphaModel
|
||||
{
|
||||
private readonly List<IAlphaModel> _alphaModels = new List<IAlphaModel>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeAlphaModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="alphaModels">The individual alpha models defining this composite model</param>
|
||||
public CompositeAlphaModel(params IAlphaModel[] alphaModels)
|
||||
{
|
||||
if (alphaModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 alpha model for the CompositeAlphaModel");
|
||||
}
|
||||
|
||||
_alphaModels.AddRange(alphaModels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeAlphaModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="alphaModels">The individual alpha models defining this composite model</param>
|
||||
public CompositeAlphaModel(params PyObject[] alphaModels)
|
||||
{
|
||||
if (alphaModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 alpha model for the CompositeAlphaModel");
|
||||
}
|
||||
|
||||
foreach (var pyAlphaModel in alphaModels)
|
||||
{
|
||||
AddAlpha(pyAlphaModel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this alpha model with the latest data from the algorithm.
|
||||
/// This is called each time the algorithm receives data for subscribed securities.
|
||||
/// This method patches this call through the each of the wrapped models.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="data">The new data available</param>
|
||||
/// <returns>The new insights generated</returns>
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
foreach (var model in _alphaModels)
|
||||
{
|
||||
var name = model.GetModelName();
|
||||
foreach (var insight in model.Update(algorithm, data))
|
||||
{
|
||||
if (string.IsNullOrEmpty(insight.SourceModel))
|
||||
{
|
||||
// set the source model name if not already set
|
||||
insight.SourceModel = name;
|
||||
}
|
||||
|
||||
yield return insight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed.
|
||||
/// This method patches this call through the each of the wrapped models.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
foreach (var model in _alphaModels)
|
||||
{
|
||||
model.OnSecuritiesChanged(algorithm, changes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="AlphaModel"/>
|
||||
/// </summary>
|
||||
/// <param name="alphaModel">The alpha model to add</param>
|
||||
public void AddAlpha(IAlphaModel alphaModel)
|
||||
{
|
||||
_alphaModels.Add(alphaModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="AlphaModel"/>
|
||||
/// </summary>
|
||||
/// <param name="pyAlphaModel">The alpha model to add</param>
|
||||
public void AddAlpha(PyObject pyAlphaModel)
|
||||
{
|
||||
var alphaModel = PythonUtil.CreateInstanceOrWrapper<IAlphaModel>(
|
||||
pyAlphaModel,
|
||||
py => new AlphaModelPythonWrapper(py)
|
||||
);
|
||||
_alphaModels.Add(alphaModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm framework model that produces insights
|
||||
/// </summary>
|
||||
public interface IAlphaModel : INotifiedSecurityChanges
|
||||
{
|
||||
/// <summary>
|
||||
/// Updates this alpha model with the latest data from the algorithm.
|
||||
/// This is called each time the algorithm receives data for subscribed securities
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="data">The new data available</param>
|
||||
/// <returns>The new insights generated</returns>
|
||||
IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a marker interface allowing models to define their own names.
|
||||
/// If not specified, the framework will use the model's type name.
|
||||
/// Implementation of this is not required unless you plan on running multiple models
|
||||
/// of the same type w/ different parameters.
|
||||
/// </summary>
|
||||
public interface INamedModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a name for a framework model
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 System.Linq;
|
||||
using QuantConnect.Data;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Alphas
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a null implementation of an alpha model
|
||||
/// </summary>
|
||||
public class NullAlphaModel : AlphaModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Updates this alpha model with the latest data from the algorithm.
|
||||
/// This is called each time the algorithm receives data for subscribed securities
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="data">The new data available</param>
|
||||
/// <returns>The new insights generated</returns>
|
||||
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
|
||||
{
|
||||
return Enumerable.Empty<Insight>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
# 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 NullAlphaModel(AlphaModel):
|
||||
'''Provides a null implementation of an alpha model'''
|
||||
|
||||
def update(self, algorithm, data):
|
||||
''' Determines an insight for each security based on it's current MACD signal
|
||||
Args:
|
||||
algorithm: The algorithm instance
|
||||
data: The new data available
|
||||
Returns:
|
||||
The new insights generated'''
|
||||
return []
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,777 @@
|
||||
/*
|
||||
* 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.Fundamental;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helpers for defining constituent universes based on the Morningstar
|
||||
/// asset classification <see cref="AssetClassification"/> https://www.morningstar.com/
|
||||
/// </summary>
|
||||
public class ConstituentUniverseDefinitions
|
||||
{
|
||||
private readonly IAlgorithm _algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies whose revenues and earnings have both been growing significantly faster than
|
||||
/// the general economy.
|
||||
/// </summary>
|
||||
public Universe AggressiveGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-AggressiveGrowth", SecurityType.Equity, Market.USA), "constituents-universe-AggressiveGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies that are growing respectably faster than the general economy, and often pay a
|
||||
/// steady dividend. They tend to be mature and solidly profitable businesses.
|
||||
/// </summary>
|
||||
public Universe ClassicGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-ClassicGrowth", SecurityType.Equity, Market.USA), "constituents-universe-ClassicGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies in the cyclicals and durables sectors, except those in the three types below.
|
||||
/// The profits of cyclicals tend to rise and fall with the general economy.
|
||||
/// </summary>
|
||||
public Universe Cyclicals(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Cyclicals", SecurityType.Equity, Market.USA), "constituents-universe-Cyclicals"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies that have had consistently declining cash flows and earnings over the past
|
||||
/// three years, and/or very high debt.
|
||||
/// </summary>
|
||||
public Universe Distressed(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Distressed", SecurityType.Equity, Market.USA), "constituents-universe-Distressed"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies that deal in assets such as oil, metals, and real estate, which tend to do
|
||||
/// well in inflationary environments.
|
||||
/// </summary>
|
||||
public Universe HardAsset(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-HardAsset", SecurityType.Equity, Market.USA), "constituents-universe-HardAsset"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies that have dividend yields at least twice the average for large-cap stocks.
|
||||
/// They tend to be mature, slow-growing companies.
|
||||
/// </summary>
|
||||
public Universe HighYield(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-HighYield", SecurityType.Equity, Market.USA), "constituents-universe-HighYield"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies that have shown slow revenue and earnings growth (typically less than the rate
|
||||
/// of GDP growth) over at least three years.
|
||||
/// </summary>
|
||||
public Universe SlowGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-SlowGrowth", SecurityType.Equity, Market.USA), "constituents-universe-SlowGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Universe"/> which selects companies that have shown strong revenue growth but slower or spotty earnings growth.
|
||||
/// Very small or young companies also tend to fall into this class.
|
||||
/// </summary>
|
||||
public Universe SpeculativeGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-SpeculativeGrowth", SecurityType.Equity, Market.USA), "constituents-universe-SpeculativeGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe LargeValue(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-LargeValue", SecurityType.Equity, Market.USA), "constituents-universe-LargeValue"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe LargeCore(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-LargeCore", SecurityType.Equity, Market.USA), "constituents-universe-LargeCore"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe LargeGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-LargeGrowth", SecurityType.Equity, Market.USA), "constituents-universe-LargeGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe MidValue(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MidValue", SecurityType.Equity, Market.USA), "constituents-universe-MidValue"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe MidCore(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MidCore", SecurityType.Equity, Market.USA), "constituents-universe-MidCore"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe MidGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MidGrowth", SecurityType.Equity, Market.USA), "constituents-universe-MidGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe SmallValue(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-SmallValue", SecurityType.Equity, Market.USA), "constituents-universe-SmallValue"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe SmallCore(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-SmallCore", SecurityType.Equity, Market.USA), "constituents-universe-SmallCore"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Classifies securities according to market capitalization and growth and value factor
|
||||
/// </summary>
|
||||
/// <remarks>Please refer to http://www.morningstar.com/InvGlossary/morningstar_style_box.aspx </remarks>
|
||||
public Universe SmallGrowth(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-SmallGrowth", SecurityType.Equity, Market.USA), "constituents-universe-SmallGrowth"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Agriculture industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Agriculture(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Agriculture", SecurityType.Equity, Market.USA), "constituents-universe-Agriculture"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar BuildingMaterials industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe BuildingMaterials(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-BuildingMaterials", SecurityType.Equity, Market.USA), "constituents-universe-BuildingMaterials"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Chemicals industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Chemicals(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Chemicals", SecurityType.Equity, Market.USA), "constituents-universe-Chemicals"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar ForestProducts industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe ForestProducts(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-ForestProducts", SecurityType.Equity, Market.USA), "constituents-universe-ForestProducts"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar MetalsAndMining industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe MetalsAndMining(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MetalsAndMining", SecurityType.Equity, Market.USA), "constituents-universe-MetalsAndMining"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Steel industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Steel(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Steel", SecurityType.Equity, Market.USA), "constituents-universe-Steel"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar VehiclesAndParts industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe VehiclesAndParts(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-VehiclesAndParts", SecurityType.Equity, Market.USA), "constituents-universe-VehiclesAndParts"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar FixturesAndAppliances industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe FixturesAndAppliances(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-FixturesAndAppliances", SecurityType.Equity, Market.USA), "constituents-universe-FixturesAndAppliances"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar HomebuildingAndConstruction industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe HomebuildingAndConstruction(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-HomebuildingAndConstruction", SecurityType.Equity, Market.USA), "constituents-universe-HomebuildingAndConstruction"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar ManufacturingApparelAndAccessories industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe ManufacturingApparelAndAccessories(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-ManufacturingApparelAndAccessories", SecurityType.Equity, Market.USA), "constituents-universe-ManufacturingApparelAndAccessories"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar PackagingAndContainers industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe PackagingAndContainers(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-PackagingAndContainers", SecurityType.Equity, Market.USA), "constituents-universe-PackagingAndContainers"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar PersonalServices industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe PersonalServices(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-PersonalServices", SecurityType.Equity, Market.USA), "constituents-universe-PersonalServices"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Restaurants industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Restaurants(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Restaurants", SecurityType.Equity, Market.USA), "constituents-universe-Restaurants"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar RetailCyclical industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe RetailCyclical(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-RetailCyclical", SecurityType.Equity, Market.USA), "constituents-universe-RetailCyclical"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar TravelAndLeisure industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe TravelAndLeisure(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-TravelAndLeisure", SecurityType.Equity, Market.USA), "constituents-universe-TravelAndLeisure"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar AssetManagement industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe AssetManagement(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-AssetManagement", SecurityType.Equity, Market.USA), "constituents-universe-AssetManagement"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Banks industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Banks(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Banks", SecurityType.Equity, Market.USA), "constituents-universe-Banks"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar CapitalMarkets industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe CapitalMarkets(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-CapitalMarkets", SecurityType.Equity, Market.USA), "constituents-universe-CapitalMarkets"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Insurance industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Insurance(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Insurance", SecurityType.Equity, Market.USA), "constituents-universe-Insurance"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar DiversifiedFinancialServices industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe DiversifiedFinancialServices(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-DiversifiedFinancialServices", SecurityType.Equity, Market.USA), "constituents-universe-DiversifiedFinancialServices"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar CreditServices industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe CreditServices(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-CreditServices", SecurityType.Equity, Market.USA), "constituents-universe-CreditServices"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar RealEstate industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe RealEstate(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-RealEstate", SecurityType.Equity, Market.USA), "constituents-universe-RealEstate"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar REITs industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe REITs(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-REITs", SecurityType.Equity, Market.USA), "constituents-universe-REITs"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar BeveragesAlcoholic industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe BeveragesAlcoholic(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-BeveragesAlcoholic", SecurityType.Equity, Market.USA), "constituents-universe-BeveragesAlcoholic"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar BeveragesNonAlcoholic industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe BeveragesNonAlcoholic(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-BeveragesNonAlcoholic", SecurityType.Equity, Market.USA), "constituents-universe-BeveragesNonAlcoholic"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar ConsumerPackagedGoods industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe ConsumerPackagedGoods(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-ConsumerPackagedGoods", SecurityType.Equity, Market.USA), "constituents-universe-ConsumerPackagedGoods"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Education industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Education(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Education", SecurityType.Equity, Market.USA), "constituents-universe-Education"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar RetailDefensive industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe RetailDefensive(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-RetailDefensive", SecurityType.Equity, Market.USA), "constituents-universe-RetailDefensive"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar TobaccoProducts industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe TobaccoProducts(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-TobaccoProducts", SecurityType.Equity, Market.USA), "constituents-universe-TobaccoProducts"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Biotechnology industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Biotechnology(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Biotechnology", SecurityType.Equity, Market.USA), "constituents-universe-Biotechnology"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar DrugManufacturers industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe DrugManufacturers(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-DrugManufacturers", SecurityType.Equity, Market.USA), "constituents-universe-DrugManufacturers"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar HealthcarePlans industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe HealthcarePlans(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-HealthcarePlans", SecurityType.Equity, Market.USA), "constituents-universe-HealthcarePlans"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar HealthcareProvidersAndServices industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe HealthcareProvidersAndServices(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-HealthcareProvidersAndServices", SecurityType.Equity, Market.USA), "constituents-universe-HealthcareProvidersAndServices"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar MedicalDevicesAndInstruments industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe MedicalDevicesAndInstruments(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MedicalDevicesAndInstruments", SecurityType.Equity, Market.USA), "constituents-universe-MedicalDevicesAndInstruments"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar MedicalDiagnosticsAndResearch industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe MedicalDiagnosticsAndResearch(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MedicalDiagnosticsAndResearch", SecurityType.Equity, Market.USA), "constituents-universe-MedicalDiagnosticsAndResearch"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar MedicalDistribution industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe MedicalDistribution(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MedicalDistribution", SecurityType.Equity, Market.USA), "constituents-universe-MedicalDistribution"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar UtilitiesIndependentPowerProducers industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe UtilitiesIndependentPowerProducers(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-UtilitiesIndependentPowerProducers", SecurityType.Equity, Market.USA), "constituents-universe-UtilitiesIndependentPowerProducers"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar UtilitiesRegulated industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe UtilitiesRegulated(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-UtilitiesRegulated", SecurityType.Equity, Market.USA), "constituents-universe-UtilitiesRegulated"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar TelecommunicationServices industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe TelecommunicationServices(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-TelecommunicationServices", SecurityType.Equity, Market.USA), "constituents-universe-TelecommunicationServices"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar MediaDiversified industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe MediaDiversified(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-MediaDiversified", SecurityType.Equity, Market.USA), "constituents-universe-MediaDiversified"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar InteractiveMedia industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe InteractiveMedia(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-InteractiveMedia", SecurityType.Equity, Market.USA), "constituents-universe-InteractiveMedia"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar OilAndGas industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe OilAndGas(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-OilAndGas", SecurityType.Equity, Market.USA), "constituents-universe-OilAndGas"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar OtherEnergySources industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe OtherEnergySources(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-OtherEnergySources", SecurityType.Equity, Market.USA), "constituents-universe-OtherEnergySources"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar AerospaceAndDefense industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe AerospaceAndDefense(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-AerospaceAndDefense", SecurityType.Equity, Market.USA), "constituents-universe-AerospaceAndDefense"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar BusinessServices industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe BusinessServices(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-BusinessServices", SecurityType.Equity, Market.USA), "constituents-universe-BusinessServices"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Conglomerates industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Conglomerates(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Conglomerates", SecurityType.Equity, Market.USA), "constituents-universe-Conglomerates"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Construction industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Construction(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Construction", SecurityType.Equity, Market.USA), "constituents-universe-Construction"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar FarmAndHeavyConstructionMachinery industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe FarmAndHeavyConstructionMachinery(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-FarmAndHeavyConstructionMachinery", SecurityType.Equity, Market.USA), "constituents-universe-FarmAndHeavyConstructionMachinery"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar IndustrialDistribution industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe IndustrialDistribution(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-IndustrialDistribution", SecurityType.Equity, Market.USA), "constituents-universe-IndustrialDistribution"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar IndustrialProducts industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe IndustrialProducts(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-IndustrialProducts", SecurityType.Equity, Market.USA), "constituents-universe-IndustrialProducts"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Transportation industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Transportation(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Transportation", SecurityType.Equity, Market.USA), "constituents-universe-Transportation"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar WasteManagement industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe WasteManagement(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-WasteManagement", SecurityType.Equity, Market.USA), "constituents-universe-WasteManagement"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Software industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Software(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Software", SecurityType.Equity, Market.USA), "constituents-universe-Software"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Hardware industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Hardware(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Hardware", SecurityType.Equity, Market.USA), "constituents-universe-Hardware"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Morningstar Semiconductors industry group <see cref="MorningstarIndustryGroupCode"/>
|
||||
/// </summary>
|
||||
public Universe Semiconductors(UniverseSettings universeSettings = null)
|
||||
{
|
||||
return new ConstituentsUniverse(
|
||||
new Symbol(SecurityIdentifier.GenerateConstituentIdentifier("constituents-universe-Semiconductors", SecurityType.Equity, Market.USA), "constituents-universe-Semiconductors"),
|
||||
universeSettings ?? _algorithm.UniverseSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConstituentUniverseDefinitions"/> class
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance, used for obtaining the default <see cref="UniverseSettings"/></param>
|
||||
public ConstituentUniverseDefinitions(IAlgorithm algorithm)
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 MathNet.Numerics.Statistics;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helpers for defining universes based on the daily dollar volume
|
||||
/// </summary>
|
||||
public class DollarVolumeUniverseDefinitions
|
||||
{
|
||||
private readonly QCAlgorithm _algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DollarVolumeUniverseDefinitions"/> class
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance, used for obtaining the default <see cref="UniverseSettings"/></param>
|
||||
public DollarVolumeUniverseDefinitions(QCAlgorithm algorithm)
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse <see cref="Universe"/> that contains the top count of stocks
|
||||
/// by daily dollar volume
|
||||
/// </summary>
|
||||
/// <param name="count">The number of stock to select</param>
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
[Obsolete("This method is deprecated. Use method `Universe.Top(...)` instead")]
|
||||
public Universe Top(int count, UniverseSettings universeSettings = null)
|
||||
{
|
||||
return _algorithm.Universe.Top(count, universeSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Python;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for execution models
|
||||
/// </summary>
|
||||
public class ExecutionModel : BasePythonWrapper<ExecutionModel>, IExecutionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, orders should be submitted asynchronously.
|
||||
/// </summary>
|
||||
protected bool Asynchronous { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExecutionModel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="asynchronous">If true, orders should be submitted asynchronously</param>
|
||||
public ExecutionModel(bool asynchronous = true)
|
||||
{
|
||||
Asynchronous = asynchronous;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submit orders for the specified portfolio targets.
|
||||
/// This model is free to delay or spread out these orders as it sees fit
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The portfolio targets just emitted by the portfolio construction model.
|
||||
/// These are always just the new/updated targets and not a complete set of targets</param>
|
||||
public virtual void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
throw new System.NotImplementedException("Types deriving from 'ExecutionModel' must implement the 'void Execute(QCAlgorithm, IPortfolioTarget[]) method.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public virtual void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// New order event handler
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="orderEvent">Order event to process</param>
|
||||
public virtual void OnOrderEvent(QCAlgorithm algorithm, OrderEvent orderEvent)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Python;
|
||||
using System;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IExecutionModel"/> that wraps a <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
public class ExecutionModelPythonWrapper : ExecutionModel
|
||||
{
|
||||
private readonly bool _onOrderEventsDefined;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for initialising the <see cref="IExecutionModel"/> class with wrapped <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
/// <param name="model">Model defining how to execute trades to reach a portfolio target</param>
|
||||
public ExecutionModelPythonWrapper(PyObject model)
|
||||
{
|
||||
SetPythonInstance(model, false);
|
||||
foreach (var attributeName in new[] { "Execute", "OnSecuritiesChanged" })
|
||||
{
|
||||
if (!HasAttr(attributeName))
|
||||
{
|
||||
throw new NotImplementedException($"IExecutionModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
|
||||
}
|
||||
}
|
||||
|
||||
_onOrderEventsDefined = HasAttr("OnOrderEvent");
|
||||
|
||||
var methodName = nameof(SetPythonInstance);
|
||||
if (HasAttr(methodName))
|
||||
{
|
||||
InvokeMethod(methodName, model);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submit orders for the specified portfolio targets.
|
||||
/// This model is free to delay or spread out these orders as it sees fit
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The portfolio targets to be ordered</param>
|
||||
public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
InvokeMethod(nameof(Execute), algorithm, targets).Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
InvokeMethod(nameof(OnSecuritiesChanged), algorithm, changes).Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// New order event handler
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="orderEvent">Order event to process</param>
|
||||
public override void OnOrderEvent(QCAlgorithm algorithm, OrderEvent orderEvent)
|
||||
{
|
||||
if (_onOrderEventsDefined)
|
||||
{
|
||||
InvokeMethod(nameof(OnOrderEvent), algorithm, orderEvent).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Orders;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm framework model that executes portfolio targets
|
||||
/// </summary>
|
||||
public interface IExecutionModel : INotifiedSecurityChanges
|
||||
{
|
||||
/// <summary>
|
||||
/// Submit orders for the specified portfolio targets.
|
||||
/// This model is free to delay or spread out these orders as it sees fit
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The portfolio targets just emitted by the portfolio construction model.
|
||||
/// These are always just the new/updated targets and not a complete set of targets</param>
|
||||
void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets);
|
||||
|
||||
/// <summary>
|
||||
/// New order event handler
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="orderEvent">Order event to process</param>
|
||||
void OnOrderEvent(QCAlgorithm algorithm, OrderEvent orderEvent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.Orders;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IExecutionModel"/> that immediately submits
|
||||
/// market orders to achieve the desired portfolio targets
|
||||
/// </summary>
|
||||
public class ImmediateExecutionModel : ExecutionModel
|
||||
{
|
||||
private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImmediateExecutionModel"/> class.
|
||||
/// </summary>
|
||||
/// <param name="asynchronous">If true, orders will be submitted asynchronously</param>
|
||||
public ImmediateExecutionModel(bool asynchronous = true)
|
||||
: base(asynchronous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Immediately submits orders for the specified portfolio targets.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The portfolio targets to be ordered</param>
|
||||
public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
_targetsCollection.AddRange(targets);
|
||||
// for performance we if empty, OrderByMarginImpact and ClearFulfilled are expensive to call
|
||||
if (!_targetsCollection.IsEmpty)
|
||||
{
|
||||
foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
|
||||
{
|
||||
var security = algorithm.Securities[target.Symbol];
|
||||
|
||||
// calculate remaining quantity to be ordered
|
||||
var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target, security, true);
|
||||
|
||||
if (quantity != 0)
|
||||
{
|
||||
if (security.BuyingPowerModel.AboveMinimumOrderMarginPortfolioPercentage(security, quantity,
|
||||
algorithm.Portfolio, algorithm.Settings.MinimumOrderMarginPortfolioPercentage))
|
||||
{
|
||||
algorithm.MarketOrder(security, quantity, Asynchronous, target.Tag);
|
||||
}
|
||||
else if (!PortfolioTarget.MinimumOrderMarginPercentageWarningSent.HasValue)
|
||||
{
|
||||
// will trigger the warning if it has not already been sent
|
||||
PortfolioTarget.MinimumOrderMarginPercentageWarningSent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_targetsCollection.ClearFulfilled(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# 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 ImmediateExecutionModel(ExecutionModel):
|
||||
'''Provides an implementation of IExecutionModel that immediately submits market orders to achieve the desired portfolio targets'''
|
||||
|
||||
def __init__(self, asynchronous=True):
|
||||
'''Initializes a new instance of the ImmediateExecutionModel class.
|
||||
Args:
|
||||
asynchronous: If True, orders will be submitted asynchronously.'''
|
||||
super().__init__(asynchronous)
|
||||
self.targets_collection = PortfolioTargetCollection()
|
||||
|
||||
def execute(self, algorithm, targets):
|
||||
'''Immediately submits orders for the specified portfolio targets.
|
||||
Args:
|
||||
algorithm: The algorithm instance
|
||||
targets: The portfolio targets to be ordered'''
|
||||
# for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
|
||||
self.targets_collection.add_range(targets)
|
||||
if not self.targets_collection.is_empty:
|
||||
for target in self.targets_collection.order_by_margin_impact(algorithm):
|
||||
security = algorithm.securities[target.symbol]
|
||||
# calculate remaining quantity to be ordered
|
||||
quantity = OrderSizing.get_unordered_quantity(algorithm, target, security, True)
|
||||
|
||||
if quantity != 0:
|
||||
above_minimum_portfolio = BuyingPowerModelExtensions.above_minimum_order_margin_portfolio_percentage(
|
||||
security.buying_power_model,
|
||||
security,
|
||||
quantity,
|
||||
algorithm.portfolio,
|
||||
algorithm.settings.minimum_order_margin_portfolio_percentage)
|
||||
if above_minimum_portfolio:
|
||||
algorithm.market_order(security, quantity, self.asynchronous, target.tag)
|
||||
elif not PortfolioTarget.minimum_order_margin_percentage_warning_sent:
|
||||
# will trigger the warning if it has not already been sent
|
||||
PortfolioTarget.minimum_order_margin_percentage_warning_sent = False
|
||||
|
||||
self.targets_collection.clear_fulfilled(algorithm)
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Execution
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IExecutionModel"/> that does nothing
|
||||
/// </summary>
|
||||
public class NullExecutionModel : ExecutionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute the ExecutionModel
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The Algorithm to execute this model on</param>
|
||||
/// <param name="targets">The portfolio targets</param>
|
||||
public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# 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 NullExecutionModel(ExecutionModel):
|
||||
'''Provides an implementation of IExecutionModel that does nothing'''
|
||||
def execute(self, algorithm, targets):
|
||||
pass
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Types implementing this interface will be called when the algorithm's set of securities changes
|
||||
/// </summary>
|
||||
public interface INotifiedSecurityChanges
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Alphas;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm framework model that
|
||||
/// </summary>
|
||||
public interface IPortfolioConstructionModel : INotifiedSecurityChanges
|
||||
{
|
||||
/// <summary>
|
||||
/// Create portfolio targets from the specified insights
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="insights">The insights to create portfolio targets from</param>
|
||||
/// <returns>An enumerable of portfolio targets to be sent to the execution model</returns>
|
||||
IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for portfolio optimization algorithms
|
||||
/// </summary>
|
||||
public interface IPortfolioOptimizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform portfolio optimization for a provided matrix of historical returns and an array of expected returns
|
||||
/// </summary>
|
||||
/// <param name="historicalReturns">Matrix of annualized historical returns where each column represents a security and each row returns for the given date/time (size: K x N).</param>
|
||||
/// <param name="expectedReturns">Array of double with the portfolio annualized expected returns (size: K x 1).</param>
|
||||
/// <param name="covariance">Multi-dimensional array of double with the portfolio covariance of annualized returns (size: K x K).</param>
|
||||
/// <returns>Array of double with the portfolio weights (size: K x 1)</returns>
|
||||
double[] Optimize(double[,] historicalReturns, double[] expectedReturns = null, double[,] covariance = null);
|
||||
}
|
||||
}
|
||||
@@ -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 System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IPortfolioConstructionModel"/> that does nothing
|
||||
/// </summary>
|
||||
public class NullPortfolioConstructionModel : PortfolioConstructionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Create Targets; Does nothing in this implementation and returns an empty IEnumerable
|
||||
/// </summary>
|
||||
/// <returns>Empty IEnumerable of <see cref="IPortfolioTarget"/>s</returns>
|
||||
public override IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
return Enumerable.Empty<IPortfolioTarget>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# 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 NullPortfolioConstructionModel(PortfolioConstructionModel):
|
||||
'''Provides an implementation of IPortfolioConstructionModel that does nothing'''
|
||||
def create_targets(self, algorithm, insights):
|
||||
return []
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the bias of the portfolio (Short, Long/Short, Long)
|
||||
/// </summary>
|
||||
public enum PortfolioBias
|
||||
{
|
||||
/// <summary>
|
||||
/// Portfolio can only have short positions (-1)
|
||||
/// </summary>
|
||||
Short = -1,
|
||||
|
||||
/// <summary>
|
||||
/// Portfolio can have both long and short positions (0)
|
||||
/// </summary>
|
||||
LongShort = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Portfolio can only have long positions (1)
|
||||
/// </summary>
|
||||
Long = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Scheduling;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for portfolio construction models
|
||||
/// </summary>
|
||||
public class PortfolioConstructionModel : IPortfolioConstructionModel
|
||||
{
|
||||
private Func<DateTime, DateTime?> _rebalancingFunc;
|
||||
private DateTime? _rebalancingTime;
|
||||
private bool _securityChanges;
|
||||
|
||||
/// <summary>
|
||||
/// True if should rebalance portfolio on security changes. True by default
|
||||
/// </summary>
|
||||
public virtual bool RebalanceOnSecurityChanges { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// True if should rebalance portfolio on new insights or expiration of insights. True by default
|
||||
/// </summary>
|
||||
public virtual bool RebalanceOnInsightChanges { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The algorithm instance
|
||||
/// </summary>
|
||||
protected IAlgorithm Algorithm { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is required due to a limitation in PythonNet to resolved overriden methods.
|
||||
/// When Python calls a C# method that calls a method that's overriden in python it won't
|
||||
/// run the python implementation unless the call is performed through python too.
|
||||
/// </summary>
|
||||
protected PortfolioConstructionModelPythonWrapper PythonWrapper { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a new instance of <see cref="PortfolioConstructionModel"/>
|
||||
/// </summary>
|
||||
/// <param name="rebalancingFunc">For a given algorithm UTC DateTime returns the next expected rebalance time
|
||||
/// or null if unknown, in which case the function will be called again in the next loop. Returning current time
|
||||
/// will trigger rebalance. If null will be ignored</param>
|
||||
public PortfolioConstructionModel(Func<DateTime, DateTime?> rebalancingFunc)
|
||||
{
|
||||
_rebalancingFunc = rebalancingFunc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a new instance of <see cref="PortfolioConstructionModel"/>
|
||||
/// </summary>
|
||||
/// <param name="rebalancingFunc">For a given algorithm UTC DateTime returns the next expected rebalance UTC time.
|
||||
/// Returning current time will trigger rebalance. If null will be ignored</param>
|
||||
public PortfolioConstructionModel(Func<DateTime, DateTime> rebalancingFunc = null)
|
||||
: this(rebalancingFunc != null ? (Func<DateTime, DateTime?>)(timeUtc => rebalancingFunc(timeUtc)) : null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to set the <see cref="PortfolioConstructionModelPythonWrapper"/> instance if any
|
||||
/// </summary>
|
||||
protected void SetPythonWrapper(PortfolioConstructionModelPythonWrapper pythonWrapper)
|
||||
{
|
||||
PythonWrapper = pythonWrapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create portfolio targets from the specified insights
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="insights">The insights to create portfolio targets from</param>
|
||||
/// <returns>An enumerable of portfolio targets to be sent to the execution model</returns>
|
||||
public virtual IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
Algorithm = algorithm;
|
||||
|
||||
if (!(PythonWrapper?.IsRebalanceDue(insights, algorithm.UtcTime)
|
||||
?? IsRebalanceDue(insights, algorithm.UtcTime)))
|
||||
{
|
||||
return Enumerable.Empty<IPortfolioTarget>();
|
||||
}
|
||||
|
||||
var targets = new List<IPortfolioTarget>();
|
||||
|
||||
var lastActiveInsights = PythonWrapper?.GetTargetInsights()
|
||||
?? GetTargetInsights();
|
||||
|
||||
var errorSymbols = new HashSet<Symbol>();
|
||||
|
||||
// Determine target percent for the given insights
|
||||
var percents = PythonWrapper?.DetermineTargetPercent(lastActiveInsights)
|
||||
?? DetermineTargetPercent(lastActiveInsights);
|
||||
|
||||
foreach (var insight in lastActiveInsights)
|
||||
{
|
||||
if (!percents.TryGetValue(insight, out var percent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var target = PortfolioTarget.Percent(algorithm, insight.Symbol, percent);
|
||||
if (target != null)
|
||||
{
|
||||
targets.Add(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
errorSymbols.Add(insight.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Get expired insights and create flatten targets for each symbol
|
||||
var expiredInsights = Algorithm.Insights.RemoveExpiredInsights(algorithm.UtcTime);
|
||||
|
||||
var expiredTargets = from insight in expiredInsights
|
||||
group insight.Symbol by insight.Symbol into g
|
||||
where !Algorithm.Insights.HasActiveInsights(g.Key, algorithm.UtcTime) && !errorSymbols.Contains(g.Key)
|
||||
select new PortfolioTarget(g.Key, 0);
|
||||
|
||||
targets.AddRange(expiredTargets);
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public virtual void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
Algorithm ??= algorithm;
|
||||
|
||||
_securityChanges = changes != SecurityChanges.None;
|
||||
// Get removed symbol and invalidate them in the insight collection
|
||||
var removedSymbols = changes.RemovedSecurities.Select(x => x.Symbol);
|
||||
algorithm?.Insights.Expire(removedSymbols);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target insights to calculate a portfolio target percent for
|
||||
/// </summary>
|
||||
/// <returns>An enumerable of the target insights</returns>
|
||||
protected virtual List<Insight> GetTargetInsights()
|
||||
{
|
||||
// Validate we should create a target for this insight
|
||||
bool IsValidInsight(Insight insight) => PythonWrapper?.ShouldCreateTargetForInsight(insight)
|
||||
?? ShouldCreateTargetForInsight(insight);
|
||||
|
||||
// Get insight that haven't expired of each symbol that is still in the universe
|
||||
var activeInsights = Algorithm.Insights.GetActiveInsights(Algorithm.UtcTime).Where(IsValidInsight);
|
||||
|
||||
// Get the last generated active insight for each symbol
|
||||
return (from insight in activeInsights
|
||||
group insight by insight.Symbol into g
|
||||
select g.OrderBy(x => x.GeneratedTimeUtc).Last()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method that will determine if the portfolio construction model should create a
|
||||
/// target for this insight
|
||||
/// </summary>
|
||||
/// <param name="insight">The insight to create a target for</param>
|
||||
/// <returns>True if the portfolio should create a target for the insight</returns>
|
||||
protected virtual bool ShouldCreateTargetForInsight(Insight insight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will determine the target percent for each insight
|
||||
/// </summary>
|
||||
/// <param name="activeInsights">The active insights to generate a target for</param>
|
||||
/// <returns>A target percent for each insight</returns>
|
||||
protected virtual Dictionary<Insight, double> DetermineTargetPercent(List<Insight> activeInsights)
|
||||
{
|
||||
throw new NotImplementedException("Types deriving from 'PortfolioConstructionModel' must implement the 'Dictionary<Insight, double> DetermineTargetPercent(ICollection<Insight>)' method.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Python helper method to set the rebalancing function.
|
||||
/// This is required due to a python net limitation not being able to use the base type constructor, and also because
|
||||
/// when python algorithms use C# portfolio construction models, it can't convert python methods into func nor resolve
|
||||
/// the correct constructor for the date rules, timespan parameter.
|
||||
/// For performance we prefer python algorithms using the C# implementation
|
||||
/// </summary>
|
||||
/// <param name="rebalance">Rebalancing func or if a date rule, timedelta will be converted into func.
|
||||
/// For a given algorithm UTC DateTime the func returns the next expected rebalance time
|
||||
/// or null if unknown, in which case the function will be called again in the next loop. Returning current time
|
||||
/// will trigger rebalance. If null will be ignored</param>
|
||||
protected void SetRebalancingFunc(PyObject rebalance)
|
||||
{
|
||||
IDateRule dateRules;
|
||||
TimeSpan timeSpan;
|
||||
if (rebalance.TryConvert(out dateRules))
|
||||
{
|
||||
_rebalancingFunc = dateRules.ToFunc();
|
||||
}
|
||||
else if (!rebalance.TrySafeAs(out _rebalancingFunc))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
// try convert does not work for timespan
|
||||
timeSpan = rebalance.As<TimeSpan>();
|
||||
if (timeSpan != default(TimeSpan))
|
||||
{
|
||||
_rebalancingFunc = time => time.Add(timeSpan);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_rebalancingFunc = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the portfolio should be rebalanced base on the provided rebalancing func,
|
||||
/// if any security change have been taken place or if an insight has expired or a new insight arrived
|
||||
/// If the rebalancing function has not been provided will return true.
|
||||
/// </summary>
|
||||
/// <param name="insights">The insights to create portfolio targets from</param>
|
||||
/// <param name="algorithmUtc">The current algorithm UTC time</param>
|
||||
/// <returns>True if should rebalance</returns>
|
||||
protected virtual bool IsRebalanceDue(Insight[] insights, DateTime algorithmUtc)
|
||||
{
|
||||
// if there is no rebalance func set, just return true but refresh state
|
||||
// just in case the rebalance func is going to be set.
|
||||
if (_rebalancingFunc == null)
|
||||
{
|
||||
RefreshRebalance(algorithmUtc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// we always get the next expiry time
|
||||
// we don't know if a new insight was added or removed
|
||||
var nextInsightExpiryTime = Algorithm.Insights.GetNextExpiryTime();
|
||||
|
||||
if (_rebalancingTime == null)
|
||||
{
|
||||
_rebalancingTime = _rebalancingFunc(algorithmUtc);
|
||||
|
||||
if (_rebalancingTime != null && _rebalancingTime <= algorithmUtc)
|
||||
{
|
||||
// if the rebalancing time stopped being null and is current time
|
||||
// we will ask for the next rebalance time in the next loop.
|
||||
// we don't want to call the '_rebalancingFunc' twice in the same loop,
|
||||
// since its internal state machine will probably be in the same state.
|
||||
_rebalancingTime = null;
|
||||
_securityChanges = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_rebalancingTime != null && _rebalancingTime <= algorithmUtc
|
||||
|| RebalanceOnSecurityChanges && _securityChanges
|
||||
|| RebalanceOnInsightChanges
|
||||
&& (insights.Length != 0
|
||||
|| nextInsightExpiryTime != null && nextInsightExpiryTime < algorithmUtc))
|
||||
{
|
||||
RefreshRebalance(algorithmUtc);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh the next rebalance time and clears the security changes flag
|
||||
/// </summary>
|
||||
protected void RefreshRebalance(DateTime algorithmUtc)
|
||||
{
|
||||
if (_rebalancingFunc != null)
|
||||
{
|
||||
_rebalancingTime = _rebalancingFunc(algorithmUtc);
|
||||
}
|
||||
_securityChanges = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class that can be used by the different <see cref="IPortfolioConstructionModel"/>
|
||||
/// implementations to filter <see cref="Insight"/> instances with an invalid
|
||||
/// <see cref="Insight.Magnitude"/> value based on the <see cref="IAlgorithmSettings"/>
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="insights">The insight collection to filter</param>
|
||||
/// <returns>Returns a new array of insights removing invalid ones</returns>
|
||||
protected static Insight[] FilterInvalidInsightMagnitude(IAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
var result = insights.Where(insight =>
|
||||
{
|
||||
if (!insight.Magnitude.HasValue || insight.Magnitude == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var absoluteMagnitude = Math.Abs(insight.Magnitude.Value);
|
||||
if (absoluteMagnitude > (double)algorithm.Settings.MaxAbsolutePortfolioTargetPercentage
|
||||
|| absoluteMagnitude < (double)algorithm.Settings.MinAbsolutePortfolioTargetPercentage)
|
||||
{
|
||||
algorithm.Error("PortfolioConstructionModel.FilterInvalidInsightMagnitude():" +
|
||||
$"The insight target Magnitude: {insight.Magnitude}, will not comply with the current " +
|
||||
$"'Algorithm.Settings' 'MaxAbsolutePortfolioTargetPercentage': {algorithm.Settings.MaxAbsolutePortfolioTargetPercentage}" +
|
||||
$" or 'MinAbsolutePortfolioTargetPercentage': {algorithm.Settings.MinAbsolutePortfolioTargetPercentage}. Skipping insight."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
return result.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Python;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Portfolio
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IPortfolioConstructionModel"/> that wraps a <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
public class PortfolioConstructionModelPythonWrapper : PortfolioConstructionModel
|
||||
{
|
||||
private readonly BasePythonWrapper<PortfolioConstructionModel> _model;
|
||||
private readonly bool _implementsDetermineTargetPercent;
|
||||
|
||||
/// <summary>
|
||||
/// True if should rebalance portfolio on security changes. True by default
|
||||
/// </summary>
|
||||
public override bool RebalanceOnSecurityChanges
|
||||
{
|
||||
get
|
||||
{
|
||||
return _model.GetProperty<bool>(nameof(RebalanceOnSecurityChanges));
|
||||
}
|
||||
set
|
||||
{
|
||||
_model.SetProperty(nameof(RebalanceOnSecurityChanges), value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if should rebalance portfolio on new insights or expiration of insights. True by default
|
||||
/// </summary>
|
||||
public override bool RebalanceOnInsightChanges
|
||||
{
|
||||
get
|
||||
{
|
||||
return _model.GetProperty<bool>(nameof(RebalanceOnInsightChanges));
|
||||
}
|
||||
set
|
||||
{
|
||||
_model.SetProperty(nameof(RebalanceOnInsightChanges), value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for initialising the <see cref="IPortfolioConstructionModel"/> class with wrapped <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
/// <param name="model">Model defining how to build a portfolio from alphas</param>
|
||||
public PortfolioConstructionModelPythonWrapper(PyObject model)
|
||||
{
|
||||
_model = new BasePythonWrapper<PortfolioConstructionModel>(model, false);
|
||||
using (Py.GIL())
|
||||
{
|
||||
foreach (var attributeName in new[] { "CreateTargets", "OnSecuritiesChanged" })
|
||||
{
|
||||
if (!_model.HasAttr(attributeName))
|
||||
{
|
||||
throw new NotImplementedException($"IPortfolioConstructionModel.{attributeName} must be implemented. Please implement this missing method on {model.GetPythonType()}");
|
||||
}
|
||||
}
|
||||
|
||||
_model.InvokeVoidMethod(nameof(SetPythonWrapper), this);
|
||||
|
||||
_implementsDetermineTargetPercent = model.GetPythonMethod("DetermineTargetPercent") != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create portfolio targets from the specified insights
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="insights">The insights to create portfolio targets from</param>
|
||||
/// <returns>An enumerable of portfolio targets to be sent to the execution model</returns>
|
||||
public override IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
|
||||
{
|
||||
return _model.InvokeMethodAndEnumerate<IPortfolioTarget>(nameof(CreateTargets), algorithm, insights);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
_model.InvokeVoidMethod(nameof(OnSecuritiesChanged), algorithm, changes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method that will determine if the portfolio construction model should create a
|
||||
/// target for this insight
|
||||
/// </summary>
|
||||
/// <param name="insight">The insight to create a target for</param>
|
||||
/// <returns>True if the portfolio should create a target for the insight</returns>
|
||||
protected override bool ShouldCreateTargetForInsight(Insight insight)
|
||||
{
|
||||
return _model.InvokeMethod<bool>(nameof(ShouldCreateTargetForInsight), insight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the portfolio should be rebalanced base on the provided rebalancing func,
|
||||
/// if any security change have been taken place or if an insight has expired or a new insight arrived
|
||||
/// If the rebalancing function has not been provided will return true.
|
||||
/// </summary>
|
||||
/// <param name="insights">The insights to create portfolio targets from</param>
|
||||
/// <param name="algorithmUtc">The current algorithm UTC time</param>
|
||||
/// <returns>True if should rebalance</returns>
|
||||
protected override bool IsRebalanceDue(Insight[] insights, DateTime algorithmUtc)
|
||||
{
|
||||
return _model.InvokeMethod<bool>(nameof(IsRebalanceDue), insights, algorithmUtc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target insights to calculate a portfolio target percent for
|
||||
/// </summary>
|
||||
/// <returns>An enumerable of the target insights</returns>
|
||||
protected override List<Insight> GetTargetInsights()
|
||||
{
|
||||
return _model.InvokeMethod<List<Insight>>(nameof(GetTargetInsights));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will determine the target percent for each insight
|
||||
/// </summary>
|
||||
/// <param name="activeInsights">The active insights to generate a target for</param>
|
||||
/// <returns>A target percent for each insight</returns>
|
||||
protected override Dictionary<Insight, double> DetermineTargetPercent(List<Insight> activeInsights)
|
||||
{
|
||||
if (!_implementsDetermineTargetPercent)
|
||||
{
|
||||
// the implementation is in C#
|
||||
return _model.InvokeMethod<Dictionary<Insight, double>>(nameof(DetermineTargetPercent), activeInsights);
|
||||
}
|
||||
|
||||
return _model.InvokeMethodAndGetDictionary<Insight, double>(nameof(DetermineTargetPercent), activeInsights);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("QuantConnect.Algorithm")]
|
||||
[assembly: AssemblyProduct("QuantConnect.Algorithm")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("5396be58-69fe-437e-8dd1-92c2aa7e9f14")]
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
public partial class QCAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void SetAlpha(PyObject alpha)
|
||||
{
|
||||
Alpha = PythonUtil.CreateInstanceOrWrapper<IAlphaModel>(
|
||||
alpha,
|
||||
py => new AlphaModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void AddAlpha(PyObject alpha)
|
||||
{
|
||||
var model = PythonUtil.CreateInstanceOrWrapper<IAlphaModel>(
|
||||
alpha,
|
||||
py => new AlphaModelPythonWrapper(py)
|
||||
);
|
||||
AddAlpha(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the execution model
|
||||
/// </summary>
|
||||
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetExecution(PyObject execution)
|
||||
{
|
||||
Execution = PythonUtil.CreateInstanceOrWrapper<IExecutionModel>(
|
||||
execution,
|
||||
py => new ExecutionModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the portfolio construction model
|
||||
/// </summary>
|
||||
/// <param name="portfolioConstruction">Model defining how to build a portfolio from alphas</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetPortfolioConstruction(PyObject portfolioConstruction)
|
||||
{
|
||||
PortfolioConstruction = PythonUtil.CreateInstanceOrWrapper<IPortfolioConstructionModel>(
|
||||
portfolioConstruction,
|
||||
py => new PortfolioConstructionModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void SetUniverseSelection(PyObject universeSelection)
|
||||
{
|
||||
UniverseSelection = PythonUtil.CreateInstanceOrWrapper<IUniverseSelectionModel>(
|
||||
universeSelection,
|
||||
py => new UniverseSelectionModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseSelection(PyObject universeSelection)
|
||||
{
|
||||
var model = PythonUtil.CreateInstanceOrWrapper<IUniverseSelectionModel>(
|
||||
universeSelection,
|
||||
py => new UniverseSelectionModelPythonWrapper(py)
|
||||
);
|
||||
AddUniverseSelection(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetRiskManagement(PyObject riskManagement)
|
||||
{
|
||||
RiskManagement = PythonUtil.CreateInstanceOrWrapper<IRiskManagementModel>(
|
||||
riskManagement,
|
||||
py => new RiskManagementModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void AddRiskManagement(PyObject riskManagement)
|
||||
{
|
||||
var model = PythonUtil.CreateInstanceOrWrapper<IRiskManagementModel>(
|
||||
riskManagement,
|
||||
py => new RiskManagementModelPythonWrapper(py)
|
||||
);
|
||||
AddRiskManagement(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* 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.Linq;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Util;
|
||||
using QuantConnect.Securities;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Algorithm.Framework.Risk;
|
||||
using QuantConnect.Algorithm.Framework.Alphas;
|
||||
using QuantConnect.Algorithm.Framework.Execution;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Algorithm.Framework.Selection;
|
||||
using QuantConnect.Algorithm.Framework.Alphas.Analysis;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
public partial class QCAlgorithm
|
||||
{
|
||||
// this is so that later during 'UniverseSelection.CreateUniverses' we wont remove the user universes from the UniverseManager
|
||||
private readonly HashSet<Symbol> _universeSelectionUniverses = new ();
|
||||
private bool _isEmitWarmupInsightWarningSent;
|
||||
private bool _isEmitDelistedInsightWarningSent;
|
||||
|
||||
/// <summary>
|
||||
/// Enables additional logging of framework models including:
|
||||
/// All insights, portfolio targets, order events, and any risk management altered targets
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Logging)]
|
||||
public bool DebugMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the universe selection model.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IUniverseSelectionModel UniverseSelection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alpha model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IAlphaModel Alpha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the insight manager
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public InsightManager Insights { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the portfolio construction model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IPortfolioConstructionModel PortfolioConstruction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the execution model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IExecutionModel Execution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the risk management model
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public IRiskManagementModel RiskManagement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called by setup handlers after <see cref="Initialize"/> and allows the algorithm a chance to organize
|
||||
/// the data gather in the <see cref="Initialize"/> method
|
||||
/// </summary>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void FrameworkPostInitialize()
|
||||
{
|
||||
foreach (var universe in UniverseSelection.CreateUniverses(this))
|
||||
{
|
||||
AddUniverse(universe);
|
||||
_universeSelectionUniverses.Add(universe.Configuration.Symbol);
|
||||
}
|
||||
|
||||
if (DebugMode)
|
||||
{
|
||||
InsightsGenerated += (algorithm, data) => Log($"{Time}: {string.Join(" | ", data.Insights.OrderBy(i => i.Symbol.ToString()))}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to send data updates to algorithm framework models
|
||||
/// </summary>
|
||||
/// <param name="slice">The current data <see cref="Slice"/></param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(HandlingData)]
|
||||
public void OnFrameworkData(Slice slice)
|
||||
{
|
||||
if (UtcTime >= UniverseSelection.GetNextRefreshTimeUtc())
|
||||
{
|
||||
// remove deselected universes by symbol before we create new universes
|
||||
foreach (var ukvp in UniverseManager.Where(kvp => kvp.Value.DisposeRequested))
|
||||
{
|
||||
var universeSymbol = ukvp.Key;
|
||||
// have to remove in the next loop after the universe is marked as disposed, when 'Dispose()' is called it will trigger universe selection
|
||||
// and deselect all symbols, sending the removed security changes, which are picked up by the AlgorithmManager and tags securities
|
||||
// as non tradable as long as they are not active in any universe (uses UniverseManager.ActiveSecurities)
|
||||
// but they will remain tradable if a position is still being hold since they won't be remove from the UniverseManager
|
||||
// but this last part will not happen if we remove the universe from the UniverseManager right away, since it won't be part of 'UniverseManager'.
|
||||
// And we have to remove the universe even if it's present at 'universes' because that one is another New universe that should get added!
|
||||
// 'UniverseManager' will skip duplicate entries getting added.
|
||||
UniverseManager.Remove(universeSymbol);
|
||||
_universeSelectionUniverses.Remove(universeSymbol);
|
||||
}
|
||||
|
||||
var toRemove = new HashSet<Symbol>(_universeSelectionUniverses);
|
||||
foreach (var universe in UniverseSelection.CreateUniverses(this))
|
||||
{
|
||||
// add newly selected universes
|
||||
_universeSelectionUniverses.Add(universe.Configuration.Symbol);
|
||||
AddUniverse(universe);
|
||||
|
||||
toRemove.Remove(universe.Configuration.Symbol);
|
||||
}
|
||||
|
||||
// remove deselected universes by symbol but prevent removal of qc algorithm created user defined universes
|
||||
foreach (var universeSymbol in toRemove)
|
||||
{
|
||||
// mark this universe as disposed to remove all child subscriptions
|
||||
UniverseManager[universeSymbol].Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// update scores
|
||||
Insights.Step(UtcTime);
|
||||
|
||||
// we only want to run universe selection if there's no data available in the slice
|
||||
if (!slice.HasData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// insight timestamping handled via InsightsGenerated event handler
|
||||
var insightsEnumerable = Alpha.Update(this, slice);
|
||||
// for performance only call 'ToArray' if not empty enumerable (which is static)
|
||||
var insights = insightsEnumerable == Enumerable.Empty<Insight>()
|
||||
? new Insight[] { } : insightsEnumerable.ToArray();
|
||||
|
||||
// only fire insights generated event if we actually have insights
|
||||
if (insights.Length != 0)
|
||||
{
|
||||
insights = InitializeInsights(insights);
|
||||
OnInsightsGenerated(insights);
|
||||
}
|
||||
|
||||
ProcessInsights(insights);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// They different framework models will process the new provided <see cref="Insight"/>.
|
||||
/// The <see cref="IPortfolioConstructionModel"/> will create targets,
|
||||
/// the <see cref="IRiskManagementModel"/> will adjust the targets
|
||||
/// and the <see cref="IExecutionModel"/> will execute the <see cref="IPortfolioTarget"/>
|
||||
/// </summary>
|
||||
/// <param name="insights">The <see cref="Insight"/> to process</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
private void ProcessInsights(Insight[] insights)
|
||||
{
|
||||
// construct portfolio targets from insights
|
||||
var targetsEnumerable = PortfolioConstruction.CreateTargets(this, insights);
|
||||
// for performance only call 'ToArray' if not empty enumerable (which is static)
|
||||
var targets = targetsEnumerable == Enumerable.Empty<IPortfolioTarget>()
|
||||
? new IPortfolioTarget[] { } : targetsEnumerable.ToArray();
|
||||
|
||||
// set security targets w/ those generated via portfolio construction module
|
||||
foreach (var target in targets)
|
||||
{
|
||||
var security = Securities[target.Symbol];
|
||||
security.Holdings.Target = target;
|
||||
}
|
||||
|
||||
if (DebugMode)
|
||||
{
|
||||
// debug printing of generated targets
|
||||
if (targets.Length > 0)
|
||||
{
|
||||
Log($"{Time}: PORTFOLIO: {string.Join(" | ", targets.Select(t => t.ToString()).OrderBy(t => t))}");
|
||||
}
|
||||
}
|
||||
|
||||
var riskTargetOverridesEnumerable = RiskManagement.ManageRisk(this, targets);
|
||||
// for performance only call 'ToArray' if not empty enumerable (which is static)
|
||||
var riskTargetOverrides = riskTargetOverridesEnumerable == Enumerable.Empty<IPortfolioTarget>()
|
||||
? new IPortfolioTarget[] { } : riskTargetOverridesEnumerable.ToArray();
|
||||
|
||||
// override security targets w/ those generated via risk management module
|
||||
foreach (var target in riskTargetOverrides)
|
||||
{
|
||||
var security = Securities[target.Symbol];
|
||||
security.Holdings.Target = target;
|
||||
}
|
||||
|
||||
if (DebugMode)
|
||||
{
|
||||
// debug printing of generated risk target overrides
|
||||
if (riskTargetOverrides.Length > 0)
|
||||
{
|
||||
Log($"{Time}: RISK: {string.Join(" | ", riskTargetOverrides.Select(t => t.ToString()).OrderBy(t => t))}");
|
||||
}
|
||||
}
|
||||
|
||||
IPortfolioTarget[] riskAdjustedTargets;
|
||||
// for performance we check the length before
|
||||
if (riskTargetOverrides.Length != 0
|
||||
|| targets.Length != 0)
|
||||
{
|
||||
// execute on the targets, overriding targets for symbols w/ risk targets
|
||||
riskAdjustedTargets = riskTargetOverrides.Concat(targets).DistinctBy(pt => pt.Symbol).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
riskAdjustedTargets = new IPortfolioTarget[] { };
|
||||
}
|
||||
|
||||
if (DebugMode)
|
||||
{
|
||||
// only log adjusted targets if we've performed an adjustment
|
||||
if (riskTargetOverrides.Length > 0)
|
||||
{
|
||||
Log($"{Time}: RISK ADJUSTED TARGETS: {string.Join(" | ", riskAdjustedTargets.Select(t => t.ToString()).OrderBy(t => t))}");
|
||||
}
|
||||
}
|
||||
|
||||
Execution.Execute(this, riskAdjustedTargets);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to send security changes to algorithm framework models
|
||||
/// </summary>
|
||||
/// <param name="changes">Security additions/removals for this time step</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void OnFrameworkSecuritiesChanged(SecurityChanges changes)
|
||||
{
|
||||
if (DebugMode)
|
||||
{
|
||||
Debug($"{Time}: {changes}");
|
||||
}
|
||||
|
||||
Alpha.OnSecuritiesChanged(this, changes);
|
||||
PortfolioConstruction.OnSecuritiesChanged(this, changes);
|
||||
Execution.OnSecuritiesChanged(this, changes);
|
||||
RiskManagement.OnSecuritiesChanged(this, changes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void SetUniverseSelection(IUniverseSelectionModel universeSelection)
|
||||
{
|
||||
UniverseSelection = universeSelection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new universe selection model
|
||||
/// </summary>
|
||||
/// <param name="universeSelection">Model defining universes for the algorithm to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseSelection(IUniverseSelectionModel universeSelection)
|
||||
{
|
||||
if (UniverseSelection.GetType() != typeof(NullUniverseSelectionModel))
|
||||
{
|
||||
var compositeUniverseSelection = UniverseSelection as CompositeUniverseSelectionModel;
|
||||
if (compositeUniverseSelection != null)
|
||||
{
|
||||
compositeUniverseSelection.AddUniverseSelection(universeSelection);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniverseSelection = new CompositeUniverseSelectionModel(UniverseSelection, universeSelection);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UniverseSelection = universeSelection;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void SetAlpha(IAlphaModel alpha)
|
||||
{
|
||||
Alpha = alpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new alpha model
|
||||
/// </summary>
|
||||
/// <param name="alpha">Model that generates alpha to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void AddAlpha(IAlphaModel alpha)
|
||||
{
|
||||
if (Alpha.GetType() != typeof(NullAlphaModel))
|
||||
{
|
||||
var compositeAlphaModel = Alpha as CompositeAlphaModel;
|
||||
if (compositeAlphaModel != null)
|
||||
{
|
||||
compositeAlphaModel.AddAlpha(alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = new CompositeAlphaModel(Alpha, alpha);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the portfolio construction model
|
||||
/// </summary>
|
||||
/// <param name="portfolioConstruction">Model defining how to build a portfolio from insights</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetPortfolioConstruction(IPortfolioConstructionModel portfolioConstruction)
|
||||
{
|
||||
PortfolioConstruction = portfolioConstruction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the execution model
|
||||
/// </summary>
|
||||
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetExecution(IExecutionModel execution)
|
||||
{
|
||||
Execution = execution;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void SetRiskManagement(IRiskManagementModel riskManagement)
|
||||
{
|
||||
RiskManagement = riskManagement;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new risk management model
|
||||
/// </summary>
|
||||
/// <param name="riskManagement">Model defining how risk is managed to add</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
[DocumentationAttribute(TradingAndOrders)]
|
||||
public void AddRiskManagement(IRiskManagementModel riskManagement)
|
||||
{
|
||||
if (RiskManagement.GetType() != typeof(NullRiskManagementModel))
|
||||
{
|
||||
var compositeRiskModel = RiskManagement as CompositeRiskManagementModel;
|
||||
if (compositeRiskModel != null)
|
||||
{
|
||||
compositeRiskModel.AddRiskManagement(riskManagement);
|
||||
}
|
||||
else
|
||||
{
|
||||
RiskManagement = new CompositeRiskManagementModel(RiskManagement, riskManagement);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RiskManagement = riskManagement;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually emit insights from an algorithm.
|
||||
/// This is typically invoked before calls to submit orders in algorithms written against
|
||||
/// QCAlgorithm that have been ported into the algorithm framework.
|
||||
/// </summary>
|
||||
/// <param name="insights">The array of insights to be emitted</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void EmitInsights(params Insight[] insights)
|
||||
{
|
||||
if (IsWarmingUp)
|
||||
{
|
||||
if (!_isEmitWarmupInsightWarningSent)
|
||||
{
|
||||
Error("Warning: insights emitted during algorithm warmup are ignored.");
|
||||
_isEmitWarmupInsightWarningSent = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
insights = InitializeInsights(insights);
|
||||
OnInsightsGenerated(insights);
|
||||
ProcessInsights(insights);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually emit insights from an algorithm.
|
||||
/// This is typically invoked before calls to submit orders in algorithms written against
|
||||
/// QCAlgorithm that have been ported into the algorithm framework.
|
||||
/// </summary>
|
||||
/// <param name="insight">The insight to be emitted</param>
|
||||
[DocumentationAttribute(AlgorithmFramework)]
|
||||
public void EmitInsights(Insight insight)
|
||||
{
|
||||
EmitInsights(new[] { insight });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method used to validate insights and prepare them to be emitted
|
||||
/// </summary>
|
||||
/// <param name="insights">insights preparing to be emitted</param>
|
||||
/// <returns>Validated insights</returns>
|
||||
private Insight[] InitializeInsights(Insight[] insights)
|
||||
{
|
||||
List<Insight> validInsights = null;
|
||||
for (var i = 0; i < insights.Length; i++)
|
||||
{
|
||||
var security = Securities[insights[i].Symbol];
|
||||
if (security.IsDelisted)
|
||||
{
|
||||
if (!_isEmitDelistedInsightWarningSent)
|
||||
{
|
||||
Error($"QCAlgorithm.EmitInsights(): Warning: cannot emit insights for delisted securities, these will be discarded");
|
||||
_isEmitDelistedInsightWarningSent = true;
|
||||
}
|
||||
|
||||
// If this is our first invalid insight, create the list and fill it with previous values
|
||||
if (validInsights == null)
|
||||
{
|
||||
validInsights = new List<Insight>() {};
|
||||
for (var j = 0; j < i; j++)
|
||||
{
|
||||
validInsights.Add(insights[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize the insight fields
|
||||
insights[i] = InitializeInsightFields(insights[i], security);
|
||||
|
||||
// If we already had an invalid insight, this will have been initialized storing the valid ones.
|
||||
if (validInsights != null)
|
||||
{
|
||||
validInsights.Add(insights[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validInsights == null ? insights : validInsights.ToArray();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class used to set values not required to be set by alpha models
|
||||
/// </summary>
|
||||
/// <param name="insight">The <see cref="Insight"/> to set the values for</param>
|
||||
/// <param name="security">The <see cref="Security"/> instance associated with this insight</param>
|
||||
/// <returns>The same <see cref="Insight"/> instance with the values set</returns>
|
||||
private Insight InitializeInsightFields(Insight insight, Security security)
|
||||
{
|
||||
insight.GeneratedTimeUtc = UtcTime;
|
||||
switch (insight.Type)
|
||||
{
|
||||
case InsightType.Price:
|
||||
insight.ReferenceValue = security.Price;
|
||||
break;
|
||||
case InsightType.Volatility:
|
||||
insight.ReferenceValue = security.VolatilityModel.Volatility;
|
||||
break;
|
||||
}
|
||||
insight.SourceModel = string.IsNullOrEmpty(insight.SourceModel) ? Alpha.GetModelName() : insight.SourceModel;
|
||||
|
||||
var exchangeHours = MarketHoursDatabase.GetExchangeHours(insight.Symbol.ID.Market, insight.Symbol, insight.Symbol.SecurityType);
|
||||
insight.SetPeriodAndCloseTime(exchangeHours);
|
||||
return insight;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
* 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.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Indicators;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
public partial class QCAlgorithm
|
||||
{
|
||||
private bool _isEmitWarmupPlotWarningSet;
|
||||
private readonly ConcurrentDictionary<string, Chart> _charts = new ConcurrentDictionary<string, Chart>();
|
||||
|
||||
private static readonly Dictionary<string, List<string>> ReservedChartSeriesNames = new Dictionary<string, List<string>>
|
||||
{
|
||||
{ "Strategy Equity", new List<string> { "Equity", "Return" } },
|
||||
{ "Capacity", new List<string> { "Strategy Capacity" } },
|
||||
{ "Drawdown", new List<string> { "Equity Drawdown" } },
|
||||
{ "Benchmark", new List<string>() { "Benchmark" } },
|
||||
{ "Assets Sales Volume", new List<string>() },
|
||||
{ "Exposure", new List<string>() },
|
||||
{ "Portfolio Margin", new List<string>() },
|
||||
{ "Portfolio Turnover", new List<string> { "Portfolio Turnover" } }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Access to the runtime statistics property. User provided statistics.
|
||||
/// </summary>
|
||||
/// <remarks> RuntimeStatistics are displayed in the head banner in live trading</remarks>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public ConcurrentDictionary<string, string> RuntimeStatistics { get; } = new ConcurrentDictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Add a Chart object to algorithm collection
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart object to add to collection.</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void AddChart(Chart chart)
|
||||
{
|
||||
_charts.TryAdd(chart.Name, chart);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart using string series name, with value.
|
||||
/// </summary>
|
||||
/// <param name="series">Name of the plot series</param>
|
||||
/// <param name="value">Value to plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, decimal value)
|
||||
{
|
||||
//By default plot to the primary chart:
|
||||
Plot("Strategy Equity", series, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart using string series name, with int value. Alias of Plot();
|
||||
/// </summary>
|
||||
/// <remarks> Record(string series, int value)</remarks>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Record(string series, int value)
|
||||
{
|
||||
Plot(series, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart using string series name, with double value. Alias of Plot();
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Record(string series, double value)
|
||||
{
|
||||
Plot(series, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart using string series name, with decimal value. Alias of Plot();
|
||||
/// </summary>
|
||||
/// <param name="series"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Record(string series, decimal value)
|
||||
{
|
||||
//By default plot to the primary chart:
|
||||
Plot(series, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart using string series name, with double value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, double value) {
|
||||
Plot(series, value.SafeDecimalCast());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart using string series name, with int value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, int value)
|
||||
{
|
||||
Plot(series, (decimal)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///Plot a chart using string series name, with float value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, float value)
|
||||
{
|
||||
Plot(series, (double)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart to string chart name, using string series name, with double value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, double value)
|
||||
{
|
||||
Plot(chart, series, value.SafeDecimalCast());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart to string chart name, using string series name, with int value
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, int value)
|
||||
{
|
||||
Plot(chart, series, (decimal)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a chart to string chart name, using string series name, with float value
|
||||
/// </summary>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, float value)
|
||||
{
|
||||
Plot(chart, series, (double)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a value to a chart of string-chart name, with string series name, and decimal value. If chart does not exist, create it.
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="value">Value of the point</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, decimal value)
|
||||
{
|
||||
if (TryGetChartSeries(chart, series, out Series chartSeries))
|
||||
{
|
||||
chartSeries.AddPoint(UtcTime, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the default/primary chart series by the given series name.
|
||||
/// </summary>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, double open, double high, double low, double close)
|
||||
{
|
||||
Plot(series, open.SafeDecimalCast(), high.SafeDecimalCast(), low.SafeDecimalCast(), close.SafeDecimalCast());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the default/primary chart series by the given series name.
|
||||
/// </summary>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, float open, float high, float low, float close)
|
||||
{
|
||||
Plot(series, (double)open, (double)high, (double)low, (double)close);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the default/primary chart series by the given series name.
|
||||
/// </summary>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, int open, int high, int low, int close)
|
||||
{
|
||||
Plot(series, (decimal)open, (decimal)high, (decimal)low, (decimal)close);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the default/primary chart series by the given series name.
|
||||
/// </summary>
|
||||
/// <param name="series">Name of the plot series</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, decimal open, decimal high, decimal low, decimal close)
|
||||
{
|
||||
//By default plot to the primary chart:
|
||||
Plot("Strategy Equity", series, open, high, low, close);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the given series of the given chart.
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, double open, double high, double low, double close)
|
||||
{
|
||||
Plot(chart, series, open.SafeDecimalCast(), high.SafeDecimalCast(), low.SafeDecimalCast(), close.SafeDecimalCast());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the given series of the given chart.
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, float open, float high, float low, float close)
|
||||
{
|
||||
Plot(chart, series, (double)open, (double)high, (double)low, (double)close);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the given series of the given chart.
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, int open, int high, int low, int close)
|
||||
{
|
||||
Plot(chart, series, (decimal)open, (decimal)high, (decimal)low, (decimal)close);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to a chart of string-chart name, with string series name, and decimal value. If chart does not exist, create it.
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Series name</param>
|
||||
/// <param name="open">The candlestick open value</param>
|
||||
/// <param name="high">The candlestick high value</param>
|
||||
/// <param name="low">The candlestick low value</param>
|
||||
/// <param name="close">The candlestick close value</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, decimal open, decimal high, decimal low, decimal close)
|
||||
{
|
||||
if (TryGetChartSeries(chart, series, out CandlestickSeries candlestickSeries))
|
||||
{
|
||||
candlestickSeries.AddPoint(UtcTime, open, high, low, close);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the given series of the given chart.
|
||||
/// </summary>
|
||||
/// <param name="series">Name of the plot series</param>
|
||||
/// <param name="bar">The trade bar to be plotted to the candlestick series</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string series, TradeBar bar)
|
||||
{
|
||||
Plot(series, bar.Open, bar.High, bar.Low, bar.Close);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot a candlestick to the given series of the given chart.
|
||||
/// </summary>
|
||||
/// <param name="chart">Chart name</param>
|
||||
/// <param name="series">Name of the plot series</param>
|
||||
/// <param name="bar">The trade bar to be plotted to the candlestick series</param>
|
||||
/// <seealso cref="Plot(string,string,decimal,decimal,decimal,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, string series, TradeBar bar)
|
||||
{
|
||||
Plot(chart, series, bar.Open, bar.High, bar.Low, bar.Close);
|
||||
}
|
||||
|
||||
private bool TryGetChartSeries<T>(string chartName, string seriesName, out T series)
|
||||
where T : BaseSeries, new()
|
||||
{
|
||||
series = null;
|
||||
|
||||
// Check if chart/series names are reserved
|
||||
if (ReservedChartSeriesNames.TryGetValue(chartName, out var reservedSeriesNames))
|
||||
{
|
||||
if (reservedSeriesNames.Count == 0)
|
||||
{
|
||||
throw new ArgumentException($"'{chartName}' is a reserved chart name.");
|
||||
}
|
||||
if (reservedSeriesNames.Contains(seriesName))
|
||||
{
|
||||
throw new ArgumentException($"'{seriesName}' is a reserved series name for chart '{chartName}'.");
|
||||
}
|
||||
}
|
||||
|
||||
if(!_charts.TryGetValue(chartName, out var chart))
|
||||
{
|
||||
// If we don't have the chart, create it
|
||||
_charts[chartName] = chart = new Chart(chartName);
|
||||
}
|
||||
|
||||
if (!chart.Series.TryGetValue(seriesName, out var chartSeries))
|
||||
{
|
||||
chartSeries = new T() { Name = seriesName };
|
||||
chart.AddSeries(chartSeries);
|
||||
}
|
||||
|
||||
if (LiveMode && IsWarmingUp)
|
||||
{
|
||||
if (!_isEmitWarmupPlotWarningSet)
|
||||
{
|
||||
_isEmitWarmupPlotWarningSet = true;
|
||||
Debug("Plotting is disabled during algorithm warmup in live trading.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
series = (T)chartSeries;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a series object for charting. This is useful when initializing charts with
|
||||
/// series other than type = line. If a series exists in the chart with the same name,
|
||||
/// then it is replaced.
|
||||
/// </summary>
|
||||
/// <param name="chart">The chart name</param>
|
||||
/// <param name="series">The series name</param>
|
||||
/// <param name="seriesType">The type of series, i.e, Scatter</param>
|
||||
/// <param name="unit">The unit of the y axis, usually $</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void AddSeries(string chart, string series, SeriesType seriesType, string unit = "$")
|
||||
{
|
||||
Chart c;
|
||||
if (!_charts.TryGetValue(chart, out c))
|
||||
{
|
||||
_charts[chart] = c = new Chart(chart);
|
||||
}
|
||||
|
||||
c.Series[series] = BaseSeries.Create(seriesType, series, unit: unit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plots the value of each indicator on the chart
|
||||
/// </summary>
|
||||
/// <param name="chart">The chart's name</param>
|
||||
/// <param name="indicators">The indicators to plot</param>
|
||||
/// <seealso cref="Plot(string,string,decimal)"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void Plot(string chart, params IndicatorBase[] indicators)
|
||||
{
|
||||
foreach (var indicator in indicators)
|
||||
{
|
||||
Plot(chart, indicator.Name, indicator.Current.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically plots each indicator when a new value is available
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Charting)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void PlotIndicator(string chart, params IndicatorBase[] indicators)
|
||||
{
|
||||
PlotIndicator(chart, false, indicators);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Charting)]
|
||||
[DocumentationAttribute(Indicators)]
|
||||
public void PlotIndicator(string chart, bool waitForReady, params IndicatorBase[] indicators)
|
||||
{
|
||||
foreach (var i in indicators)
|
||||
{
|
||||
if (i == null) continue;
|
||||
|
||||
// copy loop variable for usage in closure
|
||||
var ilocal = i;
|
||||
i.Updated += (sender, args) =>
|
||||
{
|
||||
if (!waitForReady || ilocal.IsReady)
|
||||
{
|
||||
Plot(chart, ilocal);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">String value of your runtime statistic</param>
|
||||
/// <seealso cref="LiveMode"/>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, string value)
|
||||
{
|
||||
RuntimeStatistics.AddOrUpdate(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">Decimal value of your runtime statistic</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, decimal value)
|
||||
{
|
||||
SetRuntimeStatistic(name, value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">Int value of your runtime statistic</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, int value)
|
||||
{
|
||||
SetRuntimeStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a runtime statistic for the algorithm. Runtime statistics are shown in the top banner of a live algorithm GUI.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of your runtime statistic</param>
|
||||
/// <param name="value">Double value of your runtime statistic</param>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public void SetRuntimeStatistic(string name, double value)
|
||||
{
|
||||
SetRuntimeStatistic(name, value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom summary statistic for the algorithm.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the custom summary statistic</param>
|
||||
/// <param name="value">Value of the custom summary statistic</param>
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, string value)
|
||||
{
|
||||
if (int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intName) &&
|
||||
intName >= 0 && intName <= 100)
|
||||
{
|
||||
throw new ArgumentException($"'{name}' is a reserved statistic name.");
|
||||
}
|
||||
|
||||
_statisticsService.SetSummaryStatistic(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom summary statistic for the algorithm.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the custom summary statistic</param>
|
||||
/// <param name="value">Value of the custom summary statistic</param>
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, int value)
|
||||
{
|
||||
SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom summary statistic for the algorithm.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the custom summary statistic</param>
|
||||
/// <param name="value">Value of the custom summary statistic</param>
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, double value)
|
||||
{
|
||||
SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom summary statistic for the algorithm.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the custom summary statistic</param>
|
||||
/// <param name="value">Value of the custom summary statistic</param>
|
||||
[DocumentationAttribute(StatisticsTag)]
|
||||
public void SetSummaryStatistic(string name, decimal value)
|
||||
{
|
||||
SetSummaryStatistic(name, value.ToStringInvariant());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the chart updates by fetch the recent points added and return for dynamic Charting.
|
||||
/// </summary>
|
||||
/// <param name="clearChartData"></param>
|
||||
/// <returns>List of chart updates since the last request</returns>
|
||||
/// <remarks>GetChartUpdates returns the latest updates since previous request.</remarks>
|
||||
[DocumentationAttribute(Charting)]
|
||||
public IEnumerable<Chart> GetChartUpdates(bool clearChartData = false)
|
||||
{
|
||||
foreach (var chart in _charts.Values)
|
||||
{
|
||||
yield return chart.GetUpdates();
|
||||
if (clearChartData)
|
||||
{
|
||||
// we can clear this data out after getting updates to prevent unnecessary memory usage
|
||||
foreach (var series in chart.Series)
|
||||
{
|
||||
series.Value.Purge();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* 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 System.Collections.Specialized;
|
||||
using System.Threading;
|
||||
using NodaTime;
|
||||
using QuantConnect.Algorithm.Selection;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Fundamental;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Scheduling;
|
||||
using QuantConnect.Securities;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
public partial class QCAlgorithm
|
||||
{
|
||||
// save universe additions and apply at end of time step
|
||||
// this removes temporal dependencies from w/in initialize method
|
||||
// original motivation: adding equity/options to enforce equity raw data mode
|
||||
private static int _universeCount;
|
||||
private readonly object _pendingUniverseAdditionsLock = new object();
|
||||
private readonly List<UserDefinedUniverseUpdate> _pendingUserDefinedUniverseSecurityChanges = new();
|
||||
private bool _pendingUniverseAdditions;
|
||||
private ConcurrentSet<Symbol> _rawNormalizationWarningSymbols = new ConcurrentSet<Symbol>();
|
||||
private readonly int _rawNormalizationWarningSymbolsMaxCount = 10;
|
||||
private bool _coarseFineUniverseObsoleteLogSent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets universe manager which holds universes keyed by their symbol
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public UniverseManager UniverseManager
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the universe settings to be used when adding securities via universe selection
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public UniverseSettings UniverseSettings
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked at the end of every time step. This allows the algorithm
|
||||
/// to process events before advancing to the next time step.
|
||||
/// </summary>
|
||||
[DocumentationAttribute(HandlingData)]
|
||||
public void OnEndOfTimeStep()
|
||||
{
|
||||
// rewrite securities w/ derivatives to be in raw mode
|
||||
lock (_pendingUniverseAdditionsLock)
|
||||
{
|
||||
if (!_pendingUniverseAdditions && _pendingUserDefinedUniverseSecurityChanges.Count == 0)
|
||||
{
|
||||
// no point in looping through everything if there's no pending changes
|
||||
return;
|
||||
}
|
||||
|
||||
var securitiesToSeed = new HashSet<Security>();
|
||||
|
||||
foreach (var security in Securities.Select(kvp => kvp.Value).Union(
|
||||
_pendingUserDefinedUniverseSecurityChanges.Where(x => x.IsAddition).Select(x => x.Security)))
|
||||
{
|
||||
// check for any derivative securities and mark the underlying as raw
|
||||
if (security.Type == SecurityType.Equity &&
|
||||
Securities.Any(skvp => skvp.Key.SecurityType != SecurityType.Base && skvp.Key.HasUnderlyingSymbol(security.Symbol)))
|
||||
{
|
||||
// set data mode raw and default volatility model
|
||||
ConfigureUnderlyingSecurity(security);
|
||||
}
|
||||
|
||||
var configs = SubscriptionManager.SubscriptionDataConfigService
|
||||
.GetSubscriptionDataConfigs(security.Symbol);
|
||||
if (security.Symbol.HasUnderlying && security.Symbol.SecurityType != SecurityType.Base)
|
||||
{
|
||||
Security underlyingSecurity;
|
||||
var underlyingSymbol = security.Symbol.Underlying;
|
||||
|
||||
var resolution = configs.GetHighestResolution();
|
||||
var isFillForward = configs.IsFillForward();
|
||||
if (UniverseManager.TryGetValue(security.Symbol, out var universe))
|
||||
{
|
||||
// as if the universe had selected this asset, the configuration of the canonical can be different
|
||||
resolution = universe.UniverseSettings.Resolution;
|
||||
isFillForward = universe.UniverseSettings.FillForward;
|
||||
}
|
||||
|
||||
// create the underlying security object if it doesn't already exist
|
||||
if (!Securities.TryGetValue(underlyingSymbol, out underlyingSecurity))
|
||||
{
|
||||
underlyingSecurity = AddSecurity(underlyingSymbol.SecurityType,
|
||||
underlyingSymbol.Value,
|
||||
resolution,
|
||||
underlyingSymbol.ID.Market,
|
||||
isFillForward,
|
||||
Security.NullLeverage,
|
||||
configs.IsExtendedMarketHours(),
|
||||
dataNormalizationMode: DataNormalizationMode.Raw);
|
||||
}
|
||||
|
||||
// set data mode raw and default volatility model
|
||||
if (underlyingSecurity.Symbol.SecurityType == SecurityType.Equity)
|
||||
{
|
||||
ConfigureUnderlyingSecurity(underlyingSecurity);
|
||||
}
|
||||
|
||||
if (LiveMode && !Settings.SeedInitialPrices && underlyingSecurity.GetLastData() == null)
|
||||
{
|
||||
securitiesToSeed.Add(underlyingSecurity);
|
||||
}
|
||||
// set the underlying security on the derivative -- we do this in two places since it's possible
|
||||
// to do AddOptionContract w/out the underlying already added and normalized properly
|
||||
var derivative = security as IDerivativeSecurity;
|
||||
if (derivative != null)
|
||||
{
|
||||
derivative.Underlying = underlyingSecurity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!securitiesToSeed.IsNullOrEmpty())
|
||||
{
|
||||
AlgorithmUtils.SeedSecurities(securitiesToSeed, this);
|
||||
}
|
||||
|
||||
// add subscriptionDataConfig to their respective user defined universes
|
||||
foreach (var userDefinedUniverseAddition in _pendingUserDefinedUniverseSecurityChanges)
|
||||
{
|
||||
var changedCollection = false;
|
||||
var action = NotifyCollectionChangedAction.Add;
|
||||
if (userDefinedUniverseAddition.IsAddition)
|
||||
{
|
||||
foreach (var subscriptionDataConfig in userDefinedUniverseAddition.SubscriptionDataConfigs)
|
||||
{
|
||||
changedCollection |= userDefinedUniverseAddition.Universe.Add(subscriptionDataConfig);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action = NotifyCollectionChangedAction.Replace;
|
||||
changedCollection |= userDefinedUniverseAddition.Universe.Remove(userDefinedUniverseAddition.Security);
|
||||
}
|
||||
|
||||
if (changedCollection)
|
||||
{
|
||||
UniverseManager.Update(userDefinedUniverseAddition.Universe.Symbol, userDefinedUniverseAddition.Universe, action);
|
||||
}
|
||||
}
|
||||
|
||||
// finally add any pending universes, this will make them available to the data feed
|
||||
// The universe will be added at the end of time step, same as the AddData user defined universes.
|
||||
// This is required to be independent of the start and end date set during initialize
|
||||
UniverseManager.ProcessChanges();
|
||||
|
||||
_pendingUniverseAdditions = false;
|
||||
_pendingUserDefinedUniverseSecurityChanges.Clear();
|
||||
}
|
||||
|
||||
if (!_rawNormalizationWarningSymbols.IsNullOrEmpty())
|
||||
{
|
||||
// Log our securities being set to raw price mode
|
||||
Debug($"Warning: The following securities were set to raw price normalization mode to work with options: " +
|
||||
$"{string.Join(", ", _rawNormalizationWarningSymbols.Take(_rawNormalizationWarningSymbolsMaxCount).Select(x => x.Value))}...");
|
||||
|
||||
// Set our warning list to null to stop emitting these warnings after its done once
|
||||
_rawNormalizationWarningSymbols = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a helper that provides pre-defined universe definitions, such as top dollar volume
|
||||
/// </summary>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public UniverseDefinitions Universe
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the universe to the algorithm
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe to be added</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Universe universe)
|
||||
{
|
||||
if (universe.UniverseSettings == null)
|
||||
{
|
||||
// set default value so that users don't need to pass it
|
||||
universe.UniverseSettings = UniverseSettings;
|
||||
}
|
||||
_pendingUniverseAdditions = true;
|
||||
// note: UniverseManager.Add uses TryAdd, so don't need to worry about duplicates here
|
||||
UniverseManager.Add(universe.Configuration.Symbol, universe);
|
||||
return universe;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse<T>(null, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse<T>(null, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse<T>(name, null, null, null, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverseStringSelector<T>(selector, null, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Resolution.Daily, and Market.USA
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse<T>(name, null, null, universeSettings, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Resolution.Daily, and Market.USA
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverseStringSelector<T>(selector, null, name, null, null, universeSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Market.USA and UniverseSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse<T>(name, resolution, null, null, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, Market.USA and UniverseSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverseStringSelector<T>(selector, null, name, resolution);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, and Market.USA
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse<T>(name, resolution, market: null, universeSettings, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
|
||||
/// of SecurityType.Equity, and Market.USA
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="universeSettings">The settings used for securities added by this universe</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverseStringSelector<T>(selector, null, name, resolution, universeSettings: universeSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name, Resolution resolution, string market, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse<T>(name, resolution, market, null, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This will use the default universe settings
|
||||
/// specified via the <see cref="UniverseSettings"/> property.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="securityType">The security type the universe produces</param>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="securityType">The security type the universe produces</param>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market, universeSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type</typeparam>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The expected resolution of the universe data</param>
|
||||
/// <param name="market">The market for selected symbols</param>
|
||||
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
|
||||
/// <param name="selector">Function delegate that performs selection on the universe data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse<T>(string name = null, Resolution? resolution = null, string market = null, UniverseSettings universeSettings = null,
|
||||
Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector = null)
|
||||
{
|
||||
return AddUniverseSymbolSelector(typeof(T), name, resolution, market, universeSettings, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This is for fundamental US Equity data and
|
||||
/// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
|
||||
/// </summary>
|
||||
/// <param name="selector">Defines an initial fundamental selection</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
return AddUniverse(FundamentalUniverse.USA(selector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This is for fundamental US Equity data and
|
||||
/// will be executed based on the provided <see cref="IDateRule"/> in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
|
||||
/// </summary>
|
||||
/// <param name="dateRule">Date rule that will be used to set the <see cref="Data.UniverseSelection.UniverseSettings.Schedule"/></param>
|
||||
/// <param name="selector">Defines an initial fundamental selection</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(IDateRule dateRule, Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector)
|
||||
{
|
||||
var otherSettings = new UniverseSettings(UniverseSettings);
|
||||
otherSettings.Schedule.On(dateRule);
|
||||
return AddUniverse(FundamentalUniverse.USA(selector, otherSettings));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 (<see cref="TimeZones.NewYork"/>)
|
||||
/// </summary>
|
||||
/// <param name="coarseSelector">Defines an initial coarse selection</param>
|
||||
/// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
|
||||
[Obsolete("This method is obsolete, please use AddUniverse(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector) instead")]
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
|
||||
{
|
||||
if (!_coarseFineUniverseObsoleteLogSent)
|
||||
{
|
||||
Debug("Warning: AddUniverse(coarseSelector, fineSelector) is obsolete, please use AddUniverse(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector) instead.");
|
||||
_coarseFineUniverseObsoleteLogSent = true;
|
||||
}
|
||||
|
||||
var coarse = new CoarseFundamentalUniverse(UniverseSettings, coarseSelector);
|
||||
|
||||
return AddUniverse(new FineFundamentalFilteredUniverse(coarse, fineSelector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This is for fine fundamental US Equity data and
|
||||
/// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
|
||||
/// </summary>
|
||||
/// <param name="universe">The universe to be filtered with fine fundamental selection</param>
|
||||
/// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(Universe universe, Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> fineSelector)
|
||||
{
|
||||
return AddUniverse(new FundamentalFilteredUniverse(universe, fineSelector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This can be used to return a list of string
|
||||
/// symbols retrieved from anywhere and will loads those symbols under the US Equity market.
|
||||
/// </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>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(string name, Func<DateTime, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe and adds it to the algorithm. This can be used to return a list of string
|
||||
/// symbols retrieved from anywhere and will loads those symbols under the US Equity market.
|
||||
/// </summary>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The resolution this universe should be triggered on</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(string name, Resolution resolution, Func<DateTime, IEnumerable<string>> selector)
|
||||
{
|
||||
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new user defined universe that will fire on the requested resolution during market hours.
|
||||
/// </summary>
|
||||
/// <param name="securityType">The security type of the universe</param>
|
||||
/// <param name="name">A unique name for this universe</param>
|
||||
/// <param name="resolution">The resolution this universe should be triggered on</param>
|
||||
/// <param name="market">The market of the universe</param>
|
||||
/// <param name="universeSettings">The subscription settings used for securities added from this universe</param>
|
||||
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public Universe AddUniverse(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<DateTime, IEnumerable<string>> selector)
|
||||
{
|
||||
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
|
||||
var dataTimeZone = marketHoursDbEntry.DataTimeZone;
|
||||
var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
|
||||
var symbol = QuantConnect.Symbol.Create(name, securityType, market);
|
||||
var config = new SubscriptionDataConfig(typeof(Fundamental), symbol, resolution, dataTimeZone, exchangeTimeZone, false, false, true, isFilteredSubscription: false);
|
||||
return AddUniverse(new UserDefinedUniverse(config, universeSettings, resolution.ToTimeSpan(), selector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new universe that creates options of the security by monitoring any changes in the Universe the provided security is in.
|
||||
/// Additionally, a filter can be applied to the options generated when the universe of the security changes.
|
||||
/// </summary>
|
||||
/// <param name="underlyingSymbol">Underlying Symbol to add as an option. For Futures, the option chain constructed will be per-contract, as long as a canonical Symbol is provided.</param>
|
||||
/// <param name="optionFilter">User-defined filter used to select the options we want out of the option chain provided.</param>
|
||||
/// <exception cref="InvalidOperationException">The underlying Symbol's universe is not found.</exception>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseOptions(Symbol underlyingSymbol, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
|
||||
{
|
||||
// We need to load the universe associated with the provided Symbol and provide that universe to the option filter universe.
|
||||
// The option filter universe will subscribe to any changes in the universe of the underlying Symbol,
|
||||
// ensuring that we load the option chain for every asset found in the underlying's Universe.
|
||||
Universe universe;
|
||||
if (!UniverseManager.TryGetValue(underlyingSymbol, out universe))
|
||||
{
|
||||
underlyingSymbol = AddSecurity(underlyingSymbol).Symbol;
|
||||
|
||||
// Recheck again, we should have a universe addition pending for the provided Symbol
|
||||
if (!UniverseManager.TryGetValue(underlyingSymbol, out universe))
|
||||
{
|
||||
// Should never happen, but it could be that the subscription
|
||||
// created with AddSecurity is not aligned with the Symbol we're using.
|
||||
throw new InvalidOperationException($"Universe not found for underlying Symbol: {underlyingSymbol}.");
|
||||
}
|
||||
}
|
||||
|
||||
// Allow all option contracts through without filtering if we're provided a null filter.
|
||||
AddUniverseOptions(universe, optionFilter ?? (_ => _));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new universe selection model and adds it to the algorithm. 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>
|
||||
/// <param name="universe">The universe we want to chain an option universe selection model too</param>
|
||||
/// <param name="optionFilter">The option filter universe to use</param>
|
||||
[DocumentationAttribute(Universes)]
|
||||
public void AddUniverseOptions(Universe universe, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
|
||||
{
|
||||
AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, optionFilter));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the security to the user defined universe
|
||||
/// </summary>
|
||||
/// <param name="security">The security to add</param>
|
||||
/// <param name="configurations">The <see cref="SubscriptionDataConfig"/> instances we want to add</param>
|
||||
private Security AddToUserDefinedUniverse(
|
||||
Security security,
|
||||
List<SubscriptionDataConfig> configurations)
|
||||
{
|
||||
var subscription = configurations.First();
|
||||
// if we are adding a non-internal security which already has an internal feed, we remove it first
|
||||
if (Securities.TryGetValue(security.Symbol, out var existingSecurity))
|
||||
{
|
||||
if (!subscription.IsInternalFeed && existingSecurity.IsInternalFeed())
|
||||
{
|
||||
var securityUniverse = UniverseManager.Select(x => x.Value).OfType<UserDefinedUniverse>().FirstOrDefault(x => x.Members.ContainsKey(security.Symbol));
|
||||
securityUniverse?.Remove(security.Symbol);
|
||||
|
||||
Securities.Remove(security.Symbol);
|
||||
Securities.Add(security);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Securities.Add(security);
|
||||
}
|
||||
|
||||
// add this security to the user defined universe
|
||||
Universe universe;
|
||||
var universeSymbol = UserDefinedUniverse.CreateSymbol(security.Type, security.Symbol.ID.Market);
|
||||
if (!UniverseManager.TryGetValue(universeSymbol, out universe))
|
||||
{
|
||||
if (universe == null)
|
||||
{
|
||||
// create a new universe, these subscription settings don't currently get used
|
||||
// since universe selection proper is never invoked on this type of universe
|
||||
var uconfig = new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed: true, fillForward: false,
|
||||
exchangeTimeZone: DateTimeZone.Utc,
|
||||
dataTimeZone: DateTimeZone.Utc);
|
||||
|
||||
// this is the universe symbol, has no real entry in the mhdb, will default to market and security type
|
||||
// set entry in market hours database for the universe subscription to match the config
|
||||
var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(uconfig.Symbol);
|
||||
MarketHoursDatabase.SetEntry(uconfig.Market, symbolString, uconfig.SecurityType,
|
||||
SecurityExchangeHours.AlwaysOpen(uconfig.ExchangeTimeZone), uconfig.DataTimeZone);
|
||||
|
||||
universe = new UserDefinedUniverse(uconfig,
|
||||
new UniverseSettings(
|
||||
subscription.Resolution,
|
||||
security.Leverage,
|
||||
subscription.FillDataForward,
|
||||
subscription.ExtendedMarketHours,
|
||||
TimeSpan.Zero),
|
||||
QuantConnect.Time.MaxTimeSpan,
|
||||
new List<Symbol>());
|
||||
|
||||
AddUniverse(universe);
|
||||
}
|
||||
}
|
||||
|
||||
var userDefinedUniverse = universe as UserDefinedUniverse;
|
||||
if (userDefinedUniverse != null)
|
||||
{
|
||||
lock (_pendingUniverseAdditionsLock)
|
||||
{
|
||||
_pendingUserDefinedUniverseSecurityChanges.Add(new UserDefinedUniverseUpdate(userDefinedUniverse, configurations, security));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// should never happen, someone would need to add a non-user defined universe with this symbol
|
||||
throw new Exception($"Expected universe with symbol '{universeSymbol.Value}' to be of type {nameof(UserDefinedUniverse)} but was {universe.GetType().Name}.");
|
||||
}
|
||||
|
||||
return security;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the security to be in raw data mode and ensures that a reasonable default volatility model is supplied
|
||||
/// </summary>
|
||||
/// <param name="security">The underlying security</param>
|
||||
private void ConfigureUnderlyingSecurity(Security security)
|
||||
{
|
||||
// force underlying securities to be raw data mode
|
||||
var configs = SubscriptionManager.SubscriptionDataConfigService
|
||||
.GetSubscriptionDataConfigs(security.Symbol);
|
||||
if (configs.DataNormalizationMode() != DataNormalizationMode.Raw)
|
||||
{
|
||||
// Add this symbol to our set of raw normalization warning symbols to alert the user at the end
|
||||
// Set a hard limit to avoid growing this collection unnecessarily large
|
||||
if (_rawNormalizationWarningSymbols != null && _rawNormalizationWarningSymbols.Count <= _rawNormalizationWarningSymbolsMaxCount)
|
||||
{
|
||||
_rawNormalizationWarningSymbols.Add(security.Symbol);
|
||||
}
|
||||
|
||||
configs.SetDataNormalizationMode(DataNormalizationMode.Raw);
|
||||
// For backward compatibility we need to refresh the security DataNormalizationMode Property
|
||||
security.RefreshDataNormalizationModeProperty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create the configuration of a custom universe
|
||||
/// </summary>
|
||||
private SubscriptionDataConfig GetCustomUniverseConfiguration(Type dataType, string name, string market, Resolution? resolution = null)
|
||||
{
|
||||
if (dataType == typeof(CoarseFundamental) || dataType == typeof(FineFundamental))
|
||||
{
|
||||
dataType = typeof(FundamentalUniverse);
|
||||
}
|
||||
|
||||
if (!TryGetUniverseSymbol(dataType, market, out var universeSymbol))
|
||||
{
|
||||
market ??= Market.USA;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
name = $"{dataType.Name}-{market}-{Interlocked.Increment(ref _universeCount):D10}-{Guid.NewGuid()}";
|
||||
}
|
||||
// same as 'AddData<>' 'T' type will be treated as custom/base data type with always open market hours
|
||||
universeSymbol = QuantConnect.Symbol.Create(name, SecurityType.Base, market, baseDataType: dataType);
|
||||
}
|
||||
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(universeSymbol, new[] { dataType });
|
||||
var dataTimeZone = marketHoursDbEntry.DataTimeZone;
|
||||
var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
|
||||
return new SubscriptionDataConfig(dataType, universeSymbol, resolution ?? Resolution.Daily, dataTimeZone, exchangeTimeZone, false, false, true, true, isFilteredSubscription: false);
|
||||
}
|
||||
|
||||
private bool TryGetUniverseSymbol(Type dataType, string market, out Symbol symbol)
|
||||
{
|
||||
symbol = null;
|
||||
if (dataType.IsAssignableTo(typeof(BaseDataCollection)))
|
||||
{
|
||||
var instance = dataType.GetBaseDataInstance() as BaseDataCollection;
|
||||
symbol = instance.UniverseSymbol(market);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Universe AddUniverseStringSelector<T>(Func<IEnumerable<BaseData>, IEnumerable<string>> selector, SecurityType? securityType = null, string name = null,
|
||||
Resolution? resolution = null, string market = null, UniverseSettings universeSettings = null)
|
||||
{
|
||||
if (market.IsNullOrEmpty())
|
||||
{
|
||||
market = Market.USA;
|
||||
}
|
||||
securityType ??= SecurityType.Equity;
|
||||
Func<IEnumerable<BaseData>, IEnumerable<Symbol>> symbolSelector = data => selector(data).Select(x => QuantConnect.Symbol.Create(x, securityType.Value, market, baseDataType: typeof(T)));
|
||||
return AddUniverse<T>(name, resolution, market, universeSettings, symbolSelector);
|
||||
}
|
||||
|
||||
private Universe AddUniverseSymbolSelector(Type dataType, string name = null, Resolution? resolution = null, string market = null, UniverseSettings universeSettings = null,
|
||||
Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector = null)
|
||||
{
|
||||
var config = GetCustomUniverseConfiguration(dataType, name, market, resolution);
|
||||
return AddUniverse(new FuncUniverse(config, universeSettings, selector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class used to store <see cref="UserDefinedUniverse"/> additions.
|
||||
/// They will be consumed at <see cref="OnEndOfTimeStep"/>
|
||||
/// </summary>
|
||||
private class UserDefinedUniverseUpdate
|
||||
{
|
||||
public bool IsAddition => SubscriptionDataConfigs != null;
|
||||
public Security Security { get; }
|
||||
public UserDefinedUniverse Universe { get; }
|
||||
public List<SubscriptionDataConfig> SubscriptionDataConfigs { get; }
|
||||
|
||||
public UserDefinedUniverseUpdate(
|
||||
UserDefinedUniverse universe,
|
||||
List<SubscriptionDataConfig> subscriptionDataConfigs,
|
||||
Security security)
|
||||
{
|
||||
Universe = universe;
|
||||
SubscriptionDataConfigs = subscriptionDataConfigs;
|
||||
Security = security;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<RootNamespace>QuantConnect.Algorithm</RootNamespace>
|
||||
<AssemblyName>QuantConnect.Algorithm</AssemblyName>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<DocumentationFile>bin\$(Configuration)\QuantConnect.Algorithm.xml</DocumentationFile>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<Description>QuantConnect LEAN Engine: Algorithm Project - Core QCAlgorithm implementation</Description>
|
||||
<NoWarn>CA1062</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.60" />
|
||||
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="NodaTime" Version="3.0.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\Properties\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Configuration\QuantConnect.Configuration.csproj" />
|
||||
<ProjectReference Include="..\Indicators\QuantConnect.Indicators.csproj" />
|
||||
<ProjectReference Include="..\Common\QuantConnect.csproj" />
|
||||
<ProjectReference Include="..\Logging\QuantConnect.Logging.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Alphas\NullAlphaModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Execution\ImmediateExecutionModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Execution\NullExecutionModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Portfolio\NullPortfolioConstructionModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Risk\CompositeRiskManagementModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Risk\NullRiskManagementModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Selection\ManualUniverseSelectionModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Selection\UniverseSelectionModel.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Risk
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IRiskManagementModel"/> that combines multiple risk
|
||||
/// models into a single risk management model and properly sets each insights 'SourceModel' property.
|
||||
/// </summary>
|
||||
public class CompositeRiskManagementModel : RiskManagementModel
|
||||
{
|
||||
private readonly List<IRiskManagementModel> _riskManagementModels = new List<IRiskManagementModel>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeRiskManagementModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="riskManagementModels">The individual risk management models defining this composite model</param>
|
||||
public CompositeRiskManagementModel(params IRiskManagementModel[] riskManagementModels)
|
||||
{
|
||||
if (riskManagementModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 risk management model for the CompositeRiskManagementModel");
|
||||
}
|
||||
|
||||
_riskManagementModels.AddRange(riskManagementModels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeRiskManagementModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="riskManagementModels">The individual risk management models defining this composite model</param>
|
||||
public CompositeRiskManagementModel(IEnumerable<IRiskManagementModel> riskManagementModels)
|
||||
{
|
||||
foreach (var riskManagementModel in riskManagementModels)
|
||||
{
|
||||
AddRiskManagement(riskManagementModel);
|
||||
}
|
||||
|
||||
if (_riskManagementModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 risk management model for the CompositeRiskManagementModel");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeRiskManagementModel"/> class
|
||||
/// </summary>
|
||||
/// <param name="riskManagementModels">The individual risk management models defining this composite model</param>
|
||||
public CompositeRiskManagementModel(params PyObject[] riskManagementModels)
|
||||
{
|
||||
if (riskManagementModels.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentException("Must specify at least 1 risk management model for the CompositeRiskManagementModel");
|
||||
}
|
||||
|
||||
foreach (var pyRiskManagementModel in riskManagementModels)
|
||||
{
|
||||
AddRiskManagement(pyRiskManagementModel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the algorithm's risk at each time step.
|
||||
/// This method patches this call through the each of the wrapped models.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The current portfolio targets to be assessed for risk</param>
|
||||
/// <returns>The new portfolio targets</returns>
|
||||
public override IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
foreach (var model in _riskManagementModels)
|
||||
{
|
||||
// take into account the possibility of ManageRisk returning nothing
|
||||
var riskAdjusted = model.ManageRisk(algorithm, targets);
|
||||
|
||||
// produce a distinct set of new targets giving preference to newer targets
|
||||
targets = riskAdjusted.Concat(targets).DistinctBy(t => t.Symbol).ToArray();
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed.
|
||||
/// This method patches this call through the each of the wrapped models.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
foreach (var model in _riskManagementModels)
|
||||
{
|
||||
model.OnSecuritiesChanged(algorithm, changes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="IRiskManagementModel"/> instance
|
||||
/// </summary>
|
||||
/// <param name="riskManagementModel">The risk management model to add</param>
|
||||
public void AddRiskManagement(IRiskManagementModel riskManagementModel)
|
||||
{
|
||||
_riskManagementModels.Add(riskManagementModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="IRiskManagementModel"/> instance
|
||||
/// </summary>
|
||||
/// <param name="pyRiskManagementModel">The risk management model to add</param>
|
||||
public void AddRiskManagement(PyObject pyRiskManagementModel)
|
||||
{
|
||||
var riskManagementModel = PythonUtil.CreateInstanceOrWrapper<IRiskManagementModel>(
|
||||
pyRiskManagementModel,
|
||||
py => new RiskManagementModelPythonWrapper(py)
|
||||
);
|
||||
_riskManagementModels.Add(riskManagementModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
# 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 CompositeRiskManagementModel(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that combines multiple risk models
|
||||
into a single risk management model and properly sets each insights 'SourceModel' property.'''
|
||||
|
||||
def __init__(self, *risk_management_models):
|
||||
'''Initializes a new instance of the CompositeRiskManagementModel class
|
||||
Args:
|
||||
risk_management_models: The individual risk management models defining this composite model.'''
|
||||
for model in risk_management_models:
|
||||
for attribute_names in [('ManageRisk', 'manage_risk'), ('OnSecuritiesChanged', 'on_securities_changed')]:
|
||||
if not hasattr(model, attribute_names[0]) and not hasattr(model, attribute_names[1]):
|
||||
raise Exception(f'IRiskManagementModel.{attribute_names[1]} must be implemented. Please implement this missing method on {model.__class__.__name__}')
|
||||
|
||||
self.risk_management_models = risk_management_models
|
||||
|
||||
def manage_risk(self, algorithm, targets):
|
||||
'''Manages the algorithm's risk at each time step
|
||||
Args:
|
||||
algorithm: The algorithm instance
|
||||
targets: The current portfolio targets to be assessed for risk'''
|
||||
for model in self.risk_management_models:
|
||||
# take into account the possibility of ManageRisk returning nothing
|
||||
risk_adjusted = model.manage_risk(algorithm, targets)
|
||||
|
||||
# produce a distinct set of new targets giving preference to newer targets
|
||||
symbols = [x.symbol for x in risk_adjusted]
|
||||
for target in targets:
|
||||
if target.symbol not in symbols:
|
||||
risk_adjusted.append(target)
|
||||
|
||||
targets = risk_adjusted
|
||||
|
||||
return targets
|
||||
|
||||
def on_securities_changed(self, algorithm, changes):
|
||||
'''Event fired each time the we add/remove securities from the data feed.
|
||||
This method patches this call through the each of the wrapped models.
|
||||
Args:
|
||||
algorithm: The algorithm instance that experienced the change in securities
|
||||
changes: The security additions and removals from the algorithm'''
|
||||
for model in self.risk_management_models:
|
||||
model.on_securities_changed(algorithm, changes)
|
||||
|
||||
def add_risk_management(self, risk_management_model):
|
||||
'''Adds a new 'IRiskManagementModel' instance
|
||||
Args:
|
||||
risk_management_model: The risk management model to add'''
|
||||
self.risk_management_models.add(risk_management_model)
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Risk
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm framework model that manages an algorithm's risk/downside
|
||||
/// </summary>
|
||||
public interface IRiskManagementModel : INotifiedSecurityChanges
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the algorithm's risk at each time step
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The current portfolio targets to be assessed for risk</param>
|
||||
IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Risk
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IRiskManagementModel"/> that does nothing
|
||||
/// </summary>
|
||||
public class NullRiskManagementModel : RiskManagementModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the algorithm's risk at each time step
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The current portfolio targets to be assessed for risk</param>
|
||||
public override IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
return Enumerable.Empty<IPortfolioTarget>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# 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 NullRiskManagementModel(RiskManagementModel):
|
||||
'''Provides an implementation of IRiskManagementModel that does nothing'''
|
||||
def manage_risk(self, algorithm, targets):
|
||||
return []
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.Algorithm.Framework.Portfolio;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Risk
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for risk management models
|
||||
/// </summary>
|
||||
public class RiskManagementModel : IRiskManagementModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the algorithm's risk at each time step
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The current portfolio targets to be assessed for risk</param>
|
||||
public virtual IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
throw new System.NotImplementedException("Types deriving from 'RiskManagementModel' must implement the 'IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm, IPortfolioTarget[]) method.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public virtual void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 QuantConnect.Python;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Algorithm.Framework.Portfolio;
|
||||
|
||||
namespace QuantConnect.Algorithm.Framework.Risk
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IRiskManagementModel"/> that wraps a <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
public class RiskManagementModelPythonWrapper : RiskManagementModel
|
||||
{
|
||||
private readonly BasePythonWrapper<IRiskManagementModel> _model;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for initialising the <see cref="IRiskManagementModel"/> class with wrapped <see cref="PyObject"/> object
|
||||
/// </summary>
|
||||
/// <param name="model">Model defining how risk is managed</param>
|
||||
public RiskManagementModelPythonWrapper(PyObject model)
|
||||
{
|
||||
_model = new BasePythonWrapper<IRiskManagementModel>(model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the algorithm's risk at each time step
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance</param>
|
||||
/// <param name="targets">The current portfolio targets to be assessed for risk</param>
|
||||
public override IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
|
||||
{
|
||||
return _model.InvokeMethodAndEnumerate<IPortfolioTarget>(nameof(ManageRisk), algorithm, targets);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired each time the we add/remove securities from the data feed
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
|
||||
/// <param name="changes">The security additions and removals from the algorithm</param>
|
||||
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
|
||||
{
|
||||
_model.InvokeMethod(nameof(OnSecuritiesChanged), algorithm, changes).Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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 Python.Runtime;
|
||||
using System.Collections.Generic;
|
||||
using QuantConnect.Data.Fundamental;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
|
||||
namespace QuantConnect.Algorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helpers for defining universes in algorithms
|
||||
/// </summary>
|
||||
public class UniverseDefinitions
|
||||
{
|
||||
private readonly QCAlgorithm _algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a helper that provides methods for creating universes based on daily dollar volumes
|
||||
/// </summary>
|
||||
public DollarVolumeUniverseDefinitions DollarVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies that universe selection should not make changes on this iteration
|
||||
/// </summary>
|
||||
public Universe.UnchangedUniverse Unchanged => Universe.Unchanged;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UniverseDefinitions"/> class
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The algorithm instance, used for obtaining the default <see cref="UniverseSettings"/></param>
|
||||
public UniverseDefinitions(QCAlgorithm algorithm)
|
||||
{
|
||||
_algorithm = algorithm;
|
||||
DollarVolume = new DollarVolumeUniverseDefinitions(algorithm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="market">Market of the ETF</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
string etfTicker,
|
||||
string market,
|
||||
UniverseSettings universeSettings,
|
||||
Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
market ??= _algorithm.BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Equity, out var defaultMarket)
|
||||
? defaultMarket
|
||||
: throw new Exception("No default market set for security type: Equity");
|
||||
|
||||
var etfSymbol = new Symbol(
|
||||
SecurityIdentifier.GenerateEquity(
|
||||
etfTicker,
|
||||
market,
|
||||
true,
|
||||
mappingResolveDate: _algorithm.Time.Date),
|
||||
etfTicker);
|
||||
|
||||
return ETF(etfSymbol, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="market">Market of the ETF</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(string etfTicker, string market, Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return ETF(etfTicker, market, null, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(string etfTicker, Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return ETF(etfTicker, null, null, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
string etfTicker,
|
||||
UniverseSettings universeSettings,
|
||||
Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return ETF(etfTicker, null, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="market">Market of the ETF</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
string etfTicker,
|
||||
string market = null,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return ETF(etfTicker, market, universeSettings, universeFilterFunc?.ConvertPythonUniverseFilterFunction<ETFConstituentUniverse>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="etfTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="etfTicker">Ticker of the ETF to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(
|
||||
string etfTicker,
|
||||
UniverseSettings universeSettings,
|
||||
PyObject universeFilterFunc)
|
||||
{
|
||||
return ETF(etfTicker, null, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided ETF <paramref name="symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="symbol">ETF Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(Symbol symbol, UniverseSettings universeSettings,
|
||||
Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return new ETFConstituentsUniverseFactory(symbol, universeSettings ?? _algorithm.UniverseSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided ETF <paramref name="symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="symbol">ETF Symbol to get constituents for</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(Symbol symbol, Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return ETF(symbol, null, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided ETF <paramref name="symbol"/>
|
||||
/// </summary>
|
||||
/// <param name="symbol">ETF Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New ETF constituents Universe</returns>
|
||||
public Universe ETF(Symbol symbol, UniverseSettings universeSettings = null, PyObject universeFilterFunc = null)
|
||||
{
|
||||
return ETF(symbol, universeSettings ?? _algorithm.UniverseSettings,
|
||||
universeFilterFunc?.ConvertPythonUniverseFilterFunction<ETFConstituentUniverse>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="market">Market of the index</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(string indexTicker, string market, UniverseSettings universeSettings,
|
||||
Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
market ??= _algorithm.BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Index, out var defaultMarket)
|
||||
? defaultMarket
|
||||
: throw new Exception("No default market set for security type: Index");
|
||||
|
||||
return Index(
|
||||
Symbol.Create(indexTicker, SecurityType.Index, market),
|
||||
universeSettings,
|
||||
universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="market">Market of the index</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(string indexTicker, string market, Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return Index(indexTicker, market, null, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(string indexTicker, Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return Index(indexTicker, null, null, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(string indexTicker, UniverseSettings universeSettings,
|
||||
Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return Index(indexTicker, null, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="market">Market of the index</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
string indexTicker,
|
||||
string market = null,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return Index(indexTicker, market, universeSettings, universeFilterFunc?.ConvertPythonUniverseFilterFunction<ETFConstituentUniverse>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexTicker"/>
|
||||
/// </summary>
|
||||
/// <param name="indexTicker">Ticker of the index to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
string indexTicker,
|
||||
UniverseSettings universeSettings,
|
||||
PyObject universeFilterFunc)
|
||||
{
|
||||
return Index(indexTicker, null, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexSymbol"/>
|
||||
/// </summary>
|
||||
/// <param name="indexSymbol">Index Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(Symbol indexSymbol, UniverseSettings universeSettings,
|
||||
Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return new ETFConstituentsUniverseFactory(indexSymbol, universeSettings, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexSymbol"/>
|
||||
/// </summary>
|
||||
/// <param name="indexSymbol">Index Symbol to get constituents for</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(Symbol indexSymbol, Func<IEnumerable<ETFConstituentUniverse>, IEnumerable<Symbol>> universeFilterFunc)
|
||||
{
|
||||
return Index(indexSymbol, null, universeFilterFunc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a universe for the constituents of the provided <paramref name="indexSymbol"/>
|
||||
/// </summary>
|
||||
/// <param name="indexSymbol">Index Symbol to get constituents for</param>
|
||||
/// <param name="universeSettings">Universe settings</param>
|
||||
/// <param name="universeFilterFunc">Function to filter universe results</param>
|
||||
/// <returns>New index constituents Universe</returns>
|
||||
public Universe Index(
|
||||
Symbol indexSymbol,
|
||||
UniverseSettings universeSettings = null,
|
||||
PyObject universeFilterFunc = null)
|
||||
{
|
||||
return Index(indexSymbol, universeSettings ?? _algorithm.UniverseSettings,
|
||||
universeFilterFunc?.ConvertPythonUniverseFilterFunction<ETFConstituentUniverse>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new fine universe that contains the constituents of QC500 index based onthe company fundamentals
|
||||
/// The algorithm creates a default tradable and liquid universe containing 500 US equities
|
||||
/// which are chosen at the first trading day of each month.
|
||||
/// </summary>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
public Universe QC500
|
||||
{
|
||||
get
|
||||
{
|
||||
return ETF(Symbol.Create("SPY", SecurityType.Equity, Market.USA));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coarse universe that contains the top count of stocks
|
||||
/// by daily dollar volume
|
||||
/// </summary>
|
||||
/// <param name="count">The number of stock to select</param>
|
||||
/// <param name="universeSettings">The settings for stocks added by this universe.
|
||||
/// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
|
||||
/// <returns>A new coarse universe for the top count of stocks by dollar volume</returns>
|
||||
public Universe Top(int count, UniverseSettings universeSettings = null)
|
||||
{
|
||||
universeSettings ??= _algorithm.UniverseSettings;
|
||||
|
||||
var symbol = Symbol.Create("us-equity-dollar-volume-top-" + count, SecurityType.Equity, Market.USA);
|
||||
return FundamentalUniverse.USA(selectionData => (
|
||||
from c in selectionData
|
||||
orderby c.DollarVolume descending
|
||||
select c.Symbol).Take(count),
|
||||
universeSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user