mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-30 00:47:22 +08:00
ENH: Allow override of order amount rounding. (#1722)
* ENH: Use regular rounding to calculate order amounts. We previously tried to prevent accidental over-ordering by truncating orders down unless they were within 1e-4 of the next higher integer. Unfortunately, this makes it easy for a sell order to be one share short of the desired position. Using regular rounding treats both buys and sells in the same way. * ENH keep non-rounding behavior consistent, but leave code structured to make easier to override * DOC make round_order public and describe behavior in docstring
This commit is contained in:
committed by
Paul Sutherland
parent
39188b393c
commit
6cf81a3f1c
@@ -907,6 +907,27 @@ def before_trading_start(context, data):
|
||||
)
|
||||
self.assertEqual(algo.sim_params.data_frequency, 'minute')
|
||||
|
||||
def test_order_rounding(self):
|
||||
answer_key = [
|
||||
(0, 0),
|
||||
(10, 10),
|
||||
(1.1, 1),
|
||||
(1.5, 1),
|
||||
(1.9998, 1),
|
||||
(1.99991, 2),
|
||||
]
|
||||
|
||||
for input, answer in answer_key:
|
||||
self.assertEqual(
|
||||
answer,
|
||||
TradingAlgorithm.round_order(input)
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
-1 * answer,
|
||||
TradingAlgorithm.round_order(-1 * input)
|
||||
)
|
||||
|
||||
@parameterized.expand([
|
||||
('order', TestOrderAlgorithm,),
|
||||
('order_value', TestOrderValueAlgorithm,),
|
||||
|
||||
+14
-5
@@ -131,7 +131,7 @@ from zipline.utils.events import (
|
||||
from zipline.utils.factory import create_simulation_parameters
|
||||
from zipline.utils.math_utils import (
|
||||
tolerant_equals,
|
||||
round_if_near_integer
|
||||
round_if_near_integer,
|
||||
)
|
||||
from zipline.utils.pandas_utils import clear_dataframe_indexer_caches
|
||||
from zipline.utils.preprocess import preprocess
|
||||
@@ -1422,10 +1422,7 @@ class TradingAlgorithm(object):
|
||||
|
||||
def _calculate_order(self, asset, amount,
|
||||
limit_price=None, stop_price=None, style=None):
|
||||
# Truncate to the integer share count that's either within .0001 of
|
||||
# amount or closer to zero.
|
||||
# E.g. 3.9999 -> 4.0; 5.5 -> 5.0; -5.5 -> -5.0
|
||||
amount = int(round_if_near_integer(amount))
|
||||
amount = self.round_order(amount)
|
||||
|
||||
# Raises a ZiplineError if invalid parameters are detected.
|
||||
self.validate_order_params(asset,
|
||||
@@ -1441,6 +1438,18 @@ class TradingAlgorithm(object):
|
||||
style)
|
||||
return amount, style
|
||||
|
||||
@staticmethod
|
||||
def round_order(amount):
|
||||
"""
|
||||
Convert number of shares to an integer.
|
||||
|
||||
By default, truncates to the integer share count that's either within
|
||||
.0001 of amount or closer to zero.
|
||||
|
||||
E.g. 3.9999 -> 4.0; 5.5 -> 5.0; -5.5 -> -5.0
|
||||
"""
|
||||
return int(round_if_near_integer(amount))
|
||||
|
||||
def validate_order_params(self,
|
||||
asset,
|
||||
amount,
|
||||
|
||||
Reference in New Issue
Block a user