Completed
Push — master ( 18db19...5c3ca1 )
by
unknown
01:20
created

zipline.examples.handle_data()   B

Complexity

Conditions 5

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 5
dl 0
loc 47
rs 8.1672
1
import sys
2
import logbook
3
import numpy as np
4
from datetime import datetime
5
import pytz
6
7
from zipline.algorithm import TradingAlgorithm
8
from zipline.utils.factory import load_from_yahoo
9
from zipline.finance import commission
10
11
zipline_logging = logbook.NestedSetup([
12
    logbook.NullHandler(level=logbook.DEBUG, bubble=True),
13
    logbook.StreamHandler(sys.stdout, level=logbook.INFO),
14
    logbook.StreamHandler(sys.stderr, level=logbook.ERROR),
15
])
16
zipline_logging.push_application()
17
18
STOCKS = ['AMD', 'CERN', 'COST', 'DELL', 'GPS', 'INTC', 'MMM']
19
20
21
# On-Line Portfolio Moving Average Reversion
22
23
# More info can be found in the corresponding paper:
24
# http://icml.cc/2012/papers/168.pdf
25
def initialize(algo, eps=1, window_length=5):
26
    algo.stocks = STOCKS
27
    algo.sids = [algo.symbol(symbol) for symbol in algo.stocks]
28
    algo.m = len(algo.stocks)
29
    algo.price = {}
30
    algo.b_t = np.ones(algo.m) / algo.m
31
    algo.last_desired_port = np.ones(algo.m) / algo.m
32
    algo.eps = eps
33
    algo.init = True
34
    algo.days = 0
35
    algo.window_length = window_length
36
    algo.add_transform('mavg', 5)
37
38
    algo.set_commission(commission.PerShare(cost=0))
39
40
41
def handle_data(algo, data):
42
    algo.days += 1
43
    if algo.days < algo.window_length:
44
        return
45
46
    if algo.init:
47
        rebalance_portfolio(algo, data, algo.b_t)
48
        algo.init = False
49
        return
50
51
    m = algo.m
52
53
    x_tilde = np.zeros(m)
54
    b = np.zeros(m)
55
56
    # find relative moving average price for each asset
57
    for i, sid in enumerate(algo.sids):
58
        price = data[sid].price
59
        # Relative mean deviation
60
        x_tilde[i] = data[sid].mavg(algo.window_length) / price
61
62
    ###########################
63
    # Inside of OLMAR (algo 2)
64
    x_bar = x_tilde.mean()
65
66
    # market relative deviation
67
    mark_rel_dev = x_tilde - x_bar
68
69
    # Expected return with current portfolio
70
    exp_return = np.dot(algo.b_t, x_tilde)
71
    weight = algo.eps - exp_return
72
    variability = (np.linalg.norm(mark_rel_dev)) ** 2
73
74
    # test for divide-by-zero case
75
    if variability == 0.0:
76
        step_size = 0
77
    else:
78
        step_size = max(0, weight / variability)
79
80
    b = algo.b_t + step_size * mark_rel_dev
81
    b_norm = simplex_projection(b)
82
    np.testing.assert_almost_equal(b_norm.sum(), 1)
83
84
    rebalance_portfolio(algo, data, b_norm)
85
86
    # update portfolio
87
    algo.b_t = b_norm
88
89
90
def rebalance_portfolio(algo, data, desired_port):
91
    # rebalance portfolio
92
    desired_amount = np.zeros_like(desired_port)
93
    current_amount = np.zeros_like(desired_port)
94
    prices = np.zeros_like(desired_port)
95
96
    if algo.init:
97
        positions_value = algo.portfolio.starting_cash
98
    else:
99
        positions_value = algo.portfolio.positions_value + \
100
            algo.portfolio.cash
101
102
    for i, sid in enumerate(algo.sids):
103
        current_amount[i] = algo.portfolio.positions[sid].amount
104
        prices[i] = data[sid].price
105
106
    desired_amount = np.round(desired_port * positions_value / prices)
107
108
    algo.last_desired_port = desired_port
109
    diff_amount = desired_amount - current_amount
110
111
    for i, sid in enumerate(algo.sids):
112
        algo.order(sid, diff_amount[i])
113
114
115
def simplex_projection(v, b=1):
116
    """Projection vectors to the simplex domain
117
118
    Implemented according to the paper: Efficient projections onto the
119
    l1-ball for learning in high dimensions, John Duchi, et al. ICML 2008.
120
    Implementation Time: 2011 June 17 by Bin@libin AT pmail.ntu.edu.sg
121
    Optimization Problem: min_{w}\| w - v \|_{2}^{2}
122
    s.t. sum_{i=1}^{m}=z, w_{i}\geq 0
123
124
    Input: A vector v \in R^{m}, and a scalar z > 0 (default=1)
125
    Output: Projection vector w
126
127
    :Example:
128
    >>> proj = simplex_projection([.4 ,.3, -.4, .5])
129
    >>> print(proj)
130
    array([ 0.33333333, 0.23333333, 0. , 0.43333333])
131
    >>> print(proj.sum())
132
    1.0
133
134
    Original matlab implementation: John Duchi ([email protected])
135
    Python-port: Copyright 2013 by Thomas Wiecki ([email protected]).
136
    """
137
138
    v = np.asarray(v)
139
    p = len(v)
140
141
    # Sort v into u in descending order
142
    v = (v > 0) * v
143
    u = np.sort(v)[::-1]
144
    sv = np.cumsum(u)
145
146
    rho = np.where(u > (sv - b) / np.arange(1, p + 1))[0][-1]
147
    theta = np.max([0, (sv[rho] - b) / (rho + 1)])
148
    w = (v - theta)
149
    w[w < 0] = 0
150
    return w
151
152
153
# Note: this function can be removed if running
154
# this algorithm on quantopian.com
155
def analyze(context=None, results=None):
156
    import matplotlib.pyplot as plt
157
    fig = plt.figure()
158
    ax = fig.add_subplot(111)
159
    results.portfolio_value.plot(ax=ax)
160
    ax.set_ylabel('Portfolio value (USD)')
161
    plt.show()
162
163
164
# Note: this if-block should be removed if running
165
# this algorithm on quantopian.com
166
if __name__ == '__main__':
167
    # Set the simulation start and end dates.
168
    start = datetime(2004, 1, 1, 0, 0, 0, 0, pytz.utc)
169
    end = datetime(2008, 1, 1, 0, 0, 0, 0, pytz.utc)
170
171
    # Load price data from yahoo.
172
    data = load_from_yahoo(stocks=STOCKS, indexes={}, start=start, end=end)
173
    data = data.dropna()
174
175
    # Create and run the algorithm.
176
    olmar = TradingAlgorithm(handle_data=handle_data,
177
                             initialize=initialize,
178
                             identifiers=STOCKS)
179
    results = olmar.run(data)
180
181
    # Plot the portfolio data.
182
    analyze(results=results)
183