Skip to content

Commit

Permalink
BUG: Exception will be raised when nan value sent to order()
Browse files Browse the repository at this point in the history
Previously order was not checking for nan values sent as
limit or stop prices. It will now raise a runtime exception
in the event that an attempt to order with a nan price is made.
  • Loading branch information
CaptainKanuk committed Aug 25, 2014
1 parent 16d15ed commit d389e38
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 11 deletions.
12 changes: 8 additions & 4 deletions tests/test_execution_styles.py
Expand Up @@ -31,6 +31,10 @@
teardown_logger,
)

from zipline.errors import(
BadOrderParameters
)


class ExecutionStyleTestCase(TestCase):
"""
Expand Down Expand Up @@ -58,7 +62,7 @@ class ExecutionStyleTestCase(TestCase):
for delta in range(1, 10)
]

INVALID_PRICES = [(-1,), (-1.0,), (0 - epsilon,)]
INVALID_PRICES = [(-1,), (-1.0,), (0 - epsilon,), (float('nan'),)]

def setUp(self):
setup_logger(self)
Expand All @@ -72,14 +76,14 @@ def test_invalid_prices(self, price):
Test that execution styles throw appropriate exceptions upon receipt
of an invalid price field.
"""
with self.assertRaises(ValueError):
with self.assertRaises(BadOrderParameters):
LimitOrder(price)

with self.assertRaises(ValueError):
with self.assertRaises(BadOrderParameters):
StopOrder(price)

for lmt, stp in [(price, 1), (1, price), (price, price)]:
with self.assertRaises(ValueError):
with self.assertRaises(BadOrderParameters):
StopLimitOrder(lmt, stp)

def test_market_order_prices(self):
Expand Down
8 changes: 8 additions & 0 deletions zipline/errors.py
Expand Up @@ -137,6 +137,14 @@ class UnsupportedOrderParameters(ZiplineError):
msg = "{msg}"


class BadOrderParameters(ZiplineError):
"""
Raised if any impossible parameters (nan, negative limit/stop)
are passed to an order call.
"""
msg = "{msg}"


class OrderDuringInitialize(ZiplineError):
"""
Raised if order is called during initialize()
Expand Down
46 changes: 39 additions & 7 deletions zipline/finance/execution.py
Expand Up @@ -21,6 +21,10 @@

import zipline.utils.math_utils as zp_math

from math import isnan

from zipline.errors import BadOrderParameters


class ExecutionStyle(with_metaclass(abc.ABCMeta)):
"""
Expand Down Expand Up @@ -77,8 +81,17 @@ def __init__(self, limit_price, exchange=None):
"""
Store the given price.
"""

if isnan(limit_price):
raise BadOrderParameters(
msg="""Attempted to place an order with a limit price that
is NaN."""
)

if limit_price < 0:
raise ValueError("Can't place a limit with a negative price.")
raise BadOrderParameters(
msg="Can't place a limit with a negative price."
)
self.limit_price = limit_price
self._exchange = exchange

Expand All @@ -98,9 +111,16 @@ def __init__(self, stop_price, exchange=None):
"""
Store the given price.
"""

if isnan(stop_price):
raise BadOrderParameters(
msg="""Attempted to place an order with a stop price that
is NaN."""
)

if stop_price < 0:
raise ValueError(
"Can't place a stop order with a negative price."
raise BadOrderParameters(
msg="Can't place a stop order with a negative price."
)
self.stop_price = stop_price
self._exchange = exchange
Expand All @@ -121,13 +141,25 @@ def __init__(self, limit_price, stop_price, exchange=None):
"""
Store the given prices
"""

if isnan(limit_price):
raise BadOrderParameters(
msg="""Attempted to place an order with a limit price that
is NaN."""
)
if isnan(stop_price):
raise BadOrderParameters(
msg="""Attempted to place an order with a stop price that
is NaN."""
)

if limit_price < 0:
raise ValueError(
"Can't place a limit with a negative price."
raise BadOrderParameters(
msg="Can't place a limit with a negative price."
)
if stop_price < 0:
raise ValueError(
"Can't place a stop order with a negative price."
raise BadOrderParameters(
msg="Can't place a stop order with a negative price."
)

self.limit_price = limit_price
Expand Down

0 comments on commit d389e38

Please sign in to comment.