Skip to content

maicoin.ws

WebSocket stream client and channel models for MAX.

Stream

Stream

Stream(
    api_key=None,
    api_secret=None,
    *,
    uri=MAX_WS_URI,
    reconnect=True,
    reconnect_policy=None,
    dispatch="inline",
    response_queue=None,
    connect_factory=None,
    on_connected=None,
    on_disconnected=None,
    on_reconnecting=None,
    on_permanent_failure=None,
    on_handler_error=None,
    **connect_options,
)

Synchronous-style wrapper around the MAX WebSocket connection.

Build the stream, call subscribe / add_handler as many times as you like, then call run to block on the event loop.

Dispatch modes
  • inline: await/call handlers before reading the next websocket message.
  • task: schedule handlers with asyncio.create_task so slow async handlers do not block the receive loop.
  • queue: put parsed responses into response_queue for consumer-owned processing; registered handlers are not invoked.

Build a stream.

Parameters:

Name Type Description Default
api_key str | None

MAX API access key. Required for private channels.

None
api_secret str | None

MAX API secret. Required for private channels.

None
uri str

WebSocket endpoint.

MAX_WS_URI
reconnect bool

Convenience switch for reconnects. Ignored when reconnect_policy is provided.

True
reconnect_policy ReconnectPolicy | None

Backoff/retry settings.

None
dispatch DispatchMode

Handler dispatch strategy: inline, task, or queue.

'inline'
response_queue Queue[Response] | None

Queue used by dispatch="queue". Created lazily when omitted.

None
connect_factory ConnectFactory | None

Injectable websockets.connect-compatible factory.

None
on_connected LifecycleCallback | None

Optional lifecycle callback after queued requests are sent.

None
on_disconnected LifecycleCallback | None

Optional lifecycle callback after a disconnect.

None
on_reconnecting LifecycleCallback | None

Optional lifecycle callback before sleeping/retrying.

None
on_permanent_failure LifecycleCallback | None

Optional lifecycle callback before giving up.

None
on_handler_error HandlerErrorCallback | None

Optional callback for handler exceptions.

None
**connect_options object

Extra options forwarded to websockets.connect, such as ping_interval, ping_timeout, close_timeout, and max_queue.

{}
Source code in src/maicoin/ws/stream.py
def __init__(
    self,
    api_key: str | None = None,
    api_secret: str | None = None,
    *,
    uri: str = MAX_WS_URI,
    reconnect: bool = True,
    reconnect_policy: ReconnectPolicy | None = None,
    dispatch: DispatchMode = "inline",
    response_queue: asyncio.Queue[Response] | None = None,
    connect_factory: ConnectFactory | None = None,
    on_connected: LifecycleCallback | None = None,
    on_disconnected: LifecycleCallback | None = None,
    on_reconnecting: LifecycleCallback | None = None,
    on_permanent_failure: LifecycleCallback | None = None,
    on_handler_error: HandlerErrorCallback | None = None,
    **connect_options: object,
) -> None:
    """Build a stream.

    Args:
        api_key: MAX API access key. Required for private channels.
        api_secret: MAX API secret. Required for private channels.
        uri: WebSocket endpoint.
        reconnect: Convenience switch for reconnects. Ignored when
            `reconnect_policy` is provided.
        reconnect_policy: Backoff/retry settings.
        dispatch: Handler dispatch strategy: `inline`, `task`, or `queue`.
        response_queue: Queue used by `dispatch="queue"`. Created lazily
            when omitted.
        connect_factory: Injectable `websockets.connect`-compatible factory.
        on_connected: Optional lifecycle callback after queued requests are sent.
        on_disconnected: Optional lifecycle callback after a disconnect.
        on_reconnecting: Optional lifecycle callback before sleeping/retrying.
        on_permanent_failure: Optional lifecycle callback before giving up.
        on_handler_error: Optional callback for handler exceptions.
        **connect_options: Extra options forwarded to `websockets.connect`,
            such as `ping_interval`, `ping_timeout`, `close_timeout`, and `max_queue`.
    """
    self.requests = []
    self.handlers = []
    self.uri = uri
    self.reconnect_policy = reconnect_policy or ReconnectPolicy(enabled=reconnect)
    self.dispatch: DispatchMode = dispatch
    self.response_queue = response_queue if response_queue is not None else asyncio.Queue()
    self.connect_factory = connect_factory or cast("ConnectFactory", websockets.connect)
    self.connect_options = connect_options
    self.on_connected = on_connected
    self.on_disconnected = on_disconnected
    self.on_reconnecting = on_reconnecting
    self.on_permanent_failure = on_permanent_failure
    self.on_handler_error = on_handler_error
    self._dispatcher = ResponseDispatcher(
        dispatch=dispatch,
        handlers=self.handlers,
        response_queue=self.response_queue,
        on_handler_error=on_handler_error,
    )
    self._handler_tasks = self._dispatcher._handler_tasks

    self.auth(api_key, api_secret)

requests instance-attribute

requests = []

Pending requests sent in order on every connect (auth first if configured).

handlers instance-attribute

handlers = []

Callbacks invoked with each parsed Response.

uri instance-attribute

uri = uri

reconnect_policy instance-attribute

reconnect_policy = reconnect_policy or ReconnectPolicy(
    enabled=reconnect
)

dispatch instance-attribute

dispatch = dispatch

response_queue instance-attribute

response_queue = (
    response_queue
    if response_queue is not None
    else Queue()
)

connect_factory instance-attribute

connect_factory = connect_factory or cast(
    "ConnectFactory", connect
)

connect_options instance-attribute

connect_options = connect_options

on_connected instance-attribute

on_connected = on_connected

on_disconnected instance-attribute

on_disconnected = on_disconnected

on_reconnecting instance-attribute

on_reconnecting = on_reconnecting

on_permanent_failure instance-attribute

on_permanent_failure = on_permanent_failure

on_handler_error instance-attribute

on_handler_error = on_handler_error

subscribe

subscribe(subscriptions)

Queue a subscribe request for the given list of subscriptions.

May be called multiple times; each call sends one sub request on each connection, including after reconnect.

Source code in src/maicoin/ws/stream.py
def subscribe(self, subscriptions: list[Subscription]) -> None:
    """Queue a `subscribe` request for the given list of subscriptions.

    May be called multiple times; each call sends one `sub` request on each
    connection, including after reconnect.
    """
    self.requests += [Request.subscribe(subscriptions)]

auth

auth(api_key, api_secret)

Queue an auth request when credentials are present.

Called automatically by __init__; expose as a method so credentials can also be added after construction. Missing credentials are silently ignored — public-only streams stay unauthenticated.

Source code in src/maicoin/ws/stream.py
def auth(self, api_key: str | None, api_secret: str | None) -> None:
    """Queue an `auth` request when credentials are present.

    Called automatically by `__init__`; expose as a method so credentials
    can also be added after construction. Missing credentials are silently
    ignored — public-only streams stay unauthenticated.
    """
    if api_key and api_secret:
        self.requests += [Request.auth(api_key, api_secret)]

from_env classmethod

from_env(
    *,
    uri=MAX_WS_URI,
    reconnect=True,
    reconnect_policy=None,
    dispatch="inline",
    response_queue=None,
    connect_factory=None,
    on_connected=None,
    on_disconnected=None,
    on_reconnecting=None,
    on_permanent_failure=None,
    on_handler_error=None,
    **connect_options,
)

Build a stream using MAX_API_KEY / MAX_API_SECRET from the environment.

Raises:

Type Description
ValueError

Either env var is missing or empty.

Source code in src/maicoin/ws/stream.py
@classmethod
def from_env(
    cls,
    *,
    uri: str = MAX_WS_URI,
    reconnect: bool = True,
    reconnect_policy: ReconnectPolicy | None = None,
    dispatch: DispatchMode = "inline",
    response_queue: asyncio.Queue[Response] | None = None,
    connect_factory: ConnectFactory | None = None,
    on_connected: LifecycleCallback | None = None,
    on_disconnected: LifecycleCallback | None = None,
    on_reconnecting: LifecycleCallback | None = None,
    on_permanent_failure: LifecycleCallback | None = None,
    on_handler_error: HandlerErrorCallback | None = None,
    **connect_options: object,
) -> Stream:
    """Build a stream using `MAX_API_KEY` / `MAX_API_SECRET` from the environment.

    Raises:
        ValueError: Either env var is missing or empty.
    """
    api_key = os.getenv("MAX_API_KEY")
    if not api_key:
        raise ValueError("MAX_API_KEY is not set")

    api_secret = os.getenv("MAX_API_SECRET")
    if not api_secret:
        raise ValueError("MAX_API_SECRET is not set")

    return cls(
        api_key=api_key,
        api_secret=api_secret,
        uri=uri,
        reconnect=reconnect,
        reconnect_policy=reconnect_policy,
        dispatch=dispatch,
        response_queue=response_queue,
        connect_factory=connect_factory,
        on_connected=on_connected,
        on_disconnected=on_disconnected,
        on_reconnecting=on_reconnecting,
        on_permanent_failure=on_permanent_failure,
        on_handler_error=on_handler_error,
        **connect_options,
    )

run

run()

Connect and dispatch messages until cancelled.

Wraps arun in asyncio.run. Use arun directly when you already have an event loop.

Source code in src/maicoin/ws/stream.py
def run(self) -> None:
    """Connect and dispatch messages until cancelled.

    Wraps [`arun`][maicoin.ws.Stream.arun] in `asyncio.run`. Use
    [`arun`][maicoin.ws.Stream.arun] directly when you already have an
    event loop.
    """
    asyncio.run(self.arun())

arun async

arun()

Async entry point: connect, replay queued requests, and dispatch responses forever.

Source code in src/maicoin/ws/stream.py
async def arun(self) -> None:
    """Async entry point: connect, replay queued requests, and dispatch responses forever."""
    session = ConnectedSession(
        requests=self.requests,
        dispatcher=self._dispatcher,
        on_connected=self.on_connected,
    )
    loop = ReconnectLoop(
        uri=self.uri,
        connect_factory=self.connect_factory,
        connect_options=self.connect_options,
        reconnect_policy=self.reconnect_policy,
        run_connected=session.run,
        on_disconnected=self.on_disconnected,
        on_reconnecting=self.on_reconnecting,
        on_permanent_failure=self.on_permanent_failure,
    )
    try:
        await loop.run()
    except asyncio.CancelledError:
        await self._cancel_handler_tasks()
        raise

add_handler

add_handler(handler)

Register a callback invoked with each Response.

In inline mode handlers run in registration order. In task mode each handler is scheduled independently; ordering is not guaranteed. In queue mode registered handlers are ignored and responses are written to response_queue.

Source code in src/maicoin/ws/stream.py
def add_handler(self, handler: Handler) -> None:
    """Register a callback invoked with each [`Response`][maicoin.ws.Response].

    In `inline` mode handlers run in registration order. In `task` mode each
    handler is scheduled independently; ordering is not guaranteed. In
    `queue` mode registered handlers are ignored and responses are written to
    [`response_queue`][maicoin.ws.Stream.response_queue].
    """
    self.handlers.append(handler)

ReconnectPolicy dataclass

ReconnectPolicy(
    enabled=True,
    max_retries=None,
    base_delay=1.0,
    max_delay=30.0,
    jitter=1.0,
)

Reconnect/backoff configuration for Stream.

Parameters:

Name Type Description Default
enabled bool

Whether to reconnect after non-cancellation disconnects.

True
max_retries int | None

Maximum reconnect attempts after the initial connection. None retries forever.

None
base_delay float

Initial backoff delay in seconds.

1.0
max_delay float

Maximum backoff delay in seconds.

30.0
jitter float

Random delay added to each backoff, in seconds.

1.0

enabled class-attribute instance-attribute

enabled = True

max_retries class-attribute instance-attribute

max_retries = None

base_delay class-attribute instance-attribute

base_delay = 1.0

max_delay class-attribute instance-attribute

max_delay = 30.0

jitter class-attribute instance-attribute

jitter = 1.0

delay

delay(retry_number)

Return the reconnect delay for a 1-based retry number.

Source code in src/maicoin/ws/_stream/reconnect.py
def delay(self, retry_number: int) -> float:
    """Return the reconnect delay for a 1-based retry number."""
    backoff = min(self.max_delay, self.base_delay * 2 ** max(0, retry_number - 1))
    if self.jitter <= 0:
        return backoff
    return backoff + random.uniform(0, self.jitter)

Subscriptions and requests

Subscription

Bases: BaseModel

A single channel subscription.

Field semantics depend on channel:

  • Public channels (book, trade, ticker, kline) require market.
  • book accepts a depth (1, 5, 10, 20, 50).
  • kline accepts a resolution (e.g. "1m", "5m").
  • Private channels (user) are tied to the authenticated session and ignore market / depth / resolution.
  • pool_quota accepts currency for M-Wallet pool tracking.
  • market_status is global and needs no extra fields.

channel instance-attribute

channel

The channel to subscribe to.

market class-attribute instance-attribute

market = None

Market id (e.g. "btcusdt") for market-scoped channels.

depth class-attribute instance-attribute

depth = None

Order-book depth for book. Allowed values: 1, 5, 10, 20, 50.

resolution class-attribute instance-attribute

resolution = None

Candle resolution for kline (e.g. "1m", "15m", "1h").

currency class-attribute instance-attribute

currency = None

Currency code for currency-scoped channels such as pool_quota.

Channel

Bases: StrEnum

Public and private MAX WebSocket channels.

See the MAX WebSocket docs for the full event list emitted by each channel.

BOOK class-attribute instance-attribute

BOOK = 'book'

Order-book snapshots and incremental updates for a market.

TRADE class-attribute instance-attribute

TRADE = 'trade'

Public trade prints for a market.

TICKER class-attribute instance-attribute

TICKER = 'ticker'

Rolling 24h ticker updates for a market.

USER class-attribute instance-attribute

USER = 'user'

Private user channel: orders, trades, and account balances.

KLINE class-attribute instance-attribute

KLINE = 'kline'

Candle stream at a configurable resolution.

MARKET_STATUS class-attribute instance-attribute

MARKET_STATUS = 'market_status'

Global market on/off and trading-mode changes.

POOL_QUOTA class-attribute instance-attribute

POOL_QUOTA = 'pool_quota'

M-Wallet borrow pool quotas, scoped by currency.

Request

Bases: BaseModel

A single outbound WebSocket request.

Use the subscribe, unsubscribe, and auth class methods rather than constructing Request directly — they fill in the correct action, generate id, and (for auth) compute the HMAC signature.

action instance-attribute

action

Verb describing what this request does.

id instance-attribute

id

Client-generated request id, echoed back in the matching response.

api_key class-attribute instance-attribute

api_key = Field(default=None, serialization_alias='apiKey')

MAX API access key. Serialized as apiKey.

nonce class-attribute instance-attribute

nonce = None

Auth nonce in milliseconds.

signature class-attribute instance-attribute

signature = None

HMAC-SHA256(api_secret, str(nonce)) hex digest.

filters class-attribute instance-attribute

filters = None

Optional Filter list narrowing private channels.

subscriptions class-attribute instance-attribute

subscriptions = None

Subscriptions for sub requests.

subscription class-attribute instance-attribute

subscription = None

Subscriptions for unsub requests. Note: MAX uses the singular key here.

auth classmethod

auth(api_key, api_secret)

Build an auth request signed with api_secret.

The signature is HMAC-SHA256(api_secret, str(nonce)) where nonce is the current UTC time in milliseconds.

Source code in src/maicoin/ws/request.py
@classmethod
def auth(cls, api_key: str, api_secret: str) -> Request:
    """Build an `auth` request signed with `api_secret`.

    The signature is `HMAC-SHA256(api_secret, str(nonce))` where `nonce`
    is the current UTC time in milliseconds.
    """
    nonce = int(datetime.now(tz=UTC).timestamp() * 1000)

    signature = hmac.new(api_secret.encode(), digestmod="sha256")
    signature.update(str(nonce).encode())
    signature = signature.hexdigest()

    return cls(
        action=Action.Authorize,
        id=str(uuid.uuid4()),
        api_key=api_key,
        signature=signature,
        nonce=nonce,
    )

subscribe classmethod

subscribe(subscriptions)

Build a sub request adding subscriptions to the connection.

Source code in src/maicoin/ws/request.py
@classmethod
def subscribe(cls, subscriptions: list[Subscription]) -> Request:
    """Build a `sub` request adding `subscriptions` to the connection."""
    return cls(
        action=Action.Subscribe,
        id=str(uuid.uuid4()),
        subscriptions=subscriptions,
    )

unsubscribe classmethod

unsubscribe(subscriptions)

Build an unsub request removing subscriptions.

Source code in src/maicoin/ws/request.py
@classmethod
def unsubscribe(cls, subscriptions: list[Subscription]) -> Request:
    """Build an `unsub` request removing `subscriptions`."""
    return cls(
        action=Action.Unsubscribe,
        id=str(uuid.uuid4()),
        subscription=subscriptions,
    )

message

message()

Serialize this request as a JSON string ready to send over the socket.

Empty fields are dropped and api_key is rendered as apiKey to match the MAX wire format.

Source code in src/maicoin/ws/request.py
def message(self) -> str:
    """Serialize this request as a JSON string ready to send over the socket.

    Empty fields are dropped and `api_key` is rendered as `apiKey` to
    match the MAX wire format.
    """
    return self.model_dump_json(by_alias=True, exclude_none=True)

Action

Bases: StrEnum

Action verb sent in the action field of a WebSocket request.

Subscribe class-attribute instance-attribute

Subscribe = 'sub'

Add subscriptions to the connection.

Authorize class-attribute instance-attribute

Authorize = 'auth'

Authenticate the connection so private channels become available.

Unsubscribe class-attribute instance-attribute

Unsubscribe = 'unsub'

Remove existing subscriptions.

Filter

Bases: StrEnum

Optional filters for subscription requests.

Filters narrow private channels to a specific event family, e.g. only order updates without trade or account events.

ORDER class-attribute instance-attribute

ORDER = 'order'

TRADE class-attribute instance-attribute

TRADE = 'trade'

ACCOUNT class-attribute instance-attribute

ACCOUNT = 'account'

TRADE_UPDATE class-attribute instance-attribute

TRADE_UPDATE = 'trade_update'

MWALLET_ORDER class-attribute instance-attribute

MWALLET_ORDER = 'mwallet_order'

MWALLET_TRADE class-attribute instance-attribute

MWALLET_TRADE = 'mwallet_trade'

MWALLET_FAST_TRADE_UPDATE class-attribute instance-attribute

MWALLET_FAST_TRADE_UPDATE = 'mwallet_fast_trade_update'

MWALLET_ACCOUNT class-attribute instance-attribute

MWALLET_ACCOUNT = 'mwallet_account'

AD_RATIO class-attribute instance-attribute

AD_RATIO = 'ad_ratio'

BORROWING class-attribute instance-attribute

BORROWING = 'borrowing'

Responses

Response

Bases: BaseModel

A single message decoded from the MAX WebSocket connection.

The MAX wire format uses one-letter aliases (e, T, M, …) to keep payloads small. This model exposes readable Python field names while preserving the wire aliases via validation_alias so it parses raw MAX JSON directly.

See the MAX response key alias reference. Inspect event to dispatch on message type, and read whichever payload field matches that event (ticker, trades, orders, …).

event class-attribute instance-attribute

event = Field(validation_alias='e')

Event type. Drives which payload fields are populated.

created_at class-attribute instance-attribute

created_at = Field(validation_alias='T')

Server timestamp, converted from millisecond UNIX time.

id class-attribute instance-attribute

id = Field(default=None, validation_alias='i')

Echoed request id for subscribed / unsubscribed / authenticated events.

errors class-attribute instance-attribute

errors = Field(default=None, validation_alias='E')

Error messages for error events.

subscriptions class-attribute instance-attribute

subscriptions = Field(default=None, validation_alias='s')

Subscription list confirmed by subscribed / unsubscribed.

channel class-attribute instance-attribute

channel = Field(default=None, validation_alias='c')

Source channel for events that carry market data.

balances class-attribute instance-attribute

balances = Field(default=None, validation_alias='B')

Balances payload for account_* events.

market class-attribute instance-attribute

market = Field(default=None, validation_alias='M')

Market id for market-scoped events.

asks class-attribute instance-attribute

asks = Field(default=None, validation_alias='a')

Order-book ask levels, each [price, volume] (string).

bids class-attribute instance-attribute

bids = Field(default=None, validation_alias='b')

Order-book bid levels, each [price, volume] (string).

first_update_id class-attribute instance-attribute

first_update_id = Field(default=None, validation_alias="fi")

First update id covered by an order-book diff.

last_update_id class-attribute instance-attribute

last_update_id = Field(default=None, validation_alias='li')

Last update id covered by an order-book diff.

version class-attribute instance-attribute

version = Field(default=None, validation_alias='v')

Snapshot version counter for the book.

orders class-attribute instance-attribute

orders = Field(default=None, validation_alias='o')

Orders payload for order_* / mwallet_order_* events.

ticker class-attribute instance-attribute

ticker = Field(default=None, validation_alias='tk')

Ticker payload for ticker events.

trades class-attribute instance-attribute

trades = Field(default=None, validation_alias='t')

Trade payload for trade_* events.

currency class-attribute instance-attribute

currency = Field(default=None, validation_alias='cu')

Currency code for currency-scoped events.

kline class-attribute instance-attribute

kline = Field(default=None, validation_alias='k')

Kline payload for kline events.

market_status class-attribute instance-attribute

market_status = Field(default=None, validation_alias='ms')

Market status payload for market_status events.

pool_quota class-attribute instance-attribute

pool_quota = Field(default=None, validation_alias='qta')

Pool quota payload for pool_quota events.

m_wallet_ad_ratio class-attribute instance-attribute

m_wallet_ad_ratio = Field(
    default=None, validation_alias="ad"
)

M-Wallet account-debt ratio payload.

m_wallet_borrowings class-attribute instance-attribute

m_wallet_borrowings = Field(
    default=None, validation_alias="db"
)

M-Wallet borrowing payload for borrowing_* events.

convert classmethod

convert(t)
Source code in src/maicoin/ws/response.py
@field_validator("created_at", mode="before")
@classmethod
def convert(cls, t: int) -> datetime:
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

Event

Bases: StrEnum

Event names sent in the e field of every MAX WebSocket response.

Snapshot events deliver the full current state on (re)subscribe; update events deliver incremental changes after that. Lifecycle events (error, subscribed, unsubscribed, authenticated) confirm request handling.

ERROR class-attribute instance-attribute

ERROR = 'error'

SUBSCRIBED class-attribute instance-attribute

SUBSCRIBED = 'subscribed'

UNSUBSCRIBED class-attribute instance-attribute

UNSUBSCRIBED = 'unsubscribed'

AUTHENTICATED class-attribute instance-attribute

AUTHENTICATED = 'authenticated'

SNAPSHOT class-attribute instance-attribute

SNAPSHOT = 'snapshot'

UPDATE class-attribute instance-attribute

UPDATE = 'update'

ORDER_SNAPSHOT class-attribute instance-attribute

ORDER_SNAPSHOT = 'order_snapshot'

ORDER_UPDATE class-attribute instance-attribute

ORDER_UPDATE = 'order_update'

TRADE_SNAPSHOT class-attribute instance-attribute

TRADE_SNAPSHOT = 'trade_snapshot'

TRADE_UPDATE class-attribute instance-attribute

TRADE_UPDATE = 'trade_update'

ACCOUNT_SNAPSHOT class-attribute instance-attribute

ACCOUNT_SNAPSHOT = 'account_snapshot'

ACCOUNT_UPDATE class-attribute instance-attribute

ACCOUNT_UPDATE = 'account_update'

FAST_TRADE_UPDATE class-attribute instance-attribute

FAST_TRADE_UPDATE = 'fast_trade_update'

MWALLET_ORDER_SNAPSHOT class-attribute instance-attribute

MWALLET_ORDER_SNAPSHOT = 'mwallet_order_snapshot'

MWALLET_ORDER_UPDATE class-attribute instance-attribute

MWALLET_ORDER_UPDATE = 'mwallet_order_update'

MWALLET_TRADE_SNAPSHOT class-attribute instance-attribute

MWALLET_TRADE_SNAPSHOT = 'mwallet_trade_snapshot'

MWALLET_TRADE_UPDATE class-attribute instance-attribute

MWALLET_TRADE_UPDATE = 'mwallet_trade_update'

MWALLET_FAST_TRADE_UPDATE class-attribute instance-attribute

MWALLET_FAST_TRADE_UPDATE = 'mwallet_fast_trade_update'

MWALLET_ACCOUNT_SNAPSHOT class-attribute instance-attribute

MWALLET_ACCOUNT_SNAPSHOT = 'mwallet_account_snapshot'

MWALLET_ACCOUNT_UPDATE class-attribute instance-attribute

MWALLET_ACCOUNT_UPDATE = 'mwallet_account_update'

AD_RATIO_SNAPSHOT class-attribute instance-attribute

AD_RATIO_SNAPSHOT = 'ad_ratio_snapshot'

AD_RATIO_UPDATE class-attribute instance-attribute

AD_RATIO_UPDATE = 'ad_ratio_update'

BORROWING_SNAPSHOT class-attribute instance-attribute

BORROWING_SNAPSHOT = 'borrowing_snapshot'

BORROWING_UPDATE class-attribute instance-attribute

BORROWING_UPDATE = 'borrowing_update'

Channel payload models

Ticker

Bases: BaseModel

market class-attribute instance-attribute

market = Field(validation_alias='M')

open class-attribute instance-attribute

open = Field(validation_alias='O')

high class-attribute instance-attribute

high = Field(validation_alias='H')

low class-attribute instance-attribute

low = Field(validation_alias='L')

close class-attribute instance-attribute

close = Field(validation_alias='C')

volume class-attribute instance-attribute

volume = Field(validation_alias='v')

volume_in_btc class-attribute instance-attribute

volume_in_btc = Field(validation_alias='V')

Trade

Bases: BaseModel

id class-attribute instance-attribute

id = Field(default=None, validation_alias='i')

market class-attribute instance-attribute

market = Field(default=None, validation_alias='M')

side class-attribute instance-attribute

side = Field(default=None, validation_alias='sd')

price class-attribute instance-attribute

price = Field(validation_alias='p')

volume class-attribute instance-attribute

volume = Field(validation_alias='v')

fee class-attribute instance-attribute

fee = Field(default=None, validation_alias='f')

fee_currency class-attribute instance-attribute

fee_currency = Field(default=None, validation_alias='fc')

fee_discounted class-attribute instance-attribute

fee_discounted = Field(default=None, validation_alias='fd')

funds class-attribute instance-attribute

funds = Field(default=None, validation_alias='fn')

created_at class-attribute instance-attribute

created_at = Field(validation_alias='T')

updated_at class-attribute instance-attribute

updated_at = Field(default=None, validation_alias='TU')

maker class-attribute instance-attribute

maker = Field(default=None, validation_alias='m')

order_id class-attribute instance-attribute

order_id = Field(default=None, validation_alias='oi')

trend class-attribute instance-attribute

trend = Field(default=None, validation_alias='tr')

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/trade.py
@field_validator("created_at", "updated_at", mode="before")
@classmethod
def convert_datetime(cls, t: int | None) -> datetime | None:
    if t is None:
        return None
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

KLine

Bases: BaseModel

start_time class-attribute instance-attribute

start_time = Field(validation_alias='ST')

end_time class-attribute instance-attribute

end_time = Field(validation_alias='ET')

market class-attribute instance-attribute

market = Field(validation_alias='M')

resolution class-attribute instance-attribute

resolution = Field(validation_alias='R')

open class-attribute instance-attribute

open = Field(validation_alias='O')

high class-attribute instance-attribute

high = Field(validation_alias='H')

low class-attribute instance-attribute

low = Field(validation_alias='L')

close class-attribute instance-attribute

close = Field(validation_alias='C')

volume class-attribute instance-attribute

volume = Field(validation_alias='v')

last_trade_id class-attribute instance-attribute

last_trade_id = Field(validation_alias='ti')

closed class-attribute instance-attribute

closed = Field(validation_alias='x')

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/kline.py
@field_validator("start_time", "end_time", mode="before")
@classmethod
def convert_datetime(cls, t: int) -> datetime:
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

Order

Bases: BaseModel

order_id class-attribute instance-attribute

order_id = Field(validation_alias='i')

side class-attribute instance-attribute

side = Field(validation_alias='sd')

order_type class-attribute instance-attribute

order_type = Field(validation_alias='ot')

price class-attribute instance-attribute

price = Field(validation_alias='p')

stop_price class-attribute instance-attribute

stop_price = Field(default=None, validation_alias='sp')

average_price class-attribute instance-attribute

average_price = Field(validation_alias='ap')

state class-attribute instance-attribute

state = Field(validation_alias='S')

market class-attribute instance-attribute

market = Field(validation_alias='M')

created_at class-attribute instance-attribute

created_at = Field(validation_alias='T')

updated_at class-attribute instance-attribute

updated_at = Field(default=None, validation_alias='TU')

volume class-attribute instance-attribute

volume = Field(validation_alias='v')

remaining_volume class-attribute instance-attribute

remaining_volume = Field(validation_alias='rv')

executed_volume class-attribute instance-attribute

executed_volume = Field(validation_alias='ev')

trade_count class-attribute instance-attribute

trade_count = Field(validation_alias='tc')

client_order_id class-attribute instance-attribute

client_order_id = Field(validation_alias='ci')

group_id class-attribute instance-attribute

group_id = Field(default=None, validation_alias='gi')

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/order.py
@field_validator("created_at", "updated_at", mode="before")
@classmethod
def convert_datetime(cls, t: int | None) -> datetime | None:
    if t is None:
        return None
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

OrderState

Bases: StrEnum

CANCEL class-attribute instance-attribute

CANCEL = 'cancel'

WAIT class-attribute instance-attribute

WAIT = 'wait'

DONE class-attribute instance-attribute

DONE = 'done'

CONVERT class-attribute instance-attribute

CONVERT = 'convert'

FINALIZING class-attribute instance-attribute

FINALIZING = 'finalizing'

FAILED class-attribute instance-attribute

FAILED = 'failed'

OrderType

Bases: StrEnum

MARKET class-attribute instance-attribute

MARKET = 'market'

LIMIT class-attribute instance-attribute

LIMIT = 'limit'

STOP_MARKET class-attribute instance-attribute

STOP_MARKET = 'stop_market'

STOP_LIMIT class-attribute instance-attribute

STOP_LIMIT = 'stop_limit'

POST_ONLY class-attribute instance-attribute

POST_ONLY = 'post_only'

IOC_LIMIT class-attribute instance-attribute

IOC_LIMIT = 'ioc_limit'

Balance

Bases: BaseModel

currency class-attribute instance-attribute

currency = Field(validation_alias='cu')

available class-attribute instance-attribute

available = Field(validation_alias='av')

locked class-attribute instance-attribute

locked = Field(validation_alias='l')

staked class-attribute instance-attribute

staked = Field(default=None, validation_alias='stk')

balance_updated_time class-attribute instance-attribute

balance_updated_time = Field(
    default=None, validation_alias="TU"
)

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/balance.py
@field_validator("balance_updated_time", mode="before")
@classmethod
def convert_datetime(cls, t: int | None) -> datetime | None:
    if t is None:
        return None
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

Side

Bases: StrEnum

BUY class-attribute instance-attribute

BUY = 'buy'

SELL class-attribute instance-attribute

SELL = 'sell'

BID class-attribute instance-attribute

BID = 'bid'

ASK class-attribute instance-attribute

ASK = 'ask'

MWalletADRatio

Bases: BaseModel

ad_ratio class-attribute instance-attribute

ad_ratio = Field(validation_alias='ad')

asset_in_usdt class-attribute instance-attribute

asset_in_usdt = Field(validation_alias='as')

debt_in_usdt class-attribute instance-attribute

debt_in_usdt = Field(validation_alias='db')

index_prices class-attribute instance-attribute

index_prices = Field(validation_alias='idxp')

updated_at class-attribute instance-attribute

updated_at = Field(validation_alias='TU')

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/m_wallet.py
@field_validator("updated_at", mode="before")
@classmethod
def convert_datetime(cls, t: int) -> datetime:
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

MWalletBorrowing

Bases: BaseModel

currency class-attribute instance-attribute

currency = Field(validation_alias='cu')

debt_principal class-attribute instance-attribute

debt_principal = Field(validation_alias='dbp')

debt_interest class-attribute instance-attribute

debt_interest = Field(validation_alias='dbi')

updated_at class-attribute instance-attribute

updated_at = Field(validation_alias='TU')

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/m_wallet.py
@field_validator("updated_at", mode="before")
@classmethod
def convert_datetime(cls, t: int) -> datetime:
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)

MWalletIndexPrice

Bases: BaseModel

market class-attribute instance-attribute

market = Field(validation_alias='M')

price class-attribute instance-attribute

price = Field(validation_alias='p')

PoolQuota

Bases: BaseModel

currency class-attribute instance-attribute

currency = Field(validation_alias='cu')

available class-attribute instance-attribute

available = Field(validation_alias='av')

updated_at class-attribute instance-attribute

updated_at = Field(validation_alias='TU')

convert_datetime classmethod

convert_datetime(t)
Source code in src/maicoin/ws/m_wallet.py
@field_validator("updated_at", mode="before")
@classmethod
def convert_datetime(cls, t: int) -> datetime:
    return datetime.fromtimestamp(int(t) / 1000, tz=UTC)