Overall Statistics |
Total Trades 9 Average Win 0% Average Loss 0% Compounding Annual Return 1130.493% Drawdown 26.300% Expectancy 0 Net Profit 24.614% Sharpe Ratio 10.83 Probabilistic Sharpe Ratio 69.521% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 10.755 Beta 1.393 Annual Standard Deviation 1.029 Annual Variance 1.06 Information Ratio 10.708 Tracking Error 1.015 Treynor Ratio 8.001 Total Fees $9.00 Estimated Strategy Capacity $200000.00 Lowest Capacity Asset CEY XM6DSR8J2TQE|CEY S67FQV7Z62CL |
#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.Algorithm.CSharp { public class DeterminedMagentaGoat : QCAlgorithm { public override void Initialize() { SetStartDate(2021, 1, 19); //Set Start Date SetEndDate(2021, 2, 19); //Set End Date SetCash(100000); //Set Strategy Cash AddUniverseSelection( new OptionsUniverseSelectionModel( new CoarseFundamentalUniverseSelectionModel(SelectCoarse), OptionFilterFunction ) ); } /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// Slice object keyed by symbol containing the stock data public override void OnData(Slice data) { // We can use data.OptionChains, based on the Fundamental universe from Initialize if (!Portfolio.Invested) { foreach (var kpv in data.OptionChains) { var optionChain = kpv.Value; // Buy closest Call Option var closestCall = optionChain.Where(c => c.Right==OptionRight.Call && c.Strike>c.UnderlyingLastPrice) .OrderBy(c => c.Strike) .Select(c => c.Symbol) .First(); Buy(closestCall, 1); } } } private IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> coarse) { // Return most liquid assets w/ fundamentals return coarse.Where(c => c.HasFundamentalData) .OrderByDescending(c => c.DollarVolume) .Take(100) .Select(c => c.Symbol); } private OptionFilterUniverse OptionFilterFunction(OptionFilterUniverse optionFilterUniverse) { return optionFilterUniverse.Strikes(-2, +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); } } } } }