Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
91fee83
add set auto earn endpoint
Dec 15, 2025
7a4fa53
feat: add idxVol and fix wrong params for posBuilder
Dec 16, 2025
f8847a9
feat: add unit-testing for the test_account
Dec 16, 2025
0234ece
add set auto earn endpoint
Dec 16, 2025
31fd401
add id parameter to all websocket subscription
Dec 16, 2025
14c3a94
websocket enhancement
Dec 17, 2025
12ebac7
创建0.4.1版本分支
Dec 18, 2025
f78c2fe
add set auto earn endpoint
Dec 18, 2025
e82ee55
feat: add idxVol and fix wrong params for posBuilder
Dec 16, 2025
3f739c2
feat: add unit-testing for the test_account
Dec 16, 2025
94c2070
websocket enhancement
Dec 18, 2025
1f0a83d
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 18, 2025
a392b53
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 18, 2025
0f4d44c
websocket enhancement
Dec 18, 2025
2839e7f
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 18, 2025
69a416a
add /api/v5/account/set-auto-earn endpoint
Dec 18, 2025
68fa15c
add /api/v5/account/set-auto-earn endpoint
Dec 19, 2025
3aebd72
add toAddrType to the 3 withdrawal endpoints
Dec 16, 2025
7398c55
add toAddrType to the 3 withdrawal endpoints
Dec 18, 2025
df68d90
add toAddrType to the 3 withdrawal endpoints
Dec 19, 2025
19f7393
add toAddrType to the 3 withdrawal endpoints
Dec 19, 2025
759c054
add market-data-history endpoint
Dec 17, 2025
46817fe
add market-data-history endpoint
Dec 18, 2025
4b165d0
add market-data-history endpoint
Dec 19, 2025
4391f0e
add /api/v5/account/set-auto-earn endpoint
Dec 19, 2025
2f9fea9
http version compatibility issue
Dec 17, 2025
ed85a8c
confirm if it's version compatibility issue
Dec 18, 2025
0023ce6
confirm if it's version compatibility issue
Dec 19, 2025
e02411c
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 19, 2025
6746db7
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 19, 2025
500baa6
add id parameter to all websocket subscription
Dec 19, 2025
69af821
add id parameter to all websocket subscription
Dec 19, 2025
240216f
Merge pull request #125 from okxapi/dev/BROK-741
okxapi Dec 19, 2025
892bc6b
Merge pull request #128 from okxapi/dev/BROK-1214
okxapi Dec 19, 2025
e808427
feat: add api changes
Dec 19, 2025
61562c4
websocket enhancement
Dec 19, 2025
32706d9
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 19, 2025
11efc37
feat: add ci cd
Dec 19, 2025
b6c3b83
websocket enhancement
Dec 19, 2025
81c269c
feat: add ci cd and remove wrong commit for gitlab
Dec 19, 2025
89e8e25
feat: add cicd
Dec 19, 2025
2d47171
fix: missing import
Dec 19, 2025
ee04e6b
fix: broken testing
Dec 19, 2025
34cf7c4
Merge pull request #130 from okxapi/dev-add-cicd
okxapi Dec 19, 2025
40e7629
Merge branch 'dev-add-cicd' to dev-add-px-amend-type-and-trade-quote-…
Dec 19, 2025
75a20fc
feat: add .env
Dec 19, 2025
6cee7dc
feat: rmv changes
Dec 19, 2025
128da2d
fix: add testing files
Dec 19, 2025
ee3c263
websocket enhancement
Dec 22, 2025
a2b7fb0
Merge pull request #133 from okxapi/dev-add-px-amend-type-and-trade-q…
okxapi Dec 22, 2025
3f53945
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 22, 2025
4813e7e
websocket enhancement
Dec 22, 2025
8d0e78e
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 22, 2025
9dfb5b6
websocket enhancement
Dec 22, 2025
fb237f6
websocket enhancement
Dec 22, 2025
2dfafef
config update
Dec 22, 2025
1fb02f4
Merge pull request #134 from okxapi/dev/config_update
okxapi Dec 22, 2025
883901f
Merge remote-tracking branch 'origin/release/version_0.4.1' into dev/…
Dec 22, 2025
7172e8e
Merge pull request #124 from okxapi/dev/BROK-653
okxapi Dec 22, 2025
c35c355
feat: add dependency file and cicd
Dec 22, 2025
a278d23
feat: rmv requirements-dev.txt
Dec 22, 2025
299acc4
fix: ci build failure
Dec 22, 2025
2b2936a
fix: ci build failure
Dec 22, 2025
b3973c7
Merge pull request #135 from okxapi/dev-add-requirements-files
okxapi Dec 22, 2025
7e40b52
add tradeQuoteCcy request param to the trade-related endpoints
Dec 22, 2025
93672c1
Merge pull request #136 from okxapi/dev/BROK-1216
okxapi Dec 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# OKX API Credentials
# Copy this file to .env and fill in your actual credentials
# NEVER commit .env to version control!

OKX_API_KEY=your_api_key_here
OKX_API_SECRET=your_api_secret_here
OKX_PASSPHRASE=your_passphrase_here

# Optional: Set to '0' for live trading, '1' for demo trading
OKX_FLAG=1
173 changes: 173 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# GitHub Actions CI/CD Configuration for python-okx
name: CI

on:
push:
branches:
- master
- 'release/*'
- 'releases/*'
pull_request:
branches:
- master
- 'release/*'
- 'releases/*'

jobs:
# ============================================
# DEPENDENCY CHECK JOB
# Ensures all imports are satisfied by requirements.txt
# ============================================
dependency-check:
name: Dependency Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install only from requirements.txt (clean environment)
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Verify all production imports work
run: |
# This catches missing dependencies in requirements.txt
python -c "
import okx
from okx import Account, Trade, Funding, MarketData, PublicData
from okx import SubAccount, Convert, BlockTrading, CopyTrading
from okx import SpreadTrading, Grid, TradingData, Status
from okx.websocket import WsPublicAsync, WsPrivateAsync
print('✅ All imports successful')
print(f' okx version: {okx.__version__}')
"

- name: Verify test imports
run: |
pip install pytest
python -c "
import pytest
import unittest
print('✅ Test imports successful')
"

# ============================================
# LINT JOB
# ============================================
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install linting tools
run: |
python -m pip install --upgrade pip
pip install ruff

- name: Run ruff
run: |
ruff check okx/ --ignore=E501
continue-on-error: true # Set to false once codebase is cleaned up

# ============================================
# TEST JOB
# ============================================
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
needs: [dependency-check] # Only run tests if dependencies are valid
strategy:
fail-fast: true
max-parallel: 1
matrix:
python-version: ["3.9", "3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.python-version }}-
${{ runner.os }}-pip-

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -e .

- name: Run tests
run: |
python -m pytest test/unit/ -v --cov=okx --cov-report=term-missing --cov-report=xml

- name: Upload coverage to Codecov
if: matrix.python-version == '3.12'
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
fail_ci_if_error: false

# ============================================
# BUILD JOB
# ============================================
build:
name: Build Package
runs-on: ubuntu-latest
needs: [test]

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Build package
run: python -m build --no-isolation

- name: Check package
run: twine check dist/*

- name: Test install from wheel (clean environment)
run: |
# Create a fresh venv and install the built wheel
python -m venv /tmp/test-install
/tmp/test-install/bin/pip install dist/*.whl
/tmp/test-install/bin/python -c "
import okx
from okx import Account, Trade, Funding
print(f'✅ Package installs correctly: okx {okx.__version__}')
"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ build/

### VS Code ###
.vscode/
id_rsa*
id_rsa*

# Environment files
.env
.env.local
.env.*.local
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include requirements.txt
include README.md

72 changes: 66 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,80 @@ Make sure you update often and check the [Changelog](https://www.okx.com/docs-v5
### Quick start
#### Prerequisites

`python version:>=3.9`
`python version:>=3.7`

`WebSocketAPI: websockets package advise version 6.0`

#### Step 1: register an account on OKX and apply for an API key
#### Step 1: Register an account on OKX and apply for an API key
- Register for an account: https://www.okx.com/account/register
- Apply for an API key: https://www.okx.com/account/users/myApi

#### Step 2: install python-okx
#### Step 2: Install python-okx

```python
```bash
pip install python-okx
```

### API Credentials

#### Option 1: Hardcoded credentials

```python
from okx import Account

account = Account.AccountAPI(
api_key="your-api-key-here",
api_secret_key="your-api-secret-here",
passphrase="your-passphrase-here",
flag="1", # 0 = live trading, 1 = demo trading
debug=False
)
```

#### Option 2: Using `.env` file (recommended)

Create a `.env` file in your project root:

```bash
OKX_API_KEY=your-api-key-here
OKX_API_SECRET=your-api-secret-here
OKX_PASSPHRASE=your-passphrase-here
OKX_FLAG=1
```

Then load it in your code:

```python
import os
from dotenv import load_dotenv
from okx import Account

load_dotenv()

account = Account.AccountAPI(
api_key=os.getenv('OKX_API_KEY'),
api_secret_key=os.getenv('OKX_API_SECRET'),
passphrase=os.getenv('OKX_PASSPHRASE'),
flag=os.getenv('OKX_FLAG', '1'),
debug=False
)
```

### Development Setup

For contributors or local development:

```bash
# Clone the repository
git clone https://github.com/okxapi/python-okx.git
cd python-okx

# Install dependencies
pip install -r requirements.txt
pip install -e .

# Run tests
pytest test/unit/ -v
```

#### Step 3: Run examples

- Fill in API credentials in the corresponding examples
Expand Down
28 changes: 21 additions & 7 deletions okx/Account.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,23 @@ def get_positions(self, instType='', instId='', posId=''):
params = {'instType': instType, 'instId': instId, 'posId': posId}
return self._request_with_params(GET, POSITION_INFO, params)

def position_builder(self, acctLv=None,inclRealPosAndEq=False, lever=None, greeksType=None, simPos=None,
simAsset=None):
def position_builder(self, acctLv=None, inclRealPosAndEq=None, lever=None, greeksType=None, simPos=None,
simAsset=None, idxVol=None):
params = {}
if acctLv is not None:
params['acctLv'] = acctLv
if inclRealPosAndEq is not None:
params['inclRealPosAndEq'] = inclRealPosAndEq
if lever is not None:
params['spotOffsetType'] = lever
params['lever'] = lever
if greeksType is not None:
params['greksType'] = greeksType
params['greeksType'] = greeksType
if simPos is not None:
params['simPos'] = simPos
if simAsset is not None:
params['simAsset'] = simAsset
if idxVol is not None:
params['idxVol'] = idxVol
return self._request_with_params(POST, POSITION_BUILDER, params)

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

# Get Maximum Tradable Size For Instrument
def get_max_order_size(self, instId, tdMode, ccy='', px=''):
def get_max_order_size(self, instId, tdMode, ccy='', px='', tradeQuoteCcy=None):
params = {'instId': instId, 'tdMode': tdMode, 'ccy': ccy, 'px': px}
if tradeQuoteCcy is not None:
params['tradeQuoteCcy'] = tradeQuoteCcy
return self._request_with_params(GET, MAX_TRADE_SIZE, params)

# Get Maximum Available Tradable Amount
def get_max_avail_size(self, instId, tdMode, ccy='', reduceOnly='', unSpotOffset='', quickMgnType=''):
def get_max_avail_size(self, instId, tdMode, ccy='', reduceOnly='', unSpotOffset='', quickMgnType='', tradeQuoteCcy=None):
params = {'instId': instId, 'tdMode': tdMode, 'ccy': ccy, 'reduceOnly': reduceOnly,
'unSpotOffset': unSpotOffset, 'quickMgnType': quickMgnType}
if tradeQuoteCcy is not None:
params['tradeQuoteCcy'] = tradeQuoteCcy
return self._request_with_params(GET, MAX_AVAIL_SIZE, params)

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

# Get the maximum loan of isolated MARGIN
def get_max_loan(self, instId, mgnMode, mgnCcy=''):
def get_max_loan(self, instId, mgnMode, mgnCcy='', tradeQuoteCcy=None):
params = {'instId': instId, 'mgnMode': mgnMode, 'mgnCcy': mgnCcy}
if tradeQuoteCcy is not None:
params['tradeQuoteCcy'] = tradeQuoteCcy
return self._request_with_params(GET, MAX_LOAN, params)

# Get Fee Rates
Expand Down Expand Up @@ -323,3 +331,9 @@ def set_auto_repay(self, autoRepay=False):
def spot_borrow_repay_history(self, ccy='', type='', after='', before='', limit=''):
params = {'ccy': ccy, 'type': type, 'after': after, 'before': before, 'limit': limit}
return self._request_with_params(GET, GET_BORROW_REPAY_HISTORY, params)

def set_auto_earn(self, ccy, action, earnType=None):
params = {'ccy': ccy, 'action': action}
if earnType is not None:
params['earnType'] = earnType
return self._request_with_params(POST, SET_AUTO_EARN, params)
13 changes: 7 additions & 6 deletions okx/Funding.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ def funds_transfer(self, ccy, amt, from_, to, type='0', subAcct='', instId='', t
return self._request_with_params(POST, FUNDS_TRANSFER, params)

# Withdrawal
def withdrawal(self, ccy, amt, dest, toAddr, chain='', areaCode='', clientId=''):
def withdrawal(self, ccy, amt, dest, toAddr, chain='', areaCode='', clientId='', toAddrType=None):
params = {'ccy': ccy, 'amt': amt, 'dest': dest, 'toAddr': toAddr, 'chain': chain,
'areaCode': areaCode, 'clientId': clientId}
if toAddrType is not None:
params['toAddrType'] = toAddrType
return self._request_with_params(POST, WITHDRAWAL_COIN, params)

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

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


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

#Get withdrawal history
def get_withdrawal_history(self, ccy='', wdId='', clientId='', txId='', type='', state='', after='', before ='', limit=''):
def get_withdrawal_history(self, ccy='', wdId='', clientId='', txId='', type='', state='', after='', before='', limit='', toAddrType=None):
params = {'ccy': ccy, 'wdId': wdId, 'clientId': clientId, 'txId': txId, 'type': type, 'state': state, 'after': after, 'before': before, 'limit': limit}
if toAddrType is not None:
params['toAddrType'] = toAddrType
return self._request_with_params(GET, GET_WITHDRAWAL_HISTORY, params)

Loading
Loading