利息计算参考申万poc
This commit is contained in:
@@ -131,6 +131,7 @@ namespace YLErp.Modules.SwapModule
|
||||
td.trade_extend = tradeExtend;
|
||||
var todyEodPositions = allEodPositions.Where(x => x.ValueDate == settleDate).ToList();
|
||||
var allPositionQty = realPositions.Sum(x => x.PosiQuantity);//总剩余持仓数量
|
||||
var orginPv = eodPositions.Sum(s => s.PosiNotionalValue);
|
||||
if (longShort && td.ExerciseDate.Value == settleDate && allPositionQty != 0)//多空组合判断是否已到到期日且无持仓信息
|
||||
{
|
||||
throw new Exception($"交易【{td.TradeNumber}】到期扔有持仓信息");
|
||||
@@ -162,7 +163,7 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0;
|
||||
//处理利息腿
|
||||
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice);
|
||||
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv);
|
||||
DealAutoInterests(autoInterests, td, settleDate, preDealDate, posiLongNotional + posiShortNotional);
|
||||
//多空组合判断是否已到到期日且无持仓信息
|
||||
if (longShort && td.ExerciseDate.Value == settleDate && allPositionQty == 0)
|
||||
@@ -211,50 +212,6 @@ namespace YLErp.Modules.SwapModule
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
/// <summary>
|
||||
/// 追加预付金腿归档
|
||||
/// </summary>
|
||||
/// <param name="settleDate"></param>
|
||||
/// <param name="ClientIds"></param>
|
||||
public void SwapEodMarginCompose(DateTime settleDate, IEnumerable<int> ClientIds)
|
||||
{
|
||||
var tradePredicate = PredicateBuilder.Create<trade>(n => n.ValidState != ConsGlobal.InValid
|
||||
&& n.TradeType == "收益互换"
|
||||
&& n.TradeDate <= settleDate
|
||||
&& n.ExerciseDate >= settleDate
|
||||
&& (n.TradeStatus == ConsTrade.确认成交 || n.UnWindDate >= settleDate)
|
||||
);
|
||||
if (ClientIds != null && ClientIds.Any())
|
||||
{
|
||||
tradePredicate = tradePredicate.And(x => ClientIds.Contains(x.ClientId));
|
||||
}
|
||||
var marginPredicate = PredicateBuilder.Create<swap_position>(n => n.IsInitial && n.HappenDate == settleDate && n.InterestMode == (int)InterestModeEnum.追加预付金 && !n.Invalid);
|
||||
var query = from p in DbContext.swap_position.Where(marginPredicate)
|
||||
join t in DbContext.trade.Where(tradePredicate) on p.SwapTradeId equals t.id
|
||||
select new
|
||||
{
|
||||
t,
|
||||
p
|
||||
};
|
||||
var result = query.ToList();
|
||||
var posiIds = result.Select(x => x.p.id).ToList();
|
||||
var eodSwapPositions = DbContext.eod_swap_position.Where(x => posiIds.Contains(x.SwapTradeId) && x.ValueDate == settleDate).ToList();
|
||||
foreach (var item in result)
|
||||
{
|
||||
List<swap_position> interestList = new List<swap_position>() { item.p };
|
||||
var td = item.t;
|
||||
var eodPosi = eodSwapPositions.FirstOrDefault(x => x.PositionId == item.p.id);
|
||||
var posiLongNotional = eodSwapPositions.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
|
||||
var posiShortNotional = eodSwapPositions.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
|
||||
var grossPrice = eodSwapPositions.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0;
|
||||
//处理利息腿
|
||||
DealInterest(item.p, eodPosi, settleDate, td, posiLongNotional, posiShortNotional, grossPrice);
|
||||
}
|
||||
if (result.Count > 0)
|
||||
{
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 处理利息腿归档
|
||||
/// </summary>
|
||||
/// <param name="interestList">利息腿持仓信息</param>
|
||||
@@ -277,7 +234,8 @@ namespace YLErp.Modules.SwapModule
|
||||
decimal posiLongNational,
|
||||
decimal posiShortNational,
|
||||
decimal closeNational,
|
||||
decimal grossPrice)
|
||||
decimal grossPrice,
|
||||
decimal orginPv)
|
||||
{
|
||||
var hasClose = flowEvents.Any(x => x.EventType == (int)SwapEventTypeEnum.平仓);
|
||||
var hasSwap = flowEvents.Any(x => x.EventType == (int)SwapEventTypeEnum.互换);
|
||||
@@ -299,7 +257,7 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
if (!hasClose)//当日无平仓
|
||||
{
|
||||
var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiLongNational, posiShortNational, grossPrice);
|
||||
var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiLongNational, posiShortNational, grossPrice, orginPv);
|
||||
if (_autoInterests.Count > 0)
|
||||
{
|
||||
autoInterests.AddRange(_autoInterests);
|
||||
@@ -307,7 +265,7 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
else
|
||||
{
|
||||
var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, true, grossPrice);
|
||||
var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, true, grossPrice, orginPv);
|
||||
if (_autoInterests.Count > 0)
|
||||
{
|
||||
autoInterests.AddRange(_autoInterests);
|
||||
@@ -320,38 +278,14 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
else if (hasClose)
|
||||
{
|
||||
SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, false, grossPrice);
|
||||
SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, false, grossPrice, orginPv);
|
||||
}
|
||||
else//无自动互换、互换/平仓,复制上一日终信息,并计算当日新增利息
|
||||
{
|
||||
SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiLongNational, posiShortNational, grossPrice);
|
||||
SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiLongNational, posiShortNational, grossPrice, orginPv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理利息腿归档
|
||||
/// </summary>
|
||||
/// <param name="interestList">利息腿持仓信息</param>
|
||||
/// <param name="eodPositions">上一日终归档持仓信息</param>
|
||||
/// <param name="todyEodPositions">当日归档持仓信息</param>
|
||||
/// <param name="settleDate">当前结算日期</param>
|
||||
/// <param name="td">互换交易主信息</param>
|
||||
/// <param name="swapDeals">当日平仓/互换信息</param>
|
||||
/// <param name="autoInterests">自动互换集合</param>
|
||||
/// <param name="longshortCloseInterests">多空组合平仓利息腿信息</param>
|
||||
/// <param name="lastEodSwap">上一日终框架合约</param>
|
||||
private void DealInterest(swap_position interest,
|
||||
eod_swap_position tdEodPosition,
|
||||
DateTime settleDate,
|
||||
trade td,
|
||||
decimal posiLongNational,
|
||||
decimal posiShortNational,
|
||||
decimal grossPrice)
|
||||
{
|
||||
var insterval = interest.SwapIntervalList.FirstOrDefault(x => x.Date == settleDate && x.Settlement == 1);//自动互换观察日信息
|
||||
SaveAutoEodInterestPosition(null, tdEodPosition, interest, td, settleDate, insterval, null, posiLongNational, posiShortNational, grossPrice);
|
||||
}
|
||||
/// <summary>
|
||||
/// 处理浮动腿归档
|
||||
/// </summary>
|
||||
@@ -758,7 +692,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <param name="preDealDate">上一平仓/互换日期</param>
|
||||
/// <param name="closeAmount">当日平仓金额</param>
|
||||
/// <param name="lastEodSwap">上一日终框架合约估值</param>
|
||||
private List<swap_flow_event> SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiLongNotional, decimal posiShortNational, decimal grossPrice)
|
||||
private List<swap_flow_event> SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiLongNotional, decimal posiShortNational, decimal grossPrice, decimal orginPv)
|
||||
{
|
||||
|
||||
var tradeExtend = td.trade_extend.ExtendObj;
|
||||
@@ -792,7 +726,11 @@ namespace YLErp.Modules.SwapModule
|
||||
positions.Add(position);
|
||||
List<eod_swap_position> preEodPositions = new List<eod_swap_position>();
|
||||
preEodPositions.Add(eodPayPosition);
|
||||
var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, posiNotionalValue, closePercent, (int)SwapEventTypeEnum.自动互换, false, true, grossPrice, true);
|
||||
if (position.InterestMode == (int)InterestModeEnum.固定值)
|
||||
{
|
||||
orginPv = eodPayPosition.InterestPrincipalFix;
|
||||
}
|
||||
var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, posiNotionalValue, closePercent, (int)SwapEventTypeEnum.自动互换, false, true, grossPrice, orginPv, true);
|
||||
decimal InterestAmount = interests.Sum(x => x.InterestAmount);
|
||||
decimal TdInterestAmount = interests.Sum(x => x.TdInterestAmount);
|
||||
|
||||
@@ -855,7 +793,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <param name="closeAmount">当日平仓金额</param>
|
||||
/// <param name="lastEodSwap">上一日终框架合约估值</param>
|
||||
/// <param name="unwintotal">平仓主信息</param>
|
||||
private List<swap_flow_event> SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiLongNotional, decimal posiShortNational, List<swap_flow_event> flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice)
|
||||
private List<swap_flow_event> SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiLongNotional, decimal posiShortNational, List<swap_flow_event> flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice, decimal orginPv)
|
||||
{
|
||||
|
||||
var tradeExtend = td.trade_extend.ExtendObj;
|
||||
@@ -879,6 +817,10 @@ namespace YLErp.Modules.SwapModule
|
||||
newEodPayPosition = eodPayPosition.Clone();
|
||||
newEodPayPosition.id = 0;
|
||||
}
|
||||
if (position.InterestMode == (int)InterestModeEnum.固定值)
|
||||
{
|
||||
orginPv = eodPayPosition.InterestPrincipalFix;
|
||||
}
|
||||
decimal closePercent = oriPosiNotionalValue == 0 ? 0 : closeNational / oriPosiNotionalValue;
|
||||
var eventType = autoSwap ? (int)SwapEventTypeEnum.自动互换 : (int)SwapEventTypeEnum.平仓;
|
||||
bool longShort = td.StructureType == ClientMarginTypeEnum.多空组合.ToString();
|
||||
@@ -894,7 +836,7 @@ namespace YLErp.Modules.SwapModule
|
||||
positions.Add(position);
|
||||
List<eod_swap_position> preEodPositions = new List<eod_swap_position>();
|
||||
preEodPositions.Add(eodPayPosition);
|
||||
var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, closeNational, 1, eventType, false, true, grossPrice, true);
|
||||
var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, closeNational, 1, eventType, false, true, grossPrice, orginPv, true);
|
||||
decimal TdInterestAmount = interests.Sum(x => x.TdInterestAmount);
|
||||
|
||||
newEodPayPosition.ValueDate = valueDate;
|
||||
@@ -968,7 +910,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <param name="preSettleDate">上一交易日</param>
|
||||
/// <param name="valueDate">当前结算日</param>
|
||||
/// <param name="td">互换交易主干</param>
|
||||
private void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiLongNational, decimal posiShortNational, decimal grossPrice)
|
||||
private void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiLongNational, decimal posiShortNational, decimal grossPrice, decimal orginPv)
|
||||
{
|
||||
List<IntervalModel> intervals = position.SwapIntervalList;
|
||||
var tradeExtend = td.trade_extend.ExtendObj;
|
||||
@@ -1003,7 +945,10 @@ namespace YLErp.Modules.SwapModule
|
||||
newEodPayPosition.id = 0;
|
||||
newEodPayPosition.PositionId = position.id;
|
||||
}
|
||||
|
||||
if (position.InterestMode == (int)InterestModeEnum.固定值)
|
||||
{
|
||||
orginPv = eodPayPosition.InterestPrincipalFix;
|
||||
}
|
||||
bool longShort = td.StructureType == ClientMarginTypeEnum.多空组合.ToString();
|
||||
decimal oriPosiNotionalValue = posiLongNational + posiShortNational;
|
||||
decimal posiNotionalValue = oriPosiNotionalValue;
|
||||
@@ -1034,7 +979,7 @@ namespace YLErp.Modules.SwapModule
|
||||
{
|
||||
preEodPositions.Add(eodPayPosition);
|
||||
}
|
||||
var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNational, posiShortNational, posiNotionalValue, closePercent, 0, false, needPrice, grossPrice);
|
||||
var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNational, posiShortNational, posiNotionalValue, closePercent, 0, false, needPrice, grossPrice, orginPv);
|
||||
UpdateDbOption(newEodPayPosition);
|
||||
|
||||
newEodPayPosition.PosiStatus = 0;
|
||||
@@ -2039,43 +1984,7 @@ namespace YLErp.Modules.SwapModule
|
||||
return;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 确认交易后,生成eod数据
|
||||
/// </summary>
|
||||
/// <param name="td"></param>
|
||||
public void InitSaveEodSwapPosition(trade td)
|
||||
{
|
||||
//if (td.StartDate > td.TradeDate)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
var positions = DbContext.swap_position.Where(x => x.SwapTradeId == td.id && x.IsInitial && !x.Invalid).ToList();
|
||||
var posiList = positions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();
|
||||
var interestList = positions.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)).ToList();
|
||||
var eodSwapPostions = DbContext.eod_swap_position.Where(x => x.SwapTradeId == td.id);
|
||||
var eodSwaps = DbContext.eod_swap.Where(x => x.SwapTradeId == td.id);
|
||||
td.trade_extend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == td.id);
|
||||
List<int> eventTypes = new List<int>() { (int)SwapFlowEventTypeEnum.平仓, (int)SwapFlowEventTypeEnum.互换, (int)SwapFlowEventTypeEnum.自动互换, (int)SwapFlowEventTypeEnum.开仓 };
|
||||
var flowEvents = GetSwapFlowEvents(td.id, td.StartDate.Value, eventTypes);//当日平仓/互换/自动互换信息
|
||||
DbContext.eod_swap_position.RemoveRange(eodSwapPostions);
|
||||
DbContext.eod_swap.RemoveRange(eodSwaps);
|
||||
var preday = QdpCalendarHelper.GetNonHolidayDefore(td.StartDate.Value.AddDays(-1));
|
||||
var preSettleDate= QdpCalendarHelper.GetNonHolidayDefore(td.TradeDate.Value.AddDays(-1));
|
||||
var posiLongNotional = positions.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
|
||||
var posiShortNotional = positions.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
|
||||
var grossPrice = posiList.FirstOrDefault()?.PosiGrossPrice ?? 0;
|
||||
foreach (var item in interestList)
|
||||
{
|
||||
SaveEodInterestPositionCopy(null, null, td.StartDate.Value, td, item, null, false, posiLongNotional, posiShortNotional, grossPrice);
|
||||
}
|
||||
foreach (var item in posiList)
|
||||
{
|
||||
SaveCurrentEodInitalPosi(item, td, td.StartDate.Value, preday, flowEvents);
|
||||
}
|
||||
DbContext.SaveChanges();
|
||||
SaveEodSwap(td, td.StartDate.Value, preSettleDate);
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取客户互换持仓信息
|
||||
/// </summary>
|
||||
@@ -2093,25 +2002,6 @@ namespace YLErp.Modules.SwapModule
|
||||
var tradeExtends = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
|
||||
return ConvertEodPnl(eodSwaps, trades, tradeExtends);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取客户互换历史持仓信息
|
||||
/// </summary>
|
||||
/// <param name="clientId"></param>
|
||||
/// <param name="valueDate"></param>
|
||||
/// <returns></returns>
|
||||
public List<eod_position> GetSwapHistoryPositions(int clientId, DateTime valueDate)
|
||||
{
|
||||
var trades = DbContext.trade.Where(x => x.TradeType == "收益互换"
|
||||
&& x.ClientId == clientId
|
||||
&& x.ExerciseDate <= valueDate
|
||||
&& ConsTrade.TradeCompleteStatus.Contains(x.TradeStatus)
|
||||
&& x.ValidState != "InValid").ToList();
|
||||
var tradeIds = trades.Select(s => s.id).ToList();
|
||||
var eodSwaps = DbContext.eod_swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && x.ValueDate == valueDate).ToList();
|
||||
var tradeExtends = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
|
||||
return ConvertEodPnl(eodSwaps, trades, tradeExtends);
|
||||
|
||||
}
|
||||
|
||||
private List<eod_position> ConvertEodPnl(List<eod_swap_position> eodSwaps, List<trade> trades, List<trade_extend> tradeExtends)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user