/* * 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 MathNet.Numerics; 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.Data.UniverseSelection; using QuantConnect.Indicators; using QuantConnect.Securities; using System; using System.Collections.Generic; using System.Linq; namespace QuantConnect.Algorithm.CSharp { /// /// CapmAlphaRankingFrameworkAlgorithm: example of custom scheduled universe selection model /// Universe Selection inspired by https://www.quantconnect.com/tutorials/strategy-library/capm-alpha-ranking-strategy-on-dow-30-companies /// public class CapmAlphaRankingFrameworkAlgorithm : QCAlgorithm { /// /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// public override void Initialize() { // Set requested data resolution UniverseSettings.Resolution = Resolution.Daily; SetStartDate(2016, 1, 1); //Set Start Date SetEndDate(2017, 1, 1); //Set End Date SetCash(100000); //Set Strategy Cash // set algorithm framework models SetUniverseSelection(new CapmAlphaRankingUniverseSelectionModel()); SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromDays(1), 0.025, null)); SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel()); SetExecution(new ImmediateExecutionModel()); SetRiskManagement(new MaximumDrawdownPercentPerSecurity(0.01m)); } /// /// This universe selection model picks stocks with the highest alpha: interception of the linear regression against a benchmark. /// private class CapmAlphaRankingUniverseSelectionModel : UniverseSelectionModel { private const int period = 21; private const string _benchmark = "SPY"; // Symbols of Dow 30 companies. private readonly IEnumerable _symbols = new[] { "AAPL", "AXP", "BA", "CAT", "CSCO", "CVX", "DD", "DIS", "GE", "GS", "HD", "IBM", "INTC", "JPM", "KO", "MCD", "MMM", "MRK", "MSFT", "NKE","PFE", "PG", "TRV", "UNH", "UTX", "V", "VZ", "WMT", "XOM" }.Select(x => QuantConnect.Symbol.Create(x, SecurityType.Equity, Market.USA)); public override IEnumerable CreateUniverses(QCAlgorithm algorithm) { // Adds the benchmark to the user defined universe var benchmark = algorithm.AddEquity(_benchmark, Resolution.Daily); // Defines a schedule universe that fires after market open when the month starts yield return new ScheduledUniverse( benchmark.Exchange.TimeZone, algorithm.DateRules.MonthStart(benchmark.Symbol), algorithm.TimeRules.AfterMarketOpen(benchmark.Symbol), datetime => SelectPair(algorithm, datetime), algorithm.UniverseSettings); } /// /// Selects the pair (two stocks) with the highest alpha /// private IEnumerable SelectPair(QCAlgorithm algorithm, DateTime dateTime) { var dictionary = new Dictionary(); var benchmark = GetReturns(algorithm, _benchmark); foreach (var symbol in _symbols) { var prices = GetReturns(algorithm, symbol); // Calculate the Least-Square fitting to the returns of a given symbol and the benchmark var ols = Fit.Line(prices, benchmark); dictionary.Add(symbol, ols.Item1); } // Returns the top 2 highest alphas var orderedDictionary = dictionary.OrderByDescending(key => key.Value); return orderedDictionary.Take(2).Select(x => x.Key); } private double[] GetReturns(QCAlgorithm algorithm, Symbol symbol) { var window = new RollingWindow(period); var rateOfChange = new RateOfChange(1); rateOfChange.Updated += (s, item) => window.Add((double)item.Value); foreach (var bar in algorithm.History(symbol, period, Resolution.Daily)) { rateOfChange.Update(bar.EndTime, bar.Close); } return window.ToArray(); } } } }