mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-07 14:22:56 +08:00
TST: Adds TestingSlippage slippage model (#1679)
Allows specifying a constant number of shares filled per tick. Also adds the WithConstantEquityMinuteBarData fixture, relocated from internal repo.
This commit is contained in:
@@ -6,12 +6,22 @@ from unittest import TestCase
|
||||
|
||||
from numpy import array, empty
|
||||
|
||||
from zipline._protocol import BarData
|
||||
from zipline.finance.asset_restrictions import NoRestrictions
|
||||
from zipline.finance.order import Order
|
||||
|
||||
from zipline.testing import (
|
||||
check_arrays,
|
||||
make_alternating_boolean_array,
|
||||
make_cascading_boolean_array,
|
||||
parameter_space,
|
||||
)
|
||||
from zipline.testing.fixtures import (
|
||||
WithConstantEquityMinuteBarData,
|
||||
WithDataPortal,
|
||||
ZiplineTestCase,
|
||||
)
|
||||
from zipline.testing.slippage import TestingSlippage
|
||||
from zipline.utils.numpy_utils import bool_dtype
|
||||
|
||||
|
||||
@@ -109,3 +119,57 @@ class TestMakeBooleanArray(TestCase):
|
||||
make_cascading_boolean_array((3, 0)),
|
||||
empty((3, 0), dtype=bool_dtype),
|
||||
)
|
||||
|
||||
|
||||
class TestTestingSlippage(WithConstantEquityMinuteBarData,
|
||||
WithDataPortal,
|
||||
ZiplineTestCase):
|
||||
ASSET_FINDER_EQUITY_SYMBOLS = ('A',)
|
||||
ASSET_FINDER_EQUITY_SIDS = (1,)
|
||||
|
||||
@classmethod
|
||||
def init_class_fixtures(cls):
|
||||
super(TestTestingSlippage, cls).init_class_fixtures()
|
||||
cls.asset = cls.asset_finder.retrieve_asset(1)
|
||||
cls.minute, _ = (
|
||||
cls.trading_calendar.open_and_close_for_session(cls.START_DATE)
|
||||
)
|
||||
|
||||
def init_instance_fixtures(self):
|
||||
super(TestTestingSlippage, self).init_instance_fixtures()
|
||||
self.bar_data = BarData(
|
||||
self.data_portal,
|
||||
lambda: self.minute,
|
||||
"minute",
|
||||
self.trading_calendar,
|
||||
NoRestrictions()
|
||||
)
|
||||
|
||||
def make_order(self, amount):
|
||||
return Order(
|
||||
self.minute,
|
||||
self.asset,
|
||||
amount,
|
||||
)
|
||||
|
||||
def test_constant_filled_per_tick(self):
|
||||
filled_per_tick = 1
|
||||
model = TestingSlippage(filled_per_tick)
|
||||
order = self.make_order(100)
|
||||
|
||||
price, volume = model.process_order(self.bar_data, order)
|
||||
|
||||
self.assertEqual(price, self.EQUITY_MINUTE_CONSTANT_CLOSE)
|
||||
self.assertEqual(volume, filled_per_tick)
|
||||
|
||||
def test_fill_all(self):
|
||||
filled_per_tick = TestingSlippage.ALL
|
||||
order_amount = 100
|
||||
|
||||
model = TestingSlippage(filled_per_tick)
|
||||
order = self.make_order(order_amount)
|
||||
|
||||
price, volume = model.process_order(self.bar_data, order)
|
||||
|
||||
self.assertEqual(price, self.EQUITY_MINUTE_CONSTANT_CLOSE)
|
||||
self.assertEqual(volume, order_amount)
|
||||
|
||||
@@ -1099,6 +1099,37 @@ class WithBcolzFutureMinuteBarReader(WithFutureMinuteBarData, WithTmpDir):
|
||||
BcolzMinuteBarReader(p)
|
||||
|
||||
|
||||
class WithConstantEquityMinuteBarData(WithEquityMinuteBarData):
|
||||
|
||||
EQUITY_MINUTE_CONSTANT_LOW = 3.0
|
||||
EQUITY_MINUTE_CONSTANT_OPEN = 4.0
|
||||
EQUITY_MINUTE_CONSTANT_CLOSE = 5.0
|
||||
EQUITY_MINUTE_CONSTANT_HIGH = 6.0
|
||||
EQUITY_MINUTE_CONSTANT_VOLUME = 100.0
|
||||
|
||||
@classmethod
|
||||
def make_equity_minute_bar_data(cls):
|
||||
trading_calendar = cls.trading_calendars[Equity]
|
||||
|
||||
sids = cls.asset_finder.equities_sids
|
||||
minutes = trading_calendar.minutes_for_sessions_in_range(
|
||||
cls.equity_minute_bar_days[0],
|
||||
cls.equity_minute_bar_days[-1],
|
||||
)
|
||||
frame = pd.DataFrame(
|
||||
{
|
||||
'open': cls.EQUITY_MINUTE_CONSTANT_OPEN,
|
||||
'high': cls.EQUITY_MINUTE_CONSTANT_HIGH,
|
||||
'low': cls.EQUITY_MINUTE_CONSTANT_LOW,
|
||||
'close': cls.EQUITY_MINUTE_CONSTANT_CLOSE,
|
||||
'volume': cls.EQUITY_MINUTE_CONSTANT_VOLUME,
|
||||
},
|
||||
index=minutes,
|
||||
)
|
||||
|
||||
return ((sid, frame) for sid in sids)
|
||||
|
||||
|
||||
class WithAdjustmentReader(WithBcolzEquityDailyBarReader):
|
||||
"""
|
||||
ZiplineTestCase mixin providing cls.adjustment_reader as a class level
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
from zipline.finance.slippage import SlippageModel
|
||||
from zipline.utils.sentinel import sentinel
|
||||
|
||||
|
||||
class TestingSlippage(SlippageModel):
|
||||
"""
|
||||
Slippage model that fills a constant number of shares per tick, for
|
||||
testing purposes.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filled_per_tick : int or TestingSlippage.ALL
|
||||
The number of shares to fill on each call to process_order. If
|
||||
TestingSlippage.ALL is passed, the entire order is filled.
|
||||
|
||||
See also
|
||||
--------
|
||||
zipline.finance.slippage.SlippageModel
|
||||
"""
|
||||
ALL = sentinel('ALL')
|
||||
|
||||
def __init__(self, filled_per_tick):
|
||||
self.filled_per_tick = filled_per_tick
|
||||
|
||||
def process_order(self, data, order):
|
||||
price = data.current(order.asset, "close")
|
||||
if self.filled_per_tick is self.ALL:
|
||||
volume = order.amount
|
||||
else:
|
||||
volume = self.filled_per_tick
|
||||
|
||||
return (price, volume)
|
||||
Reference in New Issue
Block a user