Merge branch 'glms/feature/dotnumber' into glms/feature/1.4.2
# Conflicts: # YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml # YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//window.otcformat.options.disableGrouping = true;
|
||||
const inputFormatTradePrice = Object.freeze({ precision: otcformat.trading.tradeSinglePrice.precision, negative: true, append: '' });
|
||||
const inputFormatSwapDeliveryPrice = Object.freeze({ precision: 9, negative: true, append: '' });
|
||||
const inputFormatTradeAmount = Object.freeze({ precision: otcformat.trading.notional.precision, append: '' });
|
||||
const inputFormatMarginRate = Object.freeze({ precision: otcformat.trading.marginRateP.precision, append: '%' });
|
||||
var clients = ylotc.clients;
|
||||
@@ -669,7 +670,7 @@ function getColModelGridStep4() {
|
||||
label: '名义本金',
|
||||
width: 160,
|
||||
align: 'center',
|
||||
formatter: otcformat.trading.umprice
|
||||
formatter: otcformat.trading.StockEqvNotional
|
||||
}
|
||||
, {
|
||||
name: 'position.PosiTradingFee',
|
||||
@@ -1198,6 +1199,7 @@ var vue = new Vue({
|
||||
},
|
||||
postSwapflow() {
|
||||
var thisObj = this;
|
||||
thisObj.swapflow.TradingAmountAvg = _.round(Number(thisObj.swapflow.TradingAmountAvg), 9);
|
||||
main.post("/swaptrade2/SaveSwapflow", { req: thisObj.swapflow, step: thisObj.step }).done(function (resp) {
|
||||
if (resp.success) {
|
||||
getList();
|
||||
@@ -1221,4 +1223,4 @@ var vue = new Vue({
|
||||
'vue-underlying': vueUnderlying()
|
||||
}
|
||||
});
|
||||
window.reloadData = getList();
|
||||
window.reloadData = getList();
|
||||
|
||||
@@ -8,6 +8,7 @@ const inputFormatEqvNotional = Object.freeze({ precision: otcformat.trading.Stoc
|
||||
const inputFormatDividend = Object.freeze({ precision: 2, append: '', negative: true });
|
||||
const inputFormatMarginRate = Object.freeze({ precision: otcformat.trading.marginRateP.precision, append: '%' });
|
||||
const inputFormatMarginRateNoPercent = Object.freeze({ precision: otcformat.trading.umpriceP.precision, append: '', percent: true });
|
||||
const inputFormatSwapDeliveryPrice = Object.freeze({ precision: 9, append: '', negative: true });
|
||||
let ValueDate = model.ValueDate;
|
||||
let MaxIncomeValueDate = model.MaxIncomeValueDate ? model.MaxIncomeValueDate.substr(0, 10) : ValueDate;
|
||||
|
||||
@@ -77,6 +78,10 @@ const vue = new Vue({
|
||||
getPriceScale() {
|
||||
return SwapCalc.getPriceScale(this.multiplier);
|
||||
},
|
||||
getStorageDeliveryPrice() {
|
||||
const precision = inputFormatSwapDeliveryPrice.precision + (this.multiplier === 100 ? 2 : 0);
|
||||
return SwapCalc.roundHalfAwayFromZero(Number(this.floatPosition.TradingAmountAvg) * this.getPriceScale(), precision);
|
||||
},
|
||||
initDeal() {
|
||||
var positions = model.FlowEvents.filter((item) => {
|
||||
return item.UnderlyingCode;
|
||||
@@ -161,7 +166,7 @@ const vue = new Vue({
|
||||
{ code: thisObj.floatPosition.UnderlyingCode, valuedate: thisObj.deal.ValueDate })
|
||||
.done(function (res) {
|
||||
res.obj = res.obj * thisObj.multiplier;
|
||||
thisObj.floatPosition.TradingAmountAvg = otcformat.trading.tradeSinglePrice(res.obj);
|
||||
thisObj.floatPosition.TradingAmountAvg = _.round(Number(res.obj), 9);
|
||||
thisObj.calcFloatClosePnl();
|
||||
});
|
||||
},
|
||||
@@ -180,11 +185,11 @@ const vue = new Vue({
|
||||
let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee);
|
||||
let TradingFeePending = thisObj.floatPosition.TradingFeePending == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFeePending);
|
||||
let DividendIn = thisObj.floatPosition.DividendIn == "" ? 0 : parseFloat(thisObj.floatPosition.DividendIn ?? 0);
|
||||
let scale = thisObj.getPriceScale();
|
||||
let deliveryPrice = thisObj.getStorageDeliveryPrice();
|
||||
// 债券全价是单位价格,价差盈亏应按持仓数量×合约乘数计算;
|
||||
// CloseNotionalValue 是期初全价折算后的名义本金,直接乘价差会重复包含期初价格。
|
||||
let positionAmount = parseFloat(thisObj.floatPosition.Quantity) * parseFloat(thisObj.floatPosition.ContractSize || 1);
|
||||
thisObj.floatPosition.MarkClosePnl = positionAmount * (thisObj.floatPosition.TradingAmountAvg * scale - thisObj.initPosiGrossPrice) * floatRatio;
|
||||
thisObj.floatPosition.MarkClosePnl = positionAmount * (deliveryPrice - thisObj.initPosiGrossPrice) * floatRatio;
|
||||
thisObj.floatPosition.MarkClosePnl = otcformat.trading.StockEqvNotional(thisObj.floatPosition.MarkClosePnl);//MarkClosePnl 纯盯市不要计算交易费用和分红
|
||||
// 守卫: 浮动盈亏合计必须保留 2 位小数 → 对应历史 bug 3c5f25a5(原代码缺精度保留)
|
||||
// 数值由 swapCalc.calcFloatPnlSum 计算, 此处 .toFixed(2) 仅保留字符串类型以兼容下游
|
||||
@@ -205,13 +210,13 @@ const vue = new Vue({
|
||||
thisObj.deal.SwapRealizedPnL = pnl;
|
||||
thisObj.deal.SwapMarginRebatePnl = 0;
|
||||
thisObj.deal.SwapMarginAmount = 0;
|
||||
let scale = thisObj.getPriceScale();
|
||||
thisObj.floatPosition.TradingAmount = parseFloat(thisObj.floatPosition.TradingAmountAvg) * parseFloat(thisObj.deal.CloseNotionalValue) * scale;
|
||||
let deliveryPrice = thisObj.getStorageDeliveryPrice();
|
||||
thisObj.floatPosition.TradingAmount = deliveryPrice * parseFloat(thisObj.deal.CloseNotionalValue);
|
||||
thisObj.floatPosition.CloseFee = TradingFee;
|
||||
if (thisObj.deal.CloseQty > 0) {
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) * scale + (TradingFee / thisObj.deal.CloseQty) * floatRatio;
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = deliveryPrice + (TradingFee / thisObj.deal.CloseQty) * floatRatio;
|
||||
} else {
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) * scale;
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = deliveryPrice;
|
||||
}
|
||||
this.interestList.forEach(x => {
|
||||
//let interestRatio = x.InterestDirection == 1 ? 1 : -1;
|
||||
@@ -277,7 +282,7 @@ const vue = new Vue({
|
||||
thisObj.floatPosition.EventDate = thisObj.deal.ValueDate;
|
||||
let floatPosition = _.cloneDeep(thisObj.floatPosition);
|
||||
floatPosition.Quantity = 0;
|
||||
floatPosition.TradingAmountAvg = floatPosition.TradingAmountAvg * thisObj.getPriceScale();
|
||||
floatPosition.TradingAmountAvg = thisObj.getStorageDeliveryPrice();
|
||||
reqObj.FlowEvents.push(floatPosition);
|
||||
var postData = { unwindData: reqObj };
|
||||
var msg = "确认提交收益结算?";
|
||||
|
||||
@@ -13,7 +13,10 @@ const inputFormatSwapRate = Object.freeze({ precision: otcformat.trading.premium
|
||||
const inputFormatTradePrice = Object.freeze({ precision: otcformat.trading.tradePrice.precision, negative: true, append: '' });
|
||||
const inputFormatTradeSinglePrice = Object.freeze({ precision: otcformat.trading.tradeSinglePrice.precision, negative: true, append: '', percent: false });
|
||||
const inputFormatMarginRate = Object.freeze({ precision: otcformat.trading.marginRateP.precision, append: '%' });
|
||||
const inputFormatMarginRateNoPercent = Object.freeze({ precision: otcformat.trading.umpriceP.precision, append: '', percent:true });
|
||||
const inputFormatSwapDeliveryPrice = Object.freeze({ precision: 9, negative: true, append: '', percent: false });
|
||||
const inputFormatSwapBondDeliveryPrice = Object.freeze({ precision: 9, negative: true, append: '', percent: true });
|
||||
const inputFormatSwapBondNetPriceAndYtm = Object.freeze({ precision: 9, negative: true, append: '', percent: true });
|
||||
const swapBondStoragePricePrecision = inputFormatSwapBondDeliveryPrice.precision + 2;
|
||||
|
||||
const consUnderlyingFlagBase = (function () {
|
||||
let unSelFlag = tradeHelper.UnderlyingSelectFlag;
|
||||
@@ -219,6 +222,15 @@ const vue = new Vue({
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
roundStorageDeliveryPrice(item, price) {
|
||||
const precision = tradeHelper.IsBond(item && item.UnderlyingInstrumentType)
|
||||
? swapBondStoragePricePrecision
|
||||
: inputFormatSwapDeliveryPrice.precision;
|
||||
return _.round(Number(price), precision);
|
||||
},
|
||||
roundStorageBondNetPriceAndYtm(value) {
|
||||
return value == null ? value : _.round(Number(value), swapBondStoragePricePrecision);
|
||||
},
|
||||
getPosiPriceFormatKey(item, field) {
|
||||
const index = item && item.index != null ? item.index : '';
|
||||
const isBond = tradeHelper.IsBond(item && item.UnderlyingInstrumentType);
|
||||
@@ -376,7 +388,8 @@ const vue = new Vue({
|
||||
//计算数量
|
||||
if (this.paySwapList.length > 0) {
|
||||
var item = this.paySwapList[0];
|
||||
var notional = item.PosiGrossPrice * item.ContractSize;
|
||||
var deliveryPrice = this.roundStorageDeliveryPrice(item, item.PosiGrossPrice);
|
||||
var notional = deliveryPrice * item.ContractSize;
|
||||
item.PosiQuantity = notional == 0 ? 0 : _.round(this.trade.StockEqvNotional / notional, page.otcFormatConfig.StockEqvNotional.precision);
|
||||
this.calcNotional();
|
||||
}
|
||||
@@ -457,7 +470,8 @@ const vue = new Vue({
|
||||
}
|
||||
var national = payItem.PosiQuantity * payItem.ContractSize;
|
||||
// 守卫: 名义本金必须 round 到 2 位 → 对应历史 bug f873239a(缺 _.round); 外置到 swapCalc.calcStockEqvNotional
|
||||
var stockEqvNotional = SwapCalc.calcStockEqvNotional(payItem.PosiGrossPrice, national);//名义本金=期初价格*数量*乘数
|
||||
var deliveryPrice = this.roundStorageDeliveryPrice(payItem, payItem.PosiGrossPrice);
|
||||
var stockEqvNotional = SwapCalc.calcStockEqvNotional(deliveryPrice, national);//名义本金=期初价格*数量*乘数
|
||||
this.trade.StockEqvNotional = otcformat.trading.stockEqvNotional(stockEqvNotional);
|
||||
payItem.PosiNotionalValue = this.trade.StockEqvNotional;
|
||||
}
|
||||
@@ -601,6 +615,9 @@ const vue = new Vue({
|
||||
errorcount++;
|
||||
return false;
|
||||
}
|
||||
x.PosiGrossPrice = thisObj.roundStorageDeliveryPrice(x, x.PosiGrossPrice);
|
||||
x.PosiNetNoFeePrice = thisObj.roundStorageBondNetPriceAndYtm(x.PosiNetNoFeePrice);
|
||||
x.InitYtm = x.InitYtm == null ? null : thisObj.roundStorageBondNetPriceAndYtm(x.InitYtm);
|
||||
thisObj.trade.swap_positions.push(x);
|
||||
});
|
||||
} else {
|
||||
@@ -735,8 +752,8 @@ const vue = new Vue({
|
||||
// 非 EodPrice 分支 ×bondPriceMultiple=0.01)。故此处仅做精度格式化,**不可**再 bondCalcPriceToStorage(÷100),
|
||||
// 否则默认价 1.0 被除成 0.01,界面 percent:true 再 ×100 显示为 1("被自动除以100"bug)。
|
||||
// 计算器(/Bond/CalcBond)返回的才是展示态,其 ÷100 落库逻辑在 calcBondForItem 内处理。
|
||||
item.PosiNetNoFeePrice = otcformat.trading.umprice(resp.obj.netPrice);
|
||||
item.PosiGrossPrice = otcformat.trading.umprice(resp.obj.price);
|
||||
item.PosiNetNoFeePrice = thisObj.roundStorageBondNetPriceAndYtm(resp.obj.netPrice);
|
||||
item.PosiGrossPrice = thisObj.roundStorageDeliveryPrice(item, resp.obj.price);
|
||||
thisObj.calcNotional();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ const inputFormatTradeAmount = Object.freeze({ precision: otcformat.trading.noti
|
||||
const inputFormatEqvNotional = Object.freeze({ precision: otcformat.trading.StockEqvNotional.precision, append: '', negative: true });
|
||||
const inputFormatMarginRate = Object.freeze({ precision: otcformat.trading.marginRateP.precision, append: '%' });
|
||||
const inputFormatMarginRateNoPercent = Object.freeze({ precision: otcformat.trading.umpriceP.precision, append: '', percent: true });
|
||||
const inputFormatSwapDeliveryPrice = Object.freeze({ precision: 9, append: '', negative: true });
|
||||
let ValueDate = model.ValueDate;
|
||||
const vue = new Vue({
|
||||
el: '#vueDiv',
|
||||
@@ -40,6 +41,10 @@ const vue = new Vue({
|
||||
getPriceScale() {
|
||||
return this.multiplier == 100 ? 0.01 : 1;
|
||||
},
|
||||
getStorageDeliveryPrice() {
|
||||
const precision = inputFormatSwapDeliveryPrice.precision + (this.multiplier === 100 ? 2 : 0);
|
||||
return SwapCalc.roundHalfAwayFromZero(Number(this.floatPosition.TradingAmountAvg) * this.getPriceScale(), precision);
|
||||
},
|
||||
initDeal() {
|
||||
var positions = model.FlowEvents.filter((item) => {
|
||||
return item.UnderlyingCode;
|
||||
@@ -84,7 +89,7 @@ const vue = new Vue({
|
||||
this.deal.SwapCloseAmount = otcformat.trading.StockEqvNotional(this.deal.SwapCloseAmount);
|
||||
//this.floatPosition.PosiNetPrice = otcformat.trading.tradeSinglePrice(this.floatPosition.PosiNetPrice);
|
||||
//this.floatPosition.PosiGrossPrice = otcformat.trading.tradeSinglePrice(this.floatPosition.PosiGrossPrice);
|
||||
this.floatPosition.TradingAmountAvg = otcformat.trading.tradeSinglePrice(this.floatPosition.TradingAmountAvg);
|
||||
this.floatPosition.TradingAmountAvg = _.round(Number(this.floatPosition.TradingAmountAvg), 9);
|
||||
this.floatPosition.TradingFee = otcformat.trading.StockEqvNotional(this.floatPosition.TradingFee);
|
||||
this.floatPosition.TradingFeePending = otcformat.trading.StockEqvNotional(this.floatPosition.TradingFeePending);
|
||||
this.floatPosition.DividendIn = parseFloat(this.floatPosition.DividendIn).toFixed(2);
|
||||
@@ -212,7 +217,7 @@ const vue = new Vue({
|
||||
{ code: thisObj.floatPosition.UnderlyingCode, valuedate: thisObj.deal.ValueDate })
|
||||
.done(function (res) {
|
||||
res.obj = res.obj * thisObj.multiplier;
|
||||
thisObj.floatPosition.TradingAmountAvg = otcformat.trading.tradeSinglePrice(res.obj);
|
||||
thisObj.floatPosition.TradingAmountAvg = _.round(Number(res.obj), 9);
|
||||
thisObj.calcFloatClosePnl();
|
||||
});
|
||||
},
|
||||
@@ -222,8 +227,8 @@ const vue = new Vue({
|
||||
let longRatio = thisObj.floatPosition.PositionType == 1 ? 1 : -1;
|
||||
let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee);
|
||||
let TradingFeePending = thisObj.floatPosition.TradingFeePending == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFeePending);
|
||||
let scale = thisObj.getPriceScale();
|
||||
thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseQty * (thisObj.floatPosition.TradingAmountAvg * scale - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000;
|
||||
let deliveryPrice = thisObj.getStorageDeliveryPrice();
|
||||
thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseQty * (deliveryPrice - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000;
|
||||
thisObj.floatPosition.MarkClosePnl = Number(thisObj.floatPosition.MarkClosePnl.toFixed(2));//MarkClosePnl 纯盯市不要计算交易费用和分红
|
||||
thisObj.floatPosition.MarkClosePnl = otcformat.trading.StockEqvNotional(thisObj.floatPosition.MarkClosePnl);
|
||||
thisObj.floatPosition.FloatPnlSum = (parseFloat(thisObj.floatPosition.MarkClosePnl) + TradingFee + TradingFeePending + parseFloat(thisObj.floatPosition.DividendIn)).toFixed(2);
|
||||
@@ -253,13 +258,13 @@ const vue = new Vue({
|
||||
thisObj.deal.SwapRealizedPnL = pnl;
|
||||
thisObj.deal.SwapMarginRebatePnl = 0;
|
||||
thisObj.deal.SwapMarginAmount = 0;
|
||||
let scale = thisObj.getPriceScale();
|
||||
thisObj.floatPosition.TradingAmount = parseFloat(thisObj.floatPosition.TradingAmountAvg) * parseFloat(thisObj.deal.CloseQty) * scale;
|
||||
let deliveryPrice = thisObj.getStorageDeliveryPrice();
|
||||
thisObj.floatPosition.TradingAmount = deliveryPrice * parseFloat(thisObj.deal.CloseQty);
|
||||
thisObj.floatPosition.CloseFee = TradingFee;
|
||||
if (thisObj.deal.CloseQty == 0) {
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = 0;
|
||||
} else {
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) * scale + (TradingFee / thisObj.deal.CloseQty) * ratio;
|
||||
thisObj.floatPosition.TradingAmountFeeAvg = deliveryPrice + (TradingFee / thisObj.deal.CloseQty) * ratio;
|
||||
}
|
||||
this.interestList.forEach(x => {
|
||||
/*let interestRatio = x.InterestDirection == 1 ? 1 : -1;*/
|
||||
@@ -360,7 +365,7 @@ const vue = new Vue({
|
||||
thisObj.floatPosition.EventDate = thisObj.deal.ValueDate;
|
||||
let floatPosition = _.cloneDeep(thisObj.floatPosition);
|
||||
floatPosition.Quantity = reqObj.CloseQty;
|
||||
floatPosition.TradingAmountAvg = floatPosition.TradingAmountAvg * thisObj.getPriceScale();
|
||||
floatPosition.TradingAmountAvg = thisObj.getStorageDeliveryPrice();
|
||||
reqObj.FlowEvents.push(floatPosition);
|
||||
var postData = { unwindData: reqObj };
|
||||
var msg = "确认提交平仓?";
|
||||
|
||||
@@ -276,6 +276,7 @@
|
||||
tradeHelper.IsBond = function (instType) {
|
||||
switch (instType) {
|
||||
case "Bonds":
|
||||
case "Bond":
|
||||
case "TBonds":
|
||||
case "CreditBonds":
|
||||
case "OtherBonds":
|
||||
|
||||
Reference in New Issue
Block a user