2656 lines
155 KiB
C#
2656 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("Vega_1bp", OtcFormatExtensions.OtcFormat(item.Vega_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", "");
|
|
dic.Add("Vega_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;
|
|
}
|
|
|
|
}
|
|
}
|