Files
zszq-trs/YLErpDAL/Modules/FinancialModule/FinancialVoucherService.cs
T
2024-05-09 14:06:26 +08:00

785 lines
46 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BaseOUDAL;
using YLErp.BLL;
using YLErp.BLL.Eod;
using YLErp.BLL.EodSettlement;
using YLErp.Commons;
using YLErp.Configuration;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Enums;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Model.FinancialVoucherCreator;
using YLErp.Models.Tag;
using YLErp.Modules.EodModule;
using YLErp.Modules.MarketRiskMoudule;
using YLErp.Modules.MarketRiskMoudule.Dto;
using YLErp.Modules.RiskExposure;
using YLErp.Modules.RiskListModule;
using YLErp.Modules.RiskModule;
using YLErp.Modules.SuperviseReportModule.CFMMC2022.Service;
using YLErp.Modules.TagModule;
using YLErp.Modules.TradeModule;
using YLErp.QdpModule;
namespace YLErp.Modules.FinancialModule
{
/// <summary>
/// 财务凭证服务
/// </summary>
public class FinancialVoucherService : YLBaseService
{
public FinancialVoucherService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 获取财务凭证
/// </summary>
public ReturnInfo<List<FinancialStatement>> GetFinancialStatements(FinancialStatementReq req)
{
var resultList = new List<FinancialStatement>();
Task ExecuteAsync(Func<List<FinancialStatement>> func)
{
return Task.Run(func).ContinueWith(t =>
{
if (t.Result?.Count > 0)
{
lock (resultList)
{
resultList.AddRange(t.Result);
}
}
});
}
var tasks = new Task[] {
ExecuteAsync(GetDepositWithdraw),
ExecuteAsync(GetAROrAPOptionFee),
ExecuteAsync(GetMaturityInvestmentIncome),
ExecuteAsync(GetTerminationInvestmentIncome),
};
Task.WaitAll(tasks);
if (req.IsSamePeer.HasValue)
{
var isSamePeer = req.IsSamePeer.Value == SamePeerEnum.IsSamePeer.GetHashCode();
resultList = resultList.Where(d => d.IsSamePeer == isSamePeer).ToList();
}
if (req.AbstractList?.Count > 0)
{
resultList = resultList.Where(f => req.AbstractList.Contains(f.AbstractTye)).ToList();
}
return Return.Success(resultList);
}
private bool IsSamePeer(int clientId)
{
using (var db = DbContextFactory.GetClientDbContext(OptUser))
{
var client = db.client.Where(n => n.id == clientId)
.Select(n => new { n.CustomerNature }).FirstOrDefault();
if (client == null)
{
return false;
//throw new Exception($"id为{clientId}的客户不存在");
}
if (!client.CustomerNature.HasValue)
{
return false;
}
switch ((CustomerNatureEnum)client.CustomerNature)
{
case CustomerNatureEnum.证券公司:
case CustomerNatureEnum.期货风险管理子公司:
return true;
default:
return false;
}
}
}
/// <summary>
/// 获取出入金凭证
/// </summary>
/// <returns></returns>
public List<FinancialStatement> GetDepositWithdraw()
{
List<ClientCashInCashOut> cashInCashOutList;
var resultList = new List<FinancialStatement>();
using (var db = new YLContext())
{
cashInCashOutList = db.ClientCashInCashOut
.Where(c => c.HappenDate == valuedateBLL.ValueDate &&
(c.Direction == "出金" || c.Direction == "入金") && c.State == ClientCashInCashOut.已确认).ToList();
}
if (cashInCashOutList.Count == 0)
{
return resultList;
}
foreach (var clientCashInCashOut in cashInCashOutList)
{
var financialStatement =
DepositWithdrawGenerator.GetFinancialStatement(IsSamePeer(clientCashInCashOut.ClientId.Value),
clientCashInCashOut.ClientName, clientCashInCashOut.Money ?? 0,
clientCashInCashOut.Direction == "出金");
resultList.Add(financialStatement);
}
return resultList;
}
/// <summary>
/// 获取应收应付期权费凭证
/// </summary>
public List<FinancialStatement> GetAROrAPOptionFee()
{
List<TradeExtends> tradeList;
using (var db = new YLContext())
{
var valueDate = valuedateBLL.ValueDate;
var query = from trade in db.trade
join tradecash in db.trade_cash on trade.id equals tradecash.TradeId
join confirmDoc in db.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid)
on new { id = trade.ParentTradeId > 0 ? trade.ParentTradeId : trade.id } equals new { id = confirmDoc.TradeId } into confirmDocT
from confirmDoc in confirmDocT.DefaultIfEmpty()
where
tradecash.ValueDate == valueDate && tradecash.Action == ClientCashInCashOut.系统操作_期权费 &&
tradecash.ValidState != ConsGlobal.InValid && !tradecash.IsDeleted && tradecash.Status == TradeCashStatusEnum.已执行
select new TradeExtends
{
Id = trade.id,
ClientId = trade.ClientId,
ClientName = trade.ClientName,
BuySell = trade.BuySell,
ContractCode = confirmDoc.ContractCode,
OptionFee = tradecash.Amount
};
tradeList = query.ToList();
}
var resultList = new List<FinancialStatement>();
foreach (var trade in tradeList)
{
var financilaStatement = AROrAPOptionFeeGenerator.GetFinancialStatement(
IsSamePeer(trade.ClientId.Value),
trade.ClientName, trade.BuySell == "买入", trade.ContractCode, trade.OptionFee ?? 0);
resultList.Add(financilaStatement);
}
return resultList;
}
/// <summary>
/// 获取到期投资收益凭证
/// </summary>
public List<FinancialStatement> GetMaturityInvestmentIncome()
{
List<TradeExtends> tradeList;
var expiredStatus = ConsTrade.已到期;
var exerciseStatus = ConsTrade.已执行;
using (var db = new YLContext())
{
var valueDate = valuedateBLL.ValueDate;
var query = from trade in db.trade
join tradecash in db.trade_cash
on new { tradeId = trade.id, tradeDate = trade.PremiumPayDate ?? trade.TradeDate ?? DateTime.Now } equals new { tradeId = tradecash.TradeId, tradeDate = tradecash.ValueDate } into tradecashT
from tradecash in tradecashT.DefaultIfEmpty()
join tradecashStrike in db.trade_cash on trade.id equals tradecashStrike.TradeId into
tradecashStrikeT
from tradecashStrike in tradecashStrikeT.DefaultIfEmpty()
join confirmDoc in
db.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid)
on new { id = trade.ParentTradeId > 0 ? trade.ParentTradeId : trade.id } equals new { id = confirmDoc.TradeId } into confirmDocT
from confirmDoc in confirmDocT.DefaultIfEmpty()
where tradecashStrike.ValueDate == valueDate &&
tradecashStrike.Action == ClientCashInCashOut.系统操作_行权费 &&
tradecashStrike.ValidState != ConsGlobal.InValid && !tradecashStrike.IsDeleted &&
tradecashStrike.Status == TradeCashStatusEnum.已执行 && trade.TradeStatus == exerciseStatus
&& tradecash.Action == ClientCashInCashOut.系统操作_期权费 && tradecash.ValidState != ConsGlobal.InValid && !tradecash.IsDeleted &&
tradecash.Status == TradeCashStatusEnum.已执行
select new TradeExtends
{
Id = trade.id,
ClientId = trade.ClientId,
ClientName = trade.ClientName,
BuySell = trade.BuySell,
ContractCode = confirmDoc.ContractCode,
OptionFee = tradecash.Amount,
StrikeFee = tradecashStrike.Amount
};
query = query.Union(from trade in db.trade
join tradecash in db.trade_cash
on new { tradeId = trade.id, tradeDate = trade.PremiumPayDate ?? trade.TradeDate ?? DateTime.Now } equals new { tradeId = tradecash.TradeId, tradeDate = tradecash.ValueDate } into tradecashT
from tradecash in tradecashT.DefaultIfEmpty()
join confirmDoc in db.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid)
on new { id = trade.ParentTradeId > 0 ? trade.ParentTradeId : trade.id } equals new { id = confirmDoc.TradeId } into confirmDocT
from confirmDoc in confirmDocT.DefaultIfEmpty()
where trade.TradeStatus == expiredStatus && trade.UnWindDate == valueDate && !tradecash.IsDeleted
&& tradecash.Action == ClientCashInCashOut.系统操作_期权费 && tradecash.ValidState != ConsGlobal.InValid &&
tradecash.Status == TradeCashStatusEnum.已执行
select new TradeExtends
{
Id = trade.id,
ClientId = trade.ClientId,
ClientName = trade.ClientName,
BuySell = trade.BuySell,
ContractCode = confirmDoc.ContractCode,
OptionFee = tradecash.Amount,
StrikeFee = 0
});
tradeList = query.ToList();
}
var resultList = new List<FinancialStatement>();
foreach (var trade in tradeList)
{
var financilaStatement = MaturityInvestmentIncomeGenerator.GetFinancialStatement(
IsSamePeer(trade.ClientId.Value),
trade.ClientName, trade.BuySell == "买入", trade.ContractCode, trade.StrikeFee.HasValue,
trade.OptionFee ?? 0, trade.StrikeFee ?? 0);
resultList.Add(financilaStatement);
}
return resultList;
}
/// <summary>
/// 获取提前终止投资收益凭证
/// </summary>
/// <returns></returns>
public List<FinancialStatement> GetTerminationInvestmentIncome()
{
List<TradeExtends> tradeList;
var unwindStatus = ConsTrade.已平仓;
using (var db = new YLContext())
{
var valueDate = valuedateBLL.ValueDate;
var query = from trade in db.trade
join tradecash in db.trade_cash
on new { tradeId = trade.id, tradeDate = trade.PremiumPayDate ?? trade.TradeDate ?? DateTime.Now } equals new { tradeId = tradecash.TradeId, tradeDate = tradecash.ValueDate } into tradecashT
from tradecash in tradecashT.DefaultIfEmpty()
join tradecashUnwind in db.trade_cash on trade.id equals tradecashUnwind.TradeId into
tradecashUnwindT
from tradecashUnwind in tradecashUnwindT.DefaultIfEmpty()
join confirmDoc in db.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid)
on new { id = trade.ParentTradeId > 0 ? trade.ParentTradeId : trade.id } equals new { id = confirmDoc.TradeId } into confirmDocT
from confirmDoc in confirmDocT.DefaultIfEmpty()
where tradecashUnwind.ValueDate == valueDate &&
tradecashUnwind.Action == ClientCashInCashOut.系统操作_平仓费 &&
tradecashUnwind.ValidState != ConsGlobal.InValid && !tradecashUnwind.IsDeleted && tradecashUnwind.Status == TradeCashStatusEnum.已执行
&& tradecash.Action == ClientCashInCashOut.系统操作_期权费 && tradecash.ValidState != ConsGlobal.InValid && !tradecash.IsDeleted &&
tradecash.Status == TradeCashStatusEnum.已执行 && trade.TradeStatus == unwindStatus
select new TradeExtends
{
Id = trade.id,
ClientId = trade.ClientId,
ClientName = trade.ClientName,
BuySell = trade.BuySell,
ContractCode = confirmDoc.ContractCode,
OptionFee = tradecash.Amount,
UnwindFee = tradecashUnwind.Amount
};
tradeList = query.ToList();
}
var resultList = new List<FinancialStatement>();
foreach (var trade in tradeList)
{
var financilaStatement = TerminationInvestmentIncomeGenerator.GetFinancialStatement(
IsSamePeer(trade.ClientId.Value),
trade.ClientName, trade.BuySell == "买入", trade.ContractCode, trade.OptionFee ?? 0,
trade.UnwindFee ?? 0);
resultList.Add(financilaStatement);
}
return resultList;
}
/// <summary>
/// 广发定制的财务汇总数据查询
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public List<FinancialSummaryOptionModel> FinancialSummary_Option_GF(FinancialSummaryModelReq req)
{
//默认值查询场外期权的交易
if (req.TradeTypeList == null || req.TradeTypeList.Count == 0)
{
switch (req.SummaryType)
{
case "远期/掉期":
req.TradeTypeList = new List<string> { "远期" };
break;
case "互换":
req.TradeTypeList = new List<string> { "收益互换" };
break;
case "场外期权":
default:
req.SummaryType = "场外期权";
req.TradeTypeList = ConsTrade.OptionTradeTypes;
break;
}
}
var contractBLL = new TradeDocumentService(UserInfo);
var modelList = new List<FinancialSummaryModelBase>();
var searchTradeList = tradeBLL.SearchOptionTrade_GF(req);
var tradeIds = searchTradeList.Select(O => O.TradeId).ToList();
var parentTradeIds = searchTradeList.Select(x => x.ParentTradeId).ToHashSet();
var parentTrades = DbContext.trade.Where(x => parentTradeIds.Contains(x.id)).ToDictionary(n => n.id);
var lastDate = QdpCalendarHelper.GetNonHolidayDefore(req.CurrentPeriodDateStart.AddDays(-1));
var currentDate = QdpCalendarHelper.GetNonHolidayDefore(req.CurrentPeriodDateEnd);
var positionReq = new EodTradePositionReq
{
ValueDateStart = lastDate,
ValueDateEnd = currentDate,
TraderIds = string.Join(",", tradeIds)
};
List<EodTradePosition> positions = null;
positions = new EodTradePositionBLL().SearchList<eod_trade_position_s>(positionReq)?.rows.Select(O => (EodTradePosition)O).ToList();
Dictionary<int, List<TagDto>> clientTagList = null;
if (searchTradeList != null && searchTradeList.Any())
{
using (var tagService = new TagService(OptUser))
{
clientTagList = tagService.GetTagByClientIds(searchTradeList.Select(p => p.ClientId).Distinct().ToList());
}
}
if (clientTagList == null)
{
clientTagList = new Dictionary<int, List<TagDto>>();
}
List<EodTradePosition> position = new List<EodTradePosition>();
Dictionary<int, EodTradeRisk> riskDict = new Dictionary<int, EodTradeRisk>();
var futureDict = position.GroupBy(O => O.UnderlyingCode).ToDictionary(K => K.Key, V => (double)V.ToList().Sum(O => O.PositionPnL));
var feeDict = position.GroupBy(O => O.UnderlyingCode).ToDictionary(K => K.Key, V => (double)V.ToList().Sum(O => O.Commission));
foreach (var item in searchTradeList)
{
if (parentTrades.TryGetValue(item.ParentTradeId, out var parentTrade))
{
item.TradeNumber = parentTrade.TradeNumber;
}
double percent = 1;
double? lastPv = positions.FindAll(O => O.TradeId == item.TradeId && O.ValueDate == lastDate).Sum(O => O.Amount == 0 ? 0 : Convert.ToDouble(O.Pv) / O.Amount);
double? lastPnl = positions.FindAll(O => O.TradeId == item.TradeId && O.ValueDate == lastDate).Sum(O => O.Amount == 0 ? 0 : Convert.ToDouble(O.PositionPnL) / O.Amount);
double? pv = positions.FindAll(O => O.TradeId == item.TradeId && O.ValueDate == currentDate).Sum(O => O.Amount == 0 ? 0 : Convert.ToDouble(O.Pv) / O.Amount);
double? Pnl = positions.FindAll(O => O.TradeId == item.TradeId && O.ValueDate == currentDate).Sum(O => O.Amount == 0 ? 0 : Convert.ToDouble(O.PositionPnL) / O.Amount);
item.LastPv = lastPv * item.Notional;//上期期末市值;
item.LastTotalPnl = lastPnl * item.Notional;//上期末累计浮动盈亏;
item.Pv = pv * item.Notional;//本期期末市值;
item.TotalPnl = Pnl * item.Notional;//本期末累计浮动盈亏;
if (item.TradeDate >= req.CurrentPeriodDateStart)
{ item.LastTotalPnl = 0; }
if (item.UnderlyingCode != null)
{
item.FuturePnl = futureDict.ContainsKey(item.UnderlyingCode) ? futureDict[item.UnderlyingCode] * percent : 0;//期货盈亏(结算价);
item.ServiceFee = feeDict.ContainsKey(item.UnderlyingCode) ? feeDict[item.UnderlyingCode] * percent : 0;//期货手续费;
item.CountRatio = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode).CountRatio;
}
else
{
item.FuturePnl = 0;//期货盈亏(结算价);
item.ServiceFee = 0;//期货手续费;
item.CountRatio = 1;
}
item.DailyPnL = positions.FindAll(O => O.TradeId == item.TradeId && O.ValueDate == currentDate).Sum(O => O.DailyPnL);
item.FinancialEntry = null;//财务入账;
var SpotPrice = DbContext.trade.Where(l => l.id == item.TradeId).FirstOrDefault()?.SpotPrice;
item.SurvivingNominalPrincipal = item.PositionAmount * SpotPrice;
//拼装标签值
if (clientTagList.ContainsKey(item.ClientId))
{
item.Tags = clientTagList[item.ClientId];
item.OutputTags = TagService.GetOutputTagsStr(item.Tags);
}
}
return searchTradeList;
}
/// <summary>
/// 汇总客户数据
/// </summary>
public List<FinancialSummaryOptionModel> GatherClientData(FinancialSummaryModelReq req)
{
//反回表格数据(明细 小计 合计
List<FinancialSummaryOptionModel> rowSummaryOptionModels = new List<FinancialSummaryOptionModel>();
//明细数据
var financialSummaryOptionDetails = FinancialSummary_Option_GF(req);
//小计数据
var reqSubTotle = new FinancialSummaryModelReq() { SummaryType = req.SummaryType, TradeTypeList = req.TradeTypeList, CurrentPeriodDateStart = req.CurrentPeriodDateStart, CurrentPeriodDateEnd = req.CurrentPeriodDateEnd, ClientIds = req.ClientIds };
var financialSummaryOptionSubtotal = FinancialSummary_Option_GF(reqSubTotle);
if (financialSummaryOptionDetails != null && financialSummaryOptionDetails.Any())
{
//小计【可用资金(财务)】= 【期末结存(财务)】-预付金占用 + 冻结资金 、【期末结存(财务)】 = 出入金净额 + 成交了结收支
var financialSummaryOptionModels = financialSummaryOptionDetails.GroupBy(l => new { l.ClientId, l.ClientFullName }).Select(l => l.Key).ToList();
var clientCashs = ClientBalanceUtility.GetClientBanlances(financialSummaryOptionModels.Select(l => l.ClientId).ToList(), req.CurrentPeriodDateEnd, req.CurrentPeriodDateEnd, false, true, false);
List<FinancialSummaryOptionModel> optionModelsSubtotal = new List<FinancialSummaryOptionModel>();
var tcQuery = new YLContext().trade_cash.Where(O => !O.IsDeleted && O.ValidState != ConsGlobal.InValid);
financialSummaryOptionModels.ForEach(l =>
{
//查询明细是否有该客户数据,如果没有就不需要小计
var financialSummaryOptionDetailsByClient = financialSummaryOptionDetails.Where(x => x.ClientId == l.ClientId);
if (financialSummaryOptionDetailsByClient != null && financialSummaryOptionDetailsByClient.Any())
{
var financialSummaryOptionModelsByClient = financialSummaryOptionSubtotal.Where(r => r.ClientId == l.ClientId);
FinancialSummaryOptionModel summaryOptionModel = CreateFinancialSummaryOptionClientModel(req, l.ClientId, " 小计:" + l.ClientFullName, "无状态", financialSummaryOptionModelsByClient.ToList(), tcQuery);
var clientCashsByClientId = clientCashs.Where(c => c.ClientId == l.ClientId).FirstOrDefault();
if (clientCashsByClientId != null)
{
//可用资金(财务) clientCashsByClientId.AvailableCash
summaryOptionModel.AvailableCash = clientCashsByClientId.AvailableAmount;
//期末结存(财务) clientCashsByClientId.EndBalance;
summaryOptionModel.EndBalance = clientCashsByClientId.AmountFund;
}
financialSummaryOptionDetailsByClient.ToList().ForEach(l =>
{
l.StatusStr = l.Status ? "完结" : "未完结";
l.ConfirmTotlePnl = l.ConfirmPnl;
l.GF_Pnl = l.Pnl;
});
rowSummaryOptionModels.AddRange(financialSummaryOptionDetailsByClient);
rowSummaryOptionModels.Add(summaryOptionModel);
optionModelsSubtotal.Add(summaryOptionModel);
}
});
FinancialSummaryOptionModel summaryOptionModel = CreateFinancialSummaryOptionClientModel(req, 0, " 合计:", "无状态", financialSummaryOptionDetails, tcQuery);
summaryOptionModel.AvailableCash = optionModelsSubtotal.Sum(f => f.AvailableCash);
summaryOptionModel.EndBalance = optionModelsSubtotal.Sum(f => f.EndBalance);
rowSummaryOptionModels.Add(summaryOptionModel);
}
return rowSummaryOptionModels;
}
/// <summary>
/// 汇总簿记数据
/// </summary>
public List<FinancialSummaryOptionModel> GatherUnitData(FinancialSummaryModelReq req)
{
var startDate = QdpCalendarHelper.GetNonHolidayDefore(req.CurrentPeriodDateStart.AddDays(-1));
var TotalPnls = CaclTotalPnl(req.CurrentPeriodDateStart, req.CurrentPeriodDateEnd, out List<T2PositionDataDto> t2);
//场内
List<FinancialSummaryOptionModel> financialSummaryExchanges = new List<FinancialSummaryOptionModel>();
using (YLContext ylContext = new YLContext())
{
var exchangList = (from eodtrade in ylContext.eod_trade_position_s
join exchangeOption in ylContext.exchange_list_option on eodtrade.ExchangeOptionCode equals exchangeOption.ContractCode
into exchangeOptionT
from exchangeOption in exchangeOptionT.DefaultIfEmpty()
where eodtrade.TradeId == 0 && !string.IsNullOrEmpty(eodtrade.HedgeUniqueCode)
&& (startDate <= eodtrade.ValueDate && req.CurrentPeriodDateEnd >= eodtrade.ValueDate)
select new
{
eodtrade.HedgeUniqueCode,
eodtrade.ExchangeOptionCode,
eodtrade.ValueDate,
eodtrade.BookId,
eodtrade.UnderlyingCode,
eodtrade.DailyPnL,
eodtrade.Commission,
eodtrade.PositionPnL,
eodtrade.RealizedPnL,
eodtrade.Pv,
eodtrade.Amount,
eodtrade.TotalPnL,
//ContractSize = DataCacheProvider.GetUnderlyingDataSource().GetData(eodtrade.UnderlyingCode).ContractSize,
Strike = eodtrade.TradeType == "场内期权" ? exchangeOption.Strike : 0,
}).ToList();
if (req.UserAssets != null && req.UserClients != null)
{
exchangList = exchangList.Where(a => req.UserAssets.Contains(a.BookId)).ToList();
}
if (req.BookIds != null && req.BookIds.Any())
{
exchangList = exchangList.Where(a => req.BookIds.Contains(a.BookId)).ToList();
}
if (!string.IsNullOrEmpty(req.VarietyCode))
{
var reqUnderlyingCodes = ylContext.underlying_manager.AsNoTracking().Where(l => l.CommodityCode == req.VarietyCode).Select(l => l.UnderlyingCode).ToList();
exchangList = exchangList.Where(a => reqUnderlyingCodes.Contains(a.UnderlyingCode)).ToList();
}
if (!string.IsNullOrEmpty(req.VarietyName))
{
var reqUnderlyingCodes = ylContext.underlying_manager.AsNoTracking().Where(l => l.CommodityCode == req.VarietyName).Select(l => l.UnderlyingCode).ToList();
exchangList = exchangList.Where(a => reqUnderlyingCodes.Contains(a.UnderlyingCode)).ToList();
}
var exchangListByHedgeUniqueCode = exchangList.GroupBy(l => new { l.ExchangeOptionCode, l.HedgeUniqueCode }).ToList();
foreach (var item in exchangListByHedgeUniqueCode)
{
var code = item.Key.ExchangeOptionCode;
if (string.IsNullOrWhiteSpace(code))
{
code = item.Key.HedgeUniqueCode;
}
else
{
if (financialSummaryExchanges.Where(l => l.ExchangeCode == code).Any())
{
continue;
}
}
var exchangListFirst = exchangList.Where(l => (l.ExchangeOptionCode == code || l.HedgeUniqueCode == code)).FirstOrDefault();
var exchangListEndDate = exchangList.Where(l => (l.ExchangeOptionCode == code || l.HedgeUniqueCode == code) && l.ValueDate == req.CurrentPeriodDateEnd);
var exchangListStartDate = exchangList.Where(l => (l.ExchangeOptionCode == code || l.HedgeUniqueCode == code) && l.ValueDate == startDate);
FinancialSummaryOptionModel financialSummaryOption = new FinancialSummaryOptionModel()
{
AssetId = exchangListFirst.BookId,
ExchangeCode = string.IsNullOrWhiteSpace(exchangListFirst.ExchangeOptionCode) ? exchangListFirst.HedgeUniqueCode : exchangListFirst.ExchangeOptionCode,
AssetBookName = DataCacheProvider.GetAssetUnitDataSource().GetData(exchangListFirst.BookId).Name,
VarietyCode = DataCacheProvider.GetVariety(exchangListFirst.UnderlyingCode).VarietyCode,
PositionAmount = exchangListEndDate.Any() ? Math.Abs(exchangListEndDate.Sum(l => l.Amount)) : 0,
PositionLots = exchangListEndDate.Any() ? (Math.Abs(exchangListEndDate.Sum(l => l.Amount)) / DataCacheProvider.GetUnderlyingDataSource().GetData(exchangListEndDate.FirstOrDefault().UnderlyingCode).ContractSize) : 0,
StockEqvNotional3 = exchangListEndDate.Any() ? (exchangListEndDate.Sum(l => Math.Abs(l.Strike * l.Amount))) : 0,
ClearPrice = 0,
ConfirmTotlePnl = exchangListEndDate.Any() ? exchangListEndDate.Sum(l => l.RealizedPnL) : 0,
Pv = exchangListEndDate.Any() ? exchangListEndDate.Sum(l => l.Pv) : 0,
LastPv = exchangListStartDate.Any() ? exchangListStartDate.Sum(l => l.Pv) : 0,
TotalPnl = exchangListEndDate.Any() ? exchangListEndDate.Sum(l => l.PositionPnL) : 0,
LastTotalPnl = exchangListStartDate.Any() ? exchangListStartDate.Sum(l => l.PositionPnL) : 0,
GF_Pnl = (exchangListEndDate.Any() ? exchangListEndDate.Sum(l => l.PositionPnL) : 0) - (exchangListStartDate.Any() ? exchangListStartDate.Sum(l => l.PositionPnL) : 0),
ServiceFee = exchangListEndDate.Any() ? exchangListEndDate.Sum(l => l.Commission) : 0,
DailyPnL = exchangListEndDate.Any() ? exchangListEndDate.Sum(l => l.DailyPnL) : 0,
NewTotalPnl = TotalPnls.Where(l => exchangList.Where(l => (l.ExchangeOptionCode == code || l.HedgeUniqueCode == code)).Select(l => l.HedgeUniqueCode).Contains(l.HedgeUniqueCode)).Sum(l => l.AccruedTotalPnL),
};
financialSummaryExchanges.Add(financialSummaryOption);
}
}
// financialSummaryOptions.GroupBy()
//反回表格数据(明细 小计 合计
List<FinancialSummaryOptionModel> rowSummaryOptionModels = new List<FinancialSummaryOptionModel>();
//场外所有明细数据
req.TradeTypeList = new List<string>() { "收益互换", "远期" }.Concat(ConsTrade.OptionTradeTypes).ToList();
var financialSummaryOptionDetails = FinancialSummary_Option_GF(req);
//场外+场内
var financialSummaryOptionAll = financialSummaryOptionDetails.Concat(financialSummaryExchanges).ToList();
var tcQuery = new YLContext().trade_cash.Where(O => !O.IsDeleted && O.ValidState != ConsGlobal.InValid);
//转换簿记维度
var financialSummaryOptionUnitDetails = CreateUnitDate(req, financialSummaryOptionAll, tcQuery, TotalPnls);
//小计数据
//var reqSubTotle = new FinancialSummaryModelReq() { SummaryType = req.SummaryType, TradeTypeList = req.TradeTypeList, CurrentPeriodDateStart = req.CurrentPeriodDateStart, CurrentPeriodDateEnd = req.CurrentPeriodDateEnd, ClientIds = req.ClientIds };
//var financialSummaryOptionSubtotal = FinancialSummary_Option_GF(reqSubTotle);
//转换簿记维度
//var financialSummaryOptionUnitSubtotal = CreateUnitDate(req, financialSummaryOptionSubtotal, tcQuery);
if (financialSummaryOptionUnitDetails != null && financialSummaryOptionUnitDetails.Any())
{
//小计【当日期货盈亏】、【累计总盈亏】
var financialSummaryOptionModels = financialSummaryOptionUnitDetails.GroupBy(l => new { l.AssetId }).Select(l => new { l.Key, AssetBookName = l.FirstOrDefault().AssetBookName, VarietyCode = l.FirstOrDefault().VarietyCode }).ToList();
List<FinancialSummaryOptionModel> optionModelsSubtotal = new List<FinancialSummaryOptionModel>();
financialSummaryOptionModels.ForEach(l =>
{
//查询明细是否有该簿记数据,如果没有就不需要小计
var financialSummaryOptionDetailsByAsset = financialSummaryOptionUnitDetails.Where(x => x.AssetId == l.Key.AssetId);
if (financialSummaryOptionDetailsByAsset != null && financialSummaryOptionDetailsByAsset.Any())
{
FinancialSummaryOptionModel summaryOptionModel = CreateFinancialSummaryOptionUnitModel(l.Key.AssetId, " 小计:" + l.AssetBookName, l.VarietyCode, financialSummaryOptionDetailsByAsset.ToList(), tcQuery);
rowSummaryOptionModels.AddRange(financialSummaryOptionDetailsByAsset);
rowSummaryOptionModels.Add(summaryOptionModel);
optionModelsSubtotal.Add(summaryOptionModel);
}
});
FinancialSummaryOptionModel summaryOptionModel = CreateFinancialSummaryOptionUnitModel(0, " 合计:", "", financialSummaryOptionUnitDetails, tcQuery);
rowSummaryOptionModels.Add(summaryOptionModel);
}
return rowSummaryOptionModels;
}
private List<FinancialSummaryOptionModel> CreateUnitDate(FinancialSummaryModelReq req, List<FinancialSummaryOptionModel> financialSummaryOptionDetails, IQueryable<trade_cash> tcQuery, List<TradePositionTotalPnLModel> totalPnls)
{
var tradeTypes = new List<string> { "雪球期权", "凤凰期权", "区间累积期权" };
//(trade.OriginalNotional ?? 0) / contractSize
var parentIds = financialSummaryOptionDetails.Where(l => l.ParentTradeId > 0).GroupBy(l => l.ParentTradeId).Select(l => l.Key).ToList();
var FSOModelsGourpByClientByTradeId = financialSummaryOptionDetails.Where(l => !parentIds.Contains(l.TradeId)&& l.TradeId != 0).GroupBy(f => f.TradeId).Select(f => new
FinancialSummaryOptionModel
{
TradeId = f.Key,
AssetId = f.FirstOrDefault().AssetId,
AssetBookName = f.FirstOrDefault().AssetBookName,
VarietyCode = f.FirstOrDefault().VarietyCode,
PositionAmount = f.Any(c => c.Status == false) ? f.Sum(c => c.PositionAmount) : 0,
PositionLots = f.Any(c => c.Status == false) ? f.Sum(c => c.PositionAmount / c.ContractSize) : 0,
StockEqvNotional3 = f.FirstOrDefault().StockEqvNotional3,
TradePrice = f.Sum(v => v.TradePrice),
ClearPrice = f.Any(c => c.Status == false) ? f.Sum(v => v.ClearPrice) : f.Sum(v => v.ClearPrice) + (f.Sum(v => tradeTypes.Contains(v.TradeType) ? tcQuery.Where(O => O.TradeId == f.Key && O.ValueDate >= req.CurrentPeriodDateStart && O.ValueDate <= req.CurrentPeriodDateEnd && O.Action == "系统操作-票息").Sum(O => (double?)O.Amount) : 0)),
ConfirmTotlePnl = f.Sum(v => v.ConfirmPnl ?? 0),
LastPv = f.Any(c => c.Status == false) ? f.Sum(f => f.LastPv) : 0,
LastTotalPnl = f.Any(c => c.Status == false) ? f.Sum(f => (f.LastTotalPnl ?? 0)) : 0,
Pv = f.Any(c => c.Status == false) ? f.Sum(f => f.Pv) : 0,
TotalPnl = f.Any(c => c.Status == false) ? f.Sum(f => f.TotalPnl) : 0,
GF_Pnl = f.Any(c => c.Status == false) ? f.Sum(f => f.Pnl) : 0,
DailyPnL = f.FirstOrDefault().DailyPnL,
ServiceFee = f.Sum(l => l.ServiceFee),
NewTotalPnl = totalPnls.Where(c => c.TradeId == f.Key).FirstOrDefault()?.AccruedTotalPnL,
}).Concat(financialSummaryOptionDetails.Where(l => l.TradeId == 0));
var FSOModelsGourpByClientByAsset = (FSOModelsGourpByClientByTradeId.GroupBy(l => new { l.AssetId, l.AssetBookName, l.VarietyCode }).Select(
l => new FinancialSummaryOptionModel
{
AssetId = l.Key.AssetId,
AssetBookName = l.Key.AssetBookName,
VarietyCode = l.Key.VarietyCode,
PositionAmount = l.Sum(v => v.PositionAmount),
PositionLots = l.Sum(v => v.PositionLots),
StockEqvNotional3 = l.FirstOrDefault().StockEqvNotional3,
TradePrice = l.Sum(v => v.TradePrice),
ClearPrice = l.Sum(v => v.ClearPrice),
ConfirmTotlePnl = l.Sum(v => v.ConfirmTotlePnl??0),
LastPv = l.Sum(f => f.LastPv),
LastTotalPnl = l.Sum(f => f.LastTotalPnl),
Pv = l.Sum(f => f.Pv),
TotalPnl = l.Sum(f => f.TotalPnl),
GF_Pnl = l.Sum(f => f.GF_Pnl),
ServiceFee = l.Sum(f => f.ServiceFee),
DailyPnL = l.Sum(f => f.DailyPnL),
NewTotalPnl = l.Sum(f => f.NewTotalPnl),
})).ToList();
return FSOModelsGourpByClientByAsset;
}
public FinancialSummaryOptionModel CreateFinancialSummaryOptionClientModel(FinancialSummaryModelReq req, int clientId, string ClientFullName, string StatusStr, List<FinancialSummaryOptionModel> financialSummaryOptionModelsByClient, IQueryable<trade_cash> trade_Cashes)
{
var tradeTypes = new List<string> { "雪球期权", "凤凰期权", "区间累积期权" };
var parentIds = financialSummaryOptionModelsByClient.Where(l=>l.ParentTradeId>0).GroupBy(l => l.ParentTradeId).Select(l=>l.Key).ToList();
//场外期权每个客户,同交易id
var FSOModelsGourpByClientByTradeId = financialSummaryOptionModelsByClient.Where(l=> !parentIds.Contains(l.TradeId)).GroupBy(f => f.TradeId).Select(f => new
{
f.Key,
StockEqvNotional3 = f.FirstOrDefault().StockEqvNotional3,
TradePrice = f.Sum(v => v.TradePrice),
ClearPrice = f.Any(c => c.Status == false) ? f.Sum(v => v.ClearPrice) : f.Sum(v => v.ClearPrice) + (f.Sum(v => tradeTypes.Contains(v.TradeType) ? trade_Cashes.Where(O => O.TradeId == f.Key && O.ValueDate >= req.CurrentPeriodDateStart && O.ValueDate <= req.CurrentPeriodDateEnd && O.Action == "系统操作-票息").Sum(O => (double?)O.Amount) : 0)),
ConfirmTotlePnl = f.Sum(v => v.ConfirmPnl ?? 0),
LastPv = f.Any(c => c.Status == false) ? f.Sum(f => f.LastPv) : 0,
LastTotalPnl = f.Any(c => c.Status == false) ? f.Sum(f => (f.LastTotalPnl ?? 0)) : 0,
Pv = f.Any(c => c.Status == false) ? f.Sum(f => f.Pv) : 0,
TotalPnl = f.Any(c => c.Status == false) ? f.Sum(f => f.TotalPnl) : 0,
GF_Pnl = f.Sum(f => f.Pnl ?? 0),
});
FinancialSummaryOptionModel summaryOptionModel = new FinancialSummaryOptionModel();
summaryOptionModel.ClientId = clientId;
summaryOptionModel.ClientFullName = ClientFullName;
summaryOptionModel.StatusStr = StatusStr;
summaryOptionModel.OptionType = StatusStr;
//名义本金
summaryOptionModel.StockEqvNotional3 = FSOModelsGourpByClientByTradeId.Sum(l => l.StockEqvNotional3).FormatValue(2);
//期初权利金收支
summaryOptionModel.TradePrice = FSOModelsGourpByClientByTradeId.Sum(f => f.TradePrice).FormatValue(2);
//清算金额
summaryOptionModel.ClearPrice = FSOModelsGourpByClientByTradeId.Sum(f => f.ClearPrice).FormatValue(2);
//我方期权清算盈亏
summaryOptionModel.ConfirmTotlePnl = FSOModelsGourpByClientByTradeId.Sum(f => f.ConfirmTotlePnl).FormatValue(2);
//上期期末市值
summaryOptionModel.LastPv = FSOModelsGourpByClientByTradeId.Sum(f => f.LastPv).FormatValue(2);
//上期期末累计浮动盈亏
summaryOptionModel.LastTotalPnl = FSOModelsGourpByClientByTradeId.Sum(f => f.LastTotalPnl).FormatValue(2);
//本期期末市值
summaryOptionModel.Pv = FSOModelsGourpByClientByTradeId.Sum(f => f.Pv).FormatValue(2);
//本期期末累计浮动盈亏
summaryOptionModel.TotalPnl = FSOModelsGourpByClientByTradeId.Sum(f => f.TotalPnl).FormatValue(2);
//本期浮动盈亏
summaryOptionModel.GF_Pnl = FSOModelsGourpByClientByTradeId.Sum(f => f.GF_Pnl).FormatValue(2);
////【累计总盈亏】
//summaryOptionModel.NewTotalPnl = financialSummaryOptionModelsByClient.GroupBy(x => x.TradeId).Sum(f => f.FirstOrDefault().NewTotalPnl);
////【当日期货盈亏】
//summaryOptionModel.TotalPnlAfterExpense = financialSummaryOptionModelsByClient.Sum(f => f.TotalPnlAfterExpense);
return summaryOptionModel;
}
public FinancialSummaryOptionModel CreateFinancialSummaryOptionUnitModel(int AssetId, string AssetBookName, string VarietyCode, List<FinancialSummaryOptionModel> financialSummaryOptionModelsByClient, IQueryable<trade_cash> trade_Cashes)
{
FinancialSummaryOptionModel summaryOptionModel = new FinancialSummaryOptionModel();
summaryOptionModel.AssetId = AssetId;
summaryOptionModel.AssetBookName = AssetBookName;
summaryOptionModel.StatusStr = "无状态";
//StatusStr
//summaryOptionModel.VarietyCode = VarietyCode;
//名义本金
summaryOptionModel.StockEqvNotional3 = financialSummaryOptionModelsByClient.Sum(l => l.StockEqvNotional3).FormatValue(2);
//期初权利金收支
summaryOptionModel.TradePrice = financialSummaryOptionModelsByClient.Sum(f => f.TradePrice).FormatValue(2);
//清算金额
summaryOptionModel.ClearPrice = financialSummaryOptionModelsByClient.Sum(f => f.ClearPrice).FormatValue(2);
//我方期权清算盈亏
summaryOptionModel.ConfirmTotlePnl = financialSummaryOptionModelsByClient.Sum(f => f.ConfirmTotlePnl).FormatValue(2);
//上期期末市值
summaryOptionModel.LastPv = financialSummaryOptionModelsByClient.Sum(f => f.LastPv).FormatValue(2);
//上期期末累计浮动盈亏
summaryOptionModel.LastTotalPnl = financialSummaryOptionModelsByClient.Sum(f => (f.LastTotalPnl??0)).FormatValue(2);
//本期期末市值
summaryOptionModel.Pv = financialSummaryOptionModelsByClient.Sum(f => f.Pv).FormatValue(2);
//本期期末累计浮动盈亏
summaryOptionModel.TotalPnl = financialSummaryOptionModelsByClient.Sum(f => f.TotalPnl).FormatValue(2);
//本期浮动盈亏
summaryOptionModel.GF_Pnl = financialSummaryOptionModelsByClient.Sum(f => f.GF_Pnl).FormatValue(2);
//【累计总盈亏】
summaryOptionModel.NewTotalPnl = financialSummaryOptionModelsByClient.Sum(f => f.NewTotalPnl).FormatValue(2);
//【当日期货盈亏】
summaryOptionModel.DailyPnL = financialSummaryOptionModelsByClient.Sum(f => f.DailyPnL).FormatValue(2);
summaryOptionModel.ServiceFee = financialSummaryOptionModelsByClient.Sum(f => f.ServiceFee).FormatValue(2);
return summaryOptionModel;
}
public List<TradePositionTotalPnLModel> CaclTotalPnl(DateTime? StartDate, DateTime EndDate, out List<T2PositionDataDto> t2PositionDataDtos)
{
// 1、确定三点 T1 T1~T2 T2
var start = EodOperationBase.GetLastSettlementDate(StartDate?.AddDays(-1) ?? valuedateBLL.SystemDate.AccruedTotalPnlStartDate ?? DateTime.Today);
var end = EndDate;
//T1
var dateT1 = EodOperationBase.GetLastSettlementDate(start);
// T2
var dateT2 = end;
RiskRequestModel reqModel = new RiskRequestModel() { ValueDateStart = dateT1, ValueDateEnd = dateT2, EodSettlePriceMode = "收盘价" };
return new AccruedTotalPnlService<eod_trade_position_s>(OptUserInfo.SystemUser).CalcuTotalPnl(out t2PositionDataDtos, dateT1, dateT2, reqModel);
}
}
public class TradeExtends
{
public int Id { get; set; }
public int? ClientId { get; set; }
public string ClientName { get; set; }
public string BuySell { get; set; }
public string ContractCode { get; set; }
public double? OptionFee { get; set; }
public double? StrikeFee { get; set; }
public double? UnwindFee { get; set; }
}
}