交易和簿记基本模型

交易和簿记基本模型涵盖了交易和簿记时发生的事件,其目的是:

  1. 准确的头寸
  2. 没有未解释的 PnL
  3. 生成 PnL 报告

每个 trader 都需要能够解释他们的 PnL(利润和损失)。例如,今天投资组合价值的 5% 增长是来自于现有头寸的价格变动还是新的交易活动的结果(或两者都是)?

什么是 Order?

trade

Order 就是字面上的意思 - 是客户希望对某种产品进行买卖下新的订单。

这个动作类比于电商平台相当于电商收到客户的订单。电商在收到订单后需要查看订单内容确认交易商品,查询仓库是否有货等等;证券交易员收到订单后同样需要确认订单中的交易内容,根据合约内容检查合规,确认订单交易类型等等。

以简单的证券交易为例,以限价单购买 [email protected] 600519.SH 茅台,订单中至少应包含以下信息:

order = {
  "order_book": "12345"
  "instrument": "600519.SH",
  "quantity": 1000,
  "operation": "Buy; Limit; Fill or Kill",
  "trade_date": "2022-02-02",
  "others": "500 to sub-account I; 500 to sub-account II",
  "fulfilled": false,
  "created_at": "2022-02-02 14:30:23 HKT"
}

交易员收到该订单后,明白该客户想要以限价单全部成交或取消订单的方式交易 1000 股茅台,并且如果交易成功后将股票平均分配到两个子账户中。

其中 order_book 字段对应的为该客户某种类型的 Orders 的记账本,其代表了某种类型的 Orders 的集合。这个记账本的字段一般有

{ "book": {
    "id": ": "12345",
    "displayName": "Client A",
    "description": "Client A Cash Equity",
    "type": "HIGH_TOUCH", 
    ...
}

其中的字段可根据业务要求高度定制,比如 type 字段可以定制为

  • HIGH_TOUCH: 需要 trader 主动人工操作
  • LOW_TOUCH: 半人工操作
  • NO_TOUCH: 系统自动向交易所或者其他 broker 撮合订单
  • DMA: 客户自己向交易所发送订单

从最简单的情况上来看,这为某一个 legal entity 提供了查看其名下所有 orders 的集合。

举个例子,机构客户 A 与一家 broker B 的下单系统通过 FIX 协议对接, A 客户下的 order 会首先在 B 的 order book 系统中对应 A 客户的 book 中出现并标记 fulfilled 为 false。系统根据 order 类型进行自动或者手动进行 Order Routing 到交易所或者其他 broker,通过 FAST 协议获取 Market Data, 并执行交易。

books

注意作为 broker B 不需要有 Order Matching Engine。关于 Order Matching Engine 可以参考

什么是 Trade?

Trade 就是成功成交后的 Order。以上面例子中的 Order 为例,假设 Trader 同意向客户 A 卖出 1000 600519.SH 并执行了交易 ,

tradeDetails = orderService.execute(order);

该交易的细节为如下数据结构

tradeDetails = [
{
  "book_a": "Broker B Delta One", 
  "book_b": "Client A I",
  "trader": "Sammy Bruce",
  "tradeType": "SELL", // 从 book_a 的角度,一般 broker 总是把自己的 trading book 放在 book_a
  "quantity": 500
  "quantityUnit": "600519.SH"
  "unitPrice": 1000
  "unitCurrency": "RMB" // 交易货币
  ...
},
{
  "book_a": "Broker B Delta One", 
  "book_b": "Client A II",
  "trader": "Sammy Bruce",
  "tradeType": "SELL", // 从 book_a 的角度,一般 broker 总是把自己的 trading book 放在 book_a
  "quantity": 500
  "quantityUnit": "600519.SH"
  "unitPrice": 1000
  "unitCurrency": "RMB" // 交易货币
  ...
},
]

什么是 Trade Book?

首先注意 Order Book 和 Trade Book 的区别:

  • Order 总是由客户单方面发起的,同时它代表还未执行的交易,所以一般单边记账
  • 而一笔 Trade 交易总是在两方之间执行的,这两方各自有一个账本,同时它代表已经执行的交易,从性质上比较重要,需要双边记账 (Double Entry Bookkeeping) 保证数据的准确性

一个 Trade Book 一般有以下属性:

  • 名称和描述
  • 账簿类型,例如
    • trading book:与产生收入和 PnL 的交易员风险账户/利润中心有关
    • customer book:与客户有关
  • 负责账簿的交易员或柜台主管
  • 公司(法律实体)
  • 报告的货币:默认的结算货币

一个客户的每条 book record 至少有三种状态(同 cash ledger 蕾西): receivable, onhand, payable。

{ "book": {
    "id": ": "123456",
    "displayName": "Broker B Delta One",
    "description": "Cash Equity",
    "type": "Trading Book",    
    "trader": "Sammy Bruce",
    "legal_entity": "Broker B HK",
    "denominated": "USD",
    ...
}

Trade Book 的基本操作

在 Trade Book 中可以根据业务需要定制许多功能。

簿记 Booking

有了交易细节 tradeDetails 和记账本 trade books, 下一步就是对 trade 进行簿记,

trades = tradeService.book(tradeDetails);

在上面的例子中,由于需要将 1000 股分配到 Client A 名下的两个子账户中,总共会生成 4 条 trades,

Book Name: Broker B Delta One
Quantity: -500
UnitPrice: 1000
Instrument: 600519.SH

Book Name: Client A I
Quantity: 500
UnitPrice: 1000
Instrument: 600519.SH

Book Name: Broker B Delta One
Quantity: -500
UnitPrice: 1000
Instrument: 600519.SH

Book Name: Client A II
Quantity: 500
UnitPrice: 1000
Instrument: 600519.SH

交易修改了两个账本之间的头寸,一个账本增加,另一个账本减少买入/卖出的数量, 对两个账本的净影响应始终为零。

获取持仓 Retrieving Instruments

book("Broker B Delta One").instruments()
---
{ "name": "600519.SH", "price": 900,000, ...},
{ "name" "TSLA", "price": 541.21, ...}
...

计算头寸 Position Calculation

假设在交易前 Broker B Delta One 记账本中 600519.SH 头寸为 2000,

{ "book": "Broker B Delta One", "instrument": "600519.SH", "quantity": 2000, "price": 1,800,000, "trading_ccy": "RMB" }

那么交易之后则会变更为

book("Broker B Delta One").instrument("600519.SH").position()
---
{ "book": "Broker B Delta One", "instrument": "600519.SH", "quantity": 1000, "price": 900,000, "trading_ccy": "RMB"
  "trades" [
     { "id:" 1, "quantity": 2000, "counterparty": "Broker C", "price": 1,800,000, ...},
     { "id:" 2, "quantity": -500, "counterparty": "Client A I", "price": 500,000, ...},
     { "id:" 3, "quantity": -500, "counterparty": "Client A II", "price": 500,000, ...}
  ]
}

注意这里的 price 为 price = sum {unit price of trade * quantity of trade} over the instrument,同时 unit price = price / quantuty

计算 PnL

假设当前茅台价格为 980 RMB。

book("Broker B Ledger").realizedPnl() // or Closed PnL, 500,000 + 500,000 - 900,000,注意这应该在 Cash Ledger book 中计算
---
100,000 RMB

book("Broker B Delta One").unrealizedPnl() // or Open PnL, 980 * 1000 - 900,000
---
80,000 RMB

// PnL =  realized PnL + UnrealizedPnL
---
180,000 RMB

其他簿记

Margin: Unrealized PnL = Instrument Unrealized PNL + Margin Loan Interest + Cash Dividend
Fully Funded: Unrealized PnL = Market Value + Dividend

Realized PnL 是从 cash ledger 中计算的

1, 2, 3 三条记录由 Transaction Event 生成。

  • Cash Dividend event 在 ex date 生成,指明 settle date;ex date 簿记入 book; settle date 簿记入 ledger
  • Stock Dividend event 在 ex date 生成,指明 settle date; ex date 簿记入 book
  • Hedging Interest 在 pre reset date 生成,指明 reset date; pre reset date 簿记入 book, settle date 簿记入 ledger

注意 book record 的 Trade Date, Settle Date 等信息用于判断 receivable, onhand, payable 等状态。

  • Margin Rebate: 与 instrument 持仓无关,只与 cash account 有关,应该簿记在 cash ledger 然后通过 event ID 和 Rebate Event 关联。

results matching ""

    No results matching ""