Completed
Pull Request — master (#858)
by Eddie
10:07 queued 01:13
created

zipline.SIDData   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 222
Duplicated Lines 0 %
Metric Value
dl 0
loc 222
rs 9.4
wmc 33
1
#
2
# Copyright 2013 Quantopian, Inc.
3
#
4
# Licensed under the Apache License, Version 2.0 (the "License");
5
# you may not use this file except in compliance with the License.
6
# You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
from copy import copy
16
17
import pandas as pd
18
19
from .utils.enum import enum
20
21
from zipline._protocol import BarData as _BarData
22
BarData = _BarData
23
from zipline.utils.serialization_utils import (
24
    VERSION_LABEL
25
)
26
27
# Datasource type should completely determine the other fields of a
28
# message with its type.
29
DATASOURCE_TYPE = enum(
30
    'AS_TRADED_EQUITY',
31
    'MERGER',
32
    'SPLIT',
33
    'DIVIDEND',
34
    'TRADE',
35
    'TRANSACTION',
36
    'ORDER',
37
    'EMPTY',
38
    'DONE',
39
    'CUSTOM',
40
    'BENCHMARK',
41
    'COMMISSION',
42
    'CLOSE_POSITION'
43
)
44
45
# Expected fields/index values for a dividend Series.
46
DIVIDEND_FIELDS = [
47
    'declared_date',
48
    'ex_date',
49
    'gross_amount',
50
    'net_amount',
51
    'pay_date',
52
    'payment_sid',
53
    'ratio',
54
    'sid',
55
]
56
# Expected fields/index values for a dividend payment Series.
57
DIVIDEND_PAYMENT_FIELDS = [
58
    'id',
59
    'payment_sid',
60
    'cash_amount',
61
    'share_count',
62
]
63
64
65
class Event(object):
66
67
    def __init__(self, initial_values=None):
68
        if initial_values:
69
            self.__dict__ = initial_values
70
71
    def __getitem__(self, name):
72
        return getattr(self, name)
73
74
    def __setitem__(self, name, value):
75
        setattr(self, name, value)
76
77
    def __delitem__(self, name):
78
        delattr(self, name)
79
80
    def keys(self):
81
        return self.__dict__.keys()
82
83
    def __eq__(self, other):
84
        return hasattr(other, '__dict__') and self.__dict__ == other.__dict__
85
86
    def __contains__(self, name):
87
        return name in self.__dict__
88
89
    def __repr__(self):
90
        return "Event({0})".format(self.__dict__)
91
92
    def to_series(self, index=None):
93
        return pd.Series(self.__dict__, index=index)
94
95
96
class Order(Event):
97
    pass
98
99
100
class Portfolio(object):
101
102
    def __init__(self):
103
        self.capital_used = 0.0
104
        self.starting_cash = 0.0
105
        self.portfolio_value = 0.0
106
        self.pnl = 0.0
107
        self.returns = 0.0
108
        self.cash = 0.0
109
        self.positions = Positions()
110
        self.start_date = None
111
        self.positions_value = 0.0
112
113
    def __getitem__(self, key):
114
        return self.__dict__[key]
115
116
    def __repr__(self):
117
        return "Portfolio({0})".format(self.__dict__)
118
119
    def __getstate__(self):
120
121
        state_dict = copy(self.__dict__)
122
123
        # Have to convert to primitive dict
124
        state_dict['positions'] = dict(self.positions)
125
126
        STATE_VERSION = 1
127
        state_dict[VERSION_LABEL] = STATE_VERSION
128
129
        return state_dict
130
131
    def __setstate__(self, state):
132
133
        OLDEST_SUPPORTED_STATE = 1
134
        version = state.pop(VERSION_LABEL)
135
136
        if version < OLDEST_SUPPORTED_STATE:
137
            raise BaseException("Portfolio saved state is too old.")
138
139
        self.positions = Positions()
140
        self.positions.update(state.pop('positions'))
141
142
        self.__dict__.update(state)
143
144
145
class Account(object):
146
    '''
147
    The account object tracks information about the trading account. The
148
    values are updated as the algorithm runs and its keys remain unchanged.
149
    If connected to a broker, one can update these values with the trading
150
    account values as reported by the broker.
151
    '''
152
153
    def __init__(self):
154
        self.settled_cash = 0.0
155
        self.accrued_interest = 0.0
156
        self.buying_power = float('inf')
157
        self.equity_with_loan = 0.0
158
        self.total_positions_value = 0.0
159
        self.regt_equity = 0.0
160
        self.regt_margin = float('inf')
161
        self.initial_margin_requirement = 0.0
162
        self.maintenance_margin_requirement = 0.0
163
        self.available_funds = 0.0
164
        self.excess_liquidity = 0.0
165
        self.cushion = 0.0
166
        self.day_trades_remaining = float('inf')
167
        self.leverage = 0.0
168
        self.net_leverage = 0.0
169
        self.net_liquidation = 0.0
170
171
    def __getitem__(self, key):
172
        return self.__dict__[key]
173
174
    def __repr__(self):
175
        return "Account({0})".format(self.__dict__)
176
177
    def __getstate__(self):
178
179
        state_dict = copy(self.__dict__)
180
181
        STATE_VERSION = 1
182
        state_dict[VERSION_LABEL] = STATE_VERSION
183
184
        return state_dict
185
186
    def __setstate__(self, state):
187
188
        OLDEST_SUPPORTED_STATE = 1
189
        version = state.pop(VERSION_LABEL)
190
191
        if version < OLDEST_SUPPORTED_STATE:
192
            raise BaseException("Account saved state is too old.")
193
194
        self.__dict__.update(state)
195
196
197
class Position(object):
198
199
    def __init__(self, sid):
200
        self.sid = sid
201
        self.amount = 0
202
        self.cost_basis = 0.0  # per share
203
        self.last_sale_price = 0.0
204
205
    def __getitem__(self, key):
206
        return self.__dict__[key]
207
208
    def __repr__(self):
209
        return "Position({0})".format(self.__dict__)
210
211
    def __getstate__(self):
212
        state_dict = copy(self.__dict__)
213
214
        STATE_VERSION = 1
215
        state_dict[VERSION_LABEL] = STATE_VERSION
216
217
        return state_dict
218
219
    def __setstate__(self, state):
220
221
        OLDEST_SUPPORTED_STATE = 1
222
        version = state.pop(VERSION_LABEL)
223
224
        if version < OLDEST_SUPPORTED_STATE:
225
            raise BaseException("Protocol Position saved state is too old.")
226
227
        self.__dict__.update(state)
228
229
230
class Positions(dict):
231
232
    def __missing__(self, key):
233
        pos = Position(key)
234
        self[key] = pos
235
        return pos
236