refactor(dividend): 优化除权除息计算逻辑并改进数据类型精度
- 将除权除息相关数值字段从 double 类型改为 decimal 类型以提高精度 - 重构了红利比率计算方法 GetRatio,新增 GetRatioDecimal 方法使用 decimal 计算 - 修改价格和持仓数量计算逻辑,统一使用 decimal 进行高精度运算 - 更新数据库查询逻辑,将篮子标的判断从 IsBasket() 方法改为 CommodityCode 条件 - 优化 AddDividendInfos 方法中的批量处理逻辑,增加业务键冲突检测 - 添加数据源标识字段 DataSource 和来源更新时间字段 SourceUpdatedAt - 新增 FindExDividendByBusinessKey 和 MergeNonZeroDividendValues 辅助方法 - 更新结算服务中除权除息信息的获取方式,使用字典查找替代 LINQ JOIN - 修复前端保存除权信息时的响应处理逻辑 - 为基金类型也开放除权功能,不仅限于股票类型 - 添加单元测试验证篮子标的查询翻译逻辑的正确性
This commit is contained in:
@@ -44,9 +44,6 @@ namespace YLErp.Modules.EodModule
|
||||
on new { eod.BookId, eod.TradeType, eod.PositionType, eod.UnderlyingCode, ExchangeOptionCode = eod.ExchangeOptionCode ?? string.Empty }
|
||||
equals new { bod.BookId, bod.TradeType, bod.PositionType, bod.UnderlyingCode, ExchangeOptionCode = bod.ExchangeOptionCode ?? string.Empty } into t_bod
|
||||
from bod in t_bod.DefaultIfEmpty()
|
||||
join dividend in DbContext.ex_dividend_info.Where(O => O.ExDividendDate == settleDate && O.ValidStatus)
|
||||
on eod.UnderlyingCode equals dividend.UnderlyingCode into t_dividend
|
||||
from dividend in t_dividend.DefaultIfEmpty()
|
||||
select new
|
||||
{
|
||||
eod,
|
||||
@@ -55,24 +52,25 @@ namespace YLErp.Modules.EodModule
|
||||
bod.Amount,
|
||||
bod.Cost,
|
||||
//bod.AveragePrice
|
||||
},
|
||||
dividend
|
||||
}
|
||||
};
|
||||
|
||||
var datas = query.ToArray();
|
||||
var diviService = new TradeModule.DealModule.DividendService(OptUser);
|
||||
var dividendDict = diviService.GetExDividendQuery(settleDate)
|
||||
.ToDictionary(O => O.UnderlyingCode, O => O, StringComparer.OrdinalIgnoreCase);
|
||||
var eodPriceProvider = new EodPriceProvider(settleDate);
|
||||
return datas.Select(data =>
|
||||
{
|
||||
var eod = data.eod;
|
||||
var bod = data.bod;
|
||||
if (data.dividend != null)
|
||||
if (dividendDict.TryGetValue(eod.UnderlyingCode, out var dividend))
|
||||
{
|
||||
if (data.eod.TradeType == "股票")
|
||||
{
|
||||
var SettlePrice = eodPriceProvider.GetPrice(data.eod.UnderlyingCode, SettlementTypeEnum.ClosePrice);
|
||||
SettlePrice = diviService.GetPrice(SettlePrice, data.dividend);
|
||||
var amount = diviService.GetPositionAmount(data.eod.Amount, data.dividend);
|
||||
SettlePrice = diviService.GetPrice(SettlePrice, dividend);
|
||||
var amount = diviService.GetPositionAmount(data.eod.Amount, dividend);
|
||||
eod.Pv = eod.Pv > 0 ? Math.Abs(amount * SettlePrice) : -Math.Abs(amount * SettlePrice);
|
||||
}
|
||||
}
|
||||
@@ -109,9 +107,6 @@ namespace YLErp.Modules.EodModule
|
||||
on new { eod.BookId, eod.TradeType, eod.PositionType, eod.UnderlyingCode, ExchangeOptionCode = eod.ExchangeOptionCode ?? string.Empty }
|
||||
equals new { bod.BookId, bod.TradeType, bod.PositionType, bod.UnderlyingCode, ExchangeOptionCode = bod.ExchangeOptionCode ?? string.Empty } into t_bod
|
||||
from bod in t_bod.DefaultIfEmpty()
|
||||
join dividend in DbContext.ex_dividend_info.AsNoTracking().Where(O => O.ExDividendDate == settleDate && O.ValidStatus)
|
||||
on eod.UnderlyingCode equals dividend.UnderlyingCode into t_dividend
|
||||
from dividend in t_dividend.DefaultIfEmpty()
|
||||
join risk in DbContext.Set<TRisk>().AsNoTracking().Where(n => n.ValueDate == settleDate && n.TradeId > 0) on new { eod.ValueDate, eod.TradeId } equals new { risk.ValueDate, risk.TradeId } into risk_t
|
||||
from risk in risk_t.DefaultIfEmpty()
|
||||
select new
|
||||
@@ -123,24 +118,25 @@ namespace YLErp.Modules.EodModule
|
||||
bod.Cost,
|
||||
//bod.AveragePrice
|
||||
},
|
||||
dividend,
|
||||
risk
|
||||
};
|
||||
|
||||
var datas = query.ToArray();
|
||||
var diviService = new TradeModule.DealModule.DividendService(OptUser);
|
||||
var dividendDict = diviService.GetExDividendQuery(settleDate)
|
||||
.ToDictionary(O => O.UnderlyingCode, O => O, StringComparer.OrdinalIgnoreCase);
|
||||
var eodPriceProvider = new EodPriceProvider(settleDate);
|
||||
return datas.Select(data =>
|
||||
{
|
||||
var pos = data.eod;
|
||||
var bod = data.bod;
|
||||
if (data.dividend != null)
|
||||
if (dividendDict.TryGetValue(pos.UnderlyingCode, out var dividend))
|
||||
{
|
||||
if (data.eod.TradeType == "股票")
|
||||
{
|
||||
var settlePrice = eodPriceProvider.GetPrice(data.eod.UnderlyingCode, SettlementTypeEnum.ClosePrice);
|
||||
settlePrice = diviService.GetPrice(settlePrice, data.dividend);
|
||||
var amount = diviService.GetPositionAmount(data.eod.Amount, data.dividend);
|
||||
settlePrice = diviService.GetPrice(settlePrice, dividend);
|
||||
var amount = diviService.GetPositionAmount(data.eod.Amount, dividend);
|
||||
pos.Pv = pos.Pv > 0 ? Math.Abs(amount * settlePrice) : -Math.Abs(amount * settlePrice);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user