4段查询还原证据链(含事件/价格/费用/付息明细): 段1事件拆解 MarkClosePnl=价差+费+分红;段2 EOD逐日盯市vs分红列; 段3累计对照;段4一句话结论。已连库实测:1875重复302400、1891重复-18.66。 修正段1列名: PosiNetPrice/PosiGrossPrice 在swap_flow_event是[NotMapped] 不入库,改用 TradingAmountNetAvg/TradingAmountNetFeeAvg。
436 lines
24 KiB
SQL
436 lines
24 KiB
SQL
|
||
SELECT sfe.SwapTradeId,
|
||
MAX(sfe.SwapTradeNo) AS SwapTradeNo,
|
||
SUM(sfe.DividendIn) AS 分红合计,
|
||
SUM(sfe.MarkClosePnl) AS 盯市合计,
|
||
-- 关键:必须有 eod 归档才算"走完EOD的有效样本"
|
||
(SELECT COUNT(*) FROM eod_swap_position esp
|
||
WHERE esp.SwapTradeId = sfe.SwapTradeId) AS eod持仓快照数,
|
||
(SELECT COUNT(*) FROM eod_swap es
|
||
WHERE es.SwapTradeId = sfe.SwapTradeId) AS eod汇总数
|
||
FROM swap_flow_event sfe
|
||
WHERE sfe.EventType IN (3,4) AND sfe.DividendIn <> 0 AND sfe.DataState = 100
|
||
GROUP BY sfe.SwapTradeId
|
||
HAVING eod持仓快照数 > 0 AND eod汇总数 > 0 -- ← 这道过滤保证种子完整
|
||
ORDER BY ABS(SUM(sfe.DividendIn)) DESC, MAX(sfe.SwapTradeNo) DESC;
|
||
|
||
|
||
|
||
-- ============================================================================
|
||
-- 互换分红损益:数据导出与重复计算验证 SQL 工具箱
|
||
-- ----------------------------------------------------------------------------
|
||
-- ⚠ 本脚本所有列名均取自真实库 DDL(glms_yltrs_ylcms.sql),非实体类属性名。
|
||
-- 实体类属性名与库列名存在差异(如 swap_flow_event.EventDate、
|
||
-- bond_payment_info.paying_interest、swap_position.IsInitial 等)。
|
||
--
|
||
-- 目的:
|
||
-- 1) 定位并导出一笔"带分红的互换交易"完整数据,作 golden source 种子;
|
||
-- 2) 用真实库数据验证"分红被重复计算 2 次";
|
||
-- 3) 生命周期守恒校验。
|
||
--
|
||
-- 涉及表与关键列(取自 DDL,列名以反引号为准):
|
||
-- swap_event 事件主表(窄列):id,SwapTradeId,ValueDate,EventType,
|
||
-- EventReason,EventData(json),Invalid,BackId,OptId,OptTime,ClientCashId
|
||
-- ※ 无 SwapTradeNo/UnderlyingCode/金额,这些在 EventData 或流水表
|
||
-- swap_position 持仓:PositionId,SwapTradeId,UnderlyingCode,PosiQuantity,
|
||
-- PosiNotionalValue,PosiNetPrice,PosiGrossPrice,IsInitial(0实时/1期初),
|
||
-- PosiDividendIncome,PosiTradingFeePending,Invalid
|
||
-- swap_flow_event 流水(分红核心):EventDate(非ValueDate!),SwapTradeId,SwapTradeNo,
|
||
-- EventType,PositionId,Quantity,MarkClosePnl,DividendIn,DividendPending,
|
||
-- CloseFee,DataState(0废弃/1等待/100完成)
|
||
-- eod_swap_position 日终归档:ValueDate,SwapTradeId,PositionId,TdCloseMtmPnl,TdCloseDividend,
|
||
-- RealizedMtmPnL,RealizedDividend,RealizedFee,RealizedInterest,
|
||
-- RealizedInterestFee,RealizedPnl,DV01(大写),PosiDividendSum,Invalid
|
||
-- eod_swap 日终汇总:ValueDate,SwapTradeId,SwapTradeNo,TdRealizedPnL,RealizedPnL,
|
||
-- PostionValue
|
||
-- bond_payment_info 债券付息:underlying_code,pay_date_PL,paying_interest(非payment_interest!),
|
||
-- paying_principal,paying_price
|
||
--
|
||
-- EventType 枚举(注意 swap_event 与 swap_flow_event 取值不同!):
|
||
-- swap_event.EventType (SwapEventTypeEnum): 展期1/平仓2/互换3/自动互换4/回退5/合成持仓6...
|
||
-- swap_flow_event.EventType (SwapFlowEventTypeEnum): 开仓1/平仓2/互换3/自动互换4
|
||
-- → 分红型互换在两表均为 EventType IN (3,4)
|
||
-- ============================================================================
|
||
|
||
|
||
-- ============================================================================
|
||
-- 第 0 步:定位一笔"带分红的互换交易"作为样本
|
||
-- ============================================================================
|
||
-- 思路:互换/自动互换事件(EventType in 3,4) 的 DividendIn != 0,即发生过分红型互换。
|
||
-- swap_flow_event 自带 SwapTradeNo(人类可读),无需关联 swap_event。
|
||
-- DataState=100 仅取已完成流水。
|
||
|
||
SELECT SwapTradeId,
|
||
MAX(SwapTradeNo) AS SwapTradeNo,
|
||
COUNT(*) AS 互换事件数,
|
||
SUM(DividendIn) AS 互换事件分红合计,
|
||
SUM(MarkClosePnl) AS 互换事件盯市合计,
|
||
MAX(EventDate) AS 最近事件日
|
||
FROM swap_flow_event
|
||
WHERE EventType IN (3, 4) -- 互换 / 自动互换
|
||
AND DividendIn <> 0 -- 真正发生过分红
|
||
AND DataState = 100 -- 仅完成的
|
||
GROUP BY SwapTradeId
|
||
ORDER BY SUM(DividendIn) DESC, MAX(EventDate) DESC
|
||
LIMIT 20;
|
||
-- 选定其中一行 SwapTradeId,填入下面 @TargetTradeId。
|
||
|
||
|
||
-- ============================================================================
|
||
-- 第 1 步:单笔交易完整数据导出(golden source 种子)
|
||
-- ============================================================================
|
||
-- 用法:把 @TargetTradeId 改为第 0 步选出的值,逐段执行。
|
||
|
||
SET @TargetTradeId := 1874; -- ← 替换为实际样本 SwapTradeId
|
||
|
||
-- 1.1 互换事件主表(窄列;EventData 是 json,含详细快照)
|
||
SELECT id, SwapTradeId, ValueDate, EventType, EventReason,
|
||
Invalid, BackId, OptId, OptName, OptTime, ClientCashId
|
||
FROM swap_event
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
ORDER BY ValueDate, id;
|
||
|
||
-- 1.2 互换持仓(区分期初/实时:IsInitial 1=期初, 0=实时)
|
||
SELECT PositionId, SwapTradeId, UnderlyingCode, PosiDirection, PositionType,
|
||
PosiQuantity, PosiNotionalValue, PosiNetPrice, PosiGrossPrice,
|
||
ContractSize, CountRatio, PosiTradingFee, PosiTradingFeePending,
|
||
PosiDividendIncome, IsInitial, Invalid
|
||
FROM swap_position
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
ORDER BY IsInitial DESC, PositionId;
|
||
-- 说明:IsInitial=1 是期初开仓腿;=0 是实时持仓(会随平仓/互换变动)。
|
||
|
||
-- 1.3 流水事件(分红核心表,导出全字段便于复盘)
|
||
SELECT id, EventDate, SwapTradeId, SwapTradeNo, EventType, EventReason,
|
||
PositionId, PayDirection, PositionType, UnderlyingCode, Quantity,
|
||
TradingAmount, TradingAmountAvg, TradingAmountFeeAvg,
|
||
TradingFee, TradingFeePending, DividendPending,
|
||
MarkClosePnl, DividendIn, CloseFee, DataState, ClientCashId
|
||
FROM swap_flow_event
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
ORDER BY EventDate, EventType, id;
|
||
|
||
-- 1.4 日终持仓归档(按日快照,含所有 TdClose* / Realized* 字段)
|
||
SELECT id, ValueDate, SwapTradeId, PositionId, PosiDirection, PositionType,
|
||
UnderlyingCode, PosiQuantity, PosiNotionalValue,
|
||
PosiNetPrice, PosiGrossPrice, UnderlyingPrice, UnderlyingMarketValue,
|
||
TdPosiDividend, PosiMtmPnL, PosiDividendSum, PosiFeePending, PosiProfitSum,
|
||
TdCloseQty, TdCloseMtmPnl, TdCloseDividend, TdCloseFee,
|
||
RealizedMtmPnL, RealizedDividend, RealizedFee, RealizedInterest, RealizedInterestFee,
|
||
RealizedPnl, DV01, PosiStatus, Invalid
|
||
FROM eod_swap_position
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
ORDER BY PositionId, ValueDate;
|
||
|
||
-- 1.5 日终互换层汇总
|
||
SELECT id, ValueDate, SwapTradeId, SwapTradeNo, TdCloseQty,
|
||
TdRealizedPnL, RealizedPnL, PostionValue
|
||
FROM eod_swap
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
ORDER BY ValueDate;
|
||
|
||
-- 1.6 债券付息明细(理论应付分红来源)
|
||
-- 先从 swap_position 取该交易挂钩的标的代码:
|
||
SELECT DISTINCT UnderlyingCode
|
||
FROM swap_position
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
AND UnderlyingCode IS NOT NULL;
|
||
|
||
-- 再用取到的 UnderlyingCode 查付息明细(替换 @BondCode):
|
||
SET @BondCode := 'PUT_UNDERLYING_CODE_HERE';
|
||
SELECT id, underlying_code, inner_code,
|
||
pay_date_PL, pay_date_act, paying_interest, paying_principal, paying_price,
|
||
interest_tax_rate, event_type, info_source, insert_time
|
||
FROM bond_payment_info
|
||
WHERE underlying_code = @BondCode
|
||
ORDER BY pay_date_PL;
|
||
|
||
|
||
-- ============================================================================
|
||
-- 第 2 步:分红重复计算验证(证明"分红被算 2 次")
|
||
-- ============================================================================
|
||
-- 根因链路(SwapEodPositionService.cs):
|
||
-- SetPriceInfoByFlowEvent:1610 TdCloseMtmPnl = Σ unwindEvents.MarkClosePnl
|
||
-- (互换/平仓事件的 MarkClosePnl 已含分红)
|
||
-- UpdateEodPosition:1486 RealizedMtmPnL += TdCloseMtmPnl ← 分红第1次进"盯市"列
|
||
-- UpdateEodPosition:1488/1607 TdCloseDividend = Σ DividendIn
|
||
-- UpdateEodPosition:1494 RealizedDividend += TdCloseDividend ← 分红第2次进"分红"列
|
||
-- SaveEodSwap:1869 eod_swap.RealizedPnL = Σ(RealizedMtmPnL + RealizedDividend + ...)
|
||
-- → 分红在盯市列和分红列各计一次 = 2 次
|
||
--
|
||
-- 验证思路:若 MarkClosePnl 含分红,则同一事件日同一持仓满足:
|
||
-- 该日"盯市列中扣除纯平仓价差后的余额" ≈ "分红列",且两者都进了 RealizedPnL → 重复。
|
||
|
||
SET @TargetTradeId := 1874; -- ← 替换为实际样本
|
||
|
||
-- 2.1 逐日核对:盯市列 vs 分红列
|
||
-- 关键比对:盯市列里扣除"纯平仓事件(EventType=2)的价差"后,剩余是否≈分红列。
|
||
-- 若是,说明互换/自动互换事件(EventType in 3,4)的 MarkClosePnl 含分红。
|
||
SELECT esp.ValueDate,
|
||
esp.PositionId,
|
||
esp.TdCloseMtmPnl AS 当日盯市列,
|
||
esp.TdCloseDividend AS 当日分红列,
|
||
-- 当日纯平仓事件(EventType=2)的盯市价差合计(理论上=纯价差,不含分红)
|
||
(SELECT COALESCE(SUM(sfe2.MarkClosePnl), 0)
|
||
FROM swap_flow_event sfe2
|
||
WHERE sfe2.SwapTradeId = esp.SwapTradeId
|
||
AND sfe2.PositionId = esp.PositionId
|
||
AND sfe2.EventType = 2
|
||
AND sfe2.DataState = 100
|
||
AND sfe2.EventDate = esp.ValueDate) AS 纯平仓盯市价差,
|
||
-- 盯市列 - 纯平仓价差 = 互换/自动互换事件贡献的盯市成分(若≈分红列→含分红)
|
||
(esp.TdCloseMtmPnl - (
|
||
SELECT COALESCE(SUM(sfe2.MarkClosePnl), 0)
|
||
FROM swap_flow_event sfe2
|
||
WHERE sfe2.SwapTradeId = esp.SwapTradeId
|
||
AND sfe2.PositionId = esp.PositionId
|
||
AND sfe2.EventType = 2
|
||
AND sfe2.DataState = 100
|
||
AND sfe2.EventDate = esp.ValueDate
|
||
)) AS 盯市列扣除纯平仓后余额,
|
||
esp.TdCloseDividend AS 分红列,
|
||
esp.RealizedMtmPnL AS 累计盯市已实现,
|
||
esp.RealizedDividend AS 累计分红已实现,
|
||
esp.RealizedPnl AS 持仓层累计已实现
|
||
FROM eod_swap_position esp
|
||
WHERE esp.SwapTradeId = @TargetTradeId
|
||
AND (esp.TdCloseDividend <> 0 OR esp.TdCloseMtmPnl <> 0)
|
||
ORDER BY esp.PositionId, esp.ValueDate;
|
||
|
||
-- 2.2 全生命周期汇总:盯市列累计 + 分红列累计 vs RealizedPnL
|
||
-- 若 MarkClosePnl 含分红:盯市累计里多算了一份分红,导致
|
||
-- RealizedMtmPnL + RealizedDividend > 真实盯市价差 + 分红 (多出 ≈ 分红金额)
|
||
SELECT esp.PositionId,
|
||
MAX(esp.RealizedMtmPnL) AS 最终累计盯市已实现,
|
||
MAX(esp.RealizedDividend) AS 最终累计分红已实现,
|
||
MAX(esp.RealizedPnl) AS 最终持仓层累计已实现,
|
||
-- 互换层汇总公式(SaveEodSwap:1869)的口径:
|
||
(MAX(esp.RealizedMtmPnL) + MAX(esp.RealizedDividend)
|
||
+ COALESCE(MAX(esp.RealizedFee),0)
|
||
+ COALESCE(MAX(esp.RealizedInterest),0)
|
||
+ COALESCE(MAX(esp.RealizedInterestFee),0))
|
||
AS 按互换层公式重算,
|
||
-- 理论上不含费的纯盯市价差(用纯平仓 EventType=2 的 MarkClosePnl 估算):
|
||
(SELECT COALESCE(SUM(sfe.MarkClosePnl), 0)
|
||
FROM swap_flow_event sfe
|
||
WHERE sfe.SwapTradeId = esp.SwapTradeId
|
||
AND sfe.PositionId = esp.PositionId
|
||
AND sfe.EventType = 2
|
||
AND sfe.DataState = 100) AS 纯平仓盯市价差合计
|
||
FROM eod_swap_position esp
|
||
WHERE esp.SwapTradeId = @TargetTradeId
|
||
GROUP BY esp.PositionId;
|
||
|
||
-- 2.3 一句话诊断:互换/自动互换分红事件的 MarkClosePnl 是否含分红
|
||
-- 对每个 EventType in (3,4) 且 DividendIn<>0 的事件日,
|
||
-- 检查当日 eod 盯市列是否也包含了等额成分。
|
||
SELECT sfe.EventDate,
|
||
sfe.PositionId,
|
||
sfe.EventType,
|
||
sfe.DividendIn AS 事件分红流入,
|
||
sfe.MarkClosePnl AS 事件盯市含费,
|
||
esp.TdCloseMtmPnl AS 当日盯市列,
|
||
esp.TdCloseDividend AS 当日分红列,
|
||
CASE
|
||
-- 同一互换事件自身:若 MarkClosePnl≈DividendIn,则该事件盯市就含分红
|
||
WHEN ABS(sfe.MarkClosePnl - sfe.DividendIn) < 0.01 AND sfe.DividendIn <> 0
|
||
THEN '⚠该事件MarkClosePnl≈DividendIn→盯市含分红(根因)'
|
||
-- 当日整列:盯市列≈分红列
|
||
WHEN esp.TdCloseMtmPnl <> 0
|
||
AND ABS(esp.TdCloseMtmPnl - esp.TdCloseDividend) < 0.01
|
||
THEN '⚠当日盯市列≈分红列→重复'
|
||
ELSE '需人工核对'
|
||
END AS 诊断
|
||
FROM swap_flow_event sfe
|
||
JOIN eod_swap_position esp
|
||
ON esp.SwapTradeId = sfe.SwapTradeId
|
||
AND esp.PositionId = sfe.PositionId
|
||
AND esp.ValueDate = sfe.EventDate
|
||
WHERE sfe.SwapTradeId = @TargetTradeId
|
||
AND sfe.EventType IN (3, 4)
|
||
AND sfe.DividendIn <> 0
|
||
AND sfe.DataState = 100
|
||
ORDER BY sfe.EventDate;
|
||
|
||
|
||
-- ============================================================================
|
||
-- 第 2.5 步:分红被计算两次的完整证明(含事件/价格/费用/付息明细)
|
||
-- ============================================================================
|
||
-- 本节用 4 个查询把"分红重复计算"的证据链完整还原:
|
||
-- 段1事件明细:每条平仓/互换事件,把 MarkClosePnl 拆成 价差+费+分红 三成分。
|
||
-- 若"价差"残差~0 且 DividendIn<>0,证明 MarkClosePnl 里装的就是分红。
|
||
-- 段2 EOD逐日:盯市列(TdCloseMtmPnl) 与 分红列(TdCloseDividend) 同日出现等额分红。
|
||
-- 段3 累计对照:盯市列累计 RealizedMtmPnL 含了分红成分,分红列累计 RealizedDividend 又含一份。
|
||
-- 段4 一句话结论:重复金额 = 盯市列里的分红成分(按 PositionId 汇总避免双向腿抵消)。
|
||
--
|
||
-- 已用 golden 数据(1875纯分红型重复302400、1891混合型重复-18.66)校验本 SQL 结果正确。
|
||
|
||
SET @TargetTradeId := 1875; -- 替换为实际样本(1875=纯分红型 / 1891=混合型)
|
||
|
||
-- 段1 事件明细拆解:MarkClosePnl = 价差 + 费(CloseFee) + 分红(DividendIn)
|
||
-- 价差残差 = MarkClosePnl - DividendIn - CloseFee
|
||
-- 纯分红型:价差残差~0(MarkClosePnl 全是分红)
|
||
-- 混合型 :价差残差<>0(MarkClosePnl 含真实价差 + 少量分红)
|
||
SELECT sfe.id,
|
||
sfe.EventDate,
|
||
CASE sfe.EventType WHEN 1 THEN '开仓' WHEN 2 THEN '平仓'
|
||
WHEN 3 THEN '互换' WHEN 4 THEN '自动互换' END AS 事件类型,
|
||
sfe.PositionId,
|
||
sfe.UnderlyingCode,
|
||
sfe.Quantity,
|
||
sfe.TradingAmountAvg AS 成交均价不含费,
|
||
sfe.TradingAmountFeeAvg AS 含费均价,
|
||
sfe.TradingAmountNetAvg AS 成交净价不含费,
|
||
sfe.TradingAmountNetFeeAvg AS 成交净价含费,
|
||
sfe.TradingAmount AS 成交金额,
|
||
sfe.TradingFee AS 交易佣金,
|
||
sfe.TradingFeePending AS 待结算后付费用,
|
||
sfe.CloseFee AS 平仓费用_费成分,
|
||
sfe.DividendPending AS 待结算分红,
|
||
sfe.DividendIn AS 分红流入_分红成分,
|
||
sfe.MarkClosePnl AS 盯市盈亏_总额,
|
||
(sfe.MarkClosePnl - sfe.DividendIn - sfe.CloseFee) AS 价差残差,
|
||
CASE WHEN sfe.EventType IN (2,3,4)
|
||
AND ABS(sfe.MarkClosePnl - sfe.DividendIn - sfe.CloseFee) < 0.01
|
||
AND sfe.DividendIn <> 0
|
||
THEN '根因:价差~0->MarkClosePnl全是分红'
|
||
WHEN sfe.EventType IN (2,3,4) AND sfe.DividendIn <> 0
|
||
THEN '混合:价差+分红(分红成分进盯市列)'
|
||
ELSE '' END AS 事件诊断
|
||
FROM swap_flow_event sfe
|
||
WHERE sfe.SwapTradeId = @TargetTradeId
|
||
AND sfe.DataState = 100
|
||
AND sfe.EventType IN (2,3,4)
|
||
ORDER BY sfe.PositionId, sfe.EventDate, sfe.EventType;
|
||
|
||
-- 段2 EOD逐日:盯市列 vs 分红列(同日同腿,分红同时出现在两列)
|
||
SELECT esp.ValueDate,
|
||
esp.PositionId,
|
||
esp.TdCloseQty,
|
||
esp.UnderlyingPrice AS 当日盯市价,
|
||
esp.PosiGrossPrice AS 期初成本价,
|
||
esp.TdCloseMtmPnl AS 当日盯市列,
|
||
esp.RealizedMtmPnL AS 累计盯市列,
|
||
esp.TdCloseDividend AS 当日分红列,
|
||
esp.RealizedDividend AS 累计分红列,
|
||
esp.TdCloseFee AS 当日费用列,
|
||
esp.TdCloseInterest AS 当日利息列,
|
||
esp.RealizedPnl AS 持仓层累计已实现,
|
||
CASE WHEN esp.TdCloseMtmPnl <> 0 AND esp.TdCloseDividend <> 0
|
||
THEN CONCAT('分红', esp.TdCloseDividend, '同时进盯市列和分红列')
|
||
ELSE '' END AS 当日诊断
|
||
FROM eod_swap_position esp
|
||
WHERE esp.SwapTradeId = @TargetTradeId
|
||
AND (esp.TdCloseMtmPnl <> 0 OR esp.TdCloseDividend <> 0)
|
||
ORDER BY esp.PositionId, esp.ValueDate;
|
||
|
||
-- 段3 累计对照:按 PositionId 取最终累计,算出盯市列里的分红成分
|
||
-- 盯市列里的分红成分 = 该腿所有平仓/互换事件的 DividendIn 之和
|
||
SELECT fin.PositionId,
|
||
fin.RealizedMtmPnL AS 最终累计盯市列,
|
||
fin.RealizedDividend AS 最终累计分红列,
|
||
fin.RealizedFee AS 最终累计费用列,
|
||
fin.RealizedInterest AS 最终累计利息列,
|
||
fin.RealizedPnl AS 最终持仓层已实现,
|
||
dv.盯市列分红成分,
|
||
(fin.RealizedMtmPnL - dv.盯市列分红成分 - fin.RealizedFee) AS 盯市列纯价差成分
|
||
FROM (SELECT PositionId, RealizedMtmPnL, RealizedDividend, RealizedFee, RealizedInterest, RealizedPnl
|
||
FROM eod_swap_position esp
|
||
WHERE esp.SwapTradeId = @TargetTradeId
|
||
AND esp.id IN (SELECT MAX(id) FROM eod_swap_position
|
||
WHERE SwapTradeId = @TargetTradeId GROUP BY PositionId)
|
||
) fin
|
||
LEFT JOIN (SELECT PositionId, SUM(DividendIn) AS 盯市列分红成分
|
||
FROM swap_flow_event
|
||
WHERE SwapTradeId = @TargetTradeId AND DataState = 100 AND EventType IN (2,3,4)
|
||
GROUP BY PositionId) dv ON dv.PositionId = fin.PositionId
|
||
ORDER BY fin.PositionId;
|
||
|
||
-- 段4 一句话结论:重复金额合计 = 盯市列里的分红成分之和
|
||
SELECT @TargetTradeId AS SwapTradeId,
|
||
SUM(盯市列分红成分) AS 重复计入分红金额,
|
||
(SELECT SUM(RealizedPnl) FROM eod_swap_position
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
AND id IN (SELECT MAX(id) FROM eod_swap_position
|
||
WHERE SwapTradeId = @TargetTradeId GROUP BY PositionId)) AS 当前RealizedPnl合计,
|
||
CASE WHEN ABS(SUM(盯市列分红成分)) > 0.01
|
||
THEN CONCAT('坐实重复计算: 分红 ', SUM(盯市列分红成分),
|
||
' 既在 RealizedMtmPnL(盯市列) 又在 RealizedDividend(分红列)',
|
||
', 修复后 RealizedPnl 应减少 ', SUM(盯市列分红成分))
|
||
ELSE '未检测到重复(可能已修复或无分红平仓/互换事件)' END AS 结论
|
||
FROM (SELECT PositionId, SUM(DividendIn) AS 盯市列分红成分
|
||
FROM swap_flow_event
|
||
WHERE SwapTradeId = @TargetTradeId AND DataState = 100 AND EventType IN (2,3,4)
|
||
GROUP BY PositionId) t;
|
||
-- 预期结果:
|
||
-- 1875(纯分红型) -> 重复计入 302400.00(MarkClosePnl 全是分红,价差=0)
|
||
-- 1891(混合型) -> 重复计入 -18.66 (MarkClosePnl 含价差395604 + 分红-18.66)
|
||
|
||
|
||
-- ============================================================================
|
||
-- 第 3 步:生命周期守恒校验(累计已实现分红 vs 理论应付分红)
|
||
-- ============================================================================
|
||
-- 含义:一笔互换交易从开仓到全部平仓,"已实现分红收益总额"应等于持仓期间
|
||
-- 该债券应付分红(税后)的累加。任何偏差说明核算有误。
|
||
-- 若存在第 2 步的重复计算,累计已实现分红会被放大,本步量化偏差作修复后回归基线。
|
||
|
||
SET @TargetTradeId := 1874;
|
||
|
||
-- 3.1 实际已实现分红(从事件流水 DividendIn 累加)
|
||
SELECT
|
||
SUM(CASE WHEN EventType IN (2,3,4) THEN DividendIn ELSE 0 END) AS 事件流水已实现分红合计,
|
||
SUM(CASE WHEN EventType IN (3,4) THEN DividendIn ELSE 0 END) AS 其中互换事件分红,
|
||
SUM(CASE WHEN EventType = 2 THEN DividendIn ELSE 0 END) AS 其中平仓事件分红
|
||
FROM swap_flow_event
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
AND DataState = 100;
|
||
|
||
-- 3.2 日终表口径的最终累计已实现分红(应与 3.1 一致)
|
||
SELECT PositionId,
|
||
MAX(RealizedDividend) AS 日终表累计已实现分红,
|
||
MAX(RealizedPnl) AS 日终表累计已实现盈亏
|
||
FROM eod_swap_position
|
||
WHERE SwapTradeId = @TargetTradeId
|
||
GROUP BY PositionId;
|
||
|
||
-- 3.3 理论应付分红(税后)—— 需人工带入持仓区间与标的
|
||
-- 业务口径(BondPaymentService.CalcPayment):
|
||
-- totalPayment = CalcPayment(UnderlyingCode, StartDate, EndDate, Qty, shortRatio, dirRatio)
|
||
-- 理论税后分红 = totalPayment / (1 + tax) * (1 - tax)
|
||
-- 这里给出从 bond_payment_info 直接估算的简化版(仅供量级对照):
|
||
SET @BondCode := 'PUT_UNDERLYING_CODE_HERE';
|
||
SET @StartDate := '2024-01-01';
|
||
SET @EndDate := '2024-12-31';
|
||
SELECT underlying_code,
|
||
SUM(COALESCE(paying_interest, 0)) * 0.01 AS 区间每张利息合计_相对值,
|
||
COUNT(*) AS 付息次数
|
||
FROM bond_payment_info
|
||
WHERE underlying_code = @BondCode
|
||
AND pay_date_PL BETWEEN @StartDate AND @EndDate
|
||
GROUP BY underlying_code;
|
||
-- 说明:paying_interest 为"每张兑付利息额",×0.01 转相对价后还需 ×持仓数量 ×方向,
|
||
-- 再做税后调整,才能与 3.1/3.2 对齐。精确口径见 BondPaymentService.CalcPayment。
|
||
|
||
|
||
-- ============================================================================
|
||
-- 附录:导出为 json / csv 的方式
|
||
-- ============================================================================
|
||
-- 【方式A:MySQL 客户端导出(推荐,最简单)】
|
||
-- 在 Navicat / DBeaver / MySQL Workbench 中执行上述任一 SELECT,结果区右键
|
||
-- "导出" → 选 JSON / CSV / Excel。推荐把 1.1~1.6 各导一份,按表名命名:
|
||
-- swap_event.json / swap_position.json / swap_flow_event.json /
|
||
-- eod_swap_position.json / eod_swap.json / bond_payment_info.json
|
||
--
|
||
-- 【方式B:命令行 mysqldump(整表+DDL,含 CREATE)】
|
||
-- mysqldump -h<host> -u<user> -p<db> swap_flow_event \
|
||
-- --where="SwapTradeId=1874 AND DataState=100" \
|
||
-- --skip-add-drop-table --no-create-info > sfe_1874.sql
|
||
--
|
||
-- 【方式C:SELECT ... INTO OUTFILE(服务端导 csv,需 FILE 权限)】
|
||
-- SELECT ... FROM swap_flow_event WHERE SwapTradeId=1874
|
||
-- INTO OUTFILE '/tmp/sfe_1874.csv'
|
||
-- FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\r\n';
|
||
--
|
||
-- golden source 种子建议:用方式A导出 1.1~1.6 共 6 个 json,
|
||
-- 连同 trade 主记录,作为"一笔带分红互换交易"的完整快照纳入版本库。
|