Skip to content

Commit

Permalink
1.107.1
Browse files Browse the repository at this point in the history
See release notes in RELEASE.md
  • Loading branch information
cjdsellers authored Mar 7, 2021
2 parents 9e2924e + 22c8bd2 commit 849e2a1
Show file tree
Hide file tree
Showing 12 changed files with 545 additions and 166 deletions.
42 changes: 42 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## NautilusTrader 1.107.0 Beta - Release Notes

The main thrust of this release is to refine some subtleties relating to order
matching and amendment behaviour for improved realism. This involved a fairly substantial refactoring
of `SimulatedExchange` to manage its complexity, and support extending the order types.

The `post_only` flag for LIMIT orders now results in the expected behaviour regarding
when a marketable limit order will become a liquidity `TAKER` during order placement
and amendment.

Test coverage was moderately increased.

### Breaking Changes
None

### Enhancements
- Refactored `SimulatedExchange` order matching and amendment logic.
- Add `risk` sub-package to group risk components.

### Fixes
- `StopLimitOrder` triggering behaviour.
- All flake8 warnings.

## NautilusTrader 1.106.0 Beta - Release Notes

The main thrust of this release is to introduce the Interactive Brokers
integration, and begin adding platform capabilities to support this effort.

### Breaking Changes
- `from_serializable_string` methods changed to `from_serializable_str`.

### Enhancements
- Scaffold Interactive Brokers integration in `adapters/ib`.
- Add the `Future` instrument type.
- Add the `StopLimitOrder` order type.
- Add the `Data` and `DataType` types to support custom data handling.
- Add the `Security` identifier types initial implementation to support extending the platforms capabilities.

### Fixes
- `BracketOrder` correctness.
- CCXT precision parsing bug.
- Some log formatting.
40 changes: 8 additions & 32 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,18 @@
# NautilusTrader 1.107.0 Beta Release Notes
## NautilusTrader 1.107.1 Beta - Release Notes

The main thrust of this release is to refine some subtleties relating to order
matching and amendment behaviour for improved realism. This involved a fairly substantial refactoring
of `SimulatedExchange` to manage its complexity, and support extending the order types.
This is a patch release which applies various fixes and refactorings.

The `post_only` flag for LIMIT orders now results in the expected behaviour regarding
when a marketable limit order will become a liquidity `TAKER` during order placement
and amendment.

Test coverage was moderately increased.
The behaviour of the `StopLimitOrder` continued to be fixed and refined.
`SimulatedExchange` was refactored further to reduce complexity.

### Breaking Changes
None

### Enhancements
- Refactored `SimulatedExchange` order matching and amendment logic.
- Add `risk` sub-package to group risk components.
None

### Fixes
- `TRIGGERED` states in order FSM.
- `StopLimitOrder` triggering behaviour.
- All flake8 warnings.

# NautilusTrader 1.106.0 Beta Release Notes

The main thrust of this release is to introduce the Interactive Brokers
integration, and begin adding platform capabilities to support this effort.

### Breaking Changes
- `from_serializable_string` methods changed to `from_serializable_str`.

### Enhancements
- Scaffold Interactive Brokers integration in `adapters/ib`.
- Add the `Future` instrument type.
- Add the `StopLimitOrder` order type.
- Add the `Data` and `DataType` types to support custom data handling.
- Add the `Security` identifier types initial implementation to support extending the platforms capabilities.

### Fixes
- `BracketOrder` correctness.
- CCXT precision parsing bug.
- Some log formatting.
- `OrderFactory.stop_limit` missing `post_only` and `hidden`.
- `Order` and `StopLimitOrder` `__repr__` string (duplicate id).
32 changes: 20 additions & 12 deletions docs/source/api_reference/backtest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@ Backtest

.. automodule:: nautilus_trader.backtest

Data Client
-----------

Config
------
.. automodule:: nautilus_trader.backtest.data_client
:show-inheritance:
:inherited-members:
:members:
:member-order: bysource

Data Container
--------------

.. automodule:: nautilus_trader.backtest.config
.. automodule:: nautilus_trader.backtest.data_container
:show-inheritance:
:inherited-members:
:members:
:member-order: bysource

Data
----
Data Producer
-------------

.. automodule:: nautilus_trader.backtest.data
.. automodule:: nautilus_trader.backtest.data_producer
:show-inheritance:
:inherited-members:
:members:
Expand Down Expand Up @@ -58,19 +66,19 @@ Loaders
:members:
:member-order: bysource

Logging
-------
Models
------

.. automodule:: nautilus_trader.backtest.logging
.. automodule:: nautilus_trader.backtest.models
:show-inheritance:
:inherited-members:
:members:
:member-order: bysource

Models
------
Modules
-------

.. automodule:: nautilus_trader.backtest.models
.. automodule:: nautilus_trader.backtest.modules
:show-inheritance:
:inherited-members:
:members:
Expand Down
87 changes: 38 additions & 49 deletions nautilus_trader/backtest/exchange.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ from nautilus_trader.model.c_enums.liquidity_side cimport LiquiditySide
from nautilus_trader.model.c_enums.oms_type cimport OMSType
from nautilus_trader.model.c_enums.order_side cimport OrderSide
from nautilus_trader.model.c_enums.order_side cimport OrderSideParser
from nautilus_trader.model.c_enums.order_state cimport OrderState
from nautilus_trader.model.c_enums.order_type cimport OrderType
from nautilus_trader.model.c_enums.price_type cimport PriceType
from nautilus_trader.model.commands cimport AmendOrder
Expand Down Expand Up @@ -499,10 +498,6 @@ cdef class SimulatedExchange:
self.exec_client.handle_event(accepted)

cdef inline void _reject_order(self, Order order, str reason) except *:
if order.state_c() != OrderState.SUBMITTED:
self._log.error(f"Cannot reject order: state was {order.state_string_c()}.")
return

# Generate event
cdef OrderRejected rejected = OrderRejected(
self.exec_client.account_id,
Expand Down Expand Up @@ -537,17 +532,8 @@ cdef class SimulatedExchange:
)
return # Cannot amend order

cdef Price bid = self._market_bids.get(order.symbol)
cdef Price ask = self._market_asks.get(order.symbol)

# Check market exists
if bid is None or ask is None: # Market not initialized
self._cancel_reject(
cl_ord_id,
"amend order",
f"no market for {order.symbol}",
)
return # Cannot amend order
cdef Price bid = self._market_bids[order.symbol] # Market must exist
cdef Price ask = self._market_asks[order.symbol] # Market must exist

if order.type == OrderType.LIMIT:
self._amend_limit_order(order, qty, price, bid, ask)
Expand Down Expand Up @@ -689,7 +675,7 @@ cdef class SimulatedExchange:
raise RuntimeError(f"Invalid order type")

cdef inline void _process_market_order(self, MarketOrder order, Price bid, Price ask) except *:
self._accept_order(order) # Some exchanges just immediately fill
self._accept_order(order)

# Immediately fill marketable order
self._fill_order(
Expand All @@ -703,7 +689,7 @@ cdef class SimulatedExchange:
if self._is_limit_marketable(order.side, order.price, bid, ask):
self._reject_order(
order,
f"{OrderSideParser.to_str(order.side)} POST_ONLY LIMIT order "
f"POST_ONLY LIMIT {OrderSideParser.to_str(order.side)} order "
f"limit px of {order.price} would have been a TAKER: bid={bid}, ask={ask}",
)
return # Invalid price
Expand All @@ -722,8 +708,8 @@ cdef class SimulatedExchange:
if self._is_stop_marketable(order.side, order.price, bid, ask):
self._reject_order(
order,
f"{OrderSideParser.to_str(order.side)} STOP order "
f"px of {order.price} was in the market: bid={bid}, ask={ask}",
f"STOP {OrderSideParser.to_str(order.side)} order "
f"stop px of {order.price} was in the market: bid={bid}, ask={ask}",
)
return # Invalid price

Expand All @@ -735,8 +721,8 @@ cdef class SimulatedExchange:
if self._is_stop_marketable(order.side, order.trigger, bid, ask):
self._reject_order(
order,
f"{OrderSideParser.to_str(order.side)} STOP_LIMIT order "
f"trigger px of {order.trigger} was in the market: bid={bid}, ask={ask}",
f"STOP_LIMIT {OrderSideParser.to_str(order.side)} order "
f"trigger stop px of {order.trigger} was in the market: bid={bid}, ask={ask}",
)
return # Invalid price

Expand All @@ -758,8 +744,8 @@ cdef class SimulatedExchange:
self._cancel_reject(
order.cl_ord_id,
"amend order",
f"{OrderSideParser.to_str(order.side)} POST_ONLY LIMIT order "
f"amended limit px of {price} would have been TAKER: bid={bid}, ask={ask}",
f"POST_ONLY LIMIT {OrderSideParser.to_str(order.side)} order "
f"amended limit px of {price} would have been a TAKER: bid={bid}, ask={ask}",
)
return # Cannot amend order
else:
Expand All @@ -784,7 +770,7 @@ cdef class SimulatedExchange:
self._cancel_reject(
order.cl_ord_id,
"amend order",
f"{OrderSideParser.to_str(order.side)} STOP order "
f"STOP {OrderSideParser.to_str(order.side)} order "
f"amended stop px of {price} was in the market: bid={bid}, ask={ask}",
)
return # Cannot amend order
Expand All @@ -806,7 +792,7 @@ cdef class SimulatedExchange:
self._cancel_reject(
order.cl_ord_id,
"amend order",
f"{OrderSideParser.to_str(order.side)} STOP_LIMIT order "
f"STOP_LIMIT {OrderSideParser.to_str(order.side)} order "
f"amended stop px trigger of {price} was in the market: bid={bid}, ask={ask}",
)
return # Cannot amend order
Expand All @@ -819,8 +805,8 @@ cdef class SimulatedExchange:
self._cancel_reject(
order.cl_ord_id,
"amend order",
f"{OrderSideParser.to_str(order.side)} POST_ONLY LIMIT order "
f"amended limit px of {price} would have been TAKER: bid={bid}, ask={ask}",
f"POST_ONLY LIMIT {OrderSideParser.to_str(order.side)} order "
f"amended limit px of {price} would have been a TAKER: bid={bid}, ask={ask}",
)
return # Cannot amend order
else:
Expand Down Expand Up @@ -873,33 +859,36 @@ cdef class SimulatedExchange:
self._fill_order(
order,
self._fill_price_stop(order.symbol, order.side, order.price),
LiquiditySide.TAKER,
LiquiditySide.TAKER, # Triggered stop places market order
)

cdef inline void _match_stop_limit_order(self, StopLimitOrder order, Price bid, Price ask) except *:
if not order.is_triggered:
if order.is_triggered:
if self._is_limit_matched(order.side, order.price, bid, ask):
self._fill_order(
order,
order.price, # Price is 'guaranteed' (negative slippage not currently modeled)
LiquiditySide.MAKER, # Providing liquidity
)
else: # Order not triggered
if self._is_stop_triggered(order.side, order.trigger, bid, ask):
self._trigger_order(order)

# Check for immediate fill
if self._is_limit_marketable(order.side, order.price, bid, ask):
if order.is_post_only: # Would be liquidity taker
del self._working_orders[order.cl_ord_id] # Remove order from working orders
self._reject_order(order, "post-only order would have been TAKER")
else:
self._fill_order(
order,
self._fill_price_taker(order.symbol, order.side, bid, ask),
LiquiditySide.TAKER, # Immediate fill takes liquidity
)
return # Triggered, rejected or filled

if self._is_limit_matched(order.side, order.price, bid, ask):
self._fill_order(
order,
order.price, # Price is 'guaranteed' (negative slippage not currently modeled)
LiquiditySide.MAKER, # Providing liquidity
)
# Check for immediate fill
if self._is_limit_marketable(order.side, order.price, bid, ask):
if order.is_post_only: # Would be liquidity taker
del self._working_orders[order.cl_ord_id] # Remove order from working orders
self._reject_order(
order,
f"POST_ONLY LIMIT {OrderSideParser.to_str(order.side)} order "
f"limit px of {order.price} would have been a TAKER: bid={bid}, ask={ask}",
)
else:
self._fill_order(
order,
self._fill_price_taker(order.symbol, order.side, bid, ask),
LiquiditySide.TAKER, # Immediate fill takes liquidity
)

cdef inline bint _is_limit_marketable(self, OrderSide side, Price order_price, Price bid, Price ask) except *:
if side == OrderSide.BUY:
Expand Down
2 changes: 2 additions & 0 deletions nautilus_trader/common/factories.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ cdef class OrderFactory:
Price trigger,
TimeInForce time_in_force=*,
datetime expire_time=*,
bint post_only=*,
bint reduce_only=*,
bint hidden=*,
)

cpdef BracketOrder bracket(
Expand Down
Loading

0 comments on commit 849e2a1

Please sign in to comment.