Back to Community
Fixing "The Wisdom of The Crowds"
  • In a previous strategy called the "Wisdom of the Crowds", I used Average Dollar Volume to select a single stock and this strategy seemed to outperform the market
  • However, it was pointed out that the strategy selected mostly AAPL. Then how can one know if the effect is due just to AAPL being AAPL or the strategy itself
  • Upon further investigation, I found out, that the strategy was susceptible to picking stocks who had a massive sell-out since Average Dollar Volume was also large of those stocks
  • The current strategy uses the difference of Average Dollar Volume in two different time periods and selects upto 5 stocks.
Clone Algorithm
45
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.factors import AverageDollarVolume, SimpleMovingAverage
from quantopian.pipeline.factors import CustomFactor
from quantopian.pipeline.data import USEquityPricing
from quantopian.pipeline.filters import QTradableStocksUS, StaticAssets

import numpy as np
import pandas as pd

from quantopian.pipeline import Pipeline

from quantopian.pipeline.filters import Q500US

from quantopian.pipeline.data import Fundamentals
from quantopian.pipeline.data.builtin import USEquityPricing

def initialize(context):
    algo.schedule_function(
        rebalance,
        algo.date_rules.every_day(),
        algo.time_rules.market_open(hours=1),
    )

    algo.schedule_function(
        record_vars,
        algo.date_rules.every_day(),
        algo.time_rules.market_close(),
    )

    algo.attach_pipeline(make_pipeline(), 'pipeline')


def f(data, asset, base_asset, formation_period=270, threshold=0.1):
    def s(inp):
        return pd.Series(inp, index=data.index)
    h = int(formation_period/2)
    prices_asset = (data[asset + ':Return']).rolling(formation_period, min_periods=h).mean()
    prices_base = (data[base_asset + ':Return']).rolling(formation_period, min_periods=h).mean()
    std = prices_asset.rolling(formation_period, min_periods=h).std()
    w = (prices_asset - prices_base)/(0.01 + std)

    w = s(np.where(w > threshold, w, 0.0))
    
    ret = (data[asset + ':Return'])
    
    return w

def make_pipeline():
    q500us = Q500US()
    dollar_volume = AverageDollarVolume(mask=q500us, window_length=270)
   
    my_etfs = StaticAssets([sid(8554)]) # SPY

    screen = (dollar_volume.top(5) & q500us) | my_etfs
    
    kf = (AverageDollarVolume(mask=q500us, window_length=130) - AverageDollarVolume(mask=q500us, window_length=260)) > 0.0      
    kf.mask = screen

    pipe = Pipeline(
        columns = {'kf': kf})
    pipe.set_screen(screen)
    return pipe


def before_trading_start(context, data):
    """
    Called every day before market open.
    """
    context.output = algo.pipeline_output('pipeline')['kf']
    context.security_list = context.output.index

def rebalance(context, data):
    selected_stocks = []
    for stock in context.output.index:  
        v = context.output.at[stock] 
        if v > 0:
            selected_stocks.append(stock)
    for stock in list(context.portfolio.positions.iterkeys()):
        if stock not in selected_stocks:
            print("closing position for " + str(stock))
            order_target_percent(stock, 0)
    
    old_stocks = list(context.portfolio.positions.iterkeys())
    if set(old_stocks) != set(selected_stocks):
        for stock in selected_stocks:
            v = 1.0/len(selected_stocks)
            print("open position for " + str(stock) + " " + str(v))
            order_target_percent(stock, v)

def record_vars(context, data):
    """
    Plot variables at the end of each day.
    """
    record(leverage=context.account.leverage)



def handle_data(context, data):
    """
    Called every minute.
    """
    pass
There was a runtime error.
1 response

Nice strategy. But I wonder why the function f() is not used?