mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-29 06:47:57 +08:00
EHN: Make continuous future adjustment style an argument
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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):
|
||||
|
||||
@@ -53,6 +53,8 @@ CHAIN_PREDICATES = {
|
||||
'PA': partial(delivery_predicate, set(['H', 'M', 'U', 'Z']))
|
||||
}
|
||||
|
||||
ADJUSTMENT_STYLES = {'add', 'mul', None}
|
||||
|
||||
|
||||
cdef class ContinuousFuture:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user