Overall Statistics |
Total Trades
4809
Average Win
0.12%
Average Loss
-0.13%
Compounding Annual Return
12.074%
Drawdown
34.000%
Expectancy
0.419
Net Profit
282.763%
Sharpe Ratio
0.697
Probabilistic Sharpe Ratio
9.103%
Loss Rate
27%
Win Rate
73%
Profit-Loss Ratio
0.93
Alpha
0.022
Beta
0.77
Annual Standard Deviation
0.131
Annual Variance
0.017
Information Ratio
0.021
Tracking Error
0.076
Treynor Ratio
0.119
Total Fees
$295.13
Estimated Strategy Capacity
$9300000.00
Lowest Capacity Asset
WCBO R735QTJ8XC9X
|
# https://quantpedia.com/strategies/alpha-cloning-following-13f-fillings/ # # Create a universe of active mutual fund managers. # Use 13F filings to identify the “best idea” stocks for each manager. # Invest in the stocks, which are the “best ideas” for most of the managers. # # QC Implementation: # - Investor preferences was downloaded from https://www.insidermonkey.com/hedge-fund/browse/A/ # - Investors list consists of first 10 investors in each browse letter and from lists in basic and premium cards on https://www.gurufocus.com/guru/list # - Investor preferences are modeled to be known 2 months after announcement. #region imports from AlgorithmImports import * import numpy as np from dateutil.relativedelta import relativedelta #endregion class AlphaCloningFollowing13FFillings(QCAlgorithm): def Initialize(self): self.SetStartDate(2011, 1, 1) self.SetCash(100000) self.weight = {} self.investors_preferences = {} self.symbol = self.AddEquity('SPY', Resolution.Daily).Symbol self.months_lag = 2 # Lag for getting investors preferences report csv_string_file = self.Download('data.quantpedia.com/backtesting_data/economic/investors_preferences.csv') lines = csv_string_file.split('\r\n') dates = [] # Skip csv header in loop for line in lines[1:]: line_split = line.split(';') date = datetime.strptime(line_split[0], "%d.%m.%Y").date() self.investors_preferences[date] = {} for ticker in line_split[1:]: if ticker not in self.investors_preferences[date]: self.investors_preferences[date][ticker] = 0 self.investors_preferences[date][ticker] += 1 self.month_counter = 0 self.selection_flag = False self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction) self.Schedule.On(self.DateRules.MonthStart(self.symbol), self.TimeRules.AfterMarketOpen(self.symbol), self.Selection) def OnSecuritiesChanged(self, changes): for security in changes.AddedSecurities: security.SetFeeModel(CustomFeeModel()) security.SetLeverage(5) def CoarseSelectionFunction(self, coarse): if not self.selection_flag: return Universe.Unchanged selected_report = None min_date = self.Time.date() - relativedelta(months=self.months_lag+1) # quarterly data max_date = self.Time.date() for date in self.investors_preferences: # Get latest report if date >= min_date and date <= max_date: selected_report = self.investors_preferences[date] # Report might not be selected, because there are no data for that date if selected_report is None: return Universe.Unchanged # Select universe based on report selected = [x.Symbol for x in coarse if x.Symbol.Value in selected_report] # Calculate total preferences votes for selected report total_preferences_votes = sum([x[1] for x in selected_report.items()]) # Calculate weight for each stock in selected universe for symbol in selected: # weight = total stock preferences votes / total investor votes in selected report self.weight[symbol] = selected_report[symbol.Value] / total_preferences_votes return selected def OnData(self, data): if not self.selection_flag: return self.selection_flag = False # Trade Execution stocks_invested = [x.Key for x in self.Portfolio if x.Value.Invested] for symbol in stocks_invested: if symbol not in self.weight: self.Liquidate(symbol) for symbol, w in self.weight.items(): if symbol in data and data[symbol]: self.SetHoldings(symbol, w) self.weight.clear() def Selection(self): if self.Time.month % 3 == 2: self.selection_flag = True # Custom fee model class CustomFeeModel(FeeModel): def GetOrderFee(self, parameters): fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005 return OrderFee(CashAmount(fee, "USD"))