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);
                }
            }
        }
    }
}