Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
from System import * from System.Collections.Generic import List from QuantConnect import * from QuantConnect.Algorithm import QCAlgorithm from QuantConnect.Data.UniverseSelection import * import pandas as pd import numpy as np class CoarseFineFundamentalComboAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2010,01,01) #Set Start Date self.SetEndDate(2014,06,01) #Set End Date self.SetCash(50000) #Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.AddEquity("SPY") self.numOfCourseSymbols = 110 self.numOfPortfolio = 5 self.numOfPortSymbols = self.numOfPortfolio * 15 self.numOfMonths = 48 self._changes = SecurityChanges.None self.flag1 = 1 self.flag2 = 0 self.pos = 0 self.df_return = pd.DataFrame(index = range(self.numOfPortfolio+1)) self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), Action(self.Rebalancing)) # sort the data by daily dollar volume and take the top 'NumberOfSymbols' def CoarseSelectionFunction(self, coarse): if self.flag1: CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData] sortedByVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True) top = sortedByVolume[:self.numOfCourseSymbols] # we need to return only the symbol objects list = List[Symbol]() for x in top: list.Add(x.Symbol) return list else: return(List[Symbol]()) def FineSelectionFunction(self, fine): if self.flag1: self.flag1 = 0 self.flag2 = 1 # filter the fine by deleting equities wit zero factor value filtered_fine = [x for x in fine if x.ValuationRatios.PERatio != 0 ] # sort the fine by reverse order of factor value sorted_fine = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PERatio, reverse=True) self.symbol = [str(x.Symbol.Value) for x in sorted_fine] # factor_value = [x.ValuationRatios.PERatio for x in sorted_fine] self.pos = self.pos + 1 return (List[Symbol]()) else: return (List[Symbol]()) def Rebalancing(self): self.flag1 = 1 def OnData(self, data): if self.pos > 0: if self.flag2 == 1: self.flag2 = 0 sorted_symbol = self.symbol self.AddEquity("SPY") # add benchmark for x in sorted_symbol: self.AddEquity(x) history = self.History(21,Resolution.Daily) monthly_return =[] new_symbol_list =[] for j in range(len(sorted_symbol)): try: daily_price = [] for slice in history: bar = slice[sorted_symbol[j]] daily_price.append(float(bar.Close)) new_symbol_list.append(sorted_symbol[j]) monthly_return.append(daily_price[-1] / daily_price[0] - 1) except: self.Log("No history data for " + str(sorted_symbol[j])) del daily_price monthly_return = monthly_return[:self.numOfPortSymbols] # devide the stocks into n portfolios reshape_return = np.reshape(monthly_return, (self.numOfPortfolio, len(monthly_return)/self.numOfPortfolio)) # calculate the average return of different portfolios port_avg_return = np.mean(reshape_return,axis=1).tolist() # add return of "SPY" as the benchmark to the end of the return list benchmark_syl = self.AddEquity("SPY").Symbol history_benchmark = self.History(21,Resolution.Daily) benchmark_daily_price = [float(slice[benchmark_syl].Close) for slice in history_benchmark] benchmark_monthly_return = (benchmark_daily_price[-1]/benchmark_daily_price[0]) - 1 port_avg_return.append(benchmark_monthly_return) self.df_return[str(self.pos)] = port_avg_return if self.pos == self.numOfMonths: self.Log(str(self.df_return)) result = self.calculate_criteria(self.df_return) self.Log(str(result)) def calculate_criteria(self,df_port_return): total_return = (df_port_return + 1).T.cumprod().iloc[-1,:] - 1 self.Log(str(total_return)) annual_return = (total_return+1)**(1./6)-1 excess_return = annual_return - np.array(annual_return)[-1] correlation = annual_return[0:5].corr(pd.Series([5,4,3,2,1],index = annual_return[0:5].index)) # higher factor with higher return if np.array(total_return)[0] > np.array(total_return)[-2]: loss_excess = df_port_return.iloc[-2,:] - df_port_return.iloc[-1,:] win_excess = df_port_return.iloc[0,:] - df_port_return.iloc[-1,:] loss_prob = loss_excess[loss_excess<0].count()/float(len(loss_excess)) win_prob = win_excess[win_excess>0].count()/float(len(win_excess)) win_port_excess_return = np.array(excess_return)[0] loss_port_excess_return = np.array(excess_return)[-2] # higher factor with lower return else: loss_excess = df_port_return.iloc[0,:] - df_port_return.iloc[-1,:] win_excess = df_port_return.iloc[-2,:] - df_port_return.iloc[-1,:] loss_prob = loss_excess[loss_excess<0].count()/float(len(loss_excess)) win_prob = win_excess[win_excess>0].count()/float(len(win_excess)) win_port_excess_return = np.array(excess_return)[-2] loss_port_excess_return = np.array(excess_return)[0] test_result = {"correelation":[], "win probality":[], "loss probality":[], "win portfolio excess return":[], "loss portfolio excess return":[]} test_result["correelation"].append(correlation) test_result["win probality"].append(win_prob) test_result["loss probality"].append(loss_prob) test_result["win portfolio excess return"].append(win_port_excess_return) test_result["loss portfolio excess return"].append(loss_port_excess_return) return pd.DataFrame(test_result)