fix 部分平仓 选择切换 会导致不一致,浮动端会错误
This commit is contained in:
@@ -101,6 +101,66 @@ describe('多次部分平仓:比例↔名义本金换算以 PosiNotionalValue
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// 多次部分平仓:全部↔部分切换时 CloseQty 不应随 ClosePercent 口径变化而跳变
|
||||
// 守卫 unwindSwapTrade.js changeCloseMethod/changeClosePercent/changeCloseQty/changeCloseNotionalValue
|
||||
// 旧 bug:ClosePercent 是占期初口径(A),但 CloseQty=PositionQty*ClosePercent 错当占剩余(B)用
|
||||
// 全部(ClosePercent=0.7,CloseQty=720000) → 部分(ClosePercent没变, CloseQty=504000) ❌ 跳变
|
||||
// 修复:CloseQty = PositionQty × (ClosePercent / oriClosePercent)
|
||||
// ============================================================================
|
||||
describe('多次部分平仓:全部↔部分切换 CloseQty 不跳变(占期初口径自洽)', () => {
|
||||
// 场景基于 GLMS-20260701-0013:
|
||||
// 期初 NotionalValue=980000,已平两次剩 PosiNotionalValue=686000, PositionQty=720000
|
||||
// oriClosePercent = 686000/980000 = 0.7
|
||||
const NotionalValue = 980000;
|
||||
const PosiNotionalValue = 686000;
|
||||
const PositionQty = 720000;
|
||||
const oriClosePercent = PosiNotionalValue / NotionalValue; // 0.7
|
||||
|
||||
test('全部平仓 ClosePercent=0.7 → CloseQty=720000(剩余全部)', () => {
|
||||
const closePercent = oriClosePercent; // 全部平仓 = oriClosePercent
|
||||
const closeQty = SwapCalc.calcCloseQtyByOriginalPercent(closePercent, oriClosePercent, PositionQty);
|
||||
expectClose(closeQty, 720000, '全部平仓应平剩余全部数量');
|
||||
});
|
||||
|
||||
test('全部→部分切换(ClosePercent 没变=0.7):CloseQty 应保持 720000 不跳变', () => {
|
||||
// 旧 bug:CloseQty = 720000 * 0.7 = 504000(错误跳变)
|
||||
// 修复:CloseQty = 720000 * (0.7/0.7) = 720000(不变)
|
||||
const closePercent = oriClosePercent;
|
||||
const closeQty = SwapCalc.calcCloseQtyByOriginalPercent(closePercent, oriClosePercent, PositionQty);
|
||||
const buggyCloseQty = Math.round(PositionQty * closePercent * 100) / 100; // 旧 bug 公式
|
||||
expectClose(closeQty, 720000, '修复后应不变');
|
||||
expect(Math.abs(buggyCloseQty - 504000)).toBeLessThanOrEqual(TOL, '旧 bug 会跳变到 504000');
|
||||
expect(Math.abs(closeQty - buggyCloseQty)).toBeGreaterThan(TOL, '修复与旧 bug 必须有差异');
|
||||
});
|
||||
|
||||
test('改比例 0.5(占期初)→ CloseQty=720000×(0.5/0.7)=514285.71', () => {
|
||||
const closePercent = 0.5;
|
||||
const closeQty = SwapCalc.calcCloseQtyByOriginalPercent(closePercent, oriClosePercent, PositionQty);
|
||||
expectClose(closeQty, 514285.71, '占期初 50% 对应占剩余 71.43%,×720000=514285.71');
|
||||
});
|
||||
|
||||
test('逆运算:CloseQty=514285.71 → ClosePercent=0.5(占期初)', () => {
|
||||
const closeQty = 514285.71;
|
||||
const closePercent = SwapCalc.calcOriginalClosePercentByQty(closeQty, PositionQty, oriClosePercent);
|
||||
expectClose(closePercent, 0.5, '逆运算应还原为占期初 0.5');
|
||||
});
|
||||
|
||||
test('逆运算自洽:CloseQty=720000(=PositionQty)→ ClosePercent=0.7(=oriClosePercent)', () => {
|
||||
const closeQty = PositionQty; // 720000
|
||||
const closePercent = SwapCalc.calcOriginalClosePercentByQty(closeQty, PositionQty, oriClosePercent);
|
||||
expectClose(closePercent, oriClosePercent, '平全部剩余 → ClosePercent=oriClosePercent');
|
||||
});
|
||||
|
||||
test('除零保护:oriClosePercent=0(已全平完)→ CloseQty=0', () => {
|
||||
expect(SwapCalc.calcCloseQtyByOriginalPercent(0.5, 0, 720000)).toBe(0);
|
||||
});
|
||||
|
||||
test('除零保护:PositionQty=0 → ClosePercent=0', () => {
|
||||
expect(SwapCalc.calcOriginalClosePercentByQty(100, 0, oriClosePercent)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('交叉校验:对齐 C# FrontendCalcCharacterizationTest 金标准', () => {
|
||||
// FC_001 平仓-债券多头-默认
|
||||
test('FC_001 平仓 债券多头 默认', () => {
|
||||
|
||||
Reference in New Issue
Block a user