Merge pull request #1726 from quantopian/cf-adjustment-arg

Make continuous future adjustment style an argument
This commit is contained in:
David Michalowicz
2017-03-29 09:15:22 -04:00
committed by GitHub
6 changed files with 87 additions and 65 deletions
+4 -1
View File
@@ -161,7 +161,10 @@ def build_lookup_generic_cases(asset_finder_type):
]
fof14 = finder.retrieve_asset(fof14_sid)
cf = finder.create_continuous_future(
root_symbol=fof14.root_symbol, offset=0, roll_style='volume',
root_symbol=fof14.root_symbol,
offset=0,
roll_style='volume',
adjustment=None,
)
dupe_0_start = dupe_0.start_date
+33 -30
View File
@@ -348,7 +348,9 @@ class ContinuousFuturesTestCase(WithCreateBarData,
close date. See `VolumeRollFinder._active_contract` for a full
explanation and example.
"""
cf = self.asset_finder.create_continuous_future('DF', 0, 'volume')
cf = self.asset_finder.create_continuous_future(
'DF', 0, 'volume', None,
)
sessions = self.trading_calendar.sessions_in_range(
'2016-02-09', '2016-02-17',
@@ -385,7 +387,7 @@ class ContinuousFuturesTestCase(WithCreateBarData,
def test_create_continuous_future(self):
cf_primary = self.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
self.assertEqual(cf_primary.root_symbol, 'FO')
self.assertEqual(cf_primary.offset, 0)
@@ -401,7 +403,7 @@ class ContinuousFuturesTestCase(WithCreateBarData,
self.assertEqual(retrieved_primary, cf_primary)
cf_secondary = self.asset_finder.create_continuous_future(
'FO', 1, 'calendar')
'FO', 1, 'calendar', None)
self.assertEqual(cf_secondary.root_symbol, 'FO')
self.assertEqual(cf_secondary.offset, 1)
@@ -421,11 +423,12 @@ class ContinuousFuturesTestCase(WithCreateBarData,
# Assert that the proper exception is raised if the given root symbol
# does not exist.
with self.assertRaises(SymbolNotFound):
self.asset_finder.create_continuous_future('NO', 0, 'calendar')
self.asset_finder.create_continuous_future(
'NO', 0, 'calendar', None)
def test_current_contract(self):
cf_primary = self.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
bar_data = self.create_bardata(
lambda: pd.Timestamp('2016-01-26', tz='UTC'))
contract = bar_data.current(cf_primary, 'contract')
@@ -442,7 +445,7 @@ class ContinuousFuturesTestCase(WithCreateBarData,
def test_get_value_contract_daily(self):
cf_primary = self.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
contract = self.data_portal.get_spot_value(
cf_primary,
@@ -466,7 +469,7 @@ class ContinuousFuturesTestCase(WithCreateBarData,
def test_get_value_close_daily(self):
cf_primary = self.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
value = self.data_portal.get_spot_value(
cf_primary,
@@ -504,7 +507,7 @@ class ContinuousFuturesTestCase(WithCreateBarData,
def test_current_contract_volume_roll(self):
cf_primary = self.asset_finder.create_continuous_future(
'FO', 0, 'volume')
'FO', 0, 'volume', None)
bar_data = self.create_bardata(
lambda: pd.Timestamp('2016-01-26', tz='UTC'))
contract = bar_data.current(cf_primary, 'contract')
@@ -535,8 +538,8 @@ from zipline.api import (
)
def initialize(algo):
algo.primary_cl = continuous_future('FO', 0, 'calendar')
algo.secondary_cl = continuous_future('FO', 1, 'calendar')
algo.primary_cl = continuous_future('FO', 0, 'calendar', None)
algo.secondary_cl = continuous_future('FO', 1, 'calendar', None)
schedule_function(record_current_contract)
def record_current_contract(algo, data):
@@ -588,8 +591,8 @@ from zipline.api import (
)
def initialize(algo):
algo.primary_cl = continuous_future('FO', 0, 'calendar')
algo.secondary_cl = continuous_future('FO', 1, 'calendar')
algo.primary_cl = continuous_future('FO', 0, 'calendar', None)
algo.secondary_cl = continuous_future('FO', 1, 'calendar', None)
schedule_function(record_current_contract)
def record_current_contract(algo, data):
@@ -681,7 +684,7 @@ def record_current_contract(algo, data):
def test_history_sid_session(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
window = self.data_portal.get_history_window(
[cf],
Timestamp('2016-03-04 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -735,7 +738,7 @@ def record_current_contract(algo, data):
def test_history_sid_session_quarter_rolls(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'BA', 0, 'calendar')
'BA', 0, 'calendar', None)
window = self.data_portal.get_history_window(
[cf],
Timestamp('2016-03-13 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -756,7 +759,7 @@ def record_current_contract(algo, data):
def test_history_sid_session_delivery_predicate(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'BZ', 0, 'calendar')
'BZ', 0, 'calendar', None)
window = self.data_portal.get_history_window(
[cf],
Timestamp('2016-01-11 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -777,7 +780,7 @@ def record_current_contract(algo, data):
def test_history_sid_session_secondary(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 1, 'calendar')
'FO', 1, 'calendar', None)
window = self.data_portal.get_history_window(
[cf],
Timestamp('2016-03-04 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -831,7 +834,7 @@ def record_current_contract(algo, data):
def test_history_sid_session_volume_roll(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'volume')
'FO', 0, 'volume', None)
window = self.data_portal.get_history_window(
[cf],
Timestamp('2016-03-04 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -895,7 +898,7 @@ def record_current_contract(algo, data):
def test_history_sid_minute(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
window = self.data_portal.get_history_window(
[cf.sid],
Timestamp('2016-01-26 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -930,7 +933,7 @@ def record_current_contract(algo, data):
def test_history_close_session(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
window = self.data_portal.get_history_window(
[cf.sid], Timestamp('2016-03-06', tz='UTC'), 30, '1d', 'close')
@@ -980,7 +983,7 @@ def record_current_contract(algo, data):
def test_history_close_session_skip_volume(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'MA', 0, 'volume')
'MA', 0, 'volume', None)
window = self.data_portal.get_history_window(
[cf.sid], Timestamp('2016-03-06', tz='UTC'), 30, '1d', 'close')
@@ -1020,11 +1023,11 @@ def record_current_contract(algo, data):
def test_history_close_session_adjusted(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
cf_mul = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar').adj('mul')
'FO', 0, 'calendar', 'mul')
cf_add = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar').adj('add')
'FO', 0, 'calendar', 'add')
window = self.data_portal.get_history_window(
[cf, cf_mul, cf_add],
Timestamp('2016-03-06', tz='UTC'), 30, '1d', 'close')
@@ -1148,7 +1151,7 @@ def record_current_contract(algo, data):
def test_history_close_minute(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
window = self.data_portal.get_history_window(
[cf.sid],
Timestamp('2016-02-25 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -1183,11 +1186,11 @@ def record_current_contract(algo, data):
def test_history_close_minute_adjusted(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar')
'FO', 0, 'calendar', None)
cf_mul = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar').adj('mul')
'FO', 0, 'calendar', 'mul')
cf_add = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'calendar').adj('add')
'FO', 0, 'calendar', 'add')
window = self.data_portal.get_history_window(
[cf, cf_mul, cf_add],
Timestamp('2016-02-25 18:01', tz='US/Eastern').tz_convert('UTC'),
@@ -1247,11 +1250,11 @@ def record_current_contract(algo, data):
def test_history_close_minute_adjusted_volume_roll(self):
cf = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'volume')
'FO', 0, 'volume', None)
cf_mul = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'volume').adj('mul')
'FO', 0, 'volume', 'mul')
cf_add = self.data_portal.asset_finder.create_continuous_future(
'FO', 0, 'volume').adj('add')
'FO', 0, 'volume', 'add')
window = self.data_portal.get_history_window(
[cf, cf_mul, cf_add],
Timestamp('2016-02-25 18:01', tz='US/Eastern').tz_convert('UTC'),
+10 -1
View File
@@ -1201,7 +1201,11 @@ class TradingAlgorithm(object):
@api_method
@preprocess(root_symbol_str=ensure_upper_case)
def continuous_future(self, root_symbol_str, offset, roll):
def continuous_future(self,
root_symbol_str,
offset,
roll,
adjustment='mul'):
"""Create a specifier for a continuous contract.
Parameters
@@ -1215,6 +1219,10 @@ class TradingAlgorithm(object):
roll_style : str
How rolls are determined.
adjustment : str
Method for adjusting lookback prices between rolls. Options are
'mul', 'add', and None. Defaults to 'mul'.
Returns
-------
continuous_future : ContinuousFuture
@@ -1224,6 +1232,7 @@ class TradingAlgorithm(object):
root_symbol_str,
offset,
roll,
adjustment,
)
@api_method
+5 -1
View File
@@ -60,7 +60,7 @@ def cancel_order(order_param):
The order_id or order object to cancel.
"""
def continuous_future(root_symbol_str, offset, roll):
def continuous_future(root_symbol_str, offset, roll, adjustment='mul'):
"""Create a specifier for a continuous contract.
Parameters
@@ -74,6 +74,10 @@ def continuous_future(root_symbol_str, offset, roll):
roll_style : str
How rolls are determined.
adjustment : str
Method for adjusting lookback prices between rolls. Options are
'mul', 'add', and None. Defaults to 'mul'.
Returns
-------
continuous_future : ContinuousFuture
+33 -32
View File
@@ -16,6 +16,7 @@ from abc import ABCMeta
import array
import binascii
from collections import deque, namedtuple
from functools import partial
from numbers import Integral
from operator import itemgetter, attrgetter
import struct
@@ -54,9 +55,10 @@ from . import (
Asset, Equity, Future,
)
from . continuous_futures import (
OrderedContracts,
ADJUSTMENT_STYLES,
CHAIN_PREDICATES,
ContinuousFuture,
CHAIN_PREDICATES
OrderedContracts,
)
from .asset_writer import (
check_version_info,
@@ -1016,7 +1018,17 @@ class AssetFinder(object):
self._ordered_contracts[root_symbol] = oc
return oc
def create_continuous_future(self, root_symbol, offset, roll_style):
def create_continuous_future(self,
root_symbol,
offset,
roll_style,
adjustment):
if adjustment not in ADJUSTMENT_STYLES:
raise ValueError(
'Invalid adjustment style {!r}. Allowed adjustment styles are '
'{}.'.format(adjustment, list(ADJUSTMENT_STYLES))
)
oc = self.get_ordered_contracts(root_symbol)
exchange = self._get_root_symbol_exchange(root_symbol)
@@ -1029,37 +1041,26 @@ class AssetFinder(object):
add_sid = _encode_continuous_future_sid(root_symbol, offset,
roll_style,
'add')
mul_cf = ContinuousFuture(mul_sid,
root_symbol,
offset,
roll_style,
oc.start_date,
oc.end_date,
exchange,
'mul')
add_cf = ContinuousFuture(add_sid,
root_symbol,
offset,
roll_style,
oc.start_date,
oc.end_date,
exchange,
'add')
cf = ContinuousFuture(sid,
root_symbol,
offset,
roll_style,
oc.start_date,
oc.end_date,
exchange,
adjustment_children={
'mul': mul_cf,
'add': add_cf
})
cf_template = partial(
ContinuousFuture,
root_symbol=root_symbol,
offset=offset,
roll_style=roll_style,
start_date=oc.start_date,
end_date=oc.end_date,
exchange=exchange,
)
cf = cf_template(sid=sid)
mul_cf = cf_template(sid=mul_sid, adjustment='mul')
add_cf = cf_template(sid=add_sid, adjustment='add')
self._asset_cache[cf.sid] = cf
self._asset_cache[add_cf.sid] = add_cf
self._asset_cache[mul_cf.sid] = mul_cf
return cf
self._asset_cache[add_cf.sid] = add_cf
return {None: cf, 'mul': mul_cf, 'add': add_cf}[adjustment]
def _make_sids(tblattr):
def _(self):
+2
View File
@@ -53,6 +53,8 @@ CHAIN_PREDICATES = {
'PA': partial(delivery_predicate, set(['H', 'M', 'U', 'Z']))
}
ADJUSTMENT_STYLES = {'add', 'mul', None}
cdef class ContinuousFuture:
"""