Python SDK
Orders
Order placement, cancellation, and management with the Python SDK
Order Operations
Complete guide to order management with the Python SDK including placement, cancellation, modification, and status tracking.
Order Types
from lux_dex.types import OrderType
# Available order types
OrderType.LIMIT # Order at specific price
OrderType.MARKET # Execute immediately at best price
OrderType.STOP # Trigger when price reaches stop level
OrderType.STOP_LIMIT # Stop that becomes limit order
OrderType.ICEBERG # Hidden quantity order
OrderType.PEG # Pegged to best bid/askPlace Order
Limit Order
from lux_dex import Client, OrderType, Side, TimeInForce
client = Client("http://localhost:8080/rpc")
# Basic limit order
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0
)
print(f"Order ID: {order.order_id}")
print(f"Status: {order.status}")
print(f"Price: {order.price}")
print(f"Size: {order.size}")Market Order
# Market buy - execute at best available ask
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.MARKET,
side=Side.BUY,
size=1.0
# No price required for market orders
)
print(f"Executed at: {order.average_price}")
print(f"Filled: {order.filled_size}")Stop Order
# Stop loss - triggers when price drops to 48000
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.STOP,
side=Side.SELL,
price=48000.0, # Stop trigger price
size=1.0
)
# Stop limit - triggers at 48000, places limit at 47900
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.STOP_LIMIT,
side=Side.SELL,
stop_price=48000.0, # Trigger price
price=47900.0, # Limit price
size=1.0
)Iceberg Order
# Iceberg order - show only 0.1 BTC of 10 BTC total
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.ICEBERG,
side=Side.BUY,
price=50000.0,
size=10.0,
display_size=0.1 # Visible quantity
)Peg Order
# Peg to best bid with 10 offset
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.PEG,
side=Side.BUY,
size=1.0,
peg_offset=-10.0 # 10 below best bid
)Time in Force
from lux_dex.types import TimeInForce
# Good Till Cancelled (default)
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0,
time_in_force=TimeInForce.GTC
)
# Immediate Or Cancel - fill what you can, cancel rest
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0,
time_in_force=TimeInForce.IOC
)
# Fill Or Kill - complete fill or nothing
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0,
time_in_force=TimeInForce.FOK
)
# Day order - expires at end of trading day
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0,
time_in_force=TimeInForce.DAY
)Order Response
from dataclasses import dataclass
from typing import Optional
from datetime import datetime
@dataclass
class Order:
"""Order response model."""
order_id: str
client_order_id: Optional[str]
symbol: str
order_type: OrderType
side: Side
price: float
size: float
filled_size: float
remaining_size: float
average_price: float
status: OrderStatus
time_in_force: TimeInForce
created_at: datetime
updated_at: datetime
user_id: str
@property
def is_open(self) -> bool:
"""Check if order is still open."""
return self.status in (OrderStatus.NEW, OrderStatus.PARTIALLY_FILLED)
@property
def is_filled(self) -> bool:
"""Check if order is completely filled."""
return self.status == OrderStatus.FILLED
@property
def fill_percentage(self) -> float:
"""Calculate fill percentage."""
if self.size == 0:
return 0.0
return (self.filled_size / self.size) * 100Cancel Order
Cancel by Order ID
# Cancel single order
cancelled = client.cancel_order(order_id="ord_123456")
print(f"Cancelled: {cancelled.status}")
# With error handling
from lux_dex.exceptions import OrderNotFoundError
try:
cancelled = client.cancel_order("ord_123456")
except OrderNotFoundError:
print("Order not found or already cancelled")Cancel Multiple Orders
# Cancel all orders for a symbol
cancelled_orders = client.cancel_all_orders(symbol="BTC-USD")
print(f"Cancelled {len(cancelled_orders)} orders")
# Cancel all orders for user
cancelled_orders = client.cancel_all_orders(user_id="trader1")
# Cancel orders by side
cancelled_orders = client.cancel_all_orders(
symbol="BTC-USD",
side=Side.BUY
)Async Cancellation
import asyncio
from lux_dex import AsyncClient
async def cancel_orders():
async with AsyncClient("http://localhost:8080/rpc") as client:
# Cancel multiple orders concurrently
order_ids = ["ord_1", "ord_2", "ord_3", "ord_4", "ord_5"]
tasks = [client.cancel_order(oid) for oid in order_ids]
results = await asyncio.gather(*tasks, return_exceptions=True)
for order_id, result in zip(order_ids, results):
if isinstance(result, Exception):
print(f"{order_id}: Failed - {result}")
else:
print(f"{order_id}: Cancelled")
asyncio.run(cancel_orders())Get Order
# Get single order
order = client.get_order("ord_123456")
print(f"Status: {order.status}")
print(f"Filled: {order.filled_size}/{order.size}")
# Get all open orders
open_orders = client.get_orders(status=OrderStatus.NEW)
for order in open_orders:
print(f"{order.order_id}: {order.side} {order.size} @ {order.price}")
# Get orders for symbol
btc_orders = client.get_orders(symbol="BTC-USD")
# Get orders with pagination
orders = client.get_orders(
symbol="BTC-USD",
limit=100,
offset=0
)Order Status
from lux_dex.types import OrderStatus
# Available statuses
OrderStatus.NEW # Order accepted, waiting to be filled
OrderStatus.PARTIALLY_FILLED # Order partially executed
OrderStatus.FILLED # Order completely filled
OrderStatus.CANCELLED # Order cancelled by user
OrderStatus.REJECTED # Order rejected by system
OrderStatus.EXPIRED # Order expired (time in force)
OrderStatus.PENDING_CANCEL # Cancel request pendingClient Order ID
Use client order IDs for idempotent order submission:
import uuid
# Generate unique client order ID
client_order_id = str(uuid.uuid4())
# Place order with client ID
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0,
client_order_id=client_order_id
)
# Retrieve order by client ID
order = client.get_order_by_client_id(client_order_id)
# Idempotent retry - same client_order_id returns existing order
order = client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=50000.0,
size=1.0,
client_order_id=client_order_id # Same ID
)
# Returns existing order instead of creating duplicateBatch Orders
from lux_dex.types import OrderRequest
# Create batch of orders
orders = [
OrderRequest(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=49000.0,
size=1.0
),
OrderRequest(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=48000.0,
size=1.0
),
OrderRequest(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=47000.0,
size=1.0
)
]
# Submit batch
results = client.place_orders_batch(orders)
for result in results:
if result.success:
print(f"Order placed: {result.order.order_id}")
else:
print(f"Order failed: {result.error}")Async Batch Orders
import asyncio
from lux_dex import AsyncClient
async def place_batch_orders():
async with AsyncClient("http://localhost:8080/rpc") as client:
# Prepare orders
order_params = [
("BTC-USD", 49000.0, 1.0),
("BTC-USD", 48000.0, 1.0),
("BTC-USD", 47000.0, 1.0),
]
# Submit concurrently
tasks = [
client.place_order(
symbol=symbol,
order_type=OrderType.LIMIT,
side=Side.BUY,
price=price,
size=size
)
for symbol, price, size in order_params
]
orders = await asyncio.gather(*tasks, return_exceptions=True)
for order in orders:
if isinstance(order, Exception):
print(f"Failed: {order}")
else:
print(f"Placed: {order.order_id}")
asyncio.run(place_batch_orders())Order Modification
# Modify order price and size
modified = client.modify_order(
order_id="ord_123456",
price=50500.0,
size=2.0
)
# Modify price only
modified = client.modify_order(
order_id="ord_123456",
price=50500.0
)
# Cancel and replace (atomic)
new_order = client.replace_order(
order_id="ord_123456",
price=51000.0,
size=1.5
)Order Events Subscription
from lux_dex import Client
from lux_dex.types import OrderEvent, OrderEventType
client = Client(
json_rpc_url="http://localhost:8080/rpc",
ws_url="ws://localhost:8081"
)
def on_order_event(event: OrderEvent) -> None:
"""Handle order events."""
match event.event_type:
case OrderEventType.NEW:
print(f"Order created: {event.order.order_id}")
case OrderEventType.FILL:
print(f"Order filled: {event.fill_size} @ {event.fill_price}")
case OrderEventType.PARTIAL_FILL:
print(f"Partial fill: {event.fill_size} @ {event.fill_price}")
case OrderEventType.CANCELLED:
print(f"Order cancelled: {event.order.order_id}")
case OrderEventType.REJECTED:
print(f"Order rejected: {event.reason}")
# Subscribe to order events
client.subscribe_order_events(
callback=on_order_event,
user_id="trader1"
)
# Keep connection alive
import time
while True:
time.sleep(1)Async Order Events
import asyncio
from lux_dex import AsyncClient
async def monitor_orders():
async with AsyncClient(
json_rpc_url="http://localhost:8080/rpc",
ws_url="ws://localhost:8081"
) as client:
async for event in client.stream_order_events(user_id="trader1"):
print(f"Event: {event.event_type} - {event.order.order_id}")
if event.event_type == OrderEventType.FILL:
print(f" Filled: {event.fill_size} @ {event.fill_price}")
asyncio.run(monitor_orders())pandas Integration
Orders to DataFrame
import pandas as pd
from lux_dex import Client
client = Client("http://localhost:8080/rpc")
# Get orders and convert to DataFrame
orders = client.get_orders(symbol="BTC-USD", limit=100)
df = pd.DataFrame([
{
"order_id": o.order_id,
"symbol": o.symbol,
"side": o.side.value,
"price": o.price,
"size": o.size,
"filled": o.filled_size,
"status": o.status.value,
"created_at": o.created_at
}
for o in orders
])
# Analysis
print(f"Total orders: {len(df)}")
print(f"Buy orders: {len(df[df['side'] == 'buy'])}")
print(f"Sell orders: {len(df[df['side'] == 'sell'])}")
print(f"Average size: {df['size'].mean():.4f}")
print(f"Total volume: {df['size'].sum():.4f}")Order History Analysis
import pandas as pd
import numpy as np
from lux_dex import Client
client = Client("http://localhost:8080/rpc")
# Get filled orders
filled_orders = client.get_orders(
symbol="BTC-USD",
status=OrderStatus.FILLED,
limit=1000
)
df = pd.DataFrame([
{
"order_id": o.order_id,
"side": o.side.value,
"price": o.average_price,
"size": o.filled_size,
"notional": o.average_price * o.filled_size,
"created_at": o.created_at,
"filled_at": o.updated_at
}
for o in filled_orders
])
df["created_at"] = pd.to_datetime(df["created_at"])
df["filled_at"] = pd.to_datetime(df["filled_at"])
df["fill_time_ms"] = (df["filled_at"] - df["created_at"]).dt.total_seconds() * 1000
# Performance metrics
print(f"Total trades: {len(df)}")
print(f"Total volume: ${df['notional'].sum():,.2f}")
print(f"Average fill time: {df['fill_time_ms'].mean():.2f}ms")
print(f"P99 fill time: {df['fill_time_ms'].quantile(0.99):.2f}ms")
# Group by side
by_side = df.groupby("side").agg({
"size": "sum",
"notional": "sum",
"fill_time_ms": "mean"
})
print(by_side)Error Handling
from lux_dex import Client
from lux_dex.exceptions import (
InsufficientBalanceError,
OrderNotFoundError,
ValidationError,
RateLimitError,
LXDexError
)
client = Client("http://localhost:8080/rpc")
def place_order_safe(
symbol: str,
price: float,
size: float
) -> Order | None:
"""Place order with comprehensive error handling."""
try:
return client.place_order(
symbol=symbol,
order_type=OrderType.LIMIT,
side=Side.BUY,
price=price,
size=size
)
except InsufficientBalanceError as e:
print(f"Insufficient balance: need {e.required}, have {e.available}")
return None
except ValidationError as e:
print(f"Invalid order: {e.field} - {e.message}")
return None
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
time.sleep(e.retry_after)
return place_order_safe(symbol, price, size) # Retry
except LXDexError as e:
print(f"DEX error [{e.code}]: {e.message}")
return NoneJupyter Notebook Examples
# Cell 1: Setup
import nest_asyncio
nest_asyncio.apply()
from lux_dex import AsyncClient, OrderType, Side
import pandas as pd
# Cell 2: Place orders
async def trading_session():
async with AsyncClient("http://localhost:8080/rpc") as client:
# Place ladder of buy orders
prices = [49000, 48500, 48000, 47500, 47000]
orders = []
for price in prices:
order = await client.place_order(
symbol="BTC-USD",
order_type=OrderType.LIMIT,
side=Side.BUY,
price=float(price),
size=0.1
)
orders.append(order)
print(f"Placed: {order.order_id} @ {price}")
return orders
orders = await trading_session()
# Cell 3: Analyze orders
df = pd.DataFrame([
{"id": o.order_id, "price": o.price, "size": o.size, "status": o.status.value}
for o in orders
])
display(df)
# Cell 4: Cancel all orders
async def cancel_all():
async with AsyncClient("http://localhost:8080/rpc") as client:
for order in orders:
try:
await client.cancel_order(order.order_id)
print(f"Cancelled: {order.order_id}")
except Exception as e:
print(f"Failed to cancel {order.order_id}: {e}")
await cancel_all()Next Steps
- Order Book - Market data access
- Trades - Trade history and streaming
- Account - Balance and portfolio management