DpExchange.Core.Types.Order (DpExchangeCore v0.3.10)

Copy Markdown View Source

Normalised order, returned by every venue package.

:created_at and :updated_at are the venue's own values where it supplies them and nil where it does not. nil is the honest answer; a substituted local clock would be a plausible value with the wrong meaning.

Not every venue supports every order_type/0 or reports every status/0. The union here is what the contract can express; what a given venue can actually accept is declared by that package's capabilities/0, and asking for one it does not support is an error rather than a silent downgrade to the nearest available type.

Why the enforced keys still admit nil

All seven are enforced, and all but provider allow nil. That is not laxity — it is the same rule as everywhere else here: the venue's word, or nothing.

A venue sending a status this package does not recognise gets nil, never the nearest atom a caller might branch on. Coinbase's close_position/3 returns an order whose side the venue never states — the venue worked the side out from a position this package did not read — and filling in :sell because closing is usually selling is wrong exactly where it matters, on a short.

symbol and id joined them on 2026-09-01. Robinhood acknowledges a cancel request without describing the order it cancelled: there is an id and nothing else, and inventing a symbol to satisfy a type would put a guess where the venue was silent.

The keys stay enforced so a constructor must decide. The types admit nil so the decision can be "the venue did not say".

Summary

Functions

Builds a t/0, failing closed only if :provider is absent or nil.

Types

order_type()

@type order_type() ::
  :market | :limit | :stop | :stop_limit | :post_only | :ioc | :fok

side()

@type side() :: :buy | :sell

status()

@type status() ::
  :pending
  | :open
  | :partially_filled
  | :filled
  | :cancelled
  | :rejected
  | :expired

t()

@type t() :: %DpExchange.Core.Types.Order{
  average_price: Decimal.t() | nil,
  created_at: DateTime.t() | nil,
  fee: Decimal.t() | nil,
  fee_currency: String.t() | nil,
  filled_quantity: Decimal.t() | nil,
  id: String.t() | nil,
  legs: [DpExchange.Core.Types.OrderLeg.t()] | nil,
  order_type: order_type() | nil,
  price: Decimal.t() | nil,
  provider: atom() | String.t(),
  quantity: Decimal.t() | nil,
  side: side() | nil,
  status: status() | nil,
  stop_price: Decimal.t() | nil,
  symbol: String.t() | nil,
  time_in_force: atom() | nil,
  updated_at: DateTime.t() | nil
}

Functions

new(attrs)

@spec new(keyword() | map()) :: t()

Builds a t/0, failing closed only if :provider is absent or nil.

Every other enforced key may legitimately be nil here — see the moduledoc's "Why the enforced keys still admit nil". @enforce_keys still guards their presence; this adds the one field where nil was never intended, using DpExchange.Core.Types.Validate.