| Overall Statistics |
|
Total Trades 144 Average Win 0.55% Average Loss -0.58% Compounding Annual Return 27.398% Drawdown 20.000% Expectancy 0.187 Net Profit 27.398% Sharpe Ratio 1.096 Probabilistic Sharpe Ratio 49.903% Loss Rate 39% Win Rate 61% Profit-Loss Ratio 0.94 Alpha 0.077 Beta 1.1 Annual Standard Deviation 0.185 Annual Variance 0.034 Information Ratio 1.022 Tracking Error 0.087 Treynor Ratio 0.184 Total Fees $239.28 Estimated Strategy Capacity $780000.00 Lowest Capacity Asset HOL TYJB6RKZ4JTX |
MAX_POSITIONS = 20
REBALANCE_PERIOD = 20
class DataTesting(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetEndDate(2010, 12, 31)
self.SetCash(100000)
self.UniverseSettings.Resolution = Resolution.Minute
self.AddUniverse(self.CoarseFilter, self.FineFilter)
self.rebalance = 0
self.buy = []
self.sell = []
def CoarseFilter(self, coarse):
if self.rebalance and self.rebalance <= REBALANCE_PERIOD:
self.rebalance += 1
return Universe.Unchanged
self.rebalance = 1
#filtered = [x for x in coarse if x.HasFundamentalData]
#filtered = [x for x in filtered if float(x.AdjustedPrice) > 5]
#filtered = [x.Symbol for x in filtered]
filtered = [x.Symbol for x in coarse if x.HasFundamentalData and (x.AdjustedPrice > 5.0)]
return filtered
def FineFilter(self, fine):
filtered = list(filter(self.FineFundamentalFilter, fine))
return self.FineSort(filtered)[:MAX_POSITIONS]
def FineFundamentalFilter(self, security):
eps3m = security.EarningRatios.DilutedEPSGrowth.ThreeMonths > 0
eps1y = security.EarningRatios.DilutedEPSGrowth.OneYear > 0
fcf3m = security.FinancialStatements.CashFlowStatement.FreeCashFlow.ThreeMonths > 0
fcf1y = security.FinancialStatements.CashFlowStatement.FreeCashFlow.TwelveMonths > 0
roe3m = security.OperationRatios.ROE.ThreeMonths > 0
roe1y = security.OperationRatios.ROE.OneYear > 0
return eps3m and eps1y and fcf3m and fcf1y and roe3m and roe1y
def FineSort(self, fine):
ranked = {}
ranks = {
'earnings_growth': [x.Symbol for x in sorted(fine, key=lambda x:
(x.EarningRatios.DilutedEPSGrowth.ThreeMonths +
x.EarningRatios.DilutedEPSGrowth.OneYear +
x.EarningRatios.DilutedEPSGrowth.ThreeYears) / 3
)],
'revenue_growth': [x.Symbol for x in sorted(fine, key=lambda x:
(x.OperationRatios.RevenueGrowth.ThreeMonths +
x.OperationRatios.RevenueGrowth.OneYear +
x.OperationRatios.RevenueGrowth.ThreeYears) / 3
)],
'book_growth': [x.Symbol for x in sorted(fine, key=lambda x:
(x.EarningRatios.BookValuePerShareGrowth.ThreeMonths +
x.EarningRatios.BookValuePerShareGrowth.OneYear +
x.EarningRatios.BookValuePerShareGrowth.ThreeYears) / 3
)],
'fcf_growth': [x.Symbol for x in sorted(fine, key=lambda x:
(x.EarningRatios.FCFPerShareGrowth.ThreeMonths +
x.EarningRatios.FCFPerShareGrowth.OneYear +
x.EarningRatios.FCFPerShareGrowth.ThreeYears) / 3
)]
}
for security in fine:
symbol = security.Symbol
ranked[symbol] = 0
for key, sort in ranks.items():
ranked[symbol] += (sort.index(symbol) + 1)
#ranked = dict(sorted(ranked.items(), key=lambda x: x[1], reverse=True))
#ranked = [symbol for symbol in ranked]
ranked = [symbol for symbol, rank in sorted(ranked.items(), key=lambda t: t[1], reverse=True)]
return ranked
def OnSecuritiesChanged(self, changes):
for added in changes.AddedSecurities:
self.buy.append(added.Symbol)
for removed in changes.RemovedSecurities:
self.sell.append(removed.Symbol)
def OnData(self, data):
#sell = self.sell[:]
#buy = self.buy[:]
#if len(sell) > 0:
# for symbol in sell:
# if data.ContainsKey(symbol):
# self.sell.remove(symbol)
# self.Liquidate(symbol)
#if len(buy) > 0:
# for symbol in buy:
# if data.ContainsKey(symbol):
# self.buy.remove(symbol)
# self.SetHoldings(symbol, 1 / MAX_POSITIONS)
for symbol in [*self.sell]:
self.sell.remove(symbol)
self.Liquidate(symbol)
for symbol in [*self.buy]:
if data.ContainsKey(symbol) and data[symbol] is not None:
self.buy.remove(symbol)
self.SetHoldings(symbol, 1 / MAX_POSITIONS)