Overall Statistics |
Total Trades 75 Average Win 0.15% Average Loss -0.01% Compounding Annual Return 83.363% Drawdown 5.500% Expectancy 8.547 Net Profit 22.067% Sharpe Ratio 2.569 Loss Rate 19% Win Rate 81% Profit-Loss Ratio 10.79 Alpha 0.301 Beta 1.825 Annual Standard Deviation 0.2 Annual Variance 0.04 Information Ratio 2.489 Tracking Error 0.159 Treynor Ratio 0.281 Total Fees $100.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 QuantConnect.Data; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; using QuantConnect.Data.Market; using QuantConnect.Data.UniverseSelection; using QuantConnect.Indicators; using QuantConnect.Data.Custom; using QuantConnect.Orders; using QuantConnect.Securities; using QuantConnect.Data.Consolidators; namespace QuantConnect.Algorithm.CSharp { public class StockRankAlgorithm : QCAlgorithm { // algorythm settings const Resolution _algo_resolution = Resolution.Daily; public const decimal _startingcash = 100000m; public const decimal _positionweight = 0.10m; private int _lastmonth = 0; // public DateTime _startdate = new DateTime(2007, 11, 23); // public DateTime _enddate = new DateTime(2014, 11, 23); public DateTime _startdate = DateTime.Now.Date.AddDays(-120); public DateTime _enddate = DateTime.Now.Date.AddDays(-1); // sort the data by daily dollar volume and take the top 'NumberOfSymbolsCoarse' public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) { var hasmorningstar = from x in coarse //where (x.HasFundamentalData && x.DollarVolume > 200000000m && x.DollarVolume > 500000000m) where (x.HasFundamentalData && x.DollarVolume > 20000000m && x.DollarVolume > 70000000m) orderby x.DollarVolume ascending select x.Symbol; // we need to return only the symbol objects return hasmorningstar.Take(100); } // calculate the f-score private int FScore( decimal netincome, decimal operating_cashflow, decimal roa_current, decimal roa_past, decimal issued_current, decimal issued_past, decimal grossm_current, decimal grossm_past, decimal longterm_current, decimal longterm_past, decimal curratio_current, decimal curratio_past, decimal assetturn_current, decimal assetturn_past ) { int fscore = 0; fscore += (roa_current > 0m ? 1 : 0 ); // return on assets is positive fscore += ( operating_cashflow > 0m ? 1 : 0 ); // operating cashflow in current year is positive fscore += ( roa_current >= roa_past ? 1 : 0 ); // roa has increased since last Time fscore += ( operating_cashflow > roa_current ? 1 : 0 ); // cashflow from current operations are greater than roa fscore += ( longterm_current <= longterm_past ? 1 : 0 ); // a decrease in the long term debt ratio fscore += ( curratio_current >= curratio_past ? 1 : 0 ); // an increase in the current ratio fscore += ( issued_current <= issued_past ? 1 : 0 ); // no new shares have been issued fscore += ( grossm_current >= grossm_past ? 1 : 0 ); // an increase in gross margin fscore += ( assetturn_current >= assetturn_past ? 1 : 0 ); // a higher asset turnover ratio // Debug("<<<<<<"); //Debug("f-score :" +fscore); // Debug("roa current : " + roa_current); // Debug("operating cashflow : " + operating_cashflow); // Debug("roa current : " + roa_current + " past : " + roa_past); // Debug("operating cashflow : " + operating_cashflow ); // Debug("longterm_current : " + longterm_current + " past : " + longterm_past); // Debug("curratio_current : " + curratio_current + " past : " + curratio_past); // Debug("issued current : " + issued_current + " : past " + issued_past); // Debug("grossm current : " + grossm_current + " : past " + grossm_past); // Debug("assetturn_current : " + assetturn_current + " : " + assetturn_past); return fscore; } // sort the data by P/E ratio and take the top 'NumberOfSymbolsFine' public IEnumerable<Symbol> FineSelectionFunction(IEnumerable<FineFundamental> fine) { // find piatroski score var piatroskiscore = from x in fine let fs = FScore( x.FinancialStatements.IncomeStatement.NetIncome.TwelveMonths, x.FinancialStatements.CashFlowStatement.CashFlowFromContinuingOperatingActivities.TwelveMonths, x.OperationRatios.ROA.ThreeMonths, x.OperationRatios.ROA.OneYear, x.FinancialStatements.BalanceSheet.ShareIssued.ThreeMonths, x.FinancialStatements.BalanceSheet.ShareIssued.TwelveMonths, x.OperationRatios.GrossMargin.ThreeMonths, x.OperationRatios.GrossMargin.OneYear, x.OperationRatios.LongTermDebtEquityRatio.ThreeMonths, x.OperationRatios.LongTermDebtEquityRatio.OneYear, // fix need last year x.OperationRatios.CurrentRatio.ThreeMonths, x.OperationRatios.CurrentRatio.OneYear, // fix need last year x.OperationRatios.AssetsTurnover.ThreeMonths, x.OperationRatios.AssetsTurnover.OneYear // fix need last year ) where (fs >= 5) orderby fs descending select x; // take the top entries from our sorted collection var topFine = piatroskiscore.Take(10); Debug("Found " + topFine.Count() + " possibilities"); // foreach (var s in topFine) // { // Debug(s.ToString()); // } // we need to return only the symbol objects return topFine.Select(x => x.Symbol); } // Initialize the data and resolution you require for your strategy: public override void Initialize() { SetStartDate(_startdate); SetEndDate(_enddate); // don't do any margin stuff SetBrokerageModel(Brokerages.BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash); //Cash allocation SetCash(_startingcash); UniverseSettings.Resolution = _algo_resolution; // this add universe method accepts two parameters: // - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol> // - fine selection function: accepts an IEnumerable<FineFundamental> and returns an IEnumerable<Symbol> AddUniverse(CoarseSelectionFunction, FineSelectionFunction); } public override void OnData(Slice slice) { // only rebalance every month if (slice.Time.Month != _lastmonth) { _lastmonth = slice.Time.Month; // sell what we are no longer interested iinterested foreach (var pos in Portfolio.Keys) { if (Portfolio[pos].HoldStock) { var check = from x in slice.Bars where (x.Value.Symbol == pos) select x.Value.Symbol; if (check.Count() == 0) SetHoldings(pos, 0m); } } // buy highly ranked stocks foreach ( var bar in slice.Bars) SetHoldings(bar.Value.Symbol, _positionweight); } } } }