backend redesign
This commit is contained in:
250
backend.old/src/exchange_kernel/events.py
Normal file
250
backend.old/src/exchange_kernel/events.py
Normal file
@@ -0,0 +1,250 @@
|
||||
"""
|
||||
Event definitions for the Exchange Kernel.
|
||||
|
||||
All events that can occur during the order lifecycle, position management,
|
||||
and account updates.
|
||||
"""
|
||||
|
||||
from enum import StrEnum
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from ..schema.order_spec import Float, Uint64
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Base Event Classes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class EventType(StrEnum):
|
||||
"""Types of events emitted by the exchange kernel"""
|
||||
# Order lifecycle
|
||||
ORDER_SUBMITTED = "ORDER_SUBMITTED"
|
||||
ORDER_ACCEPTED = "ORDER_ACCEPTED"
|
||||
ORDER_REJECTED = "ORDER_REJECTED"
|
||||
ORDER_PARTIALLY_FILLED = "ORDER_PARTIALLY_FILLED"
|
||||
ORDER_FILLED = "ORDER_FILLED"
|
||||
ORDER_CANCELED = "ORDER_CANCELED"
|
||||
ORDER_MODIFIED = "ORDER_MODIFIED"
|
||||
ORDER_EXPIRED = "ORDER_EXPIRED"
|
||||
|
||||
# Position events
|
||||
POSITION_OPENED = "POSITION_OPENED"
|
||||
POSITION_MODIFIED = "POSITION_MODIFIED"
|
||||
POSITION_CLOSED = "POSITION_CLOSED"
|
||||
|
||||
# Account events
|
||||
ACCOUNT_BALANCE_UPDATED = "ACCOUNT_BALANCE_UPDATED"
|
||||
MARGIN_CALL_WARNING = "MARGIN_CALL_WARNING"
|
||||
|
||||
# System events
|
||||
RECONCILIATION_FAILED = "RECONCILIATION_FAILED"
|
||||
CONNECTION_LOST = "CONNECTION_LOST"
|
||||
CONNECTION_RESTORED = "CONNECTION_RESTORED"
|
||||
|
||||
|
||||
class BaseEvent(BaseModel):
|
||||
"""Base class for all exchange kernel events"""
|
||||
|
||||
model_config = {"extra": "forbid"}
|
||||
|
||||
event_type: EventType = Field(description="Type of event")
|
||||
timestamp: Uint64 = Field(description="Event timestamp (Unix milliseconds)")
|
||||
exchange: str = Field(description="Exchange identifier")
|
||||
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional event data")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Order Events
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class OrderEvent(BaseEvent):
|
||||
"""Base class for order-related events"""
|
||||
|
||||
intent_id: str = Field(description="Order intent ID")
|
||||
order_id: str | None = Field(default=None, description="Exchange order ID (if assigned)")
|
||||
symbol_id: str = Field(description="Symbol being traded")
|
||||
|
||||
|
||||
class OrderSubmitted(OrderEvent):
|
||||
"""Order has been submitted to the exchange"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_SUBMITTED)
|
||||
client_order_id: str | None = Field(default=None, description="Client-assigned order ID")
|
||||
|
||||
|
||||
class OrderAccepted(OrderEvent):
|
||||
"""Order has been accepted by the exchange"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_ACCEPTED)
|
||||
order_id: str = Field(description="Exchange-assigned order ID")
|
||||
accepted_at: Uint64 = Field(description="Exchange acceptance timestamp")
|
||||
|
||||
|
||||
class OrderRejected(OrderEvent):
|
||||
"""Order was rejected by the exchange"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_REJECTED)
|
||||
reason: str = Field(description="Rejection reason")
|
||||
error_code: str | None = Field(default=None, description="Exchange error code")
|
||||
|
||||
|
||||
class OrderPartiallyFilled(OrderEvent):
|
||||
"""Order was partially filled"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_PARTIALLY_FILLED)
|
||||
order_id: str = Field(description="Exchange order ID")
|
||||
fill_price: Float = Field(description="Fill price for this execution")
|
||||
fill_quantity: Float = Field(description="Quantity filled in this execution")
|
||||
total_filled: Float = Field(description="Total quantity filled so far")
|
||||
remaining_quantity: Float = Field(description="Remaining quantity to fill")
|
||||
commission: Float = Field(default=0.0, description="Commission/fee for this fill")
|
||||
commission_asset: str | None = Field(default=None, description="Asset used for commission")
|
||||
trade_id: str | None = Field(default=None, description="Exchange trade ID")
|
||||
|
||||
|
||||
class OrderFilled(OrderEvent):
|
||||
"""Order was completely filled"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_FILLED)
|
||||
order_id: str = Field(description="Exchange order ID")
|
||||
average_fill_price: Float = Field(description="Average execution price")
|
||||
total_quantity: Float = Field(description="Total quantity filled")
|
||||
total_commission: Float = Field(default=0.0, description="Total commission/fees")
|
||||
commission_asset: str | None = Field(default=None, description="Asset used for commission")
|
||||
completed_at: Uint64 = Field(description="Completion timestamp")
|
||||
|
||||
|
||||
class OrderCanceled(OrderEvent):
|
||||
"""Order was canceled"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_CANCELED)
|
||||
order_id: str = Field(description="Exchange order ID")
|
||||
reason: str = Field(description="Cancellation reason")
|
||||
filled_quantity: Float = Field(default=0.0, description="Quantity filled before cancellation")
|
||||
canceled_at: Uint64 = Field(description="Cancellation timestamp")
|
||||
|
||||
|
||||
class OrderModified(OrderEvent):
|
||||
"""Order was modified (price, quantity, etc.)"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_MODIFIED)
|
||||
order_id: str = Field(description="Exchange order ID")
|
||||
old_price: Float | None = Field(default=None, description="Previous price")
|
||||
new_price: Float | None = Field(default=None, description="New price")
|
||||
old_quantity: Float | None = Field(default=None, description="Previous quantity")
|
||||
new_quantity: Float | None = Field(default=None, description="New quantity")
|
||||
modified_at: Uint64 = Field(description="Modification timestamp")
|
||||
|
||||
|
||||
class OrderExpired(OrderEvent):
|
||||
"""Order expired (GTD, DAY orders)"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ORDER_EXPIRED)
|
||||
order_id: str = Field(description="Exchange order ID")
|
||||
filled_quantity: Float = Field(default=0.0, description="Quantity filled before expiration")
|
||||
expired_at: Uint64 = Field(description="Expiration timestamp")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Position Events
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class PositionEvent(BaseEvent):
|
||||
"""Base class for position-related events"""
|
||||
|
||||
position_id: str = Field(description="Position identifier")
|
||||
symbol_id: str = Field(description="Symbol identifier")
|
||||
asset_id: str = Field(description="Asset identifier")
|
||||
|
||||
|
||||
class PositionOpened(PositionEvent):
|
||||
"""New position was opened"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.POSITION_OPENED)
|
||||
quantity: Float = Field(description="Position quantity")
|
||||
entry_price: Float = Field(description="Entry price")
|
||||
side: str = Field(description="LONG or SHORT")
|
||||
leverage: Float | None = Field(default=None, description="Leverage")
|
||||
|
||||
|
||||
class PositionModified(PositionEvent):
|
||||
"""Existing position was modified (size change, etc.)"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.POSITION_MODIFIED)
|
||||
old_quantity: Float = Field(description="Previous quantity")
|
||||
new_quantity: Float = Field(description="New quantity")
|
||||
average_entry_price: Float = Field(description="Updated average entry price")
|
||||
unrealized_pnl: Float | None = Field(default=None, description="Current unrealized P&L")
|
||||
|
||||
|
||||
class PositionClosed(PositionEvent):
|
||||
"""Position was closed"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.POSITION_CLOSED)
|
||||
exit_price: Float = Field(description="Exit price")
|
||||
realized_pnl: Float = Field(description="Realized profit/loss")
|
||||
closed_at: Uint64 = Field(description="Closure timestamp")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Account Events
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class AccountEvent(BaseEvent):
|
||||
"""Base class for account-related events"""
|
||||
|
||||
account_id: str = Field(description="Account identifier")
|
||||
|
||||
|
||||
class AccountBalanceUpdated(AccountEvent):
|
||||
"""Account balance was updated"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.ACCOUNT_BALANCE_UPDATED)
|
||||
asset_id: str = Field(description="Asset that changed")
|
||||
old_balance: Float = Field(description="Previous balance")
|
||||
new_balance: Float = Field(description="New balance")
|
||||
old_available: Float = Field(description="Previous available")
|
||||
new_available: Float = Field(description="New available")
|
||||
change_reason: str = Field(description="Why balance changed (TRADE, DEPOSIT, WITHDRAWAL, etc.)")
|
||||
|
||||
|
||||
class MarginCallWarning(AccountEvent):
|
||||
"""Margin level is approaching liquidation threshold"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.MARGIN_CALL_WARNING)
|
||||
margin_level: Float = Field(description="Current margin level")
|
||||
liquidation_threshold: Float = Field(description="Liquidation threshold")
|
||||
required_action: str = Field(description="Required action to avoid liquidation")
|
||||
estimated_liquidation_price: Float | None = Field(
|
||||
default=None,
|
||||
description="Estimated liquidation price for positions"
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# System Events
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ReconciliationFailed(BaseEvent):
|
||||
"""Failed to reconcile intent with actual state"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.RECONCILIATION_FAILED)
|
||||
intent_id: str = Field(description="Order intent ID")
|
||||
error_message: str = Field(description="Error details")
|
||||
retry_count: int = Field(description="Number of retry attempts")
|
||||
|
||||
|
||||
class ConnectionLost(BaseEvent):
|
||||
"""Connection to exchange was lost"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.CONNECTION_LOST)
|
||||
reason: str = Field(description="Disconnection reason")
|
||||
|
||||
|
||||
class ConnectionRestored(BaseEvent):
|
||||
"""Connection to exchange was restored"""
|
||||
|
||||
event_type: EventType = Field(default=EventType.CONNECTION_RESTORED)
|
||||
downtime_duration: int = Field(description="Duration of downtime in milliseconds")
|
||||
Reference in New Issue
Block a user