using BaseOUDAL;
using Qdp.Foundation.Implementations;
using System.Data;
using System.Linq.Expressions;
using YLErp.BLL;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Enums;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Models;
using YLErp.Modules.DataCacheModule;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.EodModule;
using YLErp.Modules.TradeModule.DealModule;
using YLErp.Modules.TradeModule.QueryModule;
using YLErp.Modules.TradeModule.QueryModule.Dto;
using YLErp.Modules.TradeRiskCalcModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule
{
///
/// 当日交易(当日成交、提前终止、当日到期、明日到期)查询服务
///
public class TodayTradeQueryService : YLBaseService
{
public TodayTradeQueryService(OptUserInfo userInfo) : base(userInfo)
{
}
public TdTradesCountSum GetTdTradesCountSum(List userAssets, List userClients, OtcTradeType otcTradeType)
{
var sum = new TdTradesCountSum();
var curTradingDate = SystemValueDate;
var basePredicate = PredicateBuilder.Create(t => t.ValidState != "InValid"
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2);
switch (otcTradeType)
{
case OtcTradeType.Forward:
basePredicate = basePredicate.And(t => t.TradeType == "远期");
break;
case OtcTradeType.EquitySwap:
basePredicate = basePredicate.And(t => t.TradeType == "收益互换");
break;
default:
basePredicate = basePredicate.And(t => t.TradeType != "远期" && t.TradeType != "收益互换" && t.ClientId > 0);
break;
}
var dateEnd = curTradingDate.AddDays(1);
//---------------------------------------------
// 当日到期
//---------------------------------------------
//如果前一天是假日,要显示包含假日的交易
var req = new TdTradeQueryModel
{
OtcTradeType = otcTradeType,
TabIndex = (int)TradeTabIndexEnum.今日到期,
UserAssets = userAssets,
UserClients = userClients
};
var predicate = BuildPredicate(req, curTradingDate);
sum.TdExerciseCount = DbContext.trade.Where(predicate).Count();
//---------------------------------------------
// 明日到期
//---------------------------------------------
var nextDay = QdpCalendarHelper.GetNonHoliday(curTradingDate.AddDays(1));
var excludeStatusArr = new[] { ConsTrade.已平仓, ConsTrade.已到期, ConsTrade.已执行 };
predicate = PredicateBuilder.Create(t => t.ExerciseDate == nextDay
&& !excludeStatusArr.Contains(t.TradeStatus)).And(basePredicate);
sum.TmExerciseCount = DbContext.trade.Where(predicate).Count();
//---------------------------------------------
// 当日提前终止
//---------------------------------------------
IQueryable baseTrade;
//交易员对应的簿记账户筛选或者客户经理对应的客户筛选
if (userAssets != null || userClients != null)
{
baseTrade = DbContext.trade.Where(t => userAssets.Contains(t.AssetId) || userClients.Contains(t.ClientId)).AsQueryable();
}
else
{
baseTrade = DbContext.trade.AsQueryable();
}
if (otcTradeType == OtcTradeType.Forward)
{
baseTrade = baseTrade.Where(x => x.TradeType == "远期");
var query1 = from tc in DbContext.trade_cash
join t in baseTrade on tc.TradeId equals t.id
where tc.ValueDate == curTradingDate
&& tc.Action == ClientCashInCashOut.系统操作_平仓费 && (t.TradeStatus == "平仓待复核" || tc.ValidState != ConsGlobal.InValid)
&& !tc.IsDeleted && tc.BarrierPrice == null
&& t.ValidState != "InValid"
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2
select t.id;
sum.TdEarlyStoppedCount = query1.Count();
}
else if (otcTradeType == OtcTradeType.EquitySwap)
{
baseTrade = baseTrade.Where(x => x.TradeType == "收益互换");
var query1 = from tc in DbContext.trade_cash
join t in baseTrade on tc.TradeId equals t.id
where tc.ValueDate == curTradingDate
&& (tc.Action == ClientCashInCashOut.系统操作_平仓费 || tc.Action == ClientCashInCashOut.系统操作_互换) && (t.TradeStatus == "平仓待复核" || t.TradeStatus == "互换待复核" || tc.ValidState != "InValid")
&& !tc.IsDeleted && tc.BarrierPrice == null
&& t.ValidState != "InValid"
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2
select t.id;
sum.TdEarlyStoppedCount = query1.Count();
}
else
{
baseTrade = DbContext.trade.Where(x => x.TradeType != "远期" && x.TradeType != "收益互换");
var query1 = from tc in DbContext.trade_cash
join t in baseTrade on tc.TradeId equals t.id
where tc.ValueDate == curTradingDate
&& tc.Action == ClientCashInCashOut.系统操作_平仓费 && (t.TradeStatus == "平仓待复核" || tc.ValidState != "InValid")
&& !tc.IsDeleted && tc.BarrierPrice == null
&& t.ValidState != ConsGlobal.InValid
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2
select t.id;
var query2 = from tc in DbContext.trade_cash
join t in baseTrade on tc.TradeId equals t.id
where tc.ValueDate == curTradingDate
&& tc.Action == ClientCashInCashOut.系统操作_行权费 && (t.TradeStatus == "行权待复核" || tc.ValidState != "InValid" && t.TradeStatus == ConsTrade.已执行)
&& t.ExerciseMode == "American" && tc.ExerciseWay != "到期行权"
&& !tc.IsDeleted && tc.BarrierPrice == null //不包含敲出数据
&& t.ValidState != ConsGlobal.InValid
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2
select t.id;
var dd1 = query1.Count();
var dd2 = query2.Count();
sum.TdEarlyStoppedCount = dd1 + dd2;
}
//---------------------------------------------
// 当日成交
//---------------------------------------------
predicate = PredicateBuilder.Create(t => t.TradeDate == curTradingDate).And(basePredicate);
sum.TdCreatedCount = DbContext.trade.Where(predicate).Count();
//---------------------------------------------
// 当日敲出
//---------------------------------------------
//var knockedOutPredicate = PredicateBuilder.Create(t => t.KnockInOutDate < dateEnd && t.KnockInOutDate >= curTradingDate && t.KnockInOutStatus == trade_barrier_option.KnockedOut);
//sum.TdKnockedOutCount = DbContext.trade_barrier_option.Where(knockedOutPredicate).Count();
var knockedOutQuery = from tc in DbContext.trade_cash
join t in DbContext.trade on tc.TradeId equals t.id
join ao in DbContext.autocall_observation on new { EndDate = tc.ValueDate, TradeId = t.id } equals new { ao.EndDate, ao.TradeId } into tempAo
from ao in tempAo.DefaultIfEmpty()
where tc.BarrierPrice != null //障碍期权敲出
&& tc.HappenedDate >= curTradingDate && tc.HappenedDate < dateEnd
&& t.ValidState != "InValid"
&& t.TradeType != "结构化交易"
&& !tc.IsDeleted
select 1;
sum.TdKnockedOutCount = knockedOutQuery.Count();
return sum;
}
//替换TradeBLL.SearchListForTradeConfirm
///
/// 获取当日成交/当日到期/明日到期数据列表
///
public SearchListResult GetConfirmList(TdTradeQueryModel req)
{
var valueDate = SystemValueDate;
var predicate = BuildPredicate(req, valueDate);
var tQuery = DbContext.trade.Where(predicate);
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "TradeNumber";
req.sord = "desc";
}
var sList = tQuery.ToSearchList(req);
if (sList.rows != null && sList.rows.Any())
{
//var realtimerisk = realtime_trade_riskBLL.GetAllrealtime_trade_valueModel();
//var tradeIds = sList.rows.Select(x => x.id).ToList();
//var tradeCashQuery = from tc in DbContext.trade_cash
// where tradeIds.Contains(tc.TradeId) && (tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_票息 || tc.Action == ClientCashInCashOut.系统操作_互换) && tc.ValidState != "InValid"
// && !tc.IsDeleted && tc.Status == TradeCashStatusEnum.已执行 && tc.BarrierPrice == null //不包含敲出数据
// select tc;
//var tradeCashDatas = tradeCashQuery.ToArray();
//未用到
//var underlyingIds = sList.rows.Select(x => x.UnderlyingId).ToList();
//var underlyings = DbContext.underlying_manager.Where(x => underlyingIds.Contains(x.id)).ToArray();
//var underlyingTypeIds = underlyings.Select(x => x.UnderlyingTypeId).Distinct();
//var varietys = DbContext.variety.Where(x => underlyingTypeIds.Contains(x.id)).ToArray();
var result = TradeRiskCalcTaskRunner.GetCalcResult("对冲");
//new TradeDalModule.TradeDalService(this).SetStructureInfo(sList.rows);
var tradeIdList = sList.rows.Select(p => p.id).Distinct().ToList();
var realtimerisk = realtime_trade_riskBLL.GetByTradeIds(tradeIdList);
if (realtimerisk == null)
{
realtimerisk = new List();
}
List tradeCashList = null;
var tradeCacheBatchGetService = new BatchGetTradeRelationDataService();
if (tradeIdList != null && tradeIdList.Count > 0)
{
//tradeCashList = DbContext.trade_cash.AsNoTracking().Where(t => tradeIdList.Contains(t.TradeId) && t.ValidState != "Invalid" && t.BarrierPrice == null && !t.IsDeleted).ToList();
tradeCashList = tradeCacheBatchGetService.GetListByWhere(t => tradeIdList.Contains(t.TradeId) && t.ValidState != "Invalid" && t.BarrierPrice == null && !t.IsDeleted, DbContext.trade_cash);
}
if (tradeCashList == null)
{
tradeCashList = new List();
}
var tradeCashDatas = tradeCashList.Where(tc => (tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_票息 || tc.Action == ClientCashInCashOut.系统操作_互换) && tc.Status == TradeCashStatusEnum.已执行).ToList();
if (tradeCashDatas == null)
{
tradeCashDatas = new List();
}
List childTradeCashList = null;
var parentTradeIds = sList.rows.Where(p => p.IsGroup == 1).Select(p => p.id).Distinct().ToList();
List childTradeList = null;
if (parentTradeIds != null && parentTradeIds.Count > 0)
{
childTradeList = DbContext.trade.AsNoTracking().Where(p => parentTradeIds.Contains(p.ParentTradeId) && p.ParentTradeId > 0).Select(p => new TradeQueryDto
{
id = p.id,
TradePrice = p.TradePrice,
BuySell = p.BuySell,
ParentTradeId = p.ParentTradeId,
ValidState = p.ValidState
}).ToList();
if (childTradeList != null && childTradeList.Count > 0)
{
var childTradeIds = childTradeList.Select(p => p.id).Distinct().ToList();
//childTradeCashList= DbContext.trade_cash.AsNoTracking().Where(t => childTradeIds.Contains(t.TradeId)).ToList();
var parentTradeCashIdList = tradeCashList.Where(p => parentTradeIds.Contains(p.TradeId) && p.Action != ClientCashInCashOut.系统操作_期权费).Select(p => p.id).Distinct().ToList();
if (parentTradeCashIdList != null && parentTradeCashIdList.Count > 0)
{
//childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(t => parentTradeCashIdList.Contains(t.ParentTradeCashId)).ToList();
//childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(t => childTradeIds.Contains(t.TradeId) && parentTradeCashIdList.Contains(t.ParentTradeCashId)).ToList();
childTradeCashList = tradeCacheBatchGetService.GetListByWhere(t => childTradeIds.Contains(t.TradeId) && parentTradeCashIdList.Contains(t.ParentTradeCashId), DbContext.trade_cash);
}
}
}
if (childTradeCashList == null)
{
childTradeCashList = new List();
}
if (childTradeList == null)
{
childTradeList = new List();
}
var forwardTradeIds = sList.rows.Where(p => "远期".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
List tradeForwardList = null;
if (forwardTradeIds != null && forwardTradeIds.Count > 0)
{
tradeForwardList = DbContext.trade_forward.AsNoTracking().Where(p => forwardTradeIds.Contains(p.TradeId)).ToList();
}
if (tradeForwardList == null)
{
tradeForwardList = new List();
}
var swapTradeIds = sList.rows.Where(p => "收益互换".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
List tradeCashSwapList = null;
if (swapTradeIds != null && swapTradeIds.Count > 0)
{
var swapTradeCashIds = tradeCashList.Where(t => t.Action == ClientCashInCashOut.系统操作_互换).Select(d => d.id).Distinct().ToList();
if (swapTradeCashIds != null && swapTradeCashIds.Count > 0)
{
tradeCashSwapList = DbContext.trade_cash_swap.AsNoTracking().Where(p => swapTradeCashIds.Contains(p.TradeCashId)).ToList();
}
}
if (tradeCashSwapList == null)
{
tradeCashSwapList = new List();
}
Dictionary keyValueSalesC = null;
using (var saleCService = new SalesModule.SalesCommissionDataService(OptUser))
{
keyValueSalesC = saleCService.GetTradeCommissionInfoByTradeIds(tradeIdList);
}
List syntheticUnderlyingList = null;
var syntheticUnderlyingCodeList = sList.rows.Where(p => "合成价差期权".Equals(p.TradeType)).Select(p => p.UnderlyingCode).Distinct().ToList();
if (syntheticUnderlyingCodeList != null && syntheticUnderlyingCodeList.Count > 0)
{
syntheticUnderlyingList = DbContext.synthetic_underlying.AsNoTracking().Where(p => syntheticUnderlyingCodeList.Contains(p.Name)).ToList();
}
if (syntheticUnderlyingList == null)
{
syntheticUnderlyingList = new List();
}
foreach (var tradeObj in sList.rows)
{
var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(tradeObj.UnderlyingCode);
if (tradeObj.TradeStatus == "已执行" || tradeObj.TradeStatus == "已到期" || tradeObj.TradeStatus == "已平仓")
{
tradeObj.TradeAmount = 0;
}
var tradeCash = tradeCashDatas.OrderByDescending(x => x.id).FirstOrDefault(d => d.TradeId == tradeObj.id);
ProcessTrade(tradeObj, tradeCash, underlying, syntheticUnderlyings: syntheticUnderlyingList);//最后一笔到期结算流水
if (tradeObj.TradeType == "远期")
{
//tradeObj.trade_forward = DbContext.trade_forward.First(x => x.TradeId == tradeObj.id);
tradeObj.trade_forward = tradeForwardList.First(x => x.TradeId == tradeObj.id);
}
//var cashTrades = DbContext.trade_cash.Where(t => t.ValidState != "Invalid" && t.TradeId == tradeObj.id && t.BarrierPrice == null && !t.IsDeleted).ToList();
var cashTrades = tradeCashList.Where(t => t.TradeId == tradeObj.id).ToList();
var cashTradesExercise = cashTrades.Where(t => t.Action == ClientCashInCashOut.系统操作_行权费).ToList();
var cashTradesUnwind = cashTrades.Where(t => t.Action == ClientCashInCashOut.系统操作_平仓费).ToList();
if (tradeObj.TradeType == "收益互换")
{
var cashTradesSwap = cashTrades.Where(t => t.Action == ClientCashInCashOut.系统操作_互换).ToList();
var lastTradeCashSwap = cashTradesSwap.OrderByDescending(x => x.ValueDate).FirstOrDefault();
if (lastTradeCashSwap != null)
{
//tradeObj.trade_cash.trade_cash_swap = DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == lastTradeCashSwap.id);
tradeObj.trade_cash.trade_cash_swap = tradeCashSwapList.FirstOrDefault(x => x.TradeCashId == lastTradeCashSwap.id);
}
tradeObj.RealizedPnl = cashTradesSwap.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesSwap.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1)
+ cashTradesUnwind.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesUnwind.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1);
}
else
{
tradeObj.RealizedPnl = cashTradesExercise.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesExercise.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1)
+ cashTradesUnwind.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesUnwind.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1);
if (tradeObj.IsGroup == 1)
{
var cashTradeIds = cashTrades.Where(t => t.Action != ClientCashInCashOut.系统操作_期权费).Select(t => t.id).ToArray();
//var childrenCashTradesSettle = DbContext.trade_cash.Where(t => cashTradeIds.Contains(t.ParentTradeCashId)).ToList();
var childrenCashTradesSettle = childTradeCashList.Where(t => cashTradeIds.Contains(t.ParentTradeCashId)).ToList();
var childrenTradeIds = childrenCashTradesSettle.Select(x => x.TradeId).Distinct().ToArray();
//var childrenTrades = DbContext.trade.Where(t => childrenTradeIds.Contains(t.id));
var childrenTrades = childTradeList.Where(t => childrenTradeIds.Contains(t.id));
var realizedPnl = 0.0;
childrenCashTradesSettle.ForEach(x =>
{
var trade = childrenTrades.FirstOrDefault(y => y.id == x.TradeId);
realizedPnl += x.Amount - ((trade?.TradePrice * x.UnwindPercentRate * ((trade?.BuySell == "卖出") ? -1 : 1)) ?? 0);
});
tradeObj.RealizedPnl = realizedPnl;
}
}
if (result != null && result.TradeRiskList != null)
{
if (tradeObj.IsGroup == 1)
{
//var childTradeIds = DbContext.trade.Where(y => y.ParentTradeId == tradeObj.id && y.ValidState != "InValid").Select(y => y.id).ToList();
var childTradeIds = childTradeList.Where(y => y.ParentTradeId == tradeObj.id && y.ValidState != "InValid").Select(y => y.id).ToList();
var risks = result.TradeRiskList.Where(x => childTradeIds.Contains(x.TradeId));
tradeObj.DeltaInLots = risks != null && risks.Any() ? risks.Sum(x => x.DeltaInLots) : 0;
}
else
{
var risk = result.TradeRiskList.FirstOrDefault(x => x.TradeId == tradeObj.id);
tradeObj.DeltaInLots = risk != null ? risk.DeltaInLots : 0;
}
}
var realStrike = tradeObj.IsMoneynessOptionData ? (tradeObj.SpotPrice ?? 0) * (tradeObj.Strike ?? 0) : tradeObj.Strike ?? 0;
tradeObj.ValueStatus = "-";
DataCacheModule.DataCacheManager.GetUnderlyingDataSource().TryGetPrice(tradeObj.UnderlyingCode, out var price);
tradeObj.UnderlyingPrice = price;
tradeObj.UnderlyingName = underlying?.UnderlyingName;
if (tradeObj.IsOption() && price > 0)
{
if (realStrike == price)
{
tradeObj.ValueStatus = "ATM 100%";
}
else if ((realStrike < price && tradeObj.OptionType == "看涨") || (realStrike > price && tradeObj.OptionType == "看跌"))
{
tradeObj.ValueStatus = "ITM " + (realStrike / price * 100).ToString("0.00") + "%";
}
else
{
tradeObj.ValueStatus = "OTM " + (realStrike / price * 100).ToString("0.00") + "%";
}
}
var pv = realtimerisk.Where(t => t.TradeId == tradeObj.id).Select(t => new KeyValuePair(t.VolType, t.Pv)).ToList();
var roundedPv = realtimerisk.Where(t => t.TradeId == tradeObj.id).Select(t => new KeyValuePair(t.VolType, t.RoundedPv)).ToList();
if (PS.Config.IsPVRounded)
{
if (roundedPv != null && roundedPv.Count > 0)
{
tradeObj.PV = roundedPv.ToJson();
}
}
else
{
if (pv != null && pv.Count > 0)
{
tradeObj.PV = pv.ToJson();
}
}
if (tradeObj.TradeType == "合成价差期权")
{
//tradeObj.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(tradeObj.UnderlyingCode);
tradeObj.SyntheticUnderlyingTipsInfo = syntheticUnderlyingList.FirstOrDefault(d => tradeObj.UnderlyingCode.Equals(d.Name))?.UnderlyingTipsInfo;
}
//tradeObj.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(tradeObj.id);
if (keyValueSalesC.ContainsKey(tradeObj.id))
{
tradeObj.SalesCommission = keyValueSalesC[tradeObj.id];
}
else
{
tradeObj.SalesCommission = new TradeSalesCommissionInfo();
}
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && tradeObj.SalesCommission?.Commission != null)
{
tradeObj.SalesCommission.Commission = tradeObj.SalesCommission.Commission * tradeObj.SalesCommission.SalesIds.Count();
}
tradeObj.CountRatio = underlying?.CountRatio ?? 1;
tradeObj.SettlementDate = tradeObj.SettlementDate ?? tradeObj.ExerciseDate;
}
}
return sList;
}
///
/// 获取今日敲出数据列表
///
public SearchListResult GetKnockedOutList(TdTradeQueryModel req)
{
var valueDate = SystemValueDate;
var endDate = valueDate.AddDays(1);
var predicate = BuildPredicate(req, valueDate);
var tQuery = DbContext.trade.Where(predicate);
var query1 = from tc in DbContext.trade_cash
join t in tQuery on tc.TradeId equals t.id
join ao in DbContext.autocall_observation on new { EndDate = tc.ValueDate, TradeId = t.id } equals new { ao.EndDate, ao.TradeId } into tempAo
from ao in tempAo.DefaultIfEmpty()
where tc.BarrierPrice != null //障碍期权敲出
&& tc.HappenedDate >= valueDate && tc.HappenedDate < endDate
&& t.ValidState != "InValid" && !tc.IsDeleted
select new TdPreEndTrade2
{
id = t.id,
trade = t,
trade_cash = new TradeCashDto
{
Action = tc.Action,
Amount = tc.Amount,
UnwindTradeAmount = tc.UnwindTradeAmount,
FinalPrice = tc.FinalPrice,
UnwindPrice = tc.UnwindPrice,
Notional = tc.Notional,
UnwindNotional = tc.UnwindNotional,
TradeAmount = tc.TradeAmount,
ValidState = tc.ValidState,
ValueDate = tc.ValueDate,
UnwindPercentRate = tc.UnwindPercentRate,
UnwindPricePercentRate = tc.UnwindPricePercentRate
}
};
if (string.IsNullOrEmpty(req.sidx))
{
query1 = query1.OrderByDescending(s => s.trade.TradeDate);
}
var sList = query1.ToSearchList(req);
foreach (var item in sList.rows)
{
tradeBLL.SetFieldsByTradeType(item.trade);
item.trade.UnWindUnderlyingPrice = DbContext.trade_cash.Where(x => x.TradeId == item.trade.id && !x.IsDeleted && x.BarrierPrice != null).Select(x => x.BarrierPrice).FirstOrDefault();
if (!ConsTrade.TradeTypesForHedge.Contains(item.trade.TradeType))
{
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.UnderlyingCode);
if (underlying != null && underlying.UnderlyingInstrumentType != "Stock")
{
item.trade.TradeOriginalAmount = item.trade.OriginalNotional / underlying.CountRatio;
}
else
{
item.trade.TradeOriginalAmount = item.trade.OriginalNotional;
}
item.trade.UnderlyingName = underlying.UnderlyingName;
}
if (item.trade.TradeType == "合成价差期权")
{
item.trade.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(item.trade.UnderlyingCode);
}
item.trade.CountRatio = DataCacheManager.GetUnderlyingDataSource().GetData(item.trade.UnderlyingCode)?.CountRatio;
}
return sList;
}
//替换TradeBLL.SearchHistoryList
///
/// 获取当日提前终止数据列表
///
public SearchListResult GetPreEndList(TdTradeQueryModel req, List userAssets, List userClients, bool isShowAll)
{
var curTradingDate = SystemValueDate;
var predicate = BuildPredicate(req, curTradingDate, req.OtcTradeType == DBModels.Enums.OtcTradeType.EquitySwap ? true : false);
var tQuery = DbContext.trade.Where(predicate);
//交易员对应的簿记账户筛选或者客户经理对应的客户筛选
if (userAssets != null || userClients != null)
{
tQuery = from source in tQuery
where userAssets.Contains(source.AssetId) || userClients.Contains(source.ClientId)
select source;
}
var query1 = from tc in DbContext.trade_cash
join t in tQuery on tc.TradeId equals t.id
where tc.ValueDate == curTradingDate
&& (tc.Action == ClientCashInCashOut.系统操作_平仓费 || tc.Action == ClientCashInCashOut.系统操作_互换) && (t.TradeStatus == "平仓待复核" || t.TradeStatus == "互换待复核" || tc.ValidState != "InValid")
&& !tc.IsDeleted && tc.BarrierPrice == null //不包含敲出数据
select new TdPreEndTrade2
{
id = t.id,
trade = t,
trade_cash = new TradeCashDto
{
id = tc.id,
Action = tc.Action,
Amount = tc.Amount,
UnwindTradeAmount = tc.UnwindTradeAmount,
FinalPrice = tc.FinalPrice,
UnwindPrice = tc.UnwindPrice,
Notional = tc.Notional,
UnwindNotional = tc.UnwindNotional,
TradeAmount = tc.TradeAmount,
ValidState = tc.ValidState,
ValueDate = tc.ValueDate,
UnwindPercentRate = tc.UnwindPercentRate,
UnwindPricePercentRate = tc.UnwindPricePercentRate
}
};
//已平仓,部分平仓,美式期权提前行权
//predicate = predicate.And(t => t.ExerciseMode == "American");
tQuery = DbContext.trade.Where(predicate);
var query2 = from tc in DbContext.trade_cash
join t in tQuery on tc.TradeId equals t.id
where tc.ValueDate == curTradingDate
&& tc.Action == ClientCashInCashOut.系统操作_行权费 && tc.ExerciseWay != "到期行权" && (t.TradeStatus == "行权待复核" || tc.ValidState != ConsGlobal.InValid && t.TradeStatus == ConsTrade.已执行)
&& !tc.IsDeleted && tc.BarrierPrice == null //不包含敲出数据
select new TdPreEndTrade2
{
id = t.id,
trade = t,
trade_cash = new TradeCashDto
{
id = tc.id,
Action = tc.Action,
Amount = tc.Amount,
UnwindTradeAmount = tc.UnwindTradeAmount,
FinalPrice = tc.FinalPrice,
UnwindPrice = tc.UnwindPrice,
Notional = tc.Notional,
UnwindNotional = tc.UnwindNotional,
TradeAmount = tc.TradeAmount,
ValidState = tc.ValidState,
ValueDate = tc.ValueDate,
UnwindPercentRate = tc.UnwindPercentRate,
UnwindPricePercentRate = tc.UnwindPricePercentRate
}
};
var query = query1.Concat(query2);
if (string.IsNullOrEmpty(req.sidx))
{
query = query.OrderByDescending(s => s.trade.TradeNumber);
}
var sList = query.ToSearchList(req);
if (sList.rows != null && sList.rows.Any())
{
var trades = sList.rows.Select(n => n.trade);
new TradeDalModule.TradeDalService(this).SetStructureInfo(trades);
var forwardIds = trades.Where(p => "远期".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
List forwardList = null;
if (forwardIds != null && forwardIds.Count > 0)
{
forwardList = DbContext.trade_forward.AsNoTracking().Where(x => forwardIds.Contains(x.TradeId)).ToList();
}
if (forwardList == null)
{
forwardList = new List();
}
var tradeIdList = trades.Select(p => p.id).Distinct().ToList();
Dictionary keyValueSalesC = null;
using (var saleCService = new SalesModule.SalesCommissionDataService(OptUser))
{
keyValueSalesC = saleCService.GetTradeCommissionInfoByTradeIds(tradeIdList);
}
var syntheticUnderlyingCodeList = trades.Where(d => "合成价差期权".Equals(d.TradeType)).Select(d => d.UnderlyingCode).Distinct().ToList();
List syntheticUnderlyingList = null;
if (syntheticUnderlyingCodeList != null && syntheticUnderlyingCodeList.Count > 0)
{
syntheticUnderlyingList = synthetic_underlyingBLL.GetListByNames(syntheticUnderlyingCodeList);
}
if (syntheticUnderlyingList == null)
{
syntheticUnderlyingList = new List();
}
List tradeCashDetailList = null;
var isGroupNotEqual1tradeCashIds = sList.rows.Where(d => d.trade.IsGroup != 1).Select(d => d.trade_cash.id).Distinct().ToList();
if (isGroupNotEqual1tradeCashIds != null && isGroupNotEqual1tradeCashIds.Count > 0)
{
tradeCashDetailList = DbContext.trade_cash_detail.AsNoTracking().Where(x => isGroupNotEqual1tradeCashIds.Contains(x.TradeCashId)).ToList();
}
if (tradeCashDetailList == null)
{
tradeCashDetailList = new List();
}
var isGroupEqual1tradeCashIds = sList.rows.Where(d => d.trade.IsGroup == 1).Select(d => d.trade_cash.id).Distinct().ToList();
List childTradeCashList = null;
var parentTradeIds = sList.rows.Where(d => d.trade.IsGroup == 1).Select(d => d.id).Distinct().ToList();
if (isGroupEqual1tradeCashIds != null && isGroupEqual1tradeCashIds.Count > 0 && parentTradeIds != null && parentTradeIds.Count > 0)
{
var childTradeIds = DbContext.trade.Where(p => parentTradeIds.Contains(p.ParentTradeId) && p.ParentTradeId > 0).Select(p => p.id).Distinct().ToList();
if (childTradeIds != null && childTradeIds.Count > 0)
{
childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(x => childTradeIds.Contains(x.TradeId) && isGroupEqual1tradeCashIds.Contains(x.ParentTradeCashId)).ToList();
}
}
if (childTradeCashList == null)
{
childTradeCashList = new List();
}
List allChildTradeIds = childTradeCashList.Select(d => d.TradeId).Distinct().ToList();
List allChildTradeList = null;
if (allChildTradeIds != null && allChildTradeIds.Count > 0)
{
allChildTradeList = DbContext.trade.AsNoTracking().Where(d => allChildTradeIds.Contains(d.id)).ToList();
}
if (allChildTradeList == null)
{
allChildTradeList = new List();
}
foreach (var item in sList.rows)
{
var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(item.trade.UnderlyingCode);
ProcessTrade(item.trade, null, underlying: underlying, syntheticUnderlyings: syntheticUnderlyingList);
if (item.trade.TradeType == "远期")
{
item.trade.trade_forward = forwardList.FirstOrDefault(x => x.TradeId == item.trade.id);
}
if (keyValueSalesC.ContainsKey(item.trade.id))
{
item.trade.SalesCommission = keyValueSalesC[item.trade.id];
}
else
{
item.trade.SalesCommission = new TradeSalesCommissionInfo();
}
//tradeObj.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(tradeObj.id);
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && item.trade.SalesCommission?.Commission != null)
{
item.trade.SalesCommission.Commission = item.trade.SalesCommission.Commission * item.trade.SalesCommission.SalesIds.Count();
}
if (item.trade.IsGroup == 1)
{
//var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeCashId == item.trade_cash.id).ToList();
var childTradeCashs = childTradeCashList.Where(x => x.ParentTradeCashId == item.trade_cash.id).ToList();
var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList();
//var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList();
var childTrades = allChildTradeList.Where(x => childTradeIds.Contains(x.id)).ToList();
var tcTradePrice = 0.0;
childTradeCashs.ForEach(x =>
{
var trade = childTrades.FirstOrDefault(y => y.id == x.TradeId);
tcTradePrice += (x.UnwindPercentRate * trade?.TradePrice * (trade?.BuySell == "买入" ? -1 : 1)) ?? 0;
});
item.WinLoss = -(item.trade_cash.Amount + tcTradePrice);
}
else
{
//var tradeCashDetail = DbContext.trade_cash_detail.Where(x => x.TradeCashId == item.trade_cash.id);
var tradeCashDetail = tradeCashDetailList.Where(x => x.TradeCashId == item.trade_cash.id);
var amount = tradeCashDetail.Any() ? tradeCashDetail.Sum(x => x.Amount ?? 0) : item.trade_cash.Amount;
item.WinLoss = -(amount + (item.trade.TradePrice ?? 0) * (item.trade_cash.UnwindPercentRate ?? 0) * ((item.trade.BuySell == "卖出" || item.trade.TradeType == "远期") ? 1 : -1));
}
item.trade.CountRatio = underlying?.CountRatio ?? 1;
item.trade.UnderlyingName = underlying?.UnderlyingName;
}
}
return sList;
}
public List GetPreEndGroupChildren(int TcId)
{
var tQuery = DbContext.trade.AsNoTracking();
var query = from tc in DbContext.trade_cash.AsNoTracking().Where(x => x.ValidState != "InValid" && x.ParentTradeCashId == TcId)
join t in tQuery on tc.TradeId equals t.id
select new TdPreEndTrade2
{
id = t.id,
trade = t,
trade_cash = new TradeCashDto
{
id = tc.id,
Action = tc.Action,
Amount = tc.Amount,
UnwindTradeAmount = tc.UnwindTradeAmount,
FinalPrice = tc.FinalPrice,
UnwindPrice = tc.UnwindPrice,
Notional = tc.Notional,
UnwindNotional = tc.UnwindNotional,
TradeAmount = tc.TradeAmount,
ValidState = tc.ValidState,
ValueDate = tc.ValueDate,
UnwindPercentRate = tc.UnwindPercentRate,
UnwindPricePercentRate = tc.UnwindPricePercentRate
}
};
var sList = query.ToList();
var trades = sList.Select(n => n.trade);
new TradeDalModule.TradeDalService(this).SetStructureInfo(trades);
foreach (var tradeObj in trades)
{
ProcessTrade(tradeObj, null);
if (tradeObj.TradeType == "远期")
{
tradeObj.trade_forward = DbContext.trade_forward.First(x => x.TradeId == tradeObj.id);
}
tradeObj.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(tradeObj.id);
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && tradeObj.SalesCommission?.Commission != null)
{
tradeObj.SalesCommission.Commission = tradeObj.SalesCommission.Commission * tradeObj.SalesCommission.SalesIds.Count();
}
}
return sList;
}
///
/// 交易观察状态列表
/// 障碍期权,双鲨期权,凤凰期权,雪球期权分tab展示
///
public SearchListResult GetObservationStatusTradeList(TdTradeQueryModel req)
{
var valueDate = SystemValueDate;
var predicate = BuildObservationStatusPredicate(req, valueDate);
var tQuery = DbContext.trade.Where(predicate);
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "TradeNumber";
req.sord = "desc";
}
var sList = tQuery.ToSearchList(req);
if (sList.rows != null && sList.rows.Any())
{
var tradeIds = sList.rows.Select(t => t.id).ToList();
//处理障碍期权类型 需要关联表 在内存中处理
var trade_barrier_option = DbContext.trade_barrier_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理双鲨期权
var trade_double_sharkfin_option = DbContext.trade_double_sharkfin_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理凤凰期权
var trade_autocall = DbContext.trade_autocall.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理雪球期权
var trade_snowball = DbContext.trade_snowball.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理二元期权
var trade_binary_option = DbContext.trade_binary_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理累计期权
var trade_accumulator_option = DbContext.trade_accumulator_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
foreach (var trade in sList.rows)
{
if (trade.TradeType == "障碍期权")
{
var barrier = trade_barrier_option.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_barrier_option = barrier == null
? new trade_barrier_option()
: trade_barrier_option.FirstOrDefault(t => t.TradeId == trade.id);
if (string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates))
{
trade.trade_barrier_option.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_barrier_option.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_barrier_option.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_barrier_option.LatestObservationDate = null;
}
}
}
else if (trade.TradeType == "双鲨期权")
{
var doubleSharkFin = trade_double_sharkfin_option.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_double_sharkfin_option = doubleSharkFin == null
? new trade_double_sharkfin_option()
: trade_double_sharkfin_option.FirstOrDefault(t => t.TradeId == trade.id);
if (string.IsNullOrEmpty(trade.trade_double_sharkfin_option.ObservationDates))
{
trade.trade_double_sharkfin_option.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_double_sharkfin_option.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_double_sharkfin_option.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_double_sharkfin_option.LatestObservationDate = null;
}
}
}
else if (trade.TradeType == "凤凰期权")
{
var autocall = trade_autocall.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_autocall = autocall == null
? new trade_autocall()
: trade_autocall.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_autocall.HappenedObservations = new TradeAutocallBLL(this).QueryHappenedObservations(trade.id, DateTime.MaxValue);
if (string.IsNullOrEmpty(trade.trade_autocall.ObservationDates))
{
trade.trade_autocall.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_autocall.LatestObservationDate = latestObservationDate.DateTime;
}
}
if (string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates))
{
trade.trade_autocall.LatestKOObservationDate = valueDate;
trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.KOObservationDates);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
trade.trade_autocall.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (customizedKOBarriers == null || !customizedKOBarriers.Any())
{
trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier;
}
else
{
trade.trade_autocall.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)];
}
}
}
}
else if (trade.TradeType == "雪球期权")
{
var snowball = trade_snowball.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_snowball = snowball == null
? new trade_snowball()
: trade_snowball.FirstOrDefault(t => t.TradeId == trade.id);
if (string.IsNullOrEmpty(trade.trade_snowball.ObservationDates))
{
trade.trade_snowball.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_snowball.LatestObservationDate = latestObservationDate.DateTime;
}
}
if (string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates))
{
trade.trade_snowball.LatestKOObservationDate = valueDate;
trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.KOObservationDates);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
trade.trade_snowball.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (customizedKOBarriers == null || !customizedKOBarriers.Any())
{
trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier;
}
else
{
trade.trade_snowball.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)];
}
}
}
}
else if (trade.TradeType == "二元期权")
{
var binary = trade_binary_option.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_binary_option = binary == null
? new trade_binary_option()
: trade_binary_option.FirstOrDefault(t => t.TradeId == trade.id);
if (string.IsNullOrEmpty(trade.trade_binary_option.ObservationDates))
{
trade.trade_binary_option.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_binary_option.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_binary_option.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_binary_option.LatestObservationDate = null;
}
}
}
else if (trade.TradeType == "累计期权")
{
var accumulator = trade_accumulator_option.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_accumulator_option = accumulator == null ? new trade_accumulator_option() : accumulator;
if (string.IsNullOrEmpty(trade.trade_accumulator_option.KOObservationDates))
{
trade.trade_accumulator_option.LatestObservationDate = valueDate;
trade.trade_accumulator_option.LatestKOBarrier = trade.trade_accumulator_option.KOBarrier;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_accumulator_option.KOObservationDates);
var observationDates = customizedResults.Item1;
var latestKOBarrier = customizedResults.Item2;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_accumulator_option.LatestObservationDate = latestObservationDate.DateTime;
if (latestKOBarrier == null || !latestKOBarrier.Any())
{
trade.trade_accumulator_option.LatestKOBarrier = trade.trade_accumulator_option.KOBarrier;
}
else
{
trade.trade_accumulator_option.LatestKOBarrier = latestKOBarrier[GetDateIndex(observationDates, latestObservationDate)];
}
}
}
}
DataCacheModule.DataCacheManager.GetUnderlyingDataSource().TryGetPrice(trade.UnderlyingCode, out var price);
trade.UnderlyingPrice = price;
}
}
return sList;
}
public SearchListResult GetObservationEventTradeList(TdTradeQueryModel req)
{
var valueDate = req.ValueDate ?? SystemValueDate;
EodPriceProvider priceProvider = null;
var predicate = BuildObservationEventPredicte(req, valueDate);
var tQuery = DbContext.trade.Where(predicate);
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "trade.TradeNumber";
req.sord = "desc";
}
var observationStatus = req.ObservationStatus;
if (observationStatus == null)
{
observationStatus = new List() { "已敲入", "已敲出", "观察中" };
}
var querylist = tQuery.ToList();
var knockOutList = new List();
var knockInList = new List();
var couponList = new List();
var customList = new List();
if (querylist != null && querylist.Any())
{
var tradeIds = querylist.Select(t => t.id).ToList();
Dictionary manuallyTradeObservationPrices = null;
if (valueDate < SystemValueDate)
{
priceProvider = new EodPriceProvider(valueDate);
manuallyTradeObservationPrices = DbContext.manually_trade_observation_price
.Where(x => tradeIds.Contains(x.TradeId) && x.ValueDate == valueDate).ToDictionary(n => n.TradeId);
}
if (req.TabIndex == 3 || req.TabIndex == 99)
{
var trade_custom = DbContext.trade_custom.Where(t => tradeIds.Contains(t.TradeId)).ToList();
foreach (var trade in querylist)
{
var custom = trade_custom.FirstOrDefault(t => t.TradeId == trade.id);
trade.trade_custom = custom == null
? new trade_custom()
: trade_custom.FirstOrDefault(t => t.TradeId == trade.id);
var tempTrade = new TdObservationTrade();
if (string.IsNullOrEmpty(trade.trade_custom.ObservationDates))
{
continue;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_custom.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_custom.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_custom.LatestObservationDate = null;
}
}
tempTrade.trade = trade.Clone();
if (trade.trade_custom.LatestObservationDate == valueDate)
{
tempTrade.Type += 8;
customList.Add(tempTrade);
}
else
{
continue;
}
var price = 0.0;
double? SettlementAmount = null;
if (valueDate >= SystemValueDate)
{
DataCacheManager.GetUnderlyingDataSource().TryGetPrice(trade.UnderlyingCode, out price);
}
else
{
if (manuallyTradeObservationPrices.TryGetValue(trade.id, out var manuallyTradeObservationPrice))
{
price = manuallyTradeObservationPrice.Price ?? 0;
SettlementAmount = manuallyTradeObservationPrice.SettlementAmount;
}
else if (!priceProvider.TryGetEodPrice(trade.UnderlyingCode, out var eodPrice))
{
throw new Exception($"[{trade.TradeType}:{trade.TradeNumber},标的:{trade.UnderlyingCode}]未找到结算价");
}
else
{
price = eodPrice.GetPrice(trade.SettlementType);
}
}
if (tempTrade.trade != null)
{
tempTrade.trade.UnderlyingPrice = price;
}
}
}
if (req.TabIndex != 3)
{
//处理障碍期权类型 需要关联表 在内存中处理
var trade_barrier_option = DbContext.trade_barrier_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理双鲨期权
var trade_double_sharkfin_option = DbContext.trade_double_sharkfin_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理凤凰期权
var trade_autocall = DbContext.trade_autocall.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理雪球期权
var trade_snowball = DbContext.trade_snowball.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//处理二元期权
var trade_binary_option = DbContext.trade_binary_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//气囊结构
var trade_airbag = DbContext.trade_airbag.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//区间累积
var trade_rangeaccrual = DbContext.trade_rangeaccrual.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//累计期权
var trade_accumulator = DbContext.trade_accumulator_option.Where(t => tradeIds.Contains(t.TradeId)).ToList();
//是否新增观察事件 -- knockOutList,knockInList,couponList,customList
bool isAdd = false;
foreach (var trade in querylist)
{
var tempTrade = new TdObservationTrade();
var tempTrade1 = new TdObservationTrade();
switch (trade.TradeType)
{
case "障碍期权":
{
var barrier = trade_barrier_option.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_barrier_option();
trade.trade_barrier_option = barrier;
if (string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates))
{
trade.trade_barrier_option.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_barrier_option.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_barrier_option.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_barrier_option.LatestObservationDate = null;
}
}
if (observationStatus.Contains(trade.trade_barrier_option.KnockInOutStatusCn))
{
tempTrade.trade = trade.Clone();
tempTrade.ObservationStatus = trade.trade_barrier_option.KnockInOutStatusCn;
tempTrade.konckInOutDate = trade.trade_barrier_option.KnockInOutDate;
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_barrier_option.BarrierPrice * trade.SpotPrice : trade.trade_barrier_option.BarrierPrice;
tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_barrier_option.UpperBarrierPrice * trade.SpotPrice : trade.trade_barrier_option.UpperBarrierPrice;
if (trade.trade_barrier_option.LatestObservationDate == valueDate)
{
if (trade.trade_barrier_option.BarrierType.Contains("敲入"))
{
tempTrade.Type += 1;
knockInList.Add(tempTrade);
isAdd = true;
}
if (trade.trade_barrier_option.BarrierType.Contains("敲出"))
{
tempTrade.Type += 2;
knockOutList.Add(tempTrade);
isAdd = true;
}
if (tempTrade.ObservationStatus != "已敲入" && (tempTrade.ObservationStatus == "观察中" || tempTrade.konckInOutDate == valueDate || trade.ExerciseDate == valueDate))
{
tempTrade.Type += 4;
couponList.Add(tempTrade);
isAdd = true;
}
}
}
}
break;
case "双鲨期权":
{
var doubleSharkFin = trade_double_sharkfin_option.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_double_sharkfin_option();
trade.trade_double_sharkfin_option = doubleSharkFin;
if (string.IsNullOrEmpty(trade.trade_double_sharkfin_option.ObservationDates))
{
trade.trade_double_sharkfin_option.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_double_sharkfin_option.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_double_sharkfin_option.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_double_sharkfin_option.LatestObservationDate = null;
}
}
if (observationStatus.Contains(trade.trade_double_sharkfin_option.KnockInOutStatusCn))
{
tempTrade.trade = trade.Clone();
tempTrade.ObservationStatus = trade.trade_double_sharkfin_option.KnockInOutStatusCn;
tempTrade.konckInOutDate = trade.trade_double_sharkfin_option.KnockInOutDate;
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_double_sharkfin_option.BarrierLow * trade.SpotPrice : trade.trade_double_sharkfin_option.BarrierLow;
tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_double_sharkfin_option.BarrierHigh * trade.SpotPrice : trade.trade_double_sharkfin_option.BarrierHigh;
if (trade.trade_double_sharkfin_option.LatestObservationDate == valueDate)
{
tempTrade.Type += 2;
knockOutList.Add(tempTrade);
if (tempTrade.ObservationStatus == "观察中" || tempTrade.konckInOutDate == valueDate)
{
tempTrade.Type += 4;
couponList.Add(tempTrade);
}
isAdd = true;
}
}
}
break;
case "凤凰期权":
{
var autocall = trade_autocall.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_autocall();
trade.trade_autocall = autocall;
trade.trade_autocall.HappenedObservations = new TradeAutocallBLL(this).QueryHappenedObservations(trade.id, DateTime.MaxValue);
if (string.IsNullOrEmpty(trade.trade_autocall.ObservationDates))
{
trade.trade_autocall.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_autocall.LatestObservationDate = latestObservationDate.DateTime;
}
}
if (string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates))
{
trade.trade_autocall.LatestKOObservationDate = valueDate;
trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier;
}
else
{
var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(trade.trade_autocall.KOObservationDates, trade.trade_autocall.CouponBarrier);
if (req.TabIndex == 2)
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ko.Item1);
var CouponsObservationDates = customizedResults.Item1;
var CouponsKOBarriers = customizedResults.Item2;
var latestKOObservationDate = CouponsObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
trade.trade_autocall.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (CouponsKOBarriers == null || !CouponsKOBarriers.Any())
{
trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier;
}
else
{
trade.trade_autocall.LatestKOBarrier = CouponsKOBarriers[GetDateIndex(CouponsObservationDates, latestKOObservationDate)];
}
}
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfoV3(ko.Item2);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
trade.trade_autocall.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (customizedKOBarriers == null || !customizedKOBarriers.Any())
{
trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier;
}
else
{
trade.trade_autocall.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)];
}
}
}
}
if (observationStatus.Contains(trade.trade_autocall.KnockInOutStatusCn))
{
tempTrade.trade = trade.Clone();
var barrier1 = (trade.IsMoneynessOption == "是" ? trade.trade_autocall.KIBarrier * trade.SpotPrice : trade.trade_autocall.KIBarrier) ?? 0;
var barrier2 = (trade.IsMoneynessOption == "是" ? trade.trade_autocall.KOBarrier * trade.SpotPrice : trade.trade_autocall.KOBarrier) ?? 0;
if (trade.trade_autocall.LatestObservationDate == valueDate)
{
tempTrade.ObservationStatus = trade.trade_autocall.KnockInOutStatusCn;
tempTrade.konckInOutDate = trade.trade_autocall.KnockInOutDate;
tempTrade.BarrierLow = trade.OptionType == "看涨" ? Math.Min(barrier1, barrier2) : Math.Max(barrier1, barrier2);
tempTrade.BarrierHigh = trade.OptionType == "看涨" ? Math.Max(barrier1, barrier2) : Math.Min(barrier1, barrier2);
tempTrade.Type += 1;
knockInList.Add(tempTrade);
isAdd = true;
}
if (trade.trade_autocall.LatestKOObservationDate == valueDate)
{
tempTrade1.trade = trade.Clone();
tempTrade1.ObservationStatus = trade.trade_autocall.KnockInOutStatusCn;
tempTrade1.konckInOutDate = trade.trade_autocall.KnockInOutDate;
tempTrade1.BarrierLow = trade.OptionType == "看涨" ? Math.Min(barrier1, barrier2) : Math.Max(barrier1, barrier2);
tempTrade1.BarrierHigh = trade.OptionType == "看涨" ? Math.Max(barrier1, barrier2) : Math.Min(barrier1, barrier2);
tempTrade.Type += 2;
knockOutList.Add(tempTrade1);
if (tempTrade1.ObservationStatus != "已敲出" || tempTrade1.konckInOutDate == valueDate)
{
tempTrade.Type += 4;
couponList.Add(tempTrade1);
}
tempTrade1.Type = tempTrade.Type;
isAdd = true;
}
}
}
break;
case "雪球期权":
{
var snowball = trade_snowball.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_snowball();
trade.trade_snowball = snowball;
if (string.IsNullOrEmpty(trade.trade_snowball.ObservationDates))
{
trade.trade_snowball.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_snowball.LatestObservationDate = latestObservationDate.DateTime;
}
}
if (string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates))
{
trade.trade_snowball.LatestKOObservationDate = valueDate;
trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.KOObservationDates);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestKOObservationDate != null)
{
trade.trade_snowball.LatestKOObservationDate = latestKOObservationDate.DateTime;
if (customizedKOBarriers == null || !customizedKOBarriers.Any())
{
trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier;
}
else
{
trade.trade_snowball.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)];
}
}
}
if (observationStatus.Contains(trade.trade_snowball.KnockInOutStatusCn))
{
tempTrade.trade = trade.Clone();
if (trade.trade_snowball.LatestObservationDate == valueDate && trade.trade_snowball.KIPayoffType != KIPayoffTypeEnum.None)
{
tempTrade.ObservationStatus = trade.trade_snowball.KnockInOutStatusCn;
tempTrade.konckInOutDate = trade.trade_snowball.KnockInOutDate;
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KIBarrier * trade.SpotPrice : trade.trade_snowball.KIBarrier;
tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KOBarrier * trade.SpotPrice : trade.trade_snowball.KOBarrier;
tempTrade.Type += 1;
knockInList.Add(tempTrade);
isAdd = true;
}
if (trade.trade_snowball.LatestKOObservationDate == valueDate)
{
tempTrade1.trade = trade.Clone();
tempTrade1.ObservationStatus = trade.trade_snowball.KnockInOutStatusCn;
tempTrade1.konckInOutDate = trade.trade_snowball.KnockInOutDate;
if (ConsGlobal.CallPut.IsCall(trade.OptionType)) //向下敲入向上敲出
{
tempTrade1.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_snowball.LatestKOBarrier * trade.SpotPrice : trade.trade_snowball.LatestKOBarrier;
tempTrade1.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KIBarrier * trade.SpotPrice : trade.trade_snowball.KIBarrier;
}
else //向上敲入向下敲出
{
tempTrade1.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_snowball.LatestKOBarrier * trade.SpotPrice : trade.trade_snowball.LatestKOBarrier;
tempTrade1.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KIBarrier * trade.SpotPrice : trade.trade_snowball.KIBarrier;
}
tempTrade.Type += 2;
knockOutList.Add(tempTrade1);
if (tempTrade1.ObservationStatus == "观察中" || tempTrade1.konckInOutDate == valueDate)
{
tempTrade.Type += 4;
couponList.Add(tempTrade1);
}
tempTrade1.Type = tempTrade.Type;
isAdd = true;
}
}
}
break;
case "二元期权":
{
var binary = trade_binary_option.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_binary_option();
trade.trade_binary_option = binary;
if (trade.ExerciseModeCn == "欧式")
{
break;
}
if (string.IsNullOrEmpty(trade.trade_binary_option.ObservationDates))
{
trade.trade_binary_option.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_binary_option.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_binary_option.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_binary_option.LatestObservationDate = null;
}
}
tempTrade.trade = trade.Clone();
if (trade.trade_binary_option.LatestObservationDate == valueDate)
{
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike;
tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_binary_option.UpperBarrier * trade.SpotPrice : trade.trade_binary_option.UpperBarrier;
tempTrade.Type += 2;
knockOutList.Add(tempTrade);
tempTrade.Type += 4;
couponList.Add(tempTrade);
isAdd = true;
}
}
break;
case "气囊结构":
{
var airbag = trade_airbag.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_airbag();
trade.trade_airbag = airbag;
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_airbag.Barrier * trade.SpotPrice : trade.trade_airbag.Barrier;
tempTrade.trade = trade.Clone();
tempTrade.Type = 4;
couponList.Add(tempTrade);
isAdd = true;
//没有观察日,只计算敲入敲出
}
break;
case "区间累积期权":
{
var rangeaccrual = trade_rangeaccrual.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_rangeaccrual();
trade.trade_rangeaccrual = rangeaccrual;
if (string.IsNullOrEmpty(trade.trade_rangeaccrual.ObservationDates))
{
trade.trade_rangeaccrual.LatestObservationDate = valueDate;
}
else
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_rangeaccrual.ObservationDates);
var observationDates = customizedResults.Item1;
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
trade.trade_rangeaccrual.LatestObservationDate = latestObservationDate.DateTime;
}
else
{
trade.trade_rangeaccrual.LatestObservationDate = null;
}
}
tempTrade.trade = trade.Clone();
if (trade.trade_rangeaccrual.LatestObservationDate == valueDate)
{
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike;
tempTrade.Type += 4;
couponList.Add(tempTrade);
isAdd = true;
}
}
break;
case "累计期权":
{
var accumulator = trade_accumulator.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_accumulator_option();
trade.trade_accumulator_option = accumulator;
DateTime? LatestObservationDate = valueDate;
if (!string.IsNullOrEmpty(accumulator.KOObservationDates))
{
var observationDates = QdpHelper.ParseObservationDate(accumulator.KOObservationDates);
var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault();
if (latestObservationDate != null)
{
LatestObservationDate = latestObservationDate.DateTime;
}
else
{
LatestObservationDate = null;
}
}
if (accumulator.KnockOutDate.HasValue)
{
tempTrade.trade = trade.Clone();
tempTrade.ObservationStatus = "敲出";
tempTrade.konckInOutDate = accumulator.KnockOutDate;
if (ConsGlobal.CallPut.IsCall(trade.OptionType))
{
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike;
tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? accumulator.KOBarrier * trade.SpotPrice : accumulator.KOBarrier;
}
else
{
tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike;
tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? accumulator.KOBarrier * trade.SpotPrice : accumulator.KOBarrier;
}
if (LatestObservationDate == valueDate)
{
tempTrade.Type += 2;
knockOutList.Add(tempTrade);
isAdd = true;
if (accumulator.PayoffType == "固定")
{
tempTrade.Type += 4;
couponList.Add(tempTrade);
}
}
}
}
break;
}
if (!isAdd)
{
continue;
}
var price = 0.0;
double? SettlementAmount = null;
if (valueDate >= SystemValueDate)
{
DataCacheManager.GetUnderlyingDataSource().TryGetPrice(trade.UnderlyingCode, out price);
}
else
{
if (manuallyTradeObservationPrices.TryGetValue(trade.id, out var manuallyTradeObservationPrice))
{
price = manuallyTradeObservationPrice.Price ?? 0;
SettlementAmount = manuallyTradeObservationPrice.SettlementAmount;
}
else if (!priceProvider.TryGetEodPrice(trade.UnderlyingCode, out var eodPrice))
{
throw new Exception($"[{trade.TradeType}:{trade.TradeNumber},标的:{trade.UnderlyingCode}]未找到结算价");
}
else
{
price = eodPrice.GetPrice(trade.SettlementType);
}
}
if (tempTrade.trade != null)
{
tempTrade.trade.UnderlyingPrice = price;
}
if (tempTrade1.trade != null)
{
tempTrade1.trade.UnderlyingPrice = price;
}
tempTrade.CouponPaidStatus = CheckCouponPaid(valueDate, trade, price, SettlementAmount);
tempTrade1.CouponPaidStatus = tempTrade.CouponPaidStatus;
}
}
}
var sList = new SearchListResult();
switch (req.TabIndex)
{
case 0:
sList = knockOutList.AsQueryable().ToSearchList(req);
break;
case 1:
sList = knockInList.AsQueryable().ToSearchList(req);
break;
case 2:
sList = couponList.AsQueryable().ToSearchList(req);
break;
case 3:
sList = customList.AsQueryable().ToSearchList(req);
break;
case 99:
couponList.AddRange(knockInList);
couponList.AddRange(knockOutList);
couponList.AddRange(customList);
sList = couponList.Distinct().AsQueryable().ToSearchList(req);
break;
default:
break;
}
return sList;
}
public SearchListResult GetDelaySettlementTradeQuery(TdTradeQueryModel req)
{
var valueDate = req.ValueDate ?? SystemValueDate;
var predicate = BuildObservationEventPredicte(req, valueDate);
var tQuery = DbContext.trade.Where(predicate);
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "TradeNumber";
req.sord = "desc";
}
var sList = tQuery.ToSearchList(req);
var sysuser = new ErpBaseContext().SystemUsers.Select(x => new { x.Id, x.Name }).ToList();
foreach (var item in sList.rows)
{
item.SettlementFlagOptName = sysuser?.FirstOrDefault(x => x.Id == item.SettlementFlagOptId)?.Name;
}
return sList;
}
///
///
///
///
///
/// 1:已付票息 0:不付票息 2:将付票息
public int CheckCouponPaid(DateTime? valueDate, trade td, double price, double? SettlementAmount)
{
var hasPaid = DbContext.autocall_observation.Any(o => o.EndDate == valueDate && o.TradeId == td.id);
if (hasPaid || ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus))
{
return 1;
}
else
{
var ret = new CheckTradeObservateStatusService(OptUser).CheckTradeObservateStatus(td, valueDate.Value, new double[3] { price, price, price }, SettlementAmount);
if (ret.Value)
{
return 2;
}
}
return 0;
}
private int GetDateIndex(Date[] source, Date value)
{
var index = 0;
foreach (var item in source)
{
if (item.DateTime == value.DateTime)
{
return index;
}
index++;
}
return -1;
}
public void ProcessTrade(trade tradeObj, trade_cash tradeCash, underlying_manager underlying = null, List syntheticUnderlyings = null)
{
if (tradeObj.TradeType == "合成价差期权")
{
if (syntheticUnderlyings != null)
{
tradeObj.SyntheticUnderlyingTipsInfo = syntheticUnderlyings.FirstOrDefault(d => d.Name.Equals(tradeObj.UnderlyingCode))?.UnderlyingTipsInfo;
}
else
{
tradeObj.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(tradeObj.UnderlyingCode);
}
}
tradeObj.FinalPrice = tradeCash?.FinalPrice;
if (!ConsTrade.TradeTypesForHedge.Contains(tradeObj.TradeType))
{
if (underlying == null)
{
underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(tradeObj.UnderlyingId);
}
if (underlying != null && underlying.UnderlyingInstrumentType != "Stock")
{
tradeObj.TradeOriginalAmount = tradeObj.OriginalNotional / underlying.CountRatio;
}
else
{
underlying = new underlying_manager();
tradeObj.TradeOriginalAmount = tradeObj.OriginalNotional;
}
tradeObj.UnderlyingName = underlying.UnderlyingName;
}
tradeObj.trade_cash = tradeCash;
}
public Dictionary getDailyEvents(DateTime? date, List userAssets, List userClients)
{
try
{
if (date == null)
{
date = SystemValueDate;
}
var ret = new Dictionary();
//到期
var settleTradeQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType != "远期" && o.TradeType != "收益互换" && o.TradeType != "现金流交易");
var settleCashTradeQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType == "现金流交易");
var settleForwardQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType == "远期");
var settleExchangeQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType == "收益互换");
if (settleTradeQuery.Any())
{
if (settleTradeQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus)))
{
ret.Add("到期期权", false);
}
else
{
ret.Add("到期期权", true);
}
}
if (settleCashTradeQuery.Any())
{
if (settleCashTradeQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus)))
{
ret.Add("到期现金流", false);
}
else
{
ret.Add("到期现金流", true);
}
}
if (settleForwardQuery.Any())
{
if (settleForwardQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus)))
{
ret.Add("到期远期", false);
}
else
{
ret.Add("到期远期", true);
}
}
if (settleExchangeQuery.Any())
{
if (settleExchangeQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus)))
{
ret.Add("到期互换", false);
}
else
{
ret.Add("到期互换", true);
}
}
//观察日
var req = new TdTradeQueryModel()
{
TabIndex = 99,
ValueDate = date,
UserAssets = userAssets,
UserClients = userClients
};
var observationEvents = GetObservationEventTradeList(req);
if (observationEvents != null && observationEvents.rows.Count() > 0)
{
var Types = observationEvents.rows.Select(o => o.Type).Distinct();
var HasDone = date < SystemValueDate;
if (Types.Any(o => o % 4 != 0))
{
ret.Add("敲入敲出", HasDone);
}
if (Types.Any(o => o % 8 != 0 && o >= 4))
{
HasDone = observationEvents.rows.Where(o => o.Type >= 4).Any(o => o.CouponPaidStatus == 1);
ret.Add("票息", HasDone);
}
if (Types.Any(o => o >= 8))
{
HasDone = observationEvents.rows.Where(o => o.Type >= 4).Where(o => o.trade.TradeType == "自定义交易").All(o => ConsTrade.TradeCompleteStatus.Contains(o.trade.TradeStatus));
ret.Add("自定义交易", HasDone);
}
}
//除权除息
var dividendReq = new DividendTradeReq()
{
DividendDate = date.Value
};
var dividendList = new DividendService(OptUser).QueryDividendTrade(dividendReq);
if (dividendList != null && dividendList.Count() > 0)
{
ret.Add("除权除息", dividendList.All(o => o.DividendStatus));
}
//互换
var swapTradeQuery = DbContext.trade.Where(o => o.TradeType == "收益互换" && o.ValidState != "InValid" && o.TradeDate <= date && o.ExerciseDate >= date);
var swapTradeIds = swapTradeQuery.Select(o => o.id).ToList();
var swapTrades = DbContext.swap_position.Where(t => swapTradeIds.Contains(t.SwapTradeId)&&t.InterestDirection>0&&t.IsInitial&&!t.Invalid).ToList();
var hasNeedObserveSwapTrade = false;
foreach (var item in swapTradeQuery)
{
var interests = swapTrades.Where(x => x.SwapTradeId == item.id).ToList();
if (interests.Any(s=>s.SwapIntervalList.Any(x=>x.Date==date)))
{
hasNeedObserveSwapTrade = true;
break;
}
}
if (hasNeedObserveSwapTrade)
{
if (date >= SystemValueDate)
{
ret.Add("收益互换", false);
}
else
{
ret.Add("收益互换", true);
}
}
//目前只有互换有延期结算
var settledelayQuery = DbContext.trade.Where(t => !ConsTrade.UnConfirmTradeStatusList.Contains(t.TradeStatus) && t.ValidState != "InValid"
&& t.ExerciseDate <= date && t.SettlementFlag == 1
&& (!(t.UnWindDate < date && ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus))));
if (settledelayQuery.Any())
{
ret.Add("延期互换", true);
}
ret.Add("日期", date);
return ret;
}
catch (Exception)
{
throw;
}
}
///
///
///
/// 筛选条件
/// 当前交易日
private Expression> BuildPredicate(TdTradeQueryModel req, DateTime curTradingDate, bool showChildrenGroupTrade = false)
{
var predicate = PredicateBuilder.True();
if (req.UserAssets != null && req.UserClients != null)
{
predicate = predicate.And(a => req.UserAssets.Contains(a.AssetId) || req.UserClients.Contains(a.ClientId));
}
switch (req.OtcTradeType)
{
case OtcTradeType.Forward:
predicate = predicate.And(t => t.TradeType == "远期");
break;
case OtcTradeType.EquitySwap:
predicate = predicate.And(t => t.TradeType == "收益互换");
break;
default:
predicate = predicate.And(t => t.TradeType != "远期" && t.TradeType != "收益互换");
break;
}
if (!string.IsNullOrEmpty(req.TradeNumber))
{
predicate = predicate.And(t => t.TradeNumber.Contains(req.TradeNumber));
}
if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n)))
{
var types = req.TradeTypes.Where(n => !string.IsNullOrEmpty(n)).ToArray();
predicate = predicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType));
}
//获取当日到期日数据
if (req.TabIndex == (int)TradeTabIndexEnum.今日到期)
{
//如果前一天是假日,要显示包含假日的交易
var preday = QdpCalendarHelper.GetNonHolidayDefore(curTradingDate.AddDays(-1));
var dateEnd = curTradingDate.AddDays(1);
//存在当日到期的黑箱组合子交易对应的主交易id
var parentTradeIds = DbContext.trade.Where(x => x.IsGroup == 2 && x.ExerciseDate > preday && x.ExerciseDate < dateEnd).Select(x => x.ParentTradeId).ToArray();
predicate = predicate.And(t => t.ExerciseDate > preday && t.ExerciseDate < dateEnd || (parentTradeIds.Contains(t.id) && (t.StructureType.Contains("累计") || t.StructureType.Contains("累购") || t.StructureType.Contains("累沽"))));
var q = from tradeCash in DbContext.trade_cash
where tradeCash.ValueDate > preday && tradeCash.ValueDate < dateEnd && tradeCash.ExerciseWay == TradeCashExerciseWayEnum.到期行权
&& (tradeCash.Action == ClientCashInCashOut.系统操作_行权费 || tradeCash.Action == ClientCashInCashOut.系统操作_票息 || tradeCash.Action == ClientCashInCashOut.系统操作_互换)
&& tradeCash.ValidState != ConsGlobal.InValid && !tradeCash.IsDeleted
select tradeCash;
predicate = predicate.And(t => ConsTrade.NeedMarginTradeStatusList.Contains(t.TradeStatus) || q.Any(n => n.TradeId == t.id) || q.Any(n => n.ParentTradeId == t.id));
}
//获取明日到期日数据
else if (req.TabIndex == (int)TradeTabIndexEnum.明日到期)
{
var nextDay = QdpCalendarHelper.GetNonHoliday(curTradingDate.AddDays(1));
predicate = predicate.And(t => t.ExerciseDate == nextDay);
}
else if (req.ExerciseDateStart != null || req.ExerciseDateEnd != null)
{
var dateStart = req.ExerciseDateStart ?? DateTime.MinValue;
var dateEnd = req.ExerciseDateEnd ?? new DateTime(2099, 1, 1);
if (req.OtcTradeType == OtcTradeType.EquitySwap)
{
predicate = predicate.And(t => t.ExerciseDate >= dateStart && t.ExerciseDate <= dateEnd);
}
else
{
predicate = predicate.And(t => string.IsNullOrEmpty(t.ExerciseMode) || t.ExerciseDate == null ||
(t.ExerciseMode == "European" && t.ExerciseDate >= dateStart && t.ExerciseDate <= dateEnd)
|| (t.ExerciseMode == "American" && ((t.StartDate >= dateStart && t.StartDate <= dateEnd) || (t.StartDate < dateStart && t.ExerciseDate >= dateStart)))
);
}
}
//明日到期过滤已平仓,已到期,已执行数据
if (req.TabIndex == (int)TradeTabIndexEnum.明日到期)
{
var excludeStatusArr = new[] { ConsTrade.已平仓, ConsTrade.已到期, ConsTrade.已执行 };
predicate = predicate.And(t => !excludeStatusArr.Contains(t.TradeStatus));
}
if (req.TabIndex == (int)TradeTabIndexEnum.今日收益结算)
{
predicate = predicate.And(t => t.ExerciseDate > curTradingDate);
var q = from tradeCash in DbContext.trade_cash
where tradeCash.ExerciseWay == TradeCashExerciseWayEnum.提前终止行权
&& (tradeCash.Action == ClientCashInCashOut.系统操作_行权费 || tradeCash.Action == ClientCashInCashOut.系统操作_票息 || tradeCash.Action == ClientCashInCashOut.系统操作_互换)
&& tradeCash.ValidState != ConsGlobal.InValid && !tradeCash.IsDeleted && tradeCash.ValueDate == curTradingDate
select tradeCash;
predicate = predicate.And(t => q.Any(n => n.TradeId == t.id) || q.Any(n => n.ParentTradeId == t.id));
}
//获取当日成交的数据
//当日成交包括操作日期和交易日为当前系统日期的数据
if (req.TabIndex == (int)TradeTabIndexEnum.今日成交)
{
var dateEnd = curTradingDate.AddDays(1);
predicate = predicate.And(t => t.TradeDate >= curTradingDate && t.TradeDate < dateEnd);
}
else
{
if (req.TradeDateStart != null)
{
predicate = predicate.And(t => t.TradeDate >= req.TradeDateStart.Value);
}
if (req.TradeDateEnd != null)
{
predicate = predicate.And(t => t.TradeDate <= req.TradeDateEnd.Value);
}
}
if (req.TabIndex == (int)TradeTabIndexEnum.今日敲出)
{
//敲出列表看子交易
predicate = predicate.And(t => !ConsTrade.TradeTypesForHedge.Contains(t.TradeType) && t.ValidState != "InValid" && t.TradeType != "结构化交易");
}
else
{
predicate = predicate.And(t => !ConsTrade.TradeTypesForHedge.Contains(t.TradeType)
&& t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && (t.IsGroup != 2 || t.TradeType == "收益互换" && showChildrenGroupTrade));
}
if (req.UnderlyingIds != null && req.UnderlyingIds.Any(n => n > 0))
{
predicate = predicate.And(t => req.UnderlyingIds.Contains(t.UnderlyingId));
}
if (req.VarietyId > 0)
{
var q = DbContext.underlying_manager.Where(n => n.UnderlyingTypeId == req.VarietyId);
predicate = predicate.And(t => q.Any(n => n.id == t.UnderlyingId));
}
if (req.TradeStatus != null && req.TradeStatus.Any(n => !string.IsNullOrEmpty(n)))
{
var statuses = req.TradeStatus.Where(n => !string.IsNullOrEmpty(n)).ToArray();
predicate = predicate.And(t => statuses.Contains(t.TradeStatus));
}
if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n)))
{
var types = req.TradeTypes.Where(n => !string.IsNullOrEmpty(n)).ToArray();
predicate = predicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType));
}
if (!string.IsNullOrEmpty(req.ExerciseMode))
{
predicate = predicate.And(t => t.ExerciseMode == req.ExerciseMode);
}
if (!string.IsNullOrEmpty(req.BuySell))
{
predicate = predicate.And(t => t.BuySell == req.BuySell);
}
if (!string.IsNullOrEmpty(req.OptionType))
{
predicate = predicate.And(t => t.OptionType == req.OptionType);
}
if (req.AssetIds != null && req.AssetIds.Any())
{
predicate = predicate.And(t => req.AssetIds.Contains(t.AssetId));
}
if (req.ClientIds != null && req.ClientIds.Any())
{
predicate = predicate.And(t => req.ClientIds.Contains(t.ClientId));
}
if (req.TraderIds != null && req.TraderIds.Any())
{
predicate = predicate.And(t => req.TraderIds.Contains(t.TraderId));
}
return predicate;
}
///
///
///
/// 筛选条件
/// 当前交易日
private Expression> BuildObservationStatusPredicate(TdTradeQueryModel req, DateTime curTradingDate)
{
var predicate = PredicateBuilder.Create(t => t.ValidState != "InValid");
if (req.UserAssets != null && req.UserClients != null)
{
Expression> pre2 = null;
if (req.UserAssets != null)
{
pre2 = PredicateBuilder.Create(t => req.UserAssets.Contains(t.AssetId));
}
if (req.UserClients != null)
{
var pre3 = PredicateBuilder.Create(t => req.UserClients.Contains(t.ClientId));
pre2 = pre2 == null ? pre3 : pre2.Or(pre3);
}
predicate = predicate.And(pre2);
}
if (!string.IsNullOrEmpty(req.TradeNumber))
{
predicate = predicate.And(t => t.TradeNumber.Contains(req.TradeNumber));
}
if (req.TabIndex == (int)ObservationStatusTradeEnum.Barrier)
{
predicate = predicate.And(t => t.TradeType == "障碍期权");
}
else if (req.TabIndex == (int)ObservationStatusTradeEnum.DoubleShark)
{
predicate = predicate.And(t => t.TradeType == "双鲨期权");
}
else if (req.TabIndex == (int)ObservationStatusTradeEnum.AutoCall)
{
predicate = predicate.And(t => t.TradeType == "凤凰期权");
}
else if (req.TabIndex == (int)ObservationStatusTradeEnum.SnowBall)
{
predicate = predicate.And(t => t.TradeType == "雪球期权");
}
else if (req.TabIndex == (int)ObservationStatusTradeEnum.Binary)
{
predicate = predicate.And(t => t.TradeType == "二元期权");
}
else if (req.TabIndex == (int)ObservationStatusTradeEnum.Accumulator)
{
predicate = predicate.And(t => t.TradeType == "累计期权");
}
predicate = predicate.And(t => t.TradeDate <= curTradingDate);
if (req.AssetIds != null && req.AssetIds.Any())
{
predicate = predicate.And(t => req.AssetIds.Contains(t.AssetId));
}
if (req.ClientIds != null && req.ClientIds.Any(n => n > 0))
{
predicate = predicate.And(t => req.ClientIds.Contains(t.ClientId));
}
if (req.UnderlyingIds != null && req.UnderlyingIds.Any(n => n > 0))
{
predicate = predicate.And(t => req.UnderlyingIds.Contains(t.UnderlyingId));
}
predicate = predicate.And(t => ConsTrade.TradeStatusAfterConfirmed.Contains(t.TradeStatus));
if (req.TradeStatus != null && req.TradeStatus.Any(n => !string.IsNullOrEmpty(n)))
{
var statuses = req.TradeStatus.Where(n => !string.IsNullOrEmpty(n)).ToArray();
predicate = predicate.And(t => statuses.Contains(t.TradeStatus));
}
if (req.TradeDateStart != null)
{
predicate = predicate.And(t => t.TradeDate >= req.TradeDateStart.Value);
}
if (req.TradeDateEnd != null)
{
predicate = predicate.And(t => t.TradeDate <= req.TradeDateEnd.Value);
}
if (req.ExerciseDateStart != null)
{
predicate = predicate.And(t => t.ExerciseDate >= req.ExerciseDateStart.Value);
}
else
{
predicate = predicate.And(t => t.ExerciseDate >= curTradingDate);
}
if (req.ExerciseDateEnd != null)
{
predicate = predicate.And(t => t.ExerciseDate <= req.ExerciseDateEnd.Value);
}
return predicate;
}
private Expression> BuildObservationEventPredicte(TdTradeQueryModel req, DateTime curTradingDate)
{
if (req.TradeTypes == null || req.TradeTypes.All(n => string.IsNullOrEmpty(n)))
{
switch (req.TabIndex)
{
case 0:
case 1:
req.TradeTypes = ConsTrade.HasBarrierPriceOptions;
break;
case 2:
req.TradeTypes = ConsTrade.HasCouponOptions;
break;
case 3:
req.TradeTypes = new List() { "自定义交易" };
break;
case 99:
req.TradeTypes = ConsTrade.HasCouponOptions.Concat(new List() { "自定义交易" });
break;
default: break;
}
}
var predicate = PredicateBuilder.True();
if (req.TabIndex == 11)
{
predicate = predicate.And(t => !ConsTrade.UnConfirmTradeStatusList.Contains(t.TradeStatus) && t.ValidState != "InValid"
&& t.ExerciseDate <= curTradingDate && t.SettlementFlag == 1
&& (!(t.UnWindDate < curTradingDate && ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus))));
}
else
{
predicate = predicate.And(t => !ConsTrade.UnConfirmTradeStatusList.Contains(t.TradeStatus) && t.ValidState != "InValid"
&& t.TradeDate <= curTradingDate && t.ExerciseDate >= curTradingDate
&& (t.UnWindDate == null || t.UnWindDate >= curTradingDate || ConsTrade.LiveTradeStatusList.Contains(t.TradeStatus)));
}
if (req.UserAssets != null && req.UserClients != null)
{
predicate = predicate.And(t => req.UserAssets.Contains(t.AssetId) || req.UserClients.Contains(t.ClientId));
}
if (req.UnderlyingIds != null && req.UnderlyingIds.Any(n => n > 0))
{
predicate = predicate.And(t => req.UnderlyingIds.Contains(t.UnderlyingId));
}
if (req.TradeStatus != null && req.TradeStatus.Any(n => !string.IsNullOrEmpty(n)))
{
var statuses = req.TradeStatus.Where(n => !string.IsNullOrEmpty(n)).ToArray();
predicate = predicate.And(t => statuses.Contains(t.TradeStatus));
}
if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n)))
{
var types = req.TradeTypes.Where(n => !string.IsNullOrEmpty(n)).ToArray();
predicate = predicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType));
}
if (!string.IsNullOrEmpty(req.BuySell))
{
predicate = predicate.And(t => t.BuySell == req.BuySell);
}
if (req.TradeDateStart != null)
{
predicate = predicate.And(t => t.TradeDate >= req.TradeDateStart.Value);
}
if (req.TradeDateEnd != null)
{
predicate = predicate.And(t => t.TradeDate <= req.TradeDateEnd.Value);
}
if (req.ExerciseDateStart != null)
{
predicate = predicate.And(t => t.ExerciseDate >= req.ExerciseDateStart.Value);
}
if (req.ExerciseDateEnd != null)
{
predicate = predicate.And(t => t.ExerciseDate <= req.ExerciseDateEnd.Value);
}
if (req.AssetIds != null && req.AssetIds.Any())
{
predicate = predicate.And(t => req.AssetIds.Contains(t.AssetId));
}
if (req.ClientIds != null && req.ClientIds.Any())
{
predicate = predicate.And(t => req.ClientIds.Contains(t.ClientId));
}
return predicate;
}
}
///
/// 当日场外期权数量统计
///
public class TdTradesCountSum
{
///
/// 当日到期交易数量
///
public int TdExerciseCount { get; set; }
///
/// 明日到期交易数量
///
public int TmExerciseCount { get; set; }
///
/// 当日提前终止交易数量
///
public int TdEarlyStoppedCount { get; set; }
///
/// 当日成交交易数量
///
public int TdCreatedCount { get; set; }
///
/// 当日敲出交易数量
///
public int TdKnockedOutCount { get; set; }
}
public class TdPreEndTrade
{
public trade trade { get; set; }
public TradeCashDto trade_cash { get; set; }
///
/// 实现盈亏
///
public double? WinLoss
{
get
{
return -(trade_cash.Amount - (trade.TradePrice ?? 0) * (trade_cash.UnwindPercentRate ?? 0) * ((trade.BuySell == "卖出") ? -1 : 1));
}
}
}
public class TdPreEndTrade2
{
public int id { get; set; }
public trade trade { get; set; }
public TradeCashDto trade_cash { get; set; }
public trade_cash_swap trade_cash_swap { get; set; }
private double? winloss;
///
/// 实现盈亏(客户角度观察)
///
public double? WinLoss
{
get
{
if (winloss != null)
{
return winloss;
}
if (trade.TradeType == "远期")
{
return -(trade_cash.Amount + (trade.TradePrice ?? 0) * (trade_cash.UnwindPercentRate ?? 0));
}
return -(trade_cash.Amount - (trade.TradePrice ?? 0) * (trade_cash.UnwindPercentRate ?? 0) * ((trade.BuySell == "卖出") ? -1 : 1));
}
set
{
winloss = value;
}
}
}
public class TdObservationTrade
{
public int id { get { return trade.id; } }
public string EncryptId { get { return trade.EncryptId; } }
public trade trade { get; set; }
//ObservationStatus konckOutDate konckInDate CouponDate BarrierLow BarrierHigh
public string ObservationStatus { get; set; }
public DateTime? konckInOutDate { get; set; }
public double? BarrierLow { get; set; }
public double? BarrierHigh { get; set; }
public int Type { get; set; }
///
/// 0:默认;1:已付票息2:将付票息
///
public int CouponPaidStatus { get; set; }
}
}