Merge pull request #510 from quantopian/move-serialization-methods-into-zipline

MAINT: Added pickle protocol methods into zipline.
This commit is contained in:
Delaney Granizo-Mackenzie
2015-03-05 15:06:54 -05:00
32 changed files with 354868 additions and 5 deletions
+139
View File
@@ -0,0 +1,139 @@
#
# Copyright 2015 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import os
import pickle
import pytz
import sys
sys.path.insert(0, '.')
from zipline.finance.blotter import Blotter, Order
from zipline.finance.commission import PerShare, PerTrade, PerDollar
from zipline.finance.performance.period import PerformancePeriod
from zipline.finance.performance.position import Position
from zipline.finance.performance.tracker import PerformanceTracker
from zipline.finance.risk.cumulative import RiskMetricsCumulative
from zipline.finance.risk.period import RiskMetricsPeriod
from zipline.finance.risk.report import RiskReport
from zipline.finance.slippage import (
FixedSlippage,
Transaction,
VolumeShareSlippage
)
from zipline.protocol import Account
from zipline.protocol import Portfolio
from zipline.protocol import Position as ProtocolPosition
from zipline.finance.trading import SimulationParameters
from zipline.utils import factory
from zipline.utils.serialization_utils import VERSION_LABEL
base_state_dir = 'tests/resources/saved_state_archive'
if not os.path.exists(base_state_dir):
os.makedirs(base_state_dir)
sim_params_daily = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='daily')
sim_params_minute = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='minute')
returns = factory.create_returns_from_list(
[1.0], sim_params_daily)
argument_list = [
(Blotter, ()),
(Order, (datetime.datetime(2013, 6, 19), 8554, 100)),
(PerShare, ()),
(PerTrade, ()),
(PerDollar, ()),
(PerformancePeriod, (10000,)),
(Position, (8554,)),
(PerformanceTracker, (sim_params_minute,)),
(RiskMetricsCumulative, (sim_params_minute,)),
(RiskMetricsPeriod, (returns.index[0], returns.index[0], returns)),
(RiskReport, (returns, sim_params_minute)),
(FixedSlippage, ()),
(Transaction, (8554, 10, datetime.datetime(2013, 6, 19), 100, "0000")),
(VolumeShareSlippage, ()),
(Account, ()),
(Portfolio, ()),
(ProtocolPosition, (8554,))
]
def write_state_to_disk(cls, state, emission_rate=None):
state_dir = cls.__module__ + '.' + cls.__name__
full_dir = base_state_dir + '/' + state_dir
if not os.path.exists(full_dir):
os.makedirs(full_dir)
if emission_rate is not None:
name = 'State_Version_' + emission_rate + \
str(state['obj_state'][VERSION_LABEL])
else:
name = 'State_Version_' + str(state['obj_state'][VERSION_LABEL])
full_path = full_dir + '/' + name
f = open(full_path, 'w')
pickle.dump(state, f)
f.close()
def generate_object_state(cls, initargs):
obj = cls(*initargs)
state = obj.__getstate__()
if hasattr(obj, '__getinitargs__'):
initargs = obj.__getinitargs__()
else:
initargs = None
if hasattr(obj, '__getnewargs__'):
newargs = obj.__getnewargs__()
else:
newargs = None
on_disk_state = {
'obj_state': state,
'initargs': initargs,
'newargs': newargs
}
write_state_to_disk(cls, on_disk_state)
if __name__ == "__main__":
for args in argument_list:
generate_object_state(*args)
@@ -0,0 +1,21 @@
(dp0
S'obj_state'
p1
(dp2
S'_stateversion_'
p3
I1
sS'new_orders'
p4
(lp5
sS'orders'
p6
(dp7
sS'open_orders'
p8
(dp9
ssS'initargs'
p10
NsS'newargs'
p11
Ns.
@@ -0,0 +1,60 @@
(dp0
S'obj_state'
p1
(dp2
S'direction'
p3
F1.0
sS'_stateversion_'
p4
I1
sS'_status'
p5
I0
sS'created'
p6
cdatetime
datetime
p7
(S'\x07\xdd\x06\x13\x00\x00\x00\x00\x00\x00'
p8
tp9
Rp10
sS'limit_reached'
p11
I00
sS'stop'
p12
NsS'reason'
p13
NsS'stop_reached'
p14
I00
sS'commission'
p15
NsS'amount'
p16
I100
sS'limit'
p17
NsS'sid'
p18
I8554
sS'dt'
p19
g10
sS'type'
p20
I6
sS'id'
p21
S'ca467b999ff148f4b4fa89aa2cd899a9'
p22
sS'filled'
p23
I0
ssS'initargs'
p24
NsS'newargs'
p25
Ns.
@@ -0,0 +1,15 @@
(dp0
S'obj_state'
p1
(dp2
S'cost'
p3
F0.0015
sS'_stateversion_'
p4
I1
ssS'initargs'
p5
NsS'newargs'
p6
Ns.
@@ -0,0 +1,17 @@
(dp0
S'obj_state'
p1
(dp2
S'min_trade_cost'
p3
NsS'cost'
p4
F0.03
sS'_stateversion_'
p5
I1
ssS'initargs'
p6
NsS'newargs'
p7
Ns.
@@ -0,0 +1,15 @@
(dp0
S'obj_state'
p1
(dp2
S'cost'
p3
F5.0
sS'_stateversion_'
p4
I1
ssS'initargs'
p5
NsS'newargs'
p6
Ns.
@@ -0,0 +1,194 @@
(dp0
S'obj_state'
p1
(dp2
S'_account_store'
p3
ccopy_reg
_reconstructor
p4
(czipline.protocol
Account
p5
c__builtin__
object
p6
Ntp7
Rp8
(dp9
S'regt_margin'
p10
Finf
sS'maintenance_margin_requirement'
p11
F0.0
sS'day_trades_remaining'
p12
Finf
sS'buying_power'
p13
Finf
sS'net_leverage'
p14
F0.0
sS'settled_cash'
p15
F0.0
sS'cushion'
p16
F0.0
sS'_stateversion_'
p17
I1
sS'leverage'
p18
F0.0
sS'regt_equity'
p19
F0.0
sS'excess_liquidity'
p20
F0.0
sS'available_funds'
p21
F0.0
sS'equity_with_loan'
p22
F0.0
sS'initial_margin_requirement'
p23
F0.0
sS'net_liquidation'
p24
F0.0
sS'total_positions_value'
p25
F0.0
sS'accrued_interest'
p26
F0.0
sbsS'orders_by_modified'
p27
(dp28
sS'keep_transactions'
p29
I01
sS'ending_cash'
p30
F10000.0
sS'_positions_store'
p31
(dp32
sS'positions'
p33
(dp34
sS'processed_transactions'
p35
(dp36
sS'ending_value'
p37
cnumpy.core.multiarray
scalar
p38
(cnumpy
dtype
p39
(S'f8'
p40
I0
I1
tp41
Rp42
(I3
S'<'
p43
NNNI-1
I-1
I0
tp44
bS'\x00\x00\x00\x00\x00\x00\x00\x00'
p45
tp46
Rp47
sS'loc_map'
p48
(dp49
sS'starting_cash'
p50
I10000
sS'returns'
p51
g38
(g42
S'\x00\x00\x00\x00\x00\x00\x00\x00'
p52
tp53
Rp54
sg17
I1
sS'pnl'
p55
g38
(g42
S'\x00\x00\x00\x00\x00\x00\x00\x00'
p56
tp57
Rp58
sS'period_cash_flow'
p59
F0.0
sS'serialize_positions'
p60
I01
sS'keep_orders'
p61
I00
sS'_portfolio_store'
p62
g4
(czipline.protocol
Portfolio
p63
g6
Ntp64
Rp65
(dp66
g17
I1
sS'portfolio_value'
p67
F0.0
sS'cash'
p68
F0.0
sg50
F0.0
sg51
F0.0
sS'capital_used'
p69
F0.0
sg55
F0.0
sg33
(dp70
sS'positions_value'
p71
F0.0
sS'start_date'
p72
NsbsS'starting_value'
p73
F0.0
sS'period_open'
p74
NsS'period_close'
p75
NsS'orders_by_id'
p76
(dp77
ssS'initargs'
p78
NsS'newargs'
p79
Ns.
@@ -0,0 +1,26 @@
(dp0
S'obj_state'
p1
(dp2
S'_stateversion_'
p3
I1
sS'cost_basis'
p4
F0.0
sS'amount'
p5
I0
sS'last_sale_price'
p6
F0.0
sS'sid'
p7
I8554
sS'last_sale_date'
p8
NssS'initargs'
p9
NsS'newargs'
p10
Ns.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
(dp0
S'obj_state'
p1
(dp2
S'spread'
p3
F0.0
sS'_stateversion_'
p4
I1
ssS'initargs'
p5
NsS'newargs'
p6
Ns.
@@ -0,0 +1,39 @@
(dp0
S'obj_state'
p1
(dp2
S'commission'
p3
NsS'amount'
p4
I10
sS'_stateversion_'
p5
I1
sS'sid'
p6
I8554
sS'order_id'
p7
S'0000'
p8
sS'price'
p9
I100
sS'type'
p10
I5
sS'dt'
p11
cdatetime
datetime
p12
(S'\x07\xdd\x06\x13\x00\x00\x00\x00\x00\x00'
p13
tp14
Rp15
ssS'initargs'
p16
NsS'newargs'
p17
Ns.
@@ -0,0 +1,18 @@
(dp0
S'obj_state'
p1
(dp2
S'price_impact'
p3
F0.1
sS'volume_limit'
p4
F0.25
sS'_stateversion_'
p5
I1
ssS'initargs'
p6
NsS'newargs'
p7
Ns.
@@ -0,0 +1,60 @@
(dp0
S'obj_state'
p1
(dp2
S'regt_margin'
p3
Finf
sS'maintenance_margin_requirement'
p4
F0.0
sS'day_trades_remaining'
p5
Finf
sS'buying_power'
p6
Finf
sS'net_leverage'
p7
F0.0
sS'settled_cash'
p8
F0.0
sS'cushion'
p9
F0.0
sS'_stateversion_'
p10
I1
sS'leverage'
p11
F0.0
sS'regt_equity'
p12
F0.0
sS'excess_liquidity'
p13
F0.0
sS'available_funds'
p14
F0.0
sS'equity_with_loan'
p15
F0.0
sS'initial_margin_requirement'
p16
F0.0
sS'net_liquidation'
p17
F0.0
sS'total_positions_value'
p18
F0.0
sS'accrued_interest'
p19
F0.0
ssS'initargs'
p20
NsS'newargs'
p21
Ns.
@@ -0,0 +1,38 @@
(dp0
S'obj_state'
p1
(dp2
S'_stateversion_'
p3
I1
sS'portfolio_value'
p4
F0.0
sS'cash'
p5
F0.0
sS'starting_cash'
p6
F0.0
sS'returns'
p7
F0.0
sS'capital_used'
p8
F0.0
sS'pnl'
p9
F0.0
sS'positions'
p10
(dp11
sS'positions_value'
p12
F0.0
sS'start_date'
p13
NssS'initargs'
p14
NsS'newargs'
p15
Ns.
@@ -0,0 +1,24 @@
(dp0
S'obj_state'
p1
(dp2
S'_stateversion_'
p3
I1
sS'amount'
p4
I0
sS'last_sale_price'
p5
F0.0
sS'cost_basis'
p6
F0.0
sS'sid'
p7
I8554
ssS'initargs'
p8
NsS'newargs'
p9
Ns.
+100
View File
@@ -0,0 +1,100 @@
#
# Copyright 2015 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import pickle
import pytz
from nose_parameterized import parameterized
from unittest import TestCase
from zipline.finance.blotter import Blotter, Order
from zipline.finance.commission import PerShare, PerTrade, PerDollar
from zipline.finance.performance.period import PerformancePeriod
from zipline.finance.performance.position import Position
from zipline.finance.performance.tracker import PerformanceTracker
from zipline.finance.risk.cumulative import RiskMetricsCumulative
from zipline.finance.risk.period import RiskMetricsPeriod
from zipline.finance.risk.report import RiskReport
from zipline.finance.slippage import (
FixedSlippage,
Transaction,
VolumeShareSlippage
)
from zipline.protocol import Account
from zipline.protocol import Portfolio
from zipline.protocol import Position as ProtocolPosition
from zipline.finance.trading import SimulationParameters
from zipline.utils import factory
sim_params_daily = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='daily')
sim_params_minute = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='minute')
returns = factory.create_returns_from_list(
[1.0], sim_params_daily)
class PickleSerializationTestCase(TestCase):
@parameterized.expand([
(Blotter, (), 'repr'),
(Order, (datetime.datetime(2013, 6, 19), 8554, 100), 'dict'),
(PerShare, (), 'dict'),
(PerTrade, (), 'dict'),
(PerDollar, (), 'dict'),
(PerformancePeriod, (10000,), 'to_dict'),
(Position, (8554,), 'dict'),
(PerformanceTracker, (sim_params_daily,), 'to_dict'),
(PerformanceTracker, (sim_params_minute,), 'to_dict'),
(RiskMetricsCumulative, (sim_params_daily,), 'to_dict'),
(RiskMetricsCumulative, (sim_params_minute,), 'to_dict'),
(RiskMetricsPeriod,
(returns.index[0], returns.index[0], returns), 'to_dict'),
(RiskReport, (returns, sim_params_daily), 'to_dict'),
(RiskReport, (returns, sim_params_minute), 'to_dict'),
(FixedSlippage, (), 'dict'),
(Transaction,
(8554, 10, datetime.datetime(2013, 6, 19), 100, "0000"), 'dict'),
(VolumeShareSlippage, (), 'dict'),
(Account, (), 'dict'),
(Portfolio, (), 'dict'),
(ProtocolPosition, (8554,), 'dict')
])
def test_object_serialization(self,
cls,
initargs,
comparison_method='dict'):
obj = cls(*initargs)
state = pickle.dumps(obj)
obj2 = pickle.loads(state)
if comparison_method == 'repr':
self.assertEqual(obj.__repr__(), obj2.__repr__())
elif comparison_method == 'to_dict':
self.assertEqual(obj.to_dict(), obj2.to_dict())
else:
self.assertEqual(obj.__dict__, obj2.__dict__)
+150
View File
@@ -0,0 +1,150 @@
#
# Copyright 2015 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import pytz
from nose_parameterized import parameterized
from unittest import TestCase
from zipline.finance.blotter import Blotter, Order
from zipline.finance.commission import PerShare, PerTrade, PerDollar
from zipline.finance.performance.period import PerformancePeriod
from zipline.finance.performance.position import Position
from zipline.finance.performance.tracker import PerformanceTracker
from zipline.finance.risk.cumulative import RiskMetricsCumulative
from zipline.finance.risk.period import RiskMetricsPeriod
from zipline.finance.risk.report import RiskReport
from zipline.finance.slippage import (
FixedSlippage,
Transaction,
VolumeShareSlippage
)
from zipline.protocol import Account
from zipline.protocol import Portfolio
from zipline.protocol import Position as ProtocolPosition
from zipline.finance.trading import SimulationParameters
from zipline.utils import factory
from six import iteritems
sim_params_daily = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='daily')
sim_params_minute = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='minute')
returns = factory.create_returns_from_list(
[1.0], sim_params_daily)
def gather_bad_dicts(state):
bad = []
for k, v in iteritems(state):
if not isinstance(v, dict):
continue
if type(v) != dict:
bad.append((k, v))
bad.extend(gather_bad_dicts(v))
return bad
def stringify_cases(cases, func=None):
# get better test case names
results = []
if func is None:
func = lambda case: case[0].__name__
for case in cases:
new_case = list(case)
key = func(case)
new_case.insert(0, key)
results.append(new_case)
return results
class SerializationTestCase(TestCase):
object_serialization_cases = stringify_cases([
(Blotter, (), 'repr'),
(Order, (datetime.datetime(2013, 6, 19), 8554, 100), 'dict'),
(PerShare, (), 'dict'),
(PerTrade, (), 'dict'),
(PerDollar, (), 'dict'),
(PerformancePeriod, (10000,), 'to_dict'),
(Position, (8554,), 'dict'),
(PerformanceTracker, (sim_params_daily,), 'to_dict'),
(PerformanceTracker, (sim_params_minute,), 'to_dict'),
(RiskMetricsCumulative, (sim_params_daily,), 'to_dict'),
(RiskMetricsCumulative, (sim_params_minute,), 'to_dict'),
(RiskMetricsPeriod,
(returns.index[0], returns.index[0], returns), 'to_dict'),
(RiskReport, (returns, sim_params_daily), 'to_dict'),
(RiskReport, (returns, sim_params_minute), 'to_dict'),
(FixedSlippage, (), 'dict'),
(Transaction,
(8554, 10, datetime.datetime(2013, 6, 19), 100, "0000"), 'dict'),
(VolumeShareSlippage, (), 'dict'),
(Account, (), 'dict'),
(Portfolio, (), 'dict'),
(ProtocolPosition, (8554,), 'dict')
])
@parameterized.expand(object_serialization_cases)
def test_object_serialization(self,
_,
cls,
initargs,
comparison_method='dict'):
obj = cls(*initargs)
state = obj.__getstate__()
bad_dicts = gather_bad_dicts(state)
bad_template = "type({0}) == {1}".format
bad_msgs = [bad_template(k, type(v)) for k, v in bad_dicts]
msg = "Only support bare dicts. " + ', '.join(bad_msgs)
self.assertEqual(len(bad_dicts), 0, msg)
# no state should have a dict subclass. Only regular PyDict
if hasattr(obj, '__getinitargs__'):
initargs = obj.__getinitargs__()
else:
initargs = None
if hasattr(obj, '__getnewargs__'):
newargs = obj.__getnewargs__()
else:
newargs = None
if newargs is not None:
obj2 = cls.__new__(cls, *newargs)
else:
obj2 = cls.__new__(cls)
if initargs is not None:
obj2.__init__(*initargs)
obj2.__setstate__(state)
if comparison_method == 'repr':
self.assertEqual(obj.__repr__(), obj2.__repr__())
elif comparison_method == 'to_dict':
self.assertEqual(obj.to_dict(), obj2.to_dict())
else:
self.assertEqual(obj.__dict__, obj2.__dict__)
+150
View File
@@ -0,0 +1,150 @@
#
# Copyright 2015 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import os
import pandas
import pickle
import pytz
from nose_parameterized import parameterized
from unittest import TestCase
from zipline.finance.blotter import Blotter, Order
from zipline.finance.commission import PerShare, PerTrade, PerDollar
from zipline.finance.performance.period import PerformancePeriod
from zipline.finance.performance.position import Position
from zipline.finance.performance.tracker import PerformanceTracker
from zipline.finance.risk.cumulative import RiskMetricsCumulative
from zipline.finance.risk.period import RiskMetricsPeriod
from zipline.finance.risk.report import RiskReport
from zipline.finance.slippage import (
FixedSlippage,
Transaction,
VolumeShareSlippage
)
from zipline.protocol import Account
from zipline.protocol import Portfolio
from zipline.protocol import Position as ProtocolPosition
from zipline.finance.trading import SimulationParameters
from zipline.utils import factory
sim_params_daily = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='daily')
sim_params_minute = SimulationParameters(
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
datetime.datetime(2013, 6, 19, tzinfo=pytz.UTC),
10000,
emission_rate='minute')
returns = factory.create_returns_from_list(
[1.0], sim_params_daily)
base_state_dir = 'tests/resources/saved_state_archive'
BASE_STATE_DIR = os.path.join(
os.path.dirname(__file__),
'resources',
'saved_state_archive')
class VersioningTestCase(TestCase):
def load_state_from_disk(self, cls):
state_dir = cls.__module__ + '.' + cls.__name__
full_dir = BASE_STATE_DIR + '/' + state_dir
state_files = \
[f for f in os.listdir(full_dir) if 'State_Version_' in f]
for f_name in state_files:
f = open(full_dir + '/' + f_name, 'r')
yield pickle.load(f)
# Only test versioning in minutely mode right now
@parameterized.expand([
(Blotter, (), 'repr'),
(Order, (datetime.datetime(2013, 6, 19), 8554, 100), 'dict'),
(PerShare, (), 'dict'),
(PerTrade, (), 'dict'),
(PerDollar, (), 'dict'),
(PerformancePeriod, (10000,), 'to_dict'),
(Position, (8554,), 'dict'),
(PerformanceTracker, (sim_params_minute,), 'to_dict'),
(RiskMetricsCumulative, (sim_params_minute,), 'to_dict'),
(RiskMetricsPeriod,
(returns.index[0], returns.index[0], returns), 'to_dict'),
(RiskReport, (returns, sim_params_minute), 'to_dict'),
(FixedSlippage, (), 'dict'),
(Transaction,
(8554, 10, datetime.datetime(2013, 6, 19), 100, "0000"), 'dict'),
(VolumeShareSlippage, (), 'dict'),
(Account, (), 'dict'),
(Portfolio, (), 'dict'),
(ProtocolPosition, (8554,), 'dict')
])
def test_object_serialization(self,
cls,
initargs,
comparison_method='dict'):
# The state generated under one version of pandas may not be
# compatible with another. To ensure that tests pass under the travis
# pandas version matrix, we only run versioning tests under the
# current version of pandas. This will need to be updated once we
# change the pandas version on prod.
if pandas.__version__ != '0.12.0':
return
# Make reference object
obj = cls(*initargs)
# Fetch state
state_versions = self.load_state_from_disk(cls)
for version in state_versions:
# For each version inflate a new object and ensure that it
# matches the original.
newargs = version['newargs']
initargs = version['initargs']
state = version['obj_state']
if newargs is not None:
obj2 = cls.__new__(cls, *newargs)
else:
obj2 = cls.__new__(cls)
if initargs is not None:
obj2.__init__(*initargs)
obj2.__setstate__(state)
# The ObjectId generated on instantiation of Order will
# not be the same as the one loaded from saved state.
if cls == Order:
obj.__dict__['id'] = obj2.__dict__['id']
if comparison_method == 'repr':
self.assertEqual(obj.__repr__(), obj2.__repr__())
elif comparison_method == 'to_dict':
self.assertEqual(obj.to_dict(), obj2.to_dict())
else:
self.assertEqual(obj.__dict__, obj2.__dict__)
+58 -1
View File
@@ -19,7 +19,7 @@ from copy import copy
from logbook import Logger
from collections import defaultdict
from six import text_type
from six import text_type, iteritems
from six.moves import filter
import zipline.errors
@@ -35,6 +35,9 @@ from zipline.finance.commission import PerShare
log = Logger('Blotter')
from zipline.utils.protocol_utils import Enum
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
ORDER_STATUS = Enum(
'OPEN',
@@ -247,6 +250,37 @@ class Blotter(object):
yield txn, order
def __getstate__(self):
state_to_save = ['new_orders', 'orders', '_status']
state_dict = {k: self.__dict__[k] for k in state_to_save
if k in self.__dict__}
# Have to handle defaultdicts specially
state_dict['open_orders'] = dict(self.open_orders)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
self.__init__()
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Blotter saved is state too old.")
open_orders = defaultdict(list)
open_orders.update(state.pop('open_orders'))
self.open_orders = open_orders
self.__dict__.update(state)
class Order(object):
def __init__(self, dt, sid, amount, stop=None, limit=None, filled=0,
@@ -385,3 +419,26 @@ class Order(object):
Unicode representation for this object.
"""
return text_type(repr(self))
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
state_dict['_status'] = self._status
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Order saved state is too old.")
self.__dict__.update(state)
+69
View File
@@ -13,6 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from six import iteritems
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
class PerShare(object):
"""
@@ -50,6 +56,27 @@ class PerShare(object):
commission = max(commission, self.min_trade_cost)
return abs(commission / transaction.amount), commission
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("PerShare saved state is too old.")
self.__dict__.update(state)
class PerTrade(object):
"""
@@ -77,6 +104,27 @@ class PerTrade(object):
return abs(self.cost / transaction.amount), self.cost
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("PerTrade saved state is too old.")
self.__dict__.update(state)
class PerDollar(object):
"""
@@ -103,3 +151,24 @@ class PerDollar(object):
"""
cost_per_share = transaction.price * self.cost
return cost_per_share, abs(transaction.amount) * cost_per_share
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("PerDollar saved state is too old.")
self.__dict__.update(state)
+64
View File
@@ -92,6 +92,10 @@ from six import iteritems, itervalues
import zipline.protocol as zp
from . position import positiondict
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
log = logbook.Logger('Performance')
TRADE_TYPE = zp.DATASOURCE_TYPE.TRADE
@@ -574,3 +578,63 @@ class PerformancePeriod(object):
if pos.amount != 0:
positions.append(pos.to_dict())
return positions
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
state_dict['_portfolio_store'] = self._portfolio_store
state_dict['_account_store'] = self._account_store
# We need to handle the defaultdict specially, otherwise
# msgpack will unpack it as a dict, causing KeyError
# nastiness.
state_dict['processed_transactions'] = \
dict(self.processed_transactions)
state_dict['orders_by_id'] = \
dict(self.orders_by_id)
state_dict['orders_by_modified'] = \
dict(self.orders_by_modified)
state_dict['positions'] = \
dict(self.positions)
state_dict['_positions_store'] = \
dict(self._positions_store)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("PerformancePeriod saved state is too old.")
processed_transactions = defaultdict(list)
processed_transactions.update(state.pop('processed_transactions'))
orders_by_id = OrderedDict()
orders_by_id.update(state.pop('orders_by_id'))
orders_by_modified = defaultdict(OrderedDict)
orders_by_modified.update(state.pop('orders_by_modified'))
positions = positiondict()
positions.update(state.pop('positions'))
_positions_store = zp.Positions()
_positions_store.update(state.pop('_positions_store'))
self.processed_transactions = processed_transactions
self.orders_by_id = orders_by_id
self.orders_by_modified = orders_by_modified
self.positions = positions
self._positions_store = _positions_store
self.__dict__.update(state)
self.initialize_position_calc_arrays()
+25
View File
@@ -38,9 +38,15 @@ from math import (
floor,
)
from copy import copy
import logbook
import zipline.protocol as zp
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
log = logbook.Logger('Performance')
@@ -207,6 +213,25 @@ last_sale_price: {last_sale_price}"
'last_sale_price': self.last_sale_price
}
def __getstate__(self):
state_dict = copy(self.__dict__)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Position saved state is too old.")
self.__dict__.update(state)
class positiondict(dict):
+40
View File
@@ -59,6 +59,8 @@ Performance Tracking
from __future__ import division
import logbook
import pickle
from six import iteritems
import numpy as np
import pandas as pd
@@ -70,6 +72,9 @@ from zipline.finance import trading
from . period import PerformancePeriod
from zipline.finance.trading import with_environment
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
log = logbook.Logger('Performance')
@@ -483,3 +488,38 @@ class PerformanceTracker(object):
risk_dict = self.risk_report.to_dict()
return risk_dict
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
state_dict['dividend_frame'] = pickle.dumps(self.dividend_frame)
state_dict['_dividend_count'] = self._dividend_count
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("PerformanceTracker saved state is too old.")
self.__dict__.update(state)
# Handle the dividend frame specially
self.dividend_frame = pickle.loads(state['dividend_frame'])
# We have to restore the references to the objects,
# as the perf periods have been reconstructed as different objects
# with the same values.
self.perf_periods[0] = self.cumulative_performance
self.perf_periods[1] = self.todays_performance
if self.sim_params.emission_rate == 'minute':
self.perf_periods[2] = self.minute_performance
+29
View File
@@ -35,6 +35,10 @@ from . risk import (
sortino_ratio,
)
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
log = logbook.Logger('Risk Cumulative')
@@ -454,3 +458,28 @@ algorithm_returns ({algo_count}) in range {start} : {end} on {dt}"
beta = algorithm_covariance / benchmark_variance
return beta
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__) if
(not k.startswith('_') and not k == 'treasury_curves')}
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("RiskMetricsCumulative \
saved state is too old.")
self.__dict__.update(state)
# This are big and we don't need to serialize them
# pop them back in now
self.treasury_curves = trading.environment.treasury_curves
+27
View File
@@ -36,6 +36,10 @@ from . risk import (
sortino_ratio,
)
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
log = logbook.Logger('Risk Period')
choose_treasury = functools.partial(risk.choose_treasury,
@@ -304,3 +308,26 @@ class RiskMetricsPeriod(object):
return 0.0
return 1.0 - math.exp(max_drawdown)
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__) if
(not k.startswith('_') and not k == 'treasury_curves')}
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("RiskMetricsPeriod saved state \
is too old.")
self.__dict__.update(state)
self.treasury_curves = trading.environment.treasury_curves
+28
View File
@@ -58,9 +58,14 @@ Risk Report
import logbook
import datetime
from dateutil.relativedelta import relativedelta
from six import iteritems
from . period import RiskMetricsPeriod
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
log = logbook.Logger('Risk Report')
@@ -138,3 +143,26 @@ class RiskReport(object):
cur_start = cur_start + relativedelta(months=1)
return ends
def __getstate__(self):
state_dict = \
{k: v for k, v in iteritems(self.__dict__)
if not k.startswith('_')}
if '_dividend_count' in dir(self):
state_dict['_dividend_count'] = self._dividend_count
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("RiskReport saved state is too old.")
self.__dict__.update(state)
+60
View File
@@ -24,6 +24,9 @@ from functools import partial
from six import with_metaclass
from zipline.protocol import DATASOURCE_TYPE
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
SELL = 1 << 0
BUY = 1 << 1
@@ -128,6 +131,25 @@ class Transaction(object):
del py['type']
return py
def __getstate__(self):
state_dict = copy(self.__dict__)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Transaction saved state is too old.")
self.__dict__.update(state)
def create_transaction(event, order, price, amount):
@@ -246,6 +268,25 @@ class VolumeShareSlippage(SlippageModel):
math.copysign(cur_volume, order.direction)
)
def __getstate__(self):
state_dict = copy(self.__dict__)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("VolumeShareSlippage saved state is too old.")
self.__dict__.update(state)
class FixedSlippage(SlippageModel):
@@ -264,3 +305,22 @@ class FixedSlippage(SlippageModel):
event.price + (self.spread / 2.0 * order.direction),
order.amount,
)
def __getstate__(self):
state_dict = copy(self.__dict__)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("FixedSlippage saved state is too old.")
self.__dict__.update(state)
+66 -4
View File
@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from copy import copy
from six import iteritems, iterkeys
import pandas as pd
import numpy as np
@@ -22,6 +24,9 @@ from . utils.math_utils import nanstd, nanmean, nansum
from zipline.finance.trading import with_environment
from zipline.utils.algo_instance import get_algo_instance
from zipline.utils.serialization_utils import (
VERSION_LABEL
)
# Datasource type should completely determine the other fields of a
# message with its type.
@@ -138,6 +143,31 @@ class Portfolio(object):
def __repr__(self):
return "Portfolio({0})".format(self.__dict__)
def __getstate__(self):
state_dict = copy(self.__dict__)
# Have to convert to primitive dict
state_dict['positions'] = dict(self.positions)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Portfolio saved state is too old.")
self.positions = Positions()
self.positions.update(state.pop('positions'))
self.__dict__.update(state)
class Account(object):
'''
@@ -171,11 +201,24 @@ class Account(object):
def __repr__(self):
return "Account({0})".format(self.__dict__)
def _get_state(self):
return 'Account', self.__dict__
def __getstate__(self):
def _set_state(self, saved_state):
self.__dict__.update(saved_state)
state_dict = copy(self.__dict__)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Account saved state is too old.")
self.__dict__.update(state)
class Position(object):
@@ -192,6 +235,25 @@ class Position(object):
def __repr__(self):
return "Position({0})".format(self.__dict__)
def __getstate__(self):
state_dict = copy(self.__dict__)
STATE_VERSION = 1
state_dict[VERSION_LABEL] = STATE_VERSION
return state_dict
def __setstate__(self, state):
OLDEST_SUPPORTED_STATE = 1
version = state.pop(VERSION_LABEL)
if version < OLDEST_SUPPORTED_STATE:
raise BaseException("Protocol Position saved state is too old.")
self.__dict__.update(state)
class Positions(dict):
+18
View File
@@ -0,0 +1,18 @@
#
# Copyright 2015 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Label for the serialization version field in the state returned by
# __getstate__.
VERSION_LABEL = '_stateversion_'