Skip to content

Commit

Permalink
MAINT: batch_order_target_percent -> batch_market_order.
Browse files Browse the repository at this point in the history
The only downstream contex that was using batch_order_target_percent
already had all necessary prices, so calling batch_order_target_percent
was wasteful.
  • Loading branch information
Scott Sanderson committed May 9, 2017
1 parent 3650220 commit d653820
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 67 deletions.
45 changes: 21 additions & 24 deletions tests/test_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@
TestTargetAlgorithm,
TestTargetPercentAlgorithm,
TestTargetValueAlgorithm,
TestBatchTargetPercentAlgorithm,
SetLongOnlyAlgorithm,
SetAssetDateBoundsAlgorithm,
SetMaxPositionSizeAlgorithm,
Expand Down Expand Up @@ -963,7 +962,6 @@ def test_order_rounding(self):
('order_percent', TestOrderPercentAlgorithm,),
('order_target_percent', TestTargetPercentAlgorithm,),
('order_target_value', TestTargetValueAlgorithm,),
('batch_order_target_percent', TestBatchTargetPercentAlgorithm,),
])
def test_order_methods(self, test_name, algo_class):
algo = algo_class(
Expand Down Expand Up @@ -1809,16 +1807,16 @@ def test_order_methods(self):
)
test_algo.run(self.data_portal)

def test_batch_order_target_percent_matches_multi_order(self):
weights = pd.Series([.3, .7])
def test_batch_market_order_matches_multiple_manual_orders(self):
share_counts = pd.Series([50, 100])

multi_blotter = RecordBatchBlotter(self.SIM_PARAMS_DATA_FREQUENCY)
multi_test_algo = TradingAlgorithm(
script=dedent("""\
from collections import OrderedDict
from six import iteritems
from zipline.api import sid, order_target_percent
from zipline.api import sid, order
def initialize(context):
Expand All @@ -1827,14 +1825,14 @@ def initialize(context):
def handle_data(context, data):
if not context.placed:
for asset, weight in iteritems(OrderedDict(zip(
context.assets, {weights}
for asset, shares in iteritems(OrderedDict(zip(
context.assets, {share_counts}
))):
order_target_percent(asset, weight)
order(asset, shares)
context.placed = True
""").format(weights=list(weights)),
""").format(share_counts=list(share_counts)),
blotter=multi_blotter,
env=self.env,
)
Expand All @@ -1844,9 +1842,9 @@ def handle_data(context, data):
batch_blotter = RecordBatchBlotter(self.SIM_PARAMS_DATA_FREQUENCY)
batch_test_algo = TradingAlgorithm(
script=dedent("""\
from collections import OrderedDict
import pandas as pd
from zipline.api import sid, batch_order_target_percent
from zipline.api import sid, batch_market_order
def initialize(context):
Expand All @@ -1855,17 +1853,17 @@ def initialize(context):
def handle_data(context, data):
if not context.placed:
orders = batch_order_target_percent(OrderedDict(zip(
context.assets, {weights}
)))
orders = batch_market_order(pd.Series(
index=context.assets, data={share_counts}
))
assert len(orders) == 2, \
"len(orders) was %s but expected 2" % len(orders)
for o in orders:
assert o is not None, "An order is None"
context.placed = True
""").format(weights=list(weights)),
""").format(share_counts=list(share_counts)),
blotter=batch_blotter,
env=self.env,
)
Expand All @@ -1881,34 +1879,33 @@ def handle_data(context, data):
)
assert_equal(multi_stats, batch_stats)

def test_batch_order_target_percent_filters_null_orders(self):
weights = pd.Series([1, 0])
def test_batch_market_order_filters_null_orders(self):
share_counts = [50, 0]

batch_blotter = RecordBatchBlotter(self.SIM_PARAMS_DATA_FREQUENCY)
batch_test_algo = TradingAlgorithm(
script=dedent("""\
from collections import OrderedDict
from zipline.api import sid, batch_order_target_percent
import pandas as pd
from zipline.api import sid, batch_market_order
def initialize(context):
context.assets = [sid(0), sid(3)]
context.placed = False
def handle_data(context, data):
if not context.placed:
orders = batch_order_target_percent(OrderedDict(zip(
context.assets, {weights}
)))
orders = batch_market_order(pd.Series(
index=context.assets, data={share_counts}
))
assert len(orders) == 1, \
"len(orders) was %s but expected 1" % len(orders)
for o in orders:
assert o is not None, "An order is None"
context.placed = True
""").format(weights=list(weights)),
""").format(share_counts=share_counts),
blotter=batch_blotter,
env=self.env,
)
Expand Down
47 changes: 18 additions & 29 deletions zipline/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from collections import Iterable
try:
# optional cython based OrderedDict
from cyordereddict import OrderedDict
except ImportError:
from collections import OrderedDict
from copy import copy
import operator as op
import warnings
Expand All @@ -38,7 +33,6 @@
itervalues,
string_types,
viewkeys,
viewvalues,
)

from zipline._protocol import handle_non_market_minutes
Expand Down Expand Up @@ -107,9 +101,11 @@
coerce_string,
ensure_upper_case,
error_keywords,
expect_dtypes,
expect_types,
optional,
)
from zipline.utils.numpy_utils import int64_dtype
from zipline.utils.calendars.trading_calendar import days_at_time
from zipline.utils.cache import CachedObject, Expired
from zipline.utils.calendars import get_calendar
Expand Down Expand Up @@ -2039,35 +2035,28 @@ def _calculate_order_target_percent_amount(self, asset, target):
return self._calculate_order_target_amount(asset, target_amount)

@api_method
@disallowed_in_before_trading_start(OrderInBeforeTradingStart())
def batch_order_target_percent(self, weights):
"""Place orders towards a given portfolio of weights.
@expect_types(share_counts=pd.Series)
@expect_dtypes(share_counts=int64_dtype)
def batch_market_order(self, share_counts):
"""Place a batch market order for multiple assets.
Parameters
----------
weights : collections.Mapping[Asset -> float]
share_counts : pd.Series[Asset -> int]
Map from asset to number of shares to order for that asset.
Returns
-------
order_ids : pd.Series[Asset -> str]
The unique identifiers for the orders that were placed.
See Also
--------
:func:`zipline.api.order_target_percent`
"""
order_args = OrderedDict()
for asset, target in iteritems(weights):
if self._can_order_asset(asset):
amount = self._calculate_order_target_percent_amount(
asset, target,
)
amount, style = self._calculate_order(asset, amount)
order_args[asset] = (asset, amount, style)

order_ids = self.blotter.batch_order(viewvalues(order_args))
order_ids = pd.Series(data=order_ids, index=order_args)
return order_ids[~order_ids.isnull()]
order_ids : pd.Index[str]
Index of ids for newly-created orders.
"""
style = MarketOrder()
order_args = [
(asset, amount, style)
for (asset, amount) in iteritems(share_counts)
if amount
]
return self.blotter.batch_order(order_args)

@error_keywords(sid='Keyword argument `sid` is no longer supported for '
'get_open_orders. Use `asset` instead.')
Expand Down
15 changes: 6 additions & 9 deletions zipline/api.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,18 @@ def attach_pipeline(pipeline, name, chunks=None):
:func:`zipline.api.pipeline_output`
"""

def batch_order_target_percent(weights):
"""Place orders towards a given portfolio of weights.
def batch_market_order(share_counts):
"""Place a batch market order for multiple assets.
Parameters
----------
weights : collections.Mapping[Asset -> float]
share_counts : pd.Series[Asset -> int]
Map from asset to number of shares to order for that asset.
Returns
-------
order_ids : pd.Series[Asset -> str]
The unique identifiers for the orders that were placed.
See Also
--------
:func:`zipline.api.order_target_percent`
order_ids : pd.Index[str]
Index of ids for newly-created orders.
"""

def cancel_order(order_param):
Expand Down
5 changes: 0 additions & 5 deletions zipline/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,6 @@ def _order(self, asset, target):
return self.order_target_percent(asset, target)


class TestBatchTargetPercentAlgorithm(TestTargetPercentAlgorithm):
def _order(self, asset, target):
return self.batch_order_target_percent({asset: target})


class TestTargetValueAlgorithm(TradingAlgorithm):
def initialize(self):
self.set_slippage(FixedSlippage())
Expand Down

0 comments on commit d653820

Please sign in to comment.