2408 lines
130 KiB
C#
2408 lines
130 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 当日交易(当日成交、提前终止、当日到期、明日到期)查询服务
|
||
/// </summary>
|
||
public class TodayTradeQueryService : YLBaseService
|
||
{
|
||
public TodayTradeQueryService(OptUserInfo userInfo) : base(userInfo)
|
||
{
|
||
|
||
}
|
||
|
||
public TdTradesCountSum GetTdTradesCountSum(List<int> userAssets, List<int> userClients, OtcTradeType otcTradeType)
|
||
{
|
||
var sum = new TdTradesCountSum();
|
||
|
||
var curTradingDate = SystemValueDate;
|
||
var basePredicate = PredicateBuilder.Create<trade>(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<trade>(t => t.ExerciseDate == nextDay
|
||
&& !excludeStatusArr.Contains(t.TradeStatus)).And(basePredicate);
|
||
sum.TmExerciseCount = DbContext.trade.Where(predicate).Count();
|
||
|
||
//---------------------------------------------
|
||
// 当日提前终止
|
||
//---------------------------------------------
|
||
IQueryable<trade> 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<trade>(t => t.TradeDate == curTradingDate).And(basePredicate);
|
||
sum.TdCreatedCount = DbContext.trade.Where(predicate).Count();
|
||
|
||
//---------------------------------------------
|
||
// 当日敲出
|
||
//---------------------------------------------
|
||
//var knockedOutPredicate = PredicateBuilder.Create<trade_barrier_option>(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
|
||
|
||
/// <summary>
|
||
/// 获取当日成交/当日到期/明日到期数据列表
|
||
/// </summary>
|
||
public SearchListResult<trade> 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<realtime_trade_risk>();
|
||
}
|
||
List<trade_cash> tradeCashList = null;
|
||
var tradeCacheBatchGetService = new BatchGetTradeRelationDataService<trade_cash>();
|
||
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<trade_cash>();
|
||
}
|
||
var tradeCashDatas = tradeCashList.Where(tc => (tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_票息 || tc.Action == ClientCashInCashOut.系统操作_互换) && tc.Status == TradeCashStatusEnum.已执行).ToList();
|
||
if (tradeCashDatas == null)
|
||
{
|
||
tradeCashDatas = new List<trade_cash>();
|
||
}
|
||
|
||
List<trade_cash> childTradeCashList = null;
|
||
var parentTradeIds = sList.rows.Where(p => p.IsGroup == 1).Select(p => p.id).Distinct().ToList();
|
||
List<TradeQueryDto> 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<trade_cash>();
|
||
}
|
||
if (childTradeList == null)
|
||
{
|
||
childTradeList = new List<TradeQueryDto>();
|
||
}
|
||
|
||
var forwardTradeIds = sList.rows.Where(p => "远期".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
|
||
List<trade_forward> 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<trade_forward>();
|
||
}
|
||
|
||
var swapTradeIds = sList.rows.Where(p => "收益互换".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
|
||
List<trade_cash_swap> 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<trade_cash_swap>();
|
||
}
|
||
Dictionary<int, TradeSalesCommissionInfo> keyValueSalesC = null;
|
||
using (var saleCService = new SalesModule.SalesCommissionDataService(OptUser))
|
||
{
|
||
keyValueSalesC = saleCService.GetTradeCommissionInfoByTradeIds(tradeIdList);
|
||
}
|
||
|
||
List<SyntheticUnderlying> 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<SyntheticUnderlying>();
|
||
}
|
||
|
||
|
||
|
||
|
||
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<string, double?>(t.VolType, t.Pv)).ToList();
|
||
var roundedPv = realtimerisk.Where(t => t.TradeId == tradeObj.id).Select(t => new KeyValuePair<string, double?>(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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取今日敲出数据列表
|
||
/// </summary>
|
||
public SearchListResult<TdPreEndTrade2> 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
|
||
|
||
/// <summary>
|
||
/// 获取当日提前终止数据列表
|
||
/// </summary>
|
||
public SearchListResult<TdPreEndTrade2> GetPreEndList(TdTradeQueryModel req, List<int> userAssets, List<int> 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<trade_forward> 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<trade_forward>();
|
||
}
|
||
var tradeIdList = trades.Select(p => p.id).Distinct().ToList();
|
||
Dictionary<int, TradeSalesCommissionInfo> 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<SyntheticUnderlying> syntheticUnderlyingList = null;
|
||
if (syntheticUnderlyingCodeList != null && syntheticUnderlyingCodeList.Count > 0)
|
||
{
|
||
syntheticUnderlyingList = synthetic_underlyingBLL.GetListByNames(syntheticUnderlyingCodeList);
|
||
}
|
||
if (syntheticUnderlyingList == null)
|
||
{
|
||
syntheticUnderlyingList = new List<SyntheticUnderlying>();
|
||
}
|
||
List<trade_cash_detail> 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<trade_cash_detail>();
|
||
}
|
||
|
||
var isGroupEqual1tradeCashIds = sList.rows.Where(d => d.trade.IsGroup == 1).Select(d => d.trade_cash.id).Distinct().ToList();
|
||
List<trade_cash> 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<trade_cash>();
|
||
}
|
||
List<int> allChildTradeIds = childTradeCashList.Select(d => d.TradeId).Distinct().ToList();
|
||
List<trade> 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<trade>();
|
||
}
|
||
|
||
|
||
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<TdPreEndTrade2> 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 交易观察状态列表
|
||
/// 障碍期权,双鲨期权,凤凰期权,雪球期权分tab展示
|
||
/// </summary>
|
||
public SearchListResult<trade> 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<TdObservationTrade> 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<string>() { "已敲入", "已敲出", "观察中" };
|
||
|
||
}
|
||
var querylist = tQuery.ToList();
|
||
var knockOutList = new List<TdObservationTrade>();
|
||
var knockInList = new List<TdObservationTrade>();
|
||
var couponList = new List<TdObservationTrade>();
|
||
var customList = new List<TdObservationTrade>();
|
||
|
||
if (querylist != null && querylist.Any())
|
||
{
|
||
var tradeIds = querylist.Select(t => t.id).ToList();
|
||
Dictionary<int, manually_trade_observation_price> 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<TdObservationTrade>();
|
||
|
||
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<trade> 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;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="valueDate"></param>
|
||
/// <param name="tradeId"></param>
|
||
/// <returns>1:已付票息 0:不付票息 2:将付票息</returns>
|
||
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<SyntheticUnderlying> 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<string, object> getDailyEvents(DateTime? date, List<int> userAssets, List<int> userClients)
|
||
{
|
||
try
|
||
{
|
||
if (date == null)
|
||
{
|
||
date = SystemValueDate;
|
||
}
|
||
var ret = new Dictionary<string, object>();
|
||
//到期
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="req">筛选条件</param>
|
||
/// <param name="curTradingDate">当前交易日</param>
|
||
private Expression<Func<trade, bool>> BuildPredicate(TdTradeQueryModel req, DateTime curTradingDate, bool showChildrenGroupTrade = false)
|
||
{
|
||
var predicate = PredicateBuilder.True<trade>();
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="req">筛选条件</param>
|
||
/// <param name="curTradingDate">当前交易日</param>
|
||
private Expression<Func<trade, bool>> BuildObservationStatusPredicate(TdTradeQueryModel req, DateTime curTradingDate)
|
||
{
|
||
var predicate = PredicateBuilder.Create<trade>(t => t.ValidState != "InValid");
|
||
|
||
if (req.UserAssets != null && req.UserClients != null)
|
||
{
|
||
Expression<Func<trade, bool>> pre2 = null;
|
||
if (req.UserAssets != null)
|
||
{
|
||
pre2 = PredicateBuilder.Create<trade>(t => req.UserAssets.Contains(t.AssetId));
|
||
}
|
||
if (req.UserClients != null)
|
||
{
|
||
var pre3 = PredicateBuilder.Create<trade>(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<Func<trade, bool>> 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<string>() { "自定义交易" };
|
||
break;
|
||
case 99:
|
||
req.TradeTypes = ConsTrade.HasCouponOptions.Concat(new List<string>() { "自定义交易" });
|
||
break;
|
||
default: break;
|
||
}
|
||
}
|
||
|
||
var predicate = PredicateBuilder.True<trade>();
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当日场外期权数量统计
|
||
/// </summary>
|
||
public class TdTradesCountSum
|
||
{
|
||
/// <summary>
|
||
/// 当日到期交易数量
|
||
/// </summary>
|
||
public int TdExerciseCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 明日到期交易数量
|
||
/// </summary>
|
||
public int TmExerciseCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日提前终止交易数量
|
||
/// </summary>
|
||
public int TdEarlyStoppedCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日成交交易数量
|
||
/// </summary>
|
||
public int TdCreatedCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日敲出交易数量
|
||
/// </summary>
|
||
public int TdKnockedOutCount { get; set; }
|
||
}
|
||
|
||
public class TdPreEndTrade
|
||
{
|
||
|
||
|
||
public trade trade { get; set; }
|
||
|
||
public TradeCashDto trade_cash { get; set; }
|
||
|
||
/// <summary>
|
||
/// 实现盈亏
|
||
/// </summary>
|
||
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;
|
||
|
||
/// <summary>
|
||
/// 实现盈亏(客户角度观察)
|
||
/// </summary>
|
||
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; }
|
||
/// <summary>
|
||
/// 0:默认;1:已付票息2:将付票息
|
||
/// </summary>
|
||
public int CouponPaidStatus { get; set; }
|
||
}
|
||
}
|