Skip to content

Commit eeb851e

Browse files
authored
Merge pull request #131 from okxapi/release/version_0.4.1
Release/version 0.4.1
2 parents 46974ba + 41b3bda commit eeb851e

51 files changed

Lines changed: 3683 additions & 228 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# OKX API Credentials
2+
# Copy this file to .env and fill in your actual credentials
3+
# NEVER commit .env to version control!
4+
5+
OKX_API_KEY=your_api_key_here
6+
OKX_API_SECRET=your_api_secret_here
7+
OKX_PASSPHRASE=your_passphrase_here
8+
9+
# Optional: Set to '0' for live trading, '1' for demo trading
10+
OKX_FLAG=1

.github/workflows/ci.yml

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# GitHub Actions CI/CD Configuration for python-okx
2+
name: CI
3+
4+
on:
5+
push:
6+
branches:
7+
- master
8+
- 'release/*'
9+
- 'releases/*'
10+
pull_request:
11+
branches:
12+
- master
13+
- 'release/*'
14+
- 'releases/*'
15+
16+
jobs:
17+
# ============================================
18+
# DEPENDENCY CHECK JOB
19+
# Ensures all imports are satisfied by requirements.txt
20+
# ============================================
21+
dependency-check:
22+
name: Dependency Check
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Set up Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: "3.11"
31+
32+
- name: Install only from requirements.txt (clean environment)
33+
run: |
34+
python -m pip install --upgrade pip
35+
pip install -r requirements.txt
36+
37+
- name: Verify all production imports work
38+
run: |
39+
# This catches missing dependencies in requirements.txt
40+
python -c "
41+
import okx
42+
from okx import Account, Trade, Funding, MarketData, PublicData
43+
from okx import SubAccount, Convert, BlockTrading, CopyTrading
44+
from okx import SpreadTrading, Grid, TradingData, Status
45+
from okx.websocket import WsPublicAsync, WsPrivateAsync
46+
print('✅ All imports successful')
47+
print(f' okx version: {okx.__version__}')
48+
"
49+
50+
- name: Verify test imports
51+
run: |
52+
pip install pytest
53+
python -c "
54+
import pytest
55+
import unittest
56+
print('✅ Test imports successful')
57+
"
58+
59+
# ============================================
60+
# LINT JOB
61+
# ============================================
62+
lint:
63+
name: Lint
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@v4
67+
68+
- name: Set up Python
69+
uses: actions/setup-python@v5
70+
with:
71+
python-version: "3.11"
72+
73+
- name: Install linting tools
74+
run: |
75+
python -m pip install --upgrade pip
76+
pip install ruff
77+
78+
- name: Run ruff
79+
run: |
80+
ruff check okx/ --ignore=E501
81+
continue-on-error: true # Set to false once codebase is cleaned up
82+
83+
# ============================================
84+
# TEST JOB
85+
# ============================================
86+
test:
87+
name: Test (Python ${{ matrix.python-version }})
88+
runs-on: ubuntu-latest
89+
needs: [dependency-check] # Only run tests if dependencies are valid
90+
strategy:
91+
fail-fast: true
92+
max-parallel: 1
93+
matrix:
94+
python-version: ["3.9", "3.12"]
95+
96+
steps:
97+
- uses: actions/checkout@v4
98+
99+
- name: Set up Python ${{ matrix.python-version }}
100+
uses: actions/setup-python@v5
101+
with:
102+
python-version: ${{ matrix.python-version }}
103+
104+
- name: Cache pip dependencies
105+
uses: actions/cache@v4
106+
with:
107+
path: ~/.cache/pip
108+
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }}
109+
restore-keys: |
110+
${{ runner.os }}-pip-${{ matrix.python-version }}-
111+
${{ runner.os }}-pip-
112+
113+
- name: Install dependencies
114+
run: |
115+
python -m pip install --upgrade pip
116+
pip install -r requirements.txt
117+
pip install -e .
118+
119+
- name: Run tests
120+
run: |
121+
python -m pytest test/unit/ -v --cov=okx --cov-report=term-missing --cov-report=xml
122+
123+
- name: Upload coverage to Codecov
124+
if: matrix.python-version == '3.12'
125+
uses: codecov/codecov-action@v4
126+
with:
127+
file: ./coverage.xml
128+
fail_ci_if_error: false
129+
130+
# ============================================
131+
# BUILD JOB
132+
# ============================================
133+
build:
134+
name: Build Package
135+
runs-on: ubuntu-latest
136+
needs: [test]
137+
138+
steps:
139+
- uses: actions/checkout@v4
140+
141+
- name: Set up Python
142+
uses: actions/setup-python@v5
143+
with:
144+
python-version: "3.11"
145+
146+
- name: Install dependencies
147+
run: |
148+
python -m pip install --upgrade pip
149+
pip install -r requirements.txt
150+
151+
- name: Build package
152+
run: python -m build --no-isolation
153+
154+
- name: Check package
155+
run: twine check dist/*
156+
157+
- name: Test install from wheel (clean environment)
158+
run: |
159+
# Create a fresh venv and install the built wheel
160+
python -m venv /tmp/test-install
161+
/tmp/test-install/bin/pip install dist/*.whl
162+
/tmp/test-install/bin/python -c "
163+
import okx
164+
from okx import Account, Trade, Funding
165+
print(f'✅ Package installs correctly: okx {okx.__version__}')
166+
"
167+
168+
- name: Upload build artifacts
169+
uses: actions/upload-artifact@v4
170+
with:
171+
name: dist
172+
path: dist/
173+
retention-days: 7

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,9 @@ build/
3232

3333
### VS Code ###
3434
.vscode/
35-
id_rsa*
35+
id_rsa*
36+
37+
# Environment files
38+
.env
39+
.env.local
40+
.env.*.local

MANIFEST.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include requirements.txt
2+
include README.md
3+

README.md

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,80 @@ Make sure you update often and check the [Changelog](https://www.okx.com/docs-v5
2020
### Quick start
2121
#### Prerequisites
2222

23-
`python version:>=3.9`
23+
`python version:>=3.7`
2424

25-
`WebSocketAPI: websockets package advise version 6.0`
26-
27-
#### Step 1: register an account on OKX and apply for an API key
25+
#### Step 1: Register an account on OKX and apply for an API key
2826
- Register for an account: https://www.okx.com/account/register
2927
- Apply for an API key: https://www.okx.com/account/users/myApi
3028

31-
#### Step 2: install python-okx
29+
#### Step 2: Install python-okx
3230

33-
```python
31+
```bash
3432
pip install python-okx
3533
```
3634

35+
### API Credentials
36+
37+
#### Option 1: Hardcoded credentials
38+
39+
```python
40+
from okx import Account
41+
42+
account = Account.AccountAPI(
43+
api_key="your-api-key-here",
44+
api_secret_key="your-api-secret-here",
45+
passphrase="your-passphrase-here",
46+
flag="1", # 0 = live trading, 1 = demo trading
47+
debug=False
48+
)
49+
```
50+
51+
#### Option 2: Using `.env` file (recommended)
52+
53+
Create a `.env` file in your project root:
54+
55+
```bash
56+
OKX_API_KEY=your-api-key-here
57+
OKX_API_SECRET=your-api-secret-here
58+
OKX_PASSPHRASE=your-passphrase-here
59+
OKX_FLAG=1
60+
```
61+
62+
Then load it in your code:
63+
64+
```python
65+
import os
66+
from dotenv import load_dotenv
67+
from okx import Account
68+
69+
load_dotenv()
70+
71+
account = Account.AccountAPI(
72+
api_key=os.getenv('OKX_API_KEY'),
73+
api_secret_key=os.getenv('OKX_API_SECRET'),
74+
passphrase=os.getenv('OKX_PASSPHRASE'),
75+
flag=os.getenv('OKX_FLAG', '1'),
76+
debug=False
77+
)
78+
```
79+
80+
### Development Setup
81+
82+
For contributors or local development:
83+
84+
```bash
85+
# Clone the repository
86+
git clone https://github.com/okxapi/python-okx.git
87+
cd python-okx
88+
89+
# Install dependencies
90+
pip install -r requirements.txt
91+
pip install -e .
92+
93+
# Run tests
94+
pytest test/unit/ -v
95+
```
96+
3797
#### Step 3: Run examples
3898

3999
- Fill in API credentials in the corresponding examples

okx/Account.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,23 @@ def get_positions(self, instType='', instId='', posId=''):
2727
params = {'instType': instType, 'instId': instId, 'posId': posId}
2828
return self._request_with_params(GET, POSITION_INFO, params)
2929

30-
def position_builder(self, acctLv=None,inclRealPosAndEq=False, lever=None, greeksType=None, simPos=None,
31-
simAsset=None):
30+
def position_builder(self, acctLv=None, inclRealPosAndEq=None, lever=None, greeksType=None, simPos=None,
31+
simAsset=None, idxVol=None):
3232
params = {}
3333
if acctLv is not None:
3434
params['acctLv'] = acctLv
3535
if inclRealPosAndEq is not None:
3636
params['inclRealPosAndEq'] = inclRealPosAndEq
3737
if lever is not None:
38-
params['spotOffsetType'] = lever
38+
params['lever'] = lever
3939
if greeksType is not None:
40-
params['greksType'] = greeksType
40+
params['greeksType'] = greeksType
4141
if simPos is not None:
4242
params['simPos'] = simPos
4343
if simAsset is not None:
4444
params['simAsset'] = simAsset
45+
if idxVol is not None:
46+
params['idxVol'] = idxVol
4547
return self._request_with_params(POST, POSITION_BUILDER, params)
4648

4749
# Get Bills Details (recent 7 days)
@@ -74,14 +76,18 @@ def set_leverage(self, lever, mgnMode, instId='', ccy='', posSide=''):
7476
return self._request_with_params(POST, SET_LEVERAGE, params)
7577

7678
# Get Maximum Tradable Size For Instrument
77-
def get_max_order_size(self, instId, tdMode, ccy='', px=''):
79+
def get_max_order_size(self, instId, tdMode, ccy='', px='', tradeQuoteCcy=None):
7880
params = {'instId': instId, 'tdMode': tdMode, 'ccy': ccy, 'px': px}
81+
if tradeQuoteCcy is not None:
82+
params['tradeQuoteCcy'] = tradeQuoteCcy
7983
return self._request_with_params(GET, MAX_TRADE_SIZE, params)
8084

8185
# Get Maximum Available Tradable Amount
82-
def get_max_avail_size(self, instId, tdMode, ccy='', reduceOnly='', unSpotOffset='', quickMgnType=''):
86+
def get_max_avail_size(self, instId, tdMode, ccy='', reduceOnly='', unSpotOffset='', quickMgnType='', tradeQuoteCcy=None):
8387
params = {'instId': instId, 'tdMode': tdMode, 'ccy': ccy, 'reduceOnly': reduceOnly,
8488
'unSpotOffset': unSpotOffset, 'quickMgnType': quickMgnType}
89+
if tradeQuoteCcy is not None:
90+
params['tradeQuoteCcy'] = tradeQuoteCcy
8591
return self._request_with_params(GET, MAX_AVAIL_SIZE, params)
8692

8793
# Increase / Decrease margin
@@ -100,8 +106,10 @@ def get_instruments(self, instType='', ugly='', instFamily='', instId=''):
100106
return self._request_with_params(GET, GET_INSTRUMENTS, params)
101107

102108
# Get the maximum loan of isolated MARGIN
103-
def get_max_loan(self, instId, mgnMode, mgnCcy=''):
109+
def get_max_loan(self, instId, mgnMode, mgnCcy='', tradeQuoteCcy=None):
104110
params = {'instId': instId, 'mgnMode': mgnMode, 'mgnCcy': mgnCcy}
111+
if tradeQuoteCcy is not None:
112+
params['tradeQuoteCcy'] = tradeQuoteCcy
105113
return self._request_with_params(GET, MAX_LOAN, params)
106114

107115
# Get Fee Rates
@@ -323,3 +331,9 @@ def set_auto_repay(self, autoRepay=False):
323331
def spot_borrow_repay_history(self, ccy='', type='', after='', before='', limit=''):
324332
params = {'ccy': ccy, 'type': type, 'after': after, 'before': before, 'limit': limit}
325333
return self._request_with_params(GET, GET_BORROW_REPAY_HISTORY, params)
334+
335+
def set_auto_earn(self, ccy, action, earnType=None):
336+
params = {'ccy': ccy, 'action': action}
337+
if earnType is not None:
338+
params['earnType'] = earnType
339+
return self._request_with_params(POST, SET_AUTO_EARN, params)

okx/Funding.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ def funds_transfer(self, ccy, amt, from_, to, type='0', subAcct='', instId='', t
3535
return self._request_with_params(POST, FUNDS_TRANSFER, params)
3636

3737
# Withdrawal
38-
def withdrawal(self, ccy, amt, dest, toAddr, chain='', areaCode='', clientId=''):
38+
def withdrawal(self, ccy, amt, dest, toAddr, chain='', areaCode='', clientId='', toAddrType=None):
3939
params = {'ccy': ccy, 'amt': amt, 'dest': dest, 'toAddr': toAddr, 'chain': chain,
4040
'areaCode': areaCode, 'clientId': clientId}
41+
if toAddrType is not None:
42+
params['toAddrType'] = toAddrType
4143
return self._request_with_params(POST, WITHDRAWAL_COIN, params)
4244

4345
# Get Deposit History
@@ -46,10 +48,7 @@ def get_deposit_history(self, ccy='', type='', state='', after='', before='', li
4648
'depId': depId, 'fromWdId': fromWdId}
4749
return self._request_with_params(GET, DEPOSIT_HISTORY, params)
4850

49-
# Get Withdrawal History
50-
def get_withdrawal_history(self, ccy='', wdId='', state='', after='', before='', limit='',txId=''):
51-
params = {'ccy': ccy, 'wdId': wdId, 'state': state, 'after': after, 'before': before, 'limit': limit,'txId':txId}
52-
return self._request_with_params(GET, WITHDRAWAL_HISTORY, params)
51+
5352

5453
# Get Currencies
5554
def get_currencies(self, ccy=''):
@@ -113,7 +112,9 @@ def get_deposit_withdraw_status(self, wdId='', txId='', ccy='', to='', chain='')
113112
return self._request_with_params(GET, GET_DEPOSIT_WITHDrAW_STATUS, params)
114113

115114
#Get withdrawal history
116-
def get_withdrawal_history(self, ccy='', wdId='', clientId='', txId='', type='', state='', after='', before ='', limit=''):
115+
def get_withdrawal_history(self, ccy='', wdId='', clientId='', txId='', type='', state='', after='', before='', limit='', toAddrType=None):
117116
params = {'ccy': ccy, 'wdId': wdId, 'clientId': clientId, 'txId': txId, 'type': type, 'state': state, 'after': after, 'before': before, 'limit': limit}
117+
if toAddrType is not None:
118+
params['toAddrType'] = toAddrType
118119
return self._request_with_params(GET, GET_WITHDRAWAL_HISTORY, params)
119120

0 commit comments

Comments
 (0)