feat(swap): 实现互换交易价格精度控制功能 init
- 添加 swapPricePrecisionHelper.js 工具类处理价格精度格式化 - 新增 swappriceprecision.js 配置文件定义各类金融产品的精度规则 - 在 EodPositionRisks.cshtml 和 SwapIncome.cshtml 中引入新的价格格式化脚本 - 替换原有的价格格式化函数为基于产品类型的动态精度控制 - 移除旧的价格验证和标准化逻辑,改用新的精度控制机制 - 添加 vue-swap-price-input 组件用于精确的价格输入控制 - 更新 Controller 中的价格处理逻辑以支持新精度格式化方式
This commit is contained in:
@@ -37,7 +37,6 @@ namespace YLErp.Modules.SwapModule
|
||||
protected virtual long SaveSwapDeal(UnwindData unwindData, int eventType, int clientCashId, string eventResason = "", bool approve = false)
|
||||
{
|
||||
NormalizeNotionalValues(unwindData);
|
||||
NormalizeDeliveryPrices(unwindData.FlowEvents);
|
||||
return SaveSwapDealInternal(unwindData, eventType, clientCashId, eventResason, approve);
|
||||
}
|
||||
|
||||
@@ -48,49 +47,6 @@ namespace YLErp.Modules.SwapModule
|
||||
unwindData.CloseNotionalValue = Math.Round(unwindData.CloseNotionalValue, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
private static int GetStorageDeliveryPriceRound(swap_flow_event flowEvent)
|
||||
{
|
||||
if (ConsGlobal.InstrumentType.IsBond(flowEvent?.UnderlyingInstrumentType))
|
||||
{
|
||||
return ConsGlobal.PriceRound;
|
||||
}
|
||||
if (string.IsNullOrEmpty(flowEvent?.UnderlyingCode))
|
||||
{
|
||||
return ConsGlobal.SwapDeliveryPriceRound;
|
||||
}
|
||||
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(flowEvent?.UnderlyingCode);
|
||||
return underlying?.IsBond() == true ? ConsGlobal.PriceRound : ConsGlobal.SwapDeliveryPriceRound;
|
||||
}
|
||||
|
||||
private static void ValidateDeliveryPrices(UnwindData unwindData)
|
||||
{
|
||||
if (unwindData.FlowEvents == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var item in unwindData.FlowEvents.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)))
|
||||
{
|
||||
var roundedPrice = Math.Round(item.TradingAmountAvg, GetStorageDeliveryPriceRound(item), MidpointRounding.AwayFromZero);
|
||||
if (item.TradingAmountAvg != roundedPrice)
|
||||
{
|
||||
throw new ServiceException($"期末交割价最多保留{ConsGlobal.SwapDeliveryPriceRound}位小数");
|
||||
}
|
||||
item.TradingAmountAvg = roundedPrice;
|
||||
}
|
||||
}
|
||||
|
||||
private static void NormalizeDeliveryPrices(IEnumerable<swap_flow_event> flowEvents)
|
||||
{
|
||||
if (flowEvents == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var item in flowEvents.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)))
|
||||
{
|
||||
item.TradingAmountAvg = Math.Round(item.TradingAmountAvg, GetStorageDeliveryPriceRound(item), MidpointRounding.AwayFromZero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>保存所有变更(生产: DbContext.SaveChanges;测试: 空操作)</summary>
|
||||
protected virtual void SaveAllChanges()
|
||||
{
|
||||
@@ -1291,7 +1247,6 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
throw new ServiceException("未找到交易信息");
|
||||
}
|
||||
ValidateDeliveryPrices(unwindData);
|
||||
NormalizeNotionalValues(unwindData);
|
||||
//CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制
|
||||
ValidateFrontendPnL(unwindData, isIncome: false); // 只读校验告警,不阻断交易
|
||||
@@ -1776,7 +1731,6 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
throw new ServiceException("未找到交易信息");
|
||||
}
|
||||
ValidateDeliveryPrices(unwindData);
|
||||
NormalizeIncomeUnwindDate(unwindData);
|
||||
ValidateIncomeValueDate(unwindData, td);
|
||||
//CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制
|
||||
@@ -1817,14 +1771,12 @@ namespace YLErp.Modules.SwapModule
|
||||
throw new Exception("该笔交易状态为平仓待复核,未找到相关记录,请检查该笔交易是否有效");
|
||||
}
|
||||
swapEvent.unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
|
||||
NormalizeDeliveryPrices(swapEvent.unwindData.FlowEvents);
|
||||
if (eventType == (int)SwapEventTypeEnum.互换)
|
||||
{
|
||||
NormalizeIncomeUnwindDate(swapEvent.unwindData);
|
||||
ValidateIncomeValueDate(swapEvent.unwindData, td);
|
||||
}
|
||||
var flowList = FindFlowEventsByEventId(swapEvent.id);
|
||||
NormalizeDeliveryPrices(flowList);
|
||||
string action = eventType == (int)SwapEventTypeEnum.互换 ? ClientCashInCashOut.系统操作_互换 : ClientCashInCashOut.系统操作_平仓费;
|
||||
int clientCashId = AddClientCash(td, Convert.ToDouble(-swapEvent.unwindData.SwapRealizedPnL), action, swapEvent.unwindData.ValueDate);
|
||||
if (swapEvent.unwindData.SwapMarginAmount != 0)
|
||||
@@ -1867,7 +1819,6 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
throw new ServiceException("未找到交易信息");
|
||||
}
|
||||
ValidateDeliveryPrices(unwindData);
|
||||
if (eventType == (int)SwapEventTypeEnum.互换)
|
||||
{
|
||||
NormalizeIncomeUnwindDate(unwindData);
|
||||
|
||||
@@ -52,16 +52,6 @@ namespace YLErp.Modules.SwapModule
|
||||
|
||||
}
|
||||
|
||||
private static decimal ValidateDeliveryPrice(decimal price, string fieldName)
|
||||
{
|
||||
var roundedPrice = Math.Round(price, ConsGlobal.SwapDeliveryPriceRound, MidpointRounding.AwayFromZero);
|
||||
if (price != roundedPrice)
|
||||
{
|
||||
throw new ServiceException($"{fieldName}最多保留{ConsGlobal.SwapDeliveryPriceRound}位小数");
|
||||
}
|
||||
return roundedPrice;
|
||||
}
|
||||
|
||||
private static decimal? RoundSwapBondNetPriceAndYtm(decimal? value)
|
||||
{
|
||||
return value.HasValue
|
||||
@@ -602,7 +592,7 @@ namespace YLErp.Modules.SwapModule
|
||||
dbTrade.trade_extend = req.trade_extend;
|
||||
dbTrade.swap_positions = req.swap_positions;
|
||||
dbTrade.MetaDic = req.MetaDic;
|
||||
dbTrade.InitYtm = RoundSwapBondNetPriceAndYtm(req.swap_positions.FirstOrDefault(p => p.InitYtm != null)?.InitYtm);
|
||||
dbTrade.InitYtm = req.swap_positions.FirstOrDefault(p => p.InitYtm != null)?.InitYtm;
|
||||
InnerSaveTrade(false, dbTrade, changsStr, changeConfirmStatus);
|
||||
|
||||
return dbTrade;
|
||||
@@ -1381,16 +1371,10 @@ namespace YLErp.Modules.SwapModule
|
||||
position.UnderlyingCode = swap.UnderlyingCode;
|
||||
position.UnderlyingInstrumentType = swap.UnderlyingInstrumentType;
|
||||
position.PosiDirection = swap.PosiDirection;
|
||||
// position.PosiGrossPrice = string.IsNullOrEmpty(swap.UnderlyingCode)
|
||||
// ? Math.Round(swap.PosiGrossPrice, ConsGlobal.SwapDeliveryPriceRound, MidpointRounding.AwayFromZero)
|
||||
// : ValidateDeliveryPrice(swap.PosiGrossPrice, "期初交割价");
|
||||
var storagePriceRound = ConsGlobal.InstrumentType.IsBond(swap.UnderlyingInstrumentType)
|
||||
? ConsGlobal.PriceRound
|
||||
: ConsGlobal.SwapDeliveryPriceRound;
|
||||
position.PosiGrossPrice = Math.Round(swap.PosiGrossPrice, storagePriceRound, MidpointRounding.AwayFromZero);
|
||||
position.PosiGrossPrice = swap.PosiGrossPrice;
|
||||
position.PosiNetPrice = swap.PosiQuantity == 0 ? 0 : (position.PosiGrossPrice + (position.PosiTradingFeePending / swap.PosiQuantity) * ratio);
|
||||
position.PosiNetPrice = Math.Round(position.PosiNetPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
position.PosiNetNoFeePrice = RoundSwapBondNetPriceAndYtm(swap.PosiNetNoFeePrice);
|
||||
position.PosiNetNoFeePrice = swap.PosiNetNoFeePrice;
|
||||
position.PosiNetFeePrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiNetNoFeePrice + (position.PosiTradingFeePending / swap.PosiQuantity) * ratio);
|
||||
position.PosiNetFeePrice = Math.Round(position.PosiNetFeePrice??0, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
position.PosiNotionalValue = Math.Round(swap.PosiNotionalValue, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
|
||||
@@ -1416,7 +1400,7 @@ namespace YLErp.Modules.SwapModule
|
||||
position.interest_rest_days = swap.interest_rest_days;
|
||||
position.interest_rule = swap.interest_rule;
|
||||
position.category_tag = string.IsNullOrEmpty(swap.category_tag) ? "互换利率" : swap.category_tag;
|
||||
position.InitYtm = RoundSwapBondNetPriceAndYtm(swap.InitYtm);
|
||||
position.InitYtm = swap.InitYtm;
|
||||
if (position.InitYtm != null && position.InitYtm > 0)
|
||||
{
|
||||
td.InitYtm = position.InitYtm;
|
||||
|
||||
Reference in New Issue
Block a user