| Overall Statistics |
|
Total Trades 764 Average Win 0.73% Average Loss -0.39% Compounding Annual Return 8.255% Drawdown 41.500% Expectancy 1.057 Net Profit 436.208% Sharpe Ratio 0.618 Probabilistic Sharpe Ratio 1.797% Loss Rate 29% Win Rate 71% Profit-Loss Ratio 1.88 Alpha 0.077 Beta -0.023 Annual Standard Deviation 0.122 Annual Variance 0.015 Information Ratio 0.023 Tracking Error 0.218 Treynor Ratio -3.317 Total Fees $2677.14 |
from QuantConnect import Resolution
from QuantConnect.Algorithm import QCAlgorithm
class NCAVsimple(QCAlgorithm):
def Initialize(self):
#rebalancing should occur in July
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
self.UniverseSettings.Resolution = Resolution.Daily
self.filtered_fine = None
self.filtered_coarse = None
self.symbol = self.AddEquity('SPY', Resolution.Daily).Symbol
# self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
self.yearly_rebalance = False
self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)
self.Schedule.On(self.DateRules.MonthEnd(self.symbol), self.TimeRules.AfterMarketOpen(self.symbol), self.rebalance)
def CoarseSelectionFunction(self, coarse):
if self.yearly_rebalance:
# drop stocks which have no fundamental data or have low price
self.filtered_coarse = [x.Symbol for x in coarse if (x.HasFundamentalData) and x.Market == 'usa']
return self.filtered_coarse
else:
return Universe.Unchanged
def FineSelectionFunction(self, fine):
if self.yearly_rebalance:
#calculate the NCAV/MV and add the property to fine universe object
#filters out the companies in the financial sector as suggested
fine = [x for x in fine if (float(x.FinancialStatements.BalanceSheet.CurrentAssets.Value) > 0)
and (float(x.EarningReports.BasicAverageShares.Value) > 0)
and (float(x.FinancialStatements.BalanceSheet.CurrentLiabilities.Value) > 0)
and (float(x.MarketCap) > 0)
# This indicator will denote which one of the six industry data collection templates applies to the company.
# Each industry data collection template includes data elements that are commonly reported by companies in that industry.
# N=Normal (Manufacturing), M=Mining, U=Utility, T=Transportation, B=Bank, I=Insurance
and (x.CompanyReference.IndustryTemplateCode!="B")
and (x.CompanyReference.IndustryTemplateCode!="I")]
fine = sorted(fine, key = lambda x:x.MarketCap, reverse=True)
self.Debug("fine len: " + str(len(fine)))
for i in fine:
#calculates the net current asset value per share
self.Debug(i.Symbol)
total_liabilities = i.FinancialStatements.BalanceSheet.TotalLiabilitiesAsReported.TwelveMonths
current_assets = i.FinancialStatements.BalanceSheet.CurrentAssets.TwelveMonths
i.ncav = (current_assets - total_liabilities)/float(i.MarketCap)
if i.ncav > 1.5:
self.Debug("-total_liabilities: " + str(total_liabilities))
self.Debug("-current_assets: " + str(current_assets))
self.Debug("-market_cap: " + str(i.MarketCap))
self.Debug("-ncav: " + str(i.ncav))
# keeps all symbols that have a NCAV/MV higher than 1.5
# sorted_fine = sorted(fine, lambda x: x.ncav)
self.filtered_fine = [i.Symbol for i in fine if (i.ncav > 1.5)]
return self.filtered_fine[:25]
else:
return []
def rebalance(self):
#yearly rebalance
if self.Time.month == 7:
self.Debug("Rebalance" + str(self.Time))
self.yearly_rebalance = True
def OnData(self, data):
if not self.yearly_rebalance: return
if self.filtered_fine:
stocks_invested = [x.Key for x in self.Portfolio]
for i in stocks_invested:
#liquidate the stocks not in the filtered NCAV/MV list
if i not in self.filtered_fine:
self.Liquidate(i)
#purchase the stocks in the list
elif i in self.filtered_fine:
self.SetHoldings(i, 1/len(self.filtered_fine))
self.yearly_rebalance = False