Merge remote-tracking branch 'dest/glms/feature/1.4.2' into test
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using BaseOUDAL;
|
||||
using BaseOUDAL;
|
||||
using DocumentFormat.OpenXml.Bibliography;
|
||||
using ExcelDataReader.Log;
|
||||
using YLErp.DBModels;
|
||||
@@ -104,7 +104,53 @@ namespace YLErp.Modules.EodModule
|
||||
.Where(x => x.reg_date > startDate && x.reg_date <= endDate)
|
||||
.AsNoTracking().ToList();
|
||||
Log.Info($"[分红-登记日口径] GetBondPayments underlyingCode={underlyingCode} 区间=({startDate:yyyy-MM-dd},{endDate:yyyy-MM-dd}] 按reg_date过滤, 命中 {result.Count} 条: " +
|
||||
string.Join(",", result.Select(r => r.reg_date?.ToString("yyyy-MM-dd"))));
|
||||
string.Join(",", result.Select(r => r.reg_date?.ToString("yyyy-MM-dd"))));
|
||||
|
||||
// 让 Copy/Update EOD 始终只依赖 BondPaymentService,而不必在收盘链路直接累加 ex_dividend_info。
|
||||
// 口径约定:bond_payment_info.payment_interest 对 Stock/Fund 统一按“每 10 份派现金额”存储,
|
||||
// 即直接存 ex_dividend_info.GiveCashAmount 原值,不做 /10;
|
||||
// 最后的 /10 由 CalcPayment 非债券分支完成。
|
||||
// 去重:镜像任务完成后的正式记录带 jsid = -dividend.id;此处先按该负号标记,
|
||||
// 或用“同一实际付息日 + 同一派现金额”兜底去重,避免镜像完成后重复计息。
|
||||
var corporatePayments = (from dividend in DbContext.ex_dividend_info.AsNoTracking()
|
||||
join underlying in DbContext.underlying_manager.AsNoTracking()
|
||||
on dividend.UnderlyingCode equals underlying.UnderlyingCode
|
||||
where dividend.ValidStatus
|
||||
&& dividend.EffectiveDate.HasValue
|
||||
&& dividend.EffectiveDate.Value > startDate
|
||||
&& dividend.EffectiveDate.Value <= endDate
|
||||
&& dividend.GiveCashAmount != 0
|
||||
&& dividend.UnderlyingCode == underlyingCode
|
||||
&& (underlying.UnderlyingInstrumentType == ConsGlobal.InstrumentType.Stock
|
||||
|| underlying.UnderlyingInstrumentType == ConsGlobal.InstrumentType.Fund)
|
||||
select dividend).ToList();
|
||||
foreach (var dividend in corporatePayments)
|
||||
{
|
||||
// 按“每 10 份派现金额”口径,直接存 GiveCashAmount 原值,与同步任务/CalcPayment 保持一致。
|
||||
var paymentInterest = dividend.GiveCashAmount;
|
||||
var hasMirroredPayment = result.Any(payment =>
|
||||
payment.jsid == -dividend.id
|
||||
|| (payment.payment_date.HasValue
|
||||
&& payment.payment_date.Value.Date == dividend.EffectiveDate.Value.Date
|
||||
&& payment.payment_interest == paymentInterest));
|
||||
if (hasMirroredPayment)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(new BondPayment
|
||||
{
|
||||
underlyingCode = dividend.UnderlyingCode,
|
||||
payment_date_pl = dividend.EffectiveDate,
|
||||
payment_date = dividend.EffectiveDate,
|
||||
payment_interest = paymentInterest,
|
||||
paying_price = paymentInterest,
|
||||
channel_source = ExDividendDataSources.Manual,
|
||||
jsid = -dividend.id,
|
||||
create_time = dividend.OptDate,
|
||||
update_time = dividend.OptDate
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -132,24 +178,50 @@ namespace YLErp.Modules.EodModule
|
||||
/// <param name="longRatio">多空方向</param>
|
||||
/// <param name="payDirection">收支方向</param>
|
||||
/// <returns></returns>
|
||||
public decimal CalcPayment(string underlyingCode, DateTime startDate, DateTime endDate, decimal qty, decimal longRatio, decimal payDirection)
|
||||
public decimal CalcPayment(
|
||||
string underlyingCode,
|
||||
DateTime startDate,
|
||||
DateTime endDate,
|
||||
decimal qty,
|
||||
decimal longRatio,
|
||||
decimal payDirection,
|
||||
bool useBondPriceScale = true)
|
||||
{
|
||||
var payments = GetBondPayments(underlyingCode, startDate, endDate);
|
||||
return CalcPayment(payments, qty, longRatio, payDirection);
|
||||
return CalcPayment(payments, qty, longRatio, payDirection, useBondPriceScale);
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算某债券期间付息
|
||||
/// 计算某标的期间现金流。债券与 Stock/Fund 公司行为共用 bond_payment_info,
|
||||
/// 但通过 useBondPriceScale 明确区分两种入库金额单位。
|
||||
/// </summary>
|
||||
/// <param name="payments">期间付息集合</param>
|
||||
/// <param name="qty">持仓数量</param>
|
||||
/// <param name="longRatio">多空方向</param>
|
||||
/// <param name="payDirection">收支方向</param>
|
||||
/// <param name="useBondPriceScale">
|
||||
/// 是否按债券报价的百分比口径换算。债券的 payment_interest 是每 100 元面值的票息,
|
||||
/// 需要继续通过 BondPriceConverter 转成入库金额;Fund/Stock 的公司行为现金分红
|
||||
/// 在 bond_payment_info 中按“每 10 份派现金额”存储,payment_interest * qty / 10 才是实际现金,
|
||||
/// 不能再套债券的 /100。默认 true 是为了保持所有历史债券调用方的原有口径。
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public decimal CalcPayment(List<BondPayment> payments, decimal qty, decimal longRatio, decimal payDirection)
|
||||
public decimal CalcPayment(
|
||||
List<BondPayment> payments,
|
||||
decimal qty,
|
||||
decimal longRatio,
|
||||
decimal payDirection,
|
||||
bool useBondPriceScale = true)
|
||||
{
|
||||
var interest = payments.Sum(s => s.payment_interest ?? 0);
|
||||
// interest 为每 100 元面值的票息,×qty 后需 ÷100 转为实际金额(与入库价格 bondPriceMultiple 同口径)
|
||||
return BondPriceConverter.ToStorage(interest * qty) * longRatio * payDirection;
|
||||
var paymentAmount = interest * qty;
|
||||
// 债券:interest 为每 100 元面值的票息,×qty 后需 ÷100 转为实际金额。
|
||||
// Fund/Stock 公司行为:payment_interest 存的是“每 10 份派现金额”(GiveCashAmount 原值),
|
||||
// interest × qty 得到“每 10 份派现额 × 持仓份数”,需再 ÷10 才是实际现金;
|
||||
// 既不能套债券的 /100,也不能直接返回 paymentAmount(那样会放大 10 倍)。
|
||||
var actualAmount = useBondPriceScale
|
||||
? BondPriceConverter.ToStorage(paymentAmount)
|
||||
: paymentAmount / 10;
|
||||
return actualAmount * longRatio * payDirection;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user