191 lines
9.0 KiB
C#
191 lines
9.0 KiB
C#
using BaseOUDAL;
|
|
using YLErp.Model;
|
|
using YLErp.Modules.VolatilityModule;
|
|
using YLErp.Modules.VolatilityModule.SkewMapVolModule;
|
|
using YLErp.QdpModule;
|
|
using YLErp.QdpModule.Constants;
|
|
|
|
namespace YLErp.BLL
|
|
{
|
|
public class underlying_main_contract_historyBLL
|
|
{
|
|
public static readonly List<string> ShowExpires;
|
|
public static readonly List<string> 有色金属ShowExpires;
|
|
|
|
static underlying_main_contract_historyBLL()
|
|
{
|
|
if (!PS.Config.ErpElement.SkewMapVolConstruction)
|
|
{
|
|
ShowExpires = new List<string> { "2W", "1M", "3M" };
|
|
有色金属ShowExpires = new List<string> { "2W", "1M", "2M" };
|
|
}
|
|
else
|
|
{
|
|
ShowExpires = new List<string> { "1M", "3M", "6M" };
|
|
有色金属ShowExpires = new List<string> { "1M", "3M", "6M" };
|
|
}
|
|
}
|
|
|
|
public static List<VolatilityQuotation> GetVolatilityQuotation(int userId, IEnumerable<flat_price_quotation> quotationList, string userGroup = null)
|
|
{
|
|
var VQ = new List<VolatilityQuotation>();
|
|
if (string.IsNullOrEmpty(userGroup))
|
|
{
|
|
userGroup = UserBLL.GetUserGroup(userId);
|
|
}
|
|
var vollist = new VolatilityQueryService(OptUserInfo.SystemUser)
|
|
.GetVolatilities(new BatchVolatilityRequest
|
|
{
|
|
QuotationDate = valuedateBLL.ValueDate,
|
|
VolTypes = ConsVolInfos.subTradeVolType,
|
|
UnderlyingCodes = quotationList.Select(O => O.UnderlyingCode).ToArray(),
|
|
UserGroup = userGroup,
|
|
TradeVolWithBidAsk = false
|
|
}, true);
|
|
var exDate = QdpCalendarHelper.GetNonHoliday(valuedateBLL.ValueDate.AddMonths(1).AddDays(-1));
|
|
var exerciseDate = exDate;
|
|
var quotationUnderlyinglist = underlying_main_contractBLL.GetDefaultAtMoneyQuoteList(exDate);
|
|
|
|
quotationList = quotationList.Where(q =>
|
|
quotationUnderlyinglist.Any(u => string.Equals(u.UnderlyingCode, q.UnderlyingCode, StringComparison.OrdinalIgnoreCase))).OrderBy(o => o.order).ToList();
|
|
|
|
var activeAsset = underlying_main_contractBLL.GetAllunderlying_main_contractModel().Where(x => x.NeedQuote == 1);
|
|
|
|
foreach (var qu in quotationList)
|
|
{
|
|
var singleVQ = new VolatilityQuotation() { MarketName = qu.MarketName, UnderlyingMainCode = qu.UnderlyingCode, UnderlyingType = qu.UnderlyingType };
|
|
var underlying = quotationUnderlyinglist.FirstOrDefault(u => string.Equals(u.UnderlyingCode, qu.UnderlyingCode, StringComparison.OrdinalIgnoreCase));
|
|
singleVQ.CommodityCode = underlying.CommodityCode;
|
|
var checkExpires = ShowExpires;
|
|
if (underlying_managerBLL.IsYouSeJinShu(qu.UnderlyingCode))
|
|
{
|
|
checkExpires = 有色金属ShowExpires;
|
|
}
|
|
var contractUnder = activeAsset.FirstOrDefault(q => q.UnderlyingType == qu.UnderlyingType);
|
|
//var tt = activeAsset.Where(v => v.UnderlyingCode == qu.UnderlyingCode).ToList();
|
|
//var ttt = quotationUnderlyinglist.Where(q => q.UnderlyingType == "棕榈油").ToList();
|
|
var contractVol = new List<volatility>();
|
|
if (contractUnder != null && vollist != null)
|
|
{
|
|
contractVol = vollist.Where(v => contractUnder.UnderlyingCodeList.Contains(v.ContractCode)).ToList();
|
|
}
|
|
|
|
volatility askVolTable = null;
|
|
volatility bidVolTable = null;
|
|
if (PS.Config.ErpElement.SkewMapVolConstruction)
|
|
{
|
|
var req = new SkewVolRequest
|
|
{
|
|
VolType = null,
|
|
valueDate = valuedateBLL.ValueDate,
|
|
Strike = qu.SpotPrice ?? 0,
|
|
UnderlyingCode = underlying.UnderlyingCode
|
|
};
|
|
req.VolType = "报价Ask";
|
|
askVolTable = SkewVolQueryService.GetVol(userId, req);
|
|
req.VolType = "报价Bid";
|
|
bidVolTable = SkewVolQueryService.GetVol(userId, req);
|
|
}
|
|
else
|
|
{
|
|
askVolTable = SetVolQuotationTable(contractVol, qu, "报价Ask", checkExpires);
|
|
bidVolTable = SetVolQuotationTable(contractVol, qu, "报价Bid", checkExpires);
|
|
}
|
|
|
|
var volReq = new InterpolatedVolReq()
|
|
{
|
|
strike = qu.SpotPrice ?? 0,
|
|
isMoneynessOption = false,
|
|
exerciseDate = exerciseDate,
|
|
valueDate = valuedateBLL.ValueDate,
|
|
spot = qu.SpotPrice ?? 0,
|
|
volSurfaceType = askVolTable.VolSurfaceMode
|
|
};
|
|
|
|
var askeGroup = new List<ExpireGroup>();
|
|
if (askVolTable.VolTable != null)
|
|
{
|
|
askeGroup = askVolTable.VolTable.GroupBy(v => v.Expire).Select(v => new ExpireGroup { Expire = v.Key, Sv = v.ToList() }).ToList();
|
|
}
|
|
|
|
var bideGroup = new List<ExpireGroup>();
|
|
if (bidVolTable.VolTable != null)
|
|
{
|
|
bideGroup = bidVolTable.VolTable.GroupBy(v => v.Expire).Select(v => new ExpireGroup { Expire = v.Key, Sv = v.ToList() }).ToList();
|
|
}
|
|
|
|
var BidAskMatureData = new List<BidAskMatureData>();
|
|
|
|
foreach (var expire in checkExpires)
|
|
{
|
|
var askvol = double.NaN;
|
|
var bidvol = double.NaN;
|
|
var askGroup = askeGroup.FirstOrDefault(a => a.Expire == expire);
|
|
var bidgroup = bideGroup.FirstOrDefault(b => b.Expire == expire);
|
|
if (askGroup != null)
|
|
{
|
|
askvol = QdpVolHelper.GetInterpolatedVolFromNormalSurface(askGroup.Sv, volReq, askVolTable.InterpolationMethod);
|
|
}
|
|
else if (!PS.Config.ErpElement.SkewMapVolConstruction)
|
|
{
|
|
askvol = QdpVolHelper.GetInterpolatedVolFromNormalSurface(askVolTable.VolTable, volReq, askVolTable.InterpolationMethod);
|
|
}
|
|
if (bidgroup != null)
|
|
{
|
|
bidvol = QdpVolHelper.GetInterpolatedVolFromNormalSurface(bidgroup.Sv, volReq, bidVolTable.InterpolationMethod);
|
|
}
|
|
else if (!PS.Config.ErpElement.SkewMapVolConstruction)
|
|
{
|
|
bidvol = QdpVolHelper.GetInterpolatedVolFromNormalSurface(bidVolTable.VolTable, volReq, bidVolTable.InterpolationMethod);
|
|
}
|
|
|
|
var md = new BidAskMatureData() { Expire = expire, AskVol = askvol, BidVol = bidvol };
|
|
BidAskMatureData.Add(md);
|
|
}
|
|
singleVQ.BidAskMatureData = BidAskMatureData;
|
|
VQ.Add(singleVQ);
|
|
|
|
}
|
|
return VQ;
|
|
}
|
|
|
|
public static volatility SetVolQuotationTable(List<volatility> vollist, flat_price_quotation qu, string voltype, List<string> ShowExpires)
|
|
{
|
|
var askVolTable = vollist.FirstOrDefault(v => v.ContractCode == qu.UnderlyingCode && v.VolType == voltype);
|
|
if (askVolTable == null)
|
|
{
|
|
askVolTable = vollist.FirstOrDefault(v => v.ContractCode.Contains(underlying_managerBLL.GetCommodityCodeByUnCode(qu.UnderlyingCode)) && v.VolType == voltype);
|
|
if (askVolTable == null)
|
|
{
|
|
askVolTable = new volatility { VolType = voltype, VolSurfaceMode = "MoneynessVol" };
|
|
return askVolTable;
|
|
}
|
|
}
|
|
if (string.IsNullOrEmpty(askVolTable.VolSurfaceMode))
|
|
{
|
|
askVolTable.VolSurfaceMode = "MoneynessVol";
|
|
}
|
|
//需要检查 ShowExpires 里不存在的
|
|
foreach (var expire in ShowExpires)
|
|
{
|
|
if (!askVolTable.VolTable.Any(v => v.Expire == expire))
|
|
{
|
|
//不存在则要查找 todo 这边应该找主力合约的波动率
|
|
var volTable = vollist.FirstOrDefault(v => v.VolTable.Any(vt => vt.Expire == expire) && v.VolType == voltype);
|
|
if (volTable != null && volTable.VolTable != null)
|
|
{
|
|
var vtInner = volTable.VolTable.Where(vt => vt.Expire == expire).ToList();
|
|
if (vtInner != null)
|
|
{
|
|
var vt = askVolTable.VolTable;
|
|
vt.AddRange(vtInner);
|
|
askVolTable.Data = vt.ToJson();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return askVolTable;
|
|
}
|
|
}
|
|
}
|