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