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
{
///
/// 财务凭证服务
///
public class FinancialVoucherService : YLBaseService
{
public FinancialVoucherService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 获取财务凭证
///
public ReturnInfo> GetFinancialStatements(FinancialStatementReq req)
{
var resultList = new List();
Task ExecuteAsync(Func> 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;
}
}
}
///
/// 获取出入金凭证
///
///
public List GetDepositWithdraw()
{
List cashInCashOutList;
var resultList = new List();
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;
}
///
/// 获取应收应付期权费凭证
///
public List GetAROrAPOptionFee()
{
List 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();
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;
}
///
/// 获取到期投资收益凭证
///
public List GetMaturityInvestmentIncome()
{
List 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();
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;
}
///
/// 获取提前终止投资收益凭证
///
///
public List GetTerminationInvestmentIncome()
{
List 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();
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;
}
///
/// 广发定制的财务汇总数据查询
///
///
///
public List FinancialSummary_Option_GF(FinancialSummaryModelReq req)
{
//默认值查询场外期权的交易
if (req.TradeTypeList == null || req.TradeTypeList.Count == 0)
{
switch (req.SummaryType)
{
case "远期/掉期":
req.TradeTypeList = new List { "远期" };
break;
case "互换":
req.TradeTypeList = new List { "收益互换" };
break;
case "场外期权":
default:
req.SummaryType = "场外期权";
req.TradeTypeList = ConsTrade.OptionTradeTypes;
break;
}
}
var contractBLL = new TradeDocumentService(UserInfo);
var modelList = new List();
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 positions = null;
positions = new EodTradePositionBLL().SearchList(positionReq)?.rows.Select(O => (EodTradePosition)O).ToList();
Dictionary> 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>();
}
List position = new List();
Dictionary riskDict = new Dictionary();
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;
}
///
/// 汇总客户数据
///
public List GatherClientData(FinancialSummaryModelReq req)
{
//反回表格数据(明细 小计 合计 )
List rowSummaryOptionModels = new List();
//明细数据
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 optionModelsSubtotal = new List();
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;
}
///
/// 汇总簿记数据
///
public List GatherUnitData(FinancialSummaryModelReq req)
{
var startDate = QdpCalendarHelper.GetNonHolidayDefore(req.CurrentPeriodDateStart.AddDays(-1));
var TotalPnls = CaclTotalPnl(req.CurrentPeriodDateStart, req.CurrentPeriodDateEnd, out List t2);
//场内
List financialSummaryExchanges = new List();
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 rowSummaryOptionModels = new List();
//场外所有明细数据
req.TradeTypeList = new List() { "收益互换", "远期" }.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 optionModelsSubtotal = new List();
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 CreateUnitDate(FinancialSummaryModelReq req, List financialSummaryOptionDetails, IQueryable tcQuery, List totalPnls)
{
var tradeTypes = new List { "雪球期权", "凤凰期权", "区间累积期权" };
//(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 financialSummaryOptionModelsByClient, IQueryable trade_Cashes)
{
var tradeTypes = new List { "雪球期权", "凤凰期权", "区间累积期权" };
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 financialSummaryOptionModelsByClient, IQueryable 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 CaclTotalPnl(DateTime? StartDate, DateTime EndDate, out List 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(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; }
}
}