fix: 实时持仓计算持仓盈亏

This commit is contained in:
gongpei
2025-10-29 17:25:14 +08:00
parent d8d7dee562
commit e891ce8faa
+23 -21
View File
@@ -510,7 +510,7 @@ namespace YLErp.BLL.Eod
&& t.TradeType == "收益互换").ToList();
//OTC持仓交易
var tradeIdList = tradeList.Select(t => t.id).ToList();
var positions = db.swap_position.Where(x => tradeIdList.Contains(x.SwapTradeId) && !x.IsInitial && x.PosiQuantity > 0&&!x.Invalid).ToList();
var positions = db.swap_position.Where(x => tradeIdList.Contains(x.SwapTradeId) && !x.IsInitial && x.PosiQuantity > 0 && !x.Invalid).ToList();
var swapFlows = db.swap_flow.Where(x => x.DataState == (int)SwapFlowDateStateEnum.).ToList();
using var bondDb = new BondOmsDBContext();
var clientPositions = bondDb.client_position.AsEnumerable();
@@ -533,18 +533,18 @@ namespace YLErp.BLL.Eod
td,
p
};
var positionGroup = query.AsEnumerable().GroupBy(x => new { x.p.UnderlyingCode, x.td.ClientId,x.p.PosiDirection});
var positionGroup = query.AsEnumerable().GroupBy(x => new { x.p.UnderlyingCode, x.td.ClientId, x.p.PosiDirection });
var dealSwapFlowIds = new List<long>();
SwapTradeAutoService swapTradeAutoService = new SwapTradeAutoService(optUser);
var datenow = DateTime.Now;
foreach (var pair in positionGroup)
{
var client = DataCacheProvider.GetClientDataSource().GetData(pair.Key.ClientId);
if (client == null||string.IsNullOrEmpty(pair.Key.UnderlyingCode))
if (client == null || string.IsNullOrEmpty(pair.Key.UnderlyingCode))
{
continue;
}
var clientPosition = clientPositions.FirstOrDefault(x => x.client_id == pair.Key.ClientId && x.security_id == pair.Key.UnderlyingCode&&x.direction== pair.Key.PosiDirection);
var clientPosition = clientPositions.FirstOrDefault(x => x.client_id == pair.Key.ClientId && x.security_id == pair.Key.UnderlyingCode && x.direction == pair.Key.PosiDirection);
var trades = pair.Select(s => s.td).ToList();
var tradeIds = trades.Select(x => x.id);
var positionGroupItems = positions.Where(x => tradeIds.Contains(x.SwapTradeId) && x.UnderlyingCode == pair.Key.UnderlyingCode && x.PosiDirection == pair.Key.PosiDirection);
@@ -563,15 +563,17 @@ namespace YLErp.BLL.Eod
var multiplier = ConsGlobal.InstrumentType.IsBond(lastPosi.UnderlyingInstrumentType) ? ConsGlobal.bondShowPriceMultiple : 1;
// 计算加权平均价格(区分债券和非债券)
var weightedPrice = posiQty==0?0: positionGroupItems
.Sum(s => {
var weightedPrice = posiQty == 0 ? 0 : positionGroupItems
.Sum(s =>
{
decimal price = ConsGlobal.InstrumentType.IsBond(lastPosi.UnderlyingInstrumentType)
? s.PosiGrossPrice * ConsGlobal.bondShowPriceMultiple
: s.PosiGrossPrice;
return s.PosiQuantity * price;
}) / posiQty;
var weightedNetPrice = posiQty==0?0: positionGroupItems
.Sum(s => {
var weightedNetPrice = posiQty == 0 ? 0 : positionGroupItems
.Sum(s =>
{
decimal price = ConsGlobal.InstrumentType.IsBond(lastPosi.UnderlyingInstrumentType)
? s.PosiNetPrice * ConsGlobal.bondShowPriceMultiple
: s.PosiNetPrice;
@@ -584,7 +586,7 @@ namespace YLErp.BLL.Eod
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(pair.Key.UnderlyingCode);
clientPosition = CreateClientPosition(clientPosition, pair.Key.ClientId, pair.Key.UnderlyingCode, netPrice, price, posiQty / 10000, comminsions, positionType == PositionTypeFlag.Long ? 0 : 1, lastPosi.ContractSize, pair.Key.PosiDirection);
clientPosition.position_notional_principal = totalNotional;
if (pair.Key.PosiDirection==(int)SwapDirectionEnum.)
if (pair.Key.PosiDirection == (int)SwapDirectionEnum.)
{
var flowMerges = MergeSwapFlow(newSwapFlows, multiplier);
dealSwapFlowIds.AddRange(newSwapFlows.Select(s => s.id));
@@ -596,7 +598,7 @@ namespace YLErp.BLL.Eod
clientPosition.update_user = 0;
SetClientPositionPrice(clientPosition);
clientPosition.swap_market_value = clientPosition.full_price_now * clientPosition.position_qty * (clientPosition.side == 0 ? 1 : -1);
clientPosition.position_profit_loss = (clientPosition.full_price_now - clientPosition.deal_full_price_avg) * clientPosition.position_qty * (clientPosition.side == 0 ? 1 : -1) - clientPosition.commission;
clientPosition.position_profit_loss = (clientPosition.full_price_now - clientPosition.deal_full_price_avg) * 0.01m * (clientPosition.position_qty * 10000) * (clientPosition.side == 0 ? 1 : -1) - clientPosition.commission;
clientPosition.position_profit_loss = Math.Round(clientPosition.position_profit_loss ?? 0, 2, MidpointRounding.AwayFromZero);
clientPosition.today_profit_loss = clientPosition.swap_market_value - lastPv;
if (clientPosition.deal_full_price_avg > 0 && enableCalcBongd)//发kafka 获取成交收益率
@@ -629,7 +631,7 @@ namespace YLErp.BLL.Eod
continue;
}
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlowGroup.Key.UnderlyingCode);
var multiplier = um!=null&& um.IsBond() ? ConsGlobal.bondShowPriceMultiple : 1;
var multiplier = um != null && um.IsBond() ? ConsGlobal.bondShowPriceMultiple : 1;
var flowMerges = MergeSwapFlow(swapFlowGroup.ToList(), multiplier);
var flowMergeMax = flowMerges.OrderByDescending(s => s.TradingQty).First();
var flowMergeMin = flowMerges.FirstOrDefault(x => x.BsType != flowMergeMax.BsType);
@@ -665,7 +667,7 @@ namespace YLErp.BLL.Eod
bondDb.SaveChanges();
}
}
sql = $"{nameof(ClientPosition.create_time)}<'{datenow.AddSeconds(-1):yyyy-MM-dd HH:mm:ss}' or {nameof(ClientPosition.position_qty)}=0";
sql = $"{nameof(ClientPosition.create_time)}<'{datenow.AddSeconds(-1):yyyy-MM-dd HH:mm:ss}' or {nameof(ClientPosition.position_qty)}=0";
bondDb.BulkDelete<ClientPosition>(sql);
bondDb.SaveChanges();
#endregion
@@ -741,10 +743,10 @@ namespace YLErp.BLL.Eod
private static void BondCalcApi(ClientPosition clientPosition)
{
var resp = BondCalcHepler.BondCalc(clientPosition.security_id, clientPosition.deal_full_price_avg ?? 0, "DP");
if (resp!=null)
if (resp != null)
{
clientPosition.deal_yield_avg = resp.ytm* ConsGlobal.bondPriceMultiple;
_yLCache.StringSetWithNoPrefix<CalBondResult>("TRS-BondFullPrice:" + clientPosition.security_id, resp,TimeSpan.FromHours(1));
clientPosition.deal_yield_avg = resp.ytm * ConsGlobal.bondPriceMultiple;
_yLCache.StringSetWithNoPrefix<CalBondResult>("TRS-BondFullPrice:" + clientPosition.security_id, resp, TimeSpan.FromHours(1));
}
}
/// <summary>
@@ -759,7 +761,7 @@ namespace YLErp.BLL.Eod
/// <param name="comminsion"></param>
/// <param name="side"></param>
/// <returns></returns>
private static ClientPosition CreateClientPosition(ClientPosition clientPosition, int clientId, string underlyingCode, decimal price, decimal fullPrice, decimal qty, decimal comminsion, int side,decimal contractsize,int direction)
private static ClientPosition CreateClientPosition(ClientPosition clientPosition, int clientId, string underlyingCode, decimal price, decimal fullPrice, decimal qty, decimal comminsion, int side, decimal contractsize, int direction)
{
var underlyingName = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode)?.UnderlyingName;
var client = DataCacheProvider.GetClientDataSource().GetData(clientId);
@@ -781,7 +783,7 @@ namespace YLErp.BLL.Eod
clientPosition.side = side;
clientPosition.create_time = DateTime.Now;
clientPosition.client_user_id = 0;
clientPosition.position_notional_principal = fullPrice* qty * 10000 * contractsize * ConsGlobal.bondPriceMultiple;
clientPosition.position_notional_principal = fullPrice * qty * 10000 * contractsize * ConsGlobal.bondPriceMultiple;
clientPosition.direction = direction;
return clientPosition;
}
@@ -865,7 +867,7 @@ namespace YLErp.BLL.Eod
clientPosition.deal_full_price_avg = priceResult.Item1;
}
clientPosition.commission = flowMerges.Sum(s => s.TradingFee);
clientPosition.position_qty = Math.Abs(allPosiQty/10000);
clientPosition.position_qty = Math.Abs(allPosiQty / 10000);
clientPosition.position_notional_principal = Math.Abs(allPosiQty) * clientPosition.deal_full_price_avg * ConsGlobal.bondPriceMultiple;
if (allPosiQty < 0)
{
@@ -881,7 +883,7 @@ namespace YLErp.BLL.Eod
return (clientPosition.deal_full_price_avg ?? 0, clientPosition.deal_price_avg ?? 0);
}
var sameAmount = flowMergeSame.TradingAmountAvg * flowMergeSame.TradingQty;
var sameNetAmount = (flowMergeSame.TradingAmountNetAvg??0) * flowMergeSame.TradingQty;
var sameNetAmount = (flowMergeSame.TradingAmountNetAvg ?? 0) * flowMergeSame.TradingQty;
var totalQty = (clientPosition.position_qty ?? 0) + flowMergeSame.TradingQty;
if (totalQty == 0)
{
@@ -1052,7 +1054,7 @@ namespace YLErp.BLL.Eod
//根据TradeId,VolType,ValueDate更新已经存在的数据
var tradeids = resultRisks.Select(t => t.TradeId).ToList();
var tradeRisks = db.realtime_trade_risk.Where(x => tradeids.Contains(x.TradeId) && x.VolType == volType && x.ValueDate == valueDate).ToList();
var delTradeRisks= db.realtime_trade_risk.Where(x => !tradeids.Contains(x.TradeId) && x.VolType == volType && x.ValueDate == valueDate).ToList();
var delTradeRisks = db.realtime_trade_risk.Where(x => !tradeids.Contains(x.TradeId) && x.VolType == volType && x.ValueDate == valueDate).ToList();
db.realtime_trade_risk.RemoveRange(delTradeRisks);
for (var i = 0; i < tradeRisks.Count; i++)
{
@@ -2388,7 +2390,7 @@ namespace YLErp.BLL.Eod
public static ClientBalanceForTrsResponse GetClientBalance(int clientId)
{
if (_yLCache!=null)
if (_yLCache != null)
{
return _yLCache.StringGet<ClientBalanceForTrsResponse>("ClientBalance:" + clientId);
}