Files
zszq-trs/YLErpWeb/fe-tests/unwindSwapTrade.test.js
T

131 lines
4.7 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const vm = require('vm');
function createNumberFormat(precision) {
const formatter = (value) => Number(Number(value || 0).toFixed(precision));
formatter.precision = precision;
return formatter;
}
function loadUnwindHelpers() {
const filePath = path.join(__dirname, '../wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js');
const code = fs.readFileSync(filePath, 'utf8') + '\nmodule.exports = { swapPosiFeeCalc, consPosiFeeType };';
const stockEqvNotional = createNumberFormat(2);
const sandbox = {
module: { exports: {} },
exports: {},
console,
require,
window: { otcformat: { options: {} } },
otcformat: {
options: {},
trading: {
premiumRateP: { precision: 4 },
tradePrice: { precision: 4 },
notional: { precision: 6 },
StockEqvNotional: stockEqvNotional,
marginRateP: { precision: 4 },
umpriceP: { precision: 4 }
},
fixed6: createNumberFormat(6)
},
model: {
ValueDate: '2026-07-27',
FlowEvents: [],
StructureType: '',
TradeStartDate: ''
},
isUseApproval: false,
Vue: function (options) { return options; },
FastVue: {
vueDatePicker() { return {}; },
vueNumberInput() { return {}; }
},
tradeHelper: { IsBond() { return false; } },
main: {
post() {
return {
done() { return this; }
};
},
message() { }
},
SwapCalc: {
roundHalfAwayFromZero(value) { return value; },
calcCloseQtyByOriginalPercent() { return 0; }
},
_: {
round(value, precision) {
return Number(Number(value || 0).toFixed(precision || 0));
}
}
};
sandbox.window.otcformat = sandbox.otcformat;
vm.runInNewContext(code, sandbox, { filename: filePath });
return sandbox.module.exports;
}
function expectClose(actual, expected, tolerance) {
expect(Math.abs(actual - expected)).toBeLessThanOrEqual(tolerance || 1e-6);
}
describe('unwindSwapTrade 基础费率计算', () => {
const { swapPosiFeeCalc, consPosiFeeType } = loadUnwindHelpers();
test('百分比模式按平仓名义本金计算并保留两位', () => {
const result = swapPosiFeeCalc.calcTradingFee(consPosiFeeType.Percent, 0.1234, 1000000, 5000);
expectClose(result, 1234.00);
});
test('单位数量模式按平仓数量计算并保留两位', () => {
const result = swapPosiFeeCalc.calcTradingFee(consPosiFeeType.Unit, 1.235, 1000000, 10);
expectClose(result, 12.35);
});
test('未知模式默认按百分比模式处理', () => {
const result = swapPosiFeeCalc.calcTradingFee(99, 0.1, 200000, 10);
expectClose(result, 200.00);
});
});
describe('base-rate pending trading fee', () => {
const { swapPosiFeeCalc, consPosiFeeType } = loadUnwindHelpers();
test('unit rate follows actual close quantity instead of an inconsistent close percent', () => {
const result = swapPosiFeeCalc.calcTradingFeePending(
2000, consPosiFeeType.Unit, 0.2, 4200, 3000, 10000, 10000, 0.42);
expectClose(result, 600.00);
});
test('percentage rate follows actual close notional value', () => {
const result = swapPosiFeeCalc.calcTradingFeePending(
2000, consPosiFeeType.Percent, 0.2, 300000, 4200, 1000000, 10000, 0.42);
expectClose(result, 600.00);
});
test('a manually adjusted original pending fee is allocated by actual close quantity', () => {
const result = swapPosiFeeCalc.calcTradingFeePending(
1500, consPosiFeeType.Unit, 0.2, 4200, 3000, 10000, 10000, 0.42);
expectClose(result, 450.00);
});
test('partial close fee and pending fee both use the rounded opening fee allocation', () => {
const tradingFee = swapPosiFeeCalc.calcAllocatedTradingFee(
113.46, consPosiFeeType.Percent, 1.1234, 4039.2, 4000, 10098, 10000);
const pendingFee = swapPosiFeeCalc.calcTradingFeePending(
113.46, consPosiFeeType.Percent, 1.1234, 4039.2, 4000, 10098, 10000, 0.4);
expectClose(tradingFee, 45.38);
expectClose(pendingFee, 45.38);
});
test('without a configured base rate, the legacy close-percent calculation remains', () => {
const result = swapPosiFeeCalc.calcTradingFeePending(
2000, consPosiFeeType.Percent, 0, 300000, 3000, 1000000, 10000, 0.42);
expectClose(result, 840.00);
});
});