//otcformat禁止千分位分组 window.otcformat.options.disableGrouping = true; const consClients = ylotc.clients; const consTraders = ylotc.traders; const consAssetUnits = page.canAddNewTrader ? ylotc.assetunits : ylotc.assetunits.filter(x => x.TraderIds.includes(page.Trade.TraderId)); const inputFormatInteger = Object.freeze({ precision: 0, append: '' }); const inputFormatEqvNotional = Object.freeze({ precision: otcformat.trading.StockEqvNotional.precision, append: '' }); const inputFormatTradeAmount = Object.freeze({ precision: otcformat.trading.notional.precision, append: '' }); const inputFormatSwapRate = Object.freeze({ precision: otcformat.trading.premiumRateP.precision, negative: true, append: '%' }); 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 inputFormatPosiFeePercent = Object.freeze({ precision: 4, negative: true, append: '%' }); const inputFormatPosiFeeUnit = Object.freeze({ precision: 2, negative: true, append: '' }); const inputFormatMarginRate = Object.freeze({ precision: otcformat.trading.marginRateP.precision, append: '%' }); 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 consPosiFeeType = Object.freeze({ Percent: 0, Unit: 1 }); const swapPosiFeeCalc = Object.freeze({ normalizeFeeType(feeType) { return Number(feeType) === consPosiFeeType.Unit ? consPosiFeeType.Unit : consPosiFeeType.Percent; }, calcPending(feeType, feeUnit, stockEqvNotional, quantity) { const normalizedFeeType = this.normalizeFeeType(feeType); const normalizedFeeUnit = Number(feeUnit) || 0; const normalizedNotional = Number(stockEqvNotional) || 0; const normalizedQuantity = Number(quantity) || 0; const tradingFeePending = normalizedFeeType === consPosiFeeType.Percent ? normalizedFeeUnit / 100 * normalizedNotional : normalizedFeeUnit * normalizedQuantity; return otcformat.trading.tradeSinglePrice(tradingFeePending); }, calcFeeUnit(feeType, tradingFeePending, stockEqvNotional, quantity) { const normalizedFeeType = this.normalizeFeeType(feeType); const normalizedTradingFeePending = Number(tradingFeePending) || 0; const normalizedNotional = Number(stockEqvNotional) || 0; const normalizedQuantity = Number(quantity) || 0; if (normalizedFeeType === consPosiFeeType.Percent) { return normalizedNotional === 0 ? 0 : _.round(normalizedTradingFeePending / normalizedNotional * 100, inputFormatPosiFeePercent.precision); } return normalizedQuantity === 0 ? 0 : _.round(normalizedTradingFeePending / normalizedQuantity, inputFormatPosiFeeUnit.precision); } }); const consUnderlyingFlagBase = (function () { let unSelFlag = tradeHelper.UnderlyingSelectFlag; return unSelFlag.UseForTrading | unSelFlag.IncludeMatured | unSelFlag.UsePinYinFilter | unSelFlag.IncludeBasket | unSelFlag.IncludeSynthetic | unSelFlag.CheckLaunch; }()); const consUnderlyingFlagNonBond = (function () { let unSelFlag = tradeHelper.UnderlyingSelectFlag; //临时注释,保证业务不受影响 //return consUnderlyingFlagBase | unSelFlag.Stock | unSelFlag.StockIndex | unSelFlag.StockIF | unSelFlag.Fund | unSelFlag.CommodityFutures | unSelFlag.CommoditySpot; return consUnderlyingFlagBase; }()); const consUnderlyingFlagBond = (function () { let unSelFlag = tradeHelper.UnderlyingSelectFlag; const consUnderlyingFlagNonBond = (function () { let unSelFlag = tradeHelper.UnderlyingSelectFlag; //临时注释,保证业务不受影响 //return consUnderlyingFlagBase | unSelFlag.Stock | unSelFlag.StockIndex | unSelFlag.StockIF | unSelFlag.Fund | unSelFlag.CommodityFutures | unSelFlag.CommoditySpot; return consUnderlyingFlagBase; }()); }()); const inputFormatDouble2 = Object.freeze({ precision: 2, append: '' }); var autoMarginTemplateName; //定价格式化(来自配置) const InputFormatPercent = Object.freeze({ precision: 2, append: '%' }); const consMetaDic = { '组合标的': JSON.parse(page.Trade.MetaDic['组合标的'] || '{}'), '组合标的2': JSON.parse(page.Trade.MetaDic['组合标的2'] || '{}') }; //定价格式化(来自配置) const pricingFormat = otcformat.trading; //数字格式化 const consNumberFormat = Object.freeze(new function () { this.umpriceP = pricingFormat.umpriceP; this.umprice = pricingFormat.umprice; this.premiumRateP = pricingFormat.premiumRateP; return this; }()); const createVueUnderlying = function (selectFlag) { return { props: ['value', 'index'], data() { return { autoUnderlying: null }; }, mounted() { var selFlag = tradeHelper.UnderlyingSelectFlag; this.autoUnderlying = tradeHelper.UnderlyingAutoComplete(this.$el, { SelectFlag: selFlag.UsePinYinFilter | selFlag.UseForTrading | selFlag.IncludeSynthetic | selFlag.IncludeMatured | selFlag.IncludeBasket | selFlag.CheckLaunch, BlackLimit: 2, }); this.autoUnderlying.onSelect(this.onchange); this.value && this.autoUnderlying.selectByCode(this.value); }, methods: { onchange(data) { this.$emit('change', data); this.$emit('input', data.Code); } }, destroyed() { this.autoUnderlying && this.autoUnderlying.dispose(); }, template: '' }; }; const vueUnderlyingNonBond = function () { return createVueUnderlying(consUnderlyingFlagNonBond); }; const vueUnderlyingBond = function () { return createVueUnderlying(consUnderlyingFlagBond); }; //标的选择组件 银行间回购定盘&其他利率 const vueUnderlyingRate = function () { return { props: ['value', 'index'], data() { return { autoUnderlying: null }; }, mounted() { var selFlag = tradeHelper.UnderlyingSelectFlag; var instrumentTypes = ["FixingRepoRate", "OtherRate"]; this.autoUnderlying = tradeHelper.UnderlyingAutoComplete(this.$el, { SelectFlag: selFlag.UsePinYinFilter | selFlag.UseForTrading | selFlag.IncludeSynthetic | selFlag.IncludeMatured | selFlag.IncludeBasket | selFlag.CheckLaunch, BlackLimit: 2, InstrumentTypes: instrumentTypes, UseAll: true, UseSignle: true }); this.autoUnderlying.onSelect(this.onchange); this.value && this.autoUnderlying.selectByCode(this.value); }, methods: { onchange(data) { data.index = this.index; if (this.value !== data.Code) { this.$emit('change', data); this.$emit('input', data.Code); } } }, destroyed() { this.autoUnderlying && this.autoUnderlying.dispose(); }, template: '' }; }; //ESC $(document).keyup(function (event) { if (event.keyCode === 27) { window.parent.layer.closeAll(); } }); const vue = new Vue({ el: '#tradeEdit', data: { page: page, trade: _.cloneDeep(page.Trade), viewState: { variety: tradeHelper.getEmptyVariety(), underlying: tradeHelper.getEmptyUnderlying(), synthetic: null, Extend: { TradingPlace: "柜台市场", ClearingAgency: "交易员方" } }, currencys: page.currencys, getNotionalSingleFee: 0, isSingleFee: page.Trade.trade_extend.ExtendObj.OpenFeeType == 0, posiFeeModePercent: true, observation: {//互换观察日 ObservationInterval: "", IntervalList: [], ObservationNum: 1, ObservationUnit: 'D', ObservationHolidayType: 'Following', ObservationAlignEnd: true, ObservationCalendar: 'Chn', ObservationSettlementRules: 0, DefaultTitle1Value: 0.1, ObservationDataList: [], CheckedAll: false, index: 0, IsDeductPrincipal: true, ObservationStart: page.Trade.TradeDate }, observationHolidayTypes: [ { text: "向后调整", value: "Following" }, { text: "向前调整", value: "Previous" }, { text: "不调整", value: "None" } ], alignEndTypes: [ { text: "向到期日对齐", value: true }, { text: "向开始日对齐", value: false } ], marginSwapList: [], getSwapList: [],//利息端 paySwapList: [],//浮动端, observationType: 0, client: null,//客户信息 StockEqvNotional: 0, underlying: { UnderlyingCode: '', UnderlyingName: '', UnderlyingIssuer: '', IssueSize: '', MaturityDate: '', Price: '', UnderlyingInstrumentType: '', QuoteUnitString: '' } }, watch: { }, created: function () { if (this.trade.MetaDic['组合标的']) { this.viewState.synthetic = JSON.parse(this.trade.MetaDic['组合标的']); } if (this.trade.MetaDic["交易场所"]) { this.viewState.Extend.TradingPlace = this.trade.MetaDic["交易场所"]; } if (this.trade.MetaDic["清算机构"]) { this.viewState.Extend.ClearingAgency = this.trade.MetaDic["清算机构"]; } }, mounted() { __init(this); $("#MainProtocolCode").val(this.trade.MetaDic["主协议编号"]); $("#SupProtocolCode").val(this.trade.MetaDic["补充协议编号"]); this.initSwapRateList(); // 初始化到期日期选择器下限 this.$nextTick(() => { if (this.$refs.exerciseDatePicker) { var minDate = this.trade.StartDate > this.trade.TradeDate ? this.trade.StartDate : this.trade.TradeDate; this.$refs.exerciseDatePicker.refresh(minDate, null); } }); }, 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); return `${index}-${field}-${isBond ? 'bond' : 'other'}`; }, getCurrentPosiFeeType() { return this.posiFeeModePercent ? consPosiFeeType.Percent : consPosiFeeType.Unit; }, normalizePosiFeeType(feeType) { return swapPosiFeeCalc.normalizeFeeType(feeType); }, syncPosiFeeModeByItem(item) { this.posiFeeModePercent = this.normalizePosiFeeType(item && item.PosiFeeType) !== consPosiFeeType.Unit; }, syncPayItemFeeType(item) { item.PosiFeeType = this.getCurrentPosiFeeType(); }, refreshTradingFeePendingByUnit(item) { this.syncPayItemFeeType(item); item.PosiTradingFeePending = swapPosiFeeCalc.calcPending( item.PosiFeeType, item.PosiTradingFeeUnit, this.trade.StockEqvNotional, item.PosiQuantity ); }, refreshTradingFeeUnitByPending(item) { this.syncPayItemFeeType(item); item.PosiTradingFeeUnit = swapPosiFeeCalc.calcFeeUnit( item.PosiFeeType, item.PosiTradingFeePending, this.trade.StockEqvNotional, item.PosiQuantity ); }, refreshPayTradingFeesByUnit() { this.paySwapList.forEach(item => { this.refreshTradingFeePendingByUnit(item); }); }, changeStructureType() { this.trade.StockEqvNotional = 0; let direction = this.trade.trade_extend.ExtendObj.Direction; if (direction !== 1 && direction !== 2) { direction = 2; this.trade.trade_extend.ExtendObj.Direction = direction; } this.paySwapList = []; this.addSwapFloat(direction); //this.trade.trade_extend.ExtendObj.FlowBookMode = 0; }, //变更初始预付金收取方向 changeInitialMargin() { if (this.trade.trade_Initial_Margin.Direction == 1) { this.trade.trade_Initial_Margin.Direction = 2; } else { this.trade.trade_Initial_Margin.Direction = 1; } }, //变更交易场所 changeTradingPlace() { this.trade.MetaDic["交易场所"] = this.viewState.Extend.TradingPlace; }, //变更清算机构 changeClearingAgency() { this.trade.MetaDic["清算机构"] = this.viewState.Extend.ClearingAgency; }, //全价(DP)列输入:先按标的单价重算名义本金(非债券标的也需要),再对债券触发三字段反算。 // 组件 vue-number-input 只 $emit('input')(失焦/回车时由底层 numberInput.onchange 触发), // 故此列绑 v-on:input,一个入口同时覆盖普通标的与债券两种情形。 onDpPriceInput(item) { this.changeSpotPrice(item); // 名义本金随全价变化(非债券标的的既有逻辑) this.onBondPriceInput(item, 'DP'); // 债券:以全价为源反算净价/收益率(非债券内部会早返回) }, //债券收益互换:编辑某一浮动腿的净价/全价/收益率之一 → 该字段标记为"已手动设过"(锁定), // 并以它为源调计算器反算"尚未手动设过"的另两个字段(已手动设过的一律不回写) onBondPriceInput(item, type) { // type: 'CP'净价 / 'DP'全价 / 'YD'收益率 if (!item.isBond) return; var m = item.bondManual || { CP: false, DP: false, YD: false }; m[type] = true; this.$set(item, 'bondManual', m); // 锁定用户手填字段 this.$set(item, 'bondDriverType', type); // 以该字段为本次计算源 this.calcBondForItem(item); }, //放弃手动覆盖、以当前某字段为源重新自动反算(清空所有手动锁定标记) resetBondCalc(item) { if (!item.isBond) return; this.$set(item, 'bondManual', { CP: false, DP: false, YD: false }); // 优先沿用用户最后一次编辑锁定的源(bondDriverType),避免"净价残留脏值"时误以净价为源反算出连锁错误; // 无历史源时再按 净价→全价→收益率 回退挑一个有值的字段。 var hasVal = function (v) { return v !== null && v !== '' && !isNaN(v); }; var driver = item.bondDriverType || (hasVal(item.PosiNetNoFeePrice) ? 'CP' : hasVal(item.PosiGrossPrice) ? 'DP' : hasVal(item.InitYtm) ? 'YD' : null); this.$set(item, 'bondDriverType', driver); this.calcBondForItem(item); }, //以该浮动腿的 bondDriverType 为源调 /Bond/CalcBond;回写时跳过"已手动设过的字段"(bondManual), //仅反向填充用户尚未手动设过的字段——故用户可逐个手填全部三个而互算不会冲掉任一个 //错误处理(对齐 bond-oms-ui / zszq-bond-oms): // - 业务/参数错误(success=false 或 errCode!=0,如债券不存在/信息不全/参数非法) // 以非阻塞 toast(main.message) 反馈真实原因,绝不回写、不弹模态框、不阻止手工输入; // - 网络/服务异常:框架 main.post 已弹"请求失败",此处不再二次提示。 calcBondForItem(item) { if (!item.isBond || !item.bondDriverType) return; if (!item.UnderlyingCode) { main.message("请先选择债券标的"); return; } var price = item.bondDriverType === 'CP' ? item.PosiNetNoFeePrice : item.bondDriverType === 'DP' ? item.PosiGrossPrice : item.InitYtm; if (price === null || price === '' || isNaN(price)) return; // 编辑中(空/非数)静默,不提示 var priceType = item.bondDriverType === 'CP' ? 'CP' : item.bondDriverType === 'DP' ? 'DP' : 'YD'; var self = this; // 估值日:债券互换的"期初"净价/全价/收益率应以【互换起始日 StartDate】估值。 // 该字段在页面上本就是可选择的日期控件(vue-datepicker),用户可改;现已默认即有。 // 不再"悄悄回退到交易日(TradeDate)"——真的为空时直接报错提示,由用户填写/手动填三数(需求2)。 var targetDate = (this.trade && this.trade.StartDate) ? this.trade.StartDate : null; var sdMsg = SwapCalc.getBondStartDateMissingMsg(targetDate); if (sdMsg) { // D3 同款去重:开始日缺失时用户在价格格逐键输入会连刷相同提示,故同一文案只弹一次 if (SwapCalc.shouldShowBondErr(item, sdMsg)) main.message(sdMsg); return; // 估值日缺失:不调用计算器、不覆盖任何手工输入 } main.post('/Bond/CalcBond', { underlyingCode: item.UnderlyingCode, // 模型 item.PosiGrossPrice/PosiNetNoFeePrice/InitYtm 存的是【存储态小数】(如 0.995), // 而 bond-calc 要的是【展示态/每百元百分比】(如 99.5)。这俩靠 BondPriceConverter.ToDisplay(×100)/ToStorage(÷100) 对齐。 // 此处传给计算器前必须 bondPriceToCalc(存储→展示);回写时再 bondCalcPriceToStorage(展示→存储), // 否则计算器拿到 0.995≈1 当 1% of par 直接发散成离谱值。 price: SwapCalc.bondPriceToCalc(price), priceType: priceType, targetDate: targetDate }, { alertFn: main.message }).done(function (resp) { if (!resp || !resp.obj) return; // 业务层错误(债券不存在/信息不全/参数非法):仅提示,绝不覆盖手工输入 var err = SwapCalc.getBondCalcErrorMessage(resp.obj); if (err) { // D3 修复:不可算债券上用户逐键手填时,每次按键都触发一次失败计算并弹 toast,会连刷相同提示; // 同一错误文案连续出现只弹一次(shouldShowBondErr 维护 item._lastBondErr),抑制噪声、不影响任何计算逻辑。 if (SwapCalc.shouldShowBondErr(item, err)) main.message(err); return; } item._lastBondErr = null; // 成功则清标记,便于下次真出不同错误时仍能提示 // 以既有三字段为代理,调用纯函数(已手动设过的字段不被覆盖),再写回。 // 关键:proxy 内必须统一为【展示态】(per-100-face),因为 applyBondCalcResult 写入的是计算器返回的展示态。 // 模型字段是【存储态小数】(percent:true 下 1.00 对应界面 100),所以初始化时要 bondPriceToCalc(×100); // 若直接用存储态初始化,则用户手填字段被 applyBondCalcResult 跳过后,proxy 中仍残留存储态, // 后续再 ÷100 就会导致该字段被二次缩小(如输入 100 变成 1)。 var proxy = { cleanPrice: SwapCalc.bondPriceToCalc(item.PosiNetNoFeePrice), dirtyPrice: SwapCalc.bondPriceToCalc(item.PosiGrossPrice), ytm: SwapCalc.bondPriceToCalc(item.InitYtm) }; var manual = item.bondManual || { CP: false, DP: false, YD: false }; SwapCalc.applyBondCalcResult(proxy, resp.obj, manual); // 回写前 bondCalcPriceToStorage(÷100)(展示态→存储态小数):proxy 里均为展示态; // 模型字段存存储态(0.995),须 ÷100 落回模型,否则配合 percent:true 显示会 ×100 成离谱值。 item.PosiNetNoFeePrice = SwapCalc.bondCalcPriceToStorage(proxy.cleanPrice); item.PosiGrossPrice = SwapCalc.bondCalcPriceToStorage(proxy.dirtyPrice); item.InitYtm = SwapCalc.bondCalcPriceToStorage(proxy.ytm); // 名义本金依赖全价(PosiGrossPrice):以净价/收益率为源反算出的全价被回写后, // 直接赋值不会触发组件 input 事件,需在此显式重算,保持名义本金与全价一致。 if (self.calcNotional) self.calcNotional(); if (self.$forceUpdate) self.$forceUpdate(); }); }, //变更收费基本单位 changeOpenFeeType() { var thisObj = this; thisObj.paySwapList.forEach(item => { thisObj.changeTradingFeeUnit(item); }) }, //变更数量 changeQuantity(item) { this.calcNotional(); }, //变更标的单价 changeSpotPrice(item) { this.calcNotional(); }, //变更标的合约乘数 changeContractSize(item) { this.calcNotional(); }, //变更名义本金(仅格式化,不反算数量) changeStockEqvNotional() { this.trade.StockEqvNotional = otcformat.trading.StockEqvNotional(this.trade.StockEqvNotional); this.refreshPayTradingFeesByUnit(); //计算数量 // if (this.paySwapList.length > 0) { // var item = this.paySwapList[0]; // 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(); // } }, //变更初始预付金 为¥ showAbsPrice() { this.trade.trade_Initial_Margin.MarginType = 1; this.trade.trade_Initial_Margin.MarginValue = this.trade.trade_Initial_Margin.MarginValue * this.trade.StockEqvNotional; }, //变更单位交易费用 为% showPercentPrice() { this.trade.trade_Initial_Margin.MarginType = 0; this.trade.trade_Initial_Margin.MarginValue = this.trade.StockEqvNotional == 0 ? 0 : this.trade.trade_Initial_Margin.MarginValue / this.trade.StockEqvNotional; }, //成交日期变更时自动修正联动日期 onTradeDateChange() { if (this.trade.StartDate < this.trade.TradeDate) { // 开始日期 = 成交日期 + 1天,跳过节假日 var d = new Date(this.trade.TradeDate); d.setDate(d.getDate() + 1); while (ylotc.isHoliday(d)) { d.setDate(d.getDate() + 1); } this.trade.StartDate = this.formatDate(d); } // 到期日期必须 ≥ 成交日期 且 ≥ 开始日期 if (this.trade.ExerciseDate < this.trade.TradeDate || this.trade.ExerciseDate < this.trade.StartDate) { // 到期日期 = 开始日期 + 14天,跳过节假日 var sd = new Date(this.trade.StartDate); sd.setDate(sd.getDate() + 14); while (ylotc.isHoliday(sd)) { sd.setDate(sd.getDate() + 1); } this.trade.ExerciseDate = this.formatDate(sd); } this.changeTradeDate(); }, //开始日期变更时检查到期日期 onStartDateChange() { if (this.trade.ExerciseDate < this.trade.StartDate) { var sd = new Date(this.trade.StartDate); sd.setDate(sd.getDate() + 14); while (ylotc.isHoliday(sd)) { sd.setDate(sd.getDate() + 1); } this.trade.ExerciseDate = this.formatDate(sd); } this.changeTradeDate(); }, //变更交易日期 changeTradeDate(force) { this.changeObservationStart(); if (this.Obervation) { this.Obervation.ObservationStart = this.trade.StartDate; } this.calcNotional(); this.refreshDatepicker(); this.changeMarginDate(); // 动态更新开始日期和到期日期的下限 this.$nextTick(() => { if (this.$refs.startDatePicker) { this.$refs.startDatePicker.refresh(this.trade.TradeDate, null); } if (this.$refs.exerciseDatePicker) { var minExerciseDate = this.trade.StartDate > this.trade.TradeDate ? this.trade.StartDate : this.trade.TradeDate; this.$refs.exerciseDatePicker.refresh(minExerciseDate, null); } }); //this.initMarginRate(); }, calcNotional(calcPrice) { if (this.paySwapList.length > 0) { var payItem = this.paySwapList[0]; if (calcPrice) { this.getSpotPrice(payItem.UnderlyingCode, this.trade.StartDate, payItem); } var national = payItem.PosiQuantity * payItem.ContractSize; // 守卫: 名义本金必须 round 到 2 位 → 对应历史 bug f873239a(缺 _.round); 外置到 swapCalc.calcStockEqvNotional 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; this.refreshPayTradingFeesByUnit(); } }, //变更到期日 changeExerciseDate() { this.refreshDatepicker(); this.changeMarginDate(); }, //变更预付金生效日期 changeMarginDate() { var thisObj = this; thisObj.observation.ObservationStart = thisObj.trade.StartDate; var startDate = thisObj.trade.StartDate; var endDate = thisObj.trade.ExerciseDate; if (thisObj.marginSwapList) { thisObj.marginSwapList.forEach((item, index) => { if (item.HappenDate < startDate) { thisObj.marginSwapList[index].HappenDate = startDate; thisObj.changeStartMarinRateDate(thisObj.marginSwapList[index]); } else if (item.HappenDate > endDate) { thisObj.marginSwapList[index].HappenDate = endDate; thisObj.changeStartMarinRateDate(thisObj.marginSwapList[index]); } }); } }, // 变更预付金结算规则起息日期 changeStartMarinRateDate(item) { if (item.Obervation) { item.Obervation.ObservationStart = item.HappenDate; } }, //变更单位交易费用 changeTradingFeeUnit(item) { this.refreshTradingFeePendingByUnit(item); }, //变更交易费用 changeTradingFee(item) { this.refreshTradingFeeUnitByPending(item); }, showPayAbsPrice() { this.posiFeeModePercent = false; this.paySwapList.forEach(item => { item.PosiFeeType = consPosiFeeType.Unit; item.PosiTradingFeeUnit = 0; item.PosiTradingFeePending = 0; }); }, showPayPercentPrice() { this.posiFeeModePercent = true; this.paySwapList.forEach(item => { item.PosiFeeType = consPosiFeeType.Percent; item.PosiTradingFeeUnit = 0; item.PosiTradingFeePending = 0; }); }, savetrade() { if (!this.checkSubmitData()) { return false; } this.savetrade_inner(); }, savetrade_inner() { var thisObj = this; //this.paySwapList.forEach(x => { // x.SwapIntervals = this.trade.ExerciseDate + ";" + x.InterestRate; //}); this.trade.IsUsePremiumRate = true; this.trade.IsTradePricePayType = true; this.trade.UnderlyingInstrumentType = "Stock"; this.trade.swap_positions = []; var date = thisObj.trade.ExerciseDate; var errorcount = 0; if (this.trade.trade_extend.ExtendObj.InterestCalcMode == "00" || this.trade.trade_extend.ExtendObj.InterestCalcMode == "10") { date = moment(date).add(-1, 'days').format('YYYY-MM-DD'); } this.getSwapList.forEach((x,index) => { if ((x.UnderlyingCode == null || x.UnderlyingCode.length == 0) && x.SwapIntervalList.length == 0) { var interval = { Date: date, Rate: x.InterestRateDefault, Settlement: 0 } x.SwapIntervalList.push(interval); } if (x.interest_rest_days != null && x.interest_rest_days <= 0) { main.message("利息端第" + (index + 1) + "行重置频率必须大于0"); errorcount++; return false; } x.FloatRateUnderlyingCode = x.FloatRateUnderlyingCode == "--" ? null : x.FloatRateUnderlyingCode; x.InterestSwapInterval = JSON.stringify(x.SwapIntervalList); thisObj.trade.swap_positions.push(x); }); if (errorcount > 0) { return; } var margin = 0; this.marginSwapList.forEach((x, index) => { if ((x.UnderlyingCode == null || x.UnderlyingCode.length == 0) && x.SwapIntervalList.length == 0) { var interval = { Date: date, Rate: x.InterestRateDefault, Settlement: 0 } x.SwapIntervalList.push(interval); } if (!x.HappenDate) { main.message("预付金/预付金第" + (index + 1) + "行生效日期不能为空"); errorcount++; return false; } x.FloatRateUnderlyingCode = x.FloatRateUnderlyingCode == "--" ? null : x.FloatRateUnderlyingCode; margin = margin + x.InterestPrincipalFix * (x.InterestDirection == 1 ? 1 : -1); x.InterestSwapInterval = JSON.stringify(x.SwapIntervalList); thisObj.trade.swap_positions.push(x); }); if (errorcount > 0) { return; } thisObj.trade.trade_Initial_Margin.MarginType = 1; thisObj.trade.trade_Initial_Margin.MarginValue = margin; thisObj.trade.trade_Initial_Margin.Direction = margin > 0 ? 1 : 2; if (this.trade.StructureType != "多空组合") { this.paySwapList.forEach((x, index) => { if (!x.UnderlyingCode) { main.message("浮动端第" + (index + 1) + "行标的不能为空"); errorcount++; return false; } if (!x.PosiQuantity > 0) { main.message("浮动端第" + (index + 1) + "数量不能为0"); errorcount++; return false; } if (!x.PosiGrossPrice) { main.message("浮动端第" + (index + 1) + "期初价格不能为空"); 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); x.PosiFeeType = thisObj.normalizePosiFeeType(x.PosiFeeType); thisObj.trade.swap_positions.push(x); }); } else { this.trade.trade_extend.ExtendObj.Direction = this.paySwapList[0].PosiDirection; } if (errorcount > 0) { return; } this.trade.MetaDic = { '组合标的': consMetaDic["组合标的"] ? JSON.stringify(consMetaDic["组合标的"]) : '', '组合标的2': consMetaDic["组合标的2"] ? JSON.stringify(consMetaDic["组合标的2"]) : '', '交易场所': this.viewState.Extend.TradingPlace, '清算机构': this.viewState.Extend.ClearingAgency, "主协议编号": $("#MainProtocolCode").val(), "补充协议编号": $("#SupProtocolCode").val() }; this.trade.trade_extend.ExtendJson = JSON.stringify(this.trade.trade_extend.ExtendObj); main.post("/swaptrade2/tradeEditJson", this.trade).done(function (resp) { window.location.href = "/swaptrade2/tradeview?enid=" + resp.obj.EncryptId; if (window.parent && window.parent.reloadtrade) { window.parent.reloadtrade(); } }); }, changeMainProtocolCode() { this.getSupProtocolCode(); }, getMainProtocolCode() { var thisObj = this; $("#MainProtocolCode option").remove(); main.post("/Client/getMainProtocolCodes", { clientId: $("#ClientId").val() }, { async: false }).done(function (resp) { var obj = $("#MainProtocolCode"); if (thisObj.client.MainProtocolCode != null && thisObj.client.MainProtocolCode != '') { obj.append(""); } _.forEach(resp, (v) => { obj.append(""); }) }); this.getSupProtocolCode() }, getSupProtocolCode() { $("#SupProtocolCode option").remove(); if ($("#MainProtocolCode").val()) { main.post("/Client/getSideProtocols", { mainProtocol: $("#MainProtocolCode").val() }, { async: false }).done(function (resp) { var obj = $("#SupProtocolCode"); if (thisObj.client.SupProtocolCode != null && thisObj.client.SupProtocolCode != '') { obj.append(""); } _.forEach(resp, (v) => { obj.append(""); }) }); } }, changeInterestMode(item) { if (item.InterestMode == 7 || item.InterestMode == 8) { item.InterestType = 0; } }, changeInterestType(item) { if (!item.interest_rest_days) { item.interest_rest_days = 7; } }, setUnderlyingCode(data, item) { var underlyingCode = item.UnderlyingCode; if (underlyingCode != data.Code) { this.getSpotPrice(data.Code, this.trade.TradeDate, item); } else { item.PosiGrossPrice = item.PosiGrossPrice; item.PosiNetNoFeePrice = item.PosiNetNoFeePrice; } item.CountRatio = data.CountRatio; item.ContractSize = data.ContractSize; item.UnderlyingInstrumentType = data.InstrumentType; item.UnderlyingCode = data.Code; item.underlying = { ...this.underlying }; item.underlying.UnderlyingCode = data.Code; item.underlying.UnderlyingName = data.Name; item.underlying.UnderlyingIssuer = data.UnderlyingIssuer; item.underlying.IssueSize = data.IssueSize; item.underlying.MaturityDate = data.MaturityDate; item.underlying.Price = data.Price; item.underlying.UnderlyingInstrumentType = data.InstrumentType; item.underlying.QuoteUnitString = data.QuoteUnitString; this.trade.UnderlyingCode = underlyingCode; // 债券标的:标记该浮动腿可启用净价/全价/收益率互算 this.$set(item, 'isBond', tradeHelper.IsBond(data.InstrumentType)); // 切换标的时清空债券三字段互算的手动/源标志(D1 修复:避免旧债券手填状态污染新债券) SwapCalc.clearBondCalcFlags(item); //this.initMarginRate(); }, setFloatRateUnderlyingCode(data, item) { item.FloatRateUnderlyingCode = data.Code; if (data.Code.length > 0 && data.Code != '--') { item.IsAnnualized = true; item.interest_rest_days = 7; item.interest_rule = data.Code === 'FR007' ? -1 : 0; } else { item.interest_rule = null; } //this.getFloatRate(item); }, getFloatRate(item) { var thisObj = this; if (item.FloatRateUnderlyingCode == null || item.FloatRateUnderlyingCode == '' || item.FloatRateUnderlyingCode == '--' || thisObj.paySwapList.length == 0) { item.InterestRateDefault = 0; blurSwapRate(item); return; } var floatPositionType = thisObj.paySwapList[0].PositionType; main.post("/SwapFloatRate/MatchRate", { clientId: thisObj.trade.ClientId, underlyingCode: item.FloatRateUnderlyingCode, startDate: thisObj.trade.StartDate, endDate: thisObj.trade.ExerciseDate }) .done(function (resp) { if (resp.success) { if (resp.obj != null) { item.InterestRateDefault = floatPositionType == 1 ? resp.obj.LongPricePoint : resp.obj.ShortPricePoint; item.InterestRateDefault = item.InterestRateDefault * 0.0001; } else { item.InterestRateDefault = 0; } thisObj.blurSwapRate(item); } }); }, getSpotPrice(underlyingCode, StartDate, item) { var thisObj = this; main.post("/pricing/AjaxGetUnderlyingPrice", { underlyingCode: underlyingCode, tradeDate: StartDate }) .done(function (resp) { // 行情接口(AjaxGetUnderlyingPrice)对债券返回的 price/netPrice 本就是【存储态小数】(1.0 代表 100 元), // 与 PosiGrossPrice/PosiNetNoFeePrice 模型字段同量纲(见 PricingController: EodPrice 直接返回、 // 非 EodPrice 分支 ×bondPriceMultiple=0.01)。故此处仅做精度格式化,**不可**再 bondCalcPriceToStorage(÷100), // 否则默认价 1.0 被除成 0.01,界面 percent:true 再 ×100 显示为 1("被自动除以100"bug)。 // 计算器(/Bond/CalcBond)返回的才是展示态,其 ÷100 落库逻辑在 calcBondForItem 内处理。 item.PosiNetNoFeePrice = thisObj.roundStorageBondNetPriceAndYtm(resp.obj.netPrice); item.PosiGrossPrice = thisObj.roundStorageDeliveryPrice(item, resp.obj.price); thisObj.calcNotional(); }); }, //年化利率变更同步修改 同行观察日利率 blurSwapRate(item) { //if (item.InterestRateDefault != 0) { // item.IsAnnualized = true; //} if (item.SwapIntervalList.length > 0) { var swapRate = item.InterestRateDefault; var same = true; var rate1 = item.SwapIntervalList[0].Rate; item.SwapIntervalList.forEach(function (item) { if (item.Rate != rate1) { same = false; } }); if (same) { var confirmMsg = "检测到互换利率发生变化,将自动覆盖观察列表"; main.confirm(confirmMsg, function () { item.SwapIntervalList.forEach(function (element, index, arr) { arr[index].Rate = swapRate; }); var observationDates = JSON.stringify(item.SwapIntervalList); item.InterestSwapInterval = observationDates; }); } else { main.message("检测到互换利率与互换利率列表不一致,请手动重新生成互换列表"); } } }, changeObservationStart() { var thisObj = this; thisObj.getSwapList.forEach((item, index) => { if (item.Obervation) { thisObj.getSwapList[index].Obervation.ObservationStart = thisObj.trade.TradeDate; } }); }, //设置观察日弹框 initObservationDates(item, type) { this.observationType = type; var thisObj = this; var observation = item.Obervation; thisObj.observation.index = item.index; thisObj.observation.IntervalList = item.SwapIntervalList; thisObj.observation.DefaultTitle1Value = item.InterestRateDefault; thisObj.observation.ObservationNum = observation ? observation.ObservationNum : 1; thisObj.observation.ObservationUnit = observation ? observation.ObservationUnit : 'D'; thisObj.observation.ObservationHolidayType = observation ? observation.ObservationHolidayType : 'Following'; thisObj.observation.ObservationAlignEnd = observation ? observation.ObservationAlignEnd : true; if (type == 1) { thisObj.observation.ObservationCalendar = observation ? observation.ObservationCalendar : 'Chn'; thisObj.observation.ObservationSettlementRules = observation ? observation.ObservationSettlementRules : 0; } thisObj.observation.IsDeductPrincipal = observation ? observation.IsDeductPrincipal : true; if (type == 1) { thisObj.observation.IsDeductPrincipal = false; } var startTime = thisObj.trade.TradeDate; var endTime = thisObj.trade.ExerciseDate; if (main.isEmpty(startTime)) { main.message("请输入开始日期"); return false; } if (main.isEmpty(endTime)) { main.message("请输入到期日期"); return false; } if (thisObj.observation.ObservationStart < startTime) { thisObj.observation.ObservationStart = startTime; } if (thisObj.observation.ObservationStart > endTime) { thisObj.observation.ObservationStart = endTime; } thisObj.observation.ObservationDataList = []; var floatRateCode = type == 1 ? (item.FloatRateUnderlyingCode || '--') : ''; thisObj.observation.IntervalList.forEach((value, num, arr) => { var val = value.Rate; var _date = ""; var m = new moment(value.Date); if (!isNaN(m.date())) { _date = m.format("YYYY-MM-DD"); } var itemChecked = thisObj.observation.IntervalList.length >= num ? (value.Settlement == 1 ? true : false) : false; var disabled = false; if (_date == thisObj.trade.ExerciseDate) { disabled = true; itemChecked = false; } var obdate = {}; if (type == 1) { var settlementDate = value.Date; if (value.SettlementDate!=null) { settlementDate = value.SettlementDate; } var m = new moment(settlementDate); obdate = { date: _date, SettlementDate: m.format("YYYY-MM-DD"), floatRateCode: floatRateCode, val: _.toString(val) ? parseFloat(consNumberFormat.umpriceP(val)) : "", itemChecked: itemChecked, disabled: disabled }; } else { obdate = { date: _date, val: _.toString(val) ? parseFloat(consNumberFormat.umpriceP(val)) : "", itemChecked: itemChecked, disabled: disabled }; } thisObj.observation.ObservationDataList.push(obdate); }); var area = type == 1 ? ['800px', '600px'] : ['750px', '600px']; layer.open({ type: 1, area: area, title: "设置互换日期", shadeClose: false, shade: 0.4, content: $("#observationInfosEdit") }); }, //计算结算日期 calcSettleDate(observationDate, settlementRules) { if (!observationDate) return ""; var m = new moment(observationDate); var settleDate = m.add(settlementRules, 'days').format("YYYY-MM-DD"); return settleDate; }, //生成观察日操作 GetObservationDates() { var thisObj = this; var observationNum = thisObj.observation.ObservationNum; var observationUnit = thisObj.observation.ObservationUnit; var observationHolidayType = thisObj.observation.ObservationHolidayType; var alignEnd = thisObj.observation.ObservationAlignEnd; var settlementRules = thisObj.observation.ObservationSettlementRules; var calendar = thisObj.observation.ObservationCalendar; var floatRateCode = this.observationType == 1 ? (thisObj.getSwapList[thisObj.observation.index]?.FloatRateUnderlyingCode || '--') : ''; thisObj.observation.ObservationDataList = []; if (this.observationType == 1) { var postData = { startDate: thisObj.observation.ObservationStart, endDate: thisObj.trade.ExerciseDate, termStr: observationNum + observationUnit, holidayAdjustment: observationHolidayType, alignEnd: alignEnd, calcMode: thisObj.trade.trade_swap.RateCalcMode, calendar: calendar, settlementRules: settlementRules }; main.post("/trade/GetSwapObservationDateList", postData).done( function (res) { $.each(res.obj, function (i) { var _date = ""; var m = new moment(this.ObservationDate); if (!isNaN(m.date())) { _date = m.format("YYYY-MM-DD"); } var _settleDate = ""; var sm = new moment(this.SettleDate); if (!isNaN(sm.date())) { _settleDate = sm.format("YYYY-MM-DD"); } var val = parseFloat(consNumberFormat.umpriceP(thisObj.observation.DefaultTitle1Value)); var itemChecked = true; var disabled = false; if (_date == thisObj.trade.ExerciseDate) { disabled = true; itemChecked = false; } var obdate = { date: _date, SettlementDate: _settleDate, floatRateCode: floatRateCode, val: val, itemChecked: itemChecked, disabled: disabled }; thisObj.observation.ObservationDataList.push(obdate); }); thisObj.initObservationCheckedAll(); }); } else { var postData = { startDate: thisObj.observation.ObservationStart, endDate: thisObj.trade.ExerciseDate, termStr: observationNum + observationUnit, holidayAdjustment: observationHolidayType, alignEnd: alignEnd, calcMode: thisObj.trade.trade_swap.RateCalcMode }; main.post("/trade/GetObservationDateList", postData).done( function (res) { $.each(res.obj, function (i) { var _date = ""; var m = new moment(this); if (!isNaN(m.date())) { _date = m.format("YYYY-MM-DD"); } var val = parseFloat(consNumberFormat.umpriceP(thisObj.observation.DefaultTitle1Value)); var itemChecked = true; var disabled = false; if (_date == thisObj.trade.ExerciseDate) { disabled = true; itemChecked = false; } var obdate = { date: _date, val: val, itemChecked: itemChecked, disabled: disabled }; thisObj.observation.ObservationDataList.push(obdate); }); thisObj.initObservationCheckedAll(); }); } }, //编辑观察日功能数据处理 SetObservationDates() { var observationStr = ""; if (this.observation.ObservationDataList != null) { this.observation.ObservationDataList.forEach(item => { observationStr = observationStr + item.date + ", " + item.SettlementDate + ", " + (item.val * 0.01).toFixed(6) + ", " + item.itemChecked + ";\n"; }); } this.observation.ObservationInterval = observationStr; $("#myModal").modal("show"); }, // 粘贴功能 pasteMe(e, rowData, index) { let copyData = ''; var thisObj = this; if (e.clipboardData || e.originalEvent) { var clipboardData = (e.clipboardData || e.originalEvent.clipboardData); copyData = clipboardData.getData('Text'); var arr = copyData.replace(/\t/g, ', ').replace(/\r/g, '').split('\n'); arr.forEach((v, i) => { if (v && !v.trim().endsWith(';')) { arr[i] = v + ";"; } }); thisObj.observation.ObservationInterval = arr.join('\r\n'); e.preventDefault(); } }, //编辑观察日模态框保存操作 saveObservationModal() { this.initObservationDataList(); $("#myModal").modal("hide"); }, //编辑观察日模态框保存 数据转换 initObservationDataList() { var thisObj = this; thisObj.observation.ObservationInterval = thisObj.observation.ObservationInterval.trim().replaceAll("\n", "").replaceAll(" ", ""); var observationDates = thisObj.observation.ObservationInterval; var items = observationDates.split(";").filter(o => o); thisObj.observation.ObservationDataList = []; var floatRateCode = thisObj.getSwapList[thisObj.observation.index]?.FloatRateUnderlyingCode || '--'; items.forEach(function (item) { if (item) { var values = item.split(","); var itemChecked = JSON.parse(values[3].trim()); var disabled = false; if (values[0] == thisObj.trade.ExerciseDate) { disabled = true; itemChecked = false; } var val = values[2].trim(); var obdate = { date: values[0], SettlementDate: values[1] || "", floatRateCode: floatRateCode, val: _.toString(val) ? parseFloat(consNumberFormat.umpriceP(val)) : "", itemChecked: itemChecked, disabled: disabled } thisObj.observation.ObservationDataList.push(obdate); } }); thisObj.initObservationCheckedAll(); }, //观察日列表初始化是否全选 initObservationCheckedAll() { var thisObj = this; var noCheckedItems = thisObj.observation.ObservationDataList.filter(item => { if ((item.itemChecked == false) && item.date != thisObj.trade.ExerciseDate) { return item; } }); this.observation.CheckedAll = noCheckedItems.length == 0 && thisObj.observation.ObservationDataList.length > 0; }, //删除单行观察日 deleteObItem(item) { var thisObj = this; var curindex = 0; for (var i = 0; i < thisObj.observation.ObservationDataList.length; i++) { if (thisObj.observation.ObservationDataList[i].date == item.date) { curindex = i; break; } } thisObj.observation.ObservationDataList.splice(curindex, 1); }, //添加观察日 addnewitem() { var thisObj = this; var obdate = {}; if (this.observationType == 1) { var floatRateCode = thisObj.getSwapList[thisObj.observation.index]?.FloatRateUnderlyingCode || '--'; obdate = { date: '', SettlementDate: '', floatRateCode: floatRateCode, val: 0, itemChecked: true, disabled: false }; } else { obdate = { date: '', val: 0, itemChecked: true, disabled: false }; } thisObj.observation.ObservationDataList.push(obdate); }, //编辑观察日模态框关闭 closeObservationModal() { $('#myModal').modal('hide'); }, //关闭互换layer层 closeParentWindow() { layer.closeAll(); }, //观察日列表确认 ObservationConfirm() { var thisObj = this; var hasTimeError = false; var hasNumberError = false; var observationArr = []; thisObj.observation.ObservationDataList.forEach(item => { var m = new moment(item.date); if (isNaN(m.date())) { hasTimeError = true; } var dateFormat = /^(-?\d+)(\.\d+)?$/; if (!dateFormat.test(item.val)) { hasNumberError = true; } var observation = { Date: item.date, Rate: item.val * 0.01, Settlement: item.itemChecked ? 1 : 0, SettlementDate: item.SettlementDate || null // 结算日期 } observationArr.push(observation); }); if (hasTimeError) { alert("日期格式有误,请输入正确格式"); return false; } if (hasNumberError) { alert("请输入正确的数字格式"); return false; } if (this.observationType == 1) { thisObj.getSwapList.forEach((val, num, arr) => { if (val.index == thisObj.observation.index) { arr[num].InterestSwapInterval = JSON.stringify(observationArr); thisObj.observation.ObservationInterval = arr[num].InterestSwapInterval; arr[num].SwapIntervalList = observationArr; arr[num].Obervation = JSON.parse(JSON.stringify(thisObj.observation)); } }); } else { thisObj.marginSwapList.forEach((val, num, arr) => { if (val.index == thisObj.observation.index) { arr[num].InterestSwapInterval = JSON.stringify(observationArr); thisObj.observation.ObservationInterval = arr[num].InterestSwapInterval; arr[num].SwapIntervalList = observationArr; arr[num].Obervation = JSON.parse(JSON.stringify(thisObj.observation)); } }); } this.closeParentWindow(); }, //互换提交数据有效性检查 checkSubmitData() { //验证输入的日期格式是否正确(包括交易日期、开始日、到期日) var ExerciseDate = this.trade.ExerciseDate; var regTime = /^[0-9]{4}-[0-1]?[0-9]{1}-[0-3]?[0-9]{1}$/; if (main.isEmpty(ExerciseDate)) { main.message("请输入到期日期"); return false; } if (!regTime.test(ExerciseDate)) { main.message("请输入正确的到期日期格式"); return false; } var TradeDate = this.trade.TradeDate; if (main.isEmpty(TradeDate)) { main.message("请输入成交日期"); return false; } if (!regTime.test(TradeDate)) { main.message("请输入正确的成交日期格式"); return false; } if (TradeDate > ExerciseDate) { main.message("到期日期不能早于成交日期"); return false; } var StartDate = this.trade.StartDate; if (main.isEmpty(StartDate)) { main.message("请输入开始日期"); return false; } if (!regTime.test(StartDate)) { main.message("请输入正确的开始日期格式"); return false; } if (StartDate < TradeDate) { main.message("开始日期不能早于成交日期"); return false; } if (StartDate > ExerciseDate) { main.message("到期日期不能早于开始日期"); return false; } if (!this.trade.AssetId) { main.message("请设置簿记账户"); return false; } if (!this.trade.ClientId) { main.message("请设置交易对手方"); return false; } if (this.trade.StructureType!="多空组合"&&(!this.trade.StockEqvNotional > 0 || this.trade.StockEqvNotional == null)) { main.message("请设置名义本金"); return false; } if (!this.trade.trade_extend.ExtendObj.AnnualDays > 0) { main.message("请设置年化天数"); return false; } if (this.trade.StructureType == "多空组合"&&!this.checkSwapRateList()) { return false; } if (!this.checkObservationDates()) { return false; } return true; }, //观察日校验 checkObservationDates() { var checkGet = true; var thisObj = this; if (thisObj.getSwapList != null) { thisObj.getSwapList.forEach((val, num, arr) => { if (checkGet && val.SwapIntervalList.length > 0) { checkGet = this.checkSwapTimeRates(val.SwapIntervalList, num + 1, '利息端'); } }); } if (!checkGet) { return false; } if (thisObj.marginSwapList != null) { thisObj.marginSwapList.forEach((val, num, arr) => { if (checkGet && val.SwapIntervalList.length > 0) { checkGet = this.checkSwapTimeRates(val.SwapIntervalList, num + 1, '预付金/预付金'); } }); } if (!checkGet) { return false; } return true; }, // 多空组合利息腿校验 checkSwapRateList() { var thisObj = this; var longInterestModelCount = 0; var shortInterestModelCount = 0; var check = true; if (thisObj.getSwapList != null) { thisObj.getSwapList.forEach((val, num, arr) => { if (val.InterestMode==7) { longInterestModelCount++; } if (val.InterestMode == 8) { shortInterestModelCount++; } }); } if (longInterestModelCount > 1) { check = false; main.message("计息基本类型为多头存续名义本金的利息腿只能有一条"); } if (shortInterestModelCount > 1) { check = false; main.message("计息基本类型为空头存续名义本金的利息腿只能有一条"); } return check; }, //观察日起始日期跟交易起始日期检查 checkSwapTimeRates(SwapIntervalList, num, title) { var StartDate = this.trade.StartDate; var ExerciseDate = this.trade.ExerciseDate; var check = true; SwapIntervalList.forEach(item => { var _date = ""; var m = new moment(item.Date); if (!isNaN(m.date())) { _date = m.format("YYYY-MM-DD"); } if (_date < StartDate) { main.message(title + "第" + num + "行互换观察日不可以早于交易开始日"); check = false; } else if (_date > ExerciseDate) { main.message(title + "第" + num + "行互换观察日不可以晚于交易到期日"); check = false; } }); return check; }, changeClient: function (client) { this.trade.ClientId = client.id; this.client = client; //if (this.client.SwapTradeType == 0) {//非DMA客户 // this.trade.trade_extend.ExtendObj.FlowBookMode = 3;//流水簿记模式为重置 //} else { // this.trade.trade_extend.ExtendObj.FlowBookMode = 2;//流水簿记模式为加权平均 暂定 //} //this.initMarginRate(); }, initMarginRate() { //初始预付金 初始话 _that = this; var swapType = this.trade.StructureType; var UnderlyingCode = ""; if (swapType != "多空组合") { swapType = "普通"; UnderlyingCode = this.paySwapList[0].UnderlyingCode; } if (page.isAdd && this.trade.ClientId != null && ((swapType == "普通" && UnderlyingCode != "") || this.trade.trade_swap.SwapType == "多空组合")) { main.post("/swapTrade/GetInitMarginRate", { ClientId: this.trade.ClientId, Type: swapType, UnderlyingCode: UnderlyingCode, tradeDate: this.trade.TradeDate }) .done(function (resp) { if (resp.obj > 0) { _that.trade.trade_Initial_Margin.MarginValue = resp.obj } }); } }, //交易审批 submit(status) { var pop = ''; if (status === 'pass') { pop = "确认通过审批?"; } if (status === 'reject') { pop = "确认拒绝?"; } var confirmFunc = function (additionalProcessing) { var pData = { tradeId: page.Trade.id, status: status, text: "" }; if (!main.isEmpty(additionalProcessing)) { pData.additionalProcessing = additionalProcessing; } main.post("/processtradelog/UpdateTradeProcessLog", pData).done( function (data) { if (data.obj && data.obj.proccessType == "AdditionalProcessing") { if (data.obj.type == "LackOfMoney") { var htmlContent = `