Primitives and utilities for automated trading strategies.
Project description
Cybotrade
Primitives and utilities for building automated trading strategies.
Cybotrade is a Python library for writing live, event-driven crypto trading
strategies. It gives you a single, consistent interface across multiple
exchanges (REST + private WebSocket), a built-in market-data layer, a job
scheduler, and a BaseStrategy harness that wires everything together so you
can focus on strategy logic instead of plumbing.
The performance-critical core (HTTP client, WebSocket transport, symbol/topic parsing) is implemented in Rust via PyO3 and shipped as a compiled extension, so there is no Rust toolchain required to use it.
Features
- Unified exchange interface — one
ExchangeClientabstraction for REST trading (place/cancel orders, positions, balances, order details, orderbook, symbol info) across all supported venues. - Private WebSocket streams — authenticated order-update streams with automatic heartbeating and reconnection.
- Market data — pull historical and streaming data through
cybotrade-datasourceusing a simpleTopicmodel, delivered as Polars DataFrames. - Strategy harness —
BaseStrategyruns your scheduled jobs, exchange events, and datasource stream together under one asyncio event loop, with gracefulSIGINT/SIGTERMshutdown. - Built-in scheduler — cron/interval/date job scheduling via
aion. - Typed throughout — ships with
py.typedand stub files; rich dataclass models (OrderUpdate,Position,Balance,SymbolInfo, …) andDecimalprecision for prices and quantities. - Logging helpers — colorized console and rotating-file handlers.
Supported exchanges
| Exchange | REST client | Private WebSocket |
|---|---|---|
| Bybit | BybitLinearClient |
BybitPrivateWS |
| Binance | BinanceLinearClient |
BinancePrivateWS |
| KuCoin | KucoinLinearClient |
KucoinPrivateWS |
| EdgeX | EdgeXClient |
EdgeXPrivateWS |
All exchange clients currently target linear (USDⓈ-M) perpetual markets.
Installation
pip install cybotrade
Requires Python 3.12+. Pre-built wheels are published for macOS
(universal2), Linux (x86_64 + aarch64), and Windows (x86_64), so no
compilation is needed on those platforms.
Quick start
Placing an order
import asyncio
from decimal import Decimal
from cybotrade import Symbol
from cybotrade.models import OrderSide
from cybotrade.bybit import BybitLinearClient
async def main():
client = BybitLinearClient(api_key="...", api_secret="...", testnet=True)
# Inspect the symbol's trading rules
info = await client.get_symbol_info(Symbol("BTCUSDT"))
print(info.quantity_precision, info.tick_size)
# Market buy 0.001 BTC
resp = await client.place_order(
symbol=Symbol("BTCUSDT"),
side=OrderSide.BUY,
quantity=Decimal("0.001"),
)
print(resp.order_id)
# Check the resulting position
positions = await client.get_positions(Symbol("BTCUSDT"))
print(positions)
asyncio.run(main())
Writing a strategy
BaseStrategy ties together three sources of work — a scheduler, an
exchange event stream, and an optional datasource stream — and drives
them from a single start() call. Subclass it and implement on_init,
on_event, and on_shutdown.
import asyncio
from datetime import timedelta
from aion import Trigger
from cybotrade import Symbol, Topic
from cybotrade.io import Event, EventType
from cybotrade.strategy import BaseStrategy
from cybotrade.bybit import BybitLinearClient, BybitPrivateWS
class MyStrategy(BaseStrategy):
def __init__(self, trader, events):
self.trader = trader
self.events = events
super().__init__(
datasource_api_key="DATASOURCE_API_KEY",
datasource_topics=[
Topic("bybit-linear", "candle", {"symbol": "BTCUSDT", "interval": "1m"}),
],
lookback_size=200,
)
def on_init(self):
# Register a recurring job (runs every 60s)
asyncio.get_event_loop().create_task(
self.schedule(self.rebalance, Trigger.Interval(duration=timedelta(minutes=1)))
)
async def rebalance(self):
price = await self.trader.get_current_price(Symbol("BTCUSDT"))
self.logger.info(f"mid price = {price}")
async def on_event(self, event: Event):
if event.event_type == EventType.DatasourceUpdate:
topic = ... # identify which subscribed Topic this update belongs to
ready = self.maintain_datamap(topic, event.data["data"])
if ready:
df = self.datamap[topic] # Polars DataFrame of the last N candles
... # compute signals, place orders via self.trader
elif event.event_type == EventType.OrderUpdate:
self.logger.info(f"order update: {event.data}")
def on_shutdown(self):
self.logger.info("shutting down cleanly")
async def main():
trader = BybitLinearClient(api_key="...", api_secret="...")
events = BybitPrivateWS(api_key="...", api_secret="...", topics=["order"])
strategy = MyStrategy(trader, events)
await strategy.start(events)
asyncio.run(main())
Core concepts
Symbol
A parsed trading pair. Construct from a venue string and split into base/quote:
from cybotrade import Symbol
s = Symbol("BTCUSDT")
s.split() # ("BTC", "USDT")
Topic — market data
A Topic identifies a data feed by provider, endpoint, and query params. It
is the addressing scheme used by cybotrade-datasource for both historical
queries and live streams.
from cybotrade import Topic
topic = Topic("bybit-linear", "candle", {"symbol": "BTCUSDT", "interval": "1m"})
topic.endpoint_with_query_params() # "candle?symbol=BTCUSDT&interval=1m"
topic.interval() # timedelta(minutes=1)
# Or parse from a string
Topic.from_str("bybit-linear|candle?symbol=BTCUSDT&interval=1m")
When datasource_topics and datasource_api_key are supplied to
BaseStrategy, the harness automatically backfills lookback_size rows into
self.datamap[topic] (a Polars DataFrame) on startup and then streams live
updates as EventType.DatasourceUpdate events. maintain_datamap() keeps each
topic's rolling window at the configured size.
ExchangeClient
The REST trading interface implemented by every exchange client:
| Method | Returns |
|---|---|
place_order(symbol, side, quantity, limit=None, ...) |
OrderResponse |
cancel_order(symbol, order_id=None, client_order_id=None) |
OrderResponse |
get_positions(symbol=None) |
list[Position] |
get_wallet_balance(coin=None) |
Balance |
get_order_details(symbol, order_id=None, client_order_id=None) |
OrderUpdate | None |
get_order_details_from_history(...) |
OrderUpdate | None |
get_open_orders(symbol=None) |
list[OrderUpdate] |
get_symbol_info(symbol) |
SymbolInfo |
get_orderbook_snapshot(symbol) |
OrderbookSnapshot |
get_current_price(symbol) |
Decimal (mid of best bid/ask) |
All prices and quantities are Decimal to avoid floating-point drift.
Events
on_event receives an Event whose event_type is one of:
Authenticated, Subscribed, OrderUpdate, DatasourceSubscribed,
DatasourceUpdate, Error, Unknown.
event.data holds the parsed payload; event.orig holds the raw message.
Utilities
from decimal import Decimal
from cybotrade.utils import getenv, truncate_decimal, round_to_tick, extract_precision
getenv("BYBIT_API_KEY") # raises if unset
truncate_decimal(Decimal("1.23456"), 3) # Decimal("1.234")
round_to_tick(Decimal("100.07"), Decimal("0.1")) # Decimal("100.1")
extract_precision(Decimal("0.001")) # 3
Logging
import logging
from cybotrade.logging import setup_logger, make_colorlog_stream_handler
setup_logger(log_level=logging.INFO, handlers=[make_colorlog_stream_handler()])
Dependencies
Installed automatically with the package:
cybotrade-datasource— market-data accessaion-scheduler— job schedulingpolars— DataFrame enginerequests,colorlog,eth-hash[pycryptodome]
License
Copyright © Balaena Quant Sdn Bhd. All rights reserved. This software is
proprietary; see LICENSE for terms.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cybotrade-2.0.17-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 3.0 MB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a676379194d6896891dadf56e208816ecc2d31092cb83c5431fcbca63bb02aba
|
|
| MD5 |
093c8aedaa5d1c247c6d1bfbe35d20ef
|
|
| BLAKE2b-256 |
8bf73333c4f0d81da9de0b3358de198aa9c7e0c6c76f6f110e543cc5c98a6945
|
File details
Details for the file cybotrade-2.0.17-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5d0bedfbb3ea8bae990c9dd5376fde18d976cefacc065913f911beaafa3304e
|
|
| MD5 |
964f8e7d1f0130b88d8915629c7075c3
|
|
| BLAKE2b-256 |
0b30d45065ba446fa7aa10bb9360205e11e85e3ccad440db7b78977783185c36
|
File details
Details for the file cybotrade-2.0.17-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e5ae445f164d28f4301be80b6c95c11d94afee9fc8300ed32dacc7143642f16
|
|
| MD5 |
0653bb950452cc235a3ec47842b6fe52
|
|
| BLAKE2b-256 |
c2f888181dfc28061a0e9fb3fd8f93c04265f780340393738abca0edc1b2b7d1
|
File details
Details for the file cybotrade-2.0.17-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 6.3 MB
- Tags: CPython 3.14, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a6113b14cbd0d676b99aa09861b1a496be74d1f324c85e1a9a1b843f2768081
|
|
| MD5 |
0ec2b42637d72b4113493b547ac2795d
|
|
| BLAKE2b-256 |
2d0a2c2777c881180e0e2385896344b205c71b4e49263976aaaa88c9ec517d34
|
File details
Details for the file cybotrade-2.0.17-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 3.0 MB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc191408bb0928d8f186c56561db802cf41ee0da04b9608f94754f5a1838b04a
|
|
| MD5 |
855b1528c7b3c3fc24b45724c98d2dcd
|
|
| BLAKE2b-256 |
fd9e6200f9ae811840c573e9d618811b17c8b179e9250ee430c9747e3ad73047
|
File details
Details for the file cybotrade-2.0.17-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc0851c219ecbd0918454132187a33f7d4f06e5418cff5987cf715e8473f076a
|
|
| MD5 |
e7dc2c18d7ce167ccb03f5413844d80c
|
|
| BLAKE2b-256 |
66201d9fe4c6665361cfea989a6b27d08bd5d20218fa3926f33e427617e5232c
|
File details
Details for the file cybotrade-2.0.17-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
247d3adf92d46584a697a120230e11bcb8ebbfd3d409ec5299dbd8c4bcfe088f
|
|
| MD5 |
7a988a52de16165b318254c324cc6910
|
|
| BLAKE2b-256 |
4878aaebb45d869f08e93b72cc8cb67548a195b8381ab80bea0bd173b828d86d
|
File details
Details for the file cybotrade-2.0.17-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 6.3 MB
- Tags: CPython 3.13, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95d130af987a791c9317b5b0d7729d10794c33a621395f633c462f2747ad618f
|
|
| MD5 |
ab3f15841ac7aebfea95e9c4d0f5b11d
|
|
| BLAKE2b-256 |
b94b02352ab9ec546f3f59e7ffb3957791e81cc2572631c780d3cbaf2fd4d768
|
File details
Details for the file cybotrade-2.0.17-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 3.0 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1eaeabe0bdb6a8f7912995a9d8eade14bbfb15b4d1c2cc60593e8c459f556db2
|
|
| MD5 |
57b60ea3a189a718b37a82ec57e91814
|
|
| BLAKE2b-256 |
a392f13d84e8e018032ce0175b926b49fb266009899e270eea6c0cd4a8957eb9
|
File details
Details for the file cybotrade-2.0.17-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9a2c3477a36fb9db0c922e197f4cbb623efede83b64f0bd9d4a4811eecdfcce
|
|
| MD5 |
40d6fa128f7c26fce5e39066e583fbb6
|
|
| BLAKE2b-256 |
92a370567093da2ad2790dc642207ab84b7c9e699dc9fb2fd79892b9ab6e8229
|
File details
Details for the file cybotrade-2.0.17-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5762e6809a2784f4b8c54a43c13e5d23c123dd25e8fca07b39a5a2dcbda73b9a
|
|
| MD5 |
a507f074bca8ca39edbe3a830669009d
|
|
| BLAKE2b-256 |
7b88a34df514ef063cc8424c6dc98a325091f41755908382ecef49ef940001d9
|
File details
Details for the file cybotrade-2.0.17-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: cybotrade-2.0.17-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 6.3 MB
- Tags: CPython 3.12, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36b7e32935330cd5811a8956b87cd34f1b27d2ac1768accb04fec85da769a37f
|
|
| MD5 |
27f88b2521850b9b0be38d97dc96bd01
|
|
| BLAKE2b-256 |
674d6e877315c2a5748aa1af3461cf6c4090dd4c25b7bb6fe27de73239449d46
|