From 358993bedbc5240591b4d7a2d5c26a35d3047976 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 9 Jul 2026 15:11:58 +0800
Subject: [PATCH 1/9] =?UTF-8?q?feat(swaptrade):=20=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E6=9C=9F=E6=9C=AB=E5=A4=B4=E5=AF=B8=E9=A3=8E=E9=99=A9=E8=A1=A8?=
=?UTF-8?q?=E6=96=B0=E5=AD=97=E6=AE=B5=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 在EodSwap实体模型中新增标的类型、期间付息/分红、保证金利息收支字段
- 在前端表格列模型中添加标的类型、期间付息/分红列定义
- 在前端表格分组配置中将新字段归入对应分组显示
- 实现后端服务中对新字段的数据查询和计算逻辑
- 添加保证金利息收入支出的分类汇总功能
- 完善标的类型字段的数据源获取和展示逻辑
---
Framework/YLErp.Core/DBModels/EodSwap.cs | 8 ++++
.../SwapModule/SwapEodPositionService.cs | 30 +++++++++++++++
.../Scripts/app/swaptrade/EodPositionRisks.js | 38 ++++++++++++++++---
3 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/Framework/YLErp.Core/DBModels/EodSwap.cs b/Framework/YLErp.Core/DBModels/EodSwap.cs
index 4d6294a0..783f0ccc 100644
--- a/Framework/YLErp.Core/DBModels/EodSwap.cs
+++ b/Framework/YLErp.Core/DBModels/EodSwap.cs
@@ -174,5 +174,13 @@ namespace YLErp.DBModels
public int ClientId { get; set; }
public string SwapTradeTypeStr { get; set; }
+
+ public string UnderlyingType { get; set; }
+
+ public decimal PeriodAmount { get; set; }
+
+ public decimal MarginInterestGain { get; set; }
+
+ public decimal MarginInterestLoss { get; set; }
}
}
diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
index b313e99c..319666ef 100644
--- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
@@ -2162,10 +2162,40 @@ namespace YLErp.Modules.SwapModule
}
DbContext.SetDebugLog();
var retListResult = query.ToSearchList(req);
+ var tradeIds = retListResult.rows.Select(x => x.position.SwapTradeId).Distinct().ToList();
+ var valueDates = retListResult.rows.Select(x => x.position.ValueDate).Distinct().ToList();
+ var eodPositionDetails = DbContext.eod_swap_position
+ .Where(x => tradeIds.Contains(x.SwapTradeId) && valueDates.Contains(x.ValueDate) && !x.Invalid)
+ .ToList();
+ var underlyingDataSource = DataCacheProvider.GetUnderlyingDataSource();
+ var varietyDataSource = DataCacheProvider.GetVarietyDataSource();
foreach (var item in retListResult.rows)
{
var client = DataCacheProvider.GetClientDataSource().GetData(item.ClientId);
item.SwapTradeTypeStr = client?.SwapTradeTypeStr;
+ var details = eodPositionDetails
+ .Where(x => x.SwapTradeId == item.position.SwapTradeId && x.ValueDate == item.position.ValueDate)
+ .ToList();
+ var floatingLegs = details.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();
+ var marginLegs = details.Where(x => marginTypes.Contains(x.InterestMode)).ToList();
+
+ item.UnderlyingType = string.Join(",", floatingLegs
+ .Select(x =>
+ {
+ var underlying = underlyingDataSource.GetData(x.UnderlyingCode);
+ return varietyDataSource.GetData(underlying?.UnderlyingTypeId ?? 0)?.AssetType
+ ?? underlying?.UnderlyingInstrumentTypeCn
+ ?? underlying?.UnderlyingType;
+ })
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Distinct());
+ item.PeriodAmount = floatingLegs.Sum(x => x.PosiDividendSum); // 分红 - 为实现
+ item.MarginInterestGain = marginLegs
+ .Where(x => x.InterestDirection == (int)SwapDirectionEnum.收取)
+ .Sum(x => Math.Abs(x.InterestIncomeSum));
+ item.MarginInterestLoss = marginLegs
+ .Where(x => x.InterestDirection == (int)SwapDirectionEnum.支付)
+ .Sum(x => Math.Abs(x.InterestIncomeSum));
}
var dv01 = query.Sum(O => O.position.dv01??0);
diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
index a011f68f..4c5b205a 100644
--- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
+++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
@@ -457,9 +457,7 @@ function colModelGridEodPosition() {
}
//框架合约table
//TODO(估值模块V1-缺失字段): 以下需求字段本轮未实现,待后端确认数据来源后补充:
-// - 期间付息/分红(浮动端分组)
// - 付息方式、合约估值(到期轧差口径/期间支付派息口径)(估值与实现收益分组)
-// - 标的类型(基本信息分组)
function colModelGridEodSwap() {
//按需求《估值模块V1》2.2 分组定义排列列顺序,确保组内列连续(setGroupHeaders 要求)
var colModelGrid = [{
@@ -526,6 +524,13 @@ function colModelGridEodSwap() {
width: 100,
align: 'center',
sortable: false
+ }, {
+ name: 'UnderlyingType',
+ label: '标的类型',
+ index: 'UnderlyingType',
+ width: 100,
+ align: 'center',
+ sortable: false
},
//=== 名义本金 ===
{
@@ -574,6 +579,13 @@ function colModelGridEodSwap() {
width: 150,
align: 'center',
formatter: StockEqvNotionalFormat,
+ }, {
+ name: 'PeriodAmount',
+ label: '期间付息/分红',
+ index: 'PeriodAmount',
+ width: 150,
+ align: 'center',
+ formatter: StockEqvNotionalFormat,
},
//=== 利息端 ===
{
@@ -613,6 +625,20 @@ function colModelGridEodSwap() {
width: 150,
align: 'center',
formatter: StockEqvNotionalFormat,
+ }, {
+ name: 'MarginInterestGain',
+ label: '收取对手方保证金利息',
+ index: 'MarginInterestGain',
+ width: 170,
+ align: 'center',
+ formatter: StockEqvNotionalFormat,
+ }, {
+ name: 'MarginInterestLoss',
+ label: '支付对手方保证金利息',
+ index: 'MarginInterestLoss',
+ width: 170,
+ align: 'center',
+ formatter: StockEqvNotionalFormat,
},
//=== 估值与实现收益 ===
{
@@ -657,12 +683,12 @@ function colModelGridEodSwap() {
//框架合约分组配置(对应需求《估值模块V1》2.2 字段定义)
//columns 使用 colModel.name;组内列在 colModel 中必须连续
var eodSwapGroupConfig = [
- { title: '基本信息', columns: ['position.ValueDate', 'AssetBookName', 'ClientName', 'SwapTradeNo', 'StructureType', 'SwapTradeTypeStr'] },
+ { title: '基本信息', columns: ['position.ValueDate', 'AssetBookName', 'ClientName', 'SwapTradeNo', 'StructureType', 'SwapTradeTypeStr', 'UnderlyingType'] },
{ title: '名义本金', columns: ['position.NotionalValue', 'position.NotionalValueLong', 'position.NotionalValueShort'] },
{ title: '标的市值', columns: ['position.MarketValueLong', 'position.MarketValueShort'] },
- { title: '浮动端', columns: ['position.FloatingPnL'] },
+ { title: '浮动端', columns: ['position.FloatingPnL', 'PeriodAmount'] },
{ title: '利息端', columns: ['position.InterestPnL'] },
- { title: '保证金', columns: ['position.InitMarginGain', 'position.PostionMarginGain', 'position.InitMarginLoss', 'position.PostionMarginLoss'] },
+ { title: '保证金', columns: ['position.InitMarginGain', 'position.PostionMarginGain', 'position.InitMarginLoss', 'position.PostionMarginLoss', 'MarginInterestGain', 'MarginInterestLoss'] },
{ title: '估值与实现收益', columns: ['position.PostionValue', 'position.TdRealizedPnL', 'position.RealizedPnL', 'position.dv01'] }
];
@@ -817,4 +843,4 @@ function SearchClick(isSearchclick) {
function showcolumnChooser() {
var jgrid = jQuery('#listGrid');
main.showcolumnChooser(jgrid, cloumnTargetName, page.configcolumn_data);
-}
\ No newline at end of file
+}
From 5f27c85ae98f8dafa693f45931b2a0e7942a44f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 9 Jul 2026 15:21:05 +0800
Subject: [PATCH 2/9] =?UTF-8?q?feat(export):=20=E4=B8=BAExcel=E5=AF=BC?=
=?UTF-8?q?=E5=87=BA=E5=8A=9F=E8=83=BD=E6=B7=BB=E5=8A=A0=E5=88=86=E7=BB=84?=
=?UTF-8?q?=E8=A1=A8=E5=A4=B4=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 修改exportVisibleColumnsToExcel函数,增加groupConfig参数
- 实现buildGroupHeaderHtml函数用于构建二级表头结构
- 当存在分组配置时自动生成合并单元格的表头
- 支持按字段分组显示标题并设置样式
- 更新函数注释文档说明新参数用途
---
.../Scripts/app/swaptrade/EodPositionRisks.js | 3 +-
YLErpWeb/wwwroot/Scripts/utils.js | 30 +++++++++++++++++--
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
index 4c5b205a..9d347225 100644
--- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
+++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js
@@ -730,7 +730,8 @@ function exportVisibleColumns() {
var dateStr = $("#DateValueDate").val() || '';
var tabName = page.tabIndex == 2 ? '框架合约' : '日终持仓';
var fileName = '日终持仓风险_互换_' + tabName + (dateStr ? '_' + dateStr : '');
- main.exportVisibleColumnsToExcel(jgrid, fileName);
+ var groupConfig = page.tabIndex == 2 ? eodSwapGroupConfig : null;
+ main.exportVisibleColumnsToExcel(jgrid, fileName, groupConfig);
}
//---------------------------Formatter---------------------------------
diff --git a/YLErpWeb/wwwroot/Scripts/utils.js b/YLErpWeb/wwwroot/Scripts/utils.js
index 993ad26c..ad2601b6 100644
--- a/YLErpWeb/wwwroot/Scripts/utils.js
+++ b/YLErpWeb/wwwroot/Scripts/utils.js
@@ -1209,8 +1209,9 @@ main.refreshCollapsibleGroupHeaders = function (jgrid) {
*
* @param {jQuery} jgrid jqGrid 容器
* @param {string} fileName 导出文件名(不含扩展名)
+ * @param {Array} groupConfig 可选,分组表头配置,每项 { title: string, columns: string[] }
*/
-main.exportVisibleColumnsToExcel = function (jgrid, fileName) {
+main.exportVisibleColumnsToExcel = function (jgrid, fileName, groupConfig) {
var colModel = jgrid.jqGrid('getGridParam', 'colModel');
// 只导出可见列(hidden !== true),与折叠状态联动:收起的列自动不可见
var visibleCols = colModel.filter(function (c) { return c.hidden !== true && c.name !== 'cb' && c.name !== 'rn'; });
@@ -1223,7 +1224,10 @@ main.exportVisibleColumnsToExcel = function (jgrid, fileName) {
var html = '';
html += '
';
html += '';
- //表头
+ //表头:有分组配置时导出两级表头(分类 + 字段),否则保持原单级表头。
+ if (groupConfig && groupConfig.length) {
+ html += buildGroupHeaderHtml(visibleCols, groupConfig);
+ }
html += '' + headerLabels.map(function (l) {
return '| ' + escapeXml(l) + ' | ';
}).join('') + '
';
@@ -1252,5 +1256,25 @@ main.exportVisibleColumnsToExcel = function (jgrid, fileName) {
function escapeXml(s) {
return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
}
+
+ function buildGroupHeaderHtml(cols, config) {
+ var titleByColumn = {};
+ config.forEach(function (group) {
+ (group.columns || []).forEach(function (name) {
+ titleByColumn[name] = group.title || '';
+ });
+ });
+
+ var cells = [];
+ for (var i = 0; i < cols.length; i++) {
+ var title = titleByColumn[cols[i].name] || '';
+ var colspan = 1;
+ while (i + colspan < cols.length && (titleByColumn[cols[i + colspan].name] || '') === title) {
+ colspan++;
+ }
+ cells.push('' + escapeXml(title) + ' | ');
+ i += colspan - 1;
+ }
+ return '' + cells.join('') + '
';
+ }
};
-
\ No newline at end of file
From 7df9e8060e1bf509c5f168ad251f33a5edf36f7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Fri, 10 Jul 2026 18:20:20 +0800
Subject: [PATCH 3/9] =?UTF-8?q?feat(swap):=20=E6=B7=BB=E5=8A=A0=E4=BA=92?=
=?UTF-8?q?=E6=8D=A2=E5=90=88=E7=BA=A6=E4=BC=B0=E5=80=BC=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E5=92=8C=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 在ClientSwapPositionRequest中新增BookId字段用于资产分类查询
- 新增FloatingUnrealizedPnl、InterestPaymentMethod、MaturityNettingValuation等估值相关字段
- 添加MaturitySettlementDate、DividendAmount、AdditionalMarginAmount等持仓详情字段
- 更新前端表格列模型,调整浮动端和估值实现收益分组显示
- 实现框架合约导出功能,支持完整数据筛选结果导出
- 优化名义本金计算逻辑,修复长短仓数值处理问题
- 完善付息方式和估值口径的业务逻辑处理
- 添加TRS估值、期间分红等关键业务字段计算
- 实现Excel导出时分组表头格式化功能
- 修复框架合约列排序和分组表头显示问题
---
Framework/YLErp.Core/DBModels/EodSwap.cs | 20 ++
.../DBModels/EodSwapPositionResponse.cs | 16 ++
YLErpDAL/Model/ClientSwapPositionRequest.cs | 1 +
.../SwapModule/SwapEodPositionService.cs | 79 +++++-
.../TradeMarketReport_EodPosition.cshtml | 1 +
.../Scripts/app/swaptrade/EodPositionRisks.js | 134 ++++++++---
.../TradeMarketReport_EodPosition.js | 226 +++++++++++++++++-
YLErpWeb/wwwroot/Scripts/utils.js | 20 +-
8 files changed, 445 insertions(+), 52 deletions(-)
diff --git a/Framework/YLErp.Core/DBModels/EodSwap.cs b/Framework/YLErp.Core/DBModels/EodSwap.cs
index 783f0ccc..9c058366 100644
--- a/Framework/YLErp.Core/DBModels/EodSwap.cs
+++ b/Framework/YLErp.Core/DBModels/EodSwap.cs
@@ -179,6 +179,26 @@ namespace YLErp.DBModels
public decimal PeriodAmount { get; set; }
+ ///
+ /// 合约浮动端待实现收益,不包含期间付息/分红
+ ///
+ public decimal FloatingUnrealizedPnl { get; set; }
+
+ ///
+ /// 付息方式
+ ///
+ public string InterestPaymentMethod { get; set; }
+
+ ///
+ /// 合约估值(到期轧差口径)
+ ///
+ public decimal? MaturityNettingValuation { get; set; }
+
+ ///
+ /// 合约估值(期间支付派息口径)
+ ///
+ public decimal? PeriodPaymentValuation { get; set; }
+
public decimal MarginInterestGain { get; set; }
public decimal MarginInterestLoss { get; set; }
diff --git a/Framework/YLErp.Core/DBModels/EodSwapPositionResponse.cs b/Framework/YLErp.Core/DBModels/EodSwapPositionResponse.cs
index 18533989..18caa892 100644
--- a/Framework/YLErp.Core/DBModels/EodSwapPositionResponse.cs
+++ b/Framework/YLErp.Core/DBModels/EodSwapPositionResponse.cs
@@ -36,6 +36,14 @@ namespace YLErp.DBModels
/// 期间付息
///
public decimal PeriodAmount { get; set; }
+ ///
+ /// 到期结算日
+ ///
+ public DateTime? MaturitySettlementDate { get; set; }
+ ///
+ /// 期间分红
+ ///
+ public decimal DividendAmount { get; set; }
public decimal? InitYtm { get; set; }
///
@@ -55,6 +63,10 @@ namespace YLErp.DBModels
///
public decimal MarginInterestAmount { get; set; }
///
+ /// 追加预付金 取轧差
+ ///
+ public decimal AdditionalMarginAmount { get; set; }
+ ///
/// 浮动利率(绝对)利率端待实现收益/(标的名义金额/期初标的交割价格全价)
///
public decimal FloatRateAbs { get; set; }
@@ -71,6 +83,10 @@ namespace YLErp.DBModels
///
public decimal NetSettmentAmount { get; set; }
///
+ /// TRS估值
+ ///
+ public decimal TrsValue { get; set; }
+ ///
/// 交易费用
///
public decimal TradingFee { get; set; }
diff --git a/YLErpDAL/Model/ClientSwapPositionRequest.cs b/YLErpDAL/Model/ClientSwapPositionRequest.cs
index c4883a06..7922a490 100644
--- a/YLErpDAL/Model/ClientSwapPositionRequest.cs
+++ b/YLErpDAL/Model/ClientSwapPositionRequest.cs
@@ -20,6 +20,7 @@ namespace YLErp.Model
public DateTime? ValueDate { get; set; }
public DateTime? ValueDateFrom { get; set; }
public int? ClientId { get; set; }
+ public int? BookId { get; set; }
public string StructureType { get; set; }
}
diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
index 319666ef..37989e5d 100644
--- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
@@ -1902,8 +1902,8 @@ namespace YLErp.Modules.SwapModule
var interestPositions = eodSwapPositions.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//利息腿
var positions = eodSwapPositions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//持仓腿
eod_Swap.NotionalValueLong = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
- eod_Swap.NotionalValueShort = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
- eod_Swap.NotionalValue = eod_Swap.NotionalValueLong + eod_Swap.NotionalValueShort;
+ eod_Swap.NotionalValueShort = -Math.Abs(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue));
+ eod_Swap.NotionalValue = Convert.ToDecimal(td.OriginalStockEqvNotional ?? td.StockEqvNotional);
eod_Swap.SwapTradeId = td.id;
eod_Swap.SwapTradeNo = td.TradeNumber;
eod_Swap.ClientId = td.ClientId;
@@ -1972,9 +1972,9 @@ namespace YLErp.Modules.SwapModule
var eodSwapPositions = DbContext.eod_swap_position.Where(x => x.SwapTradeId == td.id && x.ValueDate == settleDate && !x.Invalid).ToList();
var interestPositions = eodSwapPositions.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//利息腿
var positions = eodSwapPositions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//持仓腿
- eod_Swap.NotionalValue = Convert.ToDecimal(td.StockEqvNotional);
+ eod_Swap.NotionalValue = Convert.ToDecimal(td.OriginalStockEqvNotional ?? td.StockEqvNotional);
eod_Swap.NotionalValueLong = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
- eod_Swap.NotionalValueShort = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
+ eod_Swap.NotionalValueShort = -Math.Abs(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue));
eod_Swap.MarketValueLong = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.UnderlyingMarketValue);
eod_Swap.MarketValueShort = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.UnderlyingMarketValue);
eod_Swap.FloatingPnL = positions.Sum(s => s.PosiProfitSum);
@@ -2164,13 +2164,23 @@ namespace YLErp.Modules.SwapModule
var retListResult = query.ToSearchList(req);
var tradeIds = retListResult.rows.Select(x => x.position.SwapTradeId).Distinct().ToList();
var valueDates = retListResult.rows.Select(x => x.position.ValueDate).Distinct().ToList();
+ var tradeNotionals = DbContext.trade
+ .Where(x => tradeIds.Contains(x.id))
+ .Select(x => new { x.id, x.OriginalStockEqvNotional, x.StockEqvNotional })
+ .ToDictionary(x => x.id);
var eodPositionDetails = DbContext.eod_swap_position
.Where(x => tradeIds.Contains(x.SwapTradeId) && valueDates.Contains(x.ValueDate) && !x.Invalid)
.ToList();
+ var tradeExtends = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
var underlyingDataSource = DataCacheProvider.GetUnderlyingDataSource();
var varietyDataSource = DataCacheProvider.GetVarietyDataSource();
foreach (var item in retListResult.rows)
{
+ item.position.NotionalValueShort = -Math.Abs(item.position.NotionalValueShort);
+ if (tradeNotionals.TryGetValue(item.position.SwapTradeId, out var tradeNotional))
+ {
+ item.position.NotionalValue = Convert.ToDecimal(tradeNotional.OriginalStockEqvNotional ?? tradeNotional.StockEqvNotional);
+ }
var client = DataCacheProvider.GetClientDataSource().GetData(item.ClientId);
item.SwapTradeTypeStr = client?.SwapTradeTypeStr;
var details = eodPositionDetails
@@ -2178,6 +2188,8 @@ namespace YLErp.Modules.SwapModule
.ToList();
var floatingLegs = details.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();
var marginLegs = details.Where(x => marginTypes.Contains(x.InterestMode)).ToList();
+ var tradeExtend = tradeExtends.FirstOrDefault(x => x.TradeId == item.position.SwapTradeId);
+ var dividendPayDate = tradeExtend?.ExtendObj?.DividendPayDate ?? 1;
item.UnderlyingType = string.Join(",", floatingLegs
.Select(x =>
@@ -2189,7 +2201,17 @@ namespace YLErp.Modules.SwapModule
})
.Where(x => !string.IsNullOrWhiteSpace(x))
.Distinct());
- item.PeriodAmount = floatingLegs.Sum(x => x.PosiDividendSum); // 分红 - 为实现
+ item.PeriodAmount = floatingLegs.Sum(x => x.RealizedDividend + x.PosiDividendSum);
+ item.FloatingUnrealizedPnl = floatingLegs.Sum(x => x.PosiMtmPnL);
+ item.InterestPaymentMethod = dividendPayDate == 0 ? "到期轧差" : "派息日支付";
+ if (dividendPayDate == 0)
+ {
+ item.MaturityNettingValuation = item.FloatingUnrealizedPnl + item.position.InterestPnL + item.PeriodAmount;
+ }
+ else
+ {
+ item.PeriodPaymentValuation = item.FloatingUnrealizedPnl + item.position.InterestPnL;
+ }
item.MarginInterestGain = marginLegs
.Where(x => x.InterestDirection == (int)SwapDirectionEnum.收取)
.Sum(x => Math.Abs(x.InterestIncomeSum));
@@ -2340,6 +2362,10 @@ namespace YLErp.Modules.SwapModule
{
predicate = predicate.And(x => x.ClientId == req.ClientId);
}
+ if (req.BookId > 0)
+ {
+ tradePredicate = tradePredicate.And(x => x.AssetId == req.BookId.Value);
+ }
if (req.ValueDateFrom != null)
{
predicate = predicate.And(x => x.ValueDate >= req.ValueDateFrom);
@@ -2373,8 +2399,13 @@ namespace YLErp.Modules.SwapModule
}
var retListResult = query.ToSearchList(req);
var tradeIds = retListResult.rows.Select(s => s.position.SwapTradeId).ToList();
+ if (!tradeIds.Any())
+ {
+ return retListResult;
+ }
interestPredicate = interestPredicate.And(x => tradeIds.Contains(x.SwapTradeId));
var valueDates = retListResult.rows.Select(s => s.position.ValueDate).Distinct().ToList();
+ interestPredicate = interestPredicate.And(x => valueDates.Contains(x.ValueDate));
var eodPositions = DbContext.eod_swap_position.Where(interestPredicate).ToList();
var positions = DbContext.swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && x.InterestMode == (int)InterestModeEnum.初始预付金 && x.IsInitial && !x.Invalid).ToList();
var tradeExtends = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
@@ -2386,6 +2417,14 @@ namespace YLErp.Modules.SwapModule
if (tradeExtend != null)
{
eventDate = QdpCalendarHelper.GetNonHoliday(eventDate.AddDays(tradeExtend.ExtendObj.SettlementRules));
+ if (item.position.PosiMatuirityDate.HasValue)
+ {
+ item.MaturitySettlementDate = QdpCalendarHelper.GetNonHoliday(item.position.PosiMatuirityDate.Value.AddDays(tradeExtend.ExtendObj.SettlementRules));
+ }
+ }
+ else
+ {
+ item.MaturitySettlementDate = item.position.PosiMatuirityDate;
}
item.DayCount = Math.Max(0, (eventDate - item.position.PosiStartDate).Days + 1);
//item.position.PosiProfitSum += item.position.VTradingFee-item.position.PosiFeePending;
@@ -2393,23 +2432,41 @@ namespace YLErp.Modules.SwapModule
//item.position.PosiProfitSum += item.TradingFee;
var posiProfitSum = item.position.PosiProfitSum;
//item.position.PosiProfitSum 不需要加交易费用
- item.position.PosiProfitSum = item.position.PosiProfitSum - item.position.PosiFeePending - item.position.PosiDividendSum;
- item.NetSettmentAmount = item.position.PosiProfitSum + item.position.PosiDividendSum + item.position.PosiFeePending;
- item.PeriodAmount = item.position.PosiDividendSum;
+ var pendingDividend = item.position.PosiDividendSum;
+ item.position.PosiProfitSum = item.position.PosiProfitSum - item.position.PosiFeePending - pendingDividend;
+ if (ConsGlobal.InstrumentType.IsBond(item.position.UnderlyingInstrumentType))
+ {
+ item.PeriodAmount = pendingDividend;
+ item.DividendAmount = 0;
+ }
+ else
+ {
+ item.PeriodAmount = 0;
+ item.DividendAmount = pendingDividend;
+ }
+ item.NetSettmentAmount = item.position.PosiProfitSum + item.PeriodAmount + item.DividendAmount + item.position.PosiFeePending;
var margins = positions.Where(x => x.SwapTradeId == item.position.SwapTradeId);
var interests = eodPositions.Where(x => x.SwapTradeId == item.position.SwapTradeId && x.ValueDate == item.position.ValueDate);
var eodMargins = interests.Where(x => marginTypes.Contains(x.InterestMode));
var eodInterests = interests.Where(x => !marginTypes.Contains(x.InterestMode));
+ var initialMargins = eodMargins.Where(x => x.InterestMode == (int)InterestModeEnum.初始预付金);
+ var additionalMargins = eodMargins.Where(x => x.InterestMode == (int)InterestModeEnum.追加预付金);
var floatRateInterest = eodInterests.Where(x => !string.IsNullOrEmpty(x.FloatRateUnderlyingCode)).FirstOrDefault();
item.position.FloatRateUnderlyingCode = floatRateInterest?.FloatRateUnderlyingCode;
item.position.FloatRate = floatRateInterest?.FloatRate ?? 0;
- item.OpenMarginAmount = margins.Sum(s => s.InterestPrincipalFix * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
- item.OpenMarginRate = margins.Sum(s => s.InterestRateDefault * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
+ item.OpenMarginAmount = initialMargins.Any()
+ ? initialMargins.Sum(s => s.InterestPrincipalFix * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1))
+ : margins.Sum(s => s.InterestPrincipalFix * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
+ item.OpenMarginRate = initialMargins.Any()
+ ? initialMargins.Sum(s => s.InterestRateDefault * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1))
+ : margins.Sum(s => s.InterestRateDefault * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
+ item.AdditionalMarginAmount = additionalMargins.Sum(s => s.InterestPrincipalFix * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
item.MarginInterestAmount = eodMargins.Sum(s => s.InterestIncomeSum * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
item.InterestAmount = eodInterests.Sum(s => s.InterestIncomeSum * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? -1 : 1));
item.InterestRate = eodInterests.Sum(s => s.InterestRateDefault);
- item.NetSettmentAmount += item.InterestAmount + item.MarginInterestAmount + eodMargins.Sum(s => s.InterestPrincipalFix * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
+ item.NetSettmentAmount += item.InterestAmount + item.MarginInterestAmount;
item.NetSettmentAmount = Math.Round(item.NetSettmentAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
+ item.TrsValue = Math.Round(item.NetSettmentAmount + item.OpenMarginAmount + item.AdditionalMarginAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
if (item.position.PosiNotionalValue != 0 && item.position.PosiNetPrice != 0)
{
item.FloatRateAbs = item.position.PosiNotionalValue == 0 ? 0 : item.InterestAmount / item.position.PosiNotionalValue;
diff --git a/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml b/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml
index 1429aaec..8cfa8006 100644
--- a/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml
+++ b/YLErpWeb/Views/SwapTrade2/TradeMarketReport_EodPosition.cshtml
@@ -39,6 +39,7 @@
}
@section JS{
+
-