namespace YLErp.Modules.TradeModule { /// /// 交易现金流水数据提供 /// (逻辑迁移自tradecontroller.tradeQuery) /// public class TradeCashProvider : YLBaseService { IEnumerable _tpdatas; Dictionary _cashDic; public TradeCashProvider(YLBaseService baseService) : base(baseService) { } public TradeCashProvider(OptUserInfo userInfo) : base(userInfo) { } /// /// 必须要初始化 /// public TradeCashProvider Initialize(IEnumerable tradeIds) { if (tradeIds is null) { throw new ArgumentNullException(nameof(tradeIds)); } if (!tradeIds.Any(n => n > 0)) { _tpdatas = Enumerable.Empty(); _cashDic = new Dictionary(0); return this; } //获取结构化交易对应的子交易ID var idSet = new HashSet(tradeIds); var tpQuery = from t in DbContext.trade where t.ParentTradeId > 0 && tradeIds.Contains(t.ParentTradeId) orderby t.ParentTradeId select new TpData { TradeId = t.id, ParentTradeId = t.ParentTradeId, IsGroup = t.IsGroup }; _tpdatas = tpQuery.ToArray(); foreach (var item in _tpdatas) { idSet.Add(item.TradeId); if (item.IsGroup == 0) { idSet.Remove(item.ParentTradeId); } } //获取tradecash数据 _cashDic = DbContext.trade_cash.Where(t => t.ValidState != ConsGlobal.InValid && idSet.Contains(t.TradeId) && !t.IsDeleted) .ToArray().GroupBy(n => n.TradeId).ToDictionary(n => n.Key, m => m.OrderBy(n => n.ValueDate).ThenBy(n => n.id).ToArray()); return this; } /// /// 必须要初始化 /// public TradeCashProvider Initialize(IEnumerable tradeIds,List childList) { if (tradeIds is null) { throw new ArgumentNullException(nameof(tradeIds)); } if (!tradeIds.Any(n => n > 0)) { _tpdatas = Enumerable.Empty(); _cashDic = new Dictionary(0); return this; } //获取结构化交易对应的子交易ID var idSet = new HashSet(tradeIds); if (childList != null && childList.Count > 0) { var tpQuery = from t in childList where t.ParentTradeId > 0 && tradeIds.Contains(t.ParentTradeId) orderby t.ParentTradeId select new TpData { TradeId = t.id, ParentTradeId = t.ParentTradeId, IsGroup = t.IsGroup }; _tpdatas = tpQuery.ToArray(); } else { _tpdatas = new List(); } foreach (var item in _tpdatas) { idSet.Add(item.TradeId); if (item.IsGroup == 0) { idSet.Remove(item.ParentTradeId); } } //获取tradecash数据 _cashDic = DbContext.trade_cash.Where(t => t.ValidState != ConsGlobal.InValid && idSet.Contains(t.TradeId) && !t.IsDeleted) .ToArray().GroupBy(n => n.TradeId).ToDictionary(n => n.Key, m => m.OrderBy(n => n.ValueDate).ThenBy(n => n.id).ToArray()); return this; } /// /// 获取交易了结详情 /// public TradeCashUnwindDetail GetUnwindDetail(trade trade, string tradeType = null) { if (_cashDic == null) { throw new ServiceException("尚未初始化"); } if (_cashDic.TryGetValue(trade.id, out var tcList)) { var tradeCashUnwindDetail = GetUnwindDetail(trade.id, tradeType, tcList); if (trade.IsGroup == 1) { var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeId == trade.id && x.ValidState != "InValid" && x.Action != ClientCashInCashOut.系统操作_期权费).ToList(); var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList(); var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList(); tradeCashUnwindDetail.UnWindTotalFee = childTradeCashs.Sum(x => x.Amount); tradeCashUnwindDetail.RealizedPnl = tradeCashUnwindDetail.UnWindTotalFee + childTradeCashs.Sum(x => (x.UnwindPercentRate ?? 0) * (childTrades.FirstOrDefault(y => y.id == x.TradeId)?.TradePrice ?? 0) * (childTrades.FirstOrDefault(y => y.id == x.TradeId).BuySell == "买入" ? -1 : 1)); } return tradeCashUnwindDetail; } //使用结构化交易处理方式 TradeCashUnwindDetail detail = null; foreach (var item in _tpdatas) { if (item.ParentTradeId == trade.id && trade.IsGroup == 0) { if (_cashDic.TryGetValue(item.TradeId, out var tcList2)) { var detail2 = GetUnwindDetail(item.TradeId, tradeType, tcList2); if (detail == null) { detail = detail2; } else { var RealizedPnl = detail.RealizedPnl + detail2.RealizedPnl; var UnWindTotalFee = detail.UnWindTotalFee + detail2.UnWindTotalFee; if (detail.UnWindDate < detail2.UnWindDate || (detail.UnWindDate == detail2.UnWindDate && detail2.LastTcId > detail.LastTcId)) { detail = detail2; //去了结日期最晚的数据 } detail.RealizedPnl = RealizedPnl; detail.UnWindTotalFee = UnWindTotalFee; } } } else if (detail != null) { break; } } return detail; } /// /// 批量获取交易了结详情 /// public List BatchGetUnwindDetail(IEnumerable tradeList, List childList) { if (_cashDic == null) { throw new ServiceException("尚未初始化"); } var res=new List(); var isGroupTradeIds = tradeList.Where(p => p.IsGroup == 1).Select(p => p.id).Distinct().ToList(); List tradeCashList =null; if(isGroupTradeIds!=null&& isGroupTradeIds.Count > 0) { tradeCashList = DbContext.trade_cash.Where(x => isGroupTradeIds.Contains(x.ParentTradeId) && x.ValidState != "InValid" && x.Action != ClientCashInCashOut.系统操作_期权费).ToList(); } if (tradeCashList == null) { tradeCashList = new List(); } foreach (var trade in tradeList) { if (_cashDic.TryGetValue(trade.id, out var tcList)) { var tradeCashUnwindDetail = GetUnwindDetail(trade.id, "", tcList); if (trade.IsGroup == 1) { var childTradeCashs = tradeCashList.Where(x => x.ParentTradeId == trade.id).ToList(); var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList(); var childTrades = childList.Where(x => childTradeIds.Contains(x.id)).ToList(); tradeCashUnwindDetail.UnWindTotalFee = childTradeCashs.Sum(x => x.Amount); tradeCashUnwindDetail.RealizedPnl = tradeCashUnwindDetail.UnWindTotalFee + childTradeCashs.Sum(x => (x.UnwindPercentRate ?? 0) * (childTrades.FirstOrDefault(y => y.id == x.TradeId)?.TradePrice ?? 0) * (childTrades.FirstOrDefault(y => y.id == x.TradeId).BuySell == "买入" ? -1 : 1)); } res.Add(tradeCashUnwindDetail); continue; } //使用结构化交易处理方式 TradeCashUnwindDetail detail = null; foreach (var item in _tpdatas) { if (item.ParentTradeId == trade.id && trade.IsGroup == 0) { if (_cashDic.TryGetValue(item.TradeId, out var tcList2)) { var detail2 = GetUnwindDetail(item.TradeId, "", tcList2); if (detail == null) { detail = detail2; } else { var RealizedPnl = detail.RealizedPnl + detail2.RealizedPnl; var UnWindTotalFee = detail.UnWindTotalFee + detail2.UnWindTotalFee; if (detail.UnWindDate < detail2.UnWindDate || (detail.UnWindDate == detail2.UnWindDate && detail2.LastTcId > detail.LastTcId)) { detail = detail2; //去了结日期最晚的数据 } detail.RealizedPnl = RealizedPnl; detail.UnWindTotalFee = UnWindTotalFee; } } } else if (detail != null) { break; } } if (detail != null) { res.Add(detail); } } return res; } private TradeCashUnwindDetail GetUnwindDetail(int tradeId, string tradeType, IEnumerable tcList) { var detail = new TradeCashUnwindDetail(tradeId); trade_cash tcFirst = null, tcLast = null; foreach (var tc in tcList) { if (tc.Action == "系统操作-期权费") { tcFirst = tc; continue; } tcLast = tc; if (tc.Action == "系统操作-行权费" || tc.Action == "系统操作-平仓费" || tc.IsLastAction) { detail.UnWindTimes++; } if (tc.Action == "系统操作-行权费") { tc.ActionTradeAmount = tc.TradeAmount ?? 0; } else { tc.ActionTradeAmount = tc.UnwindTradeAmount ?? 0; } detail.UnWindTotalFee += tc.Amount; detail.UnWindTotalAmount += tc.ActionTradeAmount; detail.UnWindPercent += tc.UnwindPercentRate ?? 0; } if (tcLast != null) { detail.LastTcId = tcLast.id; if (tcLast.Action == "系统操作-行权费") { //到期收益/到期数目。 到期权利金即payoff=到期收益单价 if (Math.Abs(tcLast.ActionTradeAmount) > 0) { detail.UnWindSinglePrice = tcLast.Amount / tcLast.ActionTradeAmount; } } else { //平仓权利金即平仓单价 detail.UnWindSinglePrice = tcLast.UnwindPrice ?? 0; } detail.UnWindUnderlyingPrice = tcLast.FinalPrice ?? 0; detail.UnWindDate = tcLast.HappenedDate ?? tcLast.ValueDate; } detail.RealizedPnl = detail.UnWindTotalFee + (tcFirst == null ? 0 : tcFirst.Amount * detail.UnWindPercent); return detail; } class TpData { public int TradeId { get; set; } public int ParentTradeId { get; set; } public int IsGroup { get; set; } public override string ToString() { return TradeId + "--" + ParentTradeId; } } } /// /// 交易了结详情 /// public class TradeCashUnwindDetail { public TradeCashUnwindDetail(int tradeId) { TradeId = tradeId; } /// /// 交易ID /// public int TradeId { get; set; } /// /// 交易现金数据ID(最后一次) /// public int LastTcId { get; set; } /// /// 了结百分比(总计) /// public double UnWindPercent { get; set; } /// /// 了结总数 /// public double UnWindTotalAmount { get; set; } /// /// 了结总额 /// public double UnWindTotalFee { get; set; } /// /// 了结次数 /// public int UnWindTimes { get; set; } /// /// 了结日期(最后一次) /// public DateTime? UnWindDate { get; set; } /// /// 了结数量(最后一次) /// public double UnWindAmount { get; set; } /// /// 了结单价(最后一次) /// public double UnWindSinglePrice { get; set; } /// /// 了结标的价格(最后一次) /// public double UnWindUnderlyingPrice { get; set; } /// /// 实现盈亏(整体) /// public double RealizedPnl { get; set; } public override string ToString() { return TradeId.ToString(); } } }