Skip to main content

Overview

The Order struct represents a trading order in a prediction market. It tracks order details, execution status, and fill information.

Structure

pub struct Order {
    pub id: String,
    pub market_id: String,
    pub outcome: String,
    pub side: OrderSide,
    pub price: f64,
    pub size: f64,
    pub filled: f64,
    pub status: OrderStatus,
    pub created_at: DateTime<Utc>,
    pub updated_at: Option<DateTime<Utc>>,
}

Fields

FieldTypeDescription
idStringUnique order identifier
market_idStringID of the market
outcomeStringThe outcome being traded (e.g., “Yes”)
sideOrderSideBuy or Sell
pricef64Order price (0.0 - 1.0)
sizef64Order size in shares
filledf64Amount already filled
statusOrderStatusCurrent order status
created_atDateTime<Utc>When the order was created
updated_atOption<DateTime<Utc>>Last update timestamp

Enums

OrderSide

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrderSide {
    Buy,
    Sell,
}

OrderStatus

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrderStatus {
    Pending,         // Order submitted, awaiting confirmation
    Open,            // Order active on the book
    Filled,          // Order completely filled
    PartiallyFilled, // Order partially filled
    Cancelled,       // Order cancelled
    Rejected,        // Order rejected by exchange
}

Methods

remaining()

Get the unfilled portion of the order:
let remaining = order.remaining();
println!("Remaining: {} shares", remaining);

is_active()

Check if the order is still active (can be filled):
if order.is_active() {
    println!("Order is still active");
} else {
    println!("Order is no longer active");
}
Active statuses: Open, PartiallyFilled

is_filled()

Check if the order has been completely filled:
if order.is_filled() {
    println!("Order fully executed!");
}

fill_percentage()

Get the fill percentage (0.0 - 1.0):
let fill_pct = order.fill_percentage();
println!("Filled: {:.1}%", fill_pct * 100.0);

Examples

Create and Monitor an Order

use pc_core::{Exchange, OrderSide, OrderStatus};
use std::collections::HashMap;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let exchange = /* initialize exchange */;

    // Create a buy order
    let order = exchange
        .create_order(
            "market-id",
            "Yes",
            OrderSide::Buy,
            0.65,       // price
            100.0,      // size
            HashMap::new(),
        )
        .await?;

    println!("Order created:");
    println!("  ID: {}", order.id);
    println!("  Side: {:?}", order.side);
    println!("  Price: ${:.2}", order.price);
    println!("  Size: {}", order.size);
    println!("  Status: {:?}", order.status);

    // Monitor order status
    loop {
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;

        let updated = exchange
            .fetch_order(&order.id, Some(&order.market_id))
            .await?;

        println!(
            "Status: {:?} | Filled: {}/{} ({:.1}%)",
            updated.status,
            updated.filled,
            updated.size,
            updated.fill_percentage() * 100.0
        );

        if !updated.is_active() {
            break;
        }
    }

    Ok(())
}

Fetch Open Orders

use pc_core::FetchOrdersParams;

// Fetch all open orders
let orders = exchange.fetch_open_orders(None).await?;

for order in orders {
    println!("═══════════════════════════════════════");
    println!("ID:       {}", order.id);
    println!("Market:   {}", order.market_id);
    println!("Outcome:  {}", order.outcome);
    println!("Side:     {:?}", order.side);
    println!("Price:    ${:.4}", order.price);
    println!("Size:     {}", order.size);
    println!("Filled:   {} ({:.1}%)", order.filled, order.fill_percentage() * 100.0);
    println!("Status:   {:?}", order.status);
    println!("Created:  {}", order.created_at.format("%Y-%m-%d %H:%M:%S UTC"));
}

// Filter by market
let market_orders = exchange
    .fetch_open_orders(Some(FetchOrdersParams {
        market_id: Some("specific-market-id".to_string()),
    }))
    .await?;

Cancel an Order

match exchange.cancel_order(&order.id, Some(&order.market_id)).await {
    Ok(cancelled) => {
        println!("Order cancelled: {:?}", cancelled.status);
    }
    Err(e) => {
        println!("Failed to cancel: {}", e);
    }
}

Bulk Order Management

// Fetch all open orders
let open_orders = exchange.fetch_open_orders(None).await?;

// Cancel all orders for a specific market
for order in open_orders {
    if order.market_id == "target-market-id" && order.is_active() {
        match exchange.cancel_order(&order.id, Some(&order.market_id)).await {
            Ok(_) => println!("Cancelled: {}", order.id),
            Err(e) => println!("Failed to cancel {}: {}", order.id, e),
        }
    }
}

Order Status Flow

┌─────────┐
│ Pending │ ──────────────────────────────┐
└────┬────┘                               │
     │                                    ▼
     ▼                              ┌───────────┐
┌────────┐                          │ Rejected  │
│  Open  │                          └───────────┘
└────┬───┘

     ├───────────────────┬──────────────────┐
     │                   │                  │
     ▼                   ▼                  ▼
┌────────────────┐  ┌─────────┐      ┌───────────┐
│ PartiallyFilled│  │ Filled  │      │ Cancelled │
└───────┬────────┘  └─────────┘      └───────────┘

        ├──────────────────┐
        │                  │
        ▼                  ▼
   ┌─────────┐       ┌───────────┐
   │ Filled  │       │ Cancelled │
   └─────────┘       └───────────┘

Serialization

Orders support serde serialization:
use serde_json;

// Serialize
let json = serde_json::to_string(&order)?;

// Deserialize
let order: Order = serde_json::from_str(&json)?;
JSON representation:
{
  "id": "order-123",
  "market_id": "market-456",
  "outcome": "Yes",
  "side": "buy",
  "price": 0.65,
  "size": 100.0,
  "filled": 50.0,
  "status": "partially_filled",
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:35:00Z"
}

Next Steps