758 lines
42 KiB
C#
758 lines
42 KiB
C#
using BaseOUDAL;
|
|
using NPOI.POIFS.Properties;
|
|
using NPOI.SS.Formula.Functions;
|
|
using OfficeOpenXml.FormulaParsing.ExpressionGraph;
|
|
using Org.BouncyCastle.Ocsp;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using YLErp.BLL;
|
|
using YLErp.Commons;
|
|
using YLErp.DBModels;
|
|
using YLErp.DBModels.Helpers;
|
|
using YLErp.Model;
|
|
using YLErp.Modules.DataProviderModule;
|
|
using YLErp.Modules.UnderlyingModule;
|
|
using YLErp.Office.ExcelModule;
|
|
|
|
namespace YLErp.Modules.RiskModule
|
|
{
|
|
public class RealtimePositionRisksQueryService : YLBaseService
|
|
{
|
|
public RealtimePositionRisksQueryService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
public SearchListResult<RealTimePositionRisksDTO> SearchList(RealTimePositionRisksReq req)
|
|
{
|
|
if (req?.IsParentTrade == true)
|
|
{
|
|
return SearchRealTimeOptionPostionRisksList(req);
|
|
}
|
|
else
|
|
{
|
|
return SearchRealTimePostionRisksList(req);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否主交易 是
|
|
/// </summary>
|
|
/// <param name="req"></param>
|
|
/// <returns></returns>
|
|
public SearchListResult<RealTimePositionRisksDTO> SearchRealTimeOptionPostionRisksList(RealTimePositionRisksReq req)
|
|
{
|
|
var voltype = req?.VolType ?? string.Empty;
|
|
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
|
|
|
|
var realtimePredicate = BuildPredicateOfRealTime(req);
|
|
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.TraderIds != null && req.TraderIds.Any(x => x > 0))
|
|
{
|
|
tradePredicate = tradePredicate.And(q => req.TraderIds.Contains(q.TraderId));
|
|
}
|
|
|
|
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))
|
|
{
|
|
realtimePredicate = realtimePredicate.And(n => n.TradeId > 0);
|
|
tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber));
|
|
}
|
|
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 tradeList = new List<string> { "收益互换", "远期", "掉期", "现金流交易" };
|
|
|
|
var query = from intradayTrade in DbContext.intraday_trade_position.Where(realtimePredicate)
|
|
join trade in DbContext.trade.Where(tradePredicate) on intradayTrade.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 realtimeRisk in DbContext.realtime_trade_risk on intradayTrade.TradeId equals realtimeRisk.TradeId into realtimeRisk_t
|
|
from realtimeRisk in realtimeRisk_t.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 intradayTrade.TradeId equals binary.TradeId into binary_t
|
|
from binary in binary_t.DefaultIfEmpty()
|
|
join asian in DbContext.trade_asian_option on intradayTrade.TradeId equals asian.TradeId into asian_t
|
|
from asian in asian_t.DefaultIfEmpty()
|
|
join barrier in DbContext.trade_barrier_option on intradayTrade.TradeId equals barrier.TradeId into barrier_t
|
|
from barrier in barrier_t.DefaultIfEmpty()
|
|
join um in DbContext.underlying_manager on intradayTrade.UnderlyingCode equals um.UnderlyingCode into um_t
|
|
from um in um_t.DefaultIfEmpty()
|
|
where !statusList.Contains(intradayTrade.TradeStatus)
|
|
&& (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId))
|
|
&& (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id))
|
|
&& !tradeList.Contains(intradayTrade.TradeType)
|
|
&& realtimeRisk.VolType == voltype
|
|
select new RealTimePositionRisksDTO
|
|
{
|
|
GroupName = trade.GroupName,
|
|
id = trade.id,
|
|
OptionType = trade.OptionType,
|
|
ClientName = trade.ClientName,
|
|
TraderName = trade.TraderName,
|
|
AssetBookName = assetUnit != null ? assetUnit.Name : null,
|
|
CurrentVolatility = realtimeRisk.Vol,
|
|
PositionPnl = intradayTrade != null ? intradayTrade.PositionPnL : 0,//浮动盈亏
|
|
RoundedPositionPnl = intradayTrade != null ? intradayTrade.RoundedPositionPnl : 0,
|
|
PV = intradayTrade != null ? (double)intradayTrade.Pv : 0,
|
|
RoundedPV = intradayTrade != null ? (double)intradayTrade.RoundedPv : 0,
|
|
|
|
Vega = realtimeRisk.Vega, //实现盈亏
|
|
Theta = realtimeRisk.Theta,
|
|
Rho = realtimeRisk.Rho,
|
|
Delta = realtimeRisk.Delta,
|
|
Gamma = realtimeRisk.Gamma,
|
|
DeltaCash = realtimeRisk.DeltaCash,
|
|
GammaCash = realtimeRisk.GammaCash,
|
|
VegaCash = realtimeRisk.VegaCash,
|
|
|
|
ExerciseDate = trade.ExerciseDate,
|
|
ExerciseMode = trade.ExerciseMode,
|
|
|
|
Notional = intradayTrade != null ? intradayTrade.Amount : 0,
|
|
StockEqvNotionalMax = trade.StockEqvNotionalMax,
|
|
OriginalStockEqvNotional = trade.OriginalStockEqvNotional,
|
|
Strike = trade.Strike,
|
|
IsMoneynessOption = trade.IsMoneynessOption,
|
|
|
|
ExchangeOptionCode = intradayTrade != null ? intradayTrade.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 = intradayTrade.UnderlyingCode,
|
|
IsGroup = trade.IsGroup,
|
|
Margin = intradayTrade != null ? intradayTrade.Margin : 0,
|
|
|
|
Exposure = realtimeRisk.CreditExposure,
|
|
RealizedPnl = realtimeRisk != null ? realtimeRisk.RealizedPnl.Value : 0,
|
|
|
|
HedgeUniqueCode = intradayTrade != null ? intradayTrade.HedgeUniqueCode : "",
|
|
OriginalPrincipalSum = trade.OriginalPrincipalSum,
|
|
SurvivingNominalPrincipal = trade.SpotPrice * intradayTrade.Amount,
|
|
UnderlyingPrice = realtimeRisk != null ? realtimeRisk.UnderlyingPrice.Value : 0,
|
|
CalSpotPrice = realtimeRisk != null ? realtimeRisk.UnderlyingPrice.Value : 0,
|
|
trade = trade,
|
|
OptDate = realtimeRisk.OptDate
|
|
};
|
|
|
|
query = query.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber);
|
|
|
|
//所有子交易
|
|
var childTradeList = query.Where(n => n.ParentTradeId > 0).ToList();
|
|
//过滤掉所有子交易
|
|
//query = query.Where(n => n.ParentTradeId == 0);
|
|
|
|
var searchResult = query.ToSearchList(req);
|
|
|
|
|
|
var tcActions = new[] { ClientCashInCashOut.系统操作_平仓费,
|
|
ClientCashInCashOut.系统操作_行权费,ClientCashInCashOut.系统操作_票息,ClientCashInCashOut.系统操作_互换,ClientCashInCashOut.人工操作_其他};
|
|
|
|
|
|
BLL.tradeBLL.SetFieldsByTradeType(searchResult.rows.Select(o => o.trade));
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
if (r.IsGroup == 1 || r.TradeType == "结构化交易")
|
|
{
|
|
var cTrades = childTradeList.Where(n => n.ParentTradeId == r.id).ToList();
|
|
|
|
if (cTrades.Count() == 0)
|
|
{
|
|
var childTradeIds = DbContext.trade.Where(n => n.ParentTradeId == r.id).Select(n => n.id).ToList();
|
|
|
|
cTrades = (from childRealTimeRisk in DbContext.realtime_trade_risk
|
|
join childIntradayTrade in DbContext.intraday_trade_position on childRealTimeRisk.TradeId equals childIntradayTrade.TradeId
|
|
where childTradeIds.Contains(childRealTimeRisk.TradeId.Value)
|
|
select new RealTimePositionRisksDTO
|
|
{
|
|
PV = childRealTimeRisk.Pv,
|
|
RoundedPV = childRealTimeRisk.RoundedPv,
|
|
PositionPnl = childRealTimeRisk.PositionPnl,
|
|
RoundedPositionPnl = childRealTimeRisk.RoundedPositionPnl,
|
|
RealizedPnl = childRealTimeRisk.RealizedPnl ?? 0,
|
|
Margin = childIntradayTrade.Margin,
|
|
Delta = childRealTimeRisk.Delta,
|
|
Gamma = childRealTimeRisk.Gamma,
|
|
Vega = childRealTimeRisk.Vega,
|
|
Theta = childRealTimeRisk.Theta,
|
|
Rho = childRealTimeRisk.Rho,
|
|
}).ToList();
|
|
|
|
}
|
|
r.PV = cTrades.Sum(y => y.PV);
|
|
r.RoundedPV = cTrades.Sum(y => y.RoundedPV);
|
|
r.PositionPnl = cTrades.Sum(y => y.PositionPnl);
|
|
r.RoundedPositionPnl = cTrades.Sum(y => y.RoundedPositionPnl);
|
|
r.RealizedPnl = cTrades.Sum(n => n.RealizedPnl);
|
|
r.Margin = cTrades.Sum(y => y.Margin);
|
|
r.Delta = cTrades.Sum(y => y.Delta);
|
|
r.Gamma = cTrades.Sum(y => y.Gamma);
|
|
r.Vega = cTrades.Sum(y => y.Vega);
|
|
r.Theta = cTrades.Sum(y => y.Theta);
|
|
r.Rho = cTrades.Sum(y => y.Rho);
|
|
|
|
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;
|
|
r.etcTradePrice = r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional);
|
|
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;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
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;
|
|
|
|
r.etcTradePrice = r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
r.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(r.trade.ClientId)?.Number;
|
|
|
|
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.Rho *= 100;
|
|
}
|
|
|
|
if (searchResult.rows.Count() > 0)
|
|
{
|
|
searchResult.Msg = searchResult.rows.FirstOrDefault().OptDate?.ToString("yyyy-MM-dd HH:mm:ss");
|
|
}
|
|
return searchResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否主交易 否
|
|
/// </summary>
|
|
/// <param name="req"></param>
|
|
/// <returns></returns>
|
|
public SearchListResult<RealTimePositionRisksDTO> SearchRealTimePostionRisksList(RealTimePositionRisksReq req)
|
|
{
|
|
var voltype = req?.VolType ?? string.Empty;
|
|
var statusList = new List<string> { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 };
|
|
|
|
var realtimePredicate = BuildPredicateOfRealTime(req);
|
|
var tradePredicate = PredicateBuilder.Create<trade>(t => t.ValidState != "InValid" && t.TradeType != "结构化交易" && t.IsGroup != 1);
|
|
|
|
if (req.UserAssets != null && req.UserClients != null)
|
|
{
|
|
tradePredicate = tradePredicate.And(a => req.UserAssets.Contains(a.AssetId) || req.UserClients.Contains(a.ClientId));
|
|
}
|
|
|
|
if (req.TraderIds != null && req.TraderIds.Any(x => x > 0))
|
|
{
|
|
tradePredicate = tradePredicate.And(q => req.TraderIds.Contains(q.TraderId));
|
|
}
|
|
|
|
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))
|
|
{
|
|
realtimePredicate = realtimePredicate.And(n => n.TradeId > 0);
|
|
tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber));
|
|
}
|
|
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 tradeList = new List<string> { "收益互换", "远期", "掉期", "现金流交易" };
|
|
|
|
var query = from intradayTrade in DbContext.intraday_trade_position.Where(realtimePredicate)
|
|
join trade in DbContext.trade.Where(tradePredicate) on intradayTrade.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 realtimeRisk in DbContext.realtime_trade_risk on intradayTrade.TradeId equals realtimeRisk.TradeId into realtimeRisk_t
|
|
from realtimeRisk in realtimeRisk_t.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 intradayTrade.TradeId equals binary.TradeId into binary_t
|
|
from binary in binary_t.DefaultIfEmpty()
|
|
join asian in DbContext.trade_asian_option on intradayTrade.TradeId equals asian.TradeId into asian_t
|
|
from asian in asian_t.DefaultIfEmpty()
|
|
join barrier in DbContext.trade_barrier_option on intradayTrade.TradeId equals barrier.TradeId into barrier_t
|
|
from barrier in barrier_t.DefaultIfEmpty()
|
|
join um in DbContext.underlying_manager on intradayTrade.UnderlyingCode equals um.UnderlyingCode into um_t
|
|
from um in um_t.DefaultIfEmpty()
|
|
where !statusList.Contains(intradayTrade.TradeStatus)
|
|
&& (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId))
|
|
&& (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id))
|
|
&& !tradeList.Contains(intradayTrade.TradeType)
|
|
&& realtimeRisk.VolType == voltype
|
|
select new RealTimePositionRisksDTO
|
|
{
|
|
GroupName = trade.GroupName,
|
|
id = trade.id,
|
|
OptionType = trade.OptionType,
|
|
ClientName = trade.ClientName,
|
|
TraderName = trade.TraderName,
|
|
AssetBookName = assetUnit != null ? assetUnit.Name : null,
|
|
CurrentVolatility = realtimeRisk.Vol,
|
|
PositionPnl = intradayTrade != null ? intradayTrade.PositionPnL : 0,//浮动盈亏
|
|
RoundedPositionPnl = intradayTrade != null ? intradayTrade.RoundedPositionPnl : 0,
|
|
PV = intradayTrade != null ? (double)intradayTrade.Pv : 0,
|
|
RoundedPV = intradayTrade != null ? (double)intradayTrade.RoundedPv : 0,
|
|
|
|
Vega = realtimeRisk.Vega, //实现盈亏
|
|
Theta = realtimeRisk.Theta,
|
|
Rho = realtimeRisk.Rho,
|
|
Delta = realtimeRisk.Delta,
|
|
Gamma = realtimeRisk.Gamma,
|
|
DeltaCash = realtimeRisk.DeltaCash,
|
|
GammaCash = realtimeRisk.GammaCash,
|
|
VegaCash = realtimeRisk.VegaCash,
|
|
|
|
ExerciseDate = trade.ExerciseDate,
|
|
ExerciseMode = trade.ExerciseMode,
|
|
|
|
Notional = intradayTrade != null ? intradayTrade.Amount : 0,
|
|
StockEqvNotionalMax = trade.StockEqvNotionalMax,
|
|
OriginalStockEqvNotional = trade.OriginalStockEqvNotional,
|
|
Strike = trade.Strike,
|
|
IsMoneynessOption = trade.IsMoneynessOption,
|
|
|
|
ExchangeOptionCode = intradayTrade != null ? intradayTrade.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.TradeType == "自定义交易" ? trade.StructureType : trade.TradeType,
|
|
UnderlyingCode = intradayTrade.UnderlyingCode,
|
|
IsGroup = trade.IsGroup,
|
|
Margin = intradayTrade != null ? intradayTrade.Margin : 0,
|
|
|
|
Exposure = realtimeRisk.CreditExposure,
|
|
RealizedPnl = realtimeRisk != null ? realtimeRisk.RealizedPnl.Value : 0,
|
|
|
|
HedgeUniqueCode = intradayTrade != null ? intradayTrade.HedgeUniqueCode : "",
|
|
OriginalPrincipalSum = trade.OriginalPrincipalSum,
|
|
SurvivingNominalPrincipal = trade.SpotPrice * intradayTrade.Amount,
|
|
UnderlyingPrice = realtimeRisk != null ? realtimeRisk.UnderlyingPrice.Value : 0,
|
|
CalSpotPrice = realtimeRisk != null ? realtimeRisk.UnderlyingPrice.Value : 0,
|
|
trade = trade,
|
|
OptDate = realtimeRisk.OptDate
|
|
};
|
|
|
|
query = query.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber);
|
|
var searchResult = query.ToSearchList(req);
|
|
|
|
|
|
var tcActions = new[] { ClientCashInCashOut.系统操作_平仓费,
|
|
ClientCashInCashOut.系统操作_行权费,ClientCashInCashOut.系统操作_票息,ClientCashInCashOut.系统操作_互换,ClientCashInCashOut.人工操作_其他};
|
|
|
|
|
|
BLL.tradeBLL.SetFieldsByTradeType(searchResult.rows.Select(o => o.trade));
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
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 = r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional);
|
|
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 (um != null)
|
|
{
|
|
r.GammaLots = (r.Gamma ?? 0) / um.ContractSize;
|
|
r.DeltaLots = (r.Delta ?? 0) / um.ContractSize;
|
|
}
|
|
r.Rho *= 100;
|
|
}
|
|
|
|
if (searchResult.rows.Count() > 0)
|
|
{
|
|
searchResult.Msg = searchResult.rows.FirstOrDefault().OptDate?.ToString("yyyy-MM-dd HH:mm:ss");
|
|
}
|
|
return searchResult;
|
|
}
|
|
|
|
public Expression<Func<intraday_trade_position, bool>> BuildPredicateOfRealTime(RealTimePositionRisksReq reqModel)
|
|
{
|
|
var predicate = PredicateBuilder.Create<intraday_trade_position>(t => t.ValueDate == valuedateBLL.ValueDate);
|
|
if (reqModel.UserAssets != null || reqModel.UserClients != null)
|
|
{
|
|
predicate = predicate.And(t => reqModel.UserAssets.Contains(t.BookId) || 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 != null && reqModel.BookIds.Any(x => x > 0))
|
|
{
|
|
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.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;
|
|
}
|
|
|
|
public byte[] ExportRealtimePositionRisksToExcel(RealTimePositionRisksReq req)
|
|
{
|
|
var results = GettRealtimePositionRisksDataHandle(req);
|
|
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 List<Dictionary<string, string>> GettRealtimePositionRisksDataHandle(RealTimePositionRisksReq req)
|
|
{
|
|
|
|
if (req.TradeIds == null || !req.TradeIds.Any())
|
|
{
|
|
req.page = 0;
|
|
req.rows = 10000;
|
|
}
|
|
req.IsOnlyExport = true;
|
|
IEnumerable<RealTimePositionRisksDTO> sList = null;
|
|
sList = SearchList(req).rows;
|
|
if (sList == null || sList.Count() == 0)
|
|
{
|
|
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.OtcFormatFlex(2, 2, percent: true));
|
|
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);
|
|
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.CalSpotPrice.OtcFormatMoney());
|
|
dic.Add("维持预付金", item.Margin.OtcFormatMoney());
|
|
results.Add(dic);
|
|
}
|
|
return results;
|
|
}
|
|
}
|
|
}
|