using System.Data; using YLErp.Commons; using YLErp.DBModels.Helpers; using YLErp.Models; using YLErp.Modules.DataProviderModule; using YLErp.Modules.TradeModule; namespace YLErp.Modules.EodModule.QueryModule { /// /// 日终清算服务 /// public class EodTradePositionApiService : YLBaseService { public EodTradePositionApiService(EodSettleInfoQueryContext context) : base(context) { } /// /// 查询场外期权持仓列表 /// public EodTradePositionResult GetEodPositions(EodSettleInfoRequest req, List clientIdsOfInside = null) { var valueDate = req.ValueDate; var result = new EodTradePositionResult { SwapPositions = new List(), OptionPositions = new List(), ForwardPositions = new List() }; var IsPVRounded = PS.Config.IsPVRounded; valueDate = valueDate.Date; var eodQuery = DbContext.eod_trade.AsQueryable(); if (clientIdsOfInside != null) { eodQuery = eodQuery.Where(a => !clientIdsOfInside.Contains(a.ClientId)); } var query = from et in eodQuery join t in DbContext.trade on et.TradeId equals t.id join etp in DbContext.eod_trade_position on new { et.TradeId, et.ValueDate } equals new { etp.TradeId, etp.ValueDate } into etp_s from etp in etp_s.DefaultIfEmpty() join etr in DbContext.eod_trade_risk on new { et.TradeId, et.ValueDate } equals new { etr.TradeId, etr.ValueDate } into etr_s from etr in etr_s.DefaultIfEmpty() where et.ValueDate == valueDate && t.ClientId > 0 select new InnerPosition { TradeId = et.TradeId, TradeJson = et.TradeJson, CallPut = t.OptionType, TradeAmount = etp == null ? 0 : etp.Amount, PositionPv = etp == null ? 0 : IsPVRounded ? etp.RoundedPv : etp.Pv, PositionPnl = etp == null ? 0 : IsPVRounded ? etp.RoundedPositionPnL : etp.PositionPnL, ParentTradeId = t.ParentTradeId, IsGroup = t.IsGroup, DailyPnl = etp == null ? 0 : etp.DailyPnL, Risk = etr == null ? null : new InnerPositionRisk { Delta = etr.Delta, Gamma = etr.Gamma, Theta = etr.Theta, Rho = etr.Rho, Vega = etr.Vega, DeltaCash = etr.DeltaCash, GammaCash = etr.GammaCash, VegaCash = etr.VegaCash, Vol = etr.Vol } }; //因为query还在读取中,所以不要用同一个dbcontext var extendService = new TradeExtendService(OptUser); var eodPriceProvider = new EodPriceProvider(valueDate).Initialize(); var posList = query.ToArray(); var groupSumDic = new Dictionary(); foreach (var pos in posList) { if (pos.IsGroup == 2 && pos.ParentTradeId > 0) { if (!groupSumDic.TryGetValue(pos.ParentTradeId, out var p)) { groupSumDic[pos.ParentTradeId] = p = new InnerPosition(); } p.PositionPv += pos.PositionPv; p.PositionPnl += pos.PositionPnl; p.DailyPnl += pos.DailyPnl; } } foreach (var pos in posList) { var td = TradeHelper2.Deserialize(pos.TradeJson); if (td == null) { td = DbContext.trade.FirstOrDefault(n => n.id == pos.TradeId); } if (td == null) { continue; } 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.TradeAmount = td.Notional; } else { continue; } } else if (td.IsGroup == 2) { continue; } extendService.SetTradeExtend(new[] { td }, false); var un = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); if (un != null) { pos.TradeAmount /= un.CountRatio; pos.CountRatio = un.CountRatio; pos.Risk.DeltaInLots = un.ContractSize != 0 ? pos.Risk.Delta / un.ContractSize : pos.Risk.Delta; } if (td.TradeType == "收益互换") { var f = GetEodPayOffSwapPostionFields(td, td.StockEqvNotional, pos); result.SwapPositions.Add(f); f.SettlePrice = eodPriceProvider.GetPrice(f.GetUnderlyingCode.TrimToNull() ?? f.PayUnderlyingCode , settlementType: PS.Config.Company == Configuration.CompanyEnum.厦门象屿 ? SettlementTypeEnum.SettlePrice : SettlementTypeEnum.ClosePrice); } else if (td.TradeType == "远期") { var f = GetEodForwardPostionFields(td, pos); result.ForwardPositions.Add(f); f.SettlePrice = eodPriceProvider.GetPrice(f.UnderlyingCode , settlementType: PS.Config.Company == Configuration.CompanyEnum.厦门象屿 ? SettlementTypeEnum.SettlePrice : SettlementTypeEnum.ClosePrice); } else { var f = GetEodOptionPostionFields(td, pos); result.OptionPositions.Add(f); f.SettlePrice = eodPriceProvider.GetPrice(f.UnderlyingCode , settlementType: PS.Config.Company == Configuration.CompanyEnum.厦门象屿 ? SettlementTypeEnum.SettlePrice : td.SettlementType); } } return result; } #region----场外期权---- private EodOptionPositionField GetEodOptionPostionFields(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 EodOptionPositionField { TradeType = td.TradeType, StructureType = td.TradeMultipleType, TradeNumber = td.TradeNumber, AssetBookName = td.AssetBookName, TraderName = td.TraderName, ClientName = td.ClientName, ExerciseMode = td.ExerciseModeCn, CallPut = pos.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 = pos.TradeAmount, DailyPnl = pos.DailyPnl }; if (pos.Risk != null) { var risk = pos.Risk; f.Delta = risk.Delta; f.DeltaInLots = risk.DeltaInLots; 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); break; case "累计期权": SetAccumulatorOption(td.trade_accumulator_option, f); 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.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, EodOptionPositionField f) { 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(f.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, EodOptionPositionField f, bool isMoneyness) { 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, f.CallPut); f.SnowballKOStrike1 = option.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; case KOPayoffTypeEnum.ToSpreadOption: f.SnowballKOPayoffType = KOPayoffTypeEnumHelper.GetDesc(option.KOPayoffType, f.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, EodOptionPositionField 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, EodOptionPositionField 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, EodOptionPositionField 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, EodOptionPositionField 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, EodOptionPositionField 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, EodOptionPositionField 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, EodOptionPositionField 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 EodPayOffSwapPositionField GetEodPayOffSwapPostionFields(trade td, double positionStockEqvNotional, InnerPosition pos) { var swap = td.trade_swap ?? new trade_swap(); var f = new EodPayOffSwapPositionField { 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 EodForwardPositionField GetEodForwardPostionFields(trade td, InnerPosition pos) { var forward = td.trade_forward ?? new trade_forward(); var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var f = new EodForwardPositionField { 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 = pos.TradeAmount, DailyPnl = pos.DailyPnl, CountRatio = pos.CountRatio }; if (_context.TryGetClientInfo(td.ClientId, out var clientInfo)) { f.ClientName = clientInfo.Name; f.ClientNumber = clientInfo.Number; } return f; } #endregion /// /// 查询场内期权持仓列表 /// public IEnumerable SearchExOptionTradeListForExport(DateTime valueDate) { var IsPVRounded = PS.Config.IsPVRounded; var umSource = DataCacheProvider.GetUnderlyingDataSource(); var exOptionSource = DataCacheProvider.GetExchangeListOptionDataSource(); var volFormat = PS.Config.ErpElement.VolMoreAccurate ? "P4" : "P2"; valueDate = valueDate.Date; var query = from etp in DbContext.eod_trade_position join etr in DbContext.eod_trade_risk on etp.TradeId equals etr.TradeId where etp.ValueDate == valueDate && etr.ValueDate == valueDate && etp.TradeType == "场内期权" select new { etp.UnderlyingCode, etp.ExchangeOptionCode, etp.Amount, etp.PositionType, PositionPv = IsPVRounded ? etp.RoundedPv : etp.Pv, PositionPnl = IsPVRounded ? etp.RoundedPositionPnL : etp.PositionPnL, etr.Vol }; var list = new List(); foreach (var item in query) { var exoption = exOptionSource.GetData(item.ExchangeOptionCode); var f = new EodExOptionPositionExportFields { OptionCode = item.ExchangeOptionCode, ExerciseMode = exoption?.ExerciseMode, Strike = (exoption?.Strike)?.ToString("F4"), UnderlyingCode = item.UnderlyingCode, PositionType = item.PositionType, PositionPnl = Convert.ToDouble(item.PositionPnl).OtcFormatMoney(), PositionPv = Convert.ToDouble(item.PositionPv).OtcFormatMoney(), PositionTradeAmount = item.Amount.OtcFormatNotional(), PositionVol = item.Vol.ToString(volFormat) }; list.Add(f); } return list; } public ClientSettleBalancesSumInfo GetClientSettleBalancesSumInfo(IEnumerable clientSettleBalances) { ClientSettleBalancesSumInfo 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; } class InnerPosition { public int TradeId { get; set; } public int ParentTradeId { get; set; } public string TradeJson { get; set; } public string CallPut { get; set; } public double TradeAmount { 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 DailyPnl { get; set; } public int IsGroup { get; set; } } class InnerPositionRisk { public double Delta { get; set; } public double DeltaInLots { 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; } } } }