| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -0.536 Tracking Error 0.188 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
#region imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Drawing;
using QuantConnect;
using QuantConnect.Algorithm.Framework;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.Positions;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Storage;
using QuantConnect.Data.Custom.AlphaStreams;
using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
public class ETFUniverseOptions : QCAlgorithm
{
Symbol _benchmark;
List<DateTime> _selections = new List<DateTime>();
public override void Initialize()
{
SetCash(1000000000);
SetStartDate(2020, 1, 1);
SetEndDate(2024, 1, 1);
UniverseSettings.Resolution = Resolution.Hour;
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
Portfolio.SetPositions(SecurityPositionGroupModel.Null);
SetSecurityInitializer(security =>
{
var seeder = new FuncSecuritySeeder(GetLastKnownPrices).SeedSecurity(security);
security.SetBuyingPowerModel(new ConstantBuyingPowerModel(1));
});
_benchmark = AddEquity("QQQ", dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
var etfUniverse = AddUniverse(Universe.ETF("QQQ", Market.USA, UniverseSettings, ETFConstituentsFilter));
AddUniverseOptions(etfUniverse, OptionFilterFunction);
}
private IEnumerable<Symbol> ETFConstituentsFilter(IEnumerable<ETFConstituentData> constituents)
{
// Get the 10 securities with the largest weight in the index
return constituents.OrderByDescending(c => c.Weight).Take(10).Select(c => c.Symbol);
}
private OptionFilterUniverse OptionFilterFunction(OptionFilterUniverse optionFilterUniverse)
{
return optionFilterUniverse.Strikes(0, 2).FrontMonth().CallsOnly();
}
}
}#region imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Drawing;
using QuantConnect;
using QuantConnect.Algorithm.Framework;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Storage;
using QuantConnect.Data.Custom.AlphaStreams;
using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion
namespace QuantConnect {
/// <summary>
/// This universe selection model will chain to the security changes of a given <see cref="UniverseSelectionModel"/> selection
/// output and create a new <see cref="OptionChainUniverse"/> for each of them
///
/// This class is based on https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/universe-selection/options-universes#61-Option-Chained-Universe-Selection
/// instead of attaching to a Universe, it attaches to a UniverseSelectionModel
/// </summary>
public class OptionsUniverseSelectionModel : UniverseSelectionModel
{
private DateTime _nextRefreshTimeUtc;
private readonly UniverseSelectionModel _universeSelectionModel;
private readonly Func<OptionFilterUniverse, OptionFilterUniverse> _optionFilter;
private readonly Dictionary<Universe, IEnumerable<Symbol>> _fundamentalUniverses;
/// <summary>
/// Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.
/// </summary>
public override DateTime GetNextRefreshTimeUtc()
{
var parentRefreshTime = _universeSelectionModel.GetNextRefreshTimeUtc();
if (parentRefreshTime <= _nextRefreshTimeUtc)
{
_fundamentalUniverses.Clear();
_nextRefreshTimeUtc = parentRefreshTime;
}
return _nextRefreshTimeUtc;
}
/// <summary>
/// Creates a new instance of <see cref="OptionsUniverseSelectionModel"/>
/// </summary>
/// <param name="universeSelectionModel">The universe selection model we want to chain to</param>
/// <param name="optionFilter">The option filter universe to use</param>
public OptionsUniverseSelectionModel(UniverseSelectionModel universeSelectionModel, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter = null) {
_nextRefreshTimeUtc = DateTime.MaxValue;
_universeSelectionModel = universeSelectionModel;
_optionFilter = optionFilter;
_fundamentalUniverses = new Dictionary<Universe, IEnumerable<Symbol>>();
}
/// <summary>
/// Creates the universes for this algorithm. Called when the original universeSelectionModel
/// or when the symbols it contains change
/// </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;
if (_fundamentalUniverses.Count <= 0)
{
var universes = _universeSelectionModel.CreateUniverses(algorithm);
foreach (var universe in universes)
{
_fundamentalUniverses.Add(universe, Enumerable.Empty<Symbol>());
universe.SelectionChanged += (sender, args) =>
{
// 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.
_fundamentalUniverses[universe] = ((Universe.SelectionEventArgs)args).CurrentSelection
.Select(symbol => Symbol.CreateOption(
symbol,
symbol.ID.Market,
symbol.SecurityType.DefaultOptionStyle(),
default(OptionRight),
0m,
SecurityIdentifier.DefaultDate))
.ToList();
// the universe we were watching changed, this will trigger a call to CreateUniverses
_nextRefreshTimeUtc = DateTime.MinValue;
};
}
}
foreach (var kpv in _fundamentalUniverses)
{
yield return kpv.Key;
foreach (var optionSymbol in kpv.Value)
{
yield return algorithm.CreateOptionChain(optionSymbol, _optionFilter, kpv.Key.UniverseSettings);
}
}
}
}
}