从山证v2.3.0拷贝

This commit is contained in:
吴方海
2024-05-09 14:06:26 +08:00
parent 566ff33259
commit f9d8a256a6
4471 changed files with 1203456 additions and 9 deletions
@@ -0,0 +1,26 @@
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 批量标的波动率请求(为了兼容海通API)
/// </summary>
public class BatchVolatilityRequest2 : BatchVolatilityRequest
{
/// <summary>
/// QuotationDate别名,海通API使用了这个,故保留
/// </summary>
public DateTime SystemDate
{
get { return QuotationDate; }
set { QuotationDate = value; }
}
/// <summary>
/// QuotationDate别名,海通API使用了这个,故保留
/// </summary>
public DateTime ValueDate
{
get { return QuotationDate; }
set { QuotationDate = value; }
}
}
}
@@ -0,0 +1,28 @@
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 批量标的波动率请求V2
/// </summary>
public class UnderlyingVolQueryApiRequestV2
{
/// <summary>
/// 标的过滤
/// </summary>
public IEnumerable<string> UnderlyingCodes { get; set; }
/// <summary>
/// 必须有值,查看波动率曲面的日期
/// </summary>
public DateTime ValueDate { get; set; }
/// <summary>
/// 必须有值,波动率类型
/// </summary>
public string[] VolTypes { get; set; }
/// <summary>
/// 用户组
/// </summary>
public string UserGroup { get; set; }
}
}
@@ -0,0 +1,40 @@
using YLErp.Models;
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 曲面波动率提供
/// </summary>
public class UnderlyingVolQueryApiResultV2
{
/// <summary>
/// 波动率类型
/// </summary>
public string VolType { get; set; }
/// <summary>
/// 波动率报价日期
/// </summary>
public string QuotationDate
{
get => InnerQuotationDate.ToString("yyyy-MM-dd");
set { }
}
/// <summary>
/// 标的代码
/// </summary>
public string UnderlyingCode { get; set; }
/// <summary>
///
/// </summary>
public List<SingleVol> VolTable { get; set; }
//--------内部类----------------
internal string VolTableJson { get; set; }
internal DateTime InnerQuotationDate { get; set; }
}
}
@@ -0,0 +1,50 @@
using YLErp.Models;
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 标的波动率保存请求V2
/// </summary>
public class UnderlyingVolSaveApiRequestV2
{
/// <summary>
/// 合约代码
/// </summary>
public string ContractCode { set; get; }
/// <summary>
/// 波动率类型
/// </summary>
public string VolType { get; set; }
/// <summary>
/// 报价日期
/// </summary>
public DateTime ValueDate { set; get; }
/// <summary>
/// 报价日期
/// </summary>
public DateTime QuotationDate { set => ValueDate = value; get => ValueDate; }
/// <summary>
/// 插值方法
/// </summary>
public string InterpolationMethod { get; set; }
/// <summary>
/// 波动率表格
/// </summary>
public List<SingleVol> VolTable { set; get; }
/// <summary>
/// 所属用户组
/// </summary>
public string UserGroup { get; set; }
/// <summary>
/// 如果传入的合约代码为连续合约则覆盖同合约其它标的
/// </summary>
public bool OverridByMainCode { get; set; }
}
}
@@ -0,0 +1,72 @@
using YLErp.BLL;
using YLErp.Models;
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 曲面波动率提供(用于API服务)
/// </summary>
public class UnderlyingVolService : YLBaseService
{
public UnderlyingVolService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// API获取波动率
/// </summary>
public List<UnderlyingVol> GetUnderlyingVolSurfaces(BatchVolatilityRequest2 request)
{
request.TradeVolWithBidAsk = true;
var vols = new VolatilityQueryService(this).GetVolatilities(request, false);
if (request.VolType != "交易")
{
return vols.Select(x => new UnderlyingVol()
{
VolTable = x.VolTable,
UnderlyingCode = x.ContractCode
}).ToList();
}
return vols.ToLookup(n => n.ContractCode).Select(n => new UnderlyingVol
{
UnderlyingCode = n.Key,
VolTable = n.FirstOrDefault(y => y.VolType == "交易")?.VolTable,
VolTableBid = n.FirstOrDefault(y => y.VolType == "报价Bid")?.VolTable,
VolTableAsk = n.FirstOrDefault(y => y.VolType == "报价Ask")?.VolTable
}).ToList();
}
/// <summary>
/// API保存波动率
/// </summary>
public volatility SaveVolatility(volatility vol)
{
var targetUnderlying = underlying_managerBLL.GetByCode(vol.ContractCode);
if (targetUnderlying != null)
{
vol.UnderlyingId = targetUnderlying.id;
vol.ContractCode = targetUnderlying.UnderlyingCode;
}
if (string.IsNullOrEmpty(vol.Data))
{
throw new ServiceException("缺少VolTable");
}
var vols = new VolatilitySaveService(this).SaveVol(vol);
return vols.FirstOrDefault();
}
public class UnderlyingVol
{
public string UnderlyingCode { get; set; }
public List<SingleVol> VolTable { get; set; }
public List<SingleVol> VolTableBid { get; set; }
public List<SingleVol> VolTableAsk { get; set; }
}
}
}
@@ -0,0 +1,227 @@
using Newtonsoft.Json;
using YLErp.DBModels.Consts;
using YLErp.Models;
using YLErp.QdpModule.Constants;
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 曲面波动率提供(用于API服务)
/// </summary>
public partial class UnderlyingVolServiceV2 : YLBaseService
{
public UnderlyingVolServiceV2(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// API获取波动率
/// </summary>
public IEnumerable<UnderlyingVolQueryApiResultV2> GetVolSurfaces(UnderlyingVolQueryApiRequestV2 request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.VolTypes == null || !request.VolTypes.Any())
{
throw new ArgumentException("VolTypes不能为空", nameof(request.VolTypes));
}
if (request.UnderlyingCodes == null || !request.UnderlyingCodes.Any())
{
throw new ArgumentException("UnderlyingCodes不能为空", nameof(request.UnderlyingCodes));
}
if (!ConsUserGroup.HasGroup)
{
request.UserGroup = string.Empty;
}
else if (string.IsNullOrWhiteSpace(request.UserGroup))
{
throw new ArgumentException("UserGroup不能为空", nameof(request.UserGroup));
}
request.ValueDate = request.ValueDate.Date;
if (request.ValueDate.Year < 1949)
{
throw new ArgumentException("ValueDate填写不正确:" + request.ValueDate, nameof(request.ValueDate));
}
//数据量小的表尽量靠前
var groupQuery = from v in DbContext.volatility
where v.QuotationDate <= request.ValueDate
&& request.VolTypes.Contains(v.VolType)
&& request.UnderlyingCodes.Contains(v.ContractCode)
&& v.UserGroup == request.UserGroup
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 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 new UnderlyingVolQueryApiResultV2
{
VolType = v.VolType,
InnerQuotationDate = v.QuotationDate,
UnderlyingCode = v.ContractCode,
VolTableJson = v.Data
};
var vols = volQuery.ToArray();
foreach (var item in vols)
{
if (!string.IsNullOrWhiteSpace(item.VolTableJson))
{
item.VolTable = JsonConvert.DeserializeObject<List<SingleVol>>(item.VolTableJson);
}
}
return vols;
}
/// <summary>
/// API保存波动率
/// </summary>
public volatility SaveVolSurface(UnderlyingVolSaveApiRequestV2 request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(request.ContractCode))
{
throw new ServiceException("标的代码 必须填写");
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(request.ContractCode);
if (underlying == null)
{
throw new ServiceException("标的信息未存在:" + request.ContractCode);
}
if (string.IsNullOrEmpty(request.VolType))
{
throw new ServiceException("波动率类型 必须填写");
}
request.ValueDate = request.ValueDate.Date;
if (request.ValueDate.Year < 1949)
{
throw new ServiceException("ValueDate填写不正确:" + request.ValueDate);
}
if (request.VolTable?.Any() != true)
{
throw new ServiceException("缺少VolTable");
}
if (string.IsNullOrEmpty(request.InterpolationMethod))
{
request.InterpolationMethod = ConsVolInfos.defInterpolationMethod;
}
if (!ConsUserGroup.HasGroup)
{
request.UserGroup = string.Empty;
}
else if (string.IsNullOrWhiteSpace(request.UserGroup))
{
throw new ArgumentException("UserGroup不能为空", nameof(request.UserGroup));
}
volatility retVol = null;
var underlyingList = new List<InnerUnderlying> {
new InnerUnderlying{ UnderlyingId = underlying.id,UnderlyingCode = underlying.UnderlyingCode}
};
//波动率上传 以连续合约 覆盖所有标的的 麻烦尽快实现
if (request.OverridByMainCode)
{
int underlyingTypeId = 0;
if (System.Text.RegularExpressions.Regex.IsMatch(request.ContractCode, "^[a-zA-Z]+00$"))
{
var un = DataCacheProvider.GetUnderlyingDataSource().GetData(request.ContractCode);
if (un?.IsFutures() == true && un.UnderlyingTypeId > 0)
{
underlyingTypeId = un.UnderlyingTypeId;
}
}
if (underlyingTypeId > 0)
{
var query = from un in DbContext.underlying_manager
where un.UnderlyingTypeId == underlyingTypeId
&& (un.MaturityDate >= request.QuotationDate)
&& un.UnderlyingCode != request.ContractCode
select new InnerUnderlying
{
UnderlyingId = un.id,
UnderlyingCode = un.UnderlyingCode
};
underlyingList.AddRange(query.ToArray());
}
}
foreach (var un in underlyingList)
{
var dbVol = DbContext.volatility.FirstOrDefault(n => n.QuotationDate == request.ValueDate
&& n.ContractCode == un.UnderlyingCode && n.VolType == request.VolType && n.UserGroup == request.UserGroup);
if (dbVol == null)
{
dbVol = new volatility
{
UnderlyingId = un.UnderlyingId,
ContractCode = un.UnderlyingCode,
VolType = request.VolType,
UserGroup = request.UserGroup,
QuotationDate = request.ValueDate,
VolSurfaceMode = ConsVolInfos.defVolMode
};
DbContext.volatility.Add(dbVol);
}
dbVol.SetOpt(OptUser);
dbVol.SetData(request.VolTable);
dbVol.InterpolationMethod = request.InterpolationMethod;
if (retVol == null)
{
retVol = dbVol;
}
}
DbContext.SaveChanges();
return retVol;
}
class InnerUnderlying
{
public int UnderlyingId { get; set; }
public string UnderlyingCode { get; set; }
}
}
}