golang高性能限价订单簿撮合引擎插件库orderbook的使用

Golang高性能限价订单簿撮合引擎插件库orderbook的使用

Go orderbook

改进的用Go(Golang)编写的撮合引擎

特性

  • 标准的价格-时间优先级
  • 支持市价单和限价单
  • 支持订单取消
  • 高性能(每秒超过30万笔交易)
  • 最优内存使用
  • JSON序列化和反序列化
  • 计算指定数量的市场价格

使用

要开始使用orderbook,你需要创建一个对象:

import (
  "fmt" 
  ob "github.com/muzykantov/orderbook"
)

func main() {
  orderBook := ob.NewOrderBook()
  fmt.Println(orderBook)
}

然后你可以使用以下主要功能:

func (ob *OrderBook) ProcessLimitOrder(side Side, orderID string, quantity, price decimal.Decimal) (done []*Order, partial *Order, err error) { ... }

func (ob *OrderBook) ProcessMarketOrder(side Side, quantity decimal.Decimal) (done []*Order, partial *Order, quantityLeft decimal.Decimal, err error) { .. }

func (ob *OrderBook) CancelOrder(orderID string) *Order { ... }

关于主要功能

ProcessLimitOrder

// ProcessLimitOrder 将新订单放入订单簿
// 参数:
//      side     - 你想做什么(ob.Sell 或 ob.Buy)
//      orderID  - 深度中的唯一订单ID
//      quantity - 你想卖出或买入的数量
//      price    - 不超过这个价格(或不低于这个价格)
//      * 要创建新的十进制数,你应该使用decimal.New()函数
// 返回:
//      error   - 如果数量(或价格)小于或等于0,则不为nil。或者如果给定ID的订单已存在
//      done    - 如果你的订单完成了另一个订单,这个订单将被添加到"done"切片中。如果你的订单也完成了,它也会被放到这个数组中
//      partial - 如果你的订单已完成但顶部订单未完全完成,则不为nil。或者如果你的订单部分完成并放入订单簿而没有全部数量 - partial将包含你的订单与剩余数量
//      partialQuantityProcessed - 如果partial订单不为nil,这个结果包含从partial订单处理的量
func (ob *OrderBook) ProcessLimitOrder(side Side, orderID string, quantity, price decimal.Decimal) (done []*Order, partial *Order, err error) { ... }

例如:

ProcessLimitOrder(ob.Sell, "uinqueID", decimal.New(55, 0), decimal.New(100, 0))

asks: 110 -> 5      110 -> 5
      100 -> 1      100 -> 56
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      80  -> 1

done    - nil
partial - nil

ProcessMarketOrder

// ProcessMarketOrder 立即以市场价格从订单簿中获取指定数量
// 参数:
//      side     - 你想做什么(ob.Sell 或 ob.Buy)
//      quantity - 你想卖出或买入的数量
//      * 要创建新的十进制数,你应该使用decimal.New()函数
// 返回:
//      error        - 如果价格小于或等于0,则不为nil
//      done         - 如果你的市价单完成了其他订单,这个订单将被添加到"done"切片中
//      partial      - 如果你的订单已完成但顶部订单未完全完成,则不为nil
//      partialQuantityProcessed - 如果partial订单不为nil,这个结果包含从partial订单处理的量
//      quantityLeft - 如果没有足够的订单来处理所有数量,则大于零
func (ob *OrderBook) ProcessMarketOrder(side Side, quantity decimal.Decimal) (done []*Order, partial *Order, quantityLeft decimal.Decimal, err error) { .. }

例如:

ProcessMarketOrder(ob.Sell, decimal.New(6, 0))

asks: 110 -> 5      110 -> 5
      100 -> 1      100 -> 1
--------------  ->  --------------
bids: 90  -> 5      80 -> 1
      80  -> 2

done         - 2 (or more orders)
partial      - 1 order with price 80
quantityLeft - 0

CancelOrder

// CancelOrder 从订单簿中移除给定ID的订单
func (ob *OrderBook) CancelOrder(orderID string) *Order { ... }

例如:

CancelOrder("myUinqueID-Sell-1-with-100")

asks: 110 -> 5
      100 -> 1      110 -> 5
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      80  -> 1
                    
done         - 2 (or more orders)
partial      - nil
quantityLeft - 4

完整示例

package main

import (
	"fmt"
	ob "github.com/muzykantov/orderbook"
	"github.com/shopspring/decimal"
)

func main() {
	// 创建新的订单簿
	orderBook := ob.NewOrderBook()

	// 添加限价买单
	done, partial, err := orderBook.ProcessLimitOrder(
		ob.Buy, 
		"buy-order-1", 
		decimal.New(10, 0),  // 数量 10
		decimal.New(100, 0), // 价格 100
	)
	if err != nil {
		fmt.Println("Error placing buy order:", err)
		return
	}
	fmt.Printf("Buy order placed. Done: %v, Partial: %v\n", done, partial)

	// 添加限价卖单
	done, partial, err = orderBook.ProcessLimitOrder(
		ob.Sell,
		"sell-order-1",
		decimal.New(5, 0),   // 数量 5
		decimal.New(105, 0), // 价格 105
	)
	if err != nil {
		fmt.Println("Error placing sell order:", err)
		return
	}
	fmt.Printf("Sell order placed. Done: %v, Partial: %v\n", done, partial)

	// 执行市价买单
	done, partial, left, err := orderBook.ProcessMarketOrder(
		ob.Buy,
		decimal.New(7, 0), // 数量 7
	)
	if err != nil {
		fmt.Println("Error processing market order:", err)
		return
	}
	fmt.Printf("Market buy order processed. Done: %v, Partial: %v, Left: %v\n", done, partial, left)

	// 取消订单
	cancelled := orderBook.CancelOrder("sell-order-1")
	fmt.Printf("Cancelled order: %v\n", cancelled)
}

许可证

MIT许可证


更多关于golang高性能限价订单簿撮合引擎插件库orderbook的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能限价订单簿撮合引擎插件库orderbook的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang高性能限价订单簿撮合引擎插件库orderbook使用指南

概述

orderbook是一个用于构建高性能交易撮合引擎的Golang库,它实现了限价订单簿(Order Book)的核心功能,包括订单匹配、深度行情生成等。下面我将详细介绍如何使用这个库。

安装

go get github.com/i25959341/orderbook

基本使用

1. 创建订单簿

package main

import (
	"fmt"
	"github.com/i25959341/orderbook"
)

func main() {
	// 创建一个新的订单簿
	ob := orderbook.NewOrderBook()
	
	// 设置订单簿ID (可选)
	ob.SetID("BTC_USDT")
}

2. 添加订单

// 添加买单
bidOrder := orderbook.NewOrder(
	"order1",         // 订单ID
	orderbook.Bid,    // 方向 (Bid=买单, Ask=卖单)
	10000.0,         // 价格
	1.0,             // 数量
	time.Now(),      // 时间戳
)

// 添加卖单
askOrder := orderbook.NewOrder(
	"order2",
	orderbook.Ask,
	10050.0,
	2.0,
	time.Now(),
)

// 将订单添加到订单簿
ob.Process(bidOrder)
ob.Process(askOrder)

3. 撮合订单

// 创建一个市价单尝试撮合
marketOrder := orderbook.NewOrder(
	"order3",
	orderbook.Ask,  // 假设这是一个市价卖单
	0,             // 市价单价格为0
	0.5,           // 数量
	time.Now(),
)

// 处理订单并返回撮合结果
trades := ob.Process(marketOrder)

// 打印撮合结果
for _, trade := range trades {
	fmt.Printf("撮合成功: %s 成交价 %.2f 数量 %.4f\n", 
		trade.TakerOrderID, trade.Price, trade.Amount)
}

高级功能

1. 获取市场深度

// 获取前5档买盘深度
bids := ob.GetBids(5)
for _, level := range bids {
	fmt.Printf("买盘: 价格 %.2f 总量 %.4f\n", level.Price, level.Amount)
}

// 获取前5档卖盘深度
asks := ob.GetAsks(5)
for _, level := range asks {
	fmt.Printf("卖盘: 价格 %.2f 总量 %.4f\n", level.Price, level.Amount)
}

2. 取消订单

// 取消订单
cancelOrder := orderbook.NewOrder(
	"order1",      // 要取消的订单ID
	orderbook.Bid, // 必须与原始订单方向一致
	10000.0,      // 必须与原始订单价格一致
	0,           // 数量设为0表示取消
	time.Now(),
)

ob.Process(cancelOrder)

3. 批量处理订单

// 创建批量订单
orders := []*orderbook.Order{
	orderbook.NewOrder("order4", orderbook.Bid, 9990.0, 0.3, time.Now()),
	orderbook.NewOrder("order5", orderbook.Ask, 10010.0, 0.4, time.Now()),
	orderbook.NewOrder("order6", orderbook.Bid, 9995.0, 0.5, time.Now()),
}

// 批量处理
for _, order := range orders {
	trades := ob.Process(order)
	// 处理撮合结果...
}

性能优化技巧

  1. 对象复用:在高频场景下,可以复用Order对象减少GC压力
var orderPool = sync.Pool{
	New: func() interface{} {
		return &orderbook.Order{}
	},
}

// 获取订单对象
order := orderPool.Get().(*orderbook.Order)
order.ID = "order7"
order.Side = orderbook.Bid
order.Price = 10000.0
order.Amount = 1.0
order.Time = time.Now()

// 使用后放回池中
orderPool.Put(order)
  1. 批量处理:尽可能批量处理订单减少锁竞争

  2. 避免频繁打印:在生产环境减少日志输出

注意事项

  1. 订单ID必须唯一
  2. 市价单的价格应设为0
  3. 取消订单时数量和方向必须与原始订单一致
  4. 时间戳用于确定订单优先级(价格相同时)

完整示例

package main

import (
	"fmt"
	"time"
	"github.com/i25959341/orderbook"
)

func main() {
	// 1. 创建订单簿
	ob := orderbook.NewOrderBook()
	ob.SetID("BTC_USDT")
	
	// 2. 添加初始订单
	ob.Process(orderbook.NewOrder("bid1", orderbook.Bid, 10000.0, 1.0, time.Now()))
	ob.Process(orderbook.NewOrder("ask1", orderbook.Ask, 10050.0, 2.0, time.Now()))
	
	// 3. 获取市场深度
	fmt.Println("初始市场深度:")
	printDepth(ob, 3)
	
	// 4. 撮合新订单
	fmt.Println("\n处理新订单...")
	trades := ob.Process(orderbook.NewOrder("bid2", orderbook.Bid, 10050.0, 1.5, time.Now()))
	
	// 5. 打印撮合结果
	for _, trade := range trades {
		fmt.Printf("撮合: %s ↔ %s @ %.2f x %.4f\n", 
			trade.MakerOrderID, trade.TakerOrderID, trade.Price, trade.Amount)
	}
	
	// 6. 更新后的市场深度
	fmt.Println("\n更新后市场深度:")
	printDepth(ob, 3)
}

func printDepth(ob *orderbook.OrderBook, depth int) {
	fmt.Println("买盘:")
	for _, bid := range ob.GetBids(depth) {
		fmt.Printf("  %.2f\t%.4f\n", bid.Price, bid.Amount)
	}
	
	fmt.Println("卖盘:")
	for _, ask := range ob.GetAsks(depth) {
		fmt.Printf("  %.2f\t%.4f\n", ask.Price, ask.Amount)
	}
}

这个库非常适合构建加密货币交易所、股票交易系统等需要高性能订单撮合的场景。通过合理使用可以轻松处理每秒数万笔订单的撮合需求。

回到顶部