├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── publishpackage.yml
│ ├── test_on_pr.yml
│ ├── testdevelop.yml
│ └── testpackage.yml
├── .gitignore
├── .readthedocs.yml
├── LICENSE
├── README.md
├── build.py
├── clear.py
├── docs
├── Makefile
├── _static
│ ├── custom.css
│ └── custom.js
├── api.rst
├── basic_usage.rst
├── conf.py
├── core_usage.rst
├── custom_handler.rst
├── custom_listener.rst
├── devs.rst
├── index.rst
├── installation.rst
└── zipper.py
├── dxfeed
├── __init__.py
├── core
│ ├── DXFeedPy.pyx
│ ├── __init__.py
│ ├── listeners
│ │ ├── __init__.py
│ │ ├── listener.pxd
│ │ └── listener.pyx
│ ├── pxd_include
│ │ ├── DXErrorCodes.pxd
│ │ ├── DXFeed.pxd
│ │ ├── DXTypes.pxd
│ │ ├── EventData.pxd
│ │ ├── RecordData.pxd
│ │ └── __init__.py
│ └── utils
│ │ ├── __init__.py
│ │ ├── data_class.py
│ │ ├── handler.pxd
│ │ ├── handler.pyx
│ │ ├── helpers.pxd
│ │ └── helpers.pyx
└── wrappers
│ ├── __init__.py
│ ├── class_utils.py
│ ├── endpoint.py
│ └── subscription.py
├── examples
├── AllSubscriptionsExample.ipynb
├── CustomHandlerExample.ipynb
├── Low_level_API
│ ├── BasicAndTimedSubscription.ipynb
│ └── CustomListenerExample.ipynb
└── SubscriptionExample.ipynb
├── pyproject.toml
└── tests
├── conftest.py
├── test_class_utils.py
├── test_dxfeedpy.py
├── test_endpoint_class.py
└── test_subscription_class.py
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | - A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | - Provide reproducible code snippet, please.
15 |
16 | **Behavior**
17 | - Bug case: provide error traceback, please.
18 | - Unexpected behavior case: describe the key points of behavior you face, please.
19 |
20 | **Expected behavior**
21 | - Provide a clear and concise description of what you expected to happen, please.
22 |
23 | **Environment:**
24 | - OS: [e.g. Ubuntu-16.04]
25 | - Python version: [e.g. 3.7.3]
26 | - Package version: [e.g. 0.4.0]
27 |
28 | Note: to get package version run `import pkg_resources; pkg_resources.get_distribution('dxfeed').version`
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the feature and the reason for it**
11 | What functionality you'd like to be added and why.
12 | E.g.: Please, add pandas dataframe support to the default handler. It is the most common way to work with tables in python
13 |
14 | **Describe the solution you'd like**
15 | A clear and concise description of what you want to happen. Expected code snippets are welcome
16 |
17 | **Describe alternatives you've considered**
18 | A clear and concise description of any alternative solutions or features you've considered.
19 |
20 | **Additional context**
21 | Add any other context or screenshots about the feature request here.
22 |
--------------------------------------------------------------------------------
/.github/workflows/publishpackage.yml:
--------------------------------------------------------------------------------
1 | # This workflow publishes package to pypi via poetry
2 |
3 | name: Publish package
4 |
5 | on:
6 | push:
7 | tags:
8 | - '*'
9 |
10 | jobs:
11 | build:
12 | strategy:
13 | matrix:
14 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
15 | python-version: [3.7, 3.8, 3.9]
16 | runs-on: ${{ matrix.os }}
17 |
18 | steps:
19 | - uses: actions/checkout@v4
20 | with:
21 | submodules: true
22 |
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v5
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 |
28 | - name: Install Poetry
29 | uses: abatilo/actions-poetry@v2
30 |
31 | - name: Set poetry env
32 | run: |
33 | pip install --upgrade pip
34 | poetry install
35 | shell: bash
36 |
37 | - name: Create tarball
38 | if: matrix.python-version == 3.7
39 | run: |
40 | poetry build -f sdist
41 | shell: bash
42 |
43 | - name: Create wheel
44 | run: |
45 | poetry build -f wheel
46 | shell: bash
47 |
48 | - name: Upload artifacts
49 | if: success()
50 | uses: actions/upload-artifact@v2
51 | with:
52 | name: artifacts
53 | path: dist/
54 |
55 |
56 | publish:
57 | runs-on: ubuntu-20.04
58 | needs: build
59 | steps:
60 | - uses: actions/checkout@v4
61 |
62 | - name: Set up Python
63 | uses: actions/setup-python@v5
64 | with:
65 | python-version: 3.7
66 |
67 | - name: Install Poetry
68 | uses: abatilo/actions-poetry@v2
69 |
70 | - name: Clear dist folder
71 | run: |
72 | rm -rf dist/
73 |
74 | - name: Download
75 | uses: actions/download-artifact@v2
76 | with:
77 | name: artifacts
78 | path: dist/
79 |
80 | - name: Publish to PyPI
81 | if: success()
82 | run: |
83 | poetry publish -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }}
84 | shell: bash
85 |
--------------------------------------------------------------------------------
/.github/workflows/test_on_pr.yml:
--------------------------------------------------------------------------------
1 | # This workflow will check package installation and runs tests on PR
2 | name: Test on PR
3 |
4 | on:
5 | pull_request:
6 | types: [opened, reopened, synchronize]
7 |
8 | jobs:
9 | installation:
10 | strategy:
11 | matrix:
12 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
13 | python-version: [3.7, 3.8, 3.9]
14 | runs-on: ${{ matrix.os }}
15 |
16 | steps:
17 | - uses: actions/checkout@v4
18 | with:
19 | submodules: true
20 |
21 | - name: Set up Python ${{ matrix.python-version }}
22 | uses: actions/setup-python@v5
23 | with:
24 | python-version: ${{ matrix.python-version }}
25 |
26 | - name: Install Poetry
27 | uses: abatilo/actions-poetry@v2
28 |
29 | - name: Set poetry env
30 | run: |
31 | pip install --upgrade pip
32 | poetry install
33 | poetry build -f sdist
34 | shell: bash
35 |
36 | - name: Install package artifact
37 | run: |
38 | pip install dist/dxfeed*
39 | pip uninstall --yes dxfeed
40 | shell: bash
41 |
42 | tests:
43 | needs: installation
44 | strategy:
45 | matrix:
46 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
47 | python-version: [3.7, 3.8, 3.9]
48 | runs-on: ${{ matrix.os }}
49 |
50 | steps:
51 | - uses: actions/checkout@v4
52 | with:
53 | submodules: true
54 |
55 | - name: Set up Python ${{ matrix.python-version }}
56 | uses: actions/setup-python@v5
57 | with:
58 | python-version: ${{ matrix.python-version }}
59 |
60 | - name: Install Poetry
61 | uses: abatilo/actions-poetry@v2
62 |
63 | - name: Set poetry env
64 | run: |
65 | pip install --upgrade pip
66 | poetry install
67 | shell: bash
68 |
69 | - name: Run tests
70 | run: |
71 | poetry run task test
72 | shell: bash
73 |
74 | - name: Generate doc
75 | if: matrix.os == 'ubuntu-20.04' && matrix.python-version == 3.7
76 | run: |
77 | poetry run task html_docs
78 | shell: bash
79 |
--------------------------------------------------------------------------------
/.github/workflows/testdevelop.yml:
--------------------------------------------------------------------------------
1 | # This workflow will check package installation and runs tests in pre-release branch
2 | # On Ubuntu, Windows and MacOS
3 | # Triggered by push to develop
4 | name: Test package dev mode
5 |
6 | on:
7 | push:
8 | branches:
9 | - develop
10 |
11 | jobs:
12 | installation:
13 | strategy:
14 | matrix:
15 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
16 | python-version: [3.7, 3.8, 3.9]
17 | runs-on: ${{ matrix.os }}
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 | with:
22 | submodules: true
23 |
24 | - name: Set up Python ${{ matrix.python-version }}
25 | uses: actions/setup-python@v5
26 | with:
27 | python-version: ${{ matrix.python-version }}
28 |
29 | - name: Install Poetry
30 | uses: abatilo/actions-poetry@v2
31 |
32 | - name: Set poetry env
33 | run: |
34 | pip install --upgrade pip
35 | poetry install
36 | poetry build -f sdist
37 | shell: bash
38 |
39 | - name: Install package artifact
40 | run: |
41 | pip install dist/dxfeed*
42 | pip uninstall --yes dxfeed
43 | shell: bash
44 |
45 | tests:
46 | needs: installation
47 | strategy:
48 | matrix:
49 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
50 | python-version: [3.7, 3.8, 3.9]
51 | runs-on: ${{ matrix.os }}
52 |
53 | steps:
54 | - uses: actions/checkout@v4
55 | with:
56 | submodules: true
57 |
58 | - name: Set up Python ${{ matrix.python-version }}
59 | uses: actions/setup-python@v5
60 | with:
61 | python-version: ${{ matrix.python-version }}
62 |
63 | - name: Install Poetry
64 | uses: abatilo/actions-poetry@v2
65 |
66 | - name: Set poetry env
67 | run: |
68 | pip install --upgrade pip
69 | poetry install
70 | shell: bash
71 |
72 | - name: Run tests
73 | run: |
74 | poetry run task test
75 | shell: bash
76 |
77 | - name: Generate doc
78 | if: matrix.os == 'ubuntu-20.04' && matrix.python-version == 3.7
79 | run: |
80 | poetry run task html_docs
81 | shell: bash
82 |
--------------------------------------------------------------------------------
/.github/workflows/testpackage.yml:
--------------------------------------------------------------------------------
1 | # This workflow will check package installation and runs tests
2 | # On Ubuntu, Windows and MacOS
3 | # Triggered by push to master
4 |
5 | name: Test package
6 |
7 | on:
8 | push:
9 | branches:
10 | - master
11 |
12 | jobs:
13 | installation:
14 | strategy:
15 | matrix:
16 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
17 | python-version: [3.7, 3.8, 3.9]
18 | runs-on: ${{ matrix.os }}
19 |
20 | steps:
21 | - uses: actions/checkout@v4
22 | with:
23 | submodules: true
24 |
25 | - name: Set up Python ${{ matrix.python-version }}
26 | uses: actions/setup-python@v5
27 | with:
28 | python-version: ${{ matrix.python-version }}
29 |
30 | - name: Install Poetry
31 | uses: abatilo/actions-poetry@v2
32 |
33 | - name: Set poetry env
34 | run: |
35 | pip install --upgrade pip
36 | poetry install
37 | poetry build -f sdist
38 | shell: bash
39 |
40 | - name: Install package artifact
41 | run: |
42 | pip install dist/dxfeed*
43 | pip uninstall --yes dxfeed
44 | shell: bash
45 |
46 | tests:
47 | needs: installation
48 | strategy:
49 | matrix:
50 | os: [ubuntu-20.04, ubuntu-latest, windows-latest, macos-latest]
51 | python-version: [3.7, 3.8, 3.9]
52 | runs-on: ${{ matrix.os }}
53 |
54 | steps:
55 | - uses: actions/checkout@v4
56 | with:
57 | submodules: true
58 |
59 | - name: Set up Python ${{ matrix.python-version }}
60 | uses: actions/setup-python@v5
61 | with:
62 | python-version: ${{ matrix.python-version }}
63 |
64 | - name: Install Poetry
65 | uses: abatilo/actions-poetry@v2
66 |
67 | - name: Set poetry env
68 | run: |
69 | pip install --upgrade pip
70 | poetry install
71 | shell: bash
72 |
73 | - name: Run tests
74 | run: |
75 | poetry run task test
76 | shell: bash
77 |
78 | - name: Generate doc
79 | if: matrix.os == 'ubuntu-20.04' && matrix.python-version == 3.7
80 | run: |
81 | poetry run task html_docs
82 | shell: bash
83 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IDE
2 | *.idea
3 |
4 | # Python Build files
5 | build/*
6 | *.pyd
7 |
8 | _build*
9 |
10 | *__pycache__
11 |
12 | *cython_debug*
13 |
14 | *Untitled*
15 |
16 | *.ipynb_checkpoints*
17 |
18 | Pipfile*
19 | dist*
20 | dist
21 | build/**
22 | dxfeed/core/**/*.c
23 | dxfeed/tmp
24 |
25 | setup.py
26 | poetry.lock
27 | dxfeed.egg-info
28 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | # Required
2 | version: 2
3 |
4 | # Build documentation in the docs/ directory with Sphinx
5 | sphinx:
6 | configuration: docs/conf.py
7 |
8 | # Optionally build your docs in additional formats such as PDF and ePub
9 | formats: all
10 |
11 | # Optionally set the version of Python and requirements required to build your docs
12 | python:
13 | version: 3.7
14 | install:
15 | - method: pip
16 | path: .
17 | extra_requirements:
18 | - docs
19 |
20 | submodules:
21 | include: all
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # dxfeed package
2 |
3 | [](https://pypi.org/project/dxfeed/)
4 | [](https://dxfeed.readthedocs.io/en/latest/?badge=latest)
5 | [](https://pypi.org/project/dxfeed/)
6 | 
7 | [](https://pypi.org/project/dxfeed/)
8 | [](https://github.com/dxFeed/dxfeed-python-api/blob/master/LICENSE)
9 | [](https://github.com/dxFeed/dxfeed-python-api/actions)
10 |
11 | :warning:
12 | This library will be superseded by the Graal Python API based on [GraalVM](https://www.graalvm.org/latest/reference-manual/native-image/)
13 | (similar to [Graal .NET API](https://github.com/dxFeed/dxfeed-graal-net-api#readme)).\
14 | The current implementation has a number of architectural limitations that will be fixed in the new one.\
15 | Please note that feature development has been completely halted in this version.
16 |
17 |
18 |
19 | This package provides access to [dxFeed](https://www.dxfeed.com/) streaming data.
20 | The library is build as a thin wrapper over [dxFeed C-API library](https://github.com/dxFeed/dxfeed-c-api).
21 | We use [Cython](https://cython.org/) in this project as it combines flexibility, reliability and
22 | usability in writing C extensions.
23 |
24 | The design of the dxfeed package allows users to write any logic related to events in python as well as
25 | extending lower level Cython functionality. Moreover, one may start working with the API using the default
26 | values like function arguments or a default event handler.
27 |
28 | Documentation: [dxfeed.readthedocs.io](https://dxfeed.readthedocs.io/en/latest/)
29 |
30 | Package distribution: [pypi.org/project/dxfeed](https://pypi.org/project/dxfeed/)
31 |
32 | ## Installation
33 |
34 | **Requirements:** python >= 3.6 and <= 3.9
35 |
36 | On Linux, WSL and macOS, we recommend installing python via [pyenv](https://github.com/pyenv/pyenv):
37 |
38 | An example of how to install python on Ubuntu 20.04:
39 |
40 | ```bash
41 | # Update the package index files on the system
42 | sudo apt-get update
43 |
44 | # Install pyenv dependencies
45 | sudo apt-get install make build-essential libssl-dev zlib1g-dev \
46 | libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
47 | libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
48 |
49 | # Run automatic pyenv installer
50 | curl https://pyenv.run | bash
51 |
52 | # Configure bash shell
53 | echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
54 | echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
55 | echo 'eval "$(pyenv init -)"' >> ~/.bashrc
56 |
57 | # Restart bash shell
58 | bash
59 |
60 | # Install python 3.9.16
61 | pyenv install 3.9.16
62 |
63 | # Set python 3.9.16 as global
64 | pyenv global 3.9.16
65 |
66 | # Check python version
67 | python --version
68 | #>>> Python 3.9.16
69 |
70 | ```
71 |
72 | Install package via PyPI:
73 |
74 | ```python
75 | python -m pip install dxfeed
76 | ```
77 |
78 | ## Installation from sources
79 |
80 | To install dxfeed from source you need Poetry. It provides a custom installer.
81 | This is the recommended way of installing poetry according to [documentation](https://python-poetry.org/docs/)
82 |
83 | For macOS / Linux / Windows (WSL):
84 |
85 | ```bash
86 | curl -sSL https://install.python-poetry.org | python3 -
87 | ```
88 |
89 | For Windows (Powershell):
90 | ```powershell
91 | (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
92 | ```
93 |
94 | In the project root directory (same one where you found this file after
95 | cloning the git repo), execute:
96 |
97 | ```bash
98 | poetry install
99 | ```
100 |
101 | By default package is installed in
102 | [development mode](https://pip.pypa.io/en/latest/reference/pip_install.html#editable-installs). To rebuild
103 | C extensions, after editing .pyx files:
104 |
105 | ```bash
106 | poetry run task build_inplace # build c extensions
107 | ```
108 |
109 | ## Basic usage
110 |
111 | Following steps should be performed:
112 |
113 | * Import
114 | * Create Endpoint
115 | * Create Subscription
116 | * Attach event handler
117 | * Add tickers
118 | * Finally close subscription and connection
119 |
120 | ### Import package
121 |
122 | ```python
123 | import dxfeed as dx
124 | from datetime import datetime # for timed subscription
125 | ```
126 |
127 | ### Configure and create connection with Endpoint class
128 | Create instance of Endpoint class which will connect provided address.
129 |
130 |
131 | ```python
132 | endpoint = dx.Endpoint('demo.dxfeed.com:7300')
133 | ```
134 |
135 | Endpoint instance contains information about the connection, e.g. connection address or status
136 |
137 |
138 | ```python
139 | print(f'Connected address: {endpoint.address}')
140 | print(f'Connection status: {endpoint.connection_status}')
141 | ```
142 |
143 | ```text
144 | Connected address: demo.dxfeed.com:7300
145 | Connection status: Connected and authorized
146 | ```
147 |
148 | ### Configure and create subscription
149 | You should specify event type. For timed subscription (conflated stream) you should also provide time to start subscription from.
150 |
151 |
152 | ```python
153 | trade_sub = endpoint.create_subscription('Trade')
154 | ```
155 |
156 | **Attach default or custom event handler** - class that process incoming events. For details about custom
157 | event handler look into `CustomHandlerExample.ipynb` jupyter notebook in `exapmles` folder of this repository.
158 |
159 |
160 | ```python
161 | trade_handler = dx.DefaultHandler()
162 | trade_sub = trade_sub.set_event_handler(trade_handler)
163 | ```
164 |
165 | **Add tikers** you want to receive events for
166 |
167 |
168 | ```python
169 | trade_sub = trade_sub.add_symbols(['C', 'AAPL'])
170 | ```
171 |
172 | For timed subscription you may provide either datetime object or string. String might be incomplete, in
173 | this case you will get warning with how your provided date parsed automatically.
174 |
175 |
176 | ```python
177 | tns_sub = endpoint.create_subscription('TimeAndSale', date_time=datetime.now()) \
178 | .add_symbols(['AMZN'])
179 | ```
180 |
181 |
182 | ```python
183 | candle_sub = endpoint.create_subscription('Candle', date_time='2020-04-16 13:05')
184 | candle_sub = candle_sub.add_symbols(['AAPL', 'MSFT'])
185 | ```
186 |
187 | We didn't provide subscriptions with event handlers. In such a case DefaultHandler is initiated automatically.
188 | One may get it with `get_event_handler` method.
189 |
190 | ```python
191 | tns_handler = tns_sub.get_event_handler()
192 | candle_handler = candle_sub.get_event_handler()
193 | ```
194 |
195 | #### Subscription instance properties
196 |
197 |
198 | ```python
199 | print(f'Subscription event type: {tns_sub.event_type}')
200 | print(f'Subscription symbols: {candle_sub.symbols}')
201 | ```
202 |
203 | ```text
204 | Subscription event type: TimeAndSale
205 | Subscription symbols: ['AAPL', 'MSFT']
206 | ```
207 |
208 | ### Access data
209 | In DefaultHandler the data is stored as deque. Its length may be configured, by default 100000 events.
210 |
211 | ```python
212 | candle_handler.get_list()
213 | ```
214 |
215 | ### Close connection
216 |
217 |
218 | ```python
219 | endpoint.close_connection()
220 | print(f'Connection status: {endpoint.connection_status}')
221 | ```
222 |
223 | ```text
224 | Connection status: Not connected
225 | ```
226 |
227 | ### Transform data to pandas DataFrame
228 |
229 | DefaultHandler has `get_dataframe` method, which allows you to get pandas.DataFrame object with events as rows.
230 |
231 | ```python
232 | trade_df = trade_handler.get_dataframe()
233 | tns_df = tns_handler.get_dataframe()
234 | candle_df = candle_handler.get_dataframe()
235 | ```
236 |
--------------------------------------------------------------------------------
/build.py:
--------------------------------------------------------------------------------
1 | import os
2 | import platform
3 | import struct
4 | from io import BytesIO
5 | from pathlib import Path
6 | from urllib.request import urlopen
7 | from zipfile import ZipFile
8 | import shutil
9 | from setuptools import Extension, find_packages
10 | from setuptools.dist import Distribution
11 | import toml
12 |
13 |
14 | class Downloader(object):
15 | """Class that downloads a dxFeed C API bundle and places the necessary include or lib files"""
16 |
17 | def __init__(self, version: str, path_to_extract: Path,
18 | path_to_copy_includes: Path, path_to_copy_libs: Path):
19 | """
20 | Parameters
21 | ----------
22 | version : str
23 | The dxFeed C API version
24 | path_to_extract : Path
25 | The temporary directory where the bundle should be unpacked
26 | path_to_copy_includes : Path
27 | The directory where the include files should be placed
28 | path_to_copy_libs
29 | The directory where the library files should be placed
30 | """
31 |
32 | self.__version = version
33 | self.__path_to_extract = path_to_extract
34 | self.__path_to_copy_includes = path_to_copy_includes
35 | self.__path_to_copy_libs = path_to_copy_libs
36 |
37 | def download(self, dxfeed_c_api_bundle_url_template: str) -> str:
38 | """
39 | The method that does the bulk of the work of downloading and placement files.
40 |
41 |
42 | Parameters
43 | ----------
44 | dxfeed_c_api_bundle_url_template: str
45 | The URL template for zipped dxFeed C API bundle. Parameters used:
46 | {version} - The C API version
47 | {os} - The target OS
48 |
49 | Returns
50 | -------
51 | : str
52 | The resulting name of the library, which is required to build an extension
53 |
54 | """
55 | c_api_extracted_root_path = self.__path_to_extract / f'dxfeed-c-api-{self.__version}-no-tls'
56 | is_x64 = 8 * struct.calcsize('P') == 64
57 |
58 | url_template_os = 'centos' # Since centos uses an earlier version of libc
59 |
60 | if platform.system() == 'Darwin':
61 | url_template_os = 'macosx'
62 | elif platform.system() == 'Windows':
63 | url_template_os = 'windows'
64 |
65 | if (not os.path.exists(self.__path_to_extract)) or (not os.path.exists(c_api_extracted_root_path)):
66 | url = dxfeed_c_api_bundle_url_template.format(version=self.__version, os=url_template_os)
67 | print(f'Downloading the "{url}"')
68 | resp = urlopen(url)
69 | zipfile = ZipFile(BytesIO(resp.read()))
70 | print(f'Extracting to "{self.__path_to_extract}"')
71 | zipfile.extractall(self.__path_to_extract)
72 |
73 | c_api_x64_suffix = '_64' if is_x64 else ''
74 | resulting_c_api_library_name = f'DXFeed{c_api_x64_suffix}'
75 |
76 | # Determine and fixing paths for unpacked artifacts.
77 | # The workaround is related to the packaging feature on POSIX systems in the dxFeed API' CI\CD.
78 | if is_x64:
79 | if platform.system() != 'Windows':
80 | c_api_extracted_root_path = c_api_extracted_root_path / f'DXFeedAll-{self.__version}-x64-no-tls'
81 |
82 | c_api_extracted_library_path = c_api_extracted_root_path / 'bin' / 'x64'
83 | else:
84 | if platform.system() == 'Windows':
85 | c_api_extracted_library_path = c_api_extracted_root_path / 'bin' / 'x86'
86 | else:
87 | raise RuntimeError('Unsupported platform')
88 |
89 | # Determine possible prefixes and extensions for library files
90 | lib_file_name_prefixes = [''] * 2
91 | lib_file_name_extensions = ['dll', 'lib']
92 |
93 | if platform.system() != 'Windows':
94 | lib_file_name_prefixes = ['lib']
95 | lib_file_name_extensions = ['dylib'] if platform.system() == 'Darwin' else ['so']
96 |
97 | # Create paths for libraries to be copied
98 | c_api_library_file_source_paths = []
99 | c_api_library_file_dest_paths = []
100 |
101 | for idx, prefix in enumerate(lib_file_name_prefixes):
102 | file_name = f'{prefix}{resulting_c_api_library_name}.{lib_file_name_extensions[idx]}'
103 | c_api_library_file_source_paths.append(c_api_extracted_library_path / file_name)
104 | c_api_library_file_dest_paths.append(self.__path_to_copy_libs / file_name)
105 |
106 | print('Copying all headers')
107 | # Copying all headers
108 | if not Path(self.__path_to_copy_includes).exists():
109 | shutil.copytree(c_api_extracted_root_path / 'include', self.__path_to_copy_includes)
110 |
111 | # Create a directory where we will copy libraries, if necessary
112 | if not Path(self.__path_to_copy_libs).exists():
113 | print(f'Creating the {self.__path_to_copy_libs} path')
114 | os.makedirs(self.__path_to_copy_libs)
115 |
116 | print('Copying the required libraries')
117 | # Copying the required libraries
118 | for idx, path in enumerate(c_api_library_file_source_paths):
119 | print(f' {path} -> {c_api_library_file_dest_paths[idx]}')
120 | shutil.copyfile(path, c_api_library_file_dest_paths[idx])
121 |
122 | return resulting_c_api_library_name
123 |
124 |
125 | try:
126 | from Cython.Build import cythonize
127 | except ImportError:
128 | use_cython = False
129 | ext = 'c'
130 | else:
131 | use_cython = True
132 | ext = 'pyx'
133 |
134 | root_path = Path(__file__).resolve().parent
135 |
136 | pyproject = toml.load(root_path / 'pyproject.toml')
137 | c_api_version = pyproject['build']['native-dependencies']['dxfeed_c_api']
138 | if c_api_version == 'env':
139 | c_api_version = os.getenv('DXFEED_C_API_VERSION')
140 |
141 | c_api_root_dir = root_path / 'dxfeed' / 'dxfeed-c-api'
142 | path_to_extract = root_path / 'dxfeed' / 'tmp'
143 | c_api_include_dir = c_api_root_dir / 'include'
144 | c_api_bin_dir = root_path / 'dxfeed' / 'core'
145 |
146 | downloader = Downloader(c_api_version, path_to_extract, c_api_include_dir, c_api_bin_dir)
147 | c_api_library_name = downloader.download(pyproject['build']['native-dependencies']['dxfeed_c_api_bundle_url_template'])
148 |
149 | if platform.system() == 'Windows':
150 | runtime_library_dirs = None
151 | extra_link_args = None
152 | elif platform.system() == 'Darwin':
153 | runtime_library_dirs = None
154 | extra_link_args = ['-Wl,-rpath,@loader_path']
155 | else:
156 | runtime_library_dirs = ['$ORIGIN']
157 | extra_link_args = None
158 |
159 | c_api_include_dirs = [str(c_api_include_dir)]
160 |
161 | libs = [c_api_library_name]
162 | if platform.system() == 'Windows':
163 | libs.append('ws2_32')
164 |
165 | extensions = [Extension('dxfeed.core.utils.helpers', ['dxfeed/core/utils/helpers.' + ext],
166 | include_dirs=c_api_include_dirs),
167 | Extension('dxfeed.core.utils.handler', ['dxfeed/core/utils/handler.' + ext],
168 | include_dirs=c_api_include_dirs),
169 | Extension('dxfeed.core.listeners.listener', ['dxfeed/core/listeners/listener.' + ext],
170 | include_dirs=c_api_include_dirs),
171 | Extension('dxfeed.core.DXFeedPy', ['dxfeed/core/DXFeedPy.' + ext], library_dirs=[str(c_api_bin_dir)],
172 | runtime_library_dirs=runtime_library_dirs,
173 | extra_link_args=extra_link_args,
174 | libraries=libs,
175 | include_dirs=c_api_include_dirs)]
176 |
177 | if use_cython:
178 | extensions = cythonize(extensions, language_level=3)
179 |
180 |
181 | def build(setup_kwargs):
182 | setup_kwargs.update({
183 | 'ext_modules': extensions,
184 | 'zip_safe': False,
185 | 'packages': find_packages(),
186 | 'include_dirs': c_api_include_dirs
187 | })
188 |
189 |
190 | def build_extensions():
191 | """
192 | Function for building extensions inplace for docs and tests
193 | :return:
194 | """
195 | build_params = {}
196 | build(build_params)
197 | dist = Distribution(attrs=build_params)
198 | build_clib_cmd = dist.get_command_obj('build_clib')
199 | build_clib_cmd.ensure_finalized()
200 | build_clib_cmd.run()
201 | build_ext_cmd = dist.get_command_obj('build_ext')
202 | build_ext_cmd.ensure_finalized()
203 | build_ext_cmd.inplace = 1
204 | build_ext_cmd.run()
205 |
--------------------------------------------------------------------------------
/clear.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | from pathlib import Path
3 | from itertools import chain
4 |
5 | c_files = Path('dxfeed/core').glob('**/*.c')
6 | cpp_files = Path('dxfeed/core').glob('**/*.cpp')
7 | pyd_files = Path('dxfeed/core').glob('**/*.pyd')
8 | so_files = Path('dxfeed/core').glob('**/*.so')
9 | dll_files = Path('dxfeed/core').glob('**/*.dll')
10 | lib_files = Path('dxfeed/core').glob('*.lib')
11 | dylib_files = Path('dxfeed/core').glob('**/*.dylib')
12 |
13 | for file_path in chain(c_files, cpp_files, pyd_files, so_files, dll_files, lib_files, dylib_files):
14 | file_path.unlink()
15 |
16 | if Path('dxfeed/tmp').exists():
17 | shutil.rmtree('dxfeed/tmp')
18 |
19 | if Path('dxfeed/dxfeed-c-api/include').exists():
20 | shutil.rmtree('dxfeed/dxfeed-c-api/include')
21 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = .
8 | BUILDDIR = _build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @cd ..; python -c 'from build import *; build_extensions()'
21 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
22 | python zipper.py
23 | @cd ..; find dxfeed/core/* -type f \( -name '*.c*' -or -name '*.pyd' \) -delete
24 |
25 | .PHONY: clean
26 | clean:
27 | rm -rf $(BUILDDIR)/*
28 |
--------------------------------------------------------------------------------
/docs/_static/custom.css:
--------------------------------------------------------------------------------
1 | .footer {
2 | display: none;
3 | }
4 | .body {
5 | margin-bottom: 50px;
6 | }
7 | .section > dl > dt {
8 | background-color: #DDE7F7;
9 | }
10 | .current.reference.internal {
11 | font-weight: bold;
12 | }
13 | .attribute {
14 | margin-left: 30px;
15 | }
16 |
17 | table {
18 | display: block;
19 | overflow-x: auto;
20 | }
21 |
22 | .highlight-text > .highlight > pre {
23 | background-color: wheat;
24 | display: block;
25 | max-height: 300px;
26 | overflow-y: auto;
27 | }
--------------------------------------------------------------------------------
/docs/_static/custom.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 | $('a[href^="http://"], a[href^="https://"]').not('a[class*=internal]').attr('target', '_blank');
3 | });
4 |
--------------------------------------------------------------------------------
/docs/api.rst:
--------------------------------------------------------------------------------
1 | .. _api:
2 |
3 | .. meta::
4 | :description lang=en: dxfeed package docstrings.
5 |
6 | API Reference
7 | =============
8 |
9 | This page contains only automatically generated documentation to functions, classes, methods, etc.
10 |
11 | API
12 | ------------------------
13 |
14 | .. automodule:: dxfeed.wrappers.endpoint
15 | :members:
16 | :inherited-members:
17 |
18 | .. automodule:: dxfeed.wrappers.subscription
19 | :members:
20 | :inherited-members:
21 |
22 | .. automodule:: dxfeed.core.utils.handler
23 | :members:
24 | :inherited-members:
25 |
26 | Low-level API
27 | -----------------------
28 |
29 | .. automodule:: dxfeed.core.DXFeedPy
30 | :members:
31 | :inherited-members:
32 |
33 | Utils functions
34 | ---------------
35 |
36 | .. automodule:: dxfeed.core.utils.helpers
37 | :members:
38 | :inherited-members:
39 |
40 | .. automodule:: dxfeed.core.utils.data_class
41 | :members:
42 | :inherited-members:
43 |
--------------------------------------------------------------------------------
/docs/basic_usage.rst:
--------------------------------------------------------------------------------
1 | .. _basic_usage:
2 |
3 | Basic Usage
4 | ===========
5 |
6 | There are three levels in the dxfeed package. The lowest is the C API
7 | library, the highest is Python wrapper classes. Cython level in the
8 | middle aims to connect these two. Here we are going to look into Python
9 | level.
10 |
11 | Python level, in its turn, mainly consists of three class types:
12 |
13 | 1. Endpoint
14 | 2. Subscription
15 | 3. EventHandler
16 |
17 | The **Endpoint** is responsible for connection management and creating
18 | dependent classes, for example Subscription. One Endpoint may have
19 | several different Subscriptions, but each Subscription is related to one
20 | Endpoint.
21 |
22 | **Subscription** class sets the type of subscription (stream or timed),
23 | the type of events (e.g. Trade, Candle), etc.
24 |
25 | After you specified the data you want to receive, you have to specify
26 | how to process upcoming events. This is where the **EventHandler** class
27 | and its children come into play. Every time an event arrives Cython
28 | event listener will call ``self.update(event)`` method. You have to
29 | inherit from the EventHandler class and redefine the update method. Or
30 | you may use DefaultHandler which stores upcoming data in deque of the
31 | length 100k.
32 |
33 | Import package
34 | ~~~~~~~~~~~~~~
35 |
36 | .. code:: python3
37 |
38 | import dxfeed as dx
39 | from datetime import datetime # for timed subscription
40 |
41 | Configure and create connection with Endpoint class
42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43 |
44 | Create instance of Endpoint class which will connect provided address.
45 |
46 | .. code:: python3
47 |
48 | endpoint = dx.Endpoint('demo.dxfeed.com:7300')
49 |
50 | Endpoint instance contains information about the connection,
51 | e.g. connection address or status
52 |
53 | .. code:: python3
54 |
55 | print(f'Connected address: {endpoint.address}')
56 | print(f'Connection status: {endpoint.connection_status}')
57 |
58 |
59 | .. code:: text
60 |
61 | Connected address: demo.dxfeed.com:7300
62 | Connection status: Connected and authorized
63 |
64 |
65 | Configure and create subscription
66 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67 |
68 | You should specify event type. For timed subscription (conflated stream)
69 | you should also provide time to start subscription from.
70 |
71 | .. code:: python3
72 |
73 | trade_sub = endpoint.create_subscription('Trade')
74 |
75 | **Set event handler** - class that process incoming events. Here we use
76 | default one
77 |
78 | .. code:: python3
79 |
80 | trade_handler = dx.DefaultHandler()
81 | trade_sub.set_event_handler(trade_handler);
82 |
83 | **Add tikers** you want to recieve events for
84 |
85 | .. code:: python3
86 |
87 | trade_sub = trade_sub.add_symbols(['C', 'IBM'])
88 |
89 | For timed subscription you should provide either datetime object or
90 | string. String might be incomlete, in this case you will get warning
91 | with how your provided date parsed automatically. For Candle event type
92 | along with base symbol, you should specify an aggregation period. You
93 | can also set price type. More details:
94 | https://kb.dxfeed.com/display/DS/REST+API#RESTAPI-Candlesymbols.
95 |
96 | .. code:: python3
97 |
98 | tns_sub = endpoint.create_subscription('TimeAndSale', date_time=datetime.now()) \
99 | .add_symbols(['AMZN'])
100 |
101 | .. code:: python3
102 |
103 | candle_sub = endpoint.create_subscription('Candle', date_time='2020-04-16 13:05')
104 | candle_sub = candle_sub.add_symbols(['AAPL{=d}', 'MSFT{=d}'])
105 |
106 |
107 | .. code:: text
108 |
109 | c:\job\python-api\dxfeed\wrappers\class_utils.py:38: UserWarning: Datetime argument does not exactly match %Y-%m-%d %H:%M:%S.%f format, date was parsed automatically as 2020-04-16 13:05:00.000000
110 | warn(warn_message, UserWarning)
111 |
112 |
113 | **Note** Two previous subscriptions attached DefaultHandler implicitly.
114 | To retrieve instances just call ``get_event_handler()`` method.
115 |
116 | .. code:: python3
117 |
118 | tns_handler = tns_sub.get_event_handler()
119 | candle_handler = candle_sub.get_event_handler()
120 |
121 | Subscription instance properties
122 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
123 |
124 | .. code:: python3
125 |
126 | print(f'TimeAndSale subscription event type: {tns_sub.event_type}')
127 | print(f'Candle subscription event type: {candle_sub.event_type}')
128 | print(f'Candle subscription symbols: {candle_sub.symbols}')
129 |
130 |
131 | .. code:: text
132 |
133 | TimeAndSale subscription event type: TimeAndSale
134 | Candle subscription event type: Candle
135 | Candle subscription symbols: ['AAPL{=d}', 'MSFT{=d}']
136 |
137 |
138 | Access data from DefaultHandler instance
139 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140 |
141 | You can get colums, list or dataframe. You are also allowed to write
142 | handler that stores no data.
143 |
144 | .. code:: python3
145 |
146 | print(f'Trade columns: {trade_handler.columns}')
147 | print(f'Candle columns: {candle_handler.columns}')
148 |
149 |
150 | .. code:: text
151 |
152 | Trade columns: ['Symbol', 'Price', 'ExchangeCode', 'Size', 'Tick', 'Change', 'DayVolume', 'Time', 'IsETH']
153 | Candle columns: ['Symbol', 'Index', 'Time', 'Sequence', 'Count', 'Open', 'High', 'Low', 'Close', 'Volume', 'VWap', 'BidVolume', 'AskVolume', 'OpenInterest', 'ImpVolatility']
154 |
155 |
156 | .. code:: python3
157 |
158 | candle_handler.get_list()[-5:]
159 |
160 |
161 |
162 |
163 | .. code:: text
164 |
165 | [['MSFT{=d}', 6816463568083353600, 1587081600000, 0, 189986.0, 179.5, 180.0, 175.87, 178.6, 52765625.0, 177.90622, 24188832.0, 22094602.0, 0, 0.4384],
166 | ['MSFT{=d}', 6816294775868620800, 1587042300000, 0, 189986.0, 179.5, 180.0, 175.87, 178.6, 52765625.0, 177.90622, 24188832.0, 22094602.0, 0, 0.4384],
167 | ['AAPL{=d}', 6839841934068940800, 1592524800000, 0, 827.0, 354.05, 355.55, 353.35, 354.72, 188804.0, 354.45941, 78039.0, 110765.0, 0, 0.3691],
168 | ['AAPL{=d}', 6839841934068940800, 1592524800000, 0, 831.0, 354.05, 355.55, 353.35, 354.9, 189555.0, 354.4611, 78039.0, 111516.0, 0, 0.3691],
169 | ['AAPL{=d}', 6839841934068940800, 1592524800000, 0, 832.0, 354.05, 355.55, 353.35, 354.72, 190055.0, 354.46178, 78539.0, 111516.0, 0, 0.3691]]
170 |
171 |
172 |
173 | .. code:: python3
174 |
175 | candle_handler.get_dataframe().head(3)
176 |
177 |
178 |
179 |
180 | .. raw:: html
181 |
182 |
183 |
196 |
197 |
198 |
199 |
200 |
Symbol
201 |
Index
202 |
Time
203 |
Sequence
204 |
Count
205 |
Open
206 |
High
207 |
Low
208 |
Close
209 |
Volume
210 |
VWap
211 |
BidVolume
212 |
AskVolume
213 |
OpenInterest
214 |
ImpVolatility
215 |
216 |
217 |
218 |
219 |
0
220 |
AAPL{=d}
221 |
6839841934068940800
222 |
2020-06-19
223 |
0
224 |
827.0
225 |
354.05
226 |
355.55
227 |
353.35
228 |
354.72
229 |
188804.0
230 |
354.45941
231 |
78039.0
232 |
110765.0
233 |
0
234 |
0.3691
235 |
236 |
237 |
1
238 |
AAPL{=d}
239 |
6839470848894566400
240 |
2020-06-18
241 |
0
242 |
96172.0
243 |
351.41
244 |
353.45
245 |
349.22
246 |
351.73
247 |
24205096.0
248 |
351.56873
249 |
8565421.0
250 |
10394906.0
251 |
0
252 |
0.3673
253 |
254 |
255 |
2
256 |
AAPL{=d}
257 |
6839099763720192000
258 |
2020-06-17
259 |
0
260 |
110438.0
261 |
355.15
262 |
355.40
263 |
351.09
264 |
351.59
265 |
28601626.0
266 |
353.70998
267 |
10686232.0
268 |
12141490.0
269 |
0
270 |
0.3713
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 | Close subscription
279 | ~~~~~~~~~~~~~~~~~~
280 |
281 | .. code:: python3
282 |
283 | trade_sub.close_subscription()
284 | tns_sub.close_subscription()
285 | candle_sub.close_subscription()
286 |
287 | Close connection
288 | ~~~~~~~~~~~~~~~~
289 |
290 | .. code:: python3
291 |
292 | endpoint.close_connection()
293 | print(f'Connection status: {endpoint.connection_status}')
294 |
295 |
296 | .. code:: text
297 |
298 | Connection status: Not connected
299 |
300 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 | import toml
5 | from pathlib import Path
6 | from pygments.lexers.python import CythonLexer
7 | from sphinx.highlighting import lexers
8 |
9 | pyproject = toml.load(Path(__file__).parents[1].joinpath('pyproject.toml'))
10 | # -- Path setup --------------------------------------------------------------
11 |
12 | sys.path.append(str(Path(__file__).parents[1]))
13 | # -- Project information -----------------------------------------------------
14 |
15 | project = pyproject['tool']['poetry']['name']
16 | copyright = '2019, dxfeed'
17 | author = 'dxfeed'
18 |
19 | # The short X.Y version
20 | version = pyproject['tool']['poetry']['version']
21 | # The full version, including alpha/beta/rc tags
22 | release = pyproject['tool']['poetry']['version']
23 |
24 |
25 | # -- General configuration ---------------------------------------------------
26 | # Add any Sphinx extension module names here, as strings.
27 | extensions = [
28 | 'sphinx.ext.autodoc',
29 | 'sphinx.ext.coverage',
30 | 'sphinx.ext.napoleon', # numpy style docstrings
31 | 'sphinx.ext.intersphinx'
32 | ]
33 |
34 | # Add any paths that contain templates here, relative to this directory.
35 | templates_path = ['_templates']
36 |
37 | # The suffix(es) of source filenames.
38 | source_suffix = '.rst'
39 |
40 | # The master toctree document.
41 | master_doc = 'index'
42 |
43 | # The language for content autogenerated by Sphinx.
44 | language = 'en'
45 |
46 | # List of patterns, relative to source directory, that match files and
47 | # directories to ignore when looking for source files.
48 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
49 |
50 | # -- Options for HTML output -------------------------------------------------
51 | html_static_path = ['_static']
52 | html_css_files = ['custom.css']
53 | html_js_files = ['custom.js']
54 |
55 | # The theme to use for HTML and HTML Help pages.
56 | html_theme = 'alabaster'
57 | html_theme_options = {
58 | 'show_powered_by': False,
59 | 'sidebar_collapse': True
60 | }
61 |
62 | # -- Options for HTMLHelp output ---------------------------------------------
63 |
64 | # Output file base name for HTML help builder.
65 | htmlhelp_basename = 'dxfeeddoc'
66 |
67 | # remove view source link
68 | html_show_sourcelink = False
69 |
70 | # highlight cython
71 | lexers['cython'] = CythonLexer()
72 |
--------------------------------------------------------------------------------
/docs/core_usage.rst:
--------------------------------------------------------------------------------
1 | .. _core_usage:
2 |
3 | Low-level API
4 | =============
5 |
6 | .. note::
7 | High-Level API have priority support in case of any issues. We highly recommend
8 | to use it and touch the Low-Level API only in special cases.
9 |
10 | This tutorial is about the Cython level of the package, which connects
11 | Python and C API. Though high-level Python classes provide the necessary
12 | functionality safely and conveniently, the user is not restricted to use
13 | low-level functions.
14 |
15 | Import core functions
16 | ~~~~~~~~~~~~~~~~~~~~~
17 |
18 | Here we deal with low level C styled api, so the import is slightly
19 | differ.
20 |
21 | .. code:: python3
22 |
23 | from dxfeed.core import DXFeedPy as dxc
24 | from dxfeed.core.utils.handler import DefaultHandler
25 | from datetime import datetime # for timed suscription
26 | from dateutil.relativedelta import relativedelta
27 |
28 | Create connection
29 | ~~~~~~~~~~~~~~~~~
30 |
31 | There are two ways at the moment to create connection: with token or
32 | with specifying connection address. Here we use the latter for
33 | simplicity.
34 |
35 | .. code:: python3
36 |
37 | con = dxc.dxf_create_connection('demo.dxfeed.com:7300')
38 |
39 | Create subscription
40 | ~~~~~~~~~~~~~~~~~~~
41 |
42 | There are two types of subscriptions: ordinary for delivering stream
43 | data as-is and timed for conflated data. Except type of subscription you
44 | should provide type of events you want to get. Note: some event types,
45 | e.g. Candle, support only timed subscription.
46 |
47 | .. code:: python3
48 |
49 | sub = dxc.dxf_create_subscription(con, 'Trade')
50 | sub_timed = dxc.dxf_create_subscription_timed(con, 'Candle', int((datetime.now() - relativedelta(days=3)).timestamp()))
51 |
52 | Attach event handler
53 | ~~~~~~~~~~~~~~~~~~~~
54 |
55 | To process incoming data you have to define define ``update(event)``
56 | method in your EventHandler child class. Or you may use DefaultHandler
57 | which stores upcoming data in deque of the length 100k. In this example
58 | we choose the latter.
59 |
60 | .. code:: python3
61 |
62 | trade_handler = DefaultHandler()
63 | candle_handler = DefaultHandler()
64 |
65 | .. code:: python3
66 |
67 | sub.set_event_handler(trade_handler)
68 | sub_timed.set_event_handler(candle_handler)
69 |
70 | Attach listener
71 | ~~~~~~~~~~~~~~~
72 |
73 | A special function that processes incoming on the C level events should
74 | be initialized. There are default ones for each event type.
75 |
76 | .. code:: python3
77 |
78 | dxc.dxf_attach_listener(sub)
79 | dxc.dxf_attach_listener(sub_timed)
80 |
81 | Add tickers
82 | ~~~~~~~~~~~
83 |
84 | Symbols that will be processed should be defined. For Candle event type
85 | along with base symbol, you should specify an aggregation period. You
86 | can also set price type. More details:
87 | https://kb.dxfeed.com/display/DS/REST+API#RESTAPI-Candlesymbols.
88 |
89 | .. code:: python3
90 |
91 | dxc.dxf_add_symbols(sub, ['AAPL', 'MSFT'])
92 | dxc.dxf_add_symbols(sub_timed, ['AAPL{=d}', 'MSFT{=d}'])
93 |
94 | Access data
95 | ~~~~~~~~~~~
96 |
97 | The DefaultHandler class has ``get_list()`` and ``get_dataframe()``
98 | methods to access the data.
99 |
100 | .. code:: python3
101 |
102 | trade_handler.get_list()[-5:]
103 |
104 |
105 |
106 |
107 | .. code:: text
108 |
109 | [['MSFT', 196.14, 'X', 100, 2, 0.0, 100.0, 1592510399515, 0],
110 | ['MSFT', 196.27, 'Y', 100, 2, 0.0, 18.0, 1592510398017, 0],
111 | ['MSFT', 196.33, 'Z', 100, 1, 0.0, 2693.0, 1592510399823, 0],
112 | ['AAPL', 351.57, 'D', 200, 1, 0.0, 44022.0, 1592510399435, 0],
113 | ['AAPL', 351.73, 'Q', 1406354, 1, 0.0, 234771.0, 1592510400351, 0]]
114 |
115 |
116 |
117 | .. code:: python3
118 |
119 | candle_handler.get_dataframe().head(3)
120 |
121 |
122 |
123 |
124 | .. raw:: html
125 |
126 |