|
3 | 3 | Custom listener |
4 | 4 | =============== |
5 | 5 |
|
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). |
7 | 8 |
|
8 | | -Pipeline |
9 | | --------- |
| 9 | +This tutorial is for cases that are not covered by previous tutorials. |
10 | 10 |
|
11 | | -1. :ref:`cython-pack` |
12 | | -2. :ref:`Build <build>` |
13 | | -3. :ref:`Import <import>` |
| 11 | +Pipeline |
| 12 | +~~~~~~~~ |
14 | 13 |
|
15 | | -.. _cython-pack: |
| 14 | +1. Create cython package |
| 15 | +2. Build |
| 16 | +3. Install |
| 17 | +4. Import |
| 18 | +5. Use! |
16 | 19 |
|
17 | 20 | Create cython package |
18 | | ---------------------- |
| 21 | +~~~~~~~~~~~~~~~~~~~~~ |
19 | 22 |
|
20 | 23 | **First of all let’s create special directory for custom listener |
21 | 24 | package** |
22 | 25 |
|
23 | 26 | .. code:: bash |
24 | 27 |
|
25 | 28 | %%bash |
26 | | - rm custom_listener -r |
27 | | - rm ../custom_listener -r |
| 29 | + rm custom_listener -rf |
28 | 30 | mkdir custom_listener |
29 | 31 |
|
30 | | -.. code:: ipython3 |
| 32 | +.. code:: python3 |
31 | 33 |
|
32 | 34 | %cd custom_listener |
33 | 35 |
|
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 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
35 | 44 |
|
36 | 45 | Here we will write listener for Trade event type that will store only |
37 | 46 | price and ticker |
38 | 47 |
|
39 | | -.. code:: cython |
| 48 | +.. code:: python3 |
40 | 49 |
|
41 | 50 | %%writefile cust.pyx |
42 | 51 | 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 |
49 | 60 | with gil: |
50 | | - py_data = <dict>user_data |
51 | | -
|
| 61 | + py_data = <EventHandler> user_data |
| 62 | + |
52 | 63 | 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 | + |
58 | 67 | tc = FuncWrapper.make_from_ptr(trade_custom_listener) |
59 | 68 |
|
| 69 | +
|
| 70 | +.. code:: text |
| 71 | +
|
| 72 | + Writing cust.pyx |
| 73 | + |
| 74 | +
|
60 | 75 | .. code:: ipython3 |
61 | 76 |
|
62 | 77 | !ls |
63 | 78 |
|
| 79 | +
|
| 80 | +.. code:: text |
| 81 | +
|
| 82 | + cust.pyx |
| 83 | + |
| 84 | +
|
64 | 85 | - Line 2 imports all type definitions and function wrapper from |
65 | 86 | 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 |
70 | 91 | corruption. More details |
71 | 92 | `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 |
73 | 94 | 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 |
76 | 97 | 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 |
78 | 99 | - Line 18, here we wrap function to have access to it from python |
79 | 100 |
|
80 | | -**Create setup.py to build the binary file** |
| 101 | +Create setup.py to build the binary file |
| 102 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
81 | 103 |
|
82 | | -.. code:: cython |
| 104 | +.. code:: python3 |
83 | 105 |
|
84 | 106 | %%writefile setup.py |
85 | 107 | from Cython.Build import cythonize |
86 | 108 | from setuptools import setup, Extension |
87 | | - import dxfeed |
88 | | -
|
| 109 | + from dxfeed.core.utils.helpers import get_include |
| 110 | + |
89 | 111 | ext = Extension(name="cust", |
90 | 112 | sources=["cust.pyx"], |
91 | | - include_dirs=dxfeed.get_include() |
| 113 | + include_dirs=get_include() |
92 | 114 | ) |
93 | | -
|
| 115 | + |
94 | 116 | setup( |
95 | 117 | ext_modules=cythonize([ext], language_level=3) |
96 | 118 | ) |
97 | 119 |
|
| 120 | +
|
| 121 | +.. code:: text |
| 122 | +
|
| 123 | + Writing setup.py |
| 124 | + |
| 125 | +
|
98 | 126 | - Line 4 imports dxfeed to get access to ``get_include`` function, |
99 | 127 | which provide paths to .pxd and .h header files |
100 | 128 |
|
101 | | -.. _build: |
102 | | - |
103 | 129 | Build the binary file |
104 | | ---------------------- |
| 130 | +^^^^^^^^^^^^^^^^^^^^^ |
105 | 131 |
|
106 | 132 | .. code:: ipython3 |
107 | 133 |
|
108 | 134 | !python setup.py build_ext --inplace |
109 | 135 |
|
| 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 | +
|
110 | 150 | .. code:: ipython3 |
111 | 151 |
|
112 | 152 | !ls |
113 | 153 |
|
114 | | -.. _import: |
115 | 154 |
|
116 | | -Import |
117 | | ------- |
| 155 | +.. code:: text |
118 | 156 |
|
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 | + |
120 | 163 |
|
121 | | -.. code:: ipython3 |
| 164 | +Import necessary modules |
| 165 | +~~~~~~~~~~~~~~~~~~~~~~~~ |
| 166 | + |
| 167 | +.. code:: python3 |
122 | 168 |
|
123 | 169 | import cust |
124 | | - import dxfeed as dx |
| 170 | + from dxfeed.core import DXFeedPy as dxc |
| 171 | + from dxfeed.core.utils.handler import EventHandler |
125 | 172 |
|
126 | | -.. code:: ipython3 |
| 173 | +Create Custom Event Handler |
| 174 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
127 | 175 |
|
128 | | - con = dx.dxf_create_connection() |
129 | | - sub = dx.dxf_create_subscription(con, 'Trade') |
| 176 | +See Custom Event Handler tutorial for more details |
130 | 177 |
|
131 | | -Attach custom listener, specifying the columns |
| 178 | +.. code:: python3 |
132 | 179 |
|
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 |
134 | 189 |
|
135 | | - dx.dxf_attach_custom_listener(sub, cust.tc, ['Symbol', 'Price']) |
136 | | - dx.dxf_add_symbols(sub, ['AAPL', 'MSFT']) |
| 190 | +.. code:: python3 |
137 | 191 |
|
138 | | -After some time you will get the data. |
| 192 | + con = dxc.dxf_create_connection() |
| 193 | + sub = dxc.dxf_create_subscription(con, 'Trade') |
139 | 194 |
|
140 | | -.. code:: ipython3 |
| 195 | +Attach custom handler |
141 | 196 |
|
142 | | - sub.get_data() |
| 197 | +.. code:: python3 |
143 | 198 |
|
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 |
145 | 229 |
|
146 | | - dx.dxf_detach_listener(sub) |
| 230 | + dxc.dxf_detach_listener(sub) |
0 commit comments