726 lines
25 KiB
C#
726 lines
25 KiB
C#
using System.Linq.Expressions;
|
|
using System.Text;
|
|
using YieldChain.Helpers;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.QdpModule.Constants;
|
|
|
|
namespace YLErp.Modules.VolatilityModule
|
|
{
|
|
/// <summary>
|
|
/// 只用于波动率数据查询
|
|
/// </summary>
|
|
public class VolatilityQueryService : YLBaseService
|
|
{
|
|
public VolatilityQueryService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
|
|
}
|
|
|
|
public VolatilityQueryService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
|
|
}
|
|
|
|
#region----获取单个标的的曲面波动率----
|
|
|
|
/// <summary>
|
|
/// 获取单个标的的曲面波动率
|
|
/// </summary>
|
|
public volatility GetVolatility(string userGroup, DateTime quotationDate, string volType, string underlyingCode, bool createIfNotFound = true)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(underlyingCode))
|
|
{
|
|
throw new ArgumentException("标的代码不能为空", nameof(underlyingCode));
|
|
}
|
|
|
|
var vols = GetVolatility(new SingleVolatilityRequest
|
|
{
|
|
UserGroup = userGroup,
|
|
QuotationDate = quotationDate,
|
|
VolType = volType,
|
|
TradeVolWithBidAsk = false,
|
|
UnderlyingCode = underlyingCode,
|
|
UnderlyingId = 0
|
|
}, createIfNotFound);
|
|
|
|
return vols?.FirstOrDefault(n => n.VolType == volType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取单个标的的曲面波动率
|
|
/// </summary>
|
|
public volatility GetVolatility(string userGroup, DateTime quotationDate, string volType, int underlyingId, bool createIfNotFound = true)
|
|
{
|
|
var vols = GetVolatility(new SingleVolatilityRequest
|
|
{
|
|
UserGroup = userGroup,
|
|
QuotationDate = quotationDate,
|
|
VolType = volType,
|
|
TradeVolWithBidAsk = false,
|
|
UnderlyingCode = string.Empty,
|
|
UnderlyingId = underlyingId
|
|
}, createIfNotFound);
|
|
|
|
return vols?.FirstOrDefault(n => n.VolType == volType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// VolType为交易的情况下,返回["交易","报价Bid","报价Ask"]波动率
|
|
/// </summary>
|
|
public IEnumerable<volatility> GetVolatility(SingleVolatilityRequest request, bool createIfNotFound = true)
|
|
{
|
|
CheckRequest(request);
|
|
|
|
underlying_manager un = null;
|
|
|
|
if (!string.IsNullOrEmpty(request.UnderlyingCode))
|
|
{
|
|
un = DataCacheProvider.GetUnderlyingDataSource().GetData(request.UnderlyingCode);
|
|
}
|
|
else if (request.UnderlyingId.HasValue)
|
|
{
|
|
un = DataCacheProvider.GetUnderlyingDataSource().GetData(request.UnderlyingId.Value);
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentException("标的代码或标的ID不能为空", nameof(request.UnderlyingCode));
|
|
}
|
|
|
|
if (un == null)
|
|
{
|
|
return Enumerable.Empty<volatility>();
|
|
}
|
|
|
|
if (un.CommodityCode == "组合标的")
|
|
{
|
|
return VolatilityHelper.GetDefaultVols(request);
|
|
}
|
|
|
|
//先对期货标的做特殊处理
|
|
if (un.IsFutures() && un.MaturityDate < request.QuotationDate)
|
|
{
|
|
return VolatilityHelper.GetDefaultVols(request, 0);
|
|
}
|
|
|
|
var volPredicate = BuildPredicate(request);
|
|
if (volPredicate == null)
|
|
{
|
|
return VolatilityHelper.GetDefaultVols(request);
|
|
}
|
|
|
|
request.UnderlyingId = un.id;
|
|
request.UnderlyingCode = un.UnderlyingCode;
|
|
|
|
var groupQuery = from v in DbContext.volatility.Where(volPredicate)
|
|
where v.ContractCode == request.UnderlyingCode
|
|
group v by new { v.UserGroup, v.ContractCode, v.VolType } into vg
|
|
select new VolGroupDto
|
|
{
|
|
UserGroup = vg.Key.UserGroup,
|
|
ContractCode = vg.Key.ContractCode,
|
|
VolType = vg.Key.VolType,
|
|
QuotationDate = vg.Max(n => n.QuotationDate)
|
|
};
|
|
|
|
var volQuery = from vg in groupQuery
|
|
join v in DbContext.volatility
|
|
on new { vg.UserGroup, vg.ContractCode, vg.VolType, vg.QuotationDate }
|
|
equals new { v.UserGroup, v.ContractCode, v.VolType, v.QuotationDate }
|
|
orderby v.ContractCode
|
|
select v;
|
|
|
|
var results = volQuery.ToArray().AsEnumerable();
|
|
|
|
if (results.Any())
|
|
{
|
|
foreach (var item in results)
|
|
{
|
|
item.QuotationDate = request.QuotationDate;
|
|
}
|
|
}
|
|
//如果从数据库中未能获取到波动率数据
|
|
else if (createIfNotFound && !results.Any())
|
|
{
|
|
results = ProcesseMissingVol(request, un);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region----批量获取标的的曲面波动率----
|
|
|
|
/// <summary>
|
|
/// 为波动率批量导出业务获取波动率列表(不需要同源波动率)
|
|
/// </summary>
|
|
public IEnumerable<volatility> GetVolatilities(BatchVolatilityRequest request, bool createIfNotFound)
|
|
{
|
|
CheckRequest(request);
|
|
|
|
var volPredicate = BuildPredicate(request, request.StartDate);
|
|
|
|
if (volPredicate == null)
|
|
{
|
|
return Enumerable.Empty<volatility>();
|
|
}
|
|
|
|
var resultList = new List<volatility>();
|
|
if (request.VarietyIds != null && request.VarietyIds.Any())
|
|
{
|
|
request.VarietyIds = request.VarietyIds.ToList();
|
|
}
|
|
//标的关联(返回null表示已没有可以筛选的标的)
|
|
var unPredicate = BuildUnderlyingPredicate(request, resultList);
|
|
if (unPredicate == null)
|
|
{
|
|
return resultList;
|
|
}
|
|
|
|
var unQuery = DbContext.underlying_manager.Where(unPredicate);
|
|
|
|
//数据量小的表尽量靠前
|
|
var groupQuery = from un in unQuery
|
|
join v in DbContext.volatility.Where(volPredicate) on un.UnderlyingCode equals v.ContractCode
|
|
group v by new { v.UserGroup, v.ContractCode, v.VolType } into vg
|
|
select new
|
|
{
|
|
vg.Key.UserGroup,
|
|
vg.Key.ContractCode,
|
|
vg.Key.VolType,
|
|
QuotationDate = vg.Max(n => n.QuotationDate)
|
|
};
|
|
|
|
//var count = groupQuery.Count();
|
|
|
|
var volQuery = from vg in groupQuery
|
|
join v in DbContext.volatility
|
|
on vg equals new { v.UserGroup, v.ContractCode, v.VolType, v.QuotationDate }
|
|
orderby v.ContractCode
|
|
select v;
|
|
|
|
resultList.AddRange(volQuery.ToList());
|
|
|
|
foreach (var item in resultList)
|
|
{
|
|
item.QuotationDate = request.QuotationDate;
|
|
}
|
|
|
|
if (createIfNotFound)
|
|
{
|
|
var unIds = resultList.Select(n => n.UnderlyingId).ToHashSet();
|
|
var missingUns = DataCacheProvider.GetUnderlyingDataSource().AsQueryable()
|
|
.Where(unPredicate).Where(n => !unIds.Remove(n.id)).ToArray();
|
|
foreach (var un in missingUns)
|
|
{
|
|
var vols = ProcesseMissingVol(new SingleVolatilityRequest(request, un.UnderlyingCode, un.id), un);
|
|
resultList.AddRange(vols);
|
|
}
|
|
}
|
|
|
|
return resultList;
|
|
}
|
|
|
|
//resultList用于存储过期标的的波动率
|
|
private Expression<Func<underlying_manager, bool>> BuildUnderlyingPredicate(BatchVolatilityRequest request, List<volatility> resultList)
|
|
{
|
|
Expression<Func<underlying_manager, bool>> predicate = null;
|
|
|
|
var unSource = DataCacheProvider.GetUnderlyingDataSource();
|
|
|
|
//优先级1(如果是有效过滤条件则忽略UnderlyingCodes)
|
|
if (request.UnderlyingIds != null && request.UnderlyingIds.Any(n => n > 0))
|
|
{
|
|
var set = request.UnderlyingIds.ToHashSet();
|
|
|
|
foreach (var unId in request.UnderlyingIds)
|
|
{
|
|
var un = unSource.GetData(unId);
|
|
if (un == null) { }
|
|
else if (un.IsFutures() && un.MaturityDate < request.QuotationDate)
|
|
{
|
|
var vols = VolatilityHelper.GetDefaultVols(new SingleVolatilityRequest(request, un.UnderlyingCode, un.id), 0);
|
|
resultList.AddRange(vols);
|
|
}
|
|
else if (unId > 0)
|
|
{
|
|
set.Add(unId);
|
|
}
|
|
}
|
|
|
|
if (!set.Any())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
predicate = PredicateBuilder.Create<underlying_manager>(n => set.Contains(n.id));
|
|
}
|
|
//优先级2
|
|
else if (request.UnderlyingCodes != null && request.UnderlyingCodes.Any(n => !string.IsNullOrEmpty(n)))
|
|
{
|
|
var set = request.UnderlyingCodes.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
|
|
foreach (var unCode in request.UnderlyingCodes)
|
|
{
|
|
var un = unSource.GetData(unCode);
|
|
if (un == null) { }
|
|
else if (un.IsFutures() && un.MaturityDate < request.QuotationDate)
|
|
{
|
|
var vols = VolatilityHelper.GetDefaultVols(new SingleVolatilityRequest(request, un.UnderlyingCode, un.id), 0);
|
|
resultList.AddRange(vols);
|
|
}
|
|
else if (!string.IsNullOrWhiteSpace(unCode))
|
|
{
|
|
set.Add(unCode);
|
|
}
|
|
}
|
|
|
|
if (!set.Any())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
predicate = PredicateBuilder.Create<underlying_manager>(n => set.Contains(n.UnderlyingCode));
|
|
}
|
|
else
|
|
{
|
|
predicate = PredicateBuilder.Create<underlying_manager>(n => n.CommodityCode != "组合标的" && n.LaunchState == "1");
|
|
}
|
|
|
|
if (request.VarietyIds != null && request.VarietyIds.Any(n => n > 0))
|
|
{
|
|
predicate = predicate.And(n => request.VarietyIds.Contains(n.UnderlyingTypeId));
|
|
}
|
|
|
|
predicate = predicate.And(n => n.UnderlyingInstrumentType != ConsGlobal.InstrumentType.CommodityFutures || n.MaturityDate >= request.QuotationDate);
|
|
|
|
return predicate;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region----处理数据库中找不到波动率的情况----
|
|
|
|
private IEnumerable<volatility> ProcesseMissingVol(SingleVolatilityRequest request, underlying_manager un)
|
|
{
|
|
if (PS.Config.ErpElement.SkewMapVolConstruction || (request != null && !ConsVolInfos.TradeVolTypes.Contains(request.VolType)))
|
|
{
|
|
return Enumerable.Empty<volatility>();
|
|
}
|
|
|
|
if (un == null)
|
|
{
|
|
if (!string.IsNullOrEmpty(request.UnderlyingCode))
|
|
{
|
|
un = DataCacheProvider.GetUnderlyingDataSource().GetData(request.UnderlyingCode);
|
|
}
|
|
else if (request.UnderlyingId > 0)
|
|
{
|
|
un = DataCacheProvider.GetUnderlyingDataSource().GetData(request.UnderlyingId.Value);
|
|
}
|
|
}
|
|
|
|
if (un == null)
|
|
{
|
|
return Enumerable.Empty<volatility>();
|
|
}
|
|
|
|
var reqVolTypes = request.GetVolTypes();
|
|
|
|
request.UnderlyingId = un.id;
|
|
request.UnderlyingCode = un.UnderlyingCode;
|
|
request.TradeVolWithBidAsk = true;
|
|
|
|
if (!PS.Config.ErpElement.SkewMapVolConstruction && ConsVolInfos.TradeVolTypes.Contains(request.VolType))
|
|
{
|
|
request.VolType = "交易";
|
|
}
|
|
|
|
var allVolTypes = request.GetVolTypes();
|
|
|
|
if (un.IsFutures())
|
|
{
|
|
if (un.CommodityCode == "组合标的")
|
|
{
|
|
//避免报价获取波动率时出错
|
|
return VolatilityHelper.GetDefaultVols(request);
|
|
}
|
|
|
|
if (un.MaturityDate < request.QuotationDate)
|
|
{
|
|
return VolatilityHelper.GetDefaultVols(request, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var defaultVols = VolatilityHelper.GetDefaultVols(request);
|
|
SaveMissingVols(defaultVols, "默认波动率");
|
|
return defaultVols.Where(n => reqVolTypes.Contains(n.VolType)).ToArray();
|
|
}
|
|
|
|
//获取同源合约代码,先主力合约再历史合约
|
|
|
|
VolCopyPara sameUn = null;
|
|
|
|
var match = System.Text.RegularExpressions.Regex.Match(un.UnderlyingCode, "^([a-zA-z]+)\\d+$");
|
|
if (match.Success)
|
|
{
|
|
var mainCode = match.Groups[1].Value + "00";
|
|
if (!mainCode.Equals(un.UnderlyingCode, StringComparison.OrdinalIgnoreCase)
|
|
&& DbContext.volatility.Any(v => v.UserGroup == request.UserGroup && v.ContractCode == mainCode && allVolTypes.Contains(v.VolType)))
|
|
{
|
|
sameUn = new VolCopyPara
|
|
{
|
|
id = un.id,
|
|
UnderlyingCode = un.UnderlyingCode,
|
|
SameCode = mainCode
|
|
};
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var query = from u1 in DbContext.underlying_manager.Where(n => n.id == un.id)
|
|
join u2 in DbContext.underlying_manager on u1.CommodityCode equals u2.CommodityCode
|
|
join v in DbContext.volatility on u2.UnderlyingCode equals v.ContractCode
|
|
where v.UserGroup == request.UserGroup && u2.MaturityDate.Value < u1.MaturityDate.Value && allVolTypes.Contains(v.VolType)
|
|
orderby u2.MaturityDate descending, v.QuotationDate descending
|
|
select new VolCopyPara
|
|
{
|
|
id = u1.id,
|
|
UnderlyingCode = u1.UnderlyingCode,
|
|
SameCode = u2.UnderlyingCode
|
|
};
|
|
|
|
sameUn = query.FirstOrDefault();
|
|
}
|
|
|
|
IEnumerable<volatility> vols = null;
|
|
|
|
if (sameUn != null)
|
|
{
|
|
request.UnderlyingCode = sameUn.SameCode;
|
|
|
|
vols = GetVolatility(request, false);
|
|
|
|
if (vols != null && vols.Count() == allVolTypes.Count())
|
|
{
|
|
foreach (var item in vols)
|
|
{
|
|
item.UnderlyingId = sameUn.id;
|
|
item.ContractCode = sameUn.UnderlyingCode;
|
|
item.QuotationDate = request.QuotationDate;
|
|
}
|
|
SaveMissingVols(vols, "同源复制" + sameUn.SameCode);
|
|
}
|
|
else
|
|
{
|
|
vols = null;
|
|
}
|
|
}
|
|
|
|
if (vols == null)
|
|
{
|
|
vols = VolatilityHelper.GetDefaultVols(request);
|
|
SaveMissingVols(vols, "默认波动率");
|
|
}
|
|
|
|
return vols.Where(n => reqVolTypes.Contains(n.VolType)).ToArray();
|
|
}
|
|
|
|
//保存同源波动率或默认波动率
|
|
private void SaveMissingVols(IEnumerable<volatility> missingVols, string dataSource)
|
|
{
|
|
if (missingVols == null || !missingVols.Any() || Interlocked.Increment(ref saveLock) > 1) return;
|
|
|
|
try
|
|
{
|
|
var date = new DateTime(2000, 1, 1);
|
|
var arr = missingVols.Where(n => ConsVolInfos.VolTypes.Contains(n.VolType))
|
|
.Select(n =>
|
|
{
|
|
//n可能是volatility类型的子类,如果clone的话会导致写入数据库出错
|
|
var clone = YLAutoMapper.Map<volatility>(n);
|
|
clone.OptId = 0;
|
|
clone.OptName = dataSource ?? "同源复制";
|
|
clone.OptDate = DateTime.Now;
|
|
clone.QuotationDate = date;
|
|
return clone;
|
|
}).ToArray();
|
|
|
|
if (arr.Any())
|
|
{
|
|
using (var db = DbContextFactory.GetYLDbContext())
|
|
{
|
|
var userGroup = arr.First().UserGroup ?? string.Empty;
|
|
var ucodes = arr.Select(n => n.ContractCode).ToHashSet();
|
|
var filters = db.volatility.Where(n => n.QuotationDate == date && n.UserGroup == userGroup && ucodes.Contains(n.ContractCode))
|
|
.Select(n => n.ContractCode + "^^" + n.VolType).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
if (filters.Any())
|
|
{
|
|
arr = arr.Where(n => !filters.Contains(n.ContractCode + "^^" + n.VolType)).ToArray();
|
|
}
|
|
db.volatility.AddRange(arr);
|
|
var changes = db.SaveChanges();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger(nameof(SaveMissingVols)).Error(ex);
|
|
}
|
|
finally
|
|
{
|
|
Interlocked.Exchange(ref saveLock, 0);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region----内部处理----
|
|
|
|
//检查请求数据是否符合预期
|
|
private static void CheckRequest(VolatilityRequest request)
|
|
{
|
|
if (request is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(request));
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(request.VolType))
|
|
{
|
|
if (!(request is BatchVolatilityRequest breq))
|
|
{
|
|
throw new ArgumentException("VolType不能为空", nameof(request.VolType));
|
|
}
|
|
else if (breq.VolTypes == null || !breq.VolTypes.Any())
|
|
{
|
|
throw new ArgumentException("VolType不能为空", nameof(request.VolType));
|
|
}
|
|
}
|
|
|
|
if (ConsUserGroup.HasGroup && string.IsNullOrWhiteSpace(request.UserGroup))
|
|
{
|
|
throw new ArgumentException("UserGroup不能为空", nameof(request.UserGroup));
|
|
}
|
|
|
|
if (request.QuotationDate.Year < 1949)
|
|
{
|
|
throw new ArgumentException("QuotationDate取值不正确:" + request.QuotationDate, nameof(request.QuotationDate));
|
|
}
|
|
|
|
request.QuotationDate = request.QuotationDate.Date;
|
|
}
|
|
|
|
//构建查询条件(没有波动率类型时返回null)
|
|
private static Expression<Func<volatility, bool>> BuildPredicate(VolatilityRequest request, DateTime? startDate = null)
|
|
{
|
|
if (!ConsUserGroup.HasGroup)
|
|
{
|
|
request.UserGroup = string.Empty;
|
|
}
|
|
|
|
var volTypes = request.GetVolTypes().Where(n => ConsVolInfos.VolTypes.Contains(n)).ToArray();
|
|
|
|
if (volTypes.Any())
|
|
{
|
|
var predicate = PredicateBuilder.Create<volatility>(v => v.QuotationDate <= request.QuotationDate);
|
|
if (startDate.HasValue)
|
|
{
|
|
predicate.And(v => v.QuotationDate >= startDate.Value);
|
|
}
|
|
return predicate.And(v => v.UserGroup == request.UserGroup && volTypes.Contains(v.VolType));
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
class VolGroupDto
|
|
{
|
|
public string UserGroup { get; set; }
|
|
|
|
public string ContractCode { get; set; }
|
|
|
|
public string VolType { get; set; }
|
|
|
|
public DateTime QuotationDate { get; set; }
|
|
}
|
|
|
|
class VolCopyPara
|
|
{
|
|
public int id { get; set; }
|
|
|
|
public string UnderlyingCode { get; set; }
|
|
|
|
public string SameCode { get; set; }
|
|
}
|
|
|
|
static int saveLock;
|
|
}
|
|
|
|
#region----请求模型类----
|
|
|
|
/// <summary>
|
|
/// 波动率请求基类
|
|
/// </summary>
|
|
public class VolatilityRequest
|
|
{
|
|
public VolatilityRequest()
|
|
{
|
|
|
|
}
|
|
|
|
public VolatilityRequest(VolatilityRequest baseRequest)
|
|
{
|
|
if (baseRequest is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(baseRequest));
|
|
}
|
|
|
|
UserGroup = baseRequest.UserGroup;
|
|
VolType = baseRequest.VolType;
|
|
TradeVolWithBidAsk = baseRequest.TradeVolWithBidAsk;
|
|
QuotationDate = baseRequest.QuotationDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 必须有值
|
|
/// </summary>
|
|
public string UserGroup { get; set; }
|
|
|
|
/// <summary>
|
|
/// 必须有值
|
|
/// </summary>
|
|
public string VolType { get; set; }
|
|
|
|
/// <summary>
|
|
/// 取交易波动率时是否附带"报价Bid"和"报价Ask",默认false
|
|
/// </summary>
|
|
public bool TradeVolWithBidAsk { get; set; }
|
|
|
|
/// <summary>
|
|
/// 必须有值
|
|
/// </summary>
|
|
public DateTime QuotationDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 获取相关波动率
|
|
/// </summary>
|
|
public virtual IEnumerable<string> GetVolTypes()
|
|
{
|
|
if (TradeVolWithBidAsk && !PS.Config.ErpElement.SkewMapVolConstruction && VolType == "交易")
|
|
{
|
|
return ConsVolInfos.TradeVolTypes;
|
|
}
|
|
|
|
return new[] { VolType };
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{VolType}--{TradeVolWithBidAsk}--{QuotationDate:yyyy-MM-dd}--{UserGroup}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 单标的波动率请求
|
|
/// </summary>
|
|
public class SingleVolatilityRequest : VolatilityRequest
|
|
{
|
|
public SingleVolatilityRequest()
|
|
{
|
|
|
|
}
|
|
|
|
public SingleVolatilityRequest(VolatilityRequest baseRequest, string underlyingCode, int? underlyingId = null)
|
|
: base(baseRequest)
|
|
{
|
|
UnderlyingCode = underlyingCode;
|
|
UnderlyingId = underlyingId;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 标的过滤(优先级1)
|
|
/// </summary>
|
|
public string UnderlyingCode { get; set; }
|
|
|
|
/// <summary>
|
|
///标的过滤(优先级2)
|
|
/// </summary>
|
|
public int? UnderlyingId { get; set; }
|
|
|
|
public SingleVolatilityRequest Clone()
|
|
{
|
|
return (SingleVolatilityRequest)MemberwiseClone();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 批量标的波动率请求
|
|
/// </summary>
|
|
public class BatchVolatilityRequest : VolatilityRequest
|
|
{
|
|
/// <summary>
|
|
/// 从这个日期开始查找数据
|
|
/// </summary>
|
|
public DateTime? StartDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 标的过滤,优先级1(如果是有效过滤条件则忽略UnderlyingCodes和VarietyIds)
|
|
/// </summary>
|
|
public IEnumerable<int> UnderlyingIds { get; set; }
|
|
|
|
/// <summary>
|
|
/// 标的过滤,优先级2(如果是有效过滤条件则忽略VarietyIds)
|
|
/// </summary>
|
|
public IEnumerable<string> UnderlyingCodes { get; set; }
|
|
|
|
/// <summary>
|
|
/// 品种过滤(和标的过滤取并集)
|
|
/// </summary>
|
|
public IEnumerable<int> VarietyIds { get; set; }
|
|
|
|
/// <summary>
|
|
/// 波动率类型过滤(如果存在则忽略VolType参数优先使用这个)
|
|
/// </summary>
|
|
public IEnumerable<string> VolTypes { get; set; }
|
|
|
|
public override IEnumerable<string> GetVolTypes()
|
|
{
|
|
return VolTypes != null && VolTypes.Any() ? VolTypes : base.GetVolTypes();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取唯一key(MD5算法)
|
|
/// </summary>
|
|
public string GetUniqueKey()
|
|
{
|
|
var sb = new StringBuilder(500);
|
|
sb.Append(UserGroup).Append('^')
|
|
.Append(VolType).Append('^')
|
|
.Append(TradeVolWithBidAsk).Append('^')
|
|
.Append(QuotationDate.ToString("yyyyMMdd")).Append('^');
|
|
|
|
if (UnderlyingIds != null)
|
|
{
|
|
sb.Append(string.Join(",", UnderlyingIds)).Append('^');
|
|
}
|
|
|
|
if (UnderlyingCodes != null)
|
|
{
|
|
sb.Append(string.Join(",", UnderlyingCodes)).Append('^');
|
|
}
|
|
|
|
if (VarietyIds != null)
|
|
{
|
|
sb.Append(string.Join(",", VarietyIds)).Append('^');
|
|
}
|
|
|
|
return HashHelper.MD5(sb.ToString());
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|