Files
zszq-trs/YLErpDAL/Modules/UnderlyingModule/UnderlyingSelectService.cs
T
2024-05-09 14:06:26 +08:00

513 lines
17 KiB
C#

using Qdp.Pricing.Library.Common.Products.Rates;
using System.Linq.Expressions;
using System.Runtime.Intrinsics.Arm;
using YLErp.BLL;
using YLErp.Modules.DataProviderModule;
namespace YLErp.Modules.UnderlyingModule
{
/// <summary>
/// 标的选项服务
/// </summary>
public class UnderlyingSelectService : YLBaseService
{
public UnderlyingSelectService(YLBaseService baseService) : base(baseService)
{
}
public UnderlyingSelectService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 获取标的选项
/// </summary>
public IEnumerable<UnderlyingSelectItem> GetSelectItems(UnderlyingSelectRequest req)
{
if (req.MaxShowLength < 1) req.MaxShowLength = 1;
IEnumerable<UnderlyingSelectItem> datas = null;
var predicate = BuildPredicate(req);
var query = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().Where(predicate).Take(req.MaxShowLength).ToList();
if (req.UseForTrading)
{
List<string> Codes = null;
var useWhiteCode = req.BlackLimit > 0 && new StockBlackWhiteService(UserInfo).GetStockBlackWhiteList((Configuration.Enums.LimitRangeEnum)req.BlackLimit, out Codes);
UnderlyingSelectItem2 convert(underlying_manager n)
{
var item = new UnderlyingSelectItem2
{
id = n.id,
Code = n.UnderlyingCode,
Name = n.CalcTypeIsStock() && !n.IsSynthetic() ? n.UnderlyingName : "",
VarietyId = n.UnderlyingTypeId,
MaturityDate = n.CalcTypeIsStock() || n.IsCommoditySpot() || !n.MaturityDate.HasValue ? "" : n.MaturityDate.Value.ToString("yyyy-MM-dd"),
CountRatio = n.CountRatio,
ContractSize = n.ContractSize,
Price = n.IsBasket() ? DataCacheProvider.GetUnderlyingDataSource().GetPrice(n.UnderlyingCode) : n.Price ?? 0,
IsSynthetic = n.IsSynthetic(),
IsBasket = n.IsBasket(),
InstrumentType = n.UnderlyingInstrumentType,
DividendRate = n.DividendRate,
QuoteUnitString = n.QuoteUnitString,
BlackWhiteState = req.BlackLimit == 0 ? 0 : useWhiteCode ? 1 : 2,
Disallow = req.BlackLimit != 0 && n.IsStock() && !n.IsSynthetic() && !n.IsBasket() && Codes != null && useWhiteCode == Codes.Contains(n.UnderlyingCode),
UpDownLimit = n.UpDownLimit,
PrevClosePrice = n.PrevClosePrice
};
if (n.IsBond()&&!string.IsNullOrEmpty(n.ExJson))
{
var bond = JsonHelper.Deserialize<UnderlyingBond>(n.ExJson);
item.Name = n.UnderlyingName;
item.UnderlyingFullName=bond.UnderlyingFullName;
item.UnderlyingIssuer = bond.UnderlyingIssuer;
item.IssueSize = bond.IssueSize;
}
return item;
}
datas = query.Select(convert).Take(req.MaxShowLength).ToArray();
Variety variety = null;
foreach (UnderlyingSelectItem2 item in datas)
{
if (string.IsNullOrWhiteSpace(item.UpDownLimit))
{
if (variety != null && variety.id == item.VarietyId)
{
item.UpDownLimit = variety.UpLimit;
}
else
{
variety = DataCacheProvider.GetVarietyDataSource().GetData(item.VarietyId);
if (variety != null)
{
item.UpDownLimit = variety.UpLimit;
}
}
}
if (Codes == null)
{
continue;
}
if (item.IsSynthetic)
{
var underlyingInfo = DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(item.Code);
item.Disallow = underlyingInfo.GetUnderlyingCodes().Any(O =>
{
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(O);
return req.BlackLimit != 0 && um.IsStock() && !um.IsSynthetic() && !um.IsBasket() && Codes != null && useWhiteCode == Codes.Contains(O);
});
}
if (item.IsBasket)
{
var underlyingInfo = DataCacheProvider.GetUnderlyingDataSource().GetData(item.Code);
var data = JsonHelper.Deserialize<List<BasketUnderlyingItem>>(underlyingInfo.SubData);
item.Disallow = data.Any(O =>
{
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(O.code);
return um == null ? true : req.BlackLimit != 0 && um.IsStock() && !um.IsSynthetic() && !um.IsBasket() && Codes != null && useWhiteCode == Codes.Contains(O.code);
});
}
}
}
else
{
var query2 = query.Select(n => new UnderlyingSelectItem
{
id = n.id,
Code = n.UnderlyingCode,
Name = ConsGlobal.InstrumentType.CalcTypeIsStock(n.UnderlyingInstrumentType) ? n.UnderlyingName : "",
VarietyId = n.UnderlyingTypeId
}).Take(req.MaxShowLength);
datas = query2.ToArray();
}
if (req.MustRetOne && !datas.Any())
{
req.MustRetOne = false;
req.MaxShowLength = 1;
req.FilterCode = null;
return GetSelectItems(req);
}
return datas;
}
//创建标的查询预测
private Expression<Func<underlying_manager, bool>> BuildPredicate(UnderlyingSelectRequest req)
{
if (req.UnderlyingId > 0)
{
return PredicateBuilder.Create<underlying_manager>(n => n.id == req.UnderlyingId);
}
if (req.ExcatCodeFilter)
{
return string.IsNullOrWhiteSpace(req.FilterCode)
? PredicateBuilder.False<underlying_manager>()
: PredicateBuilder.Create<underlying_manager>(n => n.UnderlyingCode==req.FilterCode);
}
var predicate = PredicateBuilder.True<underlying_manager>();
//标的品种
IEnumerable<int> varietyids = null;
if (req.ClientId > 0)
{
varietyids = TradeRightProvider.GetClientVarietyIds(req.ClientId);
}
if (req.UseRightFilter)
{
var varietyids2 = TradeRightProvider.GetUserVarietyIds(UserId);
varietyids = varietyids == null ? varietyids2 : varietyids.Concat(varietyids2);
}
if (varietyids != null)
{
if (!varietyids.Any(n => n > 0))
{
return PredicateBuilder.False<underlying_manager>();
}
predicate = predicate.And(n => varietyids.Contains(n.UnderlyingTypeId));
}
//是否启用
if (req.CheckLaunch)
{
predicate = predicate.And(n => n.LaunchState == "1");
}
//资产类型
List<string> instTypes = null;
if (req.InstrumentTypes != null && req.InstrumentTypes.Any(n => !string.IsNullOrEmpty(n)))
{
instTypes = req.InstrumentTypes.Where(n => !string.IsNullOrEmpty(n)).ToList();
}
if (!string.IsNullOrWhiteSpace(req.Scenario))
{
if (instTypes == null)
{
instTypes = new List<string>();
}
if (req.Scenario == "期权交易")
{
instTypes.AddRange(ConsGlobal.InstrumentType.GetFutureTypes());
instTypes.AddRange(ConsGlobal.InstrumentType.GetSpotTypes());
instTypes.AddRange(ConsGlobal.InstrumentType.GetStockTypes());
}
}
if (instTypes != null)
{
if (!instTypes.Any())
{
return PredicateBuilder.False<underlying_manager>();
}
predicate = predicate.And(n => instTypes.Contains(n.UnderlyingInstrumentType));
}
//组合标的
if (req.OnlySynthetic)
{
predicate = predicate.And(n => n.CommodityCode == "组合标的");
}
else if (!req.IncludeSynthetic)
{
predicate = predicate.And(n => n.CommodityCode != "组合标的");
}
//篮子标的
if (req.OnlyBasket)
{
predicate = predicate.And(n => n.CommodityCode == "篮子标的");
}
else if (!req.IncludeBasket)
{
predicate = predicate.And(n => n.CommodityCode != "篮子标的");
}
//过期标的
if (req.MinMaturityDate.HasValue)
{
predicate = predicate.And(n => n.UnderlyingInstrumentType != ConsGlobal.InstrumentType.CommodityFutures || n.MaturityDate >= req.MinMaturityDate.Value);
}
else if (!req.IncludeMatured)
{
var valueDate = valuedateBLL.ValueDate;
predicate = predicate.And(n => n.UnderlyingInstrumentType != ConsGlobal.InstrumentType.CommodityFutures || n.MaturityDate >= valueDate);
}
//标的代码
var filterCode = req.FilterCode.TrimToNull();
if (filterCode != null)
{
predicate = predicate.And(n => n.UnderlyingCode.StartsWith(filterCode));
if (filterCode.Length >= 4 && req.MaxShowLength > 10)
{
req.MaxShowLength = 10;
}
}
else if (req.VarietyId != 0) //品种ID
{
predicate = predicate.And(n => n.UnderlyingTypeId == req.VarietyId);
}
return predicate;
}
}
/// <summary>
/// 标的选择请求Model
/// </summary>
public class UnderlyingSelectRequest
{
/// <summary>
/// 最大显示条目数(默认20)
/// </summary>
public int MaxShowLength { get; set; } = 20;
/// <summary>
/// 客户ID(用于客户授信时配置的限制交易品种过滤)
/// </summary>
public int ClientId { get; set; }
/// <summary>
/// 使用角色权限过滤(默认false)
/// </summary>
public bool UseRightFilter { get; set; }
/// <summary>
/// 标的资产类型
/// </summary>
public IEnumerable<string> InstrumentTypes { get; set; }
/// <summary>
/// 包括组合标的(默认false)
/// </summary>
public bool IncludeSynthetic { get; set; }
/// <summary>
/// 只取组合标的(默认false)
/// </summary>
public bool OnlySynthetic { get; set; }
/// <summary>
/// 包括篮子标的(默认false)
/// </summary>
public bool IncludeBasket { get; set; }
/// <summary>
/// 只取篮子标的(默认false)
/// </summary>
public bool OnlyBasket { get; set; }
/// <summary>
/// 检查标的启用状态(默认true)
/// </summary>
public bool CheckLaunch { get; set; } = true;
//--------特殊处理------------------------------
/// <summary>
/// 使用拼音过滤
/// </summary>
public bool UsePinYinFilter { get; set; }
/// <summary>
/// 包括已过期标的(默认false)()
/// </summary>
public bool IncludeMatured { get; set; }
/// <summary>
/// 代码过滤(默认null)
/// </summary>
public string FilterCode { get; set; }
/// <summary>
/// 品种ID(只在FilterCode为空时时所用)
/// </summary>
public int VarietyId { get; set; }
/// <summary>
/// 只使用FilterCode精确匹配
/// </summary>
public bool ExcatCodeFilter { get; set; }
/// <summary>
/// 必须返回一个标的
/// </summary>
public bool MustRetOne { get; set; }
//--------数据用途------------------------------
/// <summary>
/// 用于交易
/// </summary>
public bool UseForTrading { get; set; }
/// <summary>
/// 大于0时用于区分互换还是场外
/// </summary>
public int BlackLimit { get; set; }
//--------标的ID------------------------------
/// <summary>
/// 标的ID
/// </summary>
public int UnderlyingId { get; set; }
/// <summary>
/// 使用场景
/// </summary>
public string Scenario { get; set; }
//--------到期日限定------------------------------
/// <summary>
/// 最小到期日
/// </summary>
public DateTime? MinMaturityDate { get; set; }
public override string ToString()
{
return $"{FilterCode}";
}
}
/// <summary>
/// 标的选项
/// </summary>
public class UnderlyingSelectItem
{
/// <summary>
/// 标的ID
/// </summary>
public int id { get; set; }
/// <summary>
/// 标的名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 标的代码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 品种ID
/// </summary>
public int VarietyId { get; set; }
public override string ToString()
{
return $"{id}--{Name}--{Code}--{VarietyId}";
}
}
/// <summary>
/// 标的选项
/// </summary>
public class UnderlyingSelectItem2 : UnderlyingSelectItem
{
/// <summary>
/// 是否组合标的
/// </summary>
public bool IsSynthetic { get; set; }
/// <summary>
/// 是否属于篮子标的
/// </summary>
public bool IsBasket { get; set; }
/// <summary>
/// 资产类型
/// </summary>
public string InstrumentType { get; set; }
/// <summary>
/// 到期日
/// </summary>
public string MaturityDate { get; set; }
/// <summary>
/// 份额和数量的乘积因子
/// </summary>
public int CountRatio { get; set; } = 1;
/// <summary>
/// 合约乘数
/// </summary>
public double ContractSize { get; set; } = 1;
/// <summary>
/// 最新价格
/// </summary>
public double Price { get; set; }
/// <summary>
/// 分红率
/// </summary>
public double? DividendRate { get; set; }
/// <summary>
/// 交易单位
/// </summary>
public string QuoteUnitString { get; set; }
/// <summary>
/// 当前黑白名单模式
/// <para>1:黑名单</para>
/// <para>2:白名单</para>
/// </summary>
public int BlackWhiteState { get; set; }
/// <summary>
/// 允许选择
/// </summary>
public bool Disallow { get; set; }
/// <summary>
/// 涨跌停幅度
/// </summary>
public string UpDownLimit { get; set; }
/// <summary>
/// 涨停价跌停价
/// </summary>
public double? PrevClosePrice { get; set; }
/// <summary>
/// 债券全名
/// </summary>
public string UnderlyingFullName { get; set; }
/// <summary>
/// 标的发行量(亿)
/// </summary>
public decimal? IssueSize { get; set; }
/// <summary>
/// 标的证券发行人
/// </summary>
public string UnderlyingIssuer { get; set; }
}
}