Files
zszq-trs/YLErpDAL/Modules/EodModule/EodPositionRisksQueryService.cs
T
2026-07-31 14:49:52 +08:00

2654 lines
155 KiB
C#

using BaseOUDAL;
using System;
using System.Data;
using System.Diagnostics;
using System.Linq.Expressions;
using YLErp.BLL;
using YLErp.BLL.EodSettlement;
using YLErp.Commons;
using YLErp.DBModels.Helpers;
using YLErp.Helpers;
using YLErp.Model;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.UnderlyingModule;
using YLErp.Office.ExcelModule;
using YLErp.QdpModule;
using Path = System.IO.Path;
namespace YLErp.Modules.EodModule
{
/// <summary>
/// 日终持仓风险查询服务
/// </summary>
public class EodPositionRisksQueryService : YLBaseService
{
public EodPositionRisksQueryService(OptUserInfo userInfo) : base(userInfo)
{
}
#region----from tadeBLL----
//from tradecontroller.EodPositionRisksQuery
public SearchListResult<EodPositionRisksDTO> SearchList(EodPositionRisksReq req, bool isSwapTrades = false)
{
var voltype = req?.VolType ?? string.Empty;
string ZeroDividendRateType = "分红率0";
if (req.DividendRateType == "采集")
{
voltype = ZeroDividendRateType;
}
switch (req?.EodSettlePriceMode)
{
case "结算价":
if (voltype == "开仓")
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_openvol_s, eod_trade_risk_openvol_s, eod_pnl_openvol_s>(req, isSwapTrades, false);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_openvol_s, eod_trade_risk_openvol_s, eod_pnl_openvol_s>(req, isSwapTrades, false);
}
}
else if (voltype == "对冲")
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_hedgevol_s, eod_trade_risk_hedgevol_s, eod_pnl_hedgevol_s>(req, isSwapTrades, false);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_hedgevol_s, eod_trade_risk_hedgevol_s, eod_pnl_hedgevol_s>(req, isSwapTrades, false);
}
}
else if (voltype == "风控" || voltype == ZeroDividendRateType)
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_extend_s, eod_trade_risk_extend_s, eod_pnl_extend_s>(req, isSwapTrades);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_extend_s, eod_trade_risk_extend_s, eod_pnl_extend_s>(req, isSwapTrades);
}
}
else
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_s, eod_trade_risk_s, eod_pnl_s>(req, isSwapTrades, false);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_s, eod_trade_risk_s, eod_pnl_s>(req, isSwapTrades, false);
}
}
default:
//不确定该逻辑的目的,但会影响到非远期期权查询到的数据,所以先注释掉;
//if (req.TradeTypes != null && req.TradeTypes.Contains("远期"))
//{
// result = new tradeBLL().SearchEodPositionRisksList<eod_trade_position_s, eod_trade_risk_s, eod_pnl_s>(req);
//}
//if (req.TradeTypes != null && req.TradeTypes.Contains("远期"))
//{
// result = new tradeBLL().SearchEodPositionRisksList<eod_trade_position, eod_trade_risk, eod_pnl>(req);
//}
if (voltype == "开仓")
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_openvol, eod_trade_risk_openvol, eod_pnl_openvol>(req, isSwapTrades);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_openvol, eod_trade_risk_openvol, eod_pnl_openvol>(req, isSwapTrades);
}
}
else if (voltype == "对冲")
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_hedgevol, eod_trade_risk_hedgevol, eod_pnl_hedgevol>(req, isSwapTrades);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_hedgevol, eod_trade_risk_hedgevol, eod_pnl_hedgevol>(req, isSwapTrades);
}
}
else if (voltype == "风控" || voltype == ZeroDividendRateType)
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position_extend, eod_trade_risk_extend, eod_pnl_extend>(req, isSwapTrades);
}
else
{
return SearchEodPositionRisksList<eod_trade_position_extend, eod_trade_risk_extend, eod_pnl_extend>(req, isSwapTrades);
}
}
else
{
if (req?.IsParentTrade == true)
{
return SearchEodOptionPositionRisksList<eod_trade_position, eod_trade_risk, eod_pnl>(req, isSwapTrades);
}
else
{
return SearchEodPositionRisksList<eod_trade_position, eod_trade_risk, eod_pnl>(req, isSwapTrades);
}
}
}
}
public SearchListResult<EodPositionRisksDTO> SearchEodOptionPositionRisksList<T1, T2, T3>(EodPositionRisksReq req
, bool isSwapTrades, bool useClosePrice = true)
where T1 : EodTradePosition where T2 : EodTradeRisk where T3 : EodPnl
{
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
if (req.needSettleData)
{
statusList = new List<string>();
}
var eodPredicate = BuildPredicateOfEodTrade(req, isSwapTrades);
var tradePredicate = PredicateBuilder.Create<trade>(t => t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2);
if (req.UserAssets != null && req.UserClients != null)
{
tradePredicate = tradePredicate.And(a => req.UserAssets.Contains(a.AssetId) || req.UserClients.Contains(a.ClientId));
}
if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x)))
{
tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0));
}
if (!string.IsNullOrWhiteSpace(req.TradeNumber))
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber));
}
if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue)
{
var TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1);
tradePredicate = tradePredicate.And(d => (d.SettlementDate ?? d.ExerciseDate) < TradeDateTemp);
}
if (req.SettlementDateStart != null && req.SettlementDateStart != DateTime.MinValue)
{
tradePredicate = tradePredicate.And(d => (d.SettlementDate ?? d.ExerciseDate) >= req.SettlementDateStart);
}
if (req.SettlementFlags != null && req.SettlementFlags.Any())
{
tradePredicate = tradePredicate.And(d => req.SettlementFlags.Contains(d.SettlementFlag));
}
if (!string.IsNullOrEmpty(req.GroupNames) && req.GroupNamesList != null && req.GroupNamesList.Count > 0)
{
var gname = req.GroupNamesList[0];
var groupNamePredicate = PredicateBuilder.Create<trade>(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname.ToString()));
if (req.GroupNamesList.Count > 1)
{
for (int i = 1; i < req.GroupNamesList.Count; i++)
{
var gname1 = req.GroupNamesList[i];
groupNamePredicate = groupNamePredicate.Or(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname1.ToString()));
}
}
tradePredicate = tradePredicate.And(groupNamePredicate);
}
if (req.TagIds != null && req.TagIds.Count > 0)
{
var tradeTagIdQuery = from tt in DbContext.trade_tag
where req.TagIds.Contains(tt.TagId)
select tt.TradeId;
tradePredicate = tradePredicate.And(p => tradeTagIdQuery.Contains(p.id));
}
var query = from eodTrade in DbContext.eod_trade.Where(eodPredicate)
join trade in DbContext.trade.Where(tradePredicate) on eodTrade.TradeId equals trade.id
join tr in DbContext.trade_contract_r.Where(O => O.Type == "交易确认书" && O.IsValid) on trade.id equals tr.TradeId into trs
from tr in trs.DefaultIfEmpty()
join eodPos in DbContext.Set<T1>().Where(O => O.ValueDate == req.ValueDate) on eodTrade.TradeId equals eodPos.TradeId into eodPoss
from eodPos in eodPoss.DefaultIfEmpty()
join eodRisk in DbContext.Set<T2>().Where(t => t.ValueDate == req.ValueDate) on eodTrade.TradeId equals eodRisk.TradeId into eodrisk_t
from eodRisk in eodrisk_t.DefaultIfEmpty()
join eodPnl in DbContext.Set<T3>().Where(O => O.ValueDate == req.ValueDate && O.TradeId > 0) on eodTrade.TradeId equals eodPnl.TradeId into eodPnls
from eodPnl in eodPnls.DefaultIfEmpty()
join tradespan in DbContext.trade_span.Where(O => O.ValueDate == req.ValueDate) on eodTrade.TradeId equals tradespan.TradeId into tradespans
from tradespan in tradespans.DefaultIfEmpty()
join assetUnit in DbContext.assetunit on trade.AssetId equals assetUnit.id into assetUnits
from assetUnit in assetUnits.DefaultIfEmpty()
join parentTrade in DbContext.trade.Where(tr => tr.ValidState != "InValid") on trade.ParentTradeId equals parentTrade.id into parentTrades
from parentTrade in parentTrades.DefaultIfEmpty()
join binary in DbContext.trade_binary_option on eodTrade.TradeId equals binary.TradeId into binary_t
from binary in binary_t.DefaultIfEmpty()
join asian in DbContext.trade_asian_option on eodTrade.TradeId equals asian.TradeId into asian_t
from asian in asian_t.DefaultIfEmpty()
join barrier in DbContext.trade_barrier_option on eodTrade.TradeId equals barrier.TradeId into barrier_t
from barrier in barrier_t.DefaultIfEmpty()
join risky in DbContext.trade_risky_option on eodPos.TradeId equals risky.TradeId into risky_t
from risky in risky_t.DefaultIfEmpty()
join accumulator in DbContext.trade_accumulator_option on eodTrade.TradeId equals accumulator.TradeId into accumulator_t
from accumulator in accumulator_t.DefaultIfEmpty()
join um in DbContext.underlying_manager on eodTrade.UnderlyingCode equals um.UnderlyingCode into um_t
from um in um_t.DefaultIfEmpty()
where !statusList.Contains(eodTrade.TradeStatus)
&& (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId))
&& (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id))
select new EodPositionRisksDTO
{
PayoffType = (binary != null && trade.TradeType == "二元期权") ? binary.PayoffType : null,
CashOrNothingAmount = (binary != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmount : null,
CashOrNothingAmountRate = (binary != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmountRate : null,
MonitorType = (binary != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? (binary.MonitorType ?? "否") : null,
RebateType = (binary != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? binary.RebateType : null,
StrikeType = (asian != null && trade.TradeType == "亚式期权") ? asian.StrikeType : null,
AveragingPeriodStartDate = (asian != null && trade.TradeType == "亚式期权") ? asian.AveragingPeriodStartDate : null,
PayoffType2 = (asian != null && trade.TradeType == "亚式期权") ? asian.PayoffType : null,
ParticipationRate = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate1 : trade != null ? trade.ParticipationRate ?? 1 : 1,
StrikeGearingFactor = (asian != null && trade.TradeType == "亚式期权") ? asian.StrikeGearingFactor : null,
EnhancedPrice = (asian != null && trade.TradeType == "亚式期权") ? asian.EnhancedPrice : 0,
BarrierType = (barrier != null && trade.TradeType == "障碍期权") ? barrier.BarrierType : null,
Discrete = (barrier != null && trade.TradeType == "障碍期权") ? barrier.Discrete : null,
BarrierPrice = (barrier != null && trade.TradeType == "障碍期权") ? barrier.BarrierPrice : null,
UpperBarrierPrice = (barrier != null && trade.TradeType == "障碍期权" && barrier.BarrierType.Contains("双障碍")) ? barrier.UpperBarrierPrice : null,
Rebate = (barrier != null && trade.TradeType == "障碍期权") ? barrier.Rebate : null,
RebateRate = (barrier != null && trade.TradeType == "障碍期权") ? barrier.RebateRate : null,
BarrierShift = (barrier != null && trade.TradeType == "障碍期权") ? barrier.BarrierShift : null,
RebateType3 = (barrier != null && trade.TradeType == "障碍期权") ? barrier.RebateType : null,
AccumulatorStructureTypeStr = (accumulator != null && trade.TradeType == "累计期权") ? accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented ? "三段式" : "标准" : null,
GroupName = trade.GroupName,
Strike2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike2 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike2 : null),
Strike3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike3 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike3 : null),
ParticipationRate2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate2 : null,
ParticipationRate3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate3 : null,
id = trade.id,
InitMargin = trade.InitialMargin,
OptionType = trade.OptionType,
ClientName = trade.ClientName,
TraderName = trade.TraderName,
AssetBookName = assetUnit != null ? assetUnit.Name : null,
CurrentVolatility = eodRisk.Vol,
PositionPnl = eodPos != null ? eodPos.PositionPnL : 0,//浮动盈亏
RoundedPositionPnl = eodPos != null ? eodPos.RoundedPositionPnL : 0,
PV = eodPos != null ? eodPos.Pv : 0,
RoundedPV = eodPos != null ? eodPos.RoundedPv : 0,
Vega = eodRisk.Vega, //实现盈亏
Theta = eodRisk.Theta,
Rho = eodRisk.Rho,
Delta = eodRisk.Delta,
Gamma = eodRisk.Gamma,
DeltaCash = eodRisk.DeltaCash,
GammaCash = eodRisk.GammaCash,
VegaCash = eodRisk.VegaCash,
ExerciseDate = trade.ExerciseDate,
ExerciseMode = trade.ExerciseMode,
Notional = eodPos != null ? eodPos.Amount : 0,
StockEqvNotionalMax = trade.StockEqvNotionalMax,
OriginalStockEqvNotional = trade.OriginalStockEqvNotional,
Strike = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike1 : trade != null ? trade.Strike : null,
IsMoneynessOption = trade.IsMoneynessOption,
ExchangeOptionCode = eodPos != null ? eodPos.ExchangeOptionCode : "",
IsUsePremiumRate = trade.IsUsePremiumRate,
PremiumRate = trade.PremiumRate,
TradeDate = trade.TradeDate,
ParentTradeNumber = parentTrade != null ? parentTrade.TradeNumber : trade.TradeNumber,
ContractCode = tr.ContractCode,
TradeNumber = trade.TradeNumber,
ParentTradeId = trade.ParentTradeId,
TradePrice = trade.TradePrice,
BuySell = trade.BuySell,
TradeSinglePrice = trade.TradeSinglePrice,
TradeType = trade.TradeType,
StructureType = trade.StructureType != "结构化交易" ? trade.StructureType : null,
UnderlyingCode = eodTrade.UnderlyingCode,
IsGroup = trade.IsGroup,
TradeJson = eodTrade.TradeJson,
Margin = eodPos != null ? eodPos.Margin : 0,
Spv1 = tradespan.Spv1,
Spv2 = tradespan.Spv2,
Spv3 = tradespan.Spv3,
Exposure = eodRisk.CreditExposure,
RealizedPnl = eodPos != null ? eodPos.ClosedPnL : 0,
PnLDelta = eodPnl.PnLDelta,
PnLGamma = eodPnl.PnLGamma,
PnLVega = eodPnl.PnLVega,
PnLTheta = eodPnl.PnLTheta,
PnLPsi = eodPnl.PnLPsi,
dailyPnl = eodPos != null ? eodPos.DailyPnL : 0,
HedgeUniqueCode = eodPos != null ? eodPos.HedgeUniqueCode : "",
OriginalPrincipalSum = trade.OriginalPrincipalSum,
SurvivingNominalPrincipal = trade.SpotPrice * eodPos.Amount,
Comments = trade.Comments
};
query = query.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber);
var searchResult = query.ToSearchList(req, isWithOrder: true);
var priceDict = new EodPriceProvider(req.ValueDate);
var tcActions = new[] { ClientCashInCashOut.系统操作_平仓费,
ClientCashInCashOut.系统操作_行权费,ClientCashInCashOut.系统操作_票息,ClientCashInCashOut.系统操作_互换,ClientCashInCashOut.人工操作_其他};
var underlyingCodes = searchResult.rows.Select(O => O.UnderlyingCode).Distinct().ToList();
var greeksHandleService = new GLMSGreeksHandleService();
greeksHandleService.InitData(req.ValueDate, underlyingCodes);
foreach (var r in searchResult.rows)
{
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(r.UnderlyingCode);
if (um == null)
{
um = new underlying_manager();
}
else
{
r.UnderlyingPrice = um.Price ?? 0;
r.UnderlyingId = um.id;
r.VarietyId = um.UnderlyingTypeId;
r.UnderlyingAssetName = um.UnderlyingName;
r.CountRatio = um.CountRatio;
if (PS.Config.IsGuoJun)
{
r.UnderlyingVariety = UnderlyingHelper.GetUnderlyingVarietyCode(r.UnderlyingCode);
}
}
//争取直接从eodrisk表取
r.UnderlyingPrice = priceDict.GetPrice(r.UnderlyingCode,
useClosePrice ? r.trade?.SettlementType ?? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice);
r.RiskFreeRate = r.trade?.NoRiskRate ?? valuedateBLL.RiskFreeRate / 100;
r.DividendRate = r.trade?.DividendRate ?? r.RiskFreeRate;
r.OriginalNotional = r.trade?.OriginalNotional;
r.TradeOriginalAmount = r.OriginalNotional / um.CountRatio;
r.TradeStatus = r.trade?.TradeStatus;
r.StockEqvNotional = r.trade?.StockEqvNotional;
r.InitialSpotPrice = r.trade?.SpotPrice;
if (r.trade != null)
{
r.PosiInitMargin = r.InitMargin * r.trade.Notional / r.trade.OriginalNotional;
}
switch (r.TradeType)
{
case "雪球期权":
r.KnockInOutStatus = r.trade?.trade_snowball.KnockInOutStatusCn;
break;
case "凤凰期权":
r.KnockInOutStatus = r.trade?.trade_autocall.KnockInOutStatusCn;
break;
case "双鲨期权":
r.KnockInOutStatus = r.trade?.trade_double_sharkfin_option.KnockInOutStatusCn;
break;
case "障碍期权":
r.KnockInOutStatus = r.trade?.trade_barrier_option.KnockInOutStatusCn;
break;
case "气囊结构":
r.KnockInOutStatus = r.trade?.trade_airbag.KnockInOutStatusCn;
break;
case "累计期权":
r.Strike = r.trade?.Strike;
var settleMode = DbContext.autocall_observation.Where(n => n.TradeId == r.id && n.EndDate <= req.ValueDate)
.OrderByDescending(n => n.EndDate).Select(n => n.SettlementMode).FirstOrDefault();
r.KnockInOutStatus = settleMode == "敲出" ? "敲出" : "观察中";
break;
}
r.etcTradePrice = ConsTrade.TradeTypesForHedge.Contains(r.TradeType)
? r.TradePrice
: r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional);
if (r.id > 0)
{
if (r.trade != null)
{
r.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? r.RoundedPV : r.PV, r.Notional
, PS.Config.ErpElement.IsPVIncludePrincipal ? r.trade.PrincipalSum() : 0, r.trade.BuySell, r.trade.TradeType, false);
}
if (r.trade != null)
{
r.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(r.trade.ClientId)?.Number;
}
if (r.trade != null && r.trade.IsGroup == 1)
{
var eodtrade = DbContext.eod_trade.Where(x => x.ValueDate == req.ValueDate && x.ParentTradeId == r.id && ConsTrade.LiveTradeStatusList.Contains(x.TradeStatus)).ToList();
r.etcTradePrice = eodtrade.Select(x => (x.trade.BuySell == "买入" ? -1 : 1) * x.trade.TradePrice * x.trade.StockEqvNotional / x.trade.OriginalStockEqvNotional).Sum();
}
if (r.ParentTradeId > 0)
{
var childTrades = DbContext.trade.Where(x => x.ParentTradeId == r.ParentTradeId).OrderBy(x => x.TradeNumber).Select(x => x.id).ToList();
r.ChildLeg = (childTrades.IndexOf(r.id) + 1).ToString();
}
}
if (r.IsGroup == 1)
{
var childTradeIds = DbContext.trade.Where(y => y.ParentTradeId == r.id && y.ValidState != "InValid").Select(y => y.id).ToList();
var childTrades = DbContext.trade.Where(y => childTradeIds.Contains(y.id)).ToList();
var childTradeCashs = DbContext.trade_cash.Where(t => childTradeIds.Contains(t.TradeId)
&& t.ValidState != ConsGlobal.InValid && t.ValueDate <= req.ValueDate
&& !t.IsDeleted && tcActions.Contains(t.Action)).ToList();
var childEodPositions = DbContext.Set<T1>().Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList();
var eodTradeRisks = DbContext.Set<T2>().Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList();
var eodTradePnls = DbContext.Set<T3>().Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList();
var tradeSpans = DbContext.trade_span.Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList();
r.PV = childEodPositions.Sum(y => y.Pv);
r.RoundedPV = childEodPositions.Sum(y => y.RoundedPv);
r.PositionPnl = childEodPositions.Sum(y => y.PositionPnL);
r.RoundedPositionPnl = childEodPositions.Sum(y => y.RoundedPositionPnL);
r.RealizedPnl = childTradeCashs.Sum(n => n.Amount + (n.Action == ClientCashInCashOut.系统操作_票息 ? 0 : (n.UnwindPercentRate == null ? 0 : n.UnwindPercentRate)) * (childTrades.FirstOrDefault(x => x.id == n.TradeId) == null || childTrades.First(x => x.id == n.TradeId).TradePrice == null ? 0 : childTrades.First(x => x.id == n.TradeId).TradePrice * ((childTrades.First(x => x.id == n.TradeId).BuySell == "卖出") ? 1 : -1))) ?? 0;
r.Margin = childEodPositions.Sum(y => y.Margin);
r.Delta = eodTradeRisks.Sum(y => y.Delta);
r.Gamma = eodTradeRisks.Sum(y => y.Gamma);
r.Vega = eodTradeRisks.Sum(y => y.Vega);
r.Theta = eodTradeRisks.Sum(y => y.Theta);
r.Rho = eodTradeRisks.Sum(y => y.Rho);
r.Exposure = eodTradeRisks.Sum(y => y.CreditExposure);
r.PnLDelta = eodTradePnls.Sum(y => y.PnLDelta);
r.PnLGamma = eodTradePnls.Sum(y => y.PnLGamma);
r.PnLVega = eodTradePnls.Sum(y => y.PnLVega);
r.PnLTheta = eodTradePnls.Sum(y => y.PnLTheta);
r.PnLPsi = eodTradePnls.Sum(y => y.PnLPsi);
r.Spv1 = tradeSpans.Sum(y => y.Spv1);
r.Spv2 = tradeSpans.Sum(y => y.Spv2);
r.Spv3 = tradeSpans.Sum(y => y.Spv3);
r.Notional = r.trade.Notional;
r.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? r.RoundedPV : r.PV, r.Notional
, PS.Config.ErpElement.IsPVIncludePrincipal ? r.trade.PrincipalSum() : 0, r.trade.BuySell, r.trade.TradeType, false);
}
if (um != null)
{
r.GammaLots = (r.Gamma ?? 0) / um.ContractSize;
r.DeltaLots = (r.Delta ?? 0) / um.ContractSize;
}
r.Rho *= 100;
greeksHandleService.Handle(r,um);
if (r.trade == null)
{
r.TradeSinglePrice = r.etcTradePrice / r.TradeAmount;
}
}
if (!isSwapTrades)
{
searchResult.Sum = new
{
dpnl = GetDPnL<T1, T3>(req, DbContext)
};
}
return searchResult;
}
private Expression<Func<eod_trade, bool>> BuildPredicateOfEodTrade(EodPositionRisksReq reqModel, bool isSwapTrades)
{
var predicate = PredicateBuilder.Create<eod_trade>(t => t.ValueDate == reqModel.ValueDate);
if (reqModel.UserAssets != null || reqModel.UserClients != null)
{
predicate = predicate.And(t => reqModel.UserAssets.Contains(t.AssetId) || reqModel.UserClients.Contains(t.ClientId));
}
if (reqModel.ClientIds != null && reqModel.ClientIds.Any(x => x > 0))
{
predicate = predicate.And(q => reqModel.ClientIds.Contains(q.ClientId));
}
if (reqModel.BookIds.Any())
{
predicate = predicate.And(q => reqModel.BookIds.Contains(q.AssetId));
}
if (reqModel.TradeIds != null && reqModel.TradeIds.Any(x => x != 0))
{
predicate = predicate.And(q => reqModel.TradeIds.Contains(q.TradeId) || reqModel.TradeIds.Contains(-q.id));
}
reqModel.VarietyIds = reqModel.VarietyIds == null ? Enumerable.Empty<int>() : reqModel.VarietyIds.Where(n => n > 0).ToArray();
reqModel.UnderlyingIds = reqModel.UnderlyingIds == null ? Enumerable.Empty<int>() : reqModel.UnderlyingIds.Where(n => n > 0).ToArray();
reqModel.SettlementFlags = reqModel.SettlementFlags == null ? Enumerable.Empty<int>() : reqModel.SettlementFlags.ToArray();
if (isSwapTrades)
{
predicate = predicate.And(q => q.TradeType == "收益互换");
}
else
{
predicate = predicate.And(q => q.TradeType != "收益互换");
}
return predicate;
}
public SearchListResult<EodPositionRisksDTO> SearchEodPositionRisksListV2<T1, T2, T3>(EodPositionRisksReq req
, bool isSwapTrades, bool useClosePrice = true)
where T1 : EodTradePosition where T2 : EodTradeRisk where T3 : EodPnl
{
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
DateTime? TradeDateTemp = null;
if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue)
{
TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1);
}
if (req.needSettleData)
{
statusList = new List<string>();
}
var eodPredicate = BuildPredicateOfEodTradePosition(req, isSwapTrades);
var tradePredicate = PredicateBuilder.Create<trade>(t => t.ValidState != "InValid");
var exTradeTypes = ConsTrade.TradeTypesForHedge.AsEnumerable(); //场内交易类型
if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x)))
{
exTradeTypes = ConsTrade.TradeTypesForHedge.Intersect(req.TradeTypes).ToArray();
if (req.TradeTypes.Count() == 1 && req.TradeTypes.Contains("收益互换"))
{
tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType ?? d.TradeType) && d.IsGroup != 1);
}
else
{
tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0));
}
}
if (!string.IsNullOrWhiteSpace(req.TradeNumber))
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber));
}
if (!string.IsNullOrEmpty(req.GroupNames) && req.GroupNamesList != null && req.GroupNamesList.Count > 0)
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
var gname = req.GroupNamesList[0];
var groupNamePredicate = PredicateBuilder.Create<trade>(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname.ToString()));
if (req.GroupNamesList.Count > 1)
{
for (int i = 1; i < req.GroupNamesList.Count; i++)
{
var gname1 = req.GroupNamesList[i];
groupNamePredicate = groupNamePredicate.Or(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname1.ToString()));
}
}
tradePredicate = tradePredicate.And(groupNamePredicate);
}
using (var db = DbContextFactory.GetYLDbContext())
{
var eodPos = db.Set<T1>().Where(eodPredicate).ToArray();
var tradeIds = eodPos.Select(O => O.TradeId);
var hedgeCodes = eodPos.Where(O => !O.HedgeUniqueCode.IsNullOrWhiteSpace()).Select(O => O.HedgeUniqueCode);
var bookIds = eodPos.Select(O => O.BookId);
var umCodes = eodPos.Select(O => O.UnderlyingCode);
var parentTradeIds = eodPos.Where(O => O.ParentTradeId > 0).Select(O => O.ParentTradeId);
var trDict =
db.trade_contract_r
.Where(O => O.Type == "交易确认书" && O.IsValid && tradeIds.Contains(O.TradeId)).ToDictionary(O => O.TradeId, V => V.ContractCode);
var eodRiskDict =
db.Set<T2>()
.Where(t => t.ValueDate == req.ValueDate && (tradeIds.Contains(t.TradeId) || hedgeCodes.Contains(t.HedgeUniqueCode + "")))
.GroupBy(O => O.TradeId + O.HedgeUniqueCode).ToDictionary(K => K.Key, V => V.FirstOrDefault());
var eodPnlDict =
db.Set<T3>().Where(O => O.ValueDate == req.ValueDate && tradeIds.Contains(O.TradeId))
.GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var tradespanDict =
db.trade_span.Where(O => O.ValueDate == req.ValueDate && tradeIds.Contains(O.TradeId))
.GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var assetUnitDict = DataCacheProvider.GetAssetUnitDataSource().AsQueryable(O => bookIds.Contains(O.id)).ToDictionary(K => K.id, V => V.Name);
var eodTradeDict =
db.eod_trade.Where(O => O.ValueDate == req.ValueDate && tradeIds.Contains(O.TradeId))
.GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var tradeDict =
db.trade.Where(t => t.ValidState != "InValid" && t.TradeType != "结构化交易" && (tradeIds.Contains(t.id) || parentTradeIds.Contains(t.id)))
.GroupBy(O => O.id).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var binaryDict = db.trade_binary_option.Where(O => tradeIds.Contains(O.TradeId))
.GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var asianDict = db.trade_asian_option.Where(O => tradeIds.Contains(O.TradeId))
.GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var barrierDict = db.trade_barrier_option.Where(O => tradeIds.Contains(O.TradeId))
.GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault());
var umDict = DataCacheProvider.GetUnderlyingDataSource().AsQueryable(O => umCodes.Contains(O.UnderlyingCode)).ToDictionary(K => K.UnderlyingCode, V => V);
var tradeIdList =
db.trade.Where(tradePredicate).Select(O => O.id);
var priceDict = new EodPriceProvider(req.ValueDate);
var list = new List<EodPositionRisksDTO>();
foreach (var item in eodPos)
{
eodTradeDict.TryGetValue(item.TradeId, out var eodTrade);
umDict.TryGetValue(item.UnderlyingCode, out var um);
tradeDict.TryGetValue(item.TradeId, out var trade);
//原Linq条件,满足取反条件则跳过;
if (!((item.TradeId == 0 || eodTrade == null || !statusList.Contains(eodTrade.TradeStatus))
&& (item.TradeId > 0 || exTradeTypes.Contains(item.TradeType))
&& (item.TradeId < 1 || tradeIdList.Any(n => n == item.TradeId))
&& (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId))
&& (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id))
&& (!req.SettlementFlags.Any() || trade != null && req.SettlementFlags.Contains(trade.SettlementFlag))
&& (!TradeDateTemp.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) < TradeDateTemp)
&& (!req.SettlementDateStart.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) >= req.SettlementDateStart)
|| (!req.SettlementFlags.Any() && !TradeDateTemp.HasValue && !req.SettlementDateStart.HasValue && trade == null)))
{
continue;
}
tradeDict.TryGetValue(item.ParentTradeId, out var parentTrade);
assetUnitDict.TryGetValue(item.BookId, out var assetUnitName);
eodRiskDict.TryGetValue(item.TradeId + (item.HedgeUniqueCode ?? ""), out var eodRisk);
trDict.TryGetValue(item.TradeId, out var trCode);
tradespanDict.TryGetValue(item.TradeId, out var tradespan);
eodPnlDict.TryGetValue(item.TradeId, out var eodPnl);
var parentEodTradeList = eodTradeDict.Values.Where(O => O.ParentTradeId == item.ParentTradeId).ToArray();
var obj = new EodPositionRisksDTO();
if (trade != null)
{
if (trade?.TradeType == "二元期权" && binaryDict.TryGetValue(item.TradeId, out var binary))
{
obj.PayoffType = binary.PayoffType;
obj.CashOrNothingAmount = binary.CashOrNothingAmount;
obj.CashOrNothingAmountRate = binary.CashOrNothingAmountRate;
if (trade.ExerciseMode != "European")
{
obj.MonitorType = binary.MonitorType ?? "否";
obj.RebateType = binary.RebateType;
}
}
if (trade?.TradeType == "亚式期权" && asianDict.TryGetValue(item.TradeId, out var asian))
{
obj.StrikeType = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeType : null;
obj.AveragingPeriodStartDate = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.AveragingPeriodStartDate : null;
obj.PayoffType2 = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.PayoffType : null;
obj.StrikeGearingFactor = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeGearingFactor : null;
}
if (trade?.TradeType == "障碍期权" && barrierDict.TryGetValue(item.TradeId, out var barrier))
{
obj.BarrierType = barrier.BarrierType;
obj.Discrete = barrier.Discrete;
obj.BarrierPrice = barrier.BarrierPrice;
obj.Rebate = barrier.Rebate;
obj.RebateRate = barrier.RebateRate;
obj.BarrierShift = barrier.BarrierShift;
obj.RebateType3 = barrier.RebateType;
if (barrier.BarrierType.Contains("双障碍"))
{
obj.UpperBarrierPrice = barrier.UpperBarrierPrice;
}
}
obj.OptionType = trade.OptionType;
obj.ClientName = trade.ClientName;
obj.TraderName = trade.TraderName;
}
obj.ParticipationRate = trade?.ParticipationRate ?? 1;
obj.GroupName = trade?.GroupName ?? "";
obj.id = trade?.id ?? -item.id;
obj.AssetBookName = assetUnitName;
obj.CurrentVolatility = eodRisk?.Vol;
obj.Vega = eodRisk?.Vega;
obj.Theta = eodRisk?.Theta;
obj.Rho = eodRisk?.Rho;
obj.Delta = eodRisk?.Delta;
obj.Gamma = eodRisk?.Gamma;
obj.DeltaCash = eodRisk?.DeltaCash;
obj.GammaCash = eodRisk?.GammaCash;
obj.VegaCash = eodRisk?.VegaCash;
obj.Exposure = eodRisk?.CreditExposure;
obj.PositionPnl = item.PositionPnL;//浮动盈亏
obj.RoundedPositionPnl = item.RoundedPositionPnL;
obj.PV = item.Pv;
obj.RoundedPV = item.RoundedPv;
obj.ExerciseDate = trade?.ExerciseDate;
obj.ExerciseMode = trade?.ExerciseMode;
obj.SettlementDate = trade?.SettlementDate ?? trade?.ExerciseDate;
obj.SettlementFlag = trade?.SettlementFlag ?? 0;
obj.OriginalNotional = trade?.OriginalNotional ?? item.Amount;
obj.Notional = item.Amount;
obj.StockEqvNotionalMax = trade?.StockEqvNotionalMax;
obj.OriginalStockEqvNotional = trade?.OriginalStockEqvNotional;
obj.Strike = trade?.Strike;
obj.IsMoneynessOption = trade?.IsMoneynessOption ?? "";
obj.ExchangeOptionCode = item.ExchangeOptionCode;
obj.IsUsePremiumRate = trade?.IsUsePremiumRate;
obj.PremiumRate = trade?.PremiumRate;
obj.TradeDate = trade?.TradeDate;
obj.ParentTradeNumber = parentTrade?.TradeNumber ?? trade?.TradeNumber;
obj.ContractCode = trCode;
obj.TradeNumber = trade?.TradeNumber;
obj.ParentTradeId = trade?.ParentTradeId ?? 0;
obj.TradePrice = trade?.TradePrice ?? item.Cost;
obj.BuySell = ConsTrade.TradeTypesForHedge.Contains(item.TradeType) ? (item.Amount < 0 ? "空头开仓" : "多头开仓") : item.BuySell;
obj.TradeSinglePrice = trade?.TradeSinglePrice ?? (item.Amount > 0 ? item.Cost / item.Amount : 0);
obj.TradeType = item.TradeType;
obj.StructureType = trade != null && trade.StructureType != "结构化交易" ? trade.StructureType : null;
obj.UnderlyingCode = eodTrade?.UnderlyingCode ?? item.UnderlyingCode;
obj.TradeJson = eodTrade?.TradeJson;
obj.Margin = item.Margin;
obj.Spv1 = tradespan?.Spv1;
obj.Spv2 = tradespan?.Spv2;
obj.Spv3 = tradespan?.Spv3;
obj.RealizedPnl = item.ClosedPnL; //实现盈亏
obj.PnLDelta = eodPnl?.PnLDelta;
obj.PnLGamma = eodPnl?.PnLGamma;
obj.PnLVega = eodPnl?.PnLVega;
obj.PnLTheta = eodPnl?.PnLTheta;
obj.PnLPsi = eodPnl?.PnLPsi;
obj.dailyPnl = item.DailyPnL;
obj.HedgeUniqueCode = item.HedgeUniqueCode;
obj.OriginalPrincipalSum = trade?.OriginalPrincipalSum;
if (obj.TradeType == "场内期权")
{
var exoption = DataCacheProvider.GetExchangeListOptionDataSource().GetData(obj.ExchangeOptionCode);
if (exoption != null)
{
obj.Strike = exoption.Strike;
obj.ExerciseDate = exoption.MaturityDate;
obj.OptionType = exoption.OptionType;
}
}
else if (obj.id < 0 && !obj.Delta.HasValue)
{
obj.Delta = obj.Notional ?? 0;
}
if (um == null)
{
um = new underlying_manager();
}
else
{
obj.UnderlyingPrice = um.Price ?? 0;
obj.UnderlyingId = um.id;
obj.VarietyId = um.UnderlyingTypeId;
obj.UnderlyingAssetName = um.UnderlyingName;
obj.CountRatio = um.CountRatio;
if (PS.Config.IsGuoJun)
{
obj.UnderlyingVariety = UnderlyingHelper.GetUnderlyingVarietyCode(obj.UnderlyingCode);
}
}
//争取直接从eodrisk表取
obj.UnderlyingPrice = priceDict.GetPrice(obj.UnderlyingCode,
useClosePrice ? obj.trade?.SettlementType ?? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice);
obj.RiskFreeRate = obj.trade?.NoRiskRate ?? valuedateBLL.RiskFreeRate / 100;
obj.DividendRate = obj.trade?.DividendRate ?? obj.RiskFreeRate;
obj.TradeStatus = obj.trade?.TradeStatus;
obj.StockEqvNotional = obj.trade?.StockEqvNotional;
//如果时场内期权交易,没有收盘eod_trade数据,那就保留eod_position的数据
if (obj.trade != null)
{
obj.OriginalNotional = obj.trade.OriginalNotional;
}
obj.InitialSpotPrice = obj.trade?.SpotPrice;
switch (obj.TradeType)
{
case "雪球期权":
obj.KnockInOutStatus = obj.trade?.trade_snowball.KnockInOutStatusCn;
break;
case "凤凰期权":
obj.KnockInOutStatus = obj.trade?.trade_autocall.KnockInOutStatusCn;
break;
case "双鲨期权":
obj.KnockInOutStatus = obj.trade?.trade_double_sharkfin_option.KnockInOutStatusCn;
break;
case "障碍期权":
obj.KnockInOutStatus = obj.trade?.trade_barrier_option.KnockInOutStatusCn;
break;
case "气囊结构":
obj.KnockInOutStatus = obj.trade?.trade_airbag.KnockInOutStatusCn;
break;
case "累计期权":
obj.Strike = obj.trade?.Strike;
var settleMode = db.autocall_observation.Where(n => n.TradeId == obj.id && n.EndDate <= req.ValueDate)
.OrderByDescending(n => n.EndDate).Select(n => n.SettlementMode).FirstOrDefault();
obj.KnockInOutStatus = settleMode == "敲出" ? "敲出" : "观察中";
break;
}
if (um != null)
{
obj.GammaLots = (obj.Gamma ?? 0) / um.ContractSize;
obj.DeltaLots = (obj.Delta ?? 0) / um.ContractSize;
}
obj.Rho *= 100;
obj.CountRatio = um.CountRatio;
obj.TradeOriginalAmount = obj.OriginalNotional / um.CountRatio;
obj.etcTradePrice = ConsTrade.TradeTypesForHedge.Contains(obj.TradeType)
? obj.TradePrice
: obj.TradePrice * (obj.trade == null ? obj.Notional / obj.OriginalNotional : obj.trade?.StockEqvNotional / obj.trade?.OriginalStockEqvNotional);
if (obj.id > 0)
{
if (obj.trade != null)
{
obj.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? obj.RoundedPV : obj.PV, obj.Notional
, PS.Config.ErpElement.IsPVIncludePrincipal ? obj.trade.PrincipalSum() : 0, obj.trade.BuySell, obj.trade.TradeType, false);
}
if (obj.trade != null)
{
obj.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(obj.trade.ClientId)?.Number;
}
if (obj.trade != null && obj.trade.IsGroup == 1 && parentEodTradeList != null)
{
obj.etcTradePrice = parentEodTradeList.Select(x => (x.trade.BuySell == "买入" ? -1 : 1) * x.trade.TradePrice * x.trade.StockEqvNotional / obj.trade.OriginalStockEqvNotional).Sum() ?? 0;
}
if (obj.ParentTradeId > 0 && parentEodTradeList != null)
{
obj.ChildLeg = (parentEodTradeList.Select(O => O.id).ToList().IndexOf(obj.id) + 1).ToString();
}
}
else
{
obj.SinglePV = obj.PV.HasValue && obj.Notional.HasValue && obj.Notional.Value != 0
? Math.Abs(obj.PV.Value / obj.Notional.Value) : 0;
if (obj.TradeType == "场内期权")
{
obj.OptionType = DataCacheProvider.GetExchangeListOptionDataSource().GetData(obj.ExchangeOptionCode).OptionType;
}
}
list.Add(obj);
}
list = list.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber).ToList();
var searchResult = new SearchListResult<EodPositionRisksDTO>();
searchResult.total = 1;
searchResult.records = list.Count;
searchResult.page = 1;
searchResult.rows = list;
if (!isSwapTrades)
{
searchResult.Sum = new
{
dpnl = GetDPnL<T1, T3>(req, db)
};
}
return searchResult;
}
}
public SearchListResult<EodPositionRisksDTO> SearchEodPositionRisksList<T1, T2, T3>(EodPositionRisksReq req
, bool isSwapTrades, bool useClosePrice = true)
where T1 : EodTradePosition where T2 : EodTradeRisk where T3 : EodPnl
{
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
DateTime? TradeDateTemp = null;
if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue)
{
TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1);
}
if (req.needSettleData)
{
statusList = new List<string>();
}
var eodPredicate = BuildPredicateOfEodTradePosition(req, isSwapTrades);
var tradePredicate = PredicateBuilder.Create<trade>(t => t.ValidState != "InValid");
var exTradeTypes = ConsTrade.TradeTypesForHedge.AsEnumerable(); //场内交易类型
if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x)))
{
exTradeTypes = ConsTrade.TradeTypesForHedge.Intersect(req.TradeTypes).ToArray();
if (req.TradeTypes.Count() == 1 && req.TradeTypes.Contains("收益互换"))
{
tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType ?? d.TradeType) && d.IsGroup != 1);
}
else
{
tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0));
}
}
if (!string.IsNullOrWhiteSpace(req.TradeNumber))
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber));
}
if (!string.IsNullOrEmpty(req.GroupNames) && req.GroupNamesList != null && req.GroupNamesList.Count > 0)
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
var gname = req.GroupNamesList[0];
var groupNamePredicate = PredicateBuilder.Create<trade>(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname.ToString()));
if (req.GroupNamesList.Count > 1)
{
for (int i = 1; i < req.GroupNamesList.Count; i++)
{
var gname1 = req.GroupNamesList[i];
groupNamePredicate = groupNamePredicate.Or(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname1.ToString()));
}
}
tradePredicate = tradePredicate.And(groupNamePredicate);
}
if (req.TagIds != null && req.TagIds.Count > 0)
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
var tradeTagIdQuery = from tt in DbContext.trade_tag
where req.TagIds.Contains(tt.TagId)
select tt.TradeId;
tradePredicate = tradePredicate.And(p => tradeTagIdQuery.Contains(p.id));
}
var query = from eodPos in DbContext.Set<T1>().Where(eodPredicate)
join tr in DbContext.trade_contract_r.Where(O => O.Type == "交易确认书" && O.IsValid) on eodPos.TradeId equals tr.TradeId into trs
from tr in trs.DefaultIfEmpty()
join eodRisk in DbContext.Set<T2>().Where(t => t.ValueDate == req.ValueDate) on new { id = eodPos.TradeId, code = eodPos.HedgeUniqueCode + "" } equals new { id = eodRisk.TradeId, code = eodRisk.HedgeUniqueCode + "" } into eodrisk_t
from eodRisk in eodrisk_t.DefaultIfEmpty()
join eodPnl in DbContext.Set<T3>().Where(O => O.ValueDate == req.ValueDate && O.TradeId > 0) on eodPos.TradeId equals eodPnl.TradeId into eodPnls
from eodPnl in eodPnls.DefaultIfEmpty()
join tradespan in DbContext.trade_span.Where(O => O.ValueDate == req.ValueDate) on eodPos.TradeId equals tradespan.TradeId into tradespans
from tradespan in tradespans.DefaultIfEmpty()
join assetUnit in DbContext.assetunit on eodPos.BookId equals assetUnit.id into assetUnits
from assetUnit in assetUnits.DefaultIfEmpty()
join eodTrade in DbContext.eod_trade.Where(O => O.ValueDate == req.ValueDate) on eodPos.TradeId equals eodTrade.TradeId into eodTrades
from eodTrade in eodTrades.DefaultIfEmpty()
join trade in DbContext.trade.Where(t => t.ValidState != "InValid" && t.TradeType != "结构化交易") on eodPos.TradeId equals trade.id into trades
from trade in trades.DefaultIfEmpty()
join parentTrade in DbContext.trade.Where(tr => tr.ValidState != "InValid" && tr.TradeType == "结构化交易") on trade.ParentTradeId equals parentTrade.id into parentTrades
from parentTrade in parentTrades.DefaultIfEmpty()
join binary in DbContext.trade_binary_option on eodPos.TradeId equals binary.TradeId into binary_t
from binary in binary_t.DefaultIfEmpty()
join asian in DbContext.trade_asian_option on eodPos.TradeId equals asian.TradeId into asian_t
from asian in asian_t.DefaultIfEmpty()
join barrier in DbContext.trade_barrier_option on eodPos.TradeId equals barrier.TradeId into barrier_t
from barrier in barrier_t.DefaultIfEmpty()
join risky in DbContext.trade_risky_option on eodPos.TradeId equals risky.TradeId into risky_t
from risky in risky_t.DefaultIfEmpty()
join accumulator in DbContext.trade_accumulator_option on eodTrade.TradeId equals accumulator.TradeId into accumulator_t
from accumulator in accumulator_t.DefaultIfEmpty()
join um in DbContext.underlying_manager on eodPos.UnderlyingCode equals um.UnderlyingCode into um_t
from um in um_t.DefaultIfEmpty()
where (eodPos.TradeId == 0 || !statusList.Contains(eodTrade.TradeStatus))
&& (eodPos.TradeId > 0 || exTradeTypes.Contains(eodPos.TradeType))
&& (eodPos.TradeId < 1 || DbContext.trade.Where(n => n.id == eodPos.TradeId).Where(tradePredicate).Any())
&& (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId))
&& (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id))
// req.SettlementFlags.Any() && TradeDateTemp.HasValue && req.SettlementDateStart.HasValue 是场外期权的筛选条件 trade != null 会把场内交易过滤掉,所以三个筛选条件都没有的情况下要让 trade 可以 == null
&& ((!req.SettlementFlags.Any() || trade != null && req.SettlementFlags.Contains(trade.SettlementFlag))
&& (!TradeDateTemp.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) < TradeDateTemp)
&& (!req.SettlementDateStart.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) >= req.SettlementDateStart)
|| (!req.SettlementFlags.Any() && !TradeDateTemp.HasValue && !req.SettlementDateStart.HasValue && trade == null))
select new EodPositionRisksDTO
{
PayoffType = (binary != null && trade != null && trade.TradeType == "二元期权") ? binary.PayoffType : null,
CashOrNothingAmount = (binary != null && trade != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmount : null,
CashOrNothingAmountRate = (binary != null && trade != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmountRate : null,
MonitorType = (binary != null && trade != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? (binary.MonitorType ?? "否") : null,
RebateType = (binary != null && trade != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? binary.RebateType : null,
StrikeType = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeType : null,
AveragingPeriodStartDate = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.AveragingPeriodStartDate : null,
PayoffType2 = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.PayoffType : null,
ParticipationRate = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate1 : trade != null ? trade.ParticipationRate ?? 1 : 1,
StrikeGearingFactor = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeGearingFactor : null,
EnhancedPrice = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.EnhancedPrice : 0,
BarrierType = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.BarrierType : null,
Discrete = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.Discrete : null,
BarrierPrice = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.BarrierPrice : null,
UpperBarrierPrice = (barrier != null && trade != null && trade.TradeType == "障碍期权" && barrier.BarrierType.Contains("双障碍")) ? barrier.UpperBarrierPrice : null,
Rebate = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.Rebate : null,
RebateRate = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.RebateRate : null,
BarrierShift = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.BarrierShift : null,
RebateType3 = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.RebateType : null,
AccumulatorStructureTypeStr = (accumulator != null && trade.TradeType == "累计期权") ? accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented ? "三段式" : "标准" : null,
GroupName = trade != null ? trade.GroupName : "",
Strike2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike2 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike2 : null),
Strike3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike3 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike3 : null),
ParticipationRate2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate2 : null,
ParticipationRate3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate3 : null,
id = trade != null ? trade.id : -eodPos.id,
InitMargin = trade != null ? trade.InitialMargin : null,
OptionType = trade != null ? trade.OptionType : null,
ClientName = trade != null ? trade.ClientName : null,
TraderName = trade != null ? trade.TraderName : null,
AssetBookName = assetUnit != null ? assetUnit.Name : null,
CurrentVolatility = eodRisk.Vol,
PositionPnl = eodPos.PositionPnL,//浮动盈亏
RoundedPositionPnl = eodPos.RoundedPositionPnL,
PV = eodPos.Pv,
RoundedPV = eodPos.RoundedPv,
Vega = eodRisk.Vega,
Theta = eodRisk.Theta,
Rho = eodRisk.Rho,
Delta = eodRisk.Delta,
Gamma = eodRisk.Gamma,
DeltaCash = eodRisk.DeltaCash,
GammaCash = eodRisk.GammaCash,
VegaCash = eodRisk.VegaCash,
ExerciseDate = trade != null ? trade.ExerciseDate : null,
ExerciseMode = trade != null ? trade.ExerciseMode : null,
SettlementDate = trade != null ? trade.SettlementDate ?? trade.ExerciseDate : null,
SettlementFlag = trade != null ? trade.SettlementFlag : 0,
OriginalNotional = trade != null ? trade.OriginalNotional : eodPos.Amount,
Notional = eodPos.Amount,
StockEqvNotionalMax = trade != null ? trade.StockEqvNotionalMax : null,
OriginalStockEqvNotional = trade != null ? trade.OriginalStockEqvNotional : null,
Strike = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike1 : trade != null ? trade.Strike : null,
IsMoneynessOption = trade != null ? trade.IsMoneynessOption : "",
ExchangeOptionCode = eodPos.ExchangeOptionCode,
IsUsePremiumRate = trade != null ? trade.IsUsePremiumRate : null,
PremiumRate = trade != null ? trade.PremiumRate : null,
TradeDate = trade != null ? trade.TradeDate : null,
ParentTradeNumber = parentTrade != null ? parentTrade.TradeNumber : (trade != null ? trade.TradeNumber : null),
ContractCode = tr.ContractCode,
TradeNumber = trade != null ? trade.TradeNumber : null,
ParentTradeId = trade != null ? trade.ParentTradeId : 0,
TradePrice = trade != null ? trade.TradePrice : eodPos.Cost,
BuySell = ConsTrade.TradeTypesForHedge.Contains(eodPos.TradeType) ? (eodPos.Amount < 0 ? "空头开仓" : "多头开仓") : eodPos.BuySell,
TradeSinglePrice = trade != null ? trade.TradeSinglePrice :
eodPos.Amount != 0 ? eodPos.Cost / eodPos.Amount : 0,
TradeType = eodPos.TradeType,
StructureType = trade.TradeType == "自定义交易" ? trade.StructureType : trade.TradeType,
UnderlyingCode = eodTrade != null ? eodTrade.UnderlyingCode : eodPos.UnderlyingCode,
//UnderlyingPrice,UnderlyingId,VarietyId,UnderlyingAssetName
TradeJson = eodTrade != null ? eodTrade.TradeJson : null,
Margin = eodPos.Margin,
Spv1 = tradespan.Spv1,
Spv2 = tradespan.Spv2,
Spv3 = tradespan.Spv3,
Exposure = eodRisk.CreditExposure,
RealizedPnl = eodPos.ClosedPnL, //实现盈亏
PnLDelta = eodPnl.PnLDelta,
PnLGamma = eodPnl.PnLGamma,
PnLVega = eodPnl.PnLVega,
PnLTheta = eodPnl.PnLTheta,
PnLPsi = eodPnl.PnLPsi,
dailyPnl = eodPos.DailyPnL,
HedgeUniqueCode = eodPos.HedgeUniqueCode,
OriginalPrincipalSum = trade != null ? trade.OriginalPrincipalSum : null,
SurvivingNominalPrincipal = trade.SpotPrice * eodPos.Amount,
Comments = trade.Comments
};
//if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x)))
//{
// query = query.Where(x => req.TradeTypes.Contains(x.TradeType) || req.TradeTypes.Contains(x.StructureType));
//}
query = query.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber);
var searchResult = query.ToSearchList(req, isWithOrder: true);
var priceDict = new EodPriceProvider(req.ValueDate);
var parentTradeIds = searchResult.rows.Where(O => O.ParentTradeId > 0).Select(O => O.ParentTradeId);
var parentTradeIdDict =
DbContext.trade
.Where(x => parentTradeIds.Contains(x.ParentTradeId))
.AsEnumerable()
.GroupBy(O => O.ParentTradeId).ToDictionary(
K => K.Key,
V => V.OrderBy(x => x.TradeNumber).Select(x => x.id).ToList());
var groupTradeIds = searchResult.rows.Where(O => O.ParentTradeId > 0 && O.trade != null && O.trade.IsGroup == 1).Select(O => O.ParentTradeId).ToList();
var eodtradeDict =
DbContext.eod_trade
.Where(x => x.ValueDate == req.ValueDate && groupTradeIds.Contains(x.ParentTradeId) && ConsTrade.LiveTradeStatusList.Contains(x.TradeStatus))
.AsEnumerable()
.GroupBy(O => O.ParentTradeId)
.ToDictionary(K => K.Key, V => V.Select(O => new xodTradeBase() { TradeJson = O.TradeJson }));
var underlyingCodes = searchResult.rows.Select(O => O.UnderlyingCode).Distinct().ToList();
var greeksHandleService = new GLMSGreeksHandleService();
greeksHandleService.InitData(req.ValueDate, underlyingCodes);
foreach (var r in searchResult.rows)
{
if (r.TradeType == "场内期权")
{
var exoption = DataCacheProvider.GetExchangeListOptionDataSource().GetData(r.ExchangeOptionCode);
if (exoption != null)
{
r.Strike = exoption.Strike;
r.ExerciseDate = exoption.MaturityDate;
r.OptionType = exoption.OptionType;
}
}
else if (r.id < 0 && !r.Delta.HasValue)
{
r.Delta = r.Notional ?? 0;
}
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(r.UnderlyingCode);
if (um == null)
{
um = new underlying_manager();
}
else
{
r.UnderlyingPrice = um.Price ?? 0;
r.UnderlyingId = um.id;
r.VarietyId = um.UnderlyingTypeId;
r.UnderlyingAssetName = um.UnderlyingName;
r.CountRatio = um.CountRatio;
if (PS.Config.IsGuoJun)
{
r.UnderlyingVariety = UnderlyingHelper.GetUnderlyingVarietyCode(r.UnderlyingCode);
}
}
//争取直接从eodrisk表取
r.UnderlyingPrice = priceDict.GetPrice(r.UnderlyingCode,
useClosePrice ? r.trade?.SettlementType ?? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice);
r.RiskFreeRate = r.trade?.NoRiskRate ?? valuedateBLL.RiskFreeRate / 100;
r.DividendRate = r.trade?.DividendRate ?? r.RiskFreeRate;
r.TradeStatus = r.trade?.TradeStatus;
r.StockEqvNotional = r.trade?.StockEqvNotional;
//如果时场内期权交易,没有收盘eod_trade数据,那就保留eod_position的数据
if (r.trade != null)
{
r.OriginalNotional = r.trade.OriginalNotional;
r.PosiInitMargin = r.InitMargin * r.trade.Notional / r.trade.OriginalNotional;
}
r.InitialSpotPrice = r.trade?.SpotPrice;
switch (r.TradeType)
{
case "雪球期权":
r.KnockInOutStatus = r.trade?.trade_snowball.KnockInOutStatusCn;
break;
case "凤凰期权":
r.KnockInOutStatus = r.trade?.trade_autocall.KnockInOutStatusCn;
break;
case "双鲨期权":
r.KnockInOutStatus = r.trade?.trade_double_sharkfin_option.KnockInOutStatusCn;
break;
case "障碍期权":
r.KnockInOutStatus = r.trade?.trade_barrier_option.KnockInOutStatusCn;
break;
case "气囊结构":
r.KnockInOutStatus = r.trade?.trade_airbag.KnockInOutStatusCn;
break;
case "累计期权":
r.Strike = r.trade?.Strike;
var settleMode = DbContext.autocall_observation.Where(n => n.TradeId == r.id && n.EndDate <= req.ValueDate)
.OrderByDescending(n => n.EndDate).Select(n => n.SettlementMode).FirstOrDefault();
r.KnockInOutStatus = settleMode == "敲出" ? "敲出" : "观察中";
break;
}
if (um != null)
{
r.GammaLots = (r.Gamma ?? 0) / um.ContractSize;
r.DeltaLots = (r.Delta ?? 0) / um.ContractSize;
}
r.Rho *= 100;
greeksHandleService.Handle(r,um);
r.CountRatio = um.CountRatio;
r.TradeOriginalAmount = r.OriginalNotional / um.CountRatio;
r.etcTradePrice = ConsTrade.TradeTypesForHedge.Contains(r.TradeType)
? r.TradePrice
: r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional);
if (r.id > 0)
{
if (r.trade != null)
{
r.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? r.RoundedPV : r.PV, r.Notional
, PS.Config.ErpElement.IsPVIncludePrincipal ? r.trade.PrincipalSum() : 0, r.trade.BuySell, r.trade.TradeType, false);
}
if (r.trade != null)
{
r.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(r.trade.ClientId)?.Number;
}
if (r.trade != null && r.trade.IsGroup == 1 && eodtradeDict.TryGetValue(r.ParentTradeId, out var et))
{
r.etcTradePrice = et.Select(x => (x.trade.BuySell == "买入" ? -1 : 1) * x.trade.TradePrice * x.trade.StockEqvNotional / r.trade.OriginalStockEqvNotional).Sum() ?? 0;
}
if (r.ParentTradeId > 0 && parentTradeIdDict.TryGetValue(r.ParentTradeId, out var legs))
{
r.ChildLeg = (legs.IndexOf(r.id) + 1).ToString();
}
}
else
{
r.SinglePV = r.PV.HasValue && r.Notional.HasValue && r.Notional.Value != 0
? Math.Abs(r.PV.Value / r.Notional.Value) : 0;
if (r.TradeType == "场内期权")
{
r.OptionType = DataCacheProvider.GetExchangeListOptionDataSource().GetData(r.ExchangeOptionCode).OptionType;
}
}
if (r.trade == null)
{
r.TradeSinglePrice = r.etcTradePrice / r.TradeAmount;
}
}
if (!isSwapTrades)
{
searchResult.Sum = new
{
dpnl = GetDPnL<T1, T3>(req, DbContext)
};
}
return searchResult;
}
//构建EodTradePositionBase对象查询预测
private Expression<Func<EodTradePosition, bool>> BuildPredicateOfEodTradePosition(EodPositionRisksReq reqModel, bool isSwapTrades = false)
{
var predicate = PredicateBuilder.Create<EodTradePosition>(t => t.ValueDate == reqModel.ValueDate && (reqModel.needSettleData || t.Amount != 0));
if (reqModel.UserAssets != null || reqModel.UserClients != null)
{
predicate = predicate.And(q => reqModel.UserAssets.Contains(q.BookId) || reqModel.UserClients.Contains(q.ClientId));
}
if (reqModel.ClientIds != null && reqModel.ClientIds.Any(x => x > 0))
{
predicate = predicate.And(q => reqModel.ClientIds.Contains(q.ClientId));
}
if (reqModel.BookIds != null && reqModel.BookIds.Any())
{
predicate = predicate.And(q => reqModel.BookIds.Contains(q.BookId));
}
if (reqModel.TradeIds != null && reqModel.TradeIds.Any(x => x != 0))
{
predicate = predicate.And(q => reqModel.TradeIds.Contains(q.TradeId) || reqModel.TradeIds.Contains(-q.id));
}
if (isSwapTrades)
{
predicate = predicate.And(q => q.TradeType == "收益互换");
}
else
{
predicate = predicate.And(q => q.TradeType != "收益互换");
}
reqModel.VarietyIds = reqModel.VarietyIds == null ? Enumerable.Empty<int>() : reqModel.VarietyIds.Where(n => n > 0).ToArray();
reqModel.UnderlyingIds = reqModel.UnderlyingIds == null ? Enumerable.Empty<int>() : reqModel.UnderlyingIds.Where(n => n > 0).ToArray();
reqModel.SettlementFlags = reqModel.SettlementFlags == null ? Enumerable.Empty<int>() : reqModel.SettlementFlags.ToArray();
return predicate;
}
#endregion
/// <summary>
/// 查询指定交易在eodTradeRisk相关表中的数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tradeNumbers"></param>
/// <param name="valueDate"></param>
/// <param name="tradeNumberDict">交易编号和交易Id的键值对</param>
/// <returns></returns>
public List<T> SearchEodRisk<T>(string[] tradeNumbers, DateTime valueDate, out Dictionary<int, string> tradeNumberDict) where T : EodTradeRisk
{
if (tradeNumbers == null || !tradeNumbers.Any(O => !string.IsNullOrWhiteSpace(O)))
{
throw new ServiceException($"“{nameof(tradeNumbers)}”不能为 null 或空白。");
}
var numbers = tradeNumbers.Where(O => !string.IsNullOrWhiteSpace(O));
tradeNumberDict =
DbContext.trade
.Where(O => numbers.Contains(O.TradeNumber) && O.ValidState != "InValid")
.Select(O => new { O.id, O.TradeNumber })
.ToDictionary(K => K.id, V => V.TradeNumber);
var tradeIds = tradeNumberDict.Keys;
return (from r in DbContext.Set<T>()
where r.ValueDate == valueDate && tradeIds.Contains(r.TradeId)
select r).ToList();
}
//每天盈亏dPnL = Theta + Old Vega + Psi + Old Delta + Old Gamma + New Gamma + New Delta + New Vega
public double GetDPnL<T1, T2>(EodPositionRisksReq req, YLContext db = null) where T1 : EodTradePosition where T2 : EodPnl
{
if (db == null)
{
db = DbContext;
}
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
var eodPredicate = BuildPredicateOfEodTradePosition(req, false);
var tradePredicate = PredicateBuilder.Create<trade>(t => t.ValidState != "InValid");
var exTradeTypes = ConsTrade.TradeTypesForHedge.AsEnumerable(); //场内交易类型
if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x)))
{
exTradeTypes = ConsTrade.TradeTypesForHedge.Intersect(req.TradeTypes).ToArray();
tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0));
}
if (!string.IsNullOrWhiteSpace(req.TradeNumber))
{
eodPredicate = eodPredicate.And(n => n.TradeId > 0);
tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber));
}
var query = from eodPos in db.Set<T1>().Where(eodPredicate)
join eodPnl in db.Set<T2>().Where(O => O.ValueDate == req.ValueDate && O.TradeId > 0) on eodPos.TradeId equals eodPnl.TradeId
join eodTrade in db.eod_trade.Where(O => O.ValueDate == req.ValueDate) on eodPos.TradeId equals eodTrade.TradeId into eodTrades
from eodTrade in eodTrades.DefaultIfEmpty()
join um in db.underlying_manager on eodPos.UnderlyingCode equals um.UnderlyingCode into um_t
from um in um_t.DefaultIfEmpty()
where (eodPos.TradeId == 0 || !statusList.Contains(eodTrade.TradeStatus))
&& (eodPos.TradeId > 0 || exTradeTypes.Contains(eodPos.TradeType))
&& (eodPos.TradeId < 1 || db.trade.Where(n => n.id == eodPos.TradeId).Where(tradePredicate).Any())
&& (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId))
&& (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id))
select new
{
eodPnl.PnLDelta,
eodPnl.PnLGamma,
eodPnl.PnLVega,
eodPnl.PnLTheta,
eodPnl.PnLPsi
};
var dpnl = query.Sum(n => (double?)(n.PnLDelta + n.PnLGamma + n.PnLVega + n.PnLTheta + n.PnLPsi));
return dpnl ?? 0;
}
/// <summary>
/// from tradecontroller.DownloadEodPositionRisks
/// </summary>
public byte[] ExportEodPositionRisksToExcel_Swap(EodPositionRisksReq req)
{
if (req.TradeIds == null || !req.TradeIds.Any())
{
req.page = 0;
req.rows = 10000;
}
req.IsOnlyExport = true;
req.TradeTypes = new List<string>() { "收益互换" };
var sList = SearchList(req, true).rows;
if (sList == null)
{
throw new ServiceException("没有可导出的数据");
}
var isPvRounded = PS.Config.IsPVRounded;
var results = new List<Dictionary<string, string>>(sList.Count());
var tradeids = sList.Select(O => O.id).ToHashSet();
var parentTradeIds = sList.Select(x => x.trade?.ParentTradeId).ToHashSet();
var tradeSwaps = DbContext.trade_swap.Where(x => tradeids.Contains(x.TradeId)).ToDictionary(n => n.TradeId);
var parentTrades = DbContext.trade.Where(x => parentTradeIds.Contains(x.id)).ToDictionary(n => n.id);
foreach (var item in sList)
{
if (item.trade == null)
{
continue;
}
if (item.trade != null && tradeSwaps.TryGetValue(item.trade.id, out var swap))
{
item.trade.trade_swap = swap;
}
if (parentTrades.TryGetValue(item.trade.ParentTradeId, out var parentTrade))
{
item.ContractCode = parentTrade.TradeNumber;
}
var dic = new Dictionary<string, string>();
if (string.IsNullOrWhiteSpace(item.UnderlyingCode))
{
item.DeltaLots = 0;
item.GammaLots = 0;
}
dic.Add("交易编号", item.ParentTradeNumber);
dic.Add("确认书编号", item.ContractCode);
dic.Add("交易对手方", item.ClientName);
dic.Add("交易对手编号", item.ClientNumber);
dic.Add("簿记账户", item.AssetBookName);
dic.Add("成交日期", item.TradeDate.OtcFormatDate());
dic.Add("到期日期", item.ExerciseDate.OtcFormatDate());
dic.Add("结算日期", item.SettlementDate.OtcFormatDate());
dic.Add("是否延期结算", item.SettlementFlag == 1 ? "是" : "否");
dic.Add("结构类型", item.StructureType.TrimToNull() ?? item.TradeType);
dic.Add("名义本金", item.StockEqvNotionalToShow.OtcFormat(OtcFormatFlag.StockEqvNotional));
var pv = Convert.ToDouble((isPvRounded ? item.RoundedPV : item.PV) ?? 0);
dic.Add("存续市值", pv.OtcFormatMoney());
dic.Add("标的代码", item.UnderlyingCode);
dic.Add("标的名称", item.UnderlyingAssetName);
dic.Add("期初标的价格", item.InitialSpotPrice.OtcFormatUmPrice());
dic.Add("浮动盈亏", (isPvRounded ? item.RoundedPositionPnl : item.PositionPnl).OtcFormatMoney());
dic.Add("实现盈亏", item.RealizedPnl.OtcFormatMoney());
dic.Add("Delta", item.Delta.OtcFormat(OtcFormatFlag.greek));
dic.Add("Delta手数", OtcFormatExtensions.OtcFormat(item.DeltaLots, OtcFormatFlag.notional));
dic.Add("收取浮动收益", item.trade.trade_swap.IsGetFloatingProfit ? "是" : "否");
dic.Add("收取标的代码", item.trade.trade_swap.GetUnderlyingCode);
dic.Add("收取标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.GetUnderlyingCode)?.UnderlyingName);
dic.Add("收取多头空头", item.trade.trade_swap.GetLongShort);
dic.Add("收取标的期初价格", item.trade.trade_swap.GetSpotPrice.OtcFormatUmPrice());
dic.Add("收取交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.GetTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.GetTradeAmount, OtcFormatFlag.notional));
dic.Add("收取交易费用", item.trade.trade_swap.GetTradePrice.OtcFormatMoney());
dic.Add("收取初始预付金率", item.trade.trade_swap.GetMarginRate.OtcFormatFlex(2, 2, percent: true));
var getCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.GetSwapTimeAndRate);
var getSwapRates = getCustomizedResults.Item2;
double? GetSwapRate = getSwapRates?.FirstOrDefault();
dic.Add("收取互换利率年化", GetSwapRate.OtcFormatPercent(4));
dic.Add("支付浮动收益", item.trade.trade_swap.IsPayFloatingProfit ? "是" : "否");
dic.Add("支付标的代码", item.trade.trade_swap.PayUnderlyingCode);
dic.Add("支付标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.PayUnderlyingCode)?.UnderlyingName);
dic.Add("支付多头空头", item.trade.trade_swap.PayLongShort);
dic.Add("支付标的期初价格", item.trade.trade_swap.PaySpotPrice.OtcFormatUmPrice());
dic.Add("支付交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.PayTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.PayTradeAmount, OtcFormatFlag.notional));
dic.Add("支付交易费用", item.trade.trade_swap.PayTradePrice.OtcFormatMoney());
dic.Add("支付初始预付金率", item.trade.trade_swap.PayMarginRate.OtcFormatFlex(2, 2, percent: true));
var payCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.PaySwapTimeAndRate);
var paySwapRates = payCustomizedResults.Item2;
double? PaySwapRate = paySwapRates?.FirstOrDefault();
dic.Add("支付互换利率年化", PaySwapRate.OtcFormatPercent(4));
results.Add(dic);
}
var list2 = results.Select(n => new ExpandoDictionary<string, string>(n)).ToArray();
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/日终持仓风险_互换.xlsx");
return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = list2 }).GenerateBytes();
}
public bool BatchDownloadEodPositionRisks_Swap(EodPositionRisksReq req)
{
req.IsOnlyExport = true;
req.TradeTypes = new List<string>() { "收益互换" };
//获取区间日期起始日期和结束日期(不包含结束日期所以日期加一)
var dates = QdpCalendarHelper.AllBizDays(req.StartDate, req.ValueDate.AddDays(1));
//for循环根据日期期间生产多个表格
DateTime endetime = req.ValueDate;
//路径名称和文档名
var minDate = dates.Min();
var maxDate = dates.Max();
var fileName = $"日终互换_{minDate:yyyy-MM-dd}-{maxDate:yyyy-MM-dd}.xlsx";
var extendParams = new DataSet(fileName);
//定义容器集合实例化
List<EodPositionRisksReq> reqList = dates.Select(O =>
{
var temp_req = req.Clone();
temp_req.ValueDate = O;
return temp_req;
}).ToList();
return ProgressHelper<EodPositionRisksReq>.Start(reqList, "ExportEodPositionRisksSwap", ExportEodPositionRisksToExcel_SwapTwo, GenerateFile, extendParams);
}
/// <summary>
/// 互换日期区间导出
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public string ExportEodPositionRisksToExcel_SwapTwo(EodPositionRisksReq req, object extends, ProgressInfo<EodPositionRisksReq> info)
{
info.ignoreIndex = false;
if (!(extends is DataSet excelFile))
{
return "参数错误";
}
if (barTask == null)
{
barTask = Task.Run(() =>
{
//var temp_req = req.Clone();
//temp_req.ValueDate = date;
Debug.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff => ") + req.ValueDate.ToString("yyyy-MM-dd"));
//获取所有的数据
var results = GetEodPositionRisksDataHandleS(req, true);
//判断区间日期内是否存在数据
if (results == null || results.Count == 0)
{
return $"{req.ValueDate.ToString("yyyy-MM-dd")} 数据不存在,跳过";
}
//结束日期为sheet命名
DataTable dt = new DataTable(req.ValueDate.ToString("yyyyMMdd"));
dt.Columns.AddRange(results.First().Keys.Select(O => new DataColumn(O)).ToArray());
//循环所有数据的每个单元格数据到表格里面
for (int i = 0; i < results.Count; i++)
{
DataRow row = dt.NewRow();
foreach (var cell in results[i])
{
row[cell.Key] = cell.Value;
}
dt.Rows.Add(row);
}
excelFile.Tables.Add(dt);
return $"{req.ValueDate.ToString("yyyy-MM-dd")} 导出完成";
});
info.ignoreIndex = true;
return $"正在导出 {req.ValueDate.ToString("yyyy-MM-dd")}";
}
else
{
Task.WaitAll(barTask);
var message = barTask.Result;
barTask = null;
return message;
}
}
public List<Dictionary<string, string>> GetEodPositionRisksDataHandleS(EodPositionRisksReq req, bool isUseemptydate = false)
{
if (req.TradeIds == null || !req.TradeIds.Any())
{
req.page = 0;
req.rows = 10000;
}
req.IsOnlyExport = true;
req.TradeTypes = new List<string>() { "收益互换" };
IEnumerable<EodPositionRisksDTO> sList = null;
sList = SearchList(req, true).rows;
if (sList == null)
{
throw new ServiceException("没有可导出的数据");
}
var isPvRounded = PS.Config.IsPVRounded;
var results = new List<Dictionary<string, string>>(sList.Count());
var tradeids = sList.Select(O => O.id).ToHashSet();
var parentTradeIds = sList.Select(x => x.trade?.ParentTradeId).ToHashSet();
Dictionary<int, trade_swap> tradeSwaps = null;
Dictionary<int, trade> parentTrades = null;
using (var db = DbContextFactory.GetYLDbContext())
{
tradeSwaps = db.trade_swap.Where(x => tradeids.Contains(x.TradeId)).ToDictionary(n => n.TradeId);
parentTrades = db.trade.Where(x => parentTradeIds.Contains(x.id)).ToDictionary(n => n.id);
}
foreach (var item in sList)
{
if (item.trade == null)
{
continue;
}
if (item.trade != null && tradeSwaps != null && tradeSwaps.TryGetValue(item.trade.id, out var swap))
{
item.trade.trade_swap = swap;
}
if (parentTrades != null && parentTrades.TryGetValue(item.trade.ParentTradeId, out var parentTrade))
{
item.ContractCode = parentTrade.TradeNumber;
}
var dic = new Dictionary<string, string>();
if (string.IsNullOrWhiteSpace(item.UnderlyingCode))
{
item.DeltaLots = 0;
item.GammaLots = 0;
}
dic.Add("交易编号", item.ParentTradeNumber);
dic.Add("确认书编号", item.ContractCode);
dic.Add("交易对手方", item.ClientName);
dic.Add("交易对手编号", item.ClientNumber);
dic.Add("簿记账户", item.AssetBookName);
dic.Add("成交日期", item.TradeDate.OtcFormatDate());
dic.Add("到期日期", item.ExerciseDate.OtcFormatDate());
dic.Add("结算日期", item.SettlementDate.OtcFormatDate());
dic.Add("是否延期结算", item.SettlementFlag == 1 ? "是" : "否");
dic.Add("结构类型", item.StructureType.TrimToNull() ?? item.TradeType);
dic.Add("名义本金", item.StockEqvNotionalToShow.OtcFormat(OtcFormatFlag.StockEqvNotional));
var pv = Convert.ToDouble((isPvRounded ? item.RoundedPV : item.PV) ?? 0);
dic.Add("存续市值", pv.OtcFormatMoney());
dic.Add("标的代码", item.UnderlyingCode);
dic.Add("标的名称", item.UnderlyingAssetName);
dic.Add("期初标的价格", item.InitialSpotPrice.OtcFormatUmPrice());
dic.Add("浮动盈亏", (isPvRounded ? item.RoundedPositionPnl : item.PositionPnl).OtcFormatMoney());
dic.Add("实现盈亏", item.RealizedPnl.OtcFormatMoney());
dic.Add("Delta", item.Delta.OtcFormat(OtcFormatFlag.greek));
dic.Add("Delta手数", OtcFormatExtensions.OtcFormat(item.DeltaLots, OtcFormatFlag.notional));
dic.Add("收取浮动收益", item.trade.trade_swap.IsGetFloatingProfit ? "是" : "否");
dic.Add("收取标的代码", item.trade.trade_swap.GetUnderlyingCode);
dic.Add("收取标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.GetUnderlyingCode)?.UnderlyingName);
dic.Add("收取多头空头", item.trade.trade_swap.GetLongShort);
dic.Add("收取标的期初价格", item.trade.trade_swap.GetSpotPrice.OtcFormatUmPrice());
dic.Add("收取交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.GetTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.GetTradeAmount, OtcFormatFlag.notional));
dic.Add("收取交易费用", item.trade.trade_swap.GetTradePrice.OtcFormatMoney());
dic.Add("收取初始预付金率", item.trade.trade_swap.GetMarginRate.OtcFormatFlex(2, 2, percent: true));
var getCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.GetSwapTimeAndRate);
var getSwapRates = getCustomizedResults.Item2;
double? GetSwapRate = getSwapRates?.FirstOrDefault();
dic.Add("收取互换利率年化", GetSwapRate.OtcFormatPercent(4));
dic.Add("支付浮动收益", item.trade.trade_swap.IsPayFloatingProfit ? "是" : "否");
dic.Add("支付标的代码", item.trade.trade_swap.PayUnderlyingCode);
dic.Add("支付标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.PayUnderlyingCode)?.UnderlyingName);
dic.Add("支付多头空头", item.trade.trade_swap.PayLongShort);
dic.Add("支付标的期初价格", item.trade.trade_swap.PaySpotPrice.OtcFormatUmPrice());
dic.Add("支付交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.PayTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.PayTradeAmount, OtcFormatFlag.notional));
dic.Add("支付交易费用", item.trade.trade_swap.PayTradePrice.OtcFormatMoney());
dic.Add("支付初始预付金率", item.trade.trade_swap.PayMarginRate.OtcFormatFlex(2, 2, percent: true));
var payCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.PaySwapTimeAndRate);
var paySwapRates = payCustomizedResults.Item2;
double? PaySwapRate = paySwapRates?.FirstOrDefault();
dic.Add("支付互换利率年化", PaySwapRate.OtcFormatPercent(4));
results.Add(dic);
}
if (results.Count == 0 && (isUseemptydate = true))
{
var dic = new Dictionary<string, string>();
dic.Add("交易编号", "");
dic.Add("确认书编号", "");
dic.Add("交易对手方", "");
dic.Add("交易对手编号", "");
dic.Add("簿记账户", "");
dic.Add("成交日期", "");
dic.Add("到期日期", "");
dic.Add("结算日期", "");
dic.Add("是否延期结算", "");
dic.Add("结构类型", "");
dic.Add("名义本金", "");
dic.Add("存续市值", "");
dic.Add("标的代码", "");
dic.Add("标的名称", "");
dic.Add("期初标的价格", "");
dic.Add("浮动盈亏", "");
dic.Add("实现盈亏", "");
dic.Add("Delta", "");
dic.Add("Delta手数", "");
dic.Add("收取浮动收益", "");
dic.Add("收取标的代码", "");
dic.Add("收取标的名称", "");
dic.Add("收取多头空头", "");
dic.Add("收取标的期初价格", "");
dic.Add("收取交易数量", "");
dic.Add("收取交易费用", "");
dic.Add("收取初始预付金率", "");
dic.Add("收取互换利率年化", "");
dic.Add("支付浮动收益", "");
dic.Add("支付标的代码", "");
dic.Add("支付标的名称", "");
dic.Add("支付多头空头", "");
dic.Add("支付标的期初价格", "");
dic.Add("支付交易数量", "");
dic.Add("支付交易费用", "");
dic.Add("支付初始预付金率", "");
dic.Add("支付互换利率年化", "");
results.Add(dic);
}
return results;
}
/// <summary>
/// from tradecontroller.DownloadEodPositionRisks
/// </summary>
public byte[] ExportEodPositionRisksToExcel(EodPositionRisksReq req)
{
var results = GetEodPositionRisksDataHandle(req);
var list2 = results.Select(n => new ExpandoDictionary<string, string>(n)).ToArray();
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/日终持仓风险_国联.xlsx");
if (PS.Config.ErpElement.NeedShowSpv)
{
templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/日终持仓风险-Spv_国联.xlsx");
}
return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = list2 }).GenerateBytes();
}
#region 日终持仓风险-期权区间
public bool BatchDownloadEodPositionRisks(EodPositionRisksReq req)
{
//获取区间日期起始日期和结束日期(不包含结束日期所以日期加一)
var dates = QdpCalendarHelper.AllBizDays(req.StartDate, req.ValueDate.AddDays(1));
//for循环根据日期期间生产多个表格
DateTime endetime = req.ValueDate;
//路径名称和文档名
var minDate = dates.Min();
var maxDate = dates.Max();
var fileName = $"日终_{minDate:yyyy-MM-dd}-{maxDate:yyyy-MM-dd}.xlsx";
var extendParams = new DataSet(fileName);
//定义容器集合实例化
List<EodPositionRisksReq> reqList = dates.Select(O =>
{
var temp_req = req.Clone();
temp_req.ValueDate = O;
return temp_req;
}).ToList();
return ProgressHelper<EodPositionRisksReq>.Start(reqList, "ExportEodPositionRisks", ExportEodPositionRisksToExcelTo, GenerateFile, extendParams);
}
private object GenerateFile(object extends)
{
if (!(extends is DataSet excelFile))
{
return "参数错误";
}
//用户路径
string path = "/App_Docs/Temp/";
path = OtcAppContext.MapPath(path);
//判断路径是否为空
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
var filePath = Path.Combine(path, excelFile.DataSetName);
new ExcelHelper().DataSetToExcel(excelFile, true, out var tempBuffer);
File.WriteAllBytes(filePath, tempBuffer);
return Path.Combine("/App_Docs/Temp/", excelFile.DataSetName);
}
private Task<string> barTask = null;
/// <summary>
/// 日期区间导出
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
private string ExportEodPositionRisksToExcelTo(EodPositionRisksReq req, object extends, ProgressInfo<EodPositionRisksReq> info)
{
info.ignoreIndex = false;
if (!(extends is DataSet excelFile))
{
return "参数错误";
}
if (barTask == null)
{
barTask = Task.Run(() =>
{
//var temp_req = req.Clone();
//temp_req.ValueDate = date;
Debug.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff => ") + req.ValueDate.ToString("yyyy-MM-dd"));
//获取所有的数据
var results = GetEodPositionRisksDataHandle(req, true);
//判断区间日期内是否存在数据
if (results == null || results.Count == 0)
{
return $"{req.ValueDate.ToString("yyyy-MM-dd")} 数据不存在,跳过";
}
//结束日期为sheet命名
DataTable dt = new DataTable(req.ValueDate.ToString("yyyyMMdd"));
dt.Columns.AddRange(results.First().Keys.Select(O => new DataColumn(O == "TraderName" ? "交易员" : O)).ToArray());
//循环所有数据的每个单元格数据到表格里面
for (int i = 0; i < results.Count; i++)
{
DataRow row = dt.NewRow();
foreach (var cell in results[i])
{
//如果为tradenumber的时候该为交易员
if (cell.Key == "TraderName")
{
row["交易员"] = cell.Value;
}
else
{
row[cell.Key] = cell.Value;
}
}
dt.Rows.Add(row);
}
excelFile.Tables.Add(dt);
return $"{req.ValueDate.ToString("yyyy-MM-dd")} 导出完成";
});
info.ignoreIndex = true;
return $"正在导出 {req.ValueDate.ToString("yyyy-MM-dd")}";
}
else
{
Task.WaitAll(barTask);
var message = barTask.Result;
barTask = null;
return message;
}
}
public List<Dictionary<string, string>> GetEodPositionRisksDataHandle(EodPositionRisksReq req, bool isUseemptydate = false)
{
if (req.TradeIds == null || !req.TradeIds.Any())
{
req.page = 0;
req.rows = 10000;
}
req.IsOnlyExport = true;
IEnumerable<EodPositionRisksDTO> sList = null;
sList = SearchList(req).rows;
if (sList == null)
{
throw new ServiceException("没有可导出的数据");
}
var isPvRounded = PS.Config.IsPVRounded;
var results = new List<Dictionary<string, string>>(sList.Count());
foreach (var item in sList)
{
var dic = new Dictionary<string, string>();
if (string.IsNullOrWhiteSpace(item.UnderlyingCode))
{
item.DeltaLots = 0;
item.GammaLots = 0;
}
dic.Add("交易编号", item.TradeNumber);
dic.Add("分组名", item.GroupName);
dic.Add("确认书编号", item.ContractCode);
dic.Add("期权代码", item.ExchangeOptionCode);
dic.Add("多腿编号", item.ChildLeg);
dic.Add("浮动盈亏", (isPvRounded ? item.RoundedPositionPnl : item.PositionPnl).OtcFormatMoney());
dic.Add("实现盈亏", item.RealizedPnl.OtcFormatMoney());
dic.Add("TraderName", item.TraderName);
dic.Add("当前波动率", item.CurrentVolatility.OtcFormat(OtcFormatFlag.premiumRateP));
dic.Add("Delta", OtcFormatExtensions.OtcFormat(item.Delta, OtcFormatFlag.greek));
dic.Add("Delta手数", OtcFormatExtensions.OtcFormat(item.DeltaLots, OtcFormatFlag.notional));
dic.Add("Gamma", OtcFormatExtensions.OtcFormat(item.Gamma, OtcFormatFlag.greek));
dic.Add("Gamma手数", OtcFormatExtensions.OtcFormat(item.GammaLots, OtcFormatFlag.notional));
dic.Add("Theta", OtcFormatExtensions.OtcFormat(item.Theta, OtcFormatFlag.greek));
dic.Add("Rho", OtcFormatExtensions.OtcFormat(item.Rho, OtcFormatFlag.greek));
dic.Add("Vega", OtcFormatExtensions.OtcFormat(item.Vega, OtcFormatFlag.greek));
dic.Add("到期日期", item.ExerciseDate.OtcFormatDate());
dic.Add("行权方式", TradeHelper.GetExerciseModeCn(item.ExerciseMode));
dic.Add("结构类型", item.StructureType.TrimToNull() ?? item.TradeType);
dic.Add("观察状态", item.KnockInOutStatus);
dic.Add("交易对手方", item.ClientName);
dic.Add("交易对手编号", item.ClientNumber);
dic.Add("簿记账户", item.AssetBookName);
dic.Add("成交日期", item.TradeDate.OtcFormatDate());
dic.Add("看涨看跌", item.OptionType);
dic.Add("买卖方向", item.BuySell);
dic.Add("标的代码", item.UnderlyingCode);
dic.Add("标的品种", item.UnderlyingVariety);
dic.Add("标的名称", item.UnderlyingAssetName);
dic.Add("期初标的价格", item.InitialSpotPrice.OtcFormatUmPrice());
dic.Add("保底收益总额", item.OriginalPrincipalSum.OtcFormatUmPrice());
if (item.TradeType == "自定义交易")
{
dic.Add("执行价格", string.Empty);
}
else
{
dic.Add("执行价格", item.Strike.OtcFormatUmPrice(item.IsMoneynessOption == "是"));
}
if (item.IsUsePremiumRate == true)
{
dic.Add("权利金成交", item.PremiumRate.OtcFormat(OtcFormatFlag.premiumRateP));
}
else
{
dic.Add("权利金成交", (item.TradeSinglePrice ?? 0).OtcFormat(OtcFormatFlag.tradeSinglePrice));
}
var tradeOriginalAmount = PS.Config.IsUseDisplayNotional ? Math.Abs((item.TradeOriginalAmount ?? 0) * (item.CountRatio ?? 1)) : Math.Abs(item.TradeOriginalAmount ?? 0);
var strTradeOriginalAmount = tradeOriginalAmount.OtcFormatNotional();
dic.Add("有效成交数量", strTradeOriginalAmount);
if (item.trade != null)
{
strTradeOriginalAmount = Math.Abs(CalculationModule.TradeCalcHelper.GetTradeAmountV(item.trade, tradeOriginalAmount, 1)).OtcFormatNotional();
}
dic.Add("成交数量", strTradeOriginalAmount);
var tradeDirection = item.BuySell == "买入" || item.BuySell == "多头开仓" || item.BuySell == "空头开仓" ? -1 : 1;
dic.Add("成交金额", (item.TradePrice * tradeDirection).OtcFormatMoney());
dic.Add("存续成本", (item.IsGroup == 1 ? item.etcTradePrice : item.etcTradePrice * tradeDirection).OtcFormatMoney());
dic.Add("名义本金", item.StockEqvNotionalToShow.OtcFormat(OtcFormatFlag.StockEqvNotional));
dic.Add("存续名义本金", item.SurvivingNominalPrincipal.OtcFormat(OtcFormatFlag.StockEqvNotional));
dic.Add("最新标的价格", item.UnderlyingPrice.OtcFormatUmPrice());
dic.Add("无风险利率", item.RiskFreeRate.OtcFormatFlex(2, 2, percent: true));
dic.Add("分红率", item.DividendRate.OtcFormatFlex(2, 2, percent: true));
if (item.IsUsePremiumRate == true)
{
var dd = TradeHelper.GetPremiumRateByTradeSinglePrice(item.SinglePV, item.InitialSpotPrice);
dic.Add("权利金存续", dd.OtcFormat(OtcFormatFlag.premiumRateP));
}
else
{
dic.Add("权利金存续", item.SinglePV.HasValue ? Convert.ToDouble(item.SinglePV.Value).OtcFormat(OtcFormatFlag.tradePrice) : "");
}
var tradeAmount = PS.Config.IsUseDisplayNotional ? Math.Abs((item.TradeAmount * (item.CountRatio ?? 1)) ?? 0) : Math.Abs(item.TradeAmount ?? 0);
var strTradeAmount = tradeAmount.OtcFormatNotional();
dic.Add("有效存续数量", strTradeAmount);
if (item.trade != null)
{
strTradeAmount = Math.Abs(CalculationModule.TradeCalcHelper.GetTradeAmountV(item.trade, tradeAmount, 1)).OtcFormatNotional();
}
dic.Add("存续数量", strTradeAmount);
var pv = Convert.ToDouble((isPvRounded ? item.RoundedPV : item.PV) ?? 0);
dic.Add("存续市值", pv.OtcFormatMoney());
dic.Add("维持预付金", item.Margin.OtcFormatMoney());
dic.Add("信用风险敞口", item.Exposure.OtcFormatMoney());
if (PS.Config.IsGuoJun)
{
dic.Add("持仓初始预付金", (item.PosiInitMargin ?? 0).OtcFormatMoney());
}
#region 奇异期权导出列(二元/亚式/单障碍/Risky)
//二元
dic.Add("二元类型", item.PayoffType);
if (item.IsUsePremiumRate == true)
{
dic.Add("二元_补偿金额", item.CashOrNothingAmountRate.OtcFormat(OtcFormatFlag.premiumRateP));
}
else
{
dic.Add("二元_补偿金额", item.CashOrNothingAmount.OtcFormat(OtcFormatFlag.tradeSinglePrice));
}
dic.Add("是否离散观察", item.IsDiscreteMonitored);
dic.Add("补偿方式", TradeHelper.GetRebateTypeCn(item.RebateType ?? item.RebateType3));
var IsMoneynessOption = item.IsMoneynessOption == "是";
//亚式
dic.Add("执行价类型", TradeHelper.GetAsianStrikeTypeCn(item.StrikeType));
dic.Add("均价起算日", item.AveragingPeriodStartDate.OtcFormatDate());
dic.Add("均价起算方式", TradeHelper.GetAsianPayoffTypeCn(item.PayoffType2));
dic.Add("参与率", item.ParticipationRate.OtcFormatPercent());
dic.Add("杠杆率", item.StrikeGearingFactor.OtcFormatPercent());
if (item.TradeType == "亚式期权" && item.PayoffType2 == "EnhancedArithmeticAverage" && item.StrikeType != "Floating")
{
dic.Add("增强价格", item.EnhancedPrice.OtcFormatUmPrice(IsMoneynessOption));
}
else
{
dic.Add("增强价格", "");
}
//障碍
dic.Add("障碍类型", item.BarrierType);
dic.Add("观察类型", item.Discrete);
dic.Add("障碍价格", item.BarrierPrice.OtcFormatUmPrice(IsMoneynessOption));
dic.Add("高障碍价格", item.UpperBarrierPrice.OtcFormatUmPrice(IsMoneynessOption));
if (item.IsUsePremiumRate == true)
{
dic.Add("补偿金额", item.RebateRate.OtcFormat(OtcFormatFlag.premiumRateP));
}
else
{
dic.Add("补偿金额", item.Rebate.OtcFormat(OtcFormatFlag.tradeSinglePrice));
}
dic.Add("障碍偏移", item.BarrierShift?.ToString("F2"));
dic.Add("补偿支付", TradeHelper.GetRebateTypeCn(item.RebateType ?? item.RebateType3));
//Risky
dic.Add("参与率2", item.ParticipationRate2.OtcFormatPercent());
dic.Add("参与率3", item.ParticipationRate3.OtcFormatPercent());
//Risky、累计三段式
dic.Add("执行价格2", item.Strike2.OtcFormatUmPrice(item.IsMoneynessOption == "是"));
dic.Add("执行价格3", item.Strike3.OtcFormatUmPrice(item.IsMoneynessOption == "是"));
#endregion
dic.Add("dPnLDelta", item.PnLDelta.OtcFormat(OtcFormatFlag.greek));
dic.Add("dPnLGamma", item.PnLGamma.OtcFormat(OtcFormatFlag.greek));
dic.Add("dPnLVega", item.PnLVega.OtcFormat(OtcFormatFlag.greek));
dic.Add("dPnLTheta", item.PnLTheta.OtcFormat(OtcFormatFlag.greek));
dic.Add("dPnLPsi", item.PnLPsi.OtcFormat(OtcFormatFlag.greek));
if (PS.Config.ErpElement.NeedShowSpv)
{
dic.Add("Spv1", item.PnLDelta.OtcFormat(OtcFormatFlag.greek));
dic.Add("Spv2", item.PnLDelta.OtcFormat(OtcFormatFlag.greek));
dic.Add("Spv3", item.PnLDelta.OtcFormat(OtcFormatFlag.greek));
}
if (PS.Config.Company == Configuration.CompanyEnum.国联)
{
dic.Add("Delta_r", OtcFormatExtensions.OtcFormat(item.Delta_r, OtcFormatFlag.greek));
dic.Add("Delta_r_1bp", OtcFormatExtensions.OtcFormat(item.Delta_r_1bp, OtcFormatFlag.greek));
dic.Add("Dv01", OtcFormatExtensions.OtcFormat(item.Dv01, OtcFormatFlag.greek));
dic.Add("Gamma_r", OtcFormatExtensions.OtcFormat(item.Gamma_r, OtcFormatFlag.greek));
dic.Add("Gamma_r_1bp", OtcFormatExtensions.OtcFormat(item.Gamma_r_1bp, OtcFormatFlag.greek));
dic.Add("Vega_r", OtcFormatExtensions.OtcFormat(item.Vega_r, OtcFormatFlag.greek));
dic.Add("Vega_r_1bp", OtcFormatExtensions.OtcFormat(item.Vega_r_1bp, OtcFormatFlag.greek));
}
dic.Add("备注", item.Comments);
results.Add(dic);
}
if (isUseemptydate && results.Count == 0)
{
var dic = new Dictionary<string, string>();
dic.Add("交易编号", "");
dic.Add("分组名", "");
dic.Add("确认书编号", "");
dic.Add("期权代码", "");
dic.Add("多腿编号", "");
dic.Add("浮动盈亏", "");
dic.Add("实现盈亏", "");
dic.Add("TraderName", "");
dic.Add("当前波动率", "");
dic.Add("Delta", "");
dic.Add("Delta手数", "");
dic.Add("Gamma", "");
dic.Add("Gamma手数", "");
dic.Add("Theta", "");
dic.Add("Rho", "");
dic.Add("Vega", "");
dic.Add("到期日期", "");
dic.Add("行权方式", "");
dic.Add("结构类型", "");
dic.Add("观察状态", "");
dic.Add("交易对手方", "");
dic.Add("交易对手编号", "");
dic.Add("簿记账户", "");
dic.Add("成交日期", "");
dic.Add("看涨看跌", "");
dic.Add("买卖方向", "");
dic.Add("标的代码", "");
dic.Add("标的品种", "");
dic.Add("标的名称", "");
dic.Add("期初标的价格", "");
dic.Add("保底收益总额", "");
dic.Add("执行价格", "");
dic.Add("权利金成交", "");
dic.Add("有效成交数量", "");
dic.Add("成交数量", "");
dic.Add("成交金额", "");
dic.Add("存续成本", "");
dic.Add("名义本金", "");
dic.Add("最新标的价格", "");
dic.Add("无风险利率", "");
dic.Add("分红率", "");
dic.Add("权利金存续", "");
dic.Add("有效存续数量", "");
dic.Add("存续数量", "");
dic.Add("存续市值", "");
dic.Add("维持预付金", "");
dic.Add("信用风险敞口", "");
if (PS.Config.IsGuoJun)
{
dic.Add("持仓初始预付金", "");
}
#region 奇异期权导出列(二元/亚式/单障碍)
//二元
dic.Add("二元类型", "");
dic.Add("二元_补偿金额", "");
dic.Add("是否离散观察", "");
dic.Add("补偿方式", "");
//亚式
dic.Add("执行价类型", "");
dic.Add("均价起算日", "");
dic.Add("均价起算方式", "");
dic.Add("参与率", "");
dic.Add("杠杆率", "");
//障碍
dic.Add("障碍类型", "");
dic.Add("观察类型", "");
dic.Add("障碍价格", "");
dic.Add("高障碍价格", "");
dic.Add("补偿金额", "");
dic.Add("障碍偏移", "");
dic.Add("补偿支付", "");
//累计
dic.Add("执行价格2", "");
dic.Add("执行价格3", "");
#endregion
dic.Add("dPnLDelta", "");
dic.Add("dPnLGamma", "");
dic.Add("dPnLVega", "");
dic.Add("dPnLTheta", "");
dic.Add("dPnLPsi", "");
if (PS.Config.ErpElement.NeedShowSpv)
{
dic.Add("Spv1", "");
dic.Add("Spv2", "");
dic.Add("Spv3", "");
}
if (PS.Config.Company == Configuration.CompanyEnum.国联)
{
dic.Add("Delta_r", "");
dic.Add("Delta_r_1bp", "");
dic.Add("Dv01", "");
dic.Add("Gamma_r", "");
dic.Add("Gamma_r_1bp", "");
dic.Add("Vega_r", "");
dic.Add("Vega_r_1bp", "");
}
results.Add(dic);
}
return results;
}
#endregion
public byte[] ExportEodRiskReport(EodPositionRisksReq req, double todayHedgeCashInOut)
{
try
{
#region 准备数据
var sList = SearchList(req).rows;
if (sList == null)
{
throw new ServiceException("没有可导出的数据");
}
var tradeParentIds = sList.Where(o => o.ParentTradeId > 0).Select(o => o.ParentTradeId).Distinct().ToList();
var count = sList.Where(o => o.ParentTradeId == 0 && !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Count() + tradeParentIds.Count();
var results = new List<Dictionary<string, object>>(sList.Count());
var tradeIds = sList.Select(o => o.id);
var beforeDate = QdpCalendarHelper.GetNonHolidayDefore(req.ValueDate.AddDays(-1));
var riskQuery = DbContext.eod_trade_risk_hedgevol.Where(o => tradeIds.Contains(o.TradeId) && o.ValueDate == beforeDate);
var riskQueryDic = riskQuery.ToDictionary(o => o.TradeId, o => OtcFormatExtensions.OtcFormatValue(o.Delta, 2));
var dayUnwindTradeQuery = DbContext.trade_cash.Where(o => (o.Action == "系统操作-平仓费" || o.Action == "系统操作-行权费" || (o.Action == "系统操作-票息" && o.IsLastAction == true))
&& o.ValueDate == req.ValueDate && o.ValidState != "InVaild" && !o.IsDeleted);
var groups = dayUnwindTradeQuery.AsEnumerable().GroupBy(o => o.TradeId).ToList();
var dayUnwindPercentDic = groups.ToDictionary(o => o.Key, o => o.Sum(x => x.UnwindPercentRate));
var priceDict = new EodPriceProvider(beforeDate, true);
//var totalPnl = sList.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Sum(o => o.dailyPnl);
//var totalProfit = sList.Sum(o => (riskQueryDic.ContainsKey(o.id) ? (double)riskQueryDic[o.id] : 0) * (o.UnderlyingPrice - priceDict.GetPrice(o.UnderlyingCode)));
double dayUnwindValue = 0;
req.VolType = "对冲";
var sList2 = SearchList(req).rows;
//var totalPnl2 = 0.0;
var startPv = 0.0;
var PVSum = 0.0;
var dailyPnlSum = 0.0;
var profitSum = 0.0;
var calcProfitSum = 0.0;
var DeltaRateSum = 0.0;
var DeltaSum = 0.0;
var GammaSum = 0.0;
var VegaSum = 0.0;
var DeltaCashSum = 0.0;
var GammaCashSum = 0.0;
var VegaCashSum = 0.0;
var StockEqvNotionalToShowSum = 0.0;
var TradePriceSum = 0.0;
var i = 1;
var tcActions = new[] { ClientCashInCashOut.系统操作_平仓费,
ClientCashInCashOut.系统操作_行权费,ClientCashInCashOut.系统操作_票息,ClientCashInCashOut.系统操作_互换,ClientCashInCashOut.人工操作_其他};
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
var beforeEodMeta = DbContext.EodMeta.FirstOrDefault(o => o.ValueDate == beforeDate && o.MetaKey == EodMeta.UFX_FundSummary);
var todayEodMeta = DbContext.EodMeta.FirstOrDefault(o => o.ValueDate == req.ValueDate && o.MetaKey == EodMeta.UFX_FundSummary);
var beforeMeta = new UFX_FundSummary();
var todayMeta = new UFX_FundSummary();
if (beforeEodMeta != null)
{
beforeMeta = JsonHelper.Deserialize<UFX_FundSummary>(beforeEodMeta.MetaValue);
}
if (todayEodMeta != null)
{
todayMeta = JsonHelper.Deserialize<UFX_FundSummary>(todayEodMeta.MetaValue);
}
var HedgeMarkingCash = todayMeta.HedgeMarkingCash;
var beforeHedgeMarkingCash = beforeMeta.HedgeMarkingCash;
var todayHedgeMarkingPro = HedgeMarkingCash - beforeHedgeMarkingCash - todayHedgeCashInOut;
todayHedgeMarkingPro = OtcFormatExtensions.OtcFormatValue(todayHedgeMarkingPro, 2);
var todayPositionQuery = DbContext.eod_trade_position.Where(o => o.ValueDate == req.ValueDate && o.TradeType != "收益互换").ToList();
var todayHedgeClosePnlSum = todayPositionQuery.Any() ? todayPositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.ClosedPnL).Sum() : 0;
//var todayHedgePositionPnlSum = todayPositionQuery.Any() ? todayPositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.PositionPnL).Sum() : 0;
//var todayDailyPnlSum = todayPositionQuery.Any() ? todayPositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.DailyPnL).Sum() : 0;
var todayPV = todayPositionQuery.Any() ? todayPositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.Pv).Sum() : 0;
var ids = todayPositionQuery.Select(x => x.TradeId);
var todayTrades = DbContext.eod_trade.Where(o => o.ValueDate == req.ValueDate && ids.Contains(o.TradeId)).ToList().Select(o => o.trade);
var NotSettledIds = todayTrades.Where(o => !statusList.Contains(o.TradeStatus) && o.IsGroup != 2).Select(o => o.id);
//var totalProfit2 = sList2.Sum(
// o => OtcFormatExtensions.OtcFormatValue(
// (riskQueryDic.ContainsKey(o.id) && NotSettledIds.Contains(o.id) ? (double)riskQueryDic[o.id] : 0)
// * (o.UnderlyingPrice - priceDict.GetPrice(o.UnderlyingCode, SettlementTypeEnum.ClosePrice))
// , 2));
var todayPositonPnl = todayPositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Sum(o => o.PositionPnL);
var todayRealizedPnl = 0.0;
var todayCashAmount = 0.0;
foreach (var r in todayTrades)
{
if (statusList.Contains(r.TradeStatus))
{
continue;
}
var tradePrice = (r.TradePrice ?? 0) * ((r.BuySell == "卖出") ? 1 : -1);
var cashQuery = DbContext.trade_cash.Where(t => t.TradeId == r.id
&& t.ValidState != ConsGlobal.InValid && t.ValueDate <= req.ValueDate
&& !t.IsDeleted && tcActions.Contains(t.Action));
var tradeRealizedPnl = cashQuery.Any() ? cashQuery
.Sum(n => n.Amount + (n.Action == ClientCashInCashOut.系统操作_票息 ? 0 : n.UnwindPercentRate) * tradePrice) ?? 0 : 0;
var tradeCashAmount = cashQuery.Any() ? cashQuery
.Sum(n => n.Amount) : 0;
todayRealizedPnl += tradeRealizedPnl;
todayCashAmount += tradeCashAmount;
}
var beforePositionQuery = DbContext.eod_trade_position.Where(o => o.ValueDate == beforeDate && o.TradeType != "收益互换").ToList();
var beforeHedgeClosePnlSum = beforePositionQuery.Any() ? beforePositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.ClosedPnL).Sum() : 0;
var beforePV = beforePositionQuery.Any() ? beforePositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.Pv).Sum() : 0;
ids = beforePositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(x => x.TradeId);
var beforeTrades = DbContext.eod_trade.Where(o => o.ValueDate == beforeDate && ids.Contains(o.TradeId)).ToList().Select(o => o.trade);
var beforeRealizedPnl = 0.0;
foreach (var r in beforeTrades)
{
var tradePrice = (r.TradePrice ?? 0) * ((r.BuySell == "卖出") ? 1 : -1);
var cashQuery = DbContext.trade_cash.Where(t => t.TradeId == r.id
&& t.ValidState != ConsGlobal.InValid && t.ValueDate <= beforeDate
&& !t.IsDeleted && tcActions.Contains(t.Action));
var tradeRealizedPnl = cashQuery.Any() ? cashQuery
.Sum(n => n.Amount + (n.Action == ClientCashInCashOut.系统操作_票息 ? 0 : n.UnwindPercentRate) * tradePrice) ?? 0 : 0;
beforeRealizedPnl += tradeRealizedPnl;
}
var parentTrades = DbContext.trade.Where(o => tradeParentIds.Contains(o.id)).ToList();
var dayIncreaseValue = (sList.Where(o => o.TradeDate == req.ValueDate && o.ParentTradeId == 0).Any() ? sList.Where(o => o.TradeDate == req.ValueDate && o.ParentTradeId == 0).Sum(o => o.OriginalStockEqvNotional ?? 0) : 0)
+ (parentTrades.Where(o => o.TradeDate == req.ValueDate).Any() ? parentTrades.Where(o => o.TradeDate == req.ValueDate).Sum(o => o.OriginalStockEqvNotional ?? 0) : 0);
dayIncreaseValue = OtcFormatExtensions.OtcFormatValue(dayIncreaseValue, 2);
//非结构化交易的先算上
var todayDayHoldValue = (todayTrades.Where(o => o.ParentTradeId == 0).Any() ? todayTrades.Where(o => o.ParentTradeId == 0).Sum(o => o.StockEqvNotional) : 0);
var hedges = new HashSet<string>();
//var hedgeList = sList.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType));
var hedgeList2 = sList2.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType));
#endregion
//LogFactory.GetLogger("调试").Debug(sList.ToJson());
//LogFactory.GetLogger("调试").Debug(sList2.ToJson());
#region sheet
var parentEodList = DbContext.eod_trade.Where(o => o.ValueDate == req.ValueDate && tradeParentIds.Contains(o.TradeId)).ToList();
foreach (var item in sList)
{
var IsHedge = false;
var item2 = sList2.FirstOrDefault(o => o.id == item.id);
if (ConsTrade.TradeTypesForHedge.Contains(item.TradeType))
{
item2 = sList2.FirstOrDefault(o => o.HedgeUniqueCode == item.HedgeUniqueCode);
IsHedge = true;
}
var IsSettled = false;
var eod = todayTrades.Where(o => (o.id == item.id) && o.ParentTradeId == 0).FirstOrDefault();
var parentEod = item.ParentTradeId > 0 ? parentEodList.Where(O => O.TradeId == item.ParentTradeId).FirstOrDefault() : null;
if (eod != null)
{
IsSettled = !IsHedge && statusList.Contains(eod.TradeStatus);
//存续统计减掉已了结的
count -= IsSettled ? 1 : 0;
}
else if (parentEod != null)
{
IsSettled = !IsHedge && statusList.Contains(parentEod.TradeStatus) && tradeParentIds.Contains(item.ParentTradeId);
//存续统计减掉已了结的
count -= IsSettled ? 1 : 0;
}
if (item2 == null)
{
throw new ServiceException($"对冲波动率收盘数据与持仓波动率数据不匹配!({item.id}--{item.HedgeUniqueCode})");
}
var StockEqvNotionalToShow = item.StockEqvNotionalToShow;
var beforeDelta = riskQueryDic.ContainsKey(item.id) ? (double)riskQueryDic[item.id] : 0;
if (item.ParentTradeId > 0)
{
if (tradeParentIds.Contains(item.ParentTradeId))
{
var parentTrade = parentTrades.FirstOrDefault(o => o.id == item.ParentTradeId);
var isgroup = parentTrade.IsGroup == 1;
var legs = sList.Where(o => o.ParentTradeId == item.ParentTradeId);
var legs2 = sList2.Where(o => o.ParentTradeId == item.ParentTradeId);
var eods = todayTrades.Where(o => o.ParentTradeId == item.ParentTradeId);
if (legs.Count() != legs2.Count())
{
throw new ServiceException($"对冲波动率收盘数据与持仓波动率数据不匹配![{item.id}--{item.HedgeUniqueCode}]");
}
var childIds = legs.Select(o => o.id);
beforeDelta = riskQueryDic.Where(o => childIds.Contains(o.Key)).Sum(o => o.Value);
//结构化交易[非分组]加腿里的较大值
if (isgroup)
{
//startPv = parentTrade.TradePrice ?? 0;
if (parentEod != null)
{
var eodtrade = parentEod.trade;
todayDayHoldValue += eodtrade.StockEqvNotional;
}
if (dayUnwindPercentDic.TryGetValue(item.ParentTradeId, out var rate))
{
dayUnwindValue += (rate ?? 0) * (parentTrade.OriginalStockEqvNotional ?? 0);
}
}
else
{
//结构化交易[非分组]加腿里的较大值
var pairs = eods.Select(o => new KeyValuePair<int, double>(o.id, o.StockEqvNotional));
var maxTradeId = pairs.OrderByDescending(x => x.Value).FirstOrDefault().Key;
todayDayHoldValue += pairs.Max(o => o.Value);
if (dayUnwindPercentDic.TryGetValue(maxTradeId, out var rate))
{
dayUnwindValue += (rate ?? 0) * (item.OriginalStockEqvNotional ?? 0);
}
}
item.ClientName = parentTrade.ClientName;
item.TraderName = parentTrade.TraderName;
//item.TradePrice = parentTrade.TradePrice;
item.TradeType = string.IsNullOrWhiteSpace(parentTrade.StructureType) ? parentTrade.TradeType : parentTrade.StructureType;
item.TradeDate = parentTrade.TradeDate;
item.ExerciseDate = parentTrade.ExerciseDate;
item.UnderlyingAssetName = parentTrade.UnderlyingAssetName;
item.UnderlyingCode = parentTrade.UnderlyingCode;
StockEqvNotionalToShow = parentTrade.OriginalStockEqvNotional;
startPv = legs.Sum(o => (o.BuySell == "买入" || o.BuySell == "多头开仓" || o.BuySell == "空头平仓" ? 1 : -1) * (o.TradePrice ?? 0));
item.PV = legs.Sum(o => o.PV);
item.RoundedPV = legs.Sum(o => o.RoundedPV);
item.BuySell = parentTrade.BuySell;
item2.DeltaCash = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.DeltaCash ?? 0, 2));
item2.GammaCash = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.GammaCash ?? 0, 2));
item2.VegaCash = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.VegaCash ?? 0, 2));
item2.Delta = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.Delta ?? 0, 2));
item2.Gamma = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.Gamma ?? 0, 2));
item2.Vega = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.Vega ?? 0, 2));
tradeParentIds.Remove(item.ParentTradeId);
}
else
{
continue;
}
}
else
{
if (dayUnwindPercentDic.TryGetValue(item.id, out var rate))
{
dayUnwindValue += (rate ?? 0) * (item.OriginalStockEqvNotional ?? 0);
}
startPv = (item.BuySell == "买入" || item.BuySell == "多头开仓" || item.BuySell == "空头平仓" ? 1 : -1) * (item.TradePrice ?? 0);
}
StockEqvNotionalToShow = OtcFormatExtensions.OtcFormatValue(StockEqvNotionalToShow ?? 0, 2);
item2.DeltaCash = OtcFormatExtensions.OtcFormatValue(item2.DeltaCash ?? 0, 2);
item2.GammaCash = OtcFormatExtensions.OtcFormatValue(item2.GammaCash ?? 0, 2);
item2.VegaCash = OtcFormatExtensions.OtcFormatValue(item2.VegaCash ?? 0, 2);
item2.Delta = OtcFormatExtensions.OtcFormatValue(item2.Delta ?? 0, 2);
item2.Gamma = OtcFormatExtensions.OtcFormatValue(item2.Gamma ?? 0, 2);
item2.Vega = OtcFormatExtensions.OtcFormatValue(item2.Vega ?? 0, 2);
if (IsHedge)
{
//合计
var hedgeCodes = item.HedgeUniqueCode.Split('_');
var hedgeCode = hedgeCodes[0] + hedgeCodes[1] + hedgeCodes[3];
if (hedges.Contains(hedgeCode))
{
continue;
}
else
{
hedges.Add(hedgeCode);
//var SameUnderlyingHedges = hedgeList.Where(o => o.AssetBookName == item.AssetBookName
// && o.TradeType == item.TradeType && (o.UnderlyingCode == item.UnderlyingCode || (o.TradeType == "场内期权" && o.ExchangeOptionCode == item.ExchangeOptionCode))).ToList();
var SameUnderlyingHedges2 = hedgeList2.Where(o => o.AssetBookName == item.AssetBookName
&& o.TradeType == item.TradeType && ((o.TradeType != "场内期权" && o.UnderlyingCode == item.UnderlyingCode) || (o.TradeType == "场内期权" && o.ExchangeOptionCode == item.ExchangeOptionCode))).ToList();
item2.DeltaCash = SameUnderlyingHedges2.Sum(o => o.DeltaCash);
item.Notional = SameUnderlyingHedges2.Sum(o => o.Notional);
}
item2.DeltaCash = OtcFormatExtensions.OtcFormatValue(item2.DeltaCash ?? 0, 2);
DeltaCashSum += item2.DeltaCash ?? 0;
//DeltaCashSum += item2.DeltaCash ?? 0;
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode);
var dic = new Dictionary<string, object>
{
{ "序号", '-' },
{ "交易对手名称", um.MarketName },
{ "起始日期", "-" },
{ "终止日期", (item.ExerciseDate ?? um.MaturityDate).OtcFormatDate() },
{ "标的证券", item.UnderlyingAssetName },
{ "标的代码", item.UnderlyingCode },
{ "合约本金规模", item.Notional / (um.ContractSize == 0 ? 1 : um.ContractSize) + "手" },
{ "期初期权价值", "-" },
{ "当前期权价值", "-" },
{ "Delta比例", "-" },
{ "Delta对应总市值", item2.DeltaCash },
{ "GammaCash", "-" },
{ "VegaCash", "-" },
{ "Delta", item2.Delta },
{ "Gamma", "-" },
{ "Vega", "-" },
{ "期权端我方收益", "-" },
{ "产品结构", item.TradeType }
};
results.Add(dic);
}
else if (!IsSettled)
{
var dic = new Dictionary<string, object>
{
{ "序号", i.ToString() },
{ "交易对手名称", item.ClientName },
{ "起始日期", item.TradeDate.OtcFormatDate() },
{ "终止日期", item.ExerciseDate.OtcFormatDate() },
{ "标的证券", item.UnderlyingAssetName },
{ "标的代码", item.UnderlyingCode }
};
startPv = OtcFormatExtensions.OtcFormatValue(startPv, 2);
item.PV = OtcFormatExtensions.OtcFormatValue(item.PV ?? 0, 2);
item2.DeltaCash = OtcFormatExtensions.OtcFormatValue(item2.DeltaCash ?? 0, 2);
DeltaCashSum += item2.DeltaCash ?? 0;
item2.GammaCash = OtcFormatExtensions.OtcFormatValue(item2.GammaCash ?? 0, 2);
item2.VegaCash = OtcFormatExtensions.OtcFormatValue(item2.VegaCash ?? 0, 2);
item2.Delta = OtcFormatExtensions.OtcFormatValue(item2.Delta ?? 0, 2);
item2.Gamma = OtcFormatExtensions.OtcFormatValue(item2.Gamma ?? 0, 2);
item2.Vega = OtcFormatExtensions.OtcFormatValue(item2.Vega ?? 0, 2);
TradePriceSum += startPv;
PVSum += item.PV ?? 0;
var deltaRate = (StockEqvNotionalToShow == null || StockEqvNotionalToShow == 0) ? 0.0 : ((double)item2.DeltaCash / StockEqvNotionalToShow);
DeltaRateSum += OtcFormatExtensions.OtcFormatValue(deltaRate ?? 0, 2);
dic.Add("合约本金规模", StockEqvNotionalToShow);
StockEqvNotionalToShowSum += IsHedge ? 0 : (StockEqvNotionalToShow ?? 0);
dic.Add("期初期权价值", startPv);
dic.Add("当前期权价值", item.PV);
dic.Add("Delta比例", OtcFormatExtensions.OtcFormatValue(deltaRate ?? 0, 2));
dic.Add("Delta对应总市值", item2.DeltaCash);
dic.Add("GammaCash", item2.GammaCash ?? 0);
dic.Add("VegaCash", item2.VegaCash);
dic.Add("Delta", item2.Delta ?? 0);
dic.Add("Gamma", item2.Gamma ?? 0);
dic.Add("Vega", item2.Vega ?? 0);
DeltaCashSum += item2.DeltaCash ?? 0;
GammaCashSum += item2.GammaCash ?? 0;
VegaCashSum += item2.VegaCash ?? 0;
DeltaSum += item2.Delta ?? 0;
GammaSum += item2.Gamma ?? 0;
VegaSum += item2.Vega ?? 0;
var profit = beforeDelta * (item.UnderlyingPrice - priceDict.GetPrice(item.UnderlyingCode, SettlementTypeEnum.ClosePrice));
profit = OtcFormatExtensions.OtcFormatValue(profit, 2);
profitSum += profit;
var dailyPnl = item.PV - startPv;
dailyPnlSum += dailyPnl ?? 0;
dic.Add("期权端我方收益", dailyPnl);
//dic.Add("对冲端当日收益", OtcFormatExtensions.OtcFormatValue(calcProfit, 2));
dic.Add("中性对冲端当日收益", OtcFormatExtensions.OtcFormatValue(profit, 2));
//dic.Add("存续期浮动盈亏", calcProfit + item.PV - startPv);
dic.Add("产品结构", item.TradeType);
dic.Add("TradeNumber", item.TradeNumber);
results.Add(dic);
i++;
}
}
foreach (var item in results)
{
if (!item.Keys.Contains("中性对冲端当日收益"))
{
continue;
}
var profitStr = item["中性对冲端当日收益"].ToString();
if (string.IsNullOrWhiteSpace(profitStr))
{
item.Add("对冲端当日收益", "");
}
else
{
var profit = double.Parse(profitStr);
var calcProfit = todayHedgeMarkingPro * profit / profitSum;
calcProfit = OtcFormatExtensions.OtcFormatValue(calcProfit, 2);
calcProfitSum += calcProfit;
item.Add("对冲端当日收益", OtcFormatExtensions.OtcFormatValue(calcProfit, 2));
}
}
#endregion
#region sheet1_sum
var dicSum = new Dictionary<string, object>();
//todayHedgePositionPnlSum = OtcFormatExtensions.OtcFormatValue(todayHedgePositionPnlSum, 2);
calcProfitSum = OtcFormatExtensions.OtcFormatValue(calcProfitSum, 2);
var calcProfitDiff = todayHedgeMarkingPro - calcProfitSum;
results.ElementAt(0)["对冲端当日收益"] = (double)results.ElementAt(0)["对冲端当日收益"] + calcProfitDiff;
//results.ElementAt(0)["存续期浮动盈亏"] = (double)results.ElementAt(0)["存续期浮动盈亏"] + calcProfitDiff;
calcProfitSum += calcProfitDiff;
dicSum.Add("序号", "总计");
dicSum.Add("合约本金规模", OtcFormatExtensions.OtcFormatValue(StockEqvNotionalToShowSum, 2));
dicSum.Add("期初期权价值", OtcFormatExtensions.OtcFormatValue(TradePriceSum, 2));
dicSum.Add("当前期权价值", OtcFormatExtensions.OtcFormatValue(PVSum, 2));
dicSum.Add("Delta比例", "");
dicSum.Add("Delta对应总市值", OtcFormatExtensions.OtcFormatValue(DeltaCashSum, 2));
dicSum.Add("GammaCash", OtcFormatExtensions.OtcFormatValue(GammaCashSum, 2));
dicSum.Add("VegaCash", OtcFormatExtensions.OtcFormatValue(VegaCashSum, 2));
dicSum.Add("Delta", OtcFormatExtensions.OtcFormatValue(DeltaSum, 2));
dicSum.Add("Gamma", OtcFormatExtensions.OtcFormatValue(GammaSum, 2));
dicSum.Add("Vega", OtcFormatExtensions.OtcFormatValue(VegaSum, 2));
dicSum.Add("期权端我方收益", OtcFormatExtensions.OtcFormatValue((dailyPnlSum), 2));
dicSum.Add("对冲端当日收益", calcProfitSum);
dicSum.Add("中性对冲端当日收益", OtcFormatExtensions.OtcFormatValue(profitSum, 2));
dicSum.Add("存续期浮动盈亏", OtcFormatExtensions.OtcFormatValue((calcProfitSum + PVSum - TradePriceSum), 2));
results.Add(dicSum);
#endregion
#region sheet2
//todayPositionQuery.Any() ? todayPositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.ClosedPnL).Sum() : 0;
//var todayTrades = DbContext.eod_trade.Where(o => o.ValueDate == req.ValueDate && todayPositionQuery.Select(x => x.TradeId).Contains(o.TradeId)).ToList();
var Futu_UseMargin = todayMeta.Futu_MarginUsed;
var Futu_MarginBalance = todayMeta.Futu_MarginBalance;
var PositionAsset = todayMeta.StockAsset;
dayUnwindValue = OtcFormatExtensions.OtcFormatValue(dayUnwindValue, 2);
var AssetValuePerDay = new Dictionary<string, object>
{
{ "日期", req.ValueDate.OtcFormatDate() },
{ "存续笔数", count },
{ "日新增名义金额", dayIncreaseValue },
{ "日平仓名义金额", -1 * Math.Abs(dayUnwindValue) },
{ "存续名义本金", todayDayHoldValue },
{ "日估值损益", OtcFormatExtensions.OtcFormatValue(todayPV - beforePV, 2) },
{ "存续累计损益", OtcFormatExtensions.OtcFormatValue(todayPositonPnl, 2) },
{ "日平仓实现损益", OtcFormatExtensions.OtcFormatValue(todayRealizedPnl - beforeRealizedPnl, 2) },
{ "了结累计损益", OtcFormatExtensions.OtcFormatValue(todayRealizedPnl, 2) },
{ "累计总收益", OtcFormatExtensions.OtcFormatValue(todayPositonPnl + todayRealizedPnl - todayCashAmount, 2) },
{ "对冲端盯市金额", OtcFormatExtensions.OtcFormatValue(HedgeMarkingCash, 2) },
{ "当日出入金", OtcFormatExtensions.OtcFormatValue(todayHedgeCashInOut, 2) },
{ "实际日收益", todayHedgeMarkingPro },
{ "了结对冲累计收益", OtcFormatExtensions.OtcFormatValue(todayHedgeClosePnlSum, 2) },
{ "期货预付金占用", OtcFormatExtensions.OtcFormatValue(Futu_UseMargin, 2) },
{ "期货可用预付金", OtcFormatExtensions.OtcFormatValue(Futu_MarginBalance, 2) },
{ "现货资产", OtcFormatExtensions.OtcFormatValue(PositionAsset, 2) },
{ "未入金预付金", "" }
};
#endregion
var list1 = results.Select(n => new ExpandoDictionary<string, object>(n)).ToArray();
var list2 = new ExpandoDictionary<string, object>[] { new ExpandoDictionary<string, object>(AssetValuePerDay) };
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/场外风控报送模板.xlsx");
return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { tradelist = list1, dayreport = list2 }).GenerateBytes(true);
}
catch (Exception e)
{
LogFactory.GetLogger().Error("导出场外风控报送模板出错:" + e);
throw;
}
}
/// <summary>
/// 计算风险敞口
/// </summary>
/// <param name="td"></param>
/// <param name="price">现价</param>
/// <returns></returns>
public static double ExposureCalc(trade td, double price, DateTime valueDate)
{
var list = ConsTrade.TradeCompleteStatus;
if (td == null || td.BuySell != "买入" || list.Contains(td.TradeStatus))//或者了结了
{
return 0;
}
if (td.TradeType == "亚式期权" && td.trade_asian_option?.AveragingPeriodStartDate > valueDate)
{
return 0;
}
var tdClone = td.Clone();
var tc = new trade_cash();
SettlementCalcCommons.SetPossibleExec(tc, tdClone, price, true, valueDate);
return tc.Amount;
}
}
}