fix(trading): 修复做市商吃单扣款金额错误(使用交易总额而非原始数量×价格)

问题:
  做市商吃单时,buyerPayAmount = tradeQuantity × price(原始数量×价格),
  未计入销毁倍数。例如:卖出 697.81 积分股,销毁倍数 5000.88,
  交易总额 = 17,615.96 积分值,但做市商只被扣了 697.81 × 0.005 = 3.49。
  10% 手续费(1,761.60)反而大于做市商支出,导致做市商不减反增。

修复:
  - 做市商吃单时:actualBuyerCost = sellerGrossAmount(含销毁倍数的交易总额)
  - 普通用户买入时:actualBuyerCost = buyerPayAmount(原始数量×价格,不变)
  - frozenCash 仍释放下单时冻结的原始金额(buyerPayAmount)
  - 做市商交易流水记录 assetType=CASH + 实际支付金额

做市商吃单扣款计算(修复后):
  MM 支出 = sellerGrossAmount(交易总额)
  MM 手续费收入 = tradeFee(10%)
  MM 净支出 = sellerReceiveAmount = 交易总额 × 90%

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-03 05:56:12 -08:00
parent 000e8f7ef1
commit 8980a169ed
1 changed files with 42 additions and 19 deletions

View File

@ -254,15 +254,22 @@ export class OrderService {
},
});
// 4. 更新买方账户(扣除冻结现金)
// 做市商吃单时:积分股不进做市商账户,只进流通池(事务外处理)
// 普通用户买入时:积分股直接进入买方账户
// 4. 更新买方账户
// 做市商吃单时:
// - 支付 sellerGrossAmount含销毁倍数的交易总额不是仅原始数量×价格
// - 积分股不进做市商账户,只进流通池
// 普通用户买入时:
// - 支付 buyerPayAmount原始数量×价格
// - 积分股直接进入买方账户
const buyerAccountRecord = await tx.tradingAccount.findUnique({
where: { accountSequence: match.buyOrder.accountSequence },
});
if (buyerAccountRecord) {
// 做市商实际支付 = 交易总额(含销毁倍数);普通用户支付 = 原始数量×价格
const actualBuyerCost = isBuyerMarketMaker ? sellerGrossAmount : buyerPayAmount;
// frozenCash 释放的是下单时冻结的原始金额
const newFrozenCash = Number(buyerAccountRecord.frozenCash) - buyerPayAmount.value.toNumber();
const newCashBalance = Number(buyerAccountRecord.cashBalance) - buyerPayAmount.value.toNumber();
const newCashBalance = Number(buyerAccountRecord.cashBalance) - actualBuyerCost.value.toNumber();
const newShareBalance = isBuyerMarketMaker
? Number(buyerAccountRecord.shareBalance)
: Number(buyerAccountRecord.shareBalance) + tradeQuantity.value.toNumber();
@ -279,21 +286,37 @@ export class OrderService {
});
// 记录买方交易流水
await tx.tradingTransaction.create({
data: {
accountSequence: match.buyOrder.accountSequence,
type: 'BUY',
assetType: 'SHARE',
amount: tradeQuantity.value,
balanceBefore: buyerAccountRecord.shareBalance,
balanceAfter: newShareBalance,
referenceId: match.trade.tradeNo,
referenceType: 'TRADE',
description: isBuyerMarketMaker
? '做市商吃单(积分股→流通池)'
: '买入成交',
},
});
if (isBuyerMarketMaker) {
// 做市商:记录现金支出(交易总额)
await tx.tradingTransaction.create({
data: {
accountSequence: match.buyOrder.accountSequence,
type: 'BUY',
assetType: 'CASH',
amount: actualBuyerCost.value,
balanceBefore: buyerAccountRecord.cashBalance,
balanceAfter: newCashBalance,
referenceId: match.trade.tradeNo,
referenceType: 'TRADE',
description: `做市商吃单(积分股→流通池), 交易总额${sellerGrossAmount.toFixed(4)}`,
},
});
} else {
// 普通用户:记录积分股收入
await tx.tradingTransaction.create({
data: {
accountSequence: match.buyOrder.accountSequence,
type: 'BUY',
assetType: 'SHARE',
amount: tradeQuantity.value,
balanceBefore: buyerAccountRecord.shareBalance,
balanceAfter: newShareBalance,
referenceId: match.trade.tradeNo,
referenceType: 'TRADE',
description: '买入成交',
},
});
}
}
// 5. 更新卖方账户(扣除冻结积分股,增加现金)