# Adapted from:
# Li, Bin, and Steven HOI. "On-Line Portfolio Selection with Moving Average Reversion." The 29th International Conference on Machine Learning (ICML2012), 2012.
# http://icml.cc/2012/papers/168.pdf
import numpy as np
from scipy import optimize
import pandas as pd
def initialize(context):
context.stocks = [ sid(8045),
sid(20680),
sid(3806),
sid(3450),
sid(368),
sid(5061),
sid(6546),
sid(3951),
sid(23709),
sid(24124),
sid(39840),
sid(5121),
sid(1406),
sid(42950),
sid(3212),
sid(14848),
sid(8132),
sid(21774),
sid(19917),
sid(24),
sid(17107),
sid(10477),
sid(23821),
sid(38650),
sid(41766),
sid(32268)] # SH Proshares Short S&P 500
context.m = len(context.stocks)
context.eps = 1.0
context.b_0 = np.ones(context.m) / context.m
context.b_t = context.b_0
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(15,'1d','price').as_matrix(context.stocks)[0:-1,:]
for stock in context.stocks:
if bool(get_open_orders(stock)):
return
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)
if denom == 0.0:
context.b_t = context.b_0
else:
context.b_t = np.divide(context.b_t,denom)
x_tilde = np.zeros(context.m)
for i, stock in enumerate(context.stocks):
mean_price = np.mean(prices[:,i])
x_tilde[i] = mean_price/prices[-1,i]
bnds = ((0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1))
cons = ({'type': 'eq', 'fun': lambda x: np.sum(x)-1.0},
{'type': 'ineq', 'fun': lambda x: np.dot(x,x_tilde) - context.eps})
res= optimize.minimize(norm_squared, context.b_0, args=context.b_t,jac=norm_squared_deriv,method='SLSQP',constraints=cons,bounds=bnds)
allocation = res.x
allocation[allocation<0] = 0
allocation = allocation/np.sum(allocation)
if np.dot(allocation,x_tilde)-context.eps > 0:
rebalance_portfolio(context,allocation)
else:
return
def rebalance_portfolio(context, desired_port):
for i, stock in enumerate(context.stocks):
order_target_percent(stock, desired_port[i])
def norm_squared(b,*args):
b_t = np.asarray(args)
delta_b = b - b_t
return 0.5*np.dot(delta_b,delta_b)
def norm_squared_deriv(b,*args):
b_t = np.asarray(args)
delta_b = b - b_t
return delta_b