//禁止千分位分组格式化 window.otcformat.options.disableGrouping = true; const consVarieties = ylotc.varieties; const pricingFormat = otcformat.trading; //波动率输入格式 const inputFormatVolPercent = Object.freeze({ precision: pageData.VolMoreAccurate ? 4 : 2, append: '%' }); //权利金输入格式 const inputFormatPremiumRate = Object.freeze({ precision: pricingFormat.premiumRateP.precision, append: '%' }); const inputFormatSinglePrice = Object.freeze({ precision: pricingFormat.tradeSinglePrice.precision, append: '' }); const consUnderlyingFlag = (function () { let unSelFlag = tradeHelper.UnderlyingSelectFlag; return unSelFlag.UseForTrading | unSelFlag.IncludeMatured | unSelFlag.UsePinYinFilter | unSelFlag.CheckLaunch; }()); var autoVariety, autoUnderlying; function __init(vue) { //标的品种 autoVariety = FastVue.autocomplete(document.getElementById('VarietyId'), { lookup: consVarieties, nameField: 'Name', valueField: 'id', searchField: ['Name', 'Code', 'PinYin'], onSelect: function (data) { vue.changeVariety(data, 'select'); } }); //标的资产 autoUnderlying = tradeHelper.UnderlyingAutoComplete('UnderlyingCode', { BlackLimit: 1 }).setFlag(consUnderlyingFlag); autoUnderlying.onSelect(vue.changeunderlying); //标的控件初始化 if (vue.Model.UnderlyingCode) { autoUnderlying.selectByCode(vue.Model.UnderlyingCode); } else { autoUnderlying.selectFirst(); } } var vue = new Vue({ el: "#listdiv", data: { Model: Model, IsMoneynessOption: false, trade: { IsUsePremiumRate: false, TradeOpenVolatility: '', TradeCloseVolatility: '', NumOfSmoothingDays: '', TradeSinglePrice: '', PremiumRate: '' } }, mounted: function () { let self = this; //设置默认值补丁 this.Model.ExerciseMode = "European"; this.Model.TradeDate = moment(this.Model.TradeDate).format("YYYY-MM-DD"); this.Model.UnderlyingInstrumentType = "CommodityFutures"; if (this.Model.Name == "Bear Spread") { self.Model.OptionType = "看跌"; } main.setTradeDatePicker("", "#ModelTradeDate", this.Model.TradeDate, function (date) { self.Model.TradeDate = date; self.refreshUnderlyingPrice(); }); main.setTradeDatePicker("", "#ModelExerciseDate", this.Model.ExerciseDate, function (date) { self.Model.ExerciseDate = date; }); main.setTradeDatePicker("", "#ModelExerciseDate2", this.Model.ExerciseDate, function (date) { self.Model.ExerciseDate2 = date; }); __init(this) }, computed: { inputFormatStrike: function () { let fmt = {}; if (this.IsMoneynessOption) { fmt.append = '%'; fmt.negative = false; fmt.precision = pricingFormat.umpriceP.precision; } else { fmt.append = ''; fmt.negative = true; fmt.precision = pricingFormat.umprice.precision; } return fmt; }, showTradeMore() { return pageData.IsTradeVol && this.Model.Name === "Straddle"; } }, filters: { ShowUnit: function (m) { return m && m.Variety ? m.Variety.QuoteUnitSingle : ""; } }, methods: { changeInstrumentType: function () { autoUnderlying.selectFirst({ InstrumentTypes: this.Model.UnderlyingInstrumentType }); }, changeUnderlyingPrice: function () { this.Model.UnderlyingPriceType = "User"; if (this.IsMoneynessOption === false) { this.Model.StockEqvNotional = pricingFormat.StockEqvNotional(this.Model.Notional * this.Model.Price); this.Model.Price = pricingFormat.umprice(this.Model.Price); } else { this.Model.Notional = pricingFormat.notional(this.Model.StockEqvNotional / this.Model.Price); var CountRatio = this.Model.Variety.CountRatio || 1; this.Model.TradeAmount = pricingFormat.notional(this.Model.Notional / CountRatio); } this.$forceUpdate(); }, refreshUnderlyingPrice: function () { var self = this; main.post("/underlying_manager/underlyingGetById", { id: self.Model.UnderlyingId, voltype: this.Model.voltype, tradeDate: this.Model.TradeDate }).done(function (res) { self.Model.Price = pricingFormat.umprice(res.underlying_manager.Price); if (self.IsMoneynessOption === false) { self.Model.Strike = self.Model.Strike2 = self.Model.Strike3 = self.Model.Strike4 = self.Model.Price; self.Model.StockEqvNotional = pricingFormat.StockEqvNotional(self.Model.Notional * self.Model.Price); } else { self.Model.Strike = self.Model.Strike2 = self.Model.Strike3 = self.Model.Strike4 = 1; self.Model.Notional = pricingFormat.notional(self.Model.StockEqvNotional / self.Model.Price); var CountRatio = self.Model.Variety.CountRatio || 1; self.Model.TradeAmount = pricingFormat.notional(self.Model.Notional / CountRatio); } self.$forceUpdate(); }); }, changeunderlying: function (data) { var self = this; self.Model.VarietyId = data.VarietyId; self.Model.UnderlyingId = data.id; self.Model.UnderlyingCode = data.Code; if (!data.Code) return; self.Model.UnderlyingInstrumentType = data.InstrumentType; main.post("/Pricing/AjaxGetExerciseDate", { underlyingMaturityDate: data.MaturityDate, tradeDate: self.Model.TradeDate }).done(function (res) { let exerciseDate = new moment(res.obj.ExerciseDate).format("YYYY-MM-DD"); Vue.set(self.Model, 'ExerciseDate', exerciseDate); }); $.each(self.Model.trades, function (i, d) { d.MaturityDate = data.MaturityDate; d.UnderlyingPrice = data.Price; }); autoUnderlying.setVarietyId(data.VarietyId); self.changeVariety(data.VarietyId ? ylotc.varieties.find(x => x.id === data.VarietyId) : null); this.refreshUnderlyingPrice(); let isMoneynessOption = self.Model.UnderlyingInstrumentType === "Stock" || self.Model.UnderlyingInstrumentType === "StockIndex"; if (isMoneynessOption) { self.Model.StockEqvNotional = 1e6; self.changeStockEqvNotional(); } else { self.changeAmount(); } this.moneynessSwitch(isMoneynessOption); this.showTradeMore && this.premiumRateSwitch(isMoneynessOption); }, setStrike: function (strikeType) { if (this.Model.Name === "Condor") { if (this.Model.Strike2 && this.Model.Strike3) { if (this.Model.Strike2 >= this.Model.Strike3) { if (strikeType === "Strike2") { main.message("执行价格2需要小于执行价格3"); this.Model.Strike2 = ""; } else if (strikeType === "Strike3") { main.message("执行价格3需要大于执行价格2"); this.Model.Strike3 = ""; } return; } var diff = this.Model.Strike3 - this.Model.Strike2; this.Model.Strike = this.Model.Strike2 - diff; this.Model.Strike4 = parseFloat(this.Model.Strike3) + diff; } } }, submitstructure: function () { var self = this; if (self.checkTrades()) { self.setModelTrades(); window.parent.vue.setOption(self.Model.trades); layer.closeMe(); } }, checkTrades: function () { var self = this; var pass = true; var checkModel = { Strike12: true, Strike12Empty: true, CheckExerciseDate: true }; switch (self.Model.Name) { case "Butterfly": checkModel.Strike12 = false; checkModel.Strike12Empty = false; self.Model.MidStrike = self.Model.Price; if (!self.Model.StrikeGap || !self.Model.MidStrike) { main.message("执行价格间距必填!"); pass = false; } if (parseFloat(self.Model.MidStrike) <= parseFloat(self.Model.StrikeGap)) { main.message("标的价格必须大于行权价间隔!"); pass = false; //中间行权价 即 标的价格 } break; case "Condor": checkModel.Strike12 = false; checkModel.Strike12Empty = false; //验证行权价是否相同,从小到大排序,中间两个行权价允许相同,其他行权价不能相同 if (!self.Model.Strike3 || !self.Model.Strike4) { main.message("行权价3,4必需输入!"); pass = false; } var strikes = [self.Model.Strike, self.Model.Strike2, self.Model.Strike3, self.Model.Strike4]; strikes.sort(); if (strikes[0] == strikes[1] || strikes[3] == strikes[2]) { main.message("中间两个行权价允许相同,其他行权价不能相同!"); pass = false; } break; //case "Preplicating Underlying": case "Straddle": //跨式组合的 执行价格 永远和标的价格一致 if (self.IsMoneynessOption) { self.Model.Strike = 1; } else { self.Model.Strike = self.Model.Price; } checkModel.Strike12 = false; checkModel.Strike12Empty = false; if (!self.Model.Strike) { main.message("行权价必需输入!"); pass = false; } break; case "Ratio Spread": break; case "Calender Spread"://ExerciseDate2 checkModel.Strike12 = false; checkModel.Strike12Empty = false; if (!self.Model.ExerciseDate || !self.Model.ExerciseDate2) { main.message("两个到期日必需输入!"); pass = false; } if ((new Date(self.Model.ExerciseDate)).getTime() <= (new Date(self.Model.ExerciseDate2)).getTime()) { main.message("到期日期2须早于到期日期1!"); pass = false; } if (!self.Model.Strike) { main.message("请输入行权价!"); pass = false; } break; case "Collar": checkModel.Strike12 = false; checkModel.Strike12Empty = false; if (!self.Model.Strike || !self.Model.Strike2 || !self.Model.Strike3) { main.message("执行价格1,2,3必需输入!"); pass = false; } if ((self.Model.Strike == self.Model.Strike2) || self.Model.Strike == self.Model.Strike3 || self.Model.Strike3 == self.Model.Strike2) { main.message("执行价格1,2,3两两不能相等!"); pass = false; } break; } if (!self.Model.TradeAmount) { main.message("请输入交易数量!"); pass = false; } if (self.Model.TradeAmount < 0) { main.message("交易数量不能小于0!"); pass = false; } if (checkModel.CheckExerciseDate) { if (!main.isDate(self.Model.ExerciseDate)) { main.message("请输入正确的到期日!"); pass = false; } } if (checkModel.Strike12Empty && (!self.Model.Strike || !self.Model.Strike2)) { // Butterfly Condor 不必 main.message("执行价格1,2必需输入!"); pass = false; } return pass; }, setModelTrades: function () { var self = this; $.each(self.Model.trades, function (i, d) { d.VarietyId = self.Model.VarietyId; d.UnderlyingId = self.Model.UnderlyingId; d.UnderlyingCode = self.Model.UnderlyingCode; d.UnderlyingInstrumentType = self.Model.UnderlyingInstrumentType; d.Notional = self.Model.Notional; d.TradeAmount = pricingFormat.notional(self.Model.TradeAmount); d.StockEqvNotional = self.Model.StockEqvNotional; d.ExerciseMode = self.Model.ExerciseMode; d.SettlementType = self.Model.SettlementType; if (self.Model.OptionType) d.OptionType = self.Model.OptionType; d.ExerciseDate = self.Model.ExerciseDate; d.TradeDate = self.Model.TradeDate; d.UnderlyingPrice = d.SpotPrice = self.Model.Price; d.NoRiskRateType = "System"; d.CountRatio = self.Model.Variety.CountRatio || 1; }); for (let [k, v] of Object.entries(self.trade)) { self.Model.trades.forEach(x => x[k] = ""); } switch (self.Model.Name) { case "Bull Spread": { if (self.Model.Strike < self.Model.Strike2) { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; } else { self.Model.trades[0].BuySell = "卖出"; self.Model.trades[1].BuySell = "买入"; } self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike2; } break; case "Bear Spread": { if (self.Model.Strike < self.Model.Strike2) { self.Model.trades[0].BuySell = "卖出"; self.Model.trades[1].BuySell = "买入"; } else { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; } self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike2; self.Model.Strike = self.Model.Price; } break; case "Straddle": { self.Model.trades.forEach(x => { x.BuySell = "买入"; self.Model.Strike = x.Strike = self.IsMoneynessOption ? 1 : self.Model.Price; _.extend(x, self.trade); }); } break; case "Preplicating Underlying": { //交易方向“买入” 0看涨,1看跌 //两条leg 分别是: 买入执行价格高的看涨和卖出执行价格低看跌 //交易方向为“卖出”:两条leg分别是:买入执行价格低的看跌和卖出执行价格高的看涨 self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike2; if (self.Model.BuySell === "买入") { if (self.Model.trades[0].Strike > self.Model.trades[1].Strike) { self.Model.trades[0].BuySell = "买入"; self.Model.trades[0].OptionType = "看涨"; self.Model.trades[1].BuySell = "卖出"; self.Model.trades[1].OptionType = "看跌"; } else { self.Model.trades[1].BuySell = "买入";//买入执行价格高的看涨 self.Model.trades[1].OptionType = "看涨"; self.Model.trades[0].BuySell = "卖出"; //看跌?? self.Model.trades[0].OptionType = "看跌"; } } else { if (self.Model.trades[0].Strike > self.Model.trades[1].Strike) { self.Model.trades[0].BuySell = "买入"; //相对客户说?? self.Model.trades[0].OptionType = "看涨"; self.Model.trades[1].BuySell = "卖出"; self.Model.trades[1].OptionType = "看跌"; } else { self.Model.trades[1].BuySell = "买入"; self.Model.trades[1].OptionType = "看涨"; self.Model.trades[0].BuySell = "卖出"; self.Model.trades[0].OptionType = "看跌"; } } self.Model.Strike = self.Model.Price; } break; case "Strangle": { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "买入"; //self.Model.Strike = self.Model.Price; self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike2; if (self.Model.Strike >= self.Model.Strike2) { self.Model.trades[0].OptionType = "看涨"; self.Model.trades[1].OptionType = "看跌"; } else { self.Model.trades[0].OptionType = "看跌"; self.Model.trades[1].OptionType = "看涨"; } } break; case "Butterfly": { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; self.Model.trades[2].BuySell = "买入"; self.Model.trades[0].Notional = self.Model.Notional; var CountRatio = self.Model.Variety.CountRatio || 1; self.Model.trades[0].TradeAmount = pricingFormat.notional(self.Model.trades[0].Notional / CountRatio); self.Model.trades[1].Notional = self.Model.Notional * 2; self.Model.trades[1].StockEqvNotional = self.Model.StockEqvNotional * 2; self.Model.trades[1].TradeAmount = pricingFormat.notional(self.Model.trades[1].Notional / CountRatio); self.Model.trades[2].Notional = self.Model.Notional; self.Model.trades[2].TradeAmount = pricingFormat.notional(self.Model.trades[2].Notional / CountRatio); //中间行权价-行权价间隔,中间行权价,中间行权价+行权价间隔 if (self.IsMoneynessOption) { let gap = self.Model.StrikeGap / self.Model.MidStrike || 0; self.Model.trades[0].Strike = 1 - gap; self.Model.trades[1].Strike = 1; self.Model.trades[2].Strike = 1 + gap; } else { self.Model.trades[0].Strike = self.Model.MidStrike - self.Model.StrikeGap; self.Model.trades[1].Strike = self.Model.MidStrike; self.Model.trades[2].Strike = parseFloat(self.Model.MidStrike) + parseFloat(self.Model.StrikeGap); } } break; case "Condor": { self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike2; self.Model.trades[2].Strike = self.Model.Strike3; self.Model.trades[3].Strike = self.Model.Strike4; self.Model.trades[0].OptionType = self.Model.OptionType; self.Model.trades[1].OptionType = self.Model.OptionType; self.Model.trades[2].OptionType = self.Model.OptionType; self.Model.trades[3].OptionType = self.Model.OptionType; self.Model.trades.sort(self.strikeSort); self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; self.Model.trades[2].BuySell = "卖出"; self.Model.trades[3].BuySell = "买入"; } break; case "Ratio Spread": { if (self.Model.OptionType === "看涨") { if (self.Model.Strike < self.Model.Strike2) { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; } else { self.Model.trades[0].BuySell = "卖出"; self.Model.trades[1].BuySell = "买入"; } } else if (self.Model.OptionType === "看跌") { if (self.Model.Strike < self.Model.Strike2) { self.Model.trades[0].BuySell = "卖出"; self.Model.trades[1].BuySell = "买入"; } else { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; } } self.Model.trades[0].Notional = self.Model.Notional; let CountRatio = self.Model.Variety.CountRatio || 1; self.Model.trades[0].TradeAmount = pricingFormat.notional(self.Model.trades[0].Notional / CountRatio); self.Model.trades[1].Notional = self.Model.Notional2; self.Model.trades[1].TradeAmount = pricingFormat.notional(self.Model.trades[1].Notional / CountRatio); self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike2; } break; case "Calender Spread": if (self.Model.ExerciseDate < self.Model.ExerciseDate2) { self.Model.trades[0].BuySell = "卖出"; self.Model.trades[1].BuySell = "买入"; } else { self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; } self.Model.trades[0].ExerciseDate = self.Model.ExerciseDate; self.Model.trades[1].ExerciseDate = self.Model.ExerciseDate2; self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike; break; case "Box Spread": self.Model.trades[0].BuySell = "买入"; self.Model.trades[1].BuySell = "卖出"; self.Model.trades[2].BuySell = "买入"; self.Model.trades[3].BuySell = "卖出"; self.Model.trades[0].OptionType = "看涨"; self.Model.trades[1].OptionType = "看跌"; self.Model.trades[2].OptionType = "看跌"; self.Model.trades[3].OptionType = "看涨"; if (self.Model.Strike < self.Model.Strike2) { self.Model.trades[0].Strike = self.Model.Strike; self.Model.trades[1].Strike = self.Model.Strike; self.Model.trades[2].Strike = self.Model.Strike2; self.Model.trades[3].Strike = self.Model.Strike2; } else { self.Model.trades[0].Strike = self.Model.Strike2; self.Model.trades[1].Strike = self.Model.Strike2; self.Model.trades[2].Strike = self.Model.Strike; self.Model.trades[3].Strike = self.Model.Strike; } break; case "Risk Reversal": self.Model.trades[0].OptionType = "看涨"; self.Model.trades[1].OptionType = "看跌"; self.Model.trades[0].Strike = Math.max(self.Model.Strike, self.Model.Strike2); self.Model.trades[1].Strike = Math.min(self.Model.Strike, self.Model.Strike2); break; case "Collar": self.Model.trades[0].OptionType = "看跌"; self.Model.trades[1].OptionType = "看跌"; self.Model.trades[2].OptionType = "看涨"; if (self.Model.SeagullType === "Bullish") { self.Model.trades[1].OptionType = "看涨"; } var strikes = [parseFloat(self.Model.Strike), parseFloat(self.Model.Strike2), parseFloat(self.Model.Strike3)]; strikes.sort((x1, x2) => x1 - x2) self.Model.trades[0].Strike = strikes[0]; self.Model.trades[1].Strike = strikes[1]; self.Model.trades[2].Strike = strikes[2]; break; } //设置初始化信息 $.each(self.Model.trades, function (i, d) { if (self.IsMoneynessOption) { d.IsMoneynessOption = "是"; !self.showTradeMore && (d.IsUsePremiumRate = true); } else { d.Strike = pricingFormat.umprice(d.Strike); } }); if (self.Model.BuySell === "卖出") { //相反 $.each(self.Model.trades, function (i, d) { d.BuySell = d.BuySell === "卖出" ? "买入" : "卖出"; }); } }, strikeSort: function (tr1, tr2) { return tr1.Strike - tr2.Strike; }, changeAmount: function () { //交易数量= 份额 / 比率 var self = this; self.Model.TradeAmount = pricingFormat.notional(self.Model.TradeAmount); self.Model.Notional = self.Model.TradeAmount * (self.Model.Variety.CountRatio || 1); self.Model.StockEqvNotional = pricingFormat.StockEqvNotional(self.Model.Notional * self.Model.Price); }, changeVariety: function (variety, flag) { if (flag === 'select') { if (this.Model.VarietyId === variety.id) return; autoUnderlying.setVarietyId(variety.id); autoUnderlying.selectFirst(variety.id); } else { autoVariety.setData(variety); } this.Model.Variety = variety; }, changeStockEqvNotional: function () { var self = this; self.Model.Notional = pricingFormat.notional(self.Model.StockEqvNotional / self.Model.Price); if (self.Model.Notional) { self.Model.TradeAmount = pricingFormat.notional(self.Model.Notional / (self.Model.Variety.CountRatio || 1)); } else { self.Model.TradeAmount = ""; } }, //绝对值执行价格 showAbsStrike() { this.moneynessSwitch(false); }, //百分比执行价格 showPercentStrike() { this.moneynessSwitch(true); }, //执行价格切换 moneynessSwitch(newVal) { if (this.IsMoneynessOption === newVal) return; //console.log("moneynessSwitch"); this.IsMoneynessOption = newVal; let spotPrice = parseFloat(this.Model.Price) || 0; let isSpotZero = Math.abs(spotPrice) < 1e-4; let strikes = ["Strike", "Strike2", "Strike3", "Strike4"]; for (var key of strikes) { if (this.IsMoneynessOption) { this.Model[key] = (isSpotZero ? 1 : this.Model[key] / spotPrice).toFixed(pricingFormat.umpriceP.precision + 2); } else { this.Model[key] = pricingFormat.umprice(this.Model[key] * spotPrice); } } }, //绝对值权利金 showAbsPrice() { this.premiumRateSwitch(false); }, //百分比权利金 showPercentPrice() { this.premiumRateSwitch(true); }, //权利金切换 premiumRateSwitch(newVal) { if (this.trade.IsUsePremiumRate === newVal) return; //console.log("premiumRateSwitch"); this.trade.IsUsePremiumRate = newVal; let spotPrice = parseFloat(this.Model.Price) || 0; let isSpotZero = Math.abs(spotPrice) < 1e-4; if (newVal) { let spotPrice = parseFloat(this.Model.Price) || 0; let isSpotZero = Math.abs(spotPrice) < 1e-4; this.trade.PremiumRate = Math.abs(spotPrice) < 1e-4 ? 1 : this.trade.TradeSinglePrice / spotPrice; } else { this.trade.TradeSinglePrice = (parseFloat(this.Model.Price) || 0) * this.trade.PremiumRate; } } }, components: { 'vue-number-input': FastVue.vueNumberInput() } });