AlgoClient
The AlgoClient provides access to algorithmic execution strategies for executing large orders with minimal market impact.
Supported Algorithms
| Algorithm | Description | Use Case |
|---|---|---|
| TWAP | Time-Weighted Average Price | Execute evenly over time |
| VWAP | Volume-Weighted Average Price | Execute proportional to market volume |
| Iceberg | Hidden liquidity orders | Large orders with visible slices |
| Conditional | Trigger-based execution | Price-triggered orders |
Quick Start
from zenotc import ZenOTCClient
async with ZenOTCClient(
api_key="your_api_key",
api_secret="your_api_secret"
) as client:
# Create a TWAP order (executes 10 BTC over 1 hour in 12 slices)
order = await client.algo.create_twap(
asset="BTC",
side="buy",
total_quantity=10.0,
duration_seconds=3600,
slice_count=12,
)
print(f"Algo order created: {order.algo_order_id}")
print(f"Status: {order.status}")
print(f"Progress: {order.progress_percent:.1f}%")
TWAP (Time-Weighted Average Price)
Execute orders evenly distributed over a time period.
Create TWAP Order
order = await client.algo.create_twap(
asset="BTC",
side="buy",
total_quantity=10.0,
duration_seconds=3600, # 1 hour
slice_count=12, # 12 slices (every 5 min)
price_limit=51000.00, # Optional max price
jitter_percent=20, # Randomize timing ±20%
min_slice_size=0.1, # Minimum slice size
auto_start=True, # Start immediately (default)
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
asset | str | Yes | Trading asset (e.g., "BTC") |
side | str | Yes | "buy" or "sell" |
total_quantity | float | Yes | Total quantity to execute |
duration_seconds | int | Yes | Total execution duration (minimum 60) |
slice_count | int | Yes | Number of slices |
price_limit | float | No | Maximum (buy) or minimum (sell) price |
jitter_percent | float | No | Random timing variance 0-50% |
min_slice_size | float | No | Minimum slice size |
auto_start | bool | No | Start immediately (default: True) |
VWAP (Volume-Weighted Average Price)
Execute orders proportional to historical volume patterns.
Create VWAP Order
order = await client.algo.create_vwap(
asset="BTC",
side="buy",
total_quantity=10.0,
duration_seconds=7200, # 2 hours
participation_rate=10, # Max 10% of market volume
price_limit=51000.00,
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
asset | str | Yes | Trading asset |
side | str | Yes | "buy" or "sell" |
total_quantity | float | Yes | Total quantity to execute |
duration_seconds | int | Yes | Total execution duration (minimum 300) |
participation_rate | float | No | Max percentage of market volume (0-100) |
max_deviation_percent | float | No | Maximum deviation from VWAP |
volume_profile | list | No | Custom volume profile entries |
price_limit | float | No | Price limit for execution |
auto_start | bool | No | Start immediately (default: True) |
Iceberg Orders
Execute large orders with only a small portion visible to the market.
Create Iceberg Order
order = await client.algo.create_iceberg(
asset="BTC",
side="buy",
total_quantity=50.0,
display_quantity=2.0, # Only 2 BTC visible at a time
price_limit=50000.00,
variance=10, # ±10% variance in display size
refresh_delay_seconds=5, # 5s delay before next slice
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
asset | str | Yes | Trading asset |
side | str | Yes | "buy" or "sell" |
total_quantity | float | Yes | Total hidden quantity |
display_quantity | float | Yes | Visible slice size |
price_limit | float | No | Limit price |
variance | float | No | Randomize display size 0-50% |
refresh_delay_seconds | int | No | Delay before next slice (seconds) |
price_limit_type | str | No | "fixed", "relative", or "trailing" |
trailing_offset | float | No | Trailing offset amount |
auto_start | bool | No | Start immediately (default: True) |
Conditional Orders
Execute orders based on price conditions.
Create Conditional Order
# Stop-loss order
order = await client.algo.create_conditional(
asset="BTC",
side="sell",
quantity=5.0,
trigger_condition="price_below",
trigger_price=48000.00,
order_type="market",
)
# Take-profit with limit order
order = await client.algo.create_conditional(
asset="BTC",
side="sell",
quantity=5.0,
trigger_condition="price_above",
trigger_price=60000.00,
order_type="limit",
limit_price=59900.00,
)
Trigger Conditions
| Condition | Description |
|---|---|
price_above | Triggers when price rises above threshold |
price_below | Triggers when price falls below threshold |
price_cross | Triggers when price crosses threshold in either direction |
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
asset | str | Yes | Trading asset |
side | str | Yes | "buy" or "sell" |
quantity | float | Yes | Order quantity |
trigger_condition | str | Yes | "price_above", "price_below", "price_cross" |
trigger_price | float | Yes | Price that activates the order |
order_type | str | No | "market" (default) or "limit" |
limit_price | float | No | Limit price (required if order_type="limit") |
expires_at | str | No | ISO datetime expiration for the trigger |
reference_asset | str | No | Asset to monitor for trigger |
auto_start | bool | No | Start monitoring immediately (default: True) |
Generic Order Creation
Use create_order() for more control over parameters:
order = await client.algo.create_order(
algo_type="vwap",
side="buy",
asset="BTC",
total_quantity=10.0,
params={
"durationSeconds": 7200,
"participationRate": 10,
"priceLimit": 51000.00,
},
)
Order Management
Get Order Status
order = await client.algo.get_order(order_id)
print(f"Status: {order.status}")
print(f"Filled: {order.executed_quantity} / {order.total_quantity}")
print(f"Progress: {order.progress_percent:.1f}%")
print(f"Average Price: {order.average_price}")
List Orders
result = await client.algo.list_orders(
status="running", # "pending", "running", "completed", "cancelled", "failed"
algo_type="twap", # Filter by algorithm
asset="BTC", # Filter by asset
limit=50,
)
for order in result.data:
print(f"{order.algo_order_id}: {order.algo_type} - {order.status}")
Cancel Order
order = await client.algo.cancel_order(order_id)
print(f"Cancelled. Filled: {order.executed_quantity}")
Pause/Resume Order
# Pause execution
await client.algo.pause_order(order_id)
# Resume execution
await client.algo.resume_order(order_id)
Cancel All Running Orders
cancelled = await client.algo.cancel_all_running()
print(f"Cancelled {len(cancelled)} orders")
Order Events
Get execution events for an order:
events = await client.algo.get_order_events(order_id, limit=50)
for event in events:
print(f"[{event.timestamp}] {event.event_type}: {event.data}")
Event Types
| Event | Description |
|---|---|
order_started | Execution started |
slice_started | New slice created |
slice_filled | Slice filled |
slice_failed | Slice execution failed |
order_paused | Order paused |
order_resumed | Order resumed |
order_completed | Order fully executed |
order_cancelled | Order cancelled |
trigger_activated | Conditional trigger fired |
AlgoOrder Properties
| Property | Type | Description |
|---|---|---|
id | str | Order ID |
algo_order_id | str | Alias for id |
asset | str | Trading asset |
side | str | "buy" or "sell" |
algo_type | str | Algorithm type |
status | str | Order status |
total_quantity | float | Total quantity to execute |
executed_quantity | float | Quantity executed so far |
remaining_quantity | float | Quantity remaining |
progress_percent | float | Execution progress (0-100) |
average_price | float | Average execution price |
params | object | Algorithm-specific parameters |
execution_state | object | Execution state details |
metrics | object | Execution metrics |
created_at | datetime | Creation time |
updated_at | datetime | Last update time |
Error Handling
from zenotc.exceptions import (
ZenOTCError,
ValidationError,
AuthenticationError,
RateLimitError,
)
try:
order = await client.algo.create_twap(...)
except ValidationError as e:
print(f"Invalid parameters: {e.message}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except ZenOTCError as e:
print(f"Error: {e}")
Best Practices
- Start with sandbox: Test all algorithms in sandbox environment first
- Set price limits: Always set price limits to avoid adverse execution
- Monitor execution: Use
get_order_events()for tracking - Use appropriate duration: Match duration to order size and market conditions
- Consider market hours: Account for liquidity variations throughout the day