538 lines
19 KiB
JavaScript
538 lines
19 KiB
JavaScript
const datePickerOpt = {
|
|
changeMonth: true,
|
|
changeYear: true,
|
|
showButtonPanel: true,
|
|
showOtherMonths: true,
|
|
selectOtherMonths: true,
|
|
maxDate: pageObj.valueDate
|
|
};
|
|
|
|
//全局SkewMap
|
|
const globalHandler = (new function () {
|
|
|
|
this.init = function () {
|
|
$('#uploadSkewMapCtrl').on('change', function () {
|
|
$(this).next().text($(this).val());
|
|
}).next().on('click', function () {
|
|
$(this).prev().click();
|
|
});
|
|
};
|
|
|
|
this.upload = function () {
|
|
var formData = new FormData();
|
|
formData.append("skewMapType", $("#skewMapType").val());
|
|
//上传的文件file
|
|
let files = document.getElementById('uploadSkewMapCtrl').files;
|
|
if (!files.length) {
|
|
return main.alert('请选择上传文件');
|
|
}
|
|
formData.append("file", files[0]);
|
|
main.waitMe("show");
|
|
$.ajax({
|
|
url: '/skewMap/UploadSkewMap',
|
|
type: 'POST',
|
|
processData: false,
|
|
contentType: false,
|
|
data: formData,
|
|
cache: false,
|
|
success(resp) {
|
|
if (resp.success) {
|
|
parent.main.message("导入成功!");
|
|
$('#uploadSkewMapCtrl').val('').next().text('请选择...');
|
|
} else {
|
|
main.message("导入失败:" + resp.msg);
|
|
}
|
|
},
|
|
error() {
|
|
main.message("导入失败");
|
|
},
|
|
complete() {
|
|
main.waitMe("hide");
|
|
}
|
|
});
|
|
};
|
|
|
|
this.download = function () {
|
|
$('#hide_skewMapType').val($("#skewMapType").val());
|
|
$('#formGlobal').submit();
|
|
};
|
|
});
|
|
|
|
//光证波动率
|
|
const gzVolHandler = (new function () {
|
|
|
|
var volInputCtrl;
|
|
|
|
function getVol() {
|
|
$("#varietyVol_gz").val("");
|
|
let data = {
|
|
varietyId: $('#varietyId_gz').val(),
|
|
valueDate: $('#maintainDate_gz').val(),
|
|
};
|
|
if (!data.valueDate || !data.varietyId) return;
|
|
main.post("/skewMap/GetVarietyVol", data).done(function (res) {
|
|
if (res.obj) {
|
|
volInputCtrl.setValue(res.obj.Vol);
|
|
} else {
|
|
main.message("光证波动率不存在");
|
|
}
|
|
});
|
|
}
|
|
|
|
this.init = function () {
|
|
|
|
$("#maintainDate_gz").datepicker(datePickerOpt).val(pageObj.valueDate).change();
|
|
|
|
let autoVariety = FastVue.autocomplete(document.getElementById('varietyId_gz'), {
|
|
lookup: pageObj.varieties, nameField: 'Name', valueField: 'id', searchField: ['Name', 'Code', 'PinYin'],
|
|
onSelect: getVol
|
|
});
|
|
|
|
volInputCtrl = FastVue.numberInput('varietyVol_gz', { append: '%' });
|
|
|
|
$('#maintainDate_gz').on('change', function () {
|
|
let enable = pageObj.valueDate === $("#maintainDate_gz").val();
|
|
$('#btnSaveGzVol').prop('disabled', !enable);
|
|
getVol();
|
|
});
|
|
}
|
|
|
|
this.saveVol = function () {
|
|
let data = {
|
|
varietyId: $('#varietyId_gz').val(),
|
|
valueDate: $('#maintainDate_gz').val(),
|
|
vol: volInputCtrl.getValue()
|
|
};
|
|
if (!data.varietyId) {
|
|
return main.alert('标的品种 必须填写');
|
|
}
|
|
if (!data.valueDate) {
|
|
return main.alert('维护日期 必须填写');
|
|
}
|
|
if (!data.vol) {
|
|
return main.alert(' 光证波动率 必须填写');
|
|
}
|
|
main.post("/skewMap/SetVarietyVol", data).done(function () {
|
|
main.message("保存成功");
|
|
});
|
|
};
|
|
});
|
|
|
|
//标的BaseVol
|
|
const baseVolVue = new Vue({
|
|
el: "#baseVolWrap",
|
|
data: {
|
|
Vollist: {},
|
|
expireList: [],
|
|
BidVar: 1,
|
|
AskVar: 1,
|
|
Model: {
|
|
canSaveVol: true, VolSurfaceMode: "MoneynessVol", InterpolationMethod: "", VolTable: [], VolType: "交易",
|
|
DefaultVol: "0.3", CacheVollist: {}, StrikeDesc: "行权价", CheckAddExpire: true, CheckVols: true
|
|
},
|
|
},
|
|
methods: {
|
|
setVolTableProxy: function (volTable) {
|
|
var thisObj = this;
|
|
var list = volTable;
|
|
const proxyProps = ["Strike"];
|
|
if (list && list.length) {
|
|
list.forEach(function (obj) {
|
|
var propDefines = {};
|
|
proxyProps.map(function (pname) {
|
|
propDefines[pname + 'Proxy'] = {
|
|
get: function () {
|
|
return numeral(obj[pname] * 100).format("0.00");
|
|
},
|
|
set: function (newValue) {
|
|
obj[pname] = newValue / 100; thisObj.Model.InputVolChange = true;
|
|
}
|
|
};
|
|
});
|
|
Object.defineProperties(obj, propDefines);
|
|
});
|
|
}
|
|
else {
|
|
var propDefines = {};
|
|
proxyProps.map(function (pname) {
|
|
propDefines[pname + 'Proxy'] = {
|
|
get: function () { return numeral(volTable[pname] * 100).format("0.00"); },
|
|
set: function (newValue) { volTable[pname] = newValue / 100; thisObj.Model.InputVolChange = true; }
|
|
};
|
|
});
|
|
Object.defineProperties(volTable, propDefines);
|
|
}
|
|
return volTable;
|
|
},
|
|
watchVol: function (VolProxy) {
|
|
var valueArray = String(VolProxy).split(".");
|
|
if (valueArray.length > 1 && valueArray[1].length > 2) {
|
|
if (pageObj.volMoreAccurate) {
|
|
VolProxy = Math.floor(VolProxy * 10000) / 10000;
|
|
}
|
|
else {
|
|
VolProxy = Math.floor(VolProxy * 100) / 100;
|
|
}
|
|
}
|
|
return VolProxy;
|
|
},
|
|
checkvols: function (event) {
|
|
//检查vol的数字必需为正数.
|
|
//2. 同一个vol grid, 检查所有数字,发现max > 10 * min,就报错,提示交易员有问题。纠正后再保存。
|
|
//如果用户选择忽略,则允许保存。
|
|
if (event) {
|
|
let vol = this.watchVol($(event.target).val());
|
|
let strike = $(event.target).attr("Strike");
|
|
let expire = $(event.target).attr("Expire");
|
|
$.each(baseVolVue.expireList, function (i, obj) {
|
|
if (obj.Expire === expire) {
|
|
$.each(obj.Vols, function (j, item) {
|
|
if (item.Strike === strike) {
|
|
item.VolProxy = vol;
|
|
item.Vol = vol / 100;
|
|
}
|
|
return false;
|
|
});
|
|
return false;
|
|
}
|
|
});
|
|
if (vol <= 0) {
|
|
$(event.target).focus();
|
|
main.message("波动率请输入正数");
|
|
this.Model.CheckVols = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
var maxVol = { Vol: 0 };
|
|
var minVol = { Vol: 99999 };
|
|
$.grep(baseVolVue.expireList, function (obj, index) {
|
|
$.grep(obj.Vols, function (data, i) {
|
|
if (data.Vol && obj.Expire !== "BidVar" && obj.Expire !== "AskVar") {
|
|
if (data.Vol > maxVol.Vol) {
|
|
maxVol = data;
|
|
}
|
|
|
|
if (data.Vol < minVol.Vol) {
|
|
minVol = data;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
if (maxVol.Vol > 10 * minVol.Vol) {
|
|
main.message("警告,最大Vol超过10倍最小Vol");
|
|
}
|
|
|
|
this.Model.CheckVols = true;
|
|
},
|
|
checkVar: function (ex) {
|
|
if (!(/^\d+$/.test(ex.currentTarget.value))) {
|
|
main.message("正确的Var值应为正整数");
|
|
ex.currentTarget.focus();
|
|
}
|
|
},
|
|
checkAddExpire: function (obj) {
|
|
var thisObj = this;
|
|
$("#newAddExpire").val($("#newAddExpire").val().toUpperCase());
|
|
var newExpire = $("#newAddExpire").val();
|
|
if (!newExpire || !thisObj.checkExpire(newExpire)) {
|
|
main.message("请输入正确的期限");
|
|
thisObj.Model.CheckAddExpire = false;
|
|
$("#newAddExpire").focus();
|
|
return;
|
|
}
|
|
var eList = [];
|
|
$.each(this.expireList, function (i, obj) {
|
|
if (!obj.IsNewExpire) {
|
|
eList.push(obj);
|
|
}
|
|
});
|
|
|
|
if (eList.some(x => x.Expire === newExpire)) {
|
|
main.message("请输入不同的期限");
|
|
thisObj.Model.CheckAddExpire = false;
|
|
$("#newAddExpire").focus();
|
|
} else {
|
|
thisObj.Model.CheckAddExpire = true;
|
|
}
|
|
this.checkvols();
|
|
},
|
|
deleteExpire: function (expire) {
|
|
var thisObj = this;
|
|
var flag = false;
|
|
var grepExpire = [];
|
|
if (!expire.IsNewExpire) { //删除行为新增到期日时
|
|
$.grep(thisObj.Vollist.VolTable, function (value) {
|
|
if (value.Expire != expire.Expire) {
|
|
grepExpire.push(value);
|
|
}
|
|
});
|
|
} else {
|
|
$.grep(thisObj.Vollist.VolTable, function (value) {
|
|
if (value.Expire != "") {
|
|
grepExpire.push(value);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!grepExpire.length) {
|
|
flag = true;
|
|
}
|
|
if (!flag) {
|
|
if (expire.IsNewExpire) { thisObj.Model.CheckAddExpire = true; }
|
|
thisObj.Vollist.VolTable = grepExpire;
|
|
thisObj.Vollist.Data = JSON.stringify(thisObj.Vollist.VolTable);
|
|
}
|
|
if (flag) {
|
|
main.message("不能删光到期日");
|
|
return;
|
|
}
|
|
thisObj.loadVollist();
|
|
if (expire.IsNewExpire) {
|
|
thisObj.Model.CheckAddExpire = true;
|
|
}
|
|
},
|
|
loadVollist: function () { //为展示分析波动率数据
|
|
var thisObj = this;
|
|
//移除空
|
|
thisObj.expireList = [];
|
|
if (thisObj.Vollist.VolTable && thisObj.Vollist.VolTable.length) {
|
|
thisObj.Vollist.VolTable.sort(function sortStrike(a, b) { return a.Strike - b.Strike });
|
|
$.each(thisObj.Vollist.VolTable, function (i, d) {
|
|
//补丁,有时候会出现Strike为1.0和1.00不是同一个strike情况
|
|
d.Strike = main.toNumber(d.Strike, 4);
|
|
|
|
if (typeof (d) !== "function") {
|
|
if (d.IsNewExpire || (d.Expire !== "" && d.Vol !== 0)) {
|
|
if (d.Expire === "AskVar") { thisObj.AskVar = d.Vol; }
|
|
else if (d.Expire === "BidVar") { thisObj.BidVar = d.Vol; }
|
|
else if (!thisObj.expireList.some(x => x.Expire === d.Expire)) {
|
|
thisObj.expireList.push({ ValidState: d.ExpireValidState, Expire: d.Expire, IsNewExpire: d.IsNewExpire, Vols: [{ Vol: d.Vol, Strike: d.Strike }] });
|
|
}
|
|
else {
|
|
$.each(thisObj.expireList, function (j, obj) {
|
|
if (obj.Expire === d.Expire) {
|
|
obj.Vols.push({ Vol: d.Vol, Strike: d.Strike });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
var orderExpire = ["D", "W", "M", "Y"];
|
|
$.each(thisObj.expireList, function (i, obj) {
|
|
thisObj.setVolTableProxy(obj.Vols);
|
|
$.each(obj.Vols, function (j, item) {
|
|
item.VolProxy = numeral(item.Vol * 100).format("0.00")
|
|
});
|
|
})
|
|
thisObj.expireList.sort(function sortExpire(a, b) {
|
|
//比较到期日字母,比较数字
|
|
var adata = thisObj.getExpireDay(a.Expire);
|
|
var bdata = thisObj.getExpireDay(b.Expire);
|
|
return adata - bdata;
|
|
});
|
|
},
|
|
getExpireDay: function (expire) {
|
|
var mu = expire.substr(expire.length - 1, 1);
|
|
var data = expire.substr(0, expire.length - 1);
|
|
var drate = 1;
|
|
switch (mu) {
|
|
case "W": drate = 7; break;
|
|
case "M": drate = 30; break;
|
|
case "Y": drate = 365; break;
|
|
}
|
|
return data * drate;
|
|
},
|
|
checkExpire: function (ex) {
|
|
return /^\d+(W|Y|M|D)$/.test(ex);
|
|
}
|
|
}
|
|
});
|
|
|
|
//标的BaseVol
|
|
const baseVolHandler = (new function () {
|
|
|
|
var _autoUnderlying;
|
|
|
|
function initVoTable() {
|
|
baseVolVue.BidVar = 1;
|
|
baseVolVue.AskVar = 1;
|
|
baseVolVue.expireList = [];
|
|
baseVolVue.Vollist = {
|
|
canSaveVol: true, VolTable: [{ Strike: 1, Expire: "", Vol: "" }],
|
|
DefaultVol: "0.3", CacheVollist: {}, StrikeDesc: "行权价", CheckAddExpire: true, CheckVols: true
|
|
};
|
|
baseVolVue.loadVollist();
|
|
}
|
|
|
|
function getBaseVolInfo() {
|
|
initVoTable();
|
|
let data = {
|
|
valueDate: _.trim($("#maintainDate").val()),
|
|
underlyingCode: _.trim($('#selUnderlying').val())
|
|
};
|
|
if (!data.valueDate || !data.underlyingCode) {
|
|
return;
|
|
}
|
|
main.post("/skewMap/GetBaseVol", data).done(function (res) {
|
|
let baseVol = res.obj;
|
|
if (baseVol) {
|
|
baseVolVue.Vollist = baseVol;
|
|
baseVolVue.loadVollist();
|
|
} else {
|
|
main.message("BaseVol不存在");
|
|
}
|
|
});
|
|
}
|
|
|
|
this.init = function () {
|
|
|
|
$("#maintainDate").datepicker(datePickerOpt).val(pageObj.valueDate).change();
|
|
|
|
$('#uploadBaseVolCtrl').on('change', function () {
|
|
$(this).next().text($(this).val());
|
|
}).next().on('click', function () {
|
|
$(this).prev().click();
|
|
});
|
|
|
|
let unflag = tradeHelper.UnderlyingSelectFlag;
|
|
let options = {
|
|
SelectFlag: unflag.UsePinYinFilter | unflag.IncludeMatured,
|
|
onSelect: getBaseVolInfo
|
|
};
|
|
_autoUnderlying = tradeHelper.UnderlyingAutoComplete('selUnderlying', options);
|
|
_autoUnderlying.selectFirst();
|
|
|
|
$('#maintainDate').on('change', function () {
|
|
let enable = pageObj.valueDate === $("#maintainDate").val();
|
|
$('#btnSaveBaseVol').prop('disabled', !enable);
|
|
getBaseVolInfo();
|
|
});
|
|
};
|
|
|
|
this.upload = function () {
|
|
let files = document.getElementById('uploadBaseVolCtrl').files;
|
|
if (!files.length) {
|
|
return main.alert('请选择上传文件');
|
|
}
|
|
var formData = new FormData();
|
|
formData.append("file", files[0]);
|
|
main.waitMe("show");
|
|
$.ajax({
|
|
url: '/skewMap/UploadBaseVol',
|
|
type: 'POST',
|
|
processData: false,
|
|
contentType: false,
|
|
data: formData,
|
|
cache: false,
|
|
success: function (resp) {
|
|
if (resp.success) {
|
|
main.message("导入成功!");
|
|
$('#uploadBaseVolCtrl').val('').next().text('请选择...');
|
|
} else {
|
|
main.message("导入失败:" + resp.msg);
|
|
}
|
|
},
|
|
error(data) {
|
|
main.message("导入失败");
|
|
},
|
|
complete() {
|
|
main.waitMe("hide");
|
|
}
|
|
});
|
|
};
|
|
|
|
this.download = function (isAll) {
|
|
let data = {
|
|
valueDate: _.trim($("#maintainDate").val()),
|
|
underlyingCode: isAll ? "" : _.trim($('#selUnderlying').val())
|
|
};
|
|
if (!data.valueDate) {
|
|
return main.alert('维护日期 必须填写');
|
|
}
|
|
if (!isAll && !data.underlyingCode) {
|
|
return main.alert('标的代码 必须填写');
|
|
}
|
|
$('#hide_base_valueDate').val(data.valueDate);
|
|
$('#hide_base_underlyingCode').val(data.underlyingCode);
|
|
$('#formBaseVol').submit();
|
|
};
|
|
|
|
this.addExpire = function () {
|
|
if (baseVolVue.Vollist.VolTable.some(x => x.IsNewExpire)) {
|
|
return main.message("已经有新增到期日");
|
|
}
|
|
var newVol = [];
|
|
if (baseVolVue.expireList.length > 0) {
|
|
$.each(baseVolVue.expireList[0].Vols, function (i, d) {
|
|
newVol.push({ Strike: d.Strike, Vol: d.Vol });
|
|
})
|
|
} else {
|
|
newVol.push({ Strike: 1, Vol: 0.3 });
|
|
}
|
|
$.each(newVol, function (i, d) {
|
|
baseVolVue.Vollist.VolTable.push({
|
|
Expire: "", IsNewExpire: true, Strike: d.Strike, Vol: d.Vol
|
|
});
|
|
})
|
|
baseVolVue.loadVollist();
|
|
};
|
|
|
|
this.clearChange = getBaseVolInfo;
|
|
|
|
this.saveBaseVol = function () {
|
|
let data = {
|
|
QuotationDate: _.trim($("#maintainDate").val()),
|
|
ContractCode: _.trim($('#selUnderlying').val())
|
|
};
|
|
if (!data.QuotationDate) {
|
|
return main.alert('维护日期 必须填写');
|
|
}
|
|
if (!data.ContractCode) {
|
|
return main.alert('标的代码 必须填写');
|
|
}
|
|
if (!baseVolVue.Model.CheckAddExpire) {
|
|
return main.message("请检查新增到期日是否正确");
|
|
}
|
|
if (!baseVolVue.Model.CheckVols) {
|
|
return main.message("请检查波动率是否正确");
|
|
}
|
|
if (!(/^\d+$/.test(baseVolVue.BidVar))) {
|
|
return main.message("请检查BidVar是否正确");
|
|
}
|
|
if (!(/^\d+$/.test(baseVolVue.AskVar))) {
|
|
return main.message("请检查AskVar是否正确");
|
|
}
|
|
|
|
let VolTable = [];
|
|
$.each(baseVolVue.expireList, function (i, obj) {
|
|
$.each(obj.Vols, function (j, d) {
|
|
VolTable.push({ Strike: d.Strike, Expire: obj.Expire.toUpperCase(), Vol: main.toNumber(d.Vol, 4) });
|
|
});
|
|
});
|
|
|
|
VolTable.push({ Strike: 1, Expire: "BidVar", Vol: baseVolVue.BidVar });
|
|
VolTable.push({ Strike: 1, Expire: "AskVar", Vol: baseVolVue.AskVar });
|
|
|
|
data.Data = JSON.stringify(VolTable);
|
|
|
|
main.post('/skewMap/SetBaseVol', data).done(function (res) {
|
|
main.alert("保存成功");
|
|
baseVolVue.Vollist = res.obj;
|
|
baseVolVue.loadVollist();
|
|
});
|
|
};
|
|
});
|
|
|
|
$(function () {
|
|
|
|
globalHandler.init();
|
|
|
|
gzVolHandler.init();
|
|
|
|
baseVolHandler.init();
|
|
}); |