名义本金算价格
This commit is contained in:
@@ -954,13 +954,13 @@ namespace YLErp.BLL.Eod
|
||||
};
|
||||
|
||||
var todayPostionList = todayPositionQuery.ToArray();
|
||||
//using var bondDb = new BondOmsDBContext();
|
||||
//var clientLongIds = new List<long>();
|
||||
//clientIds.ForEach(item =>
|
||||
//{
|
||||
// clientLongIds.Add(Convert.ToInt64(item));
|
||||
//});
|
||||
//var swapPositionQuery = bondDb.client_position.Where(x => clientLongIds.Contains(x.client_id ?? 0)).ToList().GroupBy(g => g.client_id);
|
||||
using var bondDb = new BondOmsDBContext();
|
||||
var clientLongIds = new List<long>();
|
||||
clientIds.ForEach(item =>
|
||||
{
|
||||
clientLongIds.Add(Convert.ToInt64(item));
|
||||
});
|
||||
var swapPositionQuery = bondDb.client_position.Where(x => clientLongIds.Contains(x.client_id ?? 0)).ToList().GroupBy(g => g.client_id);
|
||||
//持仓合计
|
||||
var pQuerySum = from t in todayPostionList
|
||||
group t by t.ClientId into g
|
||||
@@ -1048,101 +1048,19 @@ namespace YLErp.BLL.Eod
|
||||
|
||||
balance.ClientSellPositionPnl = (parentPositionPnlTotal.FirstOrDefault(x => x.clientId == data.clientId)?.ClientSellPositionPnl ?? 0) + (singlePositionPnlTotal.FirstOrDefault(x => x.clientId == data.clientId)?.ClientSellPositionPnl ?? 0);
|
||||
}
|
||||
//foreach (var data in swapPositionQuery)
|
||||
//{
|
||||
// var clientId = Convert.ToInt32(data.Key);
|
||||
// var balance = _clientBalanceDic[clientId];
|
||||
// var pvSum = data.Sum(s => s.swap_market_value ?? 0);
|
||||
// var pnlSum = data.Sum(s => s.position_profit_loss ?? 0);
|
||||
// var preminumSum = data.Sum(s => s.commission ?? 0);
|
||||
// var dayPnlSum = data.Sum(s => s.today_profit_loss ?? 0);
|
||||
// balance.PotentialSurpluses += -Convert.ToDouble(pvSum);
|
||||
// balance.PositionPv += Convert.ToDouble(pvSum);
|
||||
// balance.RoundedPositionPv += Convert.ToDouble(pvSum);
|
||||
// balance.PositionPnl += Convert.ToDouble(pnlSum);
|
||||
// balance.RoundedPositionPnl += Convert.ToDouble(pnlSum);
|
||||
// balance.PositionPremiumNetCash += Convert.ToDouble(preminumSum);
|
||||
// //balance.DaliyPnl += Convert.ToDouble(dayPnlSum);
|
||||
// //balance.RoundedDaliyPnl += Convert.ToDouble(dayPnlSum);
|
||||
//}
|
||||
//专业版雪球预付金
|
||||
if (PS.Config.ErpElement.SuppotSnowballSpecialist)
|
||||
foreach (var data in swapPositionQuery)
|
||||
{
|
||||
//DbContext.SetDebugLog();
|
||||
|
||||
var query = from p in DbContext.intraday_trade_position
|
||||
join sn in DbContext.trade_snowball on p.TradeId equals sn.TradeId
|
||||
join t in DbContext.trade on p.TradeId equals t.id
|
||||
where p.ValueDate == _valueDate && clientIds.Contains(p.ClientId)
|
||||
&& ConsTrade.NeedMarginTradeStatusList.Contains(p.TradeStatus)
|
||||
&& sn.PrepaymentUsed
|
||||
select new
|
||||
{
|
||||
p.ClientId,
|
||||
Prepayment = (sn.PrepaymentRatio ?? 0) * t.Notional * (t.SpotPrice ?? 0)
|
||||
* (t.BuySell == "卖出" ? 1 : -1)
|
||||
};
|
||||
|
||||
var querySum = from q in query
|
||||
group q by q.ClientId into g
|
||||
select new
|
||||
{
|
||||
ClientId = g.Key,
|
||||
Prepayment = g.Sum(t => t.Prepayment)
|
||||
};
|
||||
|
||||
var sumPrepayments = querySum.ToArray();
|
||||
|
||||
foreach (var item in sumPrepayments)
|
||||
{
|
||||
if (_clientBalanceDic.TryGetValue(item.ClientId, out var balance))
|
||||
{
|
||||
balance.PrepaymentAmount = item.Prepayment;
|
||||
}
|
||||
}
|
||||
var clientId = Convert.ToInt32(data.Key);
|
||||
var balance = _clientBalanceDic[clientId];
|
||||
var pvSum = data.Sum(s => s.swap_market_value ?? 0);
|
||||
var pnlSum = data.Sum(s => s.position_profit_loss ?? 0);
|
||||
var posiSum = data.Sum(s => s.position_notional_principal ?? 0);
|
||||
balance.PotentialSurpluses += Convert.ToDouble(pvSum);
|
||||
balance.PositionPv += Convert.ToDouble(pvSum);
|
||||
balance.RoundedPositionPv += Convert.ToDouble(pvSum);
|
||||
balance.PositionNotionalPrincipal += Convert.ToDouble(posiSum);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取国君互换实时持仓
|
||||
/// </summary>
|
||||
private void ProcessClientSwapPosition_GuoJun(DateTime startDate, DateTime lastSettletDate)
|
||||
{
|
||||
var underlyDataSource = DataCacheProvider.GetUnderlyingDataSource();
|
||||
var varietyDataSource = DataCacheProvider.GetVarietyDataSource();
|
||||
var clientIds = _clientBalanceDic.Keys;
|
||||
var swap_mannualQuery = DbContext.eod_trade_position_swap_mannual.Where(x => x.ValueDate <= startDate && x.ValueDate >= lastSettletDate);//取收盘日后的最大日期
|
||||
if (!swap_mannualQuery.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var maxValueDate = swap_mannualQuery.Max(x => x.ValueDate);
|
||||
var eodPositionSwapMannuals = DbContext.eod_trade_position_swap_mannual.Where(x => x.ValueDate == maxValueDate && clientIds.Contains(x.ClientId)).ToLookup(n => n.ClientId);
|
||||
foreach (var item in eodPositionSwapMannuals)
|
||||
{
|
||||
double swapMargin = 0.0;
|
||||
double swappv = 0.0;
|
||||
double swappnl = 0.0;
|
||||
var eodPostionsSwaps = item.ToList();
|
||||
var clientBalance = _clientBalanceDic[item.Key];
|
||||
foreach (var x in eodPostionsSwaps)
|
||||
{
|
||||
var underly = underlyDataSource.GetData(x.UnderlyingCode);
|
||||
var variety = varietyDataSource.GetData(underly.UnderlyingTypeId);
|
||||
|
||||
_currencyProvider.TryGetCurrencyRate(variety.QuoteCurrency, clientBalance.SettlementCurrency, out var rateObj);
|
||||
//预付金导入是客户方向,其他值是交易员方向
|
||||
swapMargin += (x.Margin) * rateObj.Rate;
|
||||
swappv += (x.PositionPnl - x.TotalFee) * rateObj.Rate;
|
||||
swappnl += (x.PositionPnl * rateObj.Rate);
|
||||
}
|
||||
clientBalance.PositionPnl += swappnl;
|
||||
clientBalance.PositionPv += swappv;
|
||||
clientBalance.RoundedPositionPv += swappv;
|
||||
clientBalance.RoundedPositionPnl += swappnl;
|
||||
clientBalance.PayableMargin -= swapMargin;
|
||||
}
|
||||
|
||||
}
|
||||
//获取当日所有出入金记录
|
||||
private void ProcessClientCash(DateTime lastSettletDate)
|
||||
{
|
||||
@@ -1328,7 +1246,7 @@ namespace YLErp.BLL.Eod
|
||||
var marginList = clientPositions.Where(x =>ConsTrade.InterestMarginModels.Contains(x.InterestMode)).Sum(s=>s.InterestPrincipalFix * (s.InterestDirection == 1 ? -1 : 1));
|
||||
balance.SwapMargin =Convert.ToDouble(marginList);
|
||||
balance.PositionCount= clientTradeIds.Count();
|
||||
balance.PositionNotionalPrincipal = Convert.ToDouble(positions.Sum(s=>s.PosiNotionalValue));//实时
|
||||
// balance.PositionNotionalPrincipal = Convert.ToDouble(positions.Sum(s=>s.PosiNotionalValue));//实时
|
||||
}
|
||||
var eodSwapQuery = DbContext.eod_swap.Where(x => clientIds.Contains(x.ClientId) && x.ValueDate >= lastSettletDate && x.ValueDate <= startDate).AsEnumerable().GroupBy(x => x.SwapTradeId)
|
||||
.Select(g => g.OrderByDescending(x => x.ValueDate).FirstOrDefault()).ToList();
|
||||
@@ -1337,6 +1255,8 @@ namespace YLErp.BLL.Eod
|
||||
eodTradeIds = eodTrades.Select(s => s.id).ToList();
|
||||
eodSwapQuery = eodSwapQuery.Where(x => eodTradeIds.Contains(x.SwapTradeId)).ToList();
|
||||
var eodSwapPositions = DbContext.eod_swap_position.Where(x => eodTradeIds.Contains(x.SwapTradeId) && x.ValueDate >= lastSettletDate && x.ValueDate <= startDate && x.PosiDirection > 0);
|
||||
var swapFlowEvents = DbContext.swap_flow_event.Where(x => x.DataState == (int)SwapFlowDateStateEnum.完成 && x.EventType == (int)SwapFlowEventTypeEnum.平仓 && x.EventDate > lastSettletDate && tradeIds.Contains(x.SwapTradeId)).AsNoTracking().ToList();
|
||||
var swapPositions = DbContext.swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && x.IsInitial && !x.Invalid && x.PosiDirection > 0).AsNoTracking().ToList();
|
||||
var eodSwaps = eodSwapQuery.GroupBy(g => g.ClientId).ToList();
|
||||
foreach (var data in eodSwaps)
|
||||
{
|
||||
@@ -1344,33 +1264,46 @@ namespace YLErp.BLL.Eod
|
||||
var clientEodSwaps = data.GroupBy(g => g.SwapTradeId).ToList();
|
||||
foreach (var item in clientEodSwaps)
|
||||
{
|
||||
var eodSwapList = item.OrderBy(o => o.ValueDate).ToList();
|
||||
var eodSwap = eodSwapList[eodSwapList.Count - 1];
|
||||
var lastEodSwap = eodSwapList.Count <= 1 ? null : eodSwapList[eodSwapList.Count - 2];
|
||||
//潜在行权收益等于实值额
|
||||
balance.PotentialSurpluses += -Convert.ToDouble(eodSwap.PostionValue);
|
||||
//持仓市值
|
||||
balance.PositionPv += Convert.ToDouble(eodSwap.PostionValue);
|
||||
balance.RoundedPositionPv += Math.Round(Convert.ToDouble(eodSwap.PostionValue), 2);
|
||||
balance.SellPv += -Convert.ToDouble(eodSwap.MarketValueShort);
|
||||
//持仓盈亏
|
||||
var pnl = eodSwap.PostionValue;
|
||||
var lastPnl = lastEodSwap?.PostionValue;
|
||||
//当日盈亏
|
||||
if (eodSwap.ValueDate == startDate)
|
||||
var lastEodSwap = item.First();
|
||||
var eodPosi = eodSwapPositions.FirstOrDefault(x => x.ValueDate == lastEodSwap.ValueDate && x.SwapTradeId == lastEodSwap.SwapTradeId);
|
||||
var posiQty = eodPosi?.PosiQuantity ?? 0;
|
||||
var flowEvents = swapFlowEvents.Where(x => x.SwapTradeId == item.Key).ToList();
|
||||
var unwindQty = flowEvents.Sum(s => s.Quantity);
|
||||
var pnl = lastEodSwap.PostionValue;
|
||||
decimal unwindPercent = 0;
|
||||
if (unwindQty != 0)
|
||||
{
|
||||
balance.DaliyPnl += Convert.ToDouble(pnl - lastPnl + eodSwap.TdRealizedPnL);
|
||||
balance.RoundedDaliyPnl += Math.Round(Convert.ToDouble(pnl - lastPnl), 2);
|
||||
balance.UpdateDate = balance.UpdateDate > eodSwap.OptTime ? balance.UpdateDate : eodSwap.OptTime;
|
||||
if (posiQty == 0 || unwindQty >= posiQty)
|
||||
{
|
||||
pnl = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pnl = pnl - (pnl * unwindQty / posiQty);
|
||||
}
|
||||
unwindPercent = posiQty == 0 ? 0 : unwindQty / posiQty;
|
||||
}
|
||||
balance.WinLoss += Convert.ToDouble(eodSwap.TdRealizedPnL);
|
||||
|
||||
var tdRealizedPnL = flowEvents.Where(x => x.EventDate > lastSettletDate).ToList().Sum(s => s.InterestClosePnL + s.MarkClosePnl);
|
||||
var tdRealizedInterestPnL = flowEvents.Where(x => x.EventDate > lastSettletDate).ToList().Sum(s => s.InterestClosePnL * unwindPercent);
|
||||
var currentEvents = flowEvents.Where(x => x.EventDate == startDate).ToList();
|
||||
var currentRealizedPnl = currentEvents.Sum(s => s.InterestClosePnL + s.MarkClosePnl);
|
||||
//潜在行权收益等于实值额
|
||||
balance.PotentialSurpluses += -Convert.ToDouble(pnl);
|
||||
//持仓市值
|
||||
balance.SellPv += -Convert.ToDouble(lastEodSwap.MarketValueShort) * -1;
|
||||
//当日盈亏
|
||||
balance.DaliyPnl += Convert.ToDouble(currentRealizedPnl) * -1;
|
||||
balance.RoundedDaliyPnl += Math.Round(Convert.ToDouble(currentRealizedPnl), 2) * -1;
|
||||
if (lastEodSwap.ValueDate == startDate)
|
||||
{
|
||||
balance.UpdateDate = balance.UpdateDate > lastEodSwap.OptTime ? balance.UpdateDate : lastEodSwap.OptTime;
|
||||
}
|
||||
balance.WinLoss += Convert.ToDouble(tdRealizedPnL) * -1;
|
||||
balance.PositionPnl += Convert.ToDouble(pnl);
|
||||
balance.RoundedPositionPnl += Math.Round(Convert.ToDouble(pnl), 2);
|
||||
//期权空头浮动盈利=∑max(期权空头持仓*(期权合约成本价-期权合约现价), 0) 从客户角度看的
|
||||
balance.ClientSellPositionPnl += Convert.ToDouble(eodSwap.FloatingPnL);
|
||||
balance.ClientSellPositionPnl += Convert.ToDouble(lastEodSwap.FloatingPnL) * -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -1397,7 +1330,10 @@ namespace YLErp.BLL.Eod
|
||||
UnderlyingCode = item.security_id,
|
||||
ClientId = item.client_id ?? 0,
|
||||
ClientName = item.client_name,
|
||||
TradingQty = (item.order_qty ?? 0) - (item.last_shares ?? 0)
|
||||
TradingQty = (item.order_qty ?? 0) - (item.last_shares ?? 0),
|
||||
TradingAmountAvg = item.full_price ?? 0,
|
||||
TradingAmountFeeAvg = item.full_price ?? 0,
|
||||
TradingFee = 0
|
||||
};
|
||||
// clientOrder中数量单位为万
|
||||
flow.TradingQty *= 10000;
|
||||
@@ -1408,25 +1344,27 @@ namespace YLErp.BLL.Eod
|
||||
var positionQuery = from t in DbContext.trade.Where(x => clientIds.Contains(x.ClientId) && x.TradeType == "收益互换" && x.ValidState != ConsGlobal.InValid && ConsTrade.PositionTradeStatusList.Contains(x.TradeStatus))
|
||||
join p in DbContext.swap_position on t.id equals p.SwapTradeId
|
||||
where !p.IsInitial && !p.Invalid
|
||||
select new
|
||||
select new swap_flow
|
||||
{
|
||||
t.ClientId,
|
||||
p.PosiDirection,
|
||||
p.PosiQuantity,
|
||||
p.UnderlyingCode,
|
||||
p.PositionType
|
||||
ClientId = t.ClientId,
|
||||
TradingQty = p.PosiQuantity,
|
||||
UnderlyingCode = p.UnderlyingCode,
|
||||
BsType = p.PositionType,
|
||||
TradingAmountAvg = p.PosiGrossPrice,
|
||||
TradingAmountFeeAvg = p.PosiNetPrice,
|
||||
TradingFee = 0
|
||||
};
|
||||
var positions = positionQuery.ToList();
|
||||
// step4 将未簿记持仓与已有持仓分别 按客户,标的分组计算各自轧差名义本金
|
||||
// 取设置的预付金比例
|
||||
var clientMarginTemplates = DbContext.client_marginrate.Where(x => x.ValueDate <= startDate).OrderByDescending(o => o.ValueDate).AsNoTracking().ToList();
|
||||
var flowGroup = flows.GroupBy(s => new { s.ClientId, s.UnderlyingCode });
|
||||
var flowGroup = flows.GroupBy(s => s.ClientId);
|
||||
foreach (var itemGroup in flowGroup)
|
||||
{
|
||||
var balance = clientBalanceDic[itemGroup.Key.ClientId ?? 0];
|
||||
var balance = clientBalanceDic[itemGroup.Key ?? 0];
|
||||
//string marginType = balance.ClientType == 1 ? "多空组合" : "品种";
|
||||
// 获取客户预付金比例设置
|
||||
var clientMarginTemplate = clientMarginTemplates.FirstOrDefault(x => x.ClientId == itemGroup.Key.ClientId );
|
||||
var clientMarginTemplate = clientMarginTemplates.FirstOrDefault(x => x.ClientId == itemGroup.Key );
|
||||
if (clientMarginTemplate == null)
|
||||
{
|
||||
clientMarginTemplate = clientMarginTemplates.FirstOrDefault(x => x.ClientId == 0 );
|
||||
@@ -1436,84 +1374,89 @@ namespace YLErp.BLL.Eod
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// 获取当前客户当前标的持仓数据,合并后的名义本金数量
|
||||
var positionLsit = positions.Where(x => x.UnderlyingCode == itemGroup.Key.UnderlyingCode && x.ClientId == itemGroup.Key.ClientId).ToList();
|
||||
var positionNotional = positionLsit.Sum(s => s.PosiQuantity * (s.PositionType == (int)PositionTypeFlag.Long ? 1 : -1));
|
||||
//获取虚拟持仓合并后的名义本金数量
|
||||
var virtualNotional = itemGroup.Sum(s => s.TradingQty * (s.BsType == (int)PositionTypeFlag.Long ? 1 : -1));
|
||||
decimal money = CalcFrozanMarginMoney(positionNotional, virtualNotional, balance.ClientType == 1, clientMarginTemplate);
|
||||
balance.FrozenMarginMoney += Convert.ToDouble(money);
|
||||
var clientPositions = positions.Where(x => x.ClientId == itemGroup.Key).ToList();
|
||||
foreach (var item in itemGroup.GroupBy(s => s.UnderlyingCode))
|
||||
{
|
||||
// 获取当前客户当前标的持仓数据,合并后的名义本金数量
|
||||
var positionLsit = clientPositions.Where(x => x.UnderlyingCode == item.Key).ToList();
|
||||
decimal money = CalcDmaMoney(positionLsit, item.ToList(), clientMarginTemplate);
|
||||
balance.FrozenMarginMoney += Convert.ToDouble(money);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算冻结的预付金变化
|
||||
/// 计算流水带来的资金变化
|
||||
/// </summary>
|
||||
/// <param name="positionNotional">持仓名义本金</param>
|
||||
/// <param name="virtualNotional">虚拟持仓名义本金</param>
|
||||
/// <param name="dma">是否定义文件类型客户</param>
|
||||
/// <param name="clientMarginTemplate">预付金设置信息</param>
|
||||
/// <returns></returns>
|
||||
private decimal CalcFrozanMarginMoney(decimal positionNotional, decimal virtualNotional, bool dma, client_marginrate clientMarginTemplate)
|
||||
/// <param name="positions">持仓列表</param>
|
||||
/// <param name="flows">流水列表</param>
|
||||
/// <param name="clientMarginTemplate">客户保证金模板</param>
|
||||
/// <returns>资金变化金额</returns>
|
||||
public decimal CalcDmaMoney(List<swap_flow> positions, List<swap_flow> flows, client_marginrate clientMarginTemplate)
|
||||
{
|
||||
decimal money = 0;
|
||||
var virtualPosi = positionNotional + virtualNotional;
|
||||
var posiType = positionNotional >= 0 ? (int)PositionTypeFlag.Long : (int)PositionTypeFlag.Short;
|
||||
var virtualPosiType = virtualPosi >= 0 ? (int)PositionTypeFlag.Long : (int)PositionTypeFlag.Short;
|
||||
var positionNotionalAbs = Math.Abs(positionNotional);
|
||||
var virtualNotionalAbs = Math.Abs(virtualNotional);
|
||||
decimal longMarginRate = 0;
|
||||
decimal shortMarginRate = 0;
|
||||
//普通客户
|
||||
if (!dma)
|
||||
var marginRate = (decimal)clientMarginTemplate.InitMarginRate;
|
||||
|
||||
// 处理持仓与流水的平仓逻辑
|
||||
foreach (var position in positions.ToList()) // 使用 ToList() 避免修改集合时的问题
|
||||
{
|
||||
longMarginRate = Convert.ToDecimal(clientMarginTemplate.InitMarginRate);
|
||||
shortMarginRate = longMarginRate;
|
||||
}
|
||||
else //定义文件类型客户
|
||||
{
|
||||
longMarginRate = Convert.ToDecimal(clientMarginTemplate.LongInitMarginRate);
|
||||
shortMarginRate = Convert.ToDecimal(clientMarginTemplate.ShortInitMarginRate);
|
||||
}
|
||||
// 当前持仓多头
|
||||
if (posiType == (int)PositionTypeFlag.Long)
|
||||
{
|
||||
if (virtualPosiType == (int)PositionTypeFlag.Long)
|
||||
var oppositeFlows = flows.Where(x => x.BsType != position.BsType && x.TradingQty > 0).ToList();
|
||||
foreach (var flow in oppositeFlows)
|
||||
{
|
||||
money = virtualNotional * longMarginRate;
|
||||
}
|
||||
else //虚拟持仓空头
|
||||
{
|
||||
if (virtualNotionalAbs <= positionNotionalAbs)
|
||||
{
|
||||
money = virtualNotional * longMarginRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
money = (-virtualNotional * shortMarginRate) - positionNotional * (longMarginRate + shortMarginRate);
|
||||
}
|
||||
if (position.TradingQty <= 0) break; // 持仓已处理完毕
|
||||
|
||||
decimal tradedQty = Math.Min(position.TradingQty, flow.TradingQty);
|
||||
money += CalculateClosePositionProfit(position, flow, tradedQty, marginRate, isPositionFlow: true);
|
||||
|
||||
// 更新持仓和流水的数量
|
||||
position.TradingQty -= tradedQty;
|
||||
flow.TradingQty -= tradedQty;
|
||||
}
|
||||
}
|
||||
// 当前持仓空头
|
||||
else
|
||||
|
||||
// 处理流水之间的轧差逻辑
|
||||
foreach (var flow in flows.Where(x => x.TradingQty > 0).ToList())
|
||||
{
|
||||
if (virtualPosiType == (int)PositionTypeFlag.Short)
|
||||
var oppositeFlows = flows.Where(x => x.BsType != flow.BsType && x.TradingQty > 0).ToList();
|
||||
foreach (var oppositeFlow in oppositeFlows)
|
||||
{
|
||||
money = (-virtualNotional) * shortMarginRate;
|
||||
}
|
||||
else //虚拟持仓多头
|
||||
{
|
||||
if (virtualNotionalAbs <= positionNotionalAbs)
|
||||
{
|
||||
money = (-virtualNotional) * shortMarginRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
money = (virtualNotional + positionNotional) * longMarginRate + positionNotional * shortMarginRate;
|
||||
}
|
||||
if (flow.TradingQty <= 0) break; // 当前流水已处理完毕
|
||||
|
||||
decimal tradedQty = Math.Min(flow.TradingQty, oppositeFlow.TradingQty);
|
||||
money += CalculateClosePositionProfit(flow, oppositeFlow, tradedQty, marginRate, isPositionFlow: false);
|
||||
|
||||
// 更新流水的数量
|
||||
flow.TradingQty -= tradedQty;
|
||||
oppositeFlow.TradingQty -= tradedQty;
|
||||
}
|
||||
}
|
||||
return money;
|
||||
|
||||
// 处理剩余流水的新开仓逻辑
|
||||
foreach (var flow in flows.Where(x => x.TradingQty > 0))
|
||||
{
|
||||
// 新开仓保证金
|
||||
money += marginRate * flow.TradingQty * flow.TradingAmountAvg;
|
||||
}
|
||||
|
||||
return Math.Round(money, 2, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算平仓损益和保证金释放
|
||||
/// </summary>
|
||||
private decimal CalculateClosePositionProfit(swap_flow position, swap_flow flow, decimal tradedQty, decimal marginRate, bool isPositionFlow)
|
||||
{
|
||||
decimal floatRatio = -1m; // 默认支付
|
||||
decimal longRatio = position.BsType == 1 ? 1m : -1m;
|
||||
|
||||
// 平仓损益
|
||||
decimal profit = (flow.TradingAmountAvg - position.TradingAmountAvg) * tradedQty * floatRatio * longRatio;
|
||||
|
||||
// 如果是持仓与流水平仓,计算保证金释放;否则不计算
|
||||
decimal releasedMargin = isPositionFlow ? marginRate * tradedQty * position.TradingAmountAvg : 0;
|
||||
|
||||
return profit - releasedMargin;
|
||||
}
|
||||
|
||||
public class ClientBalanceEx : ClientSettleBalance
|
||||
{
|
||||
public double InFundOther { get; set; }
|
||||
|
||||
@@ -586,6 +586,9 @@ namespace YLErp.BLL.Eod
|
||||
}
|
||||
bondDb.SaveChanges();
|
||||
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 = 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,8 +632,10 @@ namespace YLErp.BLL.Eod
|
||||
}
|
||||
bondDb.SaveChanges();
|
||||
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.position_profit_loss = Math.Round(clientPosition.position_profit_loss ?? 0, 2, MidpointRounding.AwayFromZero);
|
||||
clientPosition.today_profit_loss = clientPosition.swap_market_value;
|
||||
|
||||
//发kafka 获取成交收益率
|
||||
if (clientPosition.deal_full_price_avg > 0 && enableCalcBongd)
|
||||
{
|
||||
@@ -781,23 +786,21 @@ namespace YLErp.BLL.Eod
|
||||
UnderlyingCode = swapflow.UnderlyingCode,
|
||||
BsType = swapflow.BsType,
|
||||
TradingQty = gourpItem.Sum(s => s.TradingQty),
|
||||
TradingFeePending = gourpItem.Sum(s => s.TradingFee),
|
||||
TradingFee = gourpItem.Sum(s => s.TradingFee),
|
||||
DataState = (int)SwapFlowDateStateEnum.等待完成,
|
||||
ContractSize = swapflow.ContractSize,
|
||||
ClientId = swapflow.ClientId,
|
||||
TradingAmount = gourpItem.Sum(s => s.TradingAmount)
|
||||
};
|
||||
int tradeSide = swap_flow_summary.BsType == (int)EnumDirection.Long ? 1 : -1;
|
||||
swap_flow_summary.FirstFlowTime = swapflow.OptTime;
|
||||
swap_flow_summary.SettleDate = gourpItem.Max(s => s.SettleDate);
|
||||
swap_flow_summary.TradingAmount = swap_flow_summary.TradingQty * swap_flow_summary.ContractSize;
|
||||
swap_flow_summary.TradingAmountAvg = swap_flow_summary.TradingQty == 0 ? 0 : gourpItem.Sum(s => s.TradingAmountAvg * s.TradingQty) / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountAvg : swap_flow_summary.TradingAmountAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountNetAvg = swap_flow_summary.TradingQty == 0 ? 0 : gourpItem.Sum(s => s.TradingAmountNet * s.TradingQty) / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountNetFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountNetAvg : swap_flow_summary.TradingAmountNetAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountAvg = Math.Round(swap_flow_summary.TradingAmountAvg, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
swap_flow_summary.TradingAmountFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountAvg : swap_flow_summary.TradingAmountAvg + swap_flow_summary.TradingFee * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountFeeAvg = Math.Round(swap_flow_summary.TradingAmountFeeAvg, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
swap_flow_summary.TradingAmountAvg *= multiplier;
|
||||
swap_flow_summary.TradingAmountFeeAvg *= multiplier;
|
||||
swap_flow_summary.TradingAmountNetAvg *= multiplier;
|
||||
swap_flow_summary.TradingAmountNetFeeAvg *= multiplier;
|
||||
list.Add(swap_flow_summary);
|
||||
}
|
||||
return list.OrderByDescending(o => o.TradingQty).ToList();
|
||||
|
||||
@@ -27,5 +27,9 @@ namespace YLErp.Model
|
||||
/// 买卖方向
|
||||
/// </summary>
|
||||
public int side { get; set; }
|
||||
/// <summary>
|
||||
/// 含费全价
|
||||
/// </summary>
|
||||
public decimal price { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,7 +837,7 @@ namespace YLErp.Modules.SwapModule
|
||||
unwindData.AnnualDays = tradeExtend == null ? 365 : tradeExtend.ExtendObj.AnnualDays;
|
||||
unwindData.CloseMethod = unwindQty == unwindData.PositionQty ? (int)CloseMethodEnum.全部平仓 : (int)CloseMethodEnum.部分平仓;
|
||||
unwindData.ClosePercent = unwindData.PositionQty == 0 ? 0 : unwindPercent;
|
||||
unwindData.CloseNotionalValue = unwindData.PosiNotionalValue* unwindPercent;
|
||||
unwindData.CloseNotionalValue = position == null ? 0 : unwindQty * position.PosiGrossPrice * position.ContractSize;
|
||||
unwindData.CloseQty = unwindQty;
|
||||
if (position != null)
|
||||
{
|
||||
@@ -867,9 +867,9 @@ namespace YLErp.Modules.SwapModule
|
||||
floatEvent.TradingFeePending = position.PosiTradingFeePending * unwindData.ClosePercent;
|
||||
var mergeClosePercent = mergeQty == 0 ? 0 : unwindQty / mergeQty;
|
||||
floatEvent.TradingFee = penddingFee * mergeClosePercent;
|
||||
floatEvent.MarkClosePnl = (unwindPriceFee - position.PosiNetPrice) * unwindQty * floatRatio * longRatio;
|
||||
floatEvent.MarkClosePnl = decimal.Parse(floatEvent.MarkClosePnl.ToString("0.00"));
|
||||
floatEvent.TradingAmount = floatEvent.Quantity * floatEvent.ContractSize;
|
||||
floatEvent.MarkClosePnl = (unwindPrice - position.PosiGrossPrice) * unwindQty * floatRatio * longRatio;
|
||||
floatEvent.MarkClosePnl = Math.Round(floatEvent.MarkClosePnl + (floatEvent.TradingFee * floatRatio * -1), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
|
||||
floatEvent.TradingAmount = unwindPrice * floatEvent.Quantity * floatEvent.ContractSize;
|
||||
floatEvent.OptLog = "流水自动";
|
||||
floatEvent.ClientId = td.ClientId;
|
||||
floatEvent.SetOpt(UserInfo);
|
||||
@@ -1038,10 +1038,10 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
AddClientCashInCashOut(td, Convert.ToDouble(unwindData.SwapMarginAmount), ClientCashInCashOut.系统操作_应付预付金, unwindData.ValueDate);
|
||||
}
|
||||
if (unwindData.SwapMarginRebatePnl != 0)
|
||||
{
|
||||
AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut.系统操作_预付金返息, unwindData.ValueDate);
|
||||
}
|
||||
//if (unwindData.SwapMarginRebatePnl != 0)
|
||||
//{
|
||||
// AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut.系统操作_预付金返息, unwindData.ValueDate);
|
||||
//}
|
||||
var flowList = new List<swap_flow_event>(unwindData.FlowEvents);
|
||||
var eventId = SaveSwapDeal(unwindData, (int)SwapEventTypeEnum.平仓, clientCashId, actionMsg);
|
||||
if (unwindData.CloseMethod == (int)CloseMethodEnum.全部平仓)
|
||||
@@ -1376,15 +1376,9 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
if (!string.IsNullOrEmpty(position.UnderlyingCode))
|
||||
{
|
||||
var dealFloat = flowList.FirstOrDefault(x => !string.IsNullOrEmpty(x.UnderlyingCode));
|
||||
if (dealFloat != null)
|
||||
{
|
||||
decimal ratio = dealFloat.EventType == (int)SwapFlowEventTypeEnum.平仓 ? -1m : 1m;
|
||||
position.PosiTradingFeePending += dealFloat.TradingFeePending * ratio;
|
||||
position.PosiDividendIncome += dealFloat.DividendPending;
|
||||
}
|
||||
position.PosiQuantity -= unwindData.CloseQty;
|
||||
position.PosiNotionalValue = position.PosiQuantity * position.ContractSize;
|
||||
position.PosiNotionalValue = position.PosiGrossPrice * position.PosiQuantity * position.ContractSize;
|
||||
position.PosiTradingFee -= position.PosiTradingFee * unwindData.ClosePercent;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1401,73 +1395,6 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 单标的互换更新实时持仓信息
|
||||
/// </summary>
|
||||
/// <param name="deal_Floats"></param>
|
||||
/// <param name="deal_Interests"></param>
|
||||
/// <param name="positions"></param>
|
||||
public void UpdateInitalPosition(DateTime valueDate, trade td, List<swap_position> positions, List<swap_flow_event> swpFlowEvents)
|
||||
{
|
||||
var preSettleDate = GetPreValueDate(valueDate);//上一交易日期
|
||||
var realPositions = positions.Where(x => !x.IsInitial);
|
||||
var originalPositions = positions.Where(x => x.IsInitial);
|
||||
var unwindFlowEvents = swpFlowEvents.Where(x => x.EventType == (int)SwapFlowEventTypeEnum.开仓 || x.EventType == (int)SwapFlowEventTypeEnum.平仓).ToList();
|
||||
List<eod_swap_position> preEodSwapPositions = DbContext.eod_swap_position.Where(x => !x.Invalid && x.SwapTradeId == td.id && valueDate == preSettleDate).ToList();
|
||||
foreach (var position in realPositions)
|
||||
{
|
||||
var currEod = new eod_swap_position() { ContractSize = position.ContractSize };
|
||||
var eod = preEodSwapPositions.FirstOrDefault(x => x.PositionId == position.PositionId);
|
||||
if (eod == null)
|
||||
{
|
||||
eod = new eod_swap_position()
|
||||
{
|
||||
ContractSize = position.ContractSize,
|
||||
PositionType = position.PositionType,
|
||||
PosiDirection = position.PosiDirection,
|
||||
PosiFeePending = 0,
|
||||
PosiNetPrice = position.PosiNetPrice,
|
||||
PosiGrossPrice = position.PosiGrossPrice,
|
||||
PosiNetFeePrice = position.PosiNetFeePrice,
|
||||
PosiNetNoFeePrice = position.PosiNetNoFeePrice,
|
||||
};
|
||||
}
|
||||
new SwapEodPositionService(UserInfo).SetPriceInfoByFlowEvent(eod, currEod, unwindFlowEvents, position);
|
||||
var oriPosition = originalPositions.FirstOrDefault(x => x.id == position.PositionId);
|
||||
position.InterestAmount = currEod.RealizedInterest;
|
||||
position.InterestFeePending = currEod.InterestFeePending;
|
||||
position.PosiTradingFeePending = currEod.PosiFeePending;
|
||||
position.PosiDividendIncome = currEod.PosiDividendSum;
|
||||
position.PosiQuantity = currEod.PosiQuantity;
|
||||
position.PosiNetPrice = currEod.PosiNetPrice;
|
||||
position.PosiGrossPrice = currEod.PosiGrossPrice;
|
||||
position.PosiNetFeePrice = currEod.PosiNetFeePrice;
|
||||
position.PosiNetNoFeePrice = currEod.PosiNetNoFeePrice;
|
||||
position.PosiNotionalValue = currEod.PosiNotionalValue;
|
||||
td.StockEqvNotional = Convert.ToDouble(position.PosiNotionalValue);
|
||||
td.TradeAmount = Convert.ToDouble(position.PosiQuantity);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取标的平仓比例
|
||||
/// </summary>
|
||||
/// <param name="tradeId"></param>
|
||||
/// <returns></returns>
|
||||
private decimal GetUnwindPercent(int tradeId)
|
||||
{
|
||||
var swapEvents = DbContext.swap_event.Where(x => x.SwapTradeId == tradeId && !x.Invalid && x.EventType == (int)SwapEventTypeEnum.平仓).ToList();
|
||||
decimal unwindPercent = 0;
|
||||
foreach (var swapEvent in swapEvents)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(swapEvent.EventData))
|
||||
{
|
||||
swapEvent.unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
|
||||
unwindPercent += swapEvent.unwindData.ClosePercent;
|
||||
}
|
||||
}
|
||||
return unwindPercent;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +156,7 @@ namespace YLErp.Modules.SwapModule
|
||||
var curEodPosis = DealFloatPositions(posiList, realPosiList, eodPositions, todyEodPositions, settleDate, td, preSettleDate, flowEvents);
|
||||
var posiLongNotional = curEodPosis.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
|
||||
var posiShortNotional = curEodPosis.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
|
||||
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize);
|
||||
if (longShort)
|
||||
{
|
||||
closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiNetPrice);
|
||||
}
|
||||
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiNetPrice);
|
||||
var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0;
|
||||
//处理利息腿
|
||||
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv);
|
||||
@@ -314,20 +310,9 @@ namespace YLErp.Modules.SwapModule
|
||||
var unwindEvents = flowEvents.Where(x => x.PositionId == posi.id).ToList();//当前日平仓信息
|
||||
var realPosition = realPosiList.FirstOrDefault(s => s.PositionId == posi.id);
|
||||
eod_swap_position eodPosi = new eod_swap_position();
|
||||
if (eodPosition == null || td.StartDate == settleDate)
|
||||
if (eodPosition == null || td.TradeDate == settleDate)
|
||||
{
|
||||
if (tdEodPosition == null)//第一次生成归档信息
|
||||
{
|
||||
eodPosi = SaveCurrentEodInitalPosi(posi, td, settleDate, preSettleDate, unwindEvents);
|
||||
}
|
||||
else
|
||||
{
|
||||
tdEodPosition.PosiFeePending = posi.PosiTradingFeePending;
|
||||
tdEodPosition.PosiNotionalValue = tdEodPosition.PosiQuantity * tdEodPosition.ContractSize;
|
||||
tdEodPosition.PosiNetFeePrice = posi.PosiNetFeePrice;
|
||||
tdEodPosition.PosiNetNoFeePrice = posi.PosiNetNoFeePrice;
|
||||
}
|
||||
|
||||
eodPosi = SaveCurrentEodInitalPosi(posi, td, settleDate, preSettleDate, unwindEvents);
|
||||
}
|
||||
else if (unwindEvents.Count() == 0)
|
||||
{
|
||||
@@ -1276,12 +1261,12 @@ namespace YLErp.Modules.SwapModule
|
||||
curretEod.PosiNetFeePrice = position.PosiNetFeePrice;
|
||||
curretEod.PosiNetNoFeePrice = position.PosiNetNoFeePrice;
|
||||
curretEod.PosiQuantity = position.PosiQuantity;
|
||||
curretEod.PosiTradingFee = position.PosiTradingFee;
|
||||
curretEod.PosiTradingFee = -position.PosiTradingFee * directionRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
var eventTradingFee = unwindEvents.Where(x => x.EventType == (int)SwapFlowEventTypeEnum.开仓 || x.EventType == (int)SwapFlowEventTypeEnum.平仓).Sum(s => s.TradingFeePending * (s.EventType == (int)SwapFlowEventTypeEnum.开仓 ? 1 : -1));
|
||||
curretEod.PosiFeePending = eod.PosiFeePending + eventTradingFee;
|
||||
var eventTradingFee = openFlowEvents.Sum(s => s.TradingFee);
|
||||
curretEod.PosiTradingFee = eod.PosiTradingFee - eventTradingFee * directionRatio;
|
||||
if (openFlowEvents.Count() == 0)
|
||||
{
|
||||
curretEod.PosiNetPrice = eod.PosiNetPrice;
|
||||
@@ -1297,12 +1282,16 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
posiQty = 0;
|
||||
}
|
||||
curretEod.PosiGrossPrice = (eod.PosiGrossPrice * posiQty + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountAvg)) / (eod.PosiQuantity + openQty);
|
||||
curretEod.PosiNetNoFeePrice = (eod.PosiNetNoFeePrice * posiQty + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountNetAvg)) / (eod.PosiQuantity + openQty);
|
||||
curretEod.PosiNetFeePrice = curretEod.PosiQuantity == 0 ? eod.PosiNetFeePrice : curretEod.PosiNetNoFeePrice + curretEod.PosiFeePending / curretEod.PosiQuantity * shortRatio;
|
||||
curretEod.PosiNetPrice = curretEod.PosiQuantity == 0 ? eod.PosiNetPrice : curretEod.PosiGrossPrice + curretEod.PosiFeePending / curretEod.PosiQuantity * shortRatio;
|
||||
curretEod.PosiGrossPrice = (eod.PosiGrossPrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountAvg)) / (eod.PosiQuantity + openQty);
|
||||
curretEod.PosiGrossPrice = Math.Round(curretEod.PosiGrossPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
curretEod.PosiNetPrice = (eod.PosiNetPrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountFeeAvg)) / (eod.PosiQuantity + openQty);
|
||||
curretEod.PosiNetPrice = Math.Round(curretEod.PosiNetPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
curretEod.PosiNetNoFeePrice = (eod.PosiNetNoFeePrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountNetAvg)) / (eod.PosiQuantity + openQty);
|
||||
curretEod.PosiNetNoFeePrice = Math.Round(curretEod.PosiNetNoFeePrice ?? 0, 10, MidpointRounding.AwayFromZero);
|
||||
curretEod.PosiNetFeePrice = (eod.PosiNetFeePrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountNetFeeAvg)) / (eod.PosiQuantity + openQty);
|
||||
curretEod.PosiNetFeePrice = Math.Round(curretEod.PosiNetFeePrice ?? 0, 10, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
curretEod.PosiNotionalValue = curretEod.PosiQuantity * curretEod.ContractSize;
|
||||
curretEod.PosiNotionalValue = curretEod.PosiGrossPrice * curretEod.PosiQuantity * curretEod.ContractSize;
|
||||
curretEod.TdPosiDividend = unwindEvents.Sum(x => x.DividendIn) * directionRatio;
|
||||
//curretEod.TdCloseFee = unwindEvents.Sum(x => x.TradingFee);
|
||||
curretEod.TdCloseQty = unwindQty;
|
||||
|
||||
@@ -341,15 +341,19 @@ namespace YLErp.Modules.SwapModule
|
||||
DataState = (int)SwapFlowDateStateEnum.等待完成,
|
||||
ContractSize = swapflow.ContractSize,
|
||||
ClientId = swapflow.ClientId,
|
||||
TradingAmount = gourpItem.Sum(s => s.TradingAmount),
|
||||
};
|
||||
int tradeSide = swap_flow_summary.BsType == (int)EnumDirection.Long ? 1 : -1;
|
||||
swap_flow_summary.FirstFlowTime = swapflow.OptTime;
|
||||
swap_flow_summary.SettleDate = gourpItem.Max(s => s.SettleDate);
|
||||
swap_flow_summary.TradingAmount = swap_flow_summary.TradingQty * swap_flow_summary.ContractSize;
|
||||
swap_flow_summary.TradingAmountAvg = swap_flow_summary.TradingQty == 0 ? 0 : gourpItem.Sum(s => s.TradingAmountAvg * s.TradingQty) / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountAvg : swap_flow_summary.TradingAmountAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountAvg = Math.Round(swap_flow_summary.TradingAmountAvg, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
swap_flow_summary.TradingAmountFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountAvg : swap_flow_summary.TradingAmountAvg + swap_flow_summary.TradingFee * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountFeeAvg = Math.Round(swap_flow_summary.TradingAmountFeeAvg, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
swap_flow_summary.TradingAmountNetAvg = swap_flow_summary.TradingQty == 0 ? 0 : gourpItem.Sum(s => s.TradingAmountNet * s.TradingQty) / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountNetFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountNetAvg : swap_flow_summary.TradingAmountNetAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountNetAvg = Math.Round(swap_flow_summary.TradingAmountNetAvg ?? 0, 10);
|
||||
swap_flow_summary.TradingAmountNetFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountNetAvg : swap_flow_summary.TradingAmountNetAvg + swap_flow_summary.TradingFee * tradeSide / swap_flow_summary.TradingQty;
|
||||
swap_flow_summary.TradingAmountNetFeeAvg = Math.Round(swap_flow_summary.TradingAmountNetFeeAvg ?? 0, 10);
|
||||
swap_flow_summary.SetOpt(UserInfo);
|
||||
if (save)
|
||||
{
|
||||
|
||||
@@ -114,32 +114,6 @@ namespace YLErp.Modules.SwapModule
|
||||
return dbTrade;
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成推送记录给衡泰
|
||||
/// </summary>
|
||||
/// <param name="add"></param>
|
||||
/// <param name="td"></param>
|
||||
public void AddPushLog(trade td)
|
||||
{
|
||||
bool longShort = td.StructureType == "多空组合";
|
||||
if (!longShort)
|
||||
{
|
||||
AddSinglePushLog(td);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成非多空组合记录
|
||||
/// </summary>
|
||||
/// <param name="add"></param>
|
||||
/// <param name="td"></param>
|
||||
/// <param name="posiPositions"></param>
|
||||
public void AddSinglePushLog(trade td)
|
||||
{
|
||||
var marginModes = new int[] { (int)InterestModeEnum.追加预付金, (int)InterestModeEnum.初始预付金 };
|
||||
var positions = DbContext.swap_position.Where(x => x.SwapTradeId == td.id && x.IsInitial && !x.Invalid).ToList();
|
||||
td.swap_positions = positions.Where(x => marginModes.Contains(x.InterestMode)).ToList();
|
||||
var posiPositions = positions.Where(x => x.PosiDirection > 0).ToList();
|
||||
}
|
||||
/// <summary>
|
||||
/// 单标的生成开仓事件
|
||||
/// </summary>
|
||||
/// <param name="td"></param>
|
||||
@@ -254,20 +228,6 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
var dbTrade = req.Clone();
|
||||
DbContext.trade.Add(dbTrade);
|
||||
//申万交易编号特殊处理(如果交易编号是用户手动输入时)
|
||||
if (!tradeNumberGenerated && PS.Config.Is申万)
|
||||
{
|
||||
var client = DataCacheProvider.GetClientDataSource().GetData(dbTrade.ClientId);
|
||||
if (client?.Code != null && dbTrade.TradeNumber.StartsWith(client.Code))
|
||||
{
|
||||
var canParseInt = int.TryParse(dbTrade.TradeNumber.Substring(client.Code.Length), out var contractNo);
|
||||
if (canParseInt && contractNo > (client.CurrentContractNo ?? 0))
|
||||
{
|
||||
client.CurrentContractNo = contractNo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InnerSaveTrade(true, dbTrade, "");
|
||||
|
||||
return dbTrade;
|
||||
@@ -413,10 +373,8 @@ namespace YLErp.Modules.SwapModule
|
||||
PosiNetFeePrice = flowMerge.TradingAmountNetFeeAvg ?? 0,
|
||||
PosiNetNoFeePrice = flowMerge.TradingAmountNetAvg ?? 0,
|
||||
PosiQuantity = flowMerge.TradingQtyAbs,
|
||||
PosiNotionalValue = flowMerge.TradingQtyAbs * flowMerge.ContractSize,
|
||||
PosiNotionalValue = flowMerge.TradingAmountAvg * flowMerge.TradingQtyAbs * flowMerge.ContractSize,
|
||||
PosiTradingFeePending = flowMerge.TradingFeePending,
|
||||
//PosiTradingFee = flowMerge.TradingFee,
|
||||
//PosiTradingFeeUnit = flowMerge.TradingQtyAbs == 0 ? 0 : flowMerge.TradingFee * flowMerge.ContractSize / flowMerge.TradingQtyAbs,
|
||||
PosiTradingFee = 0,
|
||||
PosiTradingFeeUnit = 0,
|
||||
SwapTradeId = td.id,
|
||||
@@ -700,10 +658,6 @@ namespace YLErp.Modules.SwapModule
|
||||
new TradeDocumentDataService(this).DeleteBooksAfterEditTrade(dbTrade);
|
||||
}
|
||||
int eventType = isAddNew ? (int)SwapEventTypeEnum.新增交易 : (int)SwapEventTypeEnum.修改交易;
|
||||
if (!string.IsNullOrEmpty(changsStr))
|
||||
{
|
||||
changsStr = new DatatraceQueryService(UserInfo).ReplaceDataChanges(new trade(), changsStr);
|
||||
}
|
||||
new SwapEventService(UserInfo).AddSwapEventDate(dbTrade.TradeDate.Value, dbTrade.id, eventType, "", 0, true, "", true);
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
@@ -1435,10 +1389,9 @@ namespace YLErp.Modules.SwapModule
|
||||
position.UnderlyingInstrumentType = swap.UnderlyingInstrumentType;
|
||||
position.PosiDirection = swap.PosiDirection;
|
||||
position.PosiGrossPrice = swap.PosiGrossPrice;
|
||||
position.PosiNetPrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiGrossPrice + (position.PosiTradingFeePending / swap.PosiQuantity) * ratio);
|
||||
position.PosiNetNoFeePrice = swap.PosiNetNoFeePrice;
|
||||
position.PosiNetFeePrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiNetNoFeePrice + (position.PosiTradingFeePending / swap.PosiQuantity) * ratio);
|
||||
position.PosiNotionalValue = swap.PosiQuantity * swap.ContractSize;
|
||||
position.PosiNetPrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiGrossPrice + (position.PosiTradingFee / swap.PosiQuantity) * ratio);
|
||||
position.PosiNetPrice = Math.Round(position.PosiNetPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
position.PosiNotionalValue = position.PosiGrossPrice * swap.PosiQuantity * swap.ContractSize;
|
||||
position.PosiQuantity = swap.PosiQuantity;
|
||||
position.InterestDirection = swap.InterestDirection;
|
||||
position.InterestMode = swap.InterestMode;
|
||||
@@ -1570,7 +1523,6 @@ namespace YLErp.Modules.SwapModule
|
||||
InvalidTradeOptionDatasByDate(tradeId, valueDate, backToBegin);
|
||||
swapEventService.AddSwapEventDate(valueDate, tradeId, (int)SwapEventTypeEnum.回退, string.Empty, 0, false, $"交易回退至{valueDate:yyyy年MM月dd日}");
|
||||
DbContext.SaveChanges();
|
||||
AddPushLog(td);
|
||||
if (del)
|
||||
{
|
||||
new TradeRiskCheckLogService(UserInfo).DeleteLog(td.TradeNumber, valueDate);//重置风控记录
|
||||
@@ -1708,6 +1660,7 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
posi.InterestAmount = eodPosi.RealizedInterest;
|
||||
posi.InterestFeePending = eodPosi.InterestFeePending;
|
||||
posi.InterestPrincipalFix= eodPosi.InterestPrincipalFix;
|
||||
posi.PosiTradingFeePending = eodPosi.PosiFeePending;
|
||||
posi.PosiDividendIncome = eodPosi.PosiDividendSum;
|
||||
posi.PosiQuantity = eodPosi.PosiQuantity;
|
||||
@@ -1731,8 +1684,6 @@ namespace YLErp.Modules.SwapModule
|
||||
var clientCashs = DbContext.ClientCashInCashOut.Where(x => x.TradeId == td.id && x.HappenDate >= valueDate).ToList();
|
||||
DbContext.ClientCashInCashOut.RemoveRange(clientCashs);
|
||||
DbContext.SaveChanges();
|
||||
var marginPosis = swapPositions.Where(x => x.HappenDate <= valueDate || x.InterestMode == (int)InterestModeEnum.初始预付金).ToList();
|
||||
ResetMarginAmount(td, valueDate, marginPosis);
|
||||
}
|
||||
/// <summary>
|
||||
/// 多空组合回到初始
|
||||
|
||||
@@ -337,8 +337,7 @@ namespace YLErp.Web.Controllers
|
||||
try
|
||||
{
|
||||
bool edit = req.id != 0;
|
||||
var r = swapTradeService.SaveTrade(req);
|
||||
swapTradeService.AddPushLog(r);
|
||||
var r= swapTradeService.SaveTrade(req);
|
||||
Task.Run(() =>
|
||||
{
|
||||
RealtimePnlCalc.RealtimeSwapPosition(new OptUserInfo(0, "互换实时持仓服务", OptUserFrom.Service));
|
||||
|
||||
@@ -191,7 +191,9 @@ namespace YLErp.Web.Controllers
|
||||
BsType = item.side + 1,
|
||||
UnderlyingCode = item.underlyingCode,
|
||||
ClientId = item.clientId,
|
||||
TradingQty = item.tradingQty
|
||||
TradingQty = item.tradingQty,
|
||||
TradingAmountAvg = item.price,
|
||||
TradingAmountFeeAvg = item.price
|
||||
};
|
||||
bondFlows.Add(flow);
|
||||
}
|
||||
@@ -205,7 +207,9 @@ namespace YLErp.Web.Controllers
|
||||
clientId = item.Key
|
||||
};
|
||||
var clientBalanceCache = _yLCache.StringGet<ClientBalanceForTrsResponse>("ClientBalance:" + item.Key);
|
||||
tradeClientCashCalc.availableAmount = (clientBalanceCache?.AvailableMoney ?? 0) - item.Value.FrozenMarginMoney;
|
||||
var availableMoney = clientBalanceCache?.AvailableMoney ?? 0;
|
||||
tradeClientCashCalc.availableAmount = availableMoney - item.Value.FrozenMarginMoney;
|
||||
tradeClientCashCalc.availableAmount = Math.Round(tradeClientCashCalc.availableAmount, 2, MidpointRounding.AwayFromZero);
|
||||
list.Add(tradeClientCashCalc);
|
||||
}
|
||||
return JsonSuccess("", list);
|
||||
|
||||
@@ -205,20 +205,15 @@ const vue = new Vue({
|
||||
},
|
||||
//变更数量
|
||||
changeQuantity(item) {
|
||||
this.changeSpotPrice(item);
|
||||
this.changeTradingFeeUnit(item);
|
||||
this.changeSpotPrice();
|
||||
},
|
||||
//变更标的单价
|
||||
changeSpotPrice(item) {
|
||||
var notional = item.PosiQuantity * item.ContractSize;
|
||||
var stockEqvNotional = this.trade.StructureType != '普通收益互换' ? notional : item.PosiGrossPrice * notional;
|
||||
this.trade.StockEqvNotional = otcformat.trading.stockEqvNotional(stockEqvNotional);
|
||||
this.StockEqvNotional = item.PosiGrossPrice * notional;
|
||||
this.changeSpotPrice();
|
||||
},
|
||||
//变更标的合约乘数
|
||||
changeContractSize(item) {
|
||||
this.changeSpotPrice(item);
|
||||
this.changeTradingFeeUnit(item);
|
||||
this.calcNotional();
|
||||
},
|
||||
//变更名义本金
|
||||
changeStockEqvNotional() {
|
||||
@@ -226,10 +221,9 @@ const vue = new Vue({
|
||||
//计算数量
|
||||
if (this.paySwapList.length > 0) {
|
||||
var item = this.paySwapList[0];
|
||||
var notional = this.trade.StructureType != '普通收益互换' ? item.ContractSize : item.PosiGrossPrice * item.ContractSize;
|
||||
var notional = item.PosiGrossPrice * item.ContractSize;
|
||||
item.PosiQuantity = notional == 0 ? 0 : this.trade.StockEqvNotional / notional;
|
||||
this.StockEqvNotional = item.PosiGrossPrice * item.ContractSize * item.PosiQuantity;
|
||||
this.changeTradingFeeUnit(item);
|
||||
this.calcNotional();
|
||||
}
|
||||
|
||||
},
|
||||
@@ -250,15 +244,23 @@ const vue = new Vue({
|
||||
if (this.Obervation) {
|
||||
this.Obervation.ObservationStart = this.trade.StartDate;
|
||||
}
|
||||
var payItem = this.paySwapList[0];
|
||||
this.getSpotPrice(payItem.UnderlyingCode, this.trade.StartDate, payItem);
|
||||
var national = payItem.PosiQuantity * payItem.ContractSize;
|
||||
var stockEqvNotional = this.trade.StructureType != '普通收益互换' ? national : payItem.PosiGrossPrice * national;//名义本金=期初价格*数量*乘数
|
||||
this.trade.StockEqvNotional = otcformat.trading.stockEqvNotional(stockEqvNotional);
|
||||
this.calcNotional();
|
||||
this.refreshDatepicker();
|
||||
this.changeMarginDate();
|
||||
//this.initMarginRate();
|
||||
},
|
||||
calcNotional(calcPrice) {
|
||||
if (this.paySwapList.length > 0) {
|
||||
var payItem = this.paySwapList[0];
|
||||
if (calcPrice) {
|
||||
this.getSpotPrice(payItem.UnderlyingCode, this.trade.StartDate, payItem);
|
||||
}
|
||||
var national = payItem.PosiQuantity * payItem.ContractSize;
|
||||
var stockEqvNotional = payItem.PosiGrossPrice * national;//名义本金=期初价格*数量*乘数
|
||||
this.trade.StockEqvNotional = otcformat.trading.stockEqvNotional(stockEqvNotional);
|
||||
payItem.PosiNotionalValue = this.StockEqvNotional;
|
||||
}
|
||||
},
|
||||
//变更到期日
|
||||
changeExerciseDate() {
|
||||
this.refreshDatepicker();
|
||||
|
||||
Reference in New Issue
Block a user