Skip to content

Commit 8fef0d5

Browse files
committed
[EN-1570] custom listener example
1 parent ec5955f commit 8fef0d5

File tree

2 files changed

+218
-81
lines changed

2 files changed

+218
-81
lines changed

docs/custom_listener.rst

Lines changed: 145 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,144 +3,228 @@
33
Custom listener
44
===============
55

6-
This is the tutorial, how to write custom listener
6+
Since dxfeed v0.4.0, there is another way to implement the logic for
7+
processing incoming events (see Custom Event Handler example).
78

8-
Pipeline
9-
--------
9+
This tutorial is for cases that are not covered by previous tutorials.
1010

11-
1. :ref:`cython-pack`
12-
2. :ref:`Build <build>`
13-
3. :ref:`Import <import>`
11+
Pipeline
12+
~~~~~~~~
1413

15-
.. _cython-pack:
14+
1. Create cython package
15+
2. Build
16+
3. Install
17+
4. Import
18+
5. Use!
1619

1720
Create cython package
18-
---------------------
21+
~~~~~~~~~~~~~~~~~~~~~
1922

2023
**First of all let’s create special directory for custom listener
2124
package**
2225

2326
.. code:: bash
2427
2528
%%bash
26-
rm custom_listener -r
27-
rm ../custom_listener -r
29+
rm custom_listener -rf
2830
mkdir custom_listener
2931
30-
.. code:: ipython3
32+
.. code:: python3
3133
3234
%cd custom_listener
3335
34-
**Next create .pyx file with the whole logic**
36+
37+
.. code:: text
38+
39+
C:\python-api\examples\Low_level_API\custom_listener
40+
41+
42+
Create .pyx file with the whole logic
43+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3544

3645
Here we will write listener for Trade event type that will store only
3746
price and ticker
3847

39-
.. code:: cython
48+
.. code:: python3
4049
4150
%%writefile cust.pyx
4251
from dxfeed.core.listeners.listener cimport *
43-
from dxfeed.core.utils.helpers cimport *
44-
45-
cdef void trade_custom_listener(int event_type, dxf_const_string_t symbol_name,
46-
const dxf_event_data_t* data, int data_count, void* user_data) nogil:
47-
48-
cdef dxf_trade_t* trades = <dxf_trade_t*>data
52+
from dxfeed.core.utils.helpers cimport unicode_from_dxf_const_string_t
53+
from dxfeed.core.utils.handler cimport EventHandler
54+
55+
cdef void trade_custom_listener(int event_type,
56+
dxf_const_string_t symbol_name,
57+
const dxf_event_data_t*data,
58+
int data_count, void*user_data) nogil:
59+
cdef dxf_trade_t*trades = <dxf_trade_t*> data
4960
with gil:
50-
py_data = <dict>user_data
51-
61+
py_data = <EventHandler> user_data
62+
5263
for i in range(data_count):
53-
py_data['data'].append([unicode_from_dxf_const_string_t(symbol_name),
54-
trades[i].price
55-
]
56-
)
57-
64+
py_data.__update([unicode_from_dxf_const_string_t(symbol_name),
65+
trades[i].price])
66+
5867
tc = FuncWrapper.make_from_ptr(trade_custom_listener)
5968
69+
70+
.. code:: text
71+
72+
Writing cust.pyx
73+
74+
6075
.. code:: ipython3
6176
6277
!ls
6378
79+
80+
.. code:: text
81+
82+
cust.pyx
83+
84+
6485
- Line 2 imports all type definitions and function wrapper from
6586
installed dxfeed package
66-
- Line 3 imports helper functions like
67-
``unicode_from_dxf_const_string_t`` in this example
68-
- Lines 5-15 stand for listener logic
69-
- nogil and with gil in lines 6 and 9 are important to prevent data
87+
- Line 3 imports helper function ``unicode_from_dxf_const_string_t``
88+
- Line 4 import EventHandler class
89+
- Lines 6-16 stand for listener logic
90+
- nogil and with gil in lines 9 and 11 are important to prevent data
7091
corruption. More details
7192
`stackoverflow <https://stackoverflow.com/questions/57805481/>`__
72-
- Line 8 converts the data to trades data structure. **It is important
93+
- Line 10 converts the data to trades data structure. **It is important
7394
to know what data structure has each event. This information can be
74-
found in EventData.pxd in the dxpyfeed package folder**
75-
- Line 10 stands for casting user data which is provided by
95+
found in EventData.pxd in the dxfeed package folder**
96+
- Line 12 stands for casting user data which is provided by
7697
subscription
77-
- Lines 12-16 we just append price and symbol to subscription dict
98+
- Lines 14-16 we just append price and symbol to subscription dict
7899
- Line 18, here we wrap function to have access to it from python
79100

80-
**Create setup.py to build the binary file**
101+
Create setup.py to build the binary file
102+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81103

82-
.. code:: cython
104+
.. code:: python3
83105
84106
%%writefile setup.py
85107
from Cython.Build import cythonize
86108
from setuptools import setup, Extension
87-
import dxfeed
88-
109+
from dxfeed.core.utils.helpers import get_include
110+
89111
ext = Extension(name="cust",
90112
sources=["cust.pyx"],
91-
include_dirs=dxfeed.get_include()
113+
include_dirs=get_include()
92114
)
93-
115+
94116
setup(
95117
ext_modules=cythonize([ext], language_level=3)
96118
)
97119
120+
121+
.. code:: text
122+
123+
Writing setup.py
124+
125+
98126
- Line 4 imports dxfeed to get access to ``get_include`` function,
99127
which provide paths to .pxd and .h header files
100128

101-
.. _build:
102-
103129
Build the binary file
104-
---------------------
130+
^^^^^^^^^^^^^^^^^^^^^
105131

106132
.. code:: ipython3
107133
108134
!python setup.py build_ext --inplace
109135
136+
137+
.. code:: text
138+
139+
Compiling cust.pyx because it changed.
140+
[1/1] Cythonizing cust.pyx
141+
running build_ext
142+
building 'cust' extension
143+
creating build
144+
...
145+
Generating code
146+
Finished generating code
147+
copying build\lib.win-amd64-3.7\cust.cp37-win_amd64.pyd ->
148+
149+
110150
.. code:: ipython3
111151
112152
!ls
113153
114-
.. _import:
115154
116-
Import
117-
------
155+
.. code:: text
118156
119-
You can either import extension built on previous step or install your extension as a python package.
157+
build
158+
cust.c
159+
cust.cp37-win_amd64.pyd
160+
cust.pyx
161+
setup.py
162+
120163
121-
.. code:: ipython3
164+
Import necessary modules
165+
~~~~~~~~~~~~~~~~~~~~~~~~
166+
167+
.. code:: python3
122168
123169
import cust
124-
import dxfeed as dx
170+
from dxfeed.core import DXFeedPy as dxc
171+
from dxfeed.core.utils.handler import EventHandler
125172
126-
.. code:: ipython3
173+
Create Custom Event Handler
174+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
127175

128-
con = dx.dxf_create_connection()
129-
sub = dx.dxf_create_subscription(con, 'Trade')
176+
See Custom Event Handler tutorial for more details
130177

131-
Attach custom listener, specifying the columns
178+
.. code:: python3
132179
133-
.. code:: ipython3
180+
class CustomHandler(EventHandler):
181+
def __init__(self):
182+
self.data = list()
183+
184+
def update(self, event):
185+
self.data.append(event)
186+
187+
def get_data(self):
188+
return self.data
134189
135-
dx.dxf_attach_custom_listener(sub, cust.tc, ['Symbol', 'Price'])
136-
dx.dxf_add_symbols(sub, ['AAPL', 'MSFT'])
190+
.. code:: python3
137191
138-
After some time you will get the data.
192+
con = dxc.dxf_create_connection()
193+
sub = dxc.dxf_create_subscription(con, 'Trade')
139194
140-
.. code:: ipython3
195+
Attach custom handler
141196

142-
sub.get_data()
197+
.. code:: python3
143198
144-
.. code:: ipython3
199+
handler = CustomHandler()
200+
sub.set_event_handler(handler)
201+
202+
Attach custom listener
203+
204+
.. code:: python3
205+
206+
dxc.dxf_attach_custom_listener(sub, cust.tc, ['Symbol', 'Price'])
207+
dxc.dxf_add_symbols(sub, ['AAPL', 'MSFT'])
208+
209+
Get data
210+
211+
.. code:: python3
212+
213+
handler.get_data()[-5:]
214+
215+
216+
217+
218+
.. code:: text
219+
220+
[['AAPL', 335.23],
221+
['AAPL', 335.23],
222+
['AAPL', 335.23],
223+
['MSFT', 186.71],
224+
['MSFT', 186.71]]
225+
226+
227+
228+
.. code:: python3
145229
146-
dx.dxf_detach_listener(sub)
230+
dxc.dxf_detach_listener(sub)

0 commit comments

Comments
 (0)