import numpy as np
import pandas as pd
def initialize(context):
context.stocks = [ sid(7792),
sid(3951),
sid(3496),
sid(5328),
sid(2190),
sid(3149),
sid(4922),
sid(7041),
sid(2119),
sid(24),
sid(5061),
sid(26578),
sid(6295),
sid(3212),
sid(368),
sid(1900),
sid(16841),
sid(1637) ]
context.m = len(context.stocks)
context.eps = 1.0028 # change epsilon here
context.b_t = np.ones(context.m) / context.m
schedule_function(trade, date_rules.every_day(), time_rules.market_open(minutes=60))
def handle_data(context,data):
pass
def trade(context,data):
prices = history(20*390,'1m','price')
prices = pd.ewma(prices, span = 390).as_matrix(context.stocks)
# skip bar if any orders are open
for stock in context.stocks:
if bool(get_open_orders(stock)):
return
sum_weighted_port = np.zeros(context.m)
sum_weights = 0
for n in range(0,len(prices[:,0])+1):
(weight,weighted_port) = get_weighted_port(data,context,prices,n)
sum_weighted_port += weighted_port
sum_weights += weight
allocation_optimum = sum_weighted_port/sum_weights
rebalance_portfolio(context, allocation_optimum)
def get_weighted_port(data,context,prices,n):
# update portfolio
for i, stock in enumerate(context.stocks):
context.b_t[i] = context.portfolio.positions[stock].amount*data[stock].price
denom = np.sum(context.b_t)
# test for divide-by-zero case
if denom == 0.0:
context.b_t = np.ones(context.m) / context.m
else:
context.b_t = np.divide(context.b_t,denom)
x_tilde = np.zeros(context.m)
b = np.zeros(context.m)
# find relative moving volume weighted average price for each secuirty
for i, stock in enumerate(context.stocks):
mean_price = np.mean(prices[-n:,i])
x_tilde[i] = mean_price/prices[-1,i]
###########################
# Inside of OLMAR (algo 2)
x_bar = x_tilde.mean()
# Calculate terms for lambda (lam)
dot_prod = np.dot(context.b_t, x_tilde)
num = context.eps - dot_prod
denom = (np.linalg.norm((x_tilde-x_bar)))**2
# test for divide-by-zero case
if denom == 0.0:
lam = 0 # no portolio update
else:
lam = max(0, num/denom)
b = context.b_t + lam*(x_tilde-x_bar)
b_norm = simplex_projection(b)
weight = np.dot(b_norm,x_tilde)
return (weight,weight*b_norm)
def rebalance_portfolio(context, desired_port):
for i, stock in enumerate(context.stocks):
order_target_percent(stock, desired_port[i])
def simplex_projection(v, b=1):
"""Projection vectors to the simplex domain
Implemented according to the paper: Efficient projections onto the
l1-ball for learning in high dimensions, John Duchi, et al. ICML 2008.
Implementation Time: 2011 June 17 by [email protected] AT pmail.ntu.edu.sg
Optimization Problem: min_{w}\| w - v \|_{2}^{2}
s.t. sum_{i=1}^{m}=z, w_{i}\geq 0
Input: A vector v \in R^{m}, and a scalar z > 0 (default=1)
Output: Projection vector w
:Example:
>>> proj = simplex_projection([.4 ,.3, -.4, .5])
>>> print proj
array([ 0.33333333, 0.23333333, 0. , 0.43333333])
>>> print proj.sum()
1.0
Original matlab implementation: John Duchi ([email protected])
Python-port: Copyright 2012 by Thomas Wiecki ([email protected]).
"""
v = np.asarray(v)
p = len(v)
# Sort v into u in descending order
v = (v > 0) * v
u = np.sort(v)[::-1]
sv = np.cumsum(u)
rho = np.where(u > (sv - b) / np.arange(1, p+1))[0][-1]
theta = np.max([0, (sv[rho] - b) / (rho+1)])
w = (v - theta)
w[w<0] = 0
return w

We have migrated this algorithm to work with a new version of the Quantopian API. The code is different than the original version, but the investment rationale of the algorithm has not changed. We've put everything you need to know

here on one page.