nautechsystems / nautilus_trader

A high-performance algorithmic trading platform and event-driven backtester
https://nautilustrader.io
GNU Lesser General Public License v3.0
2.15k stars 483 forks source link

handle_instrument_response - Cannot convert list to Instrument #826

Closed SeverinJB closed 2 years ago

SeverinJB commented 2 years ago

Bug Report

Hi everybody - It looks like there is an issue with the actor's handle_instrument_response function. Let me know if I should be missing something!

Expected Behavior

The handle_instrument_response function can handle a list as the data engine requires the instrument to be wrapped in a list.

Screenshot 2022-10-25 at 17 02 21

Actual Behavior

TypeError when passing an instrument wrapped by a list. See the below:

/*/nautilus_trader/nautilus_trader/live/node.py:347: UserWarning: on_dispose was called when not overridden
  self.kernel.trader.dispose()
Traceback (most recent call last):
  File "/*/yuzu_nautilus/minimal_example_adapter.py", line 71, in <module>
    node.start()
  File "/*/nautilus_trader/nautilus_trader/live/node.py", line 288, in start
    self.kernel.loop.run_until_complete(self._run())
  File "uvloop/loop.pyx", line 1517, in uvloop.loop.Loop.run_until_complete
  File "/*/nautilus_trader/nautilus_trader/live/node.py", line 467, in _run
    await self.kernel.data_engine.get_run_queue_task()
  File "nautilus_trader/live/data_engine.pyx", line 331, in _run_message_queue
  File "nautilus_trader/data/engine.pyx", line 1169, in nautilus_trader.data.engine.DataEngine._handle_response
  File "nautilus_trader/msgbus/bus.pyx", line 301, in nautilus_trader.msgbus.bus.MessageBus.response
  File "nautilus_trader/common/actor.pyx", line 2032, in nautilus_trader.common.actor.Actor._handle_instrument_response
  File "nautilus_trader/common/actor.pyx", line 2033, in nautilus_trader.common.actor.Actor._handle_instrument_response
TypeError: Cannot convert list to nautilus_trader.model.instruments.base.Instrument

However, equally, we are getting an error when the list does not wrap the instrument as the data engine expects a list:

/*/nautilus_trader/nautilus_trader/live/node.py:347: UserWarning: on_dispose was called when not overridden
  self.kernel.trader.dispose()
Traceback (most recent call last):
  File "/*/yuzu_nautilus/minimal_example_adapter.py", line 71, in <module>
    node.start()
  File "/*/nautilus_trader/nautilus_trader/live/node.py", line 288, in start
    self.kernel.loop.run_until_complete(self._run())
  File "uvloop/loop.pyx", line 1517, in uvloop.loop.Loop.run_until_complete
  File "/Users/SeverinBurg/Documents/GitHub/nautilus_trader/nautilus_trader/live/node.py", line 467, in _run
    await self.kernel.data_engine.get_run_queue_task()
  File "nautilus_trader/live/data_engine.pyx", line 331, in _run_message_queue
  File "nautilus_trader/data/engine.pyx", line 1161, in nautilus_trader.data.engine.DataEngine._handle_response
TypeError: Expected list, got nautilus_trader.model.instruments.equity.Equity

Steps to Reproduce the Problem

  1. Create instances of Instrument, DataType and UUID4
  2. Use the above to call self._handle_data_response(DataType, [Instrument], UUID4)
  3. See error message

Specifications

cjdsellers commented 2 years ago

Hi @SeverinJB

You're quite right, the Actor was lacking a dedicated handler for instrument lists.

I've now added a request_instruments method to the Actor which also takes a venue (in case the data client handles multiple venues).

Since it looks like you're writing your own adapter, I've also added these convenience methods:

def _handle_instrument_py(self, Instrument instrument, UUID4 correlation_id) 
def _handle_instruments_py(self, Venue venue, list instruments, UUID4 correlation_id)

cpdef void _handle_instrument(self, Instrument instrument, UUID4 correlation_id) except *
cpdef void _handle_instruments(self, Venue venue, list instruments, UUID4 correlation_id) except *

I've also covered the new code paths with tests d6ddbedf1ebd64e53779a6985d9b3acadc4d027a.

Thanks for much for the detailed report, and please let me know if this works for you.

SeverinJB commented 2 years ago

Hi @cjdsellers,

Thank you for looking into this so swiftly!

I checked out the develop branch, built it with poetry install --no-dev and then used pip install -e . to install it in a clean conda environment, but I am getting this error whenever I try running the program:

<frozen importlib._bootstrap>:241: RuntimeWarning: nautilus_trader.common.clock.LiveClock size changed, may indicate binary incompatibility. Expected 288 from C header, got 312 from PyObject
Traceback (most recent call last):
  File "/*/GitHub/nautilus_trader/examples/live/alpaca_scalping_strategy.py", line 22, in <module>
    from nautilus_trader.live.node import TradingNode
  File "/*/GitHub/nautilus_trader/nautilus_trader/live/node.py", line 38, in <module>
    from nautilus_trader.system.kernel import NautilusKernel
  File "nautilus_trader/system/kernel.pyx", line 1, in init nautilus_trader.system.kernel
ValueError: nautilus_trader.execution.messages.SubmitOrder size changed, may indicate binary incompatibility. Expected 104 from C header, got 96 from PyObject

I am sorry, but I don't have much experience with Cython and Rust. It looks like there is a problem with the built binaries, but I am not sure what I am doing wrong and how to fix it.

Do you have a tip?

cjdsellers commented 2 years ago

So it looks like you have an old extension module in play there, for a truly clean build I would recommend this, with the caveat that its going to take everything which isn't tracked by git:

make clean build

I see you must be on an older version of develop which still has a kernel.pyx.

I'd also recommend if you're working from source you stay on the head of develop to pick up any bug fixes.

Hope that helps!

SeverinJB commented 2 years ago

Thank you, @cjdsellers! This did the trick.