Documentation
¶
Overview ¶
Package ellipxobj provides core types for a trading/exchange system.
Package ellipxobj provides core types for a trading/exchange system.
Index ¶
- Constants
- Variables
- type Amount
- func NewAmount(value int64, decimals int) *Amount
- func NewAmountFromFloat(f *big.Float, decimals int) (*Amount, big.Accuracy)
- func NewAmountFromFloat64(f float64, exp int) (*Amount, big.Accuracy)
- func NewAmountFromString(s string, decimals int) (*Amount, error)
- func NewAmountRaw(v *big.Int, decimals int) *Amount
- func (a *Amount) Add(x, y *Amount) *Amount
- func (a Amount) Bytes() []byte
- func (a Amount) Cmp(b *Amount) int
- func (a *Amount) Div(x, y *Amount) *Amount
- func (a *Amount) Dup() *Amount
- func (a Amount) Exp() int
- func (a Amount) Float() *big.Float
- func (a Amount) IsZero() bool
- func (a Amount) MarshalBinary() ([]byte, error)
- func (a Amount) MarshalJSON() ([]byte, error)
- func (a *Amount) Mul(x, y *Amount) *Amount
- func (a Amount) Neg() *Amount
- func (a Amount) Reciprocal() (*Amount, big.Accuracy)
- func (a *Amount) Scan(v any) error
- func (a *Amount) SetExp(e int) *Amount
- func (a Amount) Sign() int
- func (a Amount) String() string
- func (a *Amount) Sub(x, y *Amount) *Amount
- func (a *Amount) UnmarshalBinary(data []byte) error
- func (a *Amount) UnmarshalJSON(b []byte) error
- func (a Amount) Value() *big.Int
- type Checkpoint
- type Order
- func (o *Order) Deduct(t *Trade) bool
- func (o *Order) Dup() *Order
- func (o *Order) IsValid() error
- func (a *Order) Matches(b *Order) *Trade
- func (o *Order) Meta() *OrderMeta
- func (a *Order) NominalAmount(amountExp int) *Amount
- func (o *Order) Reverse() *Order
- func (o *Order) SetId(orderId, brokerId string) *Order
- func (o *Order) String() string
- func (a *Order) TradeAmount(b *Order) *Amount
- type OrderFlags
- type OrderMeta
- type OrderStatus
- type OrderType
- type PairName
- type TimeId
- func (t TimeId) Bytes(buf []byte) []byte
- func (a TimeId) Cmp(b TimeId) int
- func (t TimeId) MarshalBinary() ([]byte, error)
- func (t TimeId) MarshalJSON() ([]byte, error)
- func (t TimeId) String() string
- func (t TimeId) Time() time.Time
- func (t *TimeId) UnmarshalBinary(v []byte) error
- func (t *TimeId) UnmarshalJSON(b []byte) error
- type TimeIdUnique
- type Trade
Constants ¶
const TimeIdDataLen = 16
TimeIdDataLen defines the number of bytes in the binary representation of a TimeId.
Variables ¶
var ( ErrOrderIdMissing = errors.New("order id is required") ErrBrokerIdMissing = errors.New("broker id is required") ErrOrderTypeNotValid = errors.New("order type is not valid") ErrOrderStatusNotValid = errors.New("order status is not valid") ErrOrderNeedsAmount = errors.New("order amount or spend limit is required") ErrAmountParseFailed = errors.New("failed to parse provided amount") )
Functions ¶
This section is empty.
Types ¶
type Amount ¶
type Amount struct {
// contains filtered or unexported fields
}
Amount represents a fixed-point decimal value with arbitrary precision. It uses a big.Int for the value and an exponent to represent the decimal position. For example, 123.456 would be stored as value=123456 and exp=3. This allows for precise decimal arithmetic without floating-point errors.
func NewAmount ¶
NewAmount returns a new Amount object set to the specific value and decimals. For example, NewAmount(12345, 2) creates the value 123.45
func NewAmountFromFloat ¶
NewAmountFromFloat returns a new Amount initialized with the big.Float value stored with the specified number of decimal places. If decimals <= 0, it will automatically determine an appropriate precision based on the input value, with a minimum of 5 decimal places. Returns the Amount and the accuracy of the conversion.
func NewAmountFromFloat64 ¶
NewAmountFromFloat64 returns a new Amount initialized with the value f stored with the specified number of decimal places. Returns the Amount and the accuracy of the conversion.
func NewAmountFromString ¶
NewAmountFromString return a new Amount initialized with the passed string value
func NewAmountRaw ¶ added in v0.0.26
NewAmountRaw returns a new Amount initialized with the passed values as is
func (*Amount) Add ¶ added in v0.0.11
Add sets a=x+y and returns a. Before adding, both x and y are converted to match the precision of 'a'. This ensures that decimal places align correctly during addition.
func (*Amount) Div ¶ added in v0.0.11
Div sets a=x/y and returns a. The division ensures appropriate precision by automatically adjusting x's exponent before performing the division. The result maintains the precision specified in parameter 'a'.
func (*Amount) Dup ¶ added in v0.0.11
Dup returns a copy of the Amount object so that modifying one won't affect the other
func (Amount) Float ¶
Float converts the Amount to a big.Float representation. This method divides the internal integer value by 10^exp to get the actual decimal value. Returns zero for zero amounts.
func (Amount) MarshalBinary ¶ added in v0.0.23
func (Amount) MarshalJSON ¶
func (*Amount) Mul ¶
Mul sets a=x*y and returns a. The multiplication preserves the desired exponent in parameter 'a' by automatically adjusting precision after multiplying the values. For example, with a.exp=5, x=1.23 (exp=2), y=4.56 (exp=2), the result will be 5.60880 adjusted to have 5 decimal places.
func (Amount) Neg ¶ added in v0.0.35
Neg returns -a (the negation) in a newly allocated Amount. The exponent/precision remains unchanged.
func (Amount) Reciprocal ¶
Reciprocal returns 1/a in a newly allocated Amount. Returns the Amount and the accuracy of the calculation. The precision is maintained at the same level as the original Amount.
func (*Amount) SetExp ¶ added in v0.0.2
SetExp sets the number of decimals (exponent) of the amount. When increasing precision (e > a.exp), this adds zeros to the right. When decreasing precision (e < a.exp), this rounds the value to the nearest decimal place using banker's rounding (round half to even).
Examples: - Setting 123.456 from exp=3 to exp=5 gives 123.45600 - Setting 123.456 from exp=3 to exp=2 gives 123.46
Returns the amount itself for method chaining.
func (*Amount) Sub ¶ added in v0.0.11
Sub sets a=x-y and returns a. Before subtracting, both x and y are converted to match the precision of 'a'. This ensures that decimal places align correctly during subtraction.
func (*Amount) UnmarshalBinary ¶ added in v0.0.23
func (*Amount) UnmarshalJSON ¶ added in v0.0.2
type Checkpoint ¶ added in v0.1.8
type Checkpoint struct {
Pair PairName `json:"pair"` // The trading pair this checkpoint belongs to
Epoch uint64 `json:"epoch"` // Current checkpoint sequence number
PrevEpoch uint64 `json:"prev"` // Previous checkpoint sequence number (for chain validation)
PrevHash []byte `json:"prev_hash"` // Hash of the previous checkpoint (for integrity verification)
Point TimeId `json:"point"` // Timestamp of when this checkpoint was created
OrderSum []byte `json:"in_sum"` // Cryptographic hash representing all orders in the book
OrderCount uint64 `json:"in_cnt"` // Total number of orders included in this checkpoint
Bids []*Order `json:"bids"` // Buy orders in the book (sorted by price, highest first)
Asks []*Order `json:"asks"` // Sell orders in the book (sorted by price, lowest first)
}
Checkpoint represents a snapshot of an order book at a specific point in time. Checkpoints can be used for verification, recovery, or synchronization of order book state between different systems.
Checkpoints form a chain through PrevEpoch and PrevHash fields, allowing validation of the integrity of the order book history.
type Order ¶
type Order struct {
OrderId string `json:"id"` // Unique order ID assigned by the broker
BrokerId string `json:"iss"` // ID of the broker that issued this order
UserId string `json:"usr,omitempty"` // Optional ID or hash of the user owner of the order
RequestTime uint64 `json:"iat"` // Unix timestamp when the order was placed
Unique *TimeId `json:"uniq,omitempty"` // Unique ID allocated on order ingress for strict ordering
Target *TimeId `json:"target,omitempty"` // Target order to be updated (for order modifications)
Version uint64 `json:"ver"` // Version counter, incremented each time order is modified
Pair PairName `json:"pair"` // Trading pair (e.g., BTC_USD)
Type OrderType `json:"type"` // Type of order (BID/ASK, Buy/Sell)
Status OrderStatus `json:"status"` // Current status of the order (Pending, Open, Filled, etc.)
Flags OrderFlags `json:"flags,omitempty"` // Special behavior flags (IOC, FOK, etc.)
Amount *Amount `json:"amount,omitempty"` // Quantity of base asset to trade (if nil, SpendLimit must be set)
Price *Amount `json:"price,omitempty"` // Limit price (if nil, this is a market order)
SpendLimit *Amount `json:"spend_limit,omitempty"` // Maximum amount of quote asset to spend/receive (if nil, Amount must be set)
StopPrice *Amount `json:"stop_price,omitempty"` // Trigger price for stop orders (ignored if Stop flag not set)
}
Order represents a financial trading order with all parameters needed to execute it. An order can be either a buy (bid) or sell (ask) on a specific trading pair.
Orders can be specified in two ways: 1. Fixed Amount: Specifies the exact quantity of the base asset to trade 2. SpendLimit: Specifies the maximum amount of the quote asset to spend/receive
At least one of Amount or SpendLimit must be set for a valid order.
Market orders have nil Price, while limit orders specify the desired price. Orders can have various flags that modify their behavior (see OrderFlags).
func NewOrder ¶
NewOrder creates a new order with the specified pair and type. It initializes the order with the current time and sets the status to Pending. After creation, the order should have OrderId and BrokerId set with SetId(), and at least one of Amount or SpendLimit must be set for the order to be valid.
Example:
order := NewOrder(Pair("BTC", "USD"), OrderBid).
SetId("order123", "broker1").
SetAmount(NewAmount(10000, 8)). // 0.1 BTC
SetPrice(NewAmount(2000000, 2)) // $20,000.00
func (*Order) Deduct ¶ added in v0.0.11
Deduct reduces this order's Amount and/or SpendLimit by the quantities in the given trade. This is called after a trade is executed to update the order's remaining quantities.
The method handles both Amount-based and SpendLimit-based orders: - For Amount-based orders: Reduces Amount by the trade's Amount - For SpendLimit-based orders: Reduces SpendLimit by the trade's Spent value - For orders with both: Reduces both values appropriately
Returns true if the order is fully consumed (either Amount or SpendLimit reduced to zero). Note that even if this method returns false (order not fully consumed), the remaining quantity might be too small to execute further trades.
This method modifies the order in place and should be called only once per trade.
func (*Order) Dup ¶ added in v0.0.14
Dup returns a copy of Order including objects such as Amount duplicated
func (*Order) Matches ¶ added in v0.0.11
Matches determines if this order (a) can match with the provided order (b), returning a Trade object if a match is possible, or nil if no match can occur.
For a match to occur: 1. Orders must have opposite types (bid vs ask) 2. For limit orders, prices must be compatible:
- For a bid (buy), a.Price must be >= b.Price
- For an ask (sell), a.Price must be <= b.Price
3. There must be a non-zero amount that can be traded
The order 'b' is assumed to be an open resting order with a defined Price. The price used for the trade will be b.Price (the resting order's price), providing price improvement for the incoming order when possible.
The Type field in the returned Trade indicates the type of the incoming order (a).
func (*Order) NominalAmount ¶ added in v0.0.12
NominalAmount calculates and returns the effective quantity of the base asset that would be traded, considering both Amount and SpendLimit constraints.
This method handles different order configurations: - For market orders (nil Price) with Amount: Returns the Amount directly - For market orders with only SpendLimit: Returns nil (cannot calculate without price) - For limit orders with only SpendLimit: Calculates Amount = SpendLimit / Price - For limit orders with both Amount and SpendLimit: Returns the smaller of:
- The specified Amount
- The calculated amount based on SpendLimit/Price
The amountExp parameter specifies the decimal precision for the returned Amount.
func (*Order) SetId ¶
SetId sets the order and broker identifiers on this order. Every order must have these IDs set before it can be considered valid. Returns the order itself for method chaining.
func (*Order) TradeAmount ¶ added in v0.0.11
TradeAmount calculates the actual amount that can be traded between this order and order b. This is a key component of the matching engine, determining the exact quantity to use when creating a trade between two orders.
The method calculates this by considering: 1. This order's Amount and/or SpendLimit (converted to an amount using b's Price) 2. The available amount in the counterparty order (b.Amount)
For SpendLimit-based orders, the amount is calculated as SpendLimit/Price. When both Amount and SpendLimit are specified, the more restrictive one is used. The result is further limited by the available amount in order b.
Returns the maximum amount that can be traded between the two orders.
type OrderFlags ¶
type OrderFlags int
const ( FlagImmediateOrCancel OrderFlags = 1 << iota // do not create an open order after execution FlagFillOrKill // if order can't be fully executed, cancel FlagStop )
func (OrderFlags) Has ¶ added in v0.1.1
func (f OrderFlags) Has(chk OrderFlags) bool
Has returns true if the flags contain all the check flags
func (OrderFlags) MarshalJSON ¶
func (f OrderFlags) MarshalJSON() ([]byte, error)
func (*OrderFlags) UnmarshalJSON ¶
func (f *OrderFlags) UnmarshalJSON(j []byte) error
type OrderStatus ¶
type OrderStatus int
const ( OrderInvalid OrderStatus = -1 OrderPending OrderStatus = iota OrderRunning OrderOpen OrderStop // pending for a trigger OrderDone OrderCancel // cancelled or overwritten order )
func OrderStatusByString ¶
func OrderStatusByString(s string) OrderStatus
func (OrderStatus) IsValid ¶
func (s OrderStatus) IsValid() bool
func (OrderStatus) MarshalJSON ¶ added in v0.0.4
func (s OrderStatus) MarshalJSON() ([]byte, error)
func (OrderStatus) String ¶
func (s OrderStatus) String() string
func (*OrderStatus) UnmarshalJSON ¶ added in v0.0.4
func (s *OrderStatus) UnmarshalJSON(b []byte) error
type OrderType ¶
type OrderType int
func OrderTypeByString ¶
func (OrderType) MarshalJSON ¶ added in v0.0.3
func (*OrderType) UnmarshalJSON ¶ added in v0.0.3
type PairName ¶
type PairName [2]string
PairName represents a trading pair with base and quote currency. For example, in BTC_USD, BTC is the base currency (index 0) and USD is the quote currency (index 1).
func Pair ¶
Pair creates a new PairName from base and quote currency strings. For example, Pair("BTC", "USD") creates the BTC_USD trading pair.
func ParsePairName ¶ added in v0.0.13
ParsePairName parses a string in the format "BASE_QUOTE" into a PairName. Returns an error if the string doesn't contain the underscore separator. For example, "BTC_USD" would be parsed into PairName{"BTC", "USD"}.
func (PairName) Hash ¶ added in v0.0.9
Hash returns a 32-byte SHA-256 hash representing the pair name. The hash is calculated by concatenating the base currency, a nil character, and the quote currency, then computing the SHA-256 hash of this string.
Results are cached in a thread-safe map for performance optimization, making repeated calls with the same pair very efficient.
func (PairName) String ¶ added in v0.0.2
String returns the string representation of a PairName in the format "BASE_QUOTE". For example, PairName{"BTC", "USD"}.String() returns "BTC_USD".
func (*PairName) UnmarshalJSON ¶ added in v0.0.8
UnmarshalJSON implements the json.Unmarshaler interface for PairName. Supports two JSON formats: 1. String format: "BTC_USD" 2. Array format: ["BTC", "USD"] Returns an error if the format is invalid or if the string format doesn't contain the required underscore separator.
type TimeId ¶
type TimeId struct {
Type string `json:"type"` // Type of object ("order" or "trade")
Unix uint64 `json:"unix"` // Unix timestamp in seconds
Nano uint32 `json:"nano"` // Nanosecond component [0, 999999999]
Index uint32 `json:"idx"` // Sequential index for events occurring at the same nanosecond
}
TimeId represents a unique timestamp-based identifier with nanosecond precision. It's used for precisely ordering events like orders and trades, and provides a unique, comparable, and sortable identifier even when multiple events occur at the exact same time.
func NewTimeId ¶ added in v0.0.2
func NewTimeId() *TimeId
NewTimeId returns a new TimeId initialized with the current system time. The Index field starts at 0 and Type is left empty. Note: This method does not guarantee uniqueness if called in rapid succession. Use NewUniqueTimeId for guaranteed uniqueness.
func NewUniqueTimeId ¶ added in v0.0.2
func NewUniqueTimeId() *TimeId
NewUniqueTimeId returns a guaranteed unique TimeId within the current process. It uses the global uniqueTime variable to ensure that even if called multiple times within the same nanosecond, each TimeId will be unique by incrementing the Index field. This ensures strict ordering of events even at extremely high throughput.
func ParseTimeId ¶ added in v0.1.3
ParseTimeId parses a string representation of a TimeId. The expected format is either "type:unix:nano:index" or "unix:nano:index". For example: - "order:1649134672:123456789:0" (with type) - "1649134672:123456789:0" (without type)
Returns an error if the format is incorrect or values cannot be parsed as integers.
func (TimeId) Bytes ¶
Bytes returns a 128bits (TimeIdDataLen bytes) bigendian sortable version of this TimeId. If buf is not nil, the data is appended to it.
func (TimeId) Cmp ¶ added in v0.0.10
Cmp compares two TimeId values and returns:
-1 if a < b (a is earlier than b) 0 if a == b (a and b represent the same moment) +1 if a > b (a is later than b)
The comparison uses a hierarchical approach: 1. First comparing Unix seconds 2. Then nanoseconds if seconds are equal 3. Finally index if both seconds and nanoseconds are equal
This provides a total ordering of TimeId values suitable for sorting.
func (TimeId) MarshalBinary ¶ added in v0.0.25
func (TimeId) MarshalJSON ¶ added in v0.0.6
func (*TimeId) UnmarshalBinary ¶ added in v0.0.25
UnmarshalBinary will convert a binary value back to TimeId. Type will not be kept
func (*TimeId) UnmarshalJSON ¶ added in v0.0.6
type TimeIdUnique ¶ added in v0.0.2
type TimeIdUnique struct {
Last TimeId // Tracks the last generated TimeId to ensure uniqueness
}
TimeIdUnique provides a mechanism to ensure TimeIds are always unique and monotonically increasing within a process, even when created in rapid succession or with system clock changes.
func (*TimeIdUnique) New ¶ added in v0.0.20
func (u *TimeIdUnique) New() *TimeId
New creates and returns a new TimeId that is guaranteed to be unique within the scope of this TimeIdUnique instance. This is a convenience method that combines NewTimeId() and Unique() in one call.
func (*TimeIdUnique) Unique ¶ added in v0.0.2
func (u *TimeIdUnique) Unique(t *TimeId)
Unique ensures the provided TimeId is always higher (later) than the latest one processed by this TimeIdUnique instance. If the provided TimeId is already higher, it becomes the new "last" value. If not, the TimeId is modified to be one increment higher than the current "last" value.
This method guarantees strict time ordering even when: - Multiple TimeIds are created within the same nanosecond - The system clock moves backward (due to NTP adjustments, etc.) - TimeIds are created on different systems with slightly unsynchronized clocks
The comparison follows a hierarchical order: Unix seconds, then nanoseconds, then index.
type Trade ¶
type Trade struct {
Id *TimeId `json:"id"` // trade id
Pair PairName `json:"pair"`
Bid *OrderMeta `json:"bid"`
Ask *OrderMeta `json:"ask"`
Type OrderType `json:"type"` // taker's order type
Amount *Amount `json:"amount"`
Price *Amount `json:"price"`
}
Trade represents a trade that happened, where two orders matched