513 lines
17 KiB
C#
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; }
|
|
}
|
|
}
|