using YLErp.Commons; using YLErp.DBModels.Helpers; using YLErp.Models; using YLErp.Modules.CalculationModule; using YLErp.Modules.TradeModule; using YLErp.QdpModule; namespace YLErp.Modules.IntradayModule { public class IntradayPositionApiService : YLBaseService { public IntradayPositionApiService(IntradaySettleInfoQueryContext context) : base(context) { } /// /// 查询场外期权持仓列表 /// public IntradayTradePositionResult GetIntradayPositions(DateTime valueDate, List clientIdsOfInside = null) { var result = new IntradayTradePositionResult { SwapPositions = new List(), OptionPositions = new List(), ForwardPositions = new List() }; var IsPVRounded = PS.Config.IsPVRounded; valueDate = valueDate.Date; var suspensionUnderlyingIdList = DataCacheProvider.GetUnderlyingDataSource().AsQueryable() .Where(t => t.UnderlyingStatus == underlying_manager.Status_Suspension).Select(t => t.id).ToList(); var predicate = PredicateBuilder.Create(t => t.ClientId > 0 && !clientIdsOfInside.Contains(t.ClientId) && ConsTrade.NeedMarginTradeStatusList.Contains(t.TradeStatus) && (t.ValidState != "InValid" || t.ValidState == null) && (t.TradeType != "结构化交易" || t.IsGroup != 0) && (t.ExerciseDate >= valueDate || suspensionUnderlyingIdList.Contains(t.UnderlyingId))); var tcgQuery = from tc in DbContext.trade_cash where tc.ValueDate == valueDate && tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted group tc by tc.TradeId into g select new { TradeId = g.Key, Amount = g.Sum(t => t.Amount), Percent = g.Sum(t => t.Action == ClientCashInCashOut.系统操作_平仓费 || t.Action == ClientCashInCashOut.系统操作_行权费 || t.Action == ClientCashInCashOut.系统操作_票息 & t.IsLastAction ? t.UnwindPercentRate : 0) }; var volType = PS.Config.Is国投 ? "开仓" : "持仓"; var query = from t in DbContext.trade.AsQueryable().Where(predicate) join risk in DbContext.realtime_trade_risk.Where(tr => tr.ValueDate == valueDate && tr.VolType == volType) on t.id equals risk.TradeId into risks from risk in risks.DefaultIfEmpty() join position in DbContext.intraday_trade_position.Where(tp => tp.ValueDate == valueDate) on t.id equals position.TradeId into positions from position in positions.DefaultIfEmpty() join tc in tcgQuery on t.id equals tc.TradeId into tc_t from tc in tc_t.DefaultIfEmpty() select new InnerPosition { Trade = t, PositionPv = position == null ? 0 : IsPVRounded ? (double)position.RoundedPv : (double)position.Pv, PositionPnl = position == null ? 0 : IsPVRounded ? position.RoundedPositionPnl : position.PositionPnL, IsGroup = t.IsGroup, DailyPnl = position == null ? 0 : (double)position.DailyPnL, Risk = risk == null ? null : new InnerPositionRisk { Delta = risk.Delta ?? 0, Gamma = risk.Gamma ?? 0, Theta = risk.Theta ?? 0, Rho = risk.Rho ?? 0, Vega = risk.Vega ?? 0, DeltaCash = risk.DeltaCash ?? 0, GammaCash = risk.GammaCash ?? 0, VegaCash = risk.VegaCash ?? 0, Vol = risk.Vol ?? 0, SettlePrice = risk.UnderlyingPrice }, UnwindPercent =tc.Percent, RealizedPnl = (double?)tc.Amount }; //DbContext.SetDebugLog(); //因为query还在读取中,所以不要用同一个dbcontext var extendService = new TradeExtendService(OptUser); var posList = query.ToArray(); var groupSumDic = new Dictionary(); var trades = posList.Select(n => n.Trade).ToArray(); BLL.tradeBLL.SetFieldsByTradeType(trades); foreach (var pos in posList) { if (pos.IsGroup == 0) { pos.RealizedPnl = TradeCalcHelper.CalcWinLoss(tradeType: pos.Trade.TradeType, buySell: pos.Trade.BuySell, tradePrice: pos.Trade.TradePrice ?? 0, tcUnwindPercent: pos.UnwindPercent??0, tcAmount: pos.RealizedPnl??0); } else if (pos.IsGroup == 2 && pos.Trade.ParentTradeId > 0) { if (!groupSumDic.TryGetValue(pos.Trade.ParentTradeId, out var p)) { groupSumDic[pos.Trade.ParentTradeId] = p = new InnerPosition(); } p.PositionPv += pos.PositionPv; p.PositionPnl += pos.PositionPnl; p.DailyPnl += pos.DailyPnl; p.RealizedPnl += pos.RealizedPnl = TradeCalcHelper.CalcWinLoss(tradeType: pos.Trade.TradeType, buySell: pos.Trade.BuySell, tradePrice: pos.Trade.TradePrice ?? 0, tcUnwindPercent: pos.UnwindPercent??0, tcAmount: pos.RealizedPnl??0); } } foreach (var pos in posList) { var td = pos.Trade; if (td.TradeType == "结构化交易") { if (td.IsGroup == 1) { td.TradeType = "组合交易"; if (groupSumDic.TryGetValue(td.id, out var p)) { pos.PositionPv = p.PositionPv; pos.PositionPnl = p.PositionPnl; pos.RealizedPnl = p.RealizedPnl; pos.DailyPnl = p.DailyPnl; } } else { continue; } } else if (td.IsGroup == 2) { continue; } extendService.SetTradeExtend(new[] { td }, false); var un = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); if (un != null) { pos.CountRatio = un.CountRatio; pos.ContractSize = un.ContractSize; } IntradayPositionField positionField = null; if (td.TradeType == "收益互换") { var f = GetIntradayPayOffSwapPostionFields(td, td.StockEqvNotional, pos); result.SwapPositions.Add(f); positionField = f; } else if (td.TradeType == "远期") { var f = GetIntradayForwardPostionFields(td, pos); result.ForwardPositions.Add(f); positionField = f; } else { var f = GetIntradayOptionPostionFields(td, pos); result.OptionPositions.Add(f); positionField = f; } if (positionField != null) { positionField.ContractSize = pos.ContractSize; positionField.RealizedPnl = pos.RealizedPnl??0; positionField.SettlePrice = pos.Risk?.SettlePrice ?? 0; positionField.DaysToExpiration = QdpCalendarHelper.GetNonHolidayDaysBetween(valueDate, td.ExerciseDate.Value); } } return result; } #region----场外期权---- private IntradayOptionPositionField GetIntradayOptionPostionFields(trade td, InnerPosition pos) { var isMoneyness = td.IsMoneynessOption == "是"; var isUsePremiumRate = td.IsUsePremiumRate == true; var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var volFormat = PS.Config.ErpElement.VolMoreAccurate ? "P4" : "P2"; var f = new IntradayOptionPositionField { TradeType = td.TradeType, StructureType = td.TradeMultipleType, TradeNumber = td.TradeNumber, AssetBookName = td.AssetBookName, TraderName = td.TraderName, ClientName = td.ClientName, ExerciseMode = td.ExerciseModeCn, CallPut = td.CallPut, TradeDate = td.TradeDate.OtcFormatDate(), ExerciseDate = td.ExerciseDate.OtcFormatDate(), SettlementDate = td.SettlementDate.OtcFormatDate(), TradeSide = td.BuySell, UnderlyingCode = td.UnderlyingCode, UnderlyingName = underlying?.UnderlyingName, InitSpotPrice = td.SpotPrice ?? 0, Strike = td.Strike.OtcFormatUmPrice(isMoneyness), IsMoneynessOption = isMoneyness ? "是" : "否", Premium = isUsePremiumRate ? td.PremiumRate.OtcFormat(OtcFormatFlag.premiumRateP) : td.TradeSinglePrice.OtcFormat(OtcFormatFlag.tradeSinglePrice), IsUsePremiumRate = isUsePremiumRate ? "是" : "否", InitialMargin = td.InitialMargin ?? 0, TradeAmount = (td.OriginalNotional ?? 0) / pos.CountRatio, TradePrice = td.TradePrice ?? 0, StockEqvNotional = td.OriginalStockEqvNotional ?? 0, StockEqvNotionalReal = td.StockEqvNotionalReal, IsAnnualized = td.IsAnnualized ? "是" : "否", AnnualizeFactor = td.AnnualizeFactor?.ToString("F8"), PrincipalRate = td.PrincipalRate.OtcFormatPercent(), ParticipationRate = td.ParticipationRate.OtcFormatPercent(), NoRiskRate = td.NoRiskRate.OtcFormatPercent(), DividendRate = td.DividendRate.OtcFormatPercent(), TradeOpenVolatility = td.TradeOpenVolatility?.ToString(volFormat), TradeCloseVolatility = td.TradeCloseVolatility?.ToString(volFormat), NumOfSmoothingDays = td.NumOfSmoothingDays ?? 0, Comments = td.Comments, PositionPv = pos.PositionPv, PositionPnl = pos.PositionPnl, PositionTradeAmount = td.TradeAmount, DailyPnl = pos.DailyPnl }; if (pos.Risk != null) { var risk = pos.Risk; f.Delta = risk.Delta; f.DeltaCash = risk.DeltaCash; f.Gamma = risk.Gamma; f.GammaCash = risk.GammaCash; f.Vega = risk.Vega; f.VegaCash = risk.VegaCash; f.Theta = risk.Theta; f.Rho = risk.Rho; f.PositionVol = risk.Vol.ToString(volFormat); } if (_context.TryGetClientInfo(td.ClientId, out var clientInfo)) { f.ClientName = clientInfo.Name; f.ClientNumber = clientInfo.Number; } switch (f.TradeType) { case "亚式期权": SetAsianOption(td.trade_asian_option, f); break; case "障碍期权": SetBarrierOption(td.trade_barrier_option, f, isMoneyness: isMoneyness, isUsePremiumRate: isUsePremiumRate); break; case "双鲨期权": SetDbSharkOption(td.trade_double_sharkfin_option, f, isMoneyness: isMoneyness, isUsePremiumRate: isUsePremiumRate); break; case "二元期权": SetBianryOption(td.trade_binary_option, f, isMoneyness: isMoneyness, isUsePremiumRate: isUsePremiumRate); break; case "区间累积期权": SetRangeAccuralOption(td.trade_rangeaccrual, f, isMoneyness); break; case "气囊结构": SetAirbagOption(td.trade_airbag, f, isMoneyness); break; case "收益增强结构": if (td.trade_underlying_enhance != null) { f.CallPut = string.Empty; f.AnnualizedEnhanceRate = td.trade_underlying_enhance.AnnualizedEnhanceRate.OtcFormatPercent(4); } break; case "凤凰期权": SetAutoCallOption(td.trade_autocall, f, isMoneyness); break; case "雪球期权": SetSnowballOption(td.trade_snowball, f, isMoneyness, td.CallPut); break; case "累计期权": SetAccumulatorOption(td.trade_accumulator_option, f, isMoneyness, td.CallPut); break; case "自定义交易": { f.StructureTypeSpec = td.StructureType; f.StructureIntroduction = td.StructureIntroduction; f.ExtendInfo = td.ExtendInfo; f.ObservationDates = td.trade_custom?.ObservationDates; } break; case "组合交易": { f.ExtendInfo = td.ExtendInfo; } break; } if (td.TradeType == "凤凰期权" || td.TradeType == "雪球期权") { f.CallPut = f.ExerciseMode = string.Empty; td.MetaDic.TryGetValue(nameof(OtcOptionTradeFull.AnnualizeFactor2), out var metaValue); f.AnnualizeFactor = metaValue; } else { td.MetaDic.TryGetValue(nameof(OtcOptionTradeFull.AnnualizeFactor), out var metaValue); f.AnnualizeFactor = metaValue; } return f; } //累计期权 private static void SetAccumulatorOption(trade_accumulator_option option, IntradayOptionPositionField f, bool isMoneyness, string callput) { if (option != null) { f.AccumulatorKOBarrier = option.KOBarrier.OtcFormatFlex(2, 2); f.AccumulatorPayoffType = option.PayoffType; if (option.PayoffType == "固定") { f.AccumulatorPayoffType = "固定(票息)"; f.AccumulatorCoupon = option.CouponPercent ? option.Coupon.OtcFormatPercent() : option.Coupon.OtcFormatFlex(2); f.AccumulatorCouponDayCount = option.CouponDayCount; f.AccumulatorIsAnnualizedCoupon = option.IsFixedCoupon ? "否" : "是"; } f.AccumulatorMultiplier = ConsGlobal.CallPut.IsCall(callput) ? option.PutMultiplier : option.CallMultiplier; f.AccumulatorEarlyTerminate = option.EarlyTerminate ? "是" : "否"; switch (option.SettlementMode) { case "现金期末": f.AccumulatorSettlementMode = "现金结算(期末)"; break; case "实物交割": f.AccumulatorSettlementMode = "实物交割"; break; default: f.AccumulatorSettlementMode = "现金结算(当日)"; break; } f.AccumulatorAccumuType = option.AccumuType; f.ObservationDates = option.KOObservationDates; f.SettlementDate = option.KOObservationSettleDates; } } //雪球期权 private static void SetSnowballOption(trade_snowball option, IntradayOptionPositionField f, bool isMoneyness, string callput) { if (option != null) { f.SnowballKOBarrier = option.KOBarrier.OtcFormatUmPrice(isMoneyness); switch (option.KOPayoffType) { case KOPayoffTypeEnum.Rebate: f.SnowballKOPayoffType = "票息补偿"; f.SnowballIsAnnualizedCoupon = option.IsFixedCoupon ? "否" : "是"; f.SnowballKORebate = option.KORebate.OtcFormatPercent(); f.SnowballAnnualizedPremiumRate = option.AnnualizedPremiumRate.OtcFormatPercent(); f.SnowballKOObservationSettleDates = option.KOObservationSettleDates; break; case KOPayoffTypeEnum.ToOption: f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(option.KOPayoffType, callput); f.SnowballKOStrike1 = option.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; case KOPayoffTypeEnum.ToSpreadOption: f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(option.KOPayoffType, callput); f.SnowballKOStrike2 = option.SpreadStrikeAtKO.OtcFormatUmPrice(isMoneyness); f.SnowballKOStrike1 = option.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; default: f.SnowballKOPayoffType = option.KOPayoffType.ToString(); break; } f.SnowballKORebateType = RebateTypeEnumHelper.GetDesc(option.KORebateType); f.SnowballKIBarrier = option.KIBarrier.OtcFormatUmPrice(isMoneyness); switch (option.KIPayoffType) { case KIPayoffTypeEnum.None: f.SnowballKIPayoffType = "无"; break; case KIPayoffTypeEnum.ToPutOption: f.SnowballKIPayoffType = "敲入转看跌"; f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToPutSpreadOption: f.SnowballKIPayoffType = "敲入转熊市价差"; f.SnowballKIStrike2 = option.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness); f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToCallOption: f.SnowballKIPayoffType = "敲入转看涨"; f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToCallSpreadOption: f.SnowballKIPayoffType = "敲入转牛市价差"; f.SnowballKIStrike2 = option.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness); f.SnowballKIStrike1 = option.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; default: f.SnowballKIPayoffType = option.KIPayoffType.ToString(); break; } f.SnowballNoKICoupon = option.Coupon.OtcFormatPercent(); var KOObservationDates = option.KOObservationDates ?? string.Empty; var index = KOObservationDates.IndexOf(';'); f.KOObservationDates = index > 0 ? option.KOObservationDates.Substring(0, index) : KOObservationDates; f.KIObservationDates = option.ObservationDates; f.IsAnnualized = option.IsAnnualized2 ? "是" : "否"; f.SnowballKnockInOutStatus = option.KnockInOutStatusCn; f.SnowballKnockInOutDate = option.KnockInOutDate.OtcFormatDate(); } } //凤凰期权 private static void SetAutoCallOption(trade_autocall option, IntradayOptionPositionField f, bool isMoneyness) { if (option != null) { f.AutocallIsAnnualizedCoupon = option.IsFixedCoupon ? "否" : "是"; f.AutocallCoupon = option.Coupon.OtcFormatPercent(); f.AutocallCouponBarrier = option.CouponBarrier.OtcFormatUmPrice(isMoneyness); f.AutocallCouponPayType = option.CouponPayTypeDesc(); f.AutocallKOBarrier = option.KOBarrier.OtcFormatUmPrice(isMoneyness); f.AutocallKIBarrier = option.KIBarrier.OtcFormatUmPrice(isMoneyness); f.AutocallIncludeCouponAfterKI = option.IncludeCouponAfterKI ? "是" : "否"; f.AutocallKIPayoffType = option.KIPayoffTypeDesc(); f.AutocallKIStrike1 = option.SpreadStrike1.OtcFormatUmPrice(isMoneyness); if (option.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption) { f.AutocallKIStrike2 = option.SpreadStrike.OtcFormatUmPrice(isMoneyness); } var KOObservationDates = option.KOObservationDates ?? string.Empty; var index = KOObservationDates.IndexOf(';'); f.KOObservationDates = index > 0 ? option.KOObservationDates.Substring(0, index) : KOObservationDates; f.KIObservationDates = option.ObservationDates; f.IsAnnualized = option.IsAnnualized2 ? "是" : "否"; f.AutocallKnockInOutStatus = option.KnockInOutStatusCn; f.AutocallKnockInOutDate = option.KnockInOutDate.OtcFormatDate(); } } //气囊结构 private static void SetAirbagOption(trade_airbag option, IntradayOptionPositionField f, bool isMoneyness) { if (option != null) { f.AirbagBarrier = option.Barrier.OtcFormatUmPrice(isMoneyness); f.AirbagIsDiscrete = option.IsDiscreteMonitored ? "是" : "否"; f.AirbagKIParticipationRate = option.KIParticipationRate.OtcFormatPercent(); f.AirbagHasPayoffLimit = option.HasPayoffLimit ? "是" : "否"; f.AirbagHighStrike = option.HighStrike.OtcFormatUmPrice(isMoneyness); f.CallPut = string.Empty; } } //区间累积 private static void SetRangeAccuralOption(trade_rangeaccrual option, IntradayOptionPositionField f, bool isMoneyness) { if (option != null) { f.CallPut = string.Empty; f.RangeAccrualLowerRange = option.LowerRange.OtcFormatUmPrice(isMoneyness); f.RangeAccrualUpperRange = option.UpperRange.OtcFormatUmPrice(isMoneyness); f.RangeAccrualBonusRate = option.BonusRate.OtcFormatPercent(4); f.ObservationDates = option.ObservationDates; } } //二元期权 private static void SetBianryOption(trade_binary_option option, IntradayOptionPositionField f, bool isMoneyness, bool isUsePremiumRate) { if (option != null) { f.BinaryPayoffType = option.PayoffType; f.BinaryUpperBarrier = option.UpperBarrier.OtcFormatUmPrice(isMoneyness); f.BinaryCashOrNothingAmount = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.CashOrNothingAmountRate, option.CashOrNothingAmount); f.BinaryCashOrNothingAmountHigh = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.CashOrNothingAmountHighRate, option.CashOrNothingAmountHigh); f.BinaryMonitorType = option.MonitorType; f.BinaryRebateType = TradeHelper.GetRebateTypeCn(option.RebateType); } } //双鲨期权 private static void SetDbSharkOption(trade_double_sharkfin_option option, IntradayOptionPositionField f, bool isMoneyness, bool isUsePremiumRate) { if (option != null) { f.DbSharkBarrierLow = option.BarrierLow.OtcFormatUmPrice(isMoneyness); f.DbSharkBarrierHigh = option.BarrierHigh.OtcFormatUmPrice(isMoneyness); f.DbSharkStrikeHigh = option.StrikeHigh.OtcFormatUmPrice(isMoneyness); f.DbSharkCallParticipationRate = option.CallParticipationRate.OtcFormatPercent(); f.DbSharkPutParticipationRate = option.PutParticipationRate.OtcFormatPercent(); f.DbSharkRebate = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.RebateRate, option.Rebate); f.DbSharkRebateHigh = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.RebateHighRate, option.RebateHigh); f.DbSharkRebateType = TradeHelper.GetRebateTypeCn(option.RebateType); f.DbSharkDiscrete = option.Discrete; f.ObservationDates = option.ObservationDates; f.DbsharkKnockInOutStatus = option.KnockInOutStatusCn; f.DbsharkKnockInOutDate = option.KnockInOutDate.OtcFormatDate(); } } //障碍期权 private static void SetBarrierOption(trade_barrier_option option, IntradayOptionPositionField f, bool isMoneyness, bool isUsePremiumRate) { if (option != null) { f.BarrierType = option.BarrierType; f.BarrierPrice = option.BarrierPrice.OtcFormatUmPrice(isMoneyness); f.BarrierPriceHigh = option.UpperBarrierPrice.OtcFormatUmPrice(isMoneyness); f.BarrierShift = option.BarrierShift ?? 0; f.BarrierRebate = OtcFormatHelper.FormatPremium(isUsePremiumRate, option.RebateRate, option.Rebate); f.BarrierRebateType = option.RebateTypeCn; f.BarrierDiscrete = option.Discrete; f.ObservationDates = option.ObservationDates; f.BarrierKnockInOutDate = option.KnockInOutDate.OtcFormatDate(); f.BarrierKnockInOutStatus = option.KnockInOutStatusCn; } } //亚式期权 private static void SetAsianOption(trade_asian_option option, IntradayOptionPositionField f) { if (option != null) { f.AsianAveragingPeriodStartDate = option.AveragingPeriodStartDate.OtcFormatDate(); f.AsianPayoffType = option.PayoffTypeCn; f.AsianStrikeType = option.StrikeTypeCn; f.AsianStrikeGearingFactor = option.StrikeGearingFactor.OtcFormatPercent(); } } #endregion #region----收益互换---- private IntradayPayOffSwapPositionField GetIntradayPayOffSwapPostionFields(trade td, double positionStockEqvNotional, InnerPosition pos) { var swap = td.trade_swap ?? new trade_swap(); var f = new IntradayPayOffSwapPositionField { StructureType = ConsGlobal.TradeType.PayoffSwap, TradeNumber = td.TradeNumber, AssetBookName = td.AssetBookName, TraderName = td.TraderName, ClientName = td.ClientName, TradeDate = td.TradeDate.OtcFormatDate(), ExerciseDate = td.ExerciseDate.OtcFormatDate(), Comments = td.Comments, StockEqvNotional = td.OriginalStockEqvNotional ?? 0, GetFixedProfit = swap.GetFixedProfit, GetLongShort = swap.GetLongShort, GetMarginRate = swap.GetMarginRate.OtcFormatFlex(minDecimals: 0, percent: true), GetTradePrice = swap.GetTradePrice, GetUnderlyingCode = swap.GetUnderlyingCode, GetSpotPrice = swap.GetSpotPrice, IsGetFloatingProfit = swap.IsGetFloatingProfit ? "是" : "否", IsPayFloatingProfit = swap.IsPayFloatingProfit ? "是" : "否", PayFixedProfit = swap.PayFixedProfit, PayLongShort = swap.PayLongShort, PayMarginRate = swap.PayMarginRate.OtcFormatPercent(), PaySpotPrice = swap.PaySpotPrice, PayTradePrice = swap.PayTradePrice, PayUnderlyingCode = swap.PayUnderlyingCode, PositionPnl = pos.PositionPnl, PositionPv = pos.PositionPv, PositionStockEqvNotional = positionStockEqvNotional, DailyPnl = pos.DailyPnl }; if (_context.TryGetClientInfo(td.ClientId, out var clientInfo)) { f.ClientName = clientInfo.Name; f.ClientNumber = clientInfo.Number; } return f; } #endregion #region----远期交易---- private IntradayForwardPositionField GetIntradayForwardPostionFields(trade td, InnerPosition pos) { var forward = td.trade_forward ?? new trade_forward(); var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var f = new IntradayForwardPositionField { StructureType = td.StructureType.TrimToNull() ?? ConsGlobal.TradeType.Forward, TradeNumber = td.TradeNumber, AssetBookName = td.AssetBookName, TraderName = td.TraderName, ClientName = td.ClientName, TradeDate = td.TradeDate.OtcFormatDate(), ExerciseDate = td.ExerciseDate.OtcFormatDate(), Comments = td.Comments, InitSpotPrice = td.SpotPrice ?? 0, AnnualMarginRate = forward.AnnualMarginRate.OtcFormatPercent(), AnnualStoragePrice = forward.AnnualStoragePrice, BasisGap = td.BasisGap, BasisUnderlyingCode = td.BasisUnderlyingCode, CallPut = ConsGlobal.CallPut.IsCall(td.CallPut) ? "多头" : "空头", NoRiskRate = td.NoRiskRate.OtcFormatPercent(), ObservationDates = forward.ObservationDates, Strike = td.Strike ?? 0, OpenFee = forward.OpenCommission, TotalFee = td.TradePrice ?? 0, TradeAmount = (td.OriginalNotional ?? 0) / pos.CountRatio, TradeSide = td.BuySell, UnderlyingCode = td.UnderlyingCode, UnderlyingName = underlying?.UnderlyingName, PositionPv = pos.PositionPv, PositionPnl = pos.PositionPnl, PositionTradeAmount = td.TradeAmount, DailyPnl = pos.DailyPnl }; if (_context.TryGetClientInfo(td.ClientId, out var clientInfo)) { f.ClientName = clientInfo.Name; f.ClientNumber = clientInfo.Number; } return f; } #endregion public ClientSettleBalancesSumInfo GetClientSettleBalancesSumInfo(IEnumerable clientSettleBalances) { var settleBalancesSumInfo = new ClientSettleBalancesSumInfo(); if (clientSettleBalances.Any()) { settleBalancesSumInfo.WinLossSum = clientSettleBalances.Sum(a => a.WinLoss) * -1; settleBalancesSumInfo.TdWinLossSum = clientSettleBalances.Sum(a => a.TdWinLoss) * -1; settleBalancesSumInfo.PositionPnlSum = clientSettleBalances.Sum(a => a.PositionPnl) * -1; } return settleBalancesSumInfo; } #region----内部类---- class InnerPosition { public trade Trade { get; set; } public double PositionPv { get; set; } public double PositionPnl { get; set; } public InnerPositionRisk Risk { get; set; } public double CountRatio { get; set; } = 1; public double ContractSize { get; set; } = 1; /// /// 当日盈亏 /// public double DailyPnl { get; set; } public int IsGroup { get; set; } public double? UnwindPercent { get; set; } public double? RealizedPnl { get; set; } } class InnerPositionRisk { public double Delta { get; set; } public double Gamma { get; set; } public double Theta { get; set; } public double Rho { get; set; } public double Vega { get; set; } public double DeltaCash { get; set; } public double GammaCash { get; set; } public double VegaCash { get; set; } public double Vol { get; set; } public double? SettlePrice { get; set; } } #endregion } }