Skip to main content

AlgoClient

The AlgoClient provides access to algorithmic execution strategies for executing large orders with minimal market impact.

Supported Algorithms

AlgorithmDescriptionUse Case
TWAPTime-Weighted Average PriceExecute evenly over time
VWAPVolume-Weighted Average PriceExecute proportional to market volume
IcebergHidden liquidity ordersLarge orders with visible slices
ConditionalTrigger-based executionPrice-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

ParameterTypeRequiredDescription
assetstrYesTrading asset (e.g., "BTC")
sidestrYes"buy" or "sell"
total_quantityfloatYesTotal quantity to execute
duration_secondsintYesTotal execution duration (minimum 60)
slice_countintYesNumber of slices
price_limitfloatNoMaximum (buy) or minimum (sell) price
jitter_percentfloatNoRandom timing variance 0-50%
min_slice_sizefloatNoMinimum slice size
auto_startboolNoStart 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

ParameterTypeRequiredDescription
assetstrYesTrading asset
sidestrYes"buy" or "sell"
total_quantityfloatYesTotal quantity to execute
duration_secondsintYesTotal execution duration (minimum 300)
participation_ratefloatNoMax percentage of market volume (0-100)
max_deviation_percentfloatNoMaximum deviation from VWAP
volume_profilelistNoCustom volume profile entries
price_limitfloatNoPrice limit for execution
auto_startboolNoStart 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

ParameterTypeRequiredDescription
assetstrYesTrading asset
sidestrYes"buy" or "sell"
total_quantityfloatYesTotal hidden quantity
display_quantityfloatYesVisible slice size
price_limitfloatNoLimit price
variancefloatNoRandomize display size 0-50%
refresh_delay_secondsintNoDelay before next slice (seconds)
price_limit_typestrNo"fixed", "relative", or "trailing"
trailing_offsetfloatNoTrailing offset amount
auto_startboolNoStart 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

ConditionDescription
price_aboveTriggers when price rises above threshold
price_belowTriggers when price falls below threshold
price_crossTriggers when price crosses threshold in either direction

Parameters

ParameterTypeRequiredDescription
assetstrYesTrading asset
sidestrYes"buy" or "sell"
quantityfloatYesOrder quantity
trigger_conditionstrYes"price_above", "price_below", "price_cross"
trigger_pricefloatYesPrice that activates the order
order_typestrNo"market" (default) or "limit"
limit_pricefloatNoLimit price (required if order_type="limit")
expires_atstrNoISO datetime expiration for the trigger
reference_assetstrNoAsset to monitor for trigger
auto_startboolNoStart 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

EventDescription
order_startedExecution started
slice_startedNew slice created
slice_filledSlice filled
slice_failedSlice execution failed
order_pausedOrder paused
order_resumedOrder resumed
order_completedOrder fully executed
order_cancelledOrder cancelled
trigger_activatedConditional trigger fired

AlgoOrder Properties

PropertyTypeDescription
idstrOrder ID
algo_order_idstrAlias for id
assetstrTrading asset
sidestr"buy" or "sell"
algo_typestrAlgorithm type
statusstrOrder status
total_quantityfloatTotal quantity to execute
executed_quantityfloatQuantity executed so far
remaining_quantityfloatQuantity remaining
progress_percentfloatExecution progress (0-100)
average_pricefloatAverage execution price
paramsobjectAlgorithm-specific parameters
execution_stateobjectExecution state details
metricsobjectExecution metrics
created_atdatetimeCreation time
updated_atdatetimeLast 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

  1. Start with sandbox: Test all algorithms in sandbox environment first
  2. Set price limits: Always set price limits to avoid adverse execution
  3. Monitor execution: Use get_order_events() for tracking
  4. Use appropriate duration: Match duration to order size and market conditions
  5. Consider market hours: Account for liquidity variations throughout the day