//定价格式化(来自配置) const inputFormatPercent = Object.freeze({ precision: 2, append: '%' }); const inputFormatPercentNegative = Object.freeze({ precision: 2, append: '%', negative: true }); const inputFormatNegative = Object.freeze({ precision: 2, negative: true }); const MarginRuleTypeEnum = { 无预付金: "0", 按固定利率: "1", 按浮动盈亏: "2", 类香草预付金规则: "3", 自动赎回买入预付金规则: "4", 触发条件预付金规则1: "5", 触发条件预付金规则2: "6", 保底预付金规则: "7", 含赔付预付金计算规则: "8", 触发条件预付金规则3: "9", 交易所基本规则: "10", 标准SPAN: "11", 买入自动赎回规则1: "12", 卖出自动赎回规则1: "13", 默认预付金规则: "99" }; const UnderlyingSeperateTypeEnum = { None: "0",//不区分 CustomStock: "1"//按自定义权益分类 }; const vue = new Vue({ el: '#marginTemplateV2Form', data: { isAdd: page.isAdd, marginTemplate: page.marginTemplate, latestValueDate: page.marginTemplate.LatestValueDate }, created: function () { this.changeRuleType(true); }, methods: { changeRuleType(isInitial) { switch (this.marginTemplate.RuleType.toString()) { case MarginRuleTypeEnum.无预付金: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为零。"; break; case MarginRuleTypeEnum.按固定利率: this.marginTemplate.Comments = "预付金占用为成交/实时名义本金的固定比例。"; break; case MarginRuleTypeEnum.按浮动盈亏: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为成交/实时名义本金的固定比例,加上对手方交易浮动亏损,扣除对手方交易浮动盈利。"; break; case MarginRuleTypeEnum.类香草预付金规则: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为为成交/实时名义本金的浮动比例,加上对手方交易浮动亏损。浮动比例依据标的涨跌停情况判断。"; break; case MarginRuleTypeEnum.自动赎回买入预付金规则: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为n+2(≤N)个票息之和,N为合约期内敲出观察日总数,n为当前经过的敲出观察日个数(当n+2>N时,n = N - 2)。"; break; case MarginRuleTypeEnum.触发条件预付金规则1: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为成交名义本金的固定比例,加标的跌幅的市值(跌幅达到一定条件触发)"; break; case MarginRuleTypeEnum.触发条件预付金规则2: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为成交/实时名义本金的固定比例,加标的跌幅的市值(跌幅达到一定条件触发)"; break; case MarginRuleTypeEnum.触发条件预付金规则3: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为成交/实时名义本金的固定比例,加上对手方分段式交易浮动亏损(涨跌幅达到一定条件触发)"; break; case MarginRuleTypeEnum.保底预付金规则: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为对手方最大亏损金额。"; break; case MarginRuleTypeEnum.含赔付预付金计算规则: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "预付金占用为对手方最大赔付金额。"; break; case MarginRuleTypeEnum.交易所基本规则: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "交易所基本规则"; break; case MarginRuleTypeEnum.标准SPAN: this.marginTemplate.Comments = "计算标的价格和波动率上涨下跌4个场景下的对手方最大亏损"; break; case MarginRuleTypeEnum.买入自动赎回规则1: this.marginTemplate.UnderlyingSeperateType = UnderlyingSeperateTypeEnum.None; this.marginTemplate.Comments = "Min(x*首次票息金额+y*Max(0,Pv),合约期间全部票息金额);\n若勾选了“取与保底金额孰小”,则还要与取较小的一个;\n保底金额 =ABS(执行价格 - 保底价格)* ABS(交易数量)。"; break; case MarginRuleTypeEnum.卖出自动赎回规则1: this.marginTemplate.Comments = "名义本金*Max(x,y-0.5*虚值比例)+ Flag*Max(0,PV);\n其中虚值比例 = max(0, P - 执行价)/期初价格,当计算日为成交日时,Flag = 0,P = 期初价格,当计算日不为成交日时,Flag = 1,P = 标的现价;\n若勾选了“取与保底金额孰小”,则取较小的一个;\n保底金额 =ABS(执行价格 - 保底价格)* ABS(交易数量)。"; break; case MarginRuleTypeEnum.默认预付金规则: this.marginTemplate.Comments = "考虑了14种场景下的Span算法与Delta算法比较的通用预付金规则,该规则可以调整Span涨跌幅度"; break; default: this.marginTemplate.Comments = ""; break; } this.changeUnderlyingSeperateType(isInitial); }, changeUnderlyingSeperateType(isInitial) { if (isInitial && this.marginTemplate.Details.length >= 1) { return; } if (this.marginTemplate.UnderlyingSeperateType == UnderlyingSeperateTypeEnum.None) { this.marginTemplate.UnderlyingSeperateComments = "无论挂钩标的代码为何,都采用同一套参数"; } else { this.marginTemplate.UnderlyingSeperateComments = "把所有标的根据代码所属区间段自动分为4类:\n【1-指数】沪深指数;\n【2-个股/ETF-核准制发行】主板股票、非科创版ETF;\n【3-个股/ETF-非核准制发行】科创版股票、科创版ETF、创业板股票;\n【4-其他】所有不满足以上分类的。"; } let that = this new Promise((reslove) => { that.marginTemplate.Details = []; reslove(); }).then(() => { var needDetailRules = []; needDetailRules.push(MarginRuleTypeEnum.按固定利率); needDetailRules.push(MarginRuleTypeEnum.按浮动盈亏); needDetailRules.push(MarginRuleTypeEnum.类香草预付金规则); needDetailRules.push(MarginRuleTypeEnum.触发条件预付金规则1); needDetailRules.push(MarginRuleTypeEnum.触发条件预付金规则2); needDetailRules.push(MarginRuleTypeEnum.触发条件预付金规则3); needDetailRules.push(MarginRuleTypeEnum.标准SPAN); needDetailRules.push(MarginRuleTypeEnum.买入自动赎回规则1); needDetailRules.push(MarginRuleTypeEnum.卖出自动赎回规则1); needDetailRules.push(MarginRuleTypeEnum.默认预付金规则); if (needDetailRules.indexOf(that.marginTemplate.RuleType.toString()) >= 0) { new Promise((reslove) => { that.marginTemplate.Details.push(_.cloneDeep(page.detail)); reslove(); }).then(() => { SetAceDropDown(); }) } }) }, saveMarginTemplateV2(isForClient) { if (!this.marginTemplate.Name) { main.message("模板名称不能为空"); return; } this.marginTemplate.TradeTypes = $("#tradeTypes").val().join(","); this.marginTemplate.IsDefault = true; this.marginTemplate.IsForClient = isForClient; this.marginTemplate.BuySellType = this.sum($("#BuySellType").val()); this.marginTemplate.MarginScenarios = this.sum($("#MarginScenarios").val()); var that = this; this.marginTemplate.Details.forEach((detail, index) => { if (that.marginTemplate.UnderlyingSeperateType == 0) { detail.UnderlyingType = 15; } else { detail.UnderlyingType = that.sum($("#UnderlyingType" + index).val()); } detail.SpanConfigJson = JSON.stringify(detail.SpanConfig); }); main.post("/margin_template_v2/saveMarginTemplateV2", { marginTemplate: this.marginTemplate }).done(function (resp) { try { window.parent.reloadmargin_template(); (parent || window).layer.closeAll(); } catch (e) { } }); }, setTemplateDetail(detail) { vueDetail.backupDetail = _.cloneDeep(detail); detail.ValueDate = new moment(detail.ValueDate).format("YYYY-MM-DD"); detail.UsePositionStockEqvNotional = false; vueDetail.detail = detail; vueDetail.isAdd = false; vueDetail.ruleType = vue.marginTemplate.RuleType; $("#myModal").modal("show"); }, addDetail() { let that = this new Promise((reslove) => { that.marginTemplate.Details.push(_.cloneDeep(page.detail)); reslove(); }).then(() => { SetAceDropDown(); }) }, deleteDetail(index) { this.marginTemplate.Details.splice(index, 1); }, sum(items) { var total = 0; if (items) { for (var index = 0; index < items.length; index++) { total = total + parseFloat(items[index]); } } return total; } }, mounted: function () { /*console.log(this.marginTemplate.Details);*/ }, components: { 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput() } }); $(function () { $(".datepicker").change(function () { var dateVal = $(this).val(); if (!dateVal) return; dateVal = dateVal.replace(/\D/g, '').padStart(4, '0'); switch (dateVal.length) { case 4: dateVal = new Date().getFullYear() + dateVal; break; case 6: dateVal = '20' + dateVal; break; case 8: break; default: dateVal = dateVal.length > 8 ? dateVal.substring(0, 8) : ''; break; } if (dateVal) { dateVal = moment(dateVal).format('YYYY-MM-DD'); !/^\d+/.test(dateVal) && (dateVal = ''); } $(this).datepicker("setDate", dateVal); }); SetAceDropDown(); }); var vueDetail = new Vue({ el: "#myModal", data: { detail: {}, backupDetail: {}, isAdd: true, ruleType: 0, }, created: function () { }, methods: { closeModal: function () { if (!this.isAdd) { Vue.set(vue.marginTemplate.Details, vue.marginTemplate.Details.indexOf(this.detail), this.backupDetail); } $('#myModal').modal('hide'); }, saveModal: function () { if (this.isAdd) { if (vue.latestValueDate && vue.latestValueDate >= this.detail.ValueDate) { main.message("生效日期需要大于已设置生效日"); return; } vue.marginTemplate.Details.push(this.detail); vue.latestValueDate = this.detail.ValueDate; } Vue.set(vue.marginTemplate.Details, vue.marginTemplate.Details.indexOf(this.detail), this.detail); $('#myModal').modal('hide'); } }, components: { 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput() } });