In [1]:
%pylab inline
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import numpy.random as rng
import pandas.io.data as web
import numpy as np
import pandas as pd
In [2]:
def get_prices(symbol):
start, end = '2007-05-02', '2016-04-11'
data = web.DataReader(symbol, 'yahoo', start, end)
data=pd.DataFrame(data)
prices=data['Adj Close']
prices=prices.astype(float)
return prices
def get_returns(prices):
return ((prices-prices.shift(-1))/prices)[:-1]
def get_data(list):
l = []
for symbol in list:
rets = get_returns(get_prices(symbol))
l.append(rets)
return np.array(l).T
def sort_data(rets):
ins = []
outs = []
for i in range(len(rets)-100):
ins.append(rets[i:i+100].tolist())
outs.append(rets[i+100])
return np.array(ins), np.array(outs)
symbol_list = ['C', 'GS']
rets = get_data(symbol_list)
ins, outs = sort_data(rets)
ins = ins.transpose([0,2,1]).reshape([-1, len(symbol_list) * 100])
div = int(.8 * ins.shape[0])
train_ins, train_outs = ins[:div], outs[:div]
test_ins, test_outs = ins[div:], outs[div:]
#normalize inputs
train_ins, test_ins = train_ins/np.std(ins), test_ins/np.std(ins)
In [49]:
class Model():
def __init__(self, config, training=True):
#CONFIG
symbol_list = self.symbol_list = config.symbol_list
num_samples = self.num_samples = config.num_samples
input_len = self.input_len = config.input_len
n_hidden_1 = self.n_hidden_1 = config.n_hidden_1
n_hidden_2 = self.n_hidden_2 = config.n_hidden_2
learning_rate = self.learning_rate = config.learning_rate
#bucket info
positions = self.positions = tf.constant([-1,0,1])
num_positions = self.num_positions = 3
#more vars
num_symbols = self.num_symbols = len(symbol_list)
n_input = self.n_input = num_symbols * input_len
n_classes = self.n_classes = num_positions * num_symbols
x =self.x = tf.placeholder(tf.float32, [None, n_input])
y_ =self.y_= tf.placeholder(tf.float32, [None, num_symbols])
weights = {
'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}
biases = {
'b1': tf.Variable(tf.random_normal([n_hidden_1])),
'b2': tf.Variable(tf.random_normal([n_hidden_2])),
'out': tf.Variable(tf.random_normal([n_classes]))
}
def multilayer_perceptron(x, weights, biases, keep_prob):
# Hidden layer with RELU activation
layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
layer_1 = tf.nn.relu(layer_1)
# Hidden layer with RELU activation
layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
layer_2 = tf.nn.relu(layer_2)
# Output layer with linear activation
out_layer_f = tf.matmul(layer_2, weights['out']) + biases['out']
out_layer = tf.nn.dropout(out_layer_f, keep_prob) # DROPOUT LAYER
return out_layer
if training == True: keep_prob = 0.5 # DROPOUT
else: keep_prob = 1.0 # NO DROPOUT
# Construct model
y = multilayer_perceptron(x, weights, biases, keep_prob)
# loop through symbol, taking the columns for each symbol's bucket together
pos = {}
sample_n = {}
sample_mask = {}
symbol_returns = {}
relevant_target_column = {}
for i in range(num_symbols):
# isolate the buckets relevant to the symbol and get a softmax as well
symbol_probs = y[:,i*num_positions:(i+1)*num_positions]
symbol_probs_softmax = tf.nn.softmax(symbol_probs) # softmax[i, j] = exp(logits[i, j]) / sum(exp(logits[i]))
# sample probability to chose our policy's action
sample = tf.multinomial(tf.log(symbol_probs_softmax), num_samples)
for sample_iter in range(num_samples):
sample_n[i*num_samples + sample_iter] = sample[:,sample_iter]
pos[i*num_samples + sample_iter] = tf.reshape(sample_n[i*num_samples + sample_iter], [-1]) - 1
symbol_returns[i*num_samples + sample_iter] = tf.mul(
tf.cast(pos[i*num_samples + sample_iter], float32),
y_[:,i])
sample_mask[i*num_samples + sample_iter] = tf.cast(tf.reshape(tf.one_hot(sample_n[i*num_samples + sample_iter], 3), [-1,3]), float32)
relevant_target_column[i*num_samples + sample_iter] = tf.reduce_sum(
symbol_probs_softmax * sample_mask[i*num_samples + sample_iter],1)
self.pos = pos
# PERFORMANCE METRICS
daily_returns_by_symbol_ = tf.concat(1, [tf.reshape(t, [-1,1]) for t in symbol_returns.values()])
daily_returns_by_symbol = tf.transpose(tf.reshape(daily_returns_by_symbol_, [-1,2,num_samples]), [0,2,1]) #[?,5,2]
self.daily_returns = daily_returns = tf.reduce_mean(daily_returns_by_symbol, 2) # [?,5]
total_return = tf.reduce_prod(daily_returns+1, 0)
z = tf.ones_like(total_return) * -1
self.total_return =total_return= tf.add(total_return, z)
self.ann_vol = ann_vol = tf.mul(
tf.sqrt(tf.reduce_mean(tf.pow((daily_returns - tf.reduce_mean(daily_returns, 0)),2),0)) ,
np.sqrt(252)
)
self.sharpe = sharpe = tf.div(total_return, ann_vol)
#Maybe metric slicing later
#segment_ids = tf.ones_like(daily_returns[:,0])
#partial_prod = tf.segment_prod(daily_returns+1, segment_ids)
training_target_cols = tf.concat(1, [tf.reshape(t, [-1,1]) for t in relevant_target_column.values()])
ones = tf.ones_like(training_target_cols)
gradient_ = tf.nn.sigmoid_cross_entropy_with_logits(training_target_cols, ones)
gradient = tf.transpose(tf.reshape(gradient_, [-1,2,num_samples]), [0,2,1]) #[?,5,2]
#L2 = tf.contrib.layers.l2_regularizer(0.1)
#t_vars = tf.trainable_variables()
#reg = tf.contrib.layers.apply_regularization(L2, tf.GraphKeys.WEIGHTS)
#cost = tf.mul(gradient , daily_returns_by_symbol_reshaped)
#cost = tf.mul(gradient , tf.expand_dims(daily_returns, -1)) #+ reg
#cost = tf.mul(gradient , tf.expand_dims(total_return, -1))
cost = tf.mul(gradient , tf.expand_dims(sharpe, -1))
self.optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
self.costfn = tf.reduce_mean(cost)
In [52]:
class SmallConfig(object):
"""Small config."""
symbol_list = ['C', 'GS']
num_samples = 20
input_len = 100
n_hidden_1 = 50
n_hidden_2 = 50
learning_rate = 0.00005
In [ ]:
sess = tf.Session()
# initialize variables to random values
with tf.variable_scope("model", reuse=None):
m = Model(config = SmallConfig)
with tf.variable_scope("model", reuse=True):
mvalid = Model(config = SmallConfig, training=False)
sess.run(tf.initialize_all_variables())
#init = tf.initialize_all_variables()
#sess.run(init)
# run optimizer on entire training data set many times
train_size = train_ins.shape[0]
for epoch in range(20000):
start = rng.randint(train_size-50)
batch_size = rng.randint(2,75)
end = min(train_size, start+batch_size)
sess.run(m.optimizer, feed_dict={m.x: train_ins[start:end], m.y_: train_outs[start:end]})#.reshape(1,-1).T})
# every 1000 iterations record progress
if (epoch+1)%1000== 0:
t,s, c = sess.run([ mvalid.total_return, mvalid.ann_vol, mvalid.costfn], feed_dict={mvalid.x: train_ins, mvalid.y_: train_outs})#.reshape(1,-1).T})
t = np.mean(t)
t = (1+t)**(1/6) -1
s = np.mean(s)
s = t/s
print("Epoch:", '%04d' % (epoch+1), "cost=",c, "total return=", "{:.9f}".format(t),
"sharpe=", "{:.9f}".format(s))
#print(t)
In [43]:
# in sample results
#init = tf.initialize_all_variables()
#sess.run(init)
d, t = sess.run([mvalid.daily_returns, mvalid.pos[0]], feed_dict={mvalid.x: train_ins, mvalid.y_: train_outs})
In [44]:
# equity curve
for i in range(mvalid.num_samples):
plot(np.cumprod(d[:,[i]]+1))
In [45]:
plot(t)
Out[45]:
In [46]:
#out of sample results
d, t = sess.run([mvalid.daily_returns, mvalid.pos[0]], feed_dict={mvalid.x: test_ins, mvalid.y_: test_outs})
In [47]:
#out of sample results
for i in range(5):
plot(np.cumprod(d[:,[i]]+1))
In [48]:
plot(t)
Out[48]:
In [ ]:
In [ ]:
In [ ]:
In [ ]: