Hackathon 2016 Agenda
10AM – 11AM: Introduction to Quantopian, dataset showcases, and explanation of competition rules.
11AM – 12PM: Hackathon Start. Competitors will be free to ask Quantopian panelist questions.
12:00PM – 12:30PM: Lunch
12:30PM – 5:30PM: Hackathon Afternoon Session. Competitors will be free to ask Quantopian panelists questions.
5:30PM – 5:45PM: Final announcement of 6:00 submission deadline.
6:00PM – 6:30PM: Submission deadline, wrap-up.
Additionally, we reserve the right to disqualify any entry at our sole discretion. For instance, if we believe that an entry is made in bad faith with the intent to "game" the contest, or if we conclude that the algorithm is not following the rules presented in our contest rules and judging criteria.
SUBJECT:
QuantCon Hackathon - [CONTESTANT NAME HERE]
BODY:
Here is my submission for QuantCon Hackathon 2016.
Name: [NAME]
Occupation: [OCCUPATION]
ATTACHED HTML NOTEBOOK AT BOTTOM
You do not have to use these templates but they are here for you to get started with.
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.research import run_pipeline
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
PsychSignal: https://psychsignal.com/
Dataset Versions:
from quantopian.pipeline.data.psychsignal import (
stocktwits_hackathon,
# twitter_withretweets_hackathon,
# aggregated_twitter_withretweets_stocktwits_hackathon
)
Take a look at what the data looks like through here
# PsychSignal
# This is the StockTwits (All Fields) dataset
from quantopian.pipeline.data.psychsignal import stocktwits_hackathon as psychsignal
pipe = Pipeline()
pipe.add(psychsignal.bull_scored_messages.latest, 'bull_messages')
pipe.add(psychsignal.bear_scored_messages.latest, 'bear_messages')
pipe.add(psychsignal.bullish_intensity.latest, "bullish_intensity")
pipe.add(psychsignal.bearish_intensity.latest, "bearish_intensity")
pipe.add(psychsignal.total_scanned_messages.latest, "total_messages")
output = run_pipeline(pipe, start_date='2014-01-04', end_date='2014-01-04')
output = output[output['total_messages'] > 10]
output.iloc[:5]
# Sample Factor
from quantopian.pipeline.data.psychsignal import stocktwits_hackathon as psychsignal
class Factor(CustomFactor):
"""
Baseline PsychSignal Factor
"""
inputs = [psychsignal.bull_minus_bear]
window_length = 1
def compute(self, today, assets, out, bull_minus_bear):
out[:] = bull_minus_bear
pipe = Pipeline()
factor = Factor()
# Screen out penny stocks and low liquidity securities.
dollar_volume = AverageDollarVolume(window_length=20)
is_liquid = dollar_volume.rank(ascending=False) < 1000
# Create the mask that we will use for our percentile methods.
base_universe = (is_liquid)
# Filter down to stocks in the top/bottom 10% by sentiment rank
longs = factor.rank().percentile_between(90, 100, mask=base_universe)
shorts = factor.rank().percentile_between(0, 10, mask=base_universe)
# Add Accern to the Pipeline
pipe.add(factor, "factor")
pipe.add(longs, "longs")
pipe.add(shorts, "shorts")
# Set our pipeline screens
pipe.set_screen((longs | shorts) & (factor != 0))
# Get the output of the pipeline
pipe_output = run_pipeline(pipe, start_date='2015-03-30', end_date='2015-03-30')
pipe.show_graph(format='png')
pipe_output.iloc[0]
Go here: https://www.quantopian.com/posts/factor-tear-sheet
This algorithm makes it very easy for you to plug Factors into. There's even code to combine multiple factors into an equally weighted scale.
import pandas as pd
import numpy as np
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, AverageDollarVolume
from quantopian.pipeline.data.psychsignal import (
stocktwits_hackathon,
# twitter_withretweets_hackathon,
# aggregated_twitter_withretweets_stocktwits_hackathon
)
# Factor belongs here
def make_pipeline():
# Create our pipeline
pipe = Pipeline()
# Screen out penny stocks and low liquidity securities.
dollar_volume = AverageDollarVolume(window_length=20)
is_liquid = dollar_volume.rank(ascending=False) < 1000
# Create the mask that we will use for our percentile methods.
base_universe = (is_liquid)
# Filter down to stocks in the top/bottom 10% by sentiment rank
factor = Factor()
longs = factor.rank().percentile_between(90, 100, mask=base_universe)
shorts = factor.rank().percentile_between(0, 10, mask=base_universe)
# Multiple Factors
# factor = Factor()
# factor_2 = Factor_2()
# combined_factor = (
# factor.rank(mask=base_universe) +
# factor_2.rank(mask=base_universe)
# )
# longs = combined_factor.rank().percentile_between(90, 100)
# shorts = combined_factor.rank().percentile_between(0, 10)
# Add Accern to the Pipeline
pipe.add(longs, "longs")
pipe.add(shorts, "shorts")
# Set our pipeline screens
pipe.set_screen((longs | shorts) & factor.notnan())
return pipe
# Put any initialization logic here. The context object will be passed to
# the other methods in your algorithm.
def initialize(context):
attach_pipeline(make_pipeline(), name='factors')
context.shorts = None
context.longs = None
# Create our scheduled functions
# This is a monthly rebalance, please change according to your
# frequency
schedule_function(rebalance, date_rules.month_start())
schedule_function(record_positions, date_rules.every_day(),
time_rules.market_close())
def before_trading_start(context, data):
# Assign long and short baskets
results = pipeline_output('factors')
if len(results.index) == 0:
log.info("Not Enough Data Yet!")
return
assets_in_universe = results.index
context.longs = assets_in_universe[results.longs]
context.shorts = assets_in_universe[results.shorts]
def record_positions(context, data):
# Record our leverage, exposure, positions, and number of open
# orders
record(lever=context.account.leverage,
exposure=context.account.net_leverage,
num_pos=len(context.portfolio.positions))
def rebalance(context, data):
if context.shorts is None or context.longs is None:
return
short_weight = -1.0/len(context.shorts)
long_weight = 1.0/len(context.longs)
assets_in_universe = (context.longs | context.shorts)
# Order our shorts
for security in context.shorts:
if data.can_trade(security):
order_target_percent(security, short_weight)
# Order our longs
for security in context.longs:
if data.can_trade(security):
order_target_percent(security, long_weight)
# Order securities not in the portfolio
for security in context.portfolio.positions:
if data.can_trade(security):
if security not in assets_in_universe:
order_target_percent(security, 0)
bt = get_backtest('573785ad82cd270f926abb5e')
bt.create_full_tear_sheet()
# Send to SLEE@QUANTOPIAN.COM