| 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"))