Hello,
I have an algo that sorts stocks based on ROIC/PE ratio, and trades shorts/longs for 100 (50 long and 50 short) securities. However this algorithm only picks a small number of securities in the backtest. Can anyone please identify the error in the constraints that causes it to trade a much smaller volume and retain a large amount of cash?
Note: I am new to Quantopian and created this algo by editing a tutorial. I am learning the concepts, and your feedback can help me find the problem.
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.factors import SimpleMovingAverage
from quantopian.pipeline.filters.fundamentals import Q1500US
import quantopian.optimize as opt
from quantopian.pipeline.data import factset
MAX_GROSS_EXPOSURE = 1.0
MAX_POSITION_CONCENTRATION = 0.01
def initialize(context):
my_pipe = make_pipeline()
algo.attach_pipeline(my_pipe, 'my_pipeline')
schedule_function(
my_rebalance,
date_rules.week_start(),
time_rules.market_open()
)
def make_pipeline():
"""
Create our pipeline.
"""
roic_factor = factset.Fundamentals.roic_af.latest
pe = factset.Fundamentals.pe_af.latest
#roic_adj = roic_factor + pe
roic_farmula= roic_factor/pe
# Filter to select securities to go long.
longs = roic_farmula.top(50)
# Filter to select securities to go shirt.
shorts = roic_farmula.bottom(50)
# Filter for all securities that we want to trade.
securities_to_trade = (shorts | longs)
return Pipeline(
columns={
'longs': longs,
'shorts': shorts,
'roic_farmula': roic_farmula
},
screen=(securities_to_trade & QTradableStocksUS()),
)
def my_rebalance(context, data):
target_weights = compute_target_weights(context, data)
max_gross_exposure = opt.MaxGrossExposure(MAX_GROSS_EXPOSURE)
max_position_concentration = opt.PositionConcentration.with_equal_bounds(
-MAX_POSITION_CONCENTRATION,
MAX_POSITION_CONCENTRATION
)
# We want to constraint our portfolio to be dollar neutral (equal amount invested in
# long and short positions).
dollar_neutral = opt.DollarNeutral()
# Stores all of our constraints in a list.
constraints = [
max_gross_exposure,
max_position_concentration,
dollar_neutral,
]
if target_weights:
algo.order_optimal_portfolio(
objective = opt.TargetWeights(target_weights),
constraints = constraints
)
def before_trading_start(context, data):
pipe_results = algo.pipeline_output('my_pipeline')
context.longs = []
for sec in pipe_results[pipe_results['longs']].index.tolist():
if data.can_trade(sec):
context.longs.append(sec)
context.shorts = []
for sec in pipe_results[pipe_results['shorts']].index.tolist():
if data.can_trade(sec):
context.shorts.append(sec)
def compute_target_weights(context, data):
weights = {}
if context.longs and context.shorts:
long_weight = 0.5/len(context.longs)
short_weight = -0.5/len(context.shorts)
else:
return weights
for security in context.portfolio.positions:
if security not in context.longs and security not in context.shorts:
weights[security] = 0
for security in context.longs:
weights[security] = long_weight
for security in context.shorts:
weights[security] = short_weight
return weights