323 lines
12 KiB
C#
323 lines
12 KiB
C#
using Newtonsoft.Json;
|
|
using System.Data;
|
|
using YLErp.BLL;
|
|
|
|
namespace YLErp.Modules.UnderlyingModule
|
|
{
|
|
/// <summary>
|
|
/// 篮子标的信息管理服务
|
|
/// </summary>
|
|
public class BasketUnderlyingService : YLBaseService
|
|
{
|
|
public BasketUnderlyingService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
}
|
|
|
|
public BasketUnderlyingService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 组合标的导入xlsx数据
|
|
/// </summary>
|
|
public BasketUnderlyingDto ImportBasketDatasFromExcel(Stream stream)
|
|
{
|
|
var result = new BasketUnderlyingDto();
|
|
try
|
|
{
|
|
//当前编码支持ansi和utf with bom
|
|
|
|
var ds = Office.ExcelHelper.ReadExcelAsDataSet(stream);
|
|
|
|
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 1)
|
|
{
|
|
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
|
|
}
|
|
|
|
var table = ds.Tables[0];
|
|
List<BasketUnderlyingItem> list = new List<BasketUnderlyingItem>();
|
|
if (table.Rows.Count < 1)
|
|
{
|
|
throw new ServiceException("导入数据不能为空!");
|
|
}
|
|
var useWhiteCode = new StockBlackWhiteService(UserInfo).GetStockBlackWhiteList(Configuration.Enums.LimitRangeEnum.Swap, out var Codes);
|
|
foreach (DataRow row in table.Rows)
|
|
{
|
|
if (row.IsNull("标的代码") || row.IsNull("标的权重"))
|
|
{
|
|
throw new ServiceException("导入标的代码或标的权重不能为空!");
|
|
}
|
|
double price = 0;
|
|
BasketUnderlyingItem importModel = new BasketUnderlyingItem();
|
|
importModel.code = (string)row["标的代码"];
|
|
double.TryParse((row["标的权重"]?.ToString() ?? ""), out var weight);
|
|
importModel.weight = weight;
|
|
double.TryParse((row["标的份额"]?.ToString() ?? ""), out var notional);
|
|
importModel.notional = notional;
|
|
DataCacheProvider.GetUnderlyingDataSource().TryGetPrice(importModel.code, out price);
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(importModel.code);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException("标的代码不存在: " + importModel.code);
|
|
}
|
|
if (ConsGlobal.InstrumentType.IsStock(underlying.UnderlyingInstrumentType) && Codes != null && useWhiteCode == Codes.Contains(importModel.code))
|
|
{
|
|
throw new ServiceException($"标的代码:{importModel.code} {(useWhiteCode ? "存在于黑名单中" : "不在白名单中")}");
|
|
}
|
|
importModel.Price = price;
|
|
list.Add(importModel);
|
|
}
|
|
result.Items = list;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw (ex.InnerException as ServiceException) ?? ex;
|
|
}
|
|
|
|
|
|
if (!result.Items.Any())
|
|
{
|
|
throw new ServiceException("没有可导入的数据");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 保存篮子标的数据
|
|
/// </summary>
|
|
public int SaveBasketUnderlying(BasketUnderlyingDto model)
|
|
{
|
|
if (model is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(model));
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(model.UnderlyingCode))
|
|
{
|
|
throw new ServiceException("别名不能为空");
|
|
}
|
|
|
|
if (DbContext.underlying_manager.Any(n => n.UnderlyingCode == model.UnderlyingCode))
|
|
{
|
|
throw new ServiceException("系统中已有重名的组合标的");
|
|
}
|
|
|
|
if (model.Items == null || !model.Items.Any())
|
|
{
|
|
throw new ServiceException("篮子标的列表没有任何数据");
|
|
}
|
|
|
|
if (model.Items.Any(n => string.IsNullOrWhiteSpace(n.code)))
|
|
{
|
|
throw new ServiceException("篮子标的列表中不应存在空白标的");
|
|
}
|
|
|
|
var isAddNew = model.id <= 0;
|
|
|
|
//----------------------------------
|
|
// 存入underlying_manager表
|
|
//----------------------------------
|
|
|
|
var variety = UnderlyingHelper.GetBasketVariety();
|
|
|
|
//----------------------------------
|
|
// 2020/5/14 获取组合标的的第一个标的
|
|
//----------------------------------
|
|
|
|
var underlyingCode1 = model.Items.First().code;
|
|
var underlying1 = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode1);
|
|
if (underlying1 == null)
|
|
{
|
|
throw new ServiceException("标的数据未找到:" + underlyingCode1);
|
|
}
|
|
|
|
// 篮子标的到期日
|
|
DateTime? MaturityDate = DateTime.MaxValue;
|
|
foreach (var item in model.Items)
|
|
{
|
|
DateTime? Date = DataCacheProvider.GetUnderlyingDataSource().GetData(item.code).MaturityDate;
|
|
MaturityDate = Date < MaturityDate ? Date : MaturityDate;
|
|
item.Price = null;
|
|
}
|
|
|
|
//----------------------------------
|
|
// 新增variety 如果没有该品种 则新增
|
|
//-------------
|
|
if (variety.id == 0)
|
|
{
|
|
variety = new Variety()
|
|
{
|
|
VarietyCode = "篮子标的",
|
|
VarietyName = "篮子标的",
|
|
OptId = model.OptId,
|
|
OptName = model.OptName,
|
|
OptDate = model.OptDate,
|
|
TradingMarketId = 0,
|
|
TradeUnit = "100股/手",
|
|
QuoteUnit = "元(人民币)/股",
|
|
DeliveryType = "",
|
|
HasNightMarket = false,
|
|
ShortName = "篮子标的",
|
|
CommissionType = "固定",
|
|
CloseTodayCommissionType = "固定",
|
|
//UnderlyingInstrumentType = "Stock",
|
|
VolatilityRate = "",
|
|
VolatilityAdjust = 0
|
|
};
|
|
DbContext.variety.Add(variety);
|
|
DbContext.SaveChanges();
|
|
}
|
|
|
|
underlying_manager underlying;
|
|
|
|
if (isAddNew)
|
|
{
|
|
underlying = new underlying_manager
|
|
{
|
|
UnderlyingCode = model.UnderlyingCode,
|
|
UnderlyingType = variety.VarietyName,
|
|
UnderlyingTypeId = variety.id,
|
|
UnderlyingName = model.UnderlyingCode,
|
|
CommodityCode = variety.VarietyCode,
|
|
OpenDate = DateTime.Today
|
|
};
|
|
DbContext.underlying_manager.Add(underlying);
|
|
}
|
|
else
|
|
{
|
|
underlying = DbContext.underlying_manager.FirstOrDefault(u => u.UnderlyingCode == model.UnderlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException("数据不存在:" + model.UnderlyingCode);
|
|
}
|
|
underlying.LaunchState = "1";
|
|
underlying.LastUpdateTime = OptDate;
|
|
}
|
|
|
|
underlying.SubData = JsonHelper.Stringify(model.Items);
|
|
|
|
underlying.OptId = UserId;
|
|
underlying.OptName = UserName;
|
|
underlying.OptDate = OptDate;
|
|
|
|
underlying.Price = 0;
|
|
|
|
underlying.MaturityDate = MaturityDate == DateTime.MaxValue ? null : MaturityDate;
|
|
underlying.UnderlyingState = "Live";
|
|
underlying.UnderlyingStatus = "正常运行";
|
|
|
|
underlying.MarketCode = underlying1.MarketCode;
|
|
underlying.UnderlyingInstrumentType = underlying1.UnderlyingInstrumentType;
|
|
|
|
//----------------------------------
|
|
//2020/5/14 使用组合标的的第一个标的为新添加的字段赋值
|
|
//----------------------------------
|
|
underlying.TradeUnit = underlying1.TradeUnit;
|
|
underlying.QuoteUnit = underlying1.QuoteUnit;
|
|
underlying.MarketName = underlying1.MarketName;
|
|
|
|
if (string.IsNullOrEmpty(underlying.TradeUnit))
|
|
{
|
|
underlying.TradeUnit = "份";
|
|
}
|
|
|
|
DbContext.SaveChanges();
|
|
//----------------------------------
|
|
// 新增underlying_parameter
|
|
//----------------------------------
|
|
|
|
var underlyingParams = DbContext.underlying_parameter.Where(u => u.UnderlyingId == underlying.id).ToList();
|
|
|
|
//如果没有报价参数,则新增
|
|
if (underlyingParams.Count == 0)
|
|
{
|
|
underlying_parameter.defaultQuoteTypes.ForEach(t =>
|
|
{
|
|
var up = new underlying_parameter()
|
|
{
|
|
NoRiskRate = valuedateBLL.SystemDate.RiskFreeRate * 0.01,
|
|
Price = 0,
|
|
Gamma = 0,
|
|
Rho = 0,
|
|
Vega = 0,
|
|
Theta = 0,
|
|
Delta = 0,
|
|
UnderlyingId = underlying.id,
|
|
Type = t,
|
|
OptDate = DateTime.Now,
|
|
OptId = model.OptId,
|
|
OptName = model.OptName
|
|
};
|
|
DbContext.underlying_parameter.Add(up);
|
|
underlyingParams.Add(up);
|
|
});
|
|
}
|
|
|
|
//最后调用保存以保证事物完整性
|
|
return DbContext.SaveChanges();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 篮子标的查看
|
|
/// </summary>
|
|
public BasketUnderlyingDto GetBasketUnderlyingByName(string name)
|
|
{
|
|
|
|
var query = from u in DbContext.underlying_manager.AsEnumerable()
|
|
where u.UnderlyingCode == name
|
|
select new BasketUnderlyingDto
|
|
{
|
|
Items = JsonConvert.DeserializeObject<List<BasketUnderlyingItem>>(u.SubData),
|
|
};
|
|
|
|
var res = query.FirstOrDefault();
|
|
|
|
double price = 0;
|
|
|
|
foreach (var item in res.Items)
|
|
{
|
|
DataCacheProvider.GetUnderlyingDataSource().TryGetPrice(item.code, out price);
|
|
item.Price = price;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class BasketUnderlyingDto : UnderlyingManagerDto
|
|
{
|
|
/// <summary>
|
|
/// 篮子标的项目
|
|
/// </summary>
|
|
public IEnumerable<BasketUnderlyingItem> Items { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 篮子标的合成项
|
|
/// </summary>
|
|
public class BasketUnderlyingItem
|
|
{
|
|
public double? Price { get; set; }
|
|
|
|
/// <summary>
|
|
/// 权重
|
|
/// </summary>
|
|
public double weight { get; set; }
|
|
|
|
/// <summary>
|
|
/// 份额
|
|
/// </summary>
|
|
public double notional { get; set; }
|
|
|
|
/// <summary>
|
|
/// 标的代码
|
|
/// </summary>
|
|
public string code { get; set; }
|
|
}
|
|
}
|