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; }
}
}
}