Skip to content

Commit 481aa9e

Browse files
authored
Merge pull request #132 from yzh-pelle/update-2024-11
feat(kucoin): upgrade spot, add futures and asyncClient
2 parents 770c413 + f3a7684 commit 481aa9e

21 files changed

+22819
-1370
lines changed

.github/workflows/python-app.yml

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,73 @@
44
name: Python application
55

66
on:
7+
workflow_dispatch:
78
push:
8-
branches: [ "develop" ]
9+
branches: [ main, master ]
910
pull_request:
10-
branches: [ "develop" ]
11+
branches: [ main, master ]
1112

1213
permissions:
1314
contents: read
1415

1516
jobs:
16-
build:
17-
17+
lint:
1818
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.9'
25+
- name: Install Ruff
26+
run: pip install ruff
27+
- name: Lint code with Ruff
28+
run: ruff check --output-format=github --target-version=py39 .
29+
- name: Check code formatting with Ruff
30+
run: ruff format --check .
31+
continue-on-error: true
1932

33+
build:
34+
needs: lint
35+
runs-on: ubuntu-latest
36+
env:
37+
PROXY: "http://51.83.140.52:16301"
38+
strategy:
39+
max-parallel: 1
40+
matrix:
41+
python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
2042
steps:
2143
- uses: actions/checkout@v4
22-
- name: Set up Python 3.10
23-
uses: actions/setup-python@v3
44+
- name: Checking env
45+
run: |
46+
echo "PROXY: $PROXY"
47+
env
48+
- name: Set up Python ${{ matrix.python }}
49+
uses: actions/setup-python@v5
2450
with:
25-
python-version: "3.10"
51+
python-version: ${{ matrix.python }}
52+
cache: 'pip'
2653
- name: Install dependencies
2754
run: |
2855
python -m pip install --upgrade pip
29-
pip install flake8 pytest
56+
pip install pytest pytest-cov pyright tox
3057
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
3158
if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi
32-
- name: Lint with flake8
33-
run: |
34-
# stop the build if there are Python syntax errors or undefined names
35-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
36-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
37-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
38-
- name: Test with pytest
39-
run: |
40-
pytest
59+
# - name: Type check with pyright
60+
# run: pyright
61+
- name: Test with tox
62+
run: tox -e py
63+
- name: Coveralls Parallel
64+
uses: coverallsapp/github-action@v2
65+
with:
66+
flag-name: run-${{ join(matrix.*, '-') }}
67+
parallel: true
68+
finish:
69+
needs: build
70+
if: ${{ always() }}
71+
runs-on: ubuntu-latest
72+
steps:
73+
- name: Coveralls Finished
74+
uses: coverallsapp/github-action@v2
75+
with:
76+
parallel-finished: true

README.rst

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
Welcome to python-kucoin v2.1.3
33
===============================
44

5-
Last Updated 4th Oct 2021
6-
75
.. image:: https://img.shields.io/pypi/v/python-kucoin.svg
86
:target: https://pypi.python.org/pypi/python-kucoin
97

@@ -22,7 +20,7 @@ Last Updated 4th Oct 2021
2220
.. image:: https://img.shields.io/pypi/pyversions/python-kucoin.svg
2321
:target: https://pypi.python.org/pypi/python-kucoin
2422

25-
This is an unofficial Python wrapper for the `Kucoin exchanges REST and Websocket API v2 <https://docs.kucoin.com/>`_.
23+
This is an unofficial Python wrapper for the `Kucoin exchanges REST and Websocket API v3 <https://docs.kucoin.com/>`_.
2624
I am in no way affiliated with `Kucoin <https://www.kucoin.com/ucenter/signup?rcode=E5wkqe>`_, use at your own risk.
2725

2826

@@ -35,17 +33,20 @@ Source code
3533
Documentation
3634
https://python-kucoin.readthedocs.io/en/latest/
3735

38-
Blog with examples
39-
https://sammchardy.github.io
36+
Examples
37+
https://github.com/sammchardy/python-kucoin/tree/master/examples
4038

4139

4240
Features
4341
--------
4442

4543
- Implementation of REST endpoints
44+
- Spot and Futures
45+
- Sync and Async suport
4646
- Simple handling of authentication
4747
- Response exception handling
4848
- Implement websockets (note only python3.5+)
49+
- Proxy support
4950

5051
TODO
5152
----
@@ -57,28 +58,22 @@ Quick Start
5758

5859
Register an account with `Kucoin <https://www.kucoin.com/ucenter/signup?rcode=E42cWB>`_.
5960

60-
To test on the Sandbox register with `Kucoin Sandbox <https://sandbox.kucoin.com/ucenter/signup?rcode=ewcefH>`_.
61-
62-
`Generate an API Key <https://kucoin.com/account/api>`_
63-
or `Generate an API Key in Sandbox <https://sandbox.kucoin.com/account/api>`_ and enable it.
61+
`Generate an API Key <https://kucoin.com/account/api>`_.
6462

6563
.. code:: bash
6664
6765
pip install python-kucoin
6866
6967
.. code:: python
7068
71-
from kucoin.client import Client
69+
from kucoin import Client
7270
7371
api_key = '<api_key>'
7472
api_secret = '<api_secret>'
7573
api_passphrase = '<api_passphrase>'
7674
7775
client = Client(api_key, api_secret, api_passphrase)
7876
79-
# or connect to Sandbox
80-
# client = Client(api_key, api_secret, api_passphrase, sandbox=True)
81-
8277
# get currencies
8378
currencies = client.get_currencies()
8479
@@ -97,6 +92,23 @@ or `Generate an API Key in Sandbox <https://sandbox.kucoin.com/account/api>`_ an
9792
# get list of active orders
9893
orders = client.get_active_orders('KCS-BTC')
9994
95+
96+
Async
97+
-----
98+
99+
.. code:: python
100+
101+
from kucoin import AsyncClient
102+
103+
api_key = '<api_key>'
104+
api_secret = '<api_secret>'
105+
api_passphrase = '<api_passphrase>'
106+
107+
client = AsyncClient(api_key, api_secret, api_passphrase)
108+
109+
# get currencies
110+
currencies = await client.get_currencies()
111+
100112
Websockets
101113
----------
102114

@@ -199,5 +211,6 @@ For more `check out the documentation <https://python-kucoin.readthedocs.io/en/l
199211
Other Exchanges
200212
---------------
201213

202-
If you use `Binance <https://www.binance.com/?ref=10099792>`_ check out my `python-binance <https://github.com/sammchardy/python-binance>`_ library.
214+
- If you use `Binance <https://accounts.binance.com/register?ref=PGDFCE46>`_ check out my `python-binance <https://github.com/sammchardy/python-binance>`_ library.
215+
- Check out `CCXT <https://github.com/ccxt/ccxt>`_ for more than 100 crypto exchanges with a unified trading API.
203216

build/generateAsyncClient.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import fs from 'fs'
2+
3+
const SOURSE_FILE_NAME = './kucoin/client.py'
4+
const TARGET_FILE_NAME = './kucoin/async_client.py'
5+
const METHOD_DEFINITION_MATCH = /def\s(\w+)/
6+
const METHOD_CALL_MATCH = /self\.(\w+)\(/
7+
const DEFINITION_PREFIX = 'def'
8+
const ASYNC_DEFINITION_PREFIX = 'async def'
9+
const CALL_PREFIX = 'self.'
10+
const ASYNC_CALL_PREFIX = 'await self.'
11+
const SPECIAL_REPLACEMENTS = {} // Add special replacements here
12+
const SPECIAL_REPLACEMENTS_KEYS = Object.keys (SPECIAL_REPLACEMENTS)
13+
14+
function replaceKeywords (data) {
15+
const lines = data.split ('\n')
16+
const asyncClient = [ ] as any
17+
for (let line of lines) {
18+
let specialMatch = false
19+
for (let key of SPECIAL_REPLACEMENTS_KEYS) {
20+
if (line.includes (key)) {
21+
asyncClient.push (line.replace (key, SPECIAL_REPLACEMENTS[key]))
22+
delete SPECIAL_REPLACEMENTS[key]
23+
specialMatch = true
24+
break
25+
}
26+
}
27+
if (specialMatch) {
28+
continue
29+
}
30+
if (line.startsWith('class Client(BaseClient):')) {
31+
asyncClient.push ('class AsyncClient(AsyncClientBase):')
32+
continue
33+
}
34+
if (line.startsWith('from .base_client import BaseClient')) {
35+
asyncClient.push ('from .async_client_base import AsyncClientBase')
36+
continue
37+
}
38+
const methodDefinition = line.match (METHOD_DEFINITION_MATCH)
39+
const methodCall = line.match (METHOD_CALL_MATCH)
40+
const match = methodDefinition || methodCall
41+
if (match) {
42+
const methodName = match[1]
43+
if (methodName !== '__init__') {
44+
if (methodDefinition) {
45+
line = line.replace (DEFINITION_PREFIX, ASYNC_DEFINITION_PREFIX)
46+
} else if (methodCall) {
47+
line = line.replace (CALL_PREFIX, ASYNC_CALL_PREFIX)
48+
}
49+
}
50+
// let replacementRequired = true
51+
// if (methodName.startsWith ('_')) {
52+
// replacementRequired = false
53+
// }
54+
55+
}
56+
asyncClient.push (line)
57+
}
58+
return asyncClient.join ('\n')
59+
}
60+
61+
function main () {
62+
fs.readFile (SOURSE_FILE_NAME, 'utf8', (err, data) => {
63+
if (err) {
64+
console.error (err)
65+
return
66+
}
67+
const asyncClient = replaceKeywords (data)
68+
fs.writeFile (TARGET_FILE_NAME, asyncClient, (err) => {
69+
if (err) {
70+
console.error (err)
71+
return
72+
}
73+
console.log (TARGET_FILE_NAME + ' file is generated')})
74+
})
75+
}
76+
77+
main ()

examples/create_order_async.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
import os
3+
import sys
4+
import asyncio
5+
6+
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7+
sys.path.append(root)
8+
9+
from kucoin import AsyncClient
10+
11+
api_key = os.environ.get('KUCOIN_APIKEY')
12+
api_secret = os.environ.get('KUCOIN_SECRET')
13+
api_passphrase = os.environ.get('KUCOIN_PASSWORD')
14+
15+
async def main():
16+
client = AsyncClient(api_key, api_secret, api_passphrase)
17+
18+
order = await client.create_market_order('LTC-USDT', AsyncClient.SIDE_SELL, size=0.1)
19+
20+
print(order)
21+
22+
asyncio.run(main())

kucoin/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,14 @@
44
55
"""
66

7-
__version__ = '2.1.3'
7+
__version__ = "2.1.3"
8+
9+
from kucoin.client import Client # noqa
10+
from kucoin.async_client import AsyncClient # noqa
11+
12+
from kucoin.exceptions import (
13+
KucoinAPIException, # noqa
14+
KucoinRequestException, # noqa
15+
MarketOrderException, # noqa
16+
LimitOrderException, # noqa
17+
)

0 commit comments

Comments
 (0)