@Delman Woodrum I've been trying to implement these pieces for the past 30 hours and it seems there is some trouble with multiple stocks. The code you sent only works with one stock while this algo uses multiple stocks based on their sentiment. Right now I'm trying to figure out a way to set a stop on each individual position using similar code but no dice so far. Right now I'm thinking about making each open position something along the lines of:
context.stocks = context.portfolio.positions[get_open_orders()].symbol
The get_open_orders query returns a dictionary that contains a list of orders for each ID, oldest first. So perhaps using this and looping the other code over the returned dictionary might work. Just a concept, this has been pretty difficult thus far. Let me know what you think and if you make progress.
UPDATE:
So I got something sorta working, except it sells all of the stocks that are currently in the portfolio:
2015-01-07 06:31 PRINT AABA | [ 0.27]
2015-01-07 06:31 PRINT JPM | [ 0.73]
2015-01-07 06:31 PRINT FB | [ 0.66]
2015-01-07 06:31 PRINT I sold a bad stock!:AABA
2015-01-07 06:31 PRINT I sold a bad stock!:JPM
2015-01-07 06:31 PRINT I sold a bad stock!:FB
Here is the algorithm with it implemented. It's almost there! We just need to fix this one issue.
> from quantopian.pipeline import Pipeline, CustomFilter
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.factors import Latest
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data.psychsignal import aggregated_twitter_withretweets_stocktwits as st
from sklearn.ensemble import RandomForestClassifier
from quantopian.pipeline.factors import SimpleMovingAverage
from quantopian.pipeline.filters import Q500US
import numpy as np
def initialize(context):
#Long only
set_long_only()
#I use robinhood when long only
set_commission(commission.PerShare(cost=0.0, min_trade_cost=0.0))
#ADDED TO MONITOR LEVERAGE MINUTELY.
context.minLeverage = [0]
context.maxLeverage = [0]
context.securities_in_results = []
attach_pipeline(Custom_pipeline(context), 'Custom_pipeline')
#PREFFERED CLASSIFIER
context.model = RandomForestClassifier()
#YOU WANT A HIGH NUMBER OF ESTIMATORS AND SAMPLES TO ENSURE CONSISTENT BACKTEST PERFROMANCE.
context.model.n_estimators = 500
context.model.min_samples_leaf = 100
context.lookback = 3
context.history_range = 5
#find the stocks we want to buy/sell
schedule_function(evaluate, date_rules.every_day(), time_rules.market_open())
#close positions
schedule_function(sell, date_rules.every_day(), time_rules.market_open())
#open positions
schedule_function(buy, date_rules.every_day(), time_rules.market_open(minutes = 5))
context.stop_price = 0
context.stop_pct = 0.95
def Custom_pipeline(context):
pipe = Pipeline()
sma_10 = SimpleMovingAverage(inputs = [USEquityPricing.close], window_length=10)
sma_50 = SimpleMovingAverage(inputs = [USEquityPricing.close], window_length=50)
pipe.add(st.bull_scored_messages .latest, 'bull_scored_messages')
pipe.add(st.bear_scored_messages .latest, 'bear_scored_messages')
#changed to be easier to read.
pipe.set_screen(Q500US()&\
(sma_10 > sma_50)&\
(0.35*st.bull_scored_messages.latest > st.bear_scored_messages.latest)&\
# it's not just about there being more bullish posts than bearish... 2 is 100% greater than 1 - but 2 isn't exactly a record breaking number of posts.
(st.bear_scored_messages.latest > 10)\
)
return pipe
def before_trading_start(context, data):
context.longs = []
#For hedgeing...
results = pipeline_output('Custom_pipeline')
context.securities_in_results = []
for s in results.index:
context.securities_in_results.append(s)
#DEBUG
def set_trailing_stop(context, data):
for sec in context.portfolio.positions:
price = data.current(sec, 'price')
context.stop_price = max(context.stop_price, context.stop_pct * price)
def evaluate (context, data):
if len(context.securities_in_results) > 0.0:
for sec in context.securities_in_results:
recent_prices, recent_volumes = data.history(sec, 'price', context.history_range, '1d').values, data.history(sec, 'volume', context.history_range, '1d').values
price_changes, volume_changes = np.diff(recent_prices).tolist(), np.diff(recent_volumes).tolist()
X,Y = [],[]
for i in range(context.history_range-context.lookback-1):
X.append(price_changes[i:i+context.lookback] + volume_changes[i:i+context.lookback])
Y.append(price_changes[i+context.lookback])
context.model.fit(X, Y)
recent_prices, recent_volumes = data.history(sec, 'price', context.lookback+1, '1d').values, data.history(sec, 'volume', context.lookback+1, '1d').values
price_changes, volume_changes = np.diff(recent_prices).tolist(), np.diff(recent_volumes).tolist()
prediction = context.model.predict(price_changes + volume_changes)
if prediction > -0.5:
print(str(sec.symbol) + " | " + str(prediction))
context.longs.append(sec)
# #if you arent a fan of puting all of your eggs in one basket:
# if len(context.longs) < 2:
# context.longs = []
# for sec in context.portfolio.positions:
# set_trailing_stop(context, data)
# if data.current(sec, 'price') < context.stop_price:
# order_target(sec, 0)
# context.stop_price = 0
# print("I sold a bad stock!:" + data.current(sec, "symbol"))
# # record(price=data[sec].price, stop=context.stop_price)
def sell (context,data):
for sec in context.securities_in_results:
set_trailing_stop(context, data)
if data.current(sec, 'price') < context.stop_price:
order_target(sec, 0)
context.stop_price = 0
print("I sold a bad stock!:" + str(sec.symbol))
if sec not in context.longs:
order_target_percent(sec, 0.0)
def buy (context,data):
for sec in context.longs:
order_target_percent(sec, 1.0 / (len(context.longs) + len(context.portfolio.positions)) )
def handle_data(context,data):
#if the current leverage is greater than the value in MaxLeverage, clear max leverage then append the current leverage. a similar method is used for minLeverage
#max leverage is set up as an array so that one can more quickly log all leverages find the mean leverage if they want.
for L in context.maxLeverage: #ADDED BY JACOB SHRUM
if context.account.leverage > L: #ADDED BY JACOB SHRUM
context.maxLeverage = [] #ADDED BY JACOB SHRUM
context.maxLeverage.append(context.account.leverage) #ADDED BY JACOB SHRUM
for L in context.minLeverage: #ADDED BY JACOB SHRUM
if context.account.leverage < L: #ADDED BY JACOB SHRUM
context.minLeverage = [] #ADDED BY JACOB SHRUM
context.minLeverage.append(context.account.leverage) #ADDED BY JACOB
record(pos=len(context.portfolio.positions), resutls=len(context.securities_in_results), Min_Leverage = context.minLeverage[0], Max_Leverage = context.maxLeverage[0],Instantaneous_Leverage = context.account.leverage)