In python an object exposes an event but I can't get at it in PyCall

Hi there

I am working my way through a python script and not sure how to progress. The python code looks like this

def onBarUpdate(bars, hasNewBar):
 
     print( datetime.timestamp(bars[-1].time),"^ ", bars.contract.localSymbol," ^ ",bars.contract.conId," ^ ",bars[-1].close )


if __name__  == '__main__' 
       stock_contract = Stock( row['ib_symbol'] , 'SMART' , 'USD')
       ib.qualifyContracts(stock_contract)
       stock_bars = ib.reqRealTimeBars(stock_contract, 5, 'TRADES', False)
       stock_bars.updateEvent += onBarUpdate

and the current Pluto cells look like this


stock_contract = 
PyObject Stock(symbol='AAPL', exchange='SMART', currency='USD')

from cell

stock_contract = ib_insync.Stock( "AAPL" , "SMART" , "USD")
PyCall.PyObject[

PyObject Stock(conId=265598, symbol='AAPL', exchange='SMART', primaryExchange='NASDAQ', currency='USD', localSymbol='AAPL', tradingClass='NMS')]

from cell

ib.qualifyContracts( stock_contract )
stock_bars is a mutable struct Vector{Any}

from cell

stock_bars = ib.reqRealTimeBars( stock_contract, 5, "TRADES", "False")

and this is where I am stuck

type Array has no field updateEvent

1. <mark> **getproperty** (::Vector{Any}, ::Symbol)</mark>@ *Base.jl:42*
2. <mark> **top-level scope** </mark>@ *[Local: 1](http://localhost:1234/edit?id=6d4e02de-68e4-11ec-0a52-db09eb3824fc#)*

from cell

stock_bars.updateEvent += onBarUpdate

Looking at it from the python side stock_bars should have an updateEvent but I can’t see how to access it in PyCall.

Python side

type(stock_bars)
<class 'ib_insync.objects.RealTimeBarList'>
>>> 

IE

[RealTimeBar(time=datetime.datetime(2021, 12, 29, 20, 47, 40, tzinfo=datetime.timezone.utc), endTime=-1, open_=138.99, high=138.99, low=138.99, close=138.99, volume=0.0, wap=138.99, count=0),
 RealTimeBar(time=datetime.datetime(2021, 12, 29, 20, 47, 45, tzinfo=datetime.timezone.utc), endTime=-1, open_=139.0, high=139.0, low=138.98, close=138.98, volume=5.13, wap=138.9831189083821, count=5),
 RealTimeBar(time=datetime.datetime(2021, 12, 29, 20, 47, 50, tzinfo=datetime.timezone.utc), endTime=-1, open_=138.99, high=138.99, low=138.99, close=138.99, volume=1.0, wap=138.99, count=1)]

=======================
type(stock_contract)
<class 'ib_insync.contract.Stock'>

ie 
stock_contract
Stock(conId=3206042, symbol='YUM', exchange='SMART', primaryExchange='NYSE', currency='USD', localSymbol='YUM', tradingClass='YUM')

======================
type(stock_bars.updateEvent)
<class 'eventkit.event.Event'>

>>> stock_bars.updateEvent
Event<updateEvent, [[None, None, <function onBarUpdate at 0x7f242481d8b0>]]>

==============

type(onBarUpdate)
<class 'function'>


ANY help would be appreciated.

It looks like PyCall is converting this to a Julia Array, but you want to leave it as a raw Python object. You can suppress the conversion with:

stock_bars = pycall(ib.reqRealTimeBars, PyObject, stock_contract, 5, "TRADES", "False")

which specifies that the return type is PyObject. See also the pycall docs

1 Like

thank you once again. Your solution worked in two ways. The cell worked AND I now have an example to work with.

I am struggling with all of this. I did read the pycall docs about PyObject and tried many things to no avail. Now I have a great example to work with I can go back and reread them. Thank you so much for getting me a step closer to getting this working.

I have to admit that I was close to shelving this approach and using ZMQ that you mentioned in another thread. It’s an approach I have used in the past and it works well, not ZMQ but reliable queues. I don’t need any kind of protocol as it’s just a stream of bytes coming down the pipe that I don’t need to validate. That said I’ll keep plugging away at this but it’s hard as I’m having to get to grips with the python oo approach I have avoided to date. The documentation and deployment of insync was so good I could get what I needed done without any real understanding of how it works below the surface. That’s coming back to bite me right now. thanks again