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