Hello,
here is an algorithm with and without using optimise api. The algorithm is not doing well, but it demonstrates that optimise api can misfire. Pl tell me what is the problem with the usage of the API (assuming API is not the problem).
thanks
-kamal
import math
import numpy as np
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.factors import SimpleMovingAverage
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
class FCFRatio(CustomFactor):
# Pre-declare inputs and window_length
inputs = [morningstar.valuation_ratios.cf_yield]
window_length = 1
# Compute market cap value
def compute(self, today, assets, out, cf_yield):
out[:] = cf_yield[-1]
class PERatio(CustomFactor):
# Pre-declare inputs and window_length
inputs = [morningstar.valuation_ratios.pe_ratio]
window_length = 1
# Compute market cap value
def compute(self, today, assets, out, pe_ratio):
out[:] = pe_ratio[-1]
class MarketCap(CustomFactor):
# Pre-declare inputs and window_length
inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding]
window_length = 1
# Compute market cap value
def compute(self, today, assets, out, close, shares):
out[:] = close[-1] * shares[-1]
Put any initialization logic here. The context object will be passed to
the other methods in your algorithm.
def initialize(context):
context.longs = 0
context.shorts = 0
# create a pipleine
pipe = Pipeline()
attach_pipeline(pipe, 'pe_ratio')
mkt_cap = MarketCap()
# create market cap filter
top_2000 = mkt_cap.top(2000)
pe_ratio = PERatio()
fcf_ratio = FCFRatio()
# add factors
pipe.add(mkt_cap, 'mkt_cap')
pipe.add(pe_ratio, "pe_ratio")
pipe.add(fcf_ratio, "fcf_ratio")
pipe.set_screen(top_2000)
# Scedule my rebalance function
schedule_function(func=rebalance,
date_rule=date_rules.every_day(),
time_rule=time_rules.market_close(minutes=60))
schedule_function(func=rebalance,
# date_rule=date_rules.month_start(days_offset=15),
# time_rule=time_rules.market_open(hours=5,minutes= 30),
half_days=True)
def before_trading_start(context, data):
context.output = pipeline_output('pe_ratio')
my_list = context.output
context.short_list = my_list.sort(["fcf_ratio"], ascending=True).iloc[:5]
context.long_list = my_list.sort(["mkt_cap"], ascending=False).iloc[:10]
Will be called on every trade event for the securities you specify.
def handle_data(context, data):
record(leverage=context.account.leverage)
record(longs=context.longs)
record(shorts=context.shorts)
log.info("\n" + str(context.long_list.sort(['pe_ratio'], ascending=True)))
This rebalancing is called according to our schedule_function settings.
def rebalance(context,data):
context.longs = 0
context.shorts = 0
for long_stock in context.long_list.index:
if data.can_trade(long_stock):
order_target_percent(long_stock, 0.06)
context.longs = context.longs + 1
# beta pf -1 and return of ~6 and sharpe of -0.1
for short_stock in context.short_list.index:
if data.can_trade(short_stock):
order_target_percent(short_stock, -0.08)
context.shorts = context.shorts + 1
'''
for stock in context.portfolio.positions.iterkeys():
if stock not in context.long_list.index and stock not in context.short_list.index:
order_target(stock, 0)
'''
for stock in context.portfolio.positions.iterkeys():
if stock not in context.long_list.index and stock not in context.short_list:
order_target(stock, 0)
using optimise api:-
-----# Changed sell universe to context.portfolio.positions from context.my_securities
Barred leveraged ETF trading
Trading 30 minutes after market open to avoid morning volatility
60/40 Long/Short split
Using Optimize API to order optimal portfolio
"""
Import necessary libraries and factors
"""
import numpy as np
from scipy import stats
from quantopian.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters import Q1500US
import quantopian.optimize as opt
import quantopian.algorithm as algo
Constraint parameters
MAX_GROSS_LEVERAGE = 1.0 # Only use capital from our portfolio
MAX_SHORT_POSITION_SIZE = 0.1 # 15%
MAX_LONG_POSITION_SIZE = 0.1 # 15%
class MarketCap(CustomFactor):
# Pre-declare inputs and window_length
inputs = [USEquityPricing.close, morningstar.valuation.shares_outstanding]
window_length = 1
# Compute market cap value
def compute(self, today, assets, out, close, shares):
out[:] = close[-1] * shares[-1]
class FCFRatio(CustomFactor):
# Pre-declare inputs and window_length
inputs = [morningstar.valuation_ratios.cf_yield]
window_length = 1
# Compute market cap value
def compute(self, today, assets, out, cf_yield):
out[:] = cf_yield[-1]
class PERatio(CustomFactor):
# Pre-declare inputs and window_length
inputs = [morningstar.valuation_ratios.pe_ratio]
window_length = 1
# Compute market cap value
def compute(self, today, assets, out, pe_ratio):
out[:] = pe_ratio[-1]
def initialize(context):
"""
Initialize function schedules, benchmarks, commissions and slippage
"""
# Set benchmark security as S&P 500 (SPY)
set_benchmark(sid(8554))
# Exclude leveraged ETFs
set_asset_restrictions(security_lists.restrict_leveraged_etfs)
# Set commissions per share according to Interactive Brokers
set_commission(commission.PerShare(cost = 0.005, min_trade_cost = 1.0))
# Set default slippage
set_slippage(slippage.VolumeShareSlippage(volume_limit = 0.025, price_impact = 0.10))
# Schedule function to place orders once a day at market open
schedule_function(rebalance,
date_rules.every_day(),
time_rules.market_open(minutes = 30))
make_pipeline(context)
def make_pipeline(context):
"""
Create list of securities to be considered for trading
"""
# top 500 by marketcap
top_500 = morningstar.valuation.market_cap.latest.top(500)
universe = Q1500US()
mkt_cap = MarketCap()
pe_ratio = PERatio()
fcf_ratio = FCFRatio()
pipe = Pipeline()
attach_pipeline(pipe, 'pe_ratio')
# add factors
pipe.add(mkt_cap, 'mkt_cap')
pipe.add(pe_ratio, "pe_ratio")
pipe.add(fcf_ratio, "fcf_ratio")
top_2000 = mkt_cap.top(2000)
pipe.set_screen(top_2000)
return pipe
def before_trading_start(context, data):
"""
Assign list to variable and attach pipeline
"""
context.output = pipeline_output('pe_ratio')
my_list = context.output
context.short_list = my_list.sort(["fcf_ratio"], ascending=True).iloc[:5]
context.long_list = my_list.sort(["mkt_cap"], ascending=False).iloc[:5]
# Pipeline_output returns the constructed dataframe
output = pipeline_output('tradable_securities')
# Assign variable to output
context.my_securities = output.index
def calculate_zscore(stock, data):
"""
Calculate z-score for all stocks in list
"""
# Initialize dictionary
zscore = {}
# Get pricing data for the last month
stock_price = data.history(stock, 'price', 30, '1d')
# Calculate the returns from past prices
stock_returns = stock_price.pct_change()[1:]
# Calculate z-score of the current returns
zscore[stock] = (np.mean(stock_returns[-5]) - np.mean(stock_returns)) / np.std(stock_returns, ddof = 2)
return zscore
def compute_weights(context, data):
"""
Calculate the ideal weights for the portfolio
"""
weights = {}
for long_stock in context.long_list.index:
weights[long_stock] = 0.1
for short_stock in context.short_list.index:
weights[short_stock] = -0.08
return weights
def rebalance(context, data):
"""
Rebalance portfolio using the Optimize API
"""
"""
# Call required funcitons
weights = compute_weights(context, data)
# Optimize API variables
optimize_weights = opt.TargetPortfolioWeights(weights)
optimize_alpha = opt.MaximizeAlpha(context.zscore)
leverage_constraint = opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE)
market_neutral = opt.DollarNeutral()
algo.order_optimal_portfolio(
objective = [
optimize_weights,
optimize_alpha
],
constraints = [
leverage_constraint,
market_neutral,
],
)
"""
# Call required funcitons
weights = compute_weights(context, data)
# Optimize API variables
objective = opt.TargetWeights(weights)
leverage_constraint = opt.MaxGrossLeverage(MAX_GROSS_LEVERAGE)
position_size = opt.PositionConcentration.with_equal_bounds(
-MAX_SHORT_POSITION_SIZE,
MAX_LONG_POSITION_SIZE,
)
market_neutral = opt.DollarNeutral()
algo.order_optimal_portfolio(
objective = objective,
constraints = [
leverage_constraint,
position_size,
market_neutral
],
)
def plot(context, data):
"""
Plot leverage, longs, and shorts throughout the course of the backtest
"""
longs = 0
for position in context.portfolio.positions.itervalues():
if position.amount > 0:
longs += 1
shorts = 0
for position in context.portfolio.positions.itervalues():
if position.amount < 0:
shorts += 1;
record(leverage = context.account.leverage, shorts = shorts, longs = longs)