交易基础概念
1. 订单类型
1.1 限价单 (Limit Order)
指定价格和数量的订单。只有当市场价格达到或优于指定价格时才会成交。
特点:
- 可以控制成交价格
- 不保证一定成交
- 可能部分成交
示例:
买入限价单:
- 价格:50,000 USDT
- 数量:0.1 BTC
- 含义:以不高于 50,000 USDT 的价格买入 0.1 BTC
数据结构:
type LimitOrder struct {
OrderID string
UserID string
Symbol string // "BTC/USDT"
Side string // "buy" or "sell"
Price float64 // 限定价格
Quantity float64 // 数量
Filled float64 // 已成交数量
Status string // "pending", "partial", "filled", "cancelled"
CreatedAt time.Time
}
1.2 市价单 (Market Order)
以当前市场最优价格立即成交的订单。
特点:
- 保证成交(如果有足够流动性)
- 价格不确定
- 可能有滑点
示例:
买入市价单:
- 数量:0.1 BTC
- 含义:以当前市场最低卖价买入 0.1 BTC
数据结构:
type MarketOrder struct {
OrderID string
UserID string
Symbol string
Side string
Quantity float64 // 要买/卖的数量
Status string
CreatedAt time.Time
}
1.3 止损单 (Stop Order)
当价格达到止损价时,自动触发的市价单或限价单。
类型:
- 止损限价单 (Stop-Limit):触发后变成限价单
- 止损市价单 (Stop-Market):触发后变成市价单
示例:
止损卖出:
- 止损价:48,000 USDT
- 限价:47,500 USDT
- 数量:0.1 BTC
- 含义:当价格跌到 48,000 时,以不低于 47,500 的价格卖出
数据结构:
type StopOrder struct {
OrderID string
UserID string
Symbol string
Side string
StopPrice float64 // 触发价格
LimitPrice float64 // 限价(可选)
Quantity float64
OrderType string // "stop_market" or "stop_limit"
Triggered bool // 是否已触发
Status string
CreatedAt time.Time
}
1.4 冰山单 (Iceberg Order)
大单拆分成多个小单,隐藏真实订单量。
特点:
- 只显示部分数量
- 成交后自动挂出下一部分
- 避免影响市场价格
示例:
冰山买单:
- 总数量:10 BTC
- 显示数量:0.5 BTC
- 价格:50,000 USDT
- 含义:总共买10 BTC,但每次只在盘口显示 0.5 BTC
1.5 时间有效性 (Time in Force)
订单的生效时间策略。
| 类型 | 全称 | 说明 |
|---|---|---|
| GTC | Good Till Cancel | 一直有效,直到成交或撤销 |
| IOC | Immediate or Cancel | 立即成交,未成交部分撤销 |
| FOK | Fill or Kill | 全部成交或全部撤销 |
| GTD | Good Till Date | 有效期到指定日期 |
2. 交易对
2.1 基础货币 vs 计价货币
交易对格式:基础货币/计价货币
示例:
- BTC/USDT:用 USDT 买卖 BTC
- 基础货币:BTC
- 计价货币:USDT
- 价格:1 BTC = 50,000 USDT
2.2 交易对配置
type TradingPair struct {
Symbol string // "BTC/USDT"
BaseAsset string // "BTC"
QuoteAsset string // "USDT"
// 价格精度
PricePrecision int // 小数位数
PriceTickSize float64 // 最小价格变动单位
// 数量精度
QuantityPrecision int
MinQuantity float64 // 最小下单量
MaxQuantity float64 // 最大下单量
// 金额限制
MinNotional float64 // 最小成交额
// 手续费
MakerFee float64 // Maker手续费率
TakerFee float64 // Taker手续费率
// 状态
Status string // "active", "suspended"
}
配置示例:
{
"symbol": "BTC/USDT",
"baseAsset": "BTC",
"quoteAsset": "USDT",
"pricePrecision": 2,
"priceTickSize": 0.01,
"quantityPrecision": 6,
"minQuantity": 0.000001,
"maxQuantity": 1000,
"minNotional": 10,
"makerFee": 0.001,
"takerFee": 0.002
}
3. Maker vs Taker
3.1 定义
Maker(挂单方):
- 提供流动性
- 订单进入订单簿等待成交
- 手续费较低(甚至为负,即返佣)
Taker(吃单方):
- 消耗流动性
- 订单立即与订单簿中的订单成交
- 手续费较高
3.2 判断逻辑
func determineMakerTaker(order *Order, matchedPrice float64) string {
if order.Type == "market" {
return "taker" // 市价单总是taker
}
if order.Side == "buy" {
if order.Price >= matchedPrice {
return "taker" // 买价高于或等于成交价,立即成交
}
return "maker"
} else {
if order.Price <= matchedPrice {
return "taker" // 卖价低于或等于成交价,立即成交
}
return "maker"
}
}
3.3 手续费计算
func calculateFee(tradingPair *TradingPair, amount float64, role string) float64 {
var feeRate float64
if role == "maker" {
feeRate = tradingPair.MakerFee
} else {
feeRate = tradingPair.TakerFee
}
return amount * feeRate
}
// 示例
// 成交:0.1 BTC @ 50,000 USDT
// 成交额:5,000 USDT
// Taker手续费(0.2%):5,000 * 0.002 = 10 USDT
// Maker手续费(0.1%):5,000 * 0.001 = 5 USDT
4. 订单簿 (Order Book)
4.1 订单簿结构
订单簿包含两部分:
- Bids(买单):按价格从高到低排列
- Asks(卖单):按价格从低到高排列
示例:
Asks (卖单)
50,003 0.5 BTC
50,002 1.2 BTC
50,001 0.8 BTC
------------ 最优价差 ------------
50,000 1.0 BTC ← 最高买价 (Best Bid)
49,999 0.6 BTC
49,998 2.0 BTC
Bids (买单)
4.2 数据结构
type OrderBook struct {
Symbol string
Bids *PriceLevel // 买盘
Asks *PriceLevel // 卖盘
mu sync.RWMutex
}
type PriceLevel struct {
levels map[float64]*Level // 价格 -> 订单列表
}
type Level struct {
Price float64
Quantity float64
Orders []*Order
}
4.3 深度数据
深度数据是订单簿的聚合视图。
格式:
{
"symbol": "BTC/USDT",
"bids": [
["50000.00", "1.234"],
["49999.00", "0.567"],
["49998.00", "2.345"]
],
"asks": [
["50001.00", "0.876"],
["50002.00", "1.234"],
["50003.00", "0.543"]
],
"timestamp": 1640000000000
}
5. 成交记录
5.1 Trade结构
type Trade struct {
TradeID string
Symbol string
BuyOrderID string
SellOrderID string
BuyUserID string
SellUserID string
Price float64
Quantity float64
BuyerMaker bool // 买方是否为Maker
Timestamp time.Time
}
5.2 成交推送
{
"event": "trade",
"symbol": "BTC/USDT",
"tradeId": "123456789",
"price": "50000.00",
"quantity": "0.1",
"side": "buy",
"timestamp": 1640000000000
}
6. Ticker数据
Ticker是24小时统计数据。
type Ticker struct {
Symbol string
LastPrice float64 // 最新成交价
OpenPrice float64 // 24h开盘价
HighPrice float64 // 24h最高价
LowPrice float64 // 24h最低价
Volume float64 // 24h成交量(基础货币)
QuoteVolume float64 // 24h成交额(计价货币)
PriceChange float64 // 24h价格变化
PriceChangePercent float64 // 24h涨跌幅
BidPrice float64 // 当前最高买价
AskPrice float64 // 当前最低卖价
Timestamp time.Time
}
示例:
{
"symbol": "BTC/USDT",
"lastPrice": "50000.00",
"openPrice": "48000.00",
"highPrice": "51000.00",
"lowPrice": "47500.00",
"volume": "1234.56",
"quoteVolume": "61234567.89",
"priceChange": "2000.00",
"priceChangePercent": "4.17",
"bidPrice": "49999.00",
"askPrice": "50001.00",
"timestamp": 1640000000000
}
7. K线数据
K线(蜡烛图)记录一段时间内的价格变化。
7.1 K线结构
type Kline struct {
Symbol string
Interval string // "1m", "5m", "1h", "1d"
OpenTime time.Time
CloseTime time.Time
Open float64 // 开盘价
High float64 // 最高价
Low float64 // 最低价
Close float64 // 收盘价
Volume float64 // 成交量
Trades int // 成交笔数
}
7.2 K线周期
| 周期 | 说明 |
|---|---|
| 1m | 1分钟 |
| 5m | 5分钟 |
| 15m | 15分钟 |
| 30m | 30分钟 |
| 1h | 1小时 |
| 4h | 4小时 |
| 1d | 1天 |
| 1w | 1周 |
| 1M | 1月 |
7.3 K线生成
func generateKline(trades []*Trade, interval string) *Kline {
if len(trades) == 0 {
return nil
}
kline := &Kline{
Symbol: trades[0].Symbol,
Interval: interval,
Open: trades[0].Price,
High: trades[0].Price,
Low: trades[0].Price,
Close: trades[len(trades)-1].Price,
OpenTime: trades[0].Timestamp,
CloseTime: trades[len(trades)-1].Timestamp,
Volume: 0,
Trades: len(trades),
}
for _, trade := range trades {
if trade.Price > kline.High {
kline.High = trade.Price
}
if trade.Price < kline.Low {
kline.Low = trade.Price
}
kline.Volume += trade.Quantity
}
return kline
}
8. 账户与余额
8.1 账户类型
现货账户:
- 用于币币交易
- 资产完全属于用户
杠杆账户:
- 可以借贷资金
- 有爆仓风险
合约账户:
- 用于合约交易
- 使用保证金模式
8.2 余额类型
type Balance struct {
UserID string
Currency string
Available float64 // 可用余额
Frozen float64 // 冻结余额(挂单占用)
Total float64 // 总余额 = Available + Frozen
}
8.3 余额变动
下单时:
// 冻结余额
balance.Available -= orderAmount
balance.Frozen += orderAmount
成交时:
// 买单成交
balance.Frozen -= quoteAmount // 解冻计价货币
balance.Available += baseAmount // 增加基础货币
// 卖单成交
balance.Frozen -= baseAmount // 解冻基础货币
balance.Available += quoteAmount // 增加计价货币
撤单时:
// 解冻余额
balance.Frozen -= orderAmount
balance.Available += orderAmount
9. 滑点 (Slippage)
滑点是预期价格与实际成交价格的差异。
9.1 产生原因
- 订单簿深度不足
- 市价单吃掉多个价格档位
- 网络延迟导致价格变化
9.2 计算示例
订单簿卖盘:
50,001 0.5 BTC
50,002 0.3 BTC
50,003 0.5 BTC
用户下市价买单:1.0 BTC
成交情况:
0.5 BTC @ 50,001 = 25,000.5 USDT
0.3 BTC @ 50,002 = 15,000.6 USDT
0.2 BTC @ 50,003 = 10,000.6 USDT
-------------------------
总计:1.0 BTC,花费 50,001.7 USDT
平均成交价:50,001.7 / 1.0 = 50,001.7 USDT
预期价格(最优卖价):50,001 USDT
滑点:50,001.7 - 50,001 = 0.7 USDT
滑点率:0.7 / 50,001 = 0.0014% = 0.14个基点
9.3 滑点控制
func calculateSlippage(marketPrice, executionPrice float64) float64 {
return (executionPrice - marketPrice) / marketPrice
}
func checkSlippage(order *MarketOrder, maxSlippage float64) error {
marketPrice := getMarketPrice(order.Symbol, order.Side)
estimatedPrice := estimateExecutionPrice(order)
slippage := calculateSlippage(marketPrice, estimatedPrice)
if slippage > maxSlippage {
return fmt.Errorf("slippage %.2f%% exceeds maximum %.2f%%",
slippage*100, maxSlippage*100)
}
return nil
}
小结
本章介绍了交易所的基础概念,包括:
- 订单类型(限价、市价、止损等)
- 交易对配置
- Maker vs Taker
- 订单簿结构
- 成交、Ticker、K线数据
- 账户余额管理
- 滑点计算
下一章将深入讲解撮合引擎的原理和实现。