Files
zszq-trs/YLErpDAL/Modules/TradeModule/QueryModule/OtcOptionMultiCloseService.cs
T
2024-05-09 14:06:26 +08:00

1000 lines
48 KiB
C#

using System.Data;
using System.Linq.Expressions;
using YLErp.BLL;
using YLErp.Commons;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Helpers;
using YLErp.Models.Tag;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.TagModule;
using YLErp.Office.ExcelModule;
using static YLErp.ConsGlobal;
namespace YLErp.Modules.TradeModule.QueryModule
{
/// <summary>
/// 场外期权多次了结查询服务
/// </summary>
public class OtcOptionMultiCloseService : YLBaseService
{
public OtcOptionMultiCloseService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 获取分页数据
/// </summary>
public IPagedList<OtcTradeDetail> GetPagedDatas(TradeMultiCloseQueryModel queryModel)
{
var query = CreateQuery(queryModel);
if (string.IsNullOrEmpty(queryModel.SortExpression))
{
queryModel.SortExpression = "id desc, TcValueDate asc, TcId asc";
}
var pagedList = query.ToPagedList(queryModel);
OtcTradeDetail preData = null;
Dictionary<int, List<TagDto>> tradeTagList = null;
if (pagedList != null)
{
using (var service = new TagService(OptUser))
{
tradeTagList = service.GetTagByTradeIds(pagedList.Select(p => p.id).Distinct().ToList());
}
}
if (tradeTagList == null)
{
tradeTagList = new Dictionary<int, List<TagDto>>();
}
List<trade_cash> childTradeCashList = null;
var parentTradeCashIdList = pagedList.Where(p => p.IsGroup == 1).Select(p => p.TcId).Distinct().ToList();
if (parentTradeCashIdList != null && parentTradeCashIdList.Count > 0)
{
childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(p => parentTradeCashIdList.Contains(p.ParentTradeCashId)).ToList();
}
if (childTradeCashList == null)
{
childTradeCashList = new List<trade_cash>();
}
List<trade> childTradeList = null;
if (childTradeCashList != null && childTradeCashList.Count > 0)
{
var childTradeIds = childTradeCashList.Select(x => x.TradeId).Distinct().ToList();
childTradeList = DbContext.trade.Where(p => childTradeIds.Contains(p.id)).ToList();
}
if (childTradeList == null)
{
childTradeList = new List<trade>();
}
List<trade_barrier_option> tradeBarrierOptionList = null;
if (pagedList.Any(p => "障碍期权".Equals(p.TradeType)))
{
var barrierTradeIds = pagedList.Where(p => "障碍期权".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
if (barrierTradeIds != null && barrierTradeIds.Any())
{
tradeBarrierOptionList = DbContext.trade_barrier_option.AsNoTracking().Where(p => barrierTradeIds.Contains(p.TradeId)).ToList();
}
}
if (tradeBarrierOptionList == null)
{
tradeBarrierOptionList = new List<trade_barrier_option>();
}
List<trade_double_sharkfin_option> tradeDoublesharkfinOptionList = null;
if (pagedList.Any(p => "双鲨期权".Equals(p.TradeType)))
{
var doubleSharkfinTradeIds = pagedList.Where(p => "双鲨期权".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
if (doubleSharkfinTradeIds != null && doubleSharkfinTradeIds.Any())
{
tradeDoublesharkfinOptionList = DbContext.trade_double_sharkfin_option.AsNoTracking().Where(p => doubleSharkfinTradeIds.Contains(p.TradeId)).ToList();
}
}
if (tradeDoublesharkfinOptionList == null)
{
tradeDoublesharkfinOptionList = new List<trade_double_sharkfin_option>();
}
List<trade_autocall> tradeAutocallList = null;
if (pagedList.Any(p => "凤凰期权".Equals(p.TradeType)))
{
var autocallTradeIds = pagedList.Where(p => "凤凰期权".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
if (autocallTradeIds != null && autocallTradeIds.Any())
{
tradeAutocallList = DbContext.trade_autocall.AsNoTracking().Where(p => autocallTradeIds.Contains(p.TradeId)).ToList();
}
}
if (tradeAutocallList == null)
{
tradeAutocallList = new List<trade_autocall>();
}
List<trade_snowball> tradeSnowballList = null;
if (pagedList.Any(p => "雪球期权".Equals(p.TradeType)))
{
var snowballTradeIds = pagedList.Where(p => "雪球期权".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
if (snowballTradeIds != null && snowballTradeIds.Any())
{
tradeSnowballList = DbContext.trade_snowball.AsNoTracking().Where(p => snowballTradeIds.Contains(p.TradeId)).ToList();
}
}
if (tradeSnowballList == null)
{
tradeSnowballList = new List<trade_snowball>();
}
List<trade_airbag> tradeAirbagList = null;
if (pagedList.Any(p => "气囊结构".Equals(p.TradeType) || "气囊结构".Equals(p.StructureType)))
{
var airbagTradeIds = pagedList.Where(p => "气囊结构".Equals(p.TradeType) || "气囊结构".Equals(p.StructureType)).Select(p => p.id).Distinct().ToList();
if (airbagTradeIds != null && airbagTradeIds.Any())
{
tradeAirbagList = DbContext.trade_airbag.AsNoTracking().Where(p => airbagTradeIds.Contains(p.TradeId)).ToList();
}
}
if (tradeAirbagList == null)
{
tradeAirbagList = new List<trade_airbag>();
}
//List<trade_accumulator_option> tradeAccumulatorOptionList = null;
List<autocall_observation> autocallObservationList = null;
if (pagedList.Any(p => "累计期权".Equals(p.TradeType)))
{
var accumulatorOptionTradeIds = pagedList.Where(p => "累计期权".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList();
if (accumulatorOptionTradeIds != null && accumulatorOptionTradeIds.Any())
{
//tradeAccumulatorOptionList = DbContext.trade_accumulator_option.AsNoTracking().Where(p => accumulatorOptionTradeIds.Contains(p.TradeId)).ToList();
autocallObservationList = DbContext.autocall_observation.AsNoTracking().Where(p => accumulatorOptionTradeIds.Contains(p.TradeId)).ToList();
}
}
//if (tradeAccumulatorOptionList == null)
//{
// tradeAccumulatorOptionList = new List<trade_accumulator_option>();
//}
if (autocallObservationList == null)
{
autocallObservationList = new List<autocall_observation>();
}
foreach (var data in pagedList)
{
preData = ProcessData(data, preData);
if (data.IsGroup == 1)
{
//var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeCashId == data.TcId).ToList();
var childTradeCashs = childTradeCashList.Where(x => x.ParentTradeCashId == data.TcId).ToList();
var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList();
//var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList();
var childTrades = childTradeList.Where(x => childTradeIds.Contains(x.id)).ToList();
data.TcTradePrice = 0;
childTradeCashs.ForEach(x =>
{
var trade = childTrades.FirstOrDefault(y => y.id == x.TradeId);
data.TcTradePrice += (x.UnwindPercentRate * trade?.TradePrice * (trade?.BuySell == "买入" ? -1 : 1)) ?? 0;
});
}
if (data.TradeType == "障碍期权")
{
//var option = DbContext.trade_barrier_option.FirstOrDefault(x => x.TradeId == data.id);
var option = tradeBarrierOptionList.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "双鲨期权")
{
//var option = DbContext.trade_double_sharkfin_option.FirstOrDefault(x => x.TradeId == data.id);
var option = tradeDoublesharkfinOptionList.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "凤凰期权")
{
//var option = DbContext.trade_autocall.FirstOrDefault(x => x.TradeId == data.id);
var option = tradeAutocallList.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "雪球期权")
{
//var option = DbContext.trade_snowball.FirstOrDefault(x => x.TradeId == data.id);
var option = tradeSnowballList.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "气囊结构" || data.StructureType == "气囊结构")
{
//var option = DbContext.trade_airbag.FirstOrDefault(x => x.TradeId == data.id);
var option = tradeAirbagList.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "累计期权")
{
new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay2(data, Convert.ToDateTime(data.TcValueDate));
//var option = DbContext.trade_accumulator_option.FirstOrDefault(x => x.TradeId == data.id);
//var option = tradeAccumulatorOptionList.FirstOrDefault(x => x.TradeId == data.id);
//data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
var obser = autocallObservationList.FirstOrDefault(x => x.TradeId == data.id && x.EndDate == data.TcValueDate);
if (obser != null)
{
data.KnockInOutStatusObservation = "敲出".Equals(obser.SettlementMode) ? "敲出" : "观察中";
}
}
if (data.CountRatio == null)
{
data.CountRatio = DataCacheProvider.GetUnderlyingDataSource().GetData(data.UnderlyingCode)?.CountRatio ?? 1;
}
//拼装标签值
if (tradeTagList.ContainsKey(data.id))
{
data.Tags = tradeTagList[data.id];
data.OutputTags = TagService.GetOutputTagsStr(data.Tags);
}
}
return pagedList;
}
/// <summary>
/// 获取了结记录
/// <para>主要用于批量生成了结简讯用</para>
/// </summary>
/// <param name="queryModel"></param>
/// <returns></returns>
public List<KeyValuePair<trade, trade_cash>> GetSettlementList(TradeMultiCloseQueryModel queryModel)
{
if (queryModel is null)
{
throw new ArgumentNullException(nameof(queryModel));
}
BuildPredicate(queryModel, out var tdPredicate, out var tcPredicate);
var query = from t in DbContext.trade.Where(tdPredicate)
join tc in DbContext.trade_cash.Where(tcPredicate) on t.id equals tc.TradeId
select new { t, tc };
if (queryModel.UnWindTimes != null && queryModel.UnWindTimes >= 0)
{
var qgp = from f in query
group f by f.t.id into fgp
where fgp.Count() == queryModel.UnWindTimes
select fgp.Key;
query = query.Where(q => qgp.Contains(q.t.id));
}
if (queryModel.TradeCashIdList != null && queryModel.TradeCashIdList.Count > 0)
{
var tcIds = query.Select(O => O.tc.id).ToList();
tcIds = queryModel.TradeCashIdList.Where(O => !tcIds.Contains(O)).ToList();
if (tcIds.Any())
{
query =
query.Union(
from tc in DbContext.trade_cash
join t in DbContext.trade
on tc.TradeId equals t.id
where tcIds.Contains(tc.id)
select new { t, tc }
);
}
}
query = query.OrderByDescending(x => x.t.id).ThenBy(x => x.tc.ValueDate).ThenBy(x => x.tc.id);
return query.ToList().Select(O => new KeyValuePair<trade, trade_cash>(O.t, O.tc)).ToList();
}
public List<OtcTradeDetail> GetGroupChildrenDatas(int TcId)
{
var query = from t in DbContext.trade.AsNoTracking().Where(x => x.ValidState != "InValid" && x.IsGroup == 2)
join tc in DbContext.trade_cash.AsNoTracking().Where(x => x.ValidState != "InValid" && x.ParentTradeCashId == TcId && (x.Amount != 0 || x.UnwindPercentRate > 0)) on t.id equals tc.TradeId
select new OtcTradeDetail
{
id = t.id,
TcId = tc.id,
UnderlyingId = t.UnderlyingId,
TradeNumber = t.TradeNumber,
ClientId = t.ClientId,
ClientName = t.ClientName,
TradeDate = t.TradeDate,
ExerciseDate = t.ExerciseDate,
BuySell = t.BuySell,
TradeType = t.TradeType,
OptionType = t.OptionType,
UnderlyingAssetName = t.UnderlyingAssetName,
UnderlyingCode = t.UnderlyingCode,
SpotPrice = t.SpotPrice,
Strike = t.Strike,
IsMoneynessOption = t.IsMoneynessOption,
TradeSinglePrice = t.TradeSinglePrice ?? 0,
TradePrice = t.TradePrice ?? 0,
IsUsePremiumRate = t.IsUsePremiumRate,
PremiumRate = t.PremiumRate,
TradeAmount = t.TradeAmount,
ExerciseMode = t.ExerciseMode,
OriginalNotional = t.OriginalNotional ?? 0,
OriginalStockEqvNotional = t.OriginalStockEqvNotional,
ParticipationRate = t.ParticipationRate,
AnnualizeFactor = t.AnnualizeFactor,
PrincipalRate = t.PrincipalRate ?? 0,
AssetBookName = t.AssetBookName,
TraderName = t.TraderName,
TcValueDate = tc.HappenedDate != null ? tc.HappenedDate : tc.ValueDate,
TcFinalPrice = tc.FinalPrice,
TcUnwindPrice = tc.UnwindPrice,
TcUnwindPricePercent = tc.UnwindPricePercentRate,
TcAmount = tc.Amount,
UnWindNotional = tc.UnwindNotional ?? tc.Notional,
TcUnwindTradeAmount = tc.UnwindTradeAmount,
TcUnwindPercent = tc.UnwindPercentRate,
TcAction = tc.Action,
TcExerciseWay = tc.ExerciseWay,
StructureType = t.StructureType,
IsGroup = t.IsGroup,
UnderlyingInstrumentType = t.UnderlyingInstrumentType
};
var result = query.ToList();
OtcTradeDetail preData = null;
Dictionary<int, List<TagDto>> tradeTagList = null;
if (result != null && result.Any())
{
using (var service = new TagService(OptUser))
{
tradeTagList = service.GetTagByTradeIds(result.Select(p=>p.id).Distinct().ToList());
}
}
if (tradeTagList == null)
{
tradeTagList = new Dictionary<int, List<TagDto>>();
}
foreach (var data in result)
{
preData = ProcessData(data, preData);
if (data.TradeType == "亚式期权")
{
var baseReq = FixingService.GetRequestBase(valuedateBLL.ValueDate, data);
var strikeReq = new AsianOptionStrikeRequest(baseReq)
{
IsMoneynessOption = data.IsMoneynessOption == "是",
SpotPrice = data.SpotPrice,
Strike = data.Strike,
};
data.ActualStrike = trade_asian_optionBLL.GetAsianStrikePrice(strikeReq, null);
}
else
{
data.ActualStrike = data.IsMoneynessOption == "是" ? (data.SpotPrice * data.Strike) : data.Strike;
}
if (data.TradeType == "障碍期权")
{
var option = DbContext.trade_barrier_option.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "双鲨期权")
{
var option = DbContext.trade_double_sharkfin_option.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "凤凰期权")
{
var option = DbContext.trade_autocall.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "雪球期权")
{
var option = DbContext.trade_snowball.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "气囊结构")
{
var option = DbContext.trade_airbag.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
//拼装标签值
if (tradeTagList.ContainsKey(data.id))
{
data.Tags = tradeTagList[data.id];
data.OutputTags = TagService.GetOutputTagsStr(data.Tags);
}
}
return result;
}
/// <summary>
/// 根据交易编号获取交易了结信息(需要重构,否则不要用于其它查询场景)
/// 用于api/v1/tradeCloseInfos
/// </summary>
public IEnumerable<TradeCloseInfo> GetTradeCloseInfos(string tradeNumber, string unWindType, DateTime? valueDate = null)
{
var queryModel = new TradeMultiCloseQueryModel
{
TradeNumber = tradeNumber,
UseForwardASwap = true
};
if (!string.IsNullOrEmpty(unWindType))
{
queryModel.UnWindType = unWindType;
}
if (valueDate != null && valueDate != DateTime.MinValue)
{
queryModel.UnwindDateStart = valueDate;
queryModel.UnwindDateEnd = valueDate;
}
var query = CreateQuery(queryModel);
var datas = query.ToArray();
var list = new List<TradeCloseInfo>();
OtcTradeDetail preData = null;
foreach (var data in datas)
{
preData = ProcessData(data, preData);
var info = new TradeCloseInfo
{
TradeNumber = data.TradeNumber,
TcValueDate = data.TcValueDate,
TcAction = data.TcAction,
TcAmount = data.TcAmount,
TcFinalPrice = data.TcFinalPrice,
TcNotional = data.TcNotional,
TcTradeAmount = data.TcTradeAmount,
TcUnwindNotional = data.TcUnwindNotional,
TcUnwindPercent = data.TcUnwindPercent,
TcUnwindPrice = data.TcUnwindPrice,
TcUnwindPricePercent = data.TcUnwindPricePercent,
TcUnwindTradeAmount = data.TcUnwindTradeAmount,
TcTradePrice = (data.TradePrice ?? 0) * (data.TcUnwindPercent ?? 0) * ((data.BuySell == "卖出" || data.TradeType == "远期") ? 1 : -1),
};
if (data.IsGroup == 1)
{
var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeCashId == data.TcId).ToList();
var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList();
var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList();
info.TcTradePrice = 0;
childTradeCashs.ForEach(x =>
{
var trade = childTrades.FirstOrDefault(y => y.id == x.TradeId);
info.TcTradePrice += (x.UnwindPercentRate * trade?.TradePrice * (trade?.BuySell == "买入" ? -1 : 1)) ?? 0;
});
}
info.WinLoss = (info.TcAmount ?? 0) + info.TcTradePrice;
list.Add(info);
}
return list;
}
/// <summary>
/// 导出所有字段
/// </summary>
public byte[] ExportAllFieldsToExcel(TradeMultiCloseQueryModel queryModel)
{
var list = HandleExportDataToList(queryModel);
var list2 = list.Select(n => new ExpandoDictionary<string, string>(n.MetaDic)).ToArray();
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/场外期权交易多次了结导出模板.xlsx");
return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = list2 }).GenerateBytes();
}
public List<OtcTradeDetail> HandleExportDataToList(TradeMultiCloseQueryModel queryModel)
{
if (queryModel is null)
{
throw new ArgumentNullException(nameof(queryModel));
}
var query = CreateQuery(queryModel);
var list = query.ToList();
OtcTradeDetail preData = null;
foreach (var data in list)
{
data.CountRatio = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(data.UnderlyingCode)?.CountRatio;
preData = ProcessData(data, preData);
HandleExportData(data);
}
new TradeExtendService(this).SetTradeExtendWithCnKey(list);
var groupTradeCashIds = list.Where(x => x.IsGroup == 1).Select(x => x.TcId).ToArray();
var childList = CreateGroupChildrenQuery(groupTradeCashIds);
groupTradeCashIds.ToList().ForEach(x =>
{
var children = childList.Where(y => y.ParentTcId == x).ToList();
var item = list.FirstOrDefault(y => y.TcId == x);
list.InsertRange(list.IndexOf(item) + 1, children.OrderBy(y => y.id));
});
return list;
}
//数据加工处理
private OtcTradeDetail ProcessData(OtcTradeDetail data, OtcTradeDetail preData)
{
if (preData?.id == data.id)
{
data.TcSequence = preData.TcSequence + 1;
data.TradeOriginalAmount = preData.OriginalNotional;
data.SyntheticUnderlyingTipsInfo = preData.SyntheticUnderlyingTipsInfo;
data.ExerciseMode = preData.ExerciseMode;
}
else
{
data.ExerciseMode = TradeHelper.GetExerciseModeCn(data.ExerciseMode);
var CountRatio = UnderlyingDataProvider.GetCountRatio(data.UnderlyingCode);
data.TradeOriginalAmount = data.OriginalNotional / CountRatio;
if (data.TradeType == "合成价差期权")
{
data.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(data.UnderlyingCode);
}
}
data.TcUnwindNotional = data.OriginalNotional * data.TcUnwindPercent;
if (data.TcAction == "系统操作-行权费" && !data.TcUnwindTradeAmount.HasValue)
{
var CountRatio = UnderlyingDataProvider.GetCountRatio(data.UnderlyingCode);
data.TcUnwindTradeAmount = data.OriginalNotional * data.TcUnwindPercent / CountRatio;
}
if (data.TcAction == "系统操作-票息")
{
data.TcAction = "票息";
}
else if (data.TcAction == "系统操作-互换")
{
data.TcAction = "互换";
}
else if (data.TcExerciseWay == TradeCashExerciseWayEnum.到期行权)
{
data.TcAction = "到期";
}
else
{
data.TcAction = "终止";
}
if (data.TradeType == "结构化交易" && data.IsGroup == 1)
{
data.TradeType = data.StructureType;
}
if (PS.Config.IsGuoJun)
{
data.UnderlyingVariety = YLErp.Modules.UnderlyingModule.UnderlyingHelper.GetUnderlyingVarietyCode(data.UnderlyingCode);
}
return data;
}
private void HandleExportData(OtcTradeDetail data)
{
var dic = data.MetaDic;
var isMoneyness = data.IsMoneynessOption == "是";
var isPremiumRate = data.IsUsePremiumRate == true;
var multiply = TradeHelper.GetStockEqvNotionalMultiply(data.OriginalStockEqvNotional, data.ParticipationRate, data.AnnualizeFactor);
if (data.IsGroup == 1)
{
var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeCashId == data.TcId).ToList();
var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList();
var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList();
data.TcTradePrice = 0;
childTradeCashs.ForEach(x =>
{
var trade = childTrades.FirstOrDefault(y => y.id == x.TradeId);
data.TcTradePrice += (x.UnwindPercentRate * trade?.TradePrice * (trade?.BuySell == "买入" ? -1 : 1)) ?? 0;
});
}
if (data.TradeType == "障碍期权")
{
var option = DbContext.trade_barrier_option.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "双鲨期权")
{
var option = DbContext.trade_double_sharkfin_option.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "凤凰期权")
{
var option = DbContext.trade_autocall.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "雪球期权")
{
var option = DbContext.trade_snowball.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "气囊结构" || data.StructureType == "气囊结构")
{
var option = DbContext.trade_airbag.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
else if (data.TradeType == "累计期权")
{
new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay2(data, Convert.ToDateTime(data.TcValueDate));
var option = DbContext.trade_accumulator_option.FirstOrDefault(x => x.TradeId == data.id);
data.KnockInOutStatusObservation = option?.KnockInOutStatusCn;
}
dic["交易编号"] = data.TradeNumber;
dic["分组交易类型"] = data.GroupTradeType;
dic["交易状态"] = data.TradeStatus;
dic["簿记账户"] = data.AssetBookName;
dic["交易员"] = data.TraderName;
dic["交易对手方"] = data.ClientName;
dic["交易对手编号"] = DataCacheProvider.GetClientDataSource().GetData(data.ClientId)?.Number;
dic["结构类型"] = data.TradeMultipleType;
dic["成交日期"] = data.TradeDate.OtcFormatDate();
dic["到期日期"] = data.ExerciseDate.OtcFormatDate();
dic["结算日期"] = data.SettlementDate.OtcFormatDate();
dic["交易方向"] = data.BuySell;
dic["标的代码"] = data.UnderlyingCode;
dic["期初标的价格"] = data.SpotPrice.OtcFormatUmPrice();
dic["执行价格"] = data.Strike.OtcFormatUmPrice(isMoneyness);
dic["权利金成交"] = OtcFormatHelper.FormatPremium(data.IsUsePremiumRate, data.PremiumRate, data.TradeSinglePrice);
dic["有效成交数量"] = PS.Config.IsUseDisplayNotional ? (data.TradeOriginalAmount * data.CountRatio).OtcFormatNotional() : data.TradeOriginalAmount.OtcFormatNotional();
dic["成交数量"] = PS.Config.IsUseDisplayNotional ? (TradeCalcHelper.GetTradeAmountV(data) * data.CountRatio).OtcFormatNotional() : TradeCalcHelper.GetTradeAmountV(data).OtcFormatNotional();
dic["成交金额"] = data.TradePrice.OtcFormatMoney();
dic["名义本金"] = data.OriginalStockEqvNotional.OtcFormat(OtcFormatFlag.StockEqvNotional);
dic["实际名义本金"] = dic["有效名义本金"] = data.StockEqvNotionalReal.OtcFormat(OtcFormatFlag.StockEqvNotional);
dic["期权年化"] = data.IsAnnualized ? "是" : "否";
dic["年化系数"] = data.AnnualizeFactor.OtcFormatFlex(2, 6);
dic["保底收益率"] = data.PrincipalRate.OtcFormatPercent(2);
dic["参与率"] = data.ParticipationRate.OtcFormatPercent(2);
dic["无风险利率"] = data.NoRiskRate.OtcFormatPercent(2);
dic["分红率"] = data.DividendRate.OtcFormatPercent(2);
dic["成交波动率"] = data.TradeOpenVolatility.OtcFormat(OtcFormatFlag.volatilityP);
dic["目标波动率"] = data.TradeCloseVolatility.OtcFormat(OtcFormatFlag.volatilityP);
dic["平滑过渡天数"] = data.NumOfSmoothingDays?.ToString();
dic["备注"] = data.Comments;
dic["敲入敲出状态"] = data.KnockInOutStatusObservation;
dic["了结序号"] = data.TcSequence.ToString();
dic["了结方式"] = data.TcAction;
dic["了结日期"] = data.TcValueDate.OtcFormatDate();
dic["了结标的价格"] = data.TcFinalPrice?.OtcFormatUmPrice();
dic["权利金了结"] = OtcFormatHelper.FormatPremium(data.IsUsePremiumRate, data.TcUnwindPricePercent, data.TcUnwindPrice)?.TrimStart('-');
dic["了结数量"] = PS.Config.IsUseDisplayNotional ? (data.TcUnwindTradeAmount * data.CountRatio).OtcFormatNotional() : data.TcUnwindTradeAmount.OtcFormatNotional();
dic["终止名义数量"] = PS.Config.IsUseDisplayNotional ? (data.TcUnwindTradeAmount * multiply * data.CountRatio).OtcFormatNotional() : (data.TcUnwindTradeAmount * multiply).OtcFormatNotional();
if (true)
{
}
var stopEqvNotional = isPremiumRate || data.TradeType == "累计期权" ? TradeHelper.GetStockEqvNotionalReal(data.OriginalStockEqvNotional, data.ParticipationRate, data.AnnualizeFactor) * data.TcUnwindPercent : data.TcUnwindNotional * data.SpotPrice;
if (data.TradeType == "雪球期权" || data.TradeType == "凤凰期权")
{
var part = data.OriginalStockEqvNotional * (data.ParticipationRate ?? 1);
var annual = part != 0 ? data.StockEqvNotionalReal / part : 0;
stopEqvNotional *= annual;
}
dic["终止实际名义金额"] = stopEqvNotional.HasValue ? Math.Abs(stopEqvNotional.Value).OtcFormat(OtcFormatFlag.StockEqvNotional) : "";
dic["了结金额"] = data.TcAmount.OtcFormatMoney();
dic["成交金额"] = data.TcTradePrice.OtcFormatMoney();
dic["实现盈亏"] = data.WinLoss.OtcFormatMoney();
dic["相对行权价"] = data.IsMoneynessOption == "是" ? "是" : "";
dic["期权费率方式"] = data.IsUsePremiumRate == true ? "是" : "";
dic["保底收益总额"] = data.OriginalPrincipalSum.OtcFormatUmPrice();
}
//创建查询
private IQueryable<OtcTradeDetail> CreateQuery(TradeMultiCloseQueryModel queryModel)
{
if (queryModel is null)
{
throw new ArgumentNullException(nameof(queryModel));
}
BuildPredicate(queryModel, out var tdPredicate, out var tcPredicate);
var query = from t in DbContext.trade.Where(tdPredicate)
join tc in DbContext.trade_cash.Where(tcPredicate) on t.id equals tc.TradeId
select new OtcTradeDetail
{
id = t.id,
TcId = tc.id,
UnderlyingId = t.UnderlyingId,
TradeNumber = t.TradeNumber,
ClientId = t.ClientId,
ClientName = t.ClientName,
TradeDate = t.TradeDate,
ExerciseDate = t.ExerciseDate,
BuySell = t.BuySell,
TradeType = t.TradeType,
OptionType = t.OptionType,
UnderlyingAssetName = t.UnderlyingAssetName,
UnderlyingCode = t.UnderlyingCode,
SpotPrice = t.SpotPrice,
Strike = t.Strike,
IsMoneynessOption = t.IsMoneynessOption,
TradeSinglePrice = t.TradeSinglePrice ?? 0,
TradePrice = t.TradePrice ?? 0,
IsUsePremiumRate = t.IsUsePremiumRate,
PremiumRate = t.PremiumRate,
TradeAmount = t.TradeAmount,
ExerciseMode = t.ExerciseMode,
OriginalNotional = t.OriginalNotional ?? 0,
StockEqvNotionalReal = t.StockEqvNotionalReal,
OriginalStockEqvNotional = t.OriginalStockEqvNotional,
ParticipationRate = t.ParticipationRate,
AnnualizeFactor = t.AnnualizeFactor,
PrincipalRate = t.PrincipalRate ?? 0,
OriginalPrincipalSum = t.OriginalPrincipalSum,
TcValueDate = tc.HappenedDate != null ? tc.HappenedDate : tc.ValueDate,
TcFinalPrice = tc.FinalPrice,
TcUnwindPrice = tc.UnwindPrice,
TcUnwindPricePercent = tc.UnwindPricePercentRate,
TcAmount = tc.Amount,
UnWindNotional = tc.UnwindNotional ?? (tc.IsLastAction ? tc.Notional : 0),
TcUnwindTradeAmount = tc.UnwindTradeAmount ?? (tc.IsLastAction ? tc.TradeAmount : 0),
TcUnwindPercent = tc.UnwindPercentRate,
TcAction = tc.Action,
TcExerciseWay = tc.ExerciseWay,
StructureType = t.StructureType,
IsGroup = t.IsGroup,
IsLastAction = tc.IsLastAction,
GroupTradeType = t.IsGroup == 0 ? "正常交易" : (t.IsGroup == 1 ? "分组主交易" : "分组子交易"),
ExtendInfo = t.ExtendInfo,
TraderName = t.TraderName,
AssetBookName = t.AssetBookName
};
if (queryModel.UnWindTimes != null && queryModel.UnWindTimes >= 0)
{
var qgp = from f in query
group f by f.id into fgp
where fgp.Count() == queryModel.UnWindTimes
select fgp.Key;
query = query.Where(q => qgp.Contains(q.id));
}
return query = query.OrderByDescending(x => x.id).ThenBy(x => x.TcValueDate).ThenBy(x => x.TcId);
}
private List<OtcTradeDetail> CreateGroupChildrenQuery(int[] parentTradeCashIds)
{
var query = from t in DbContext.trade
join tc in DbContext.trade_cash.Where(x => parentTradeCashIds.Contains(x.ParentTradeCashId)) on t.id equals tc.TradeId
select new OtcTradeDetail
{
id = t.id,
TcId = tc.id,
ParentTcId = tc.ParentTradeCashId,
UnderlyingId = t.UnderlyingId,
TradeNumber = t.TradeNumber,
ClientId = t.ClientId,
ClientName = t.ClientName,
TradeDate = t.TradeDate,
ExerciseDate = t.ExerciseDate,
BuySell = t.BuySell,
TradeType = t.TradeType,
OptionType = t.OptionType,
UnderlyingAssetName = t.UnderlyingAssetName,
UnderlyingCode = t.UnderlyingCode,
SpotPrice = t.SpotPrice,
Strike = t.Strike,
IsMoneynessOption = t.IsMoneynessOption,
TradeSinglePrice = t.TradeSinglePrice ?? 0,
TradePrice = t.TradePrice ?? 0,
IsUsePremiumRate = t.IsUsePremiumRate,
PremiumRate = t.PremiumRate,
TradeAmount = t.TradeAmount,
ExerciseMode = t.ExerciseMode,
OriginalNotional = t.OriginalNotional ?? 0,
StockEqvNotionalReal = t.StockEqvNotionalReal,
OriginalStockEqvNotional = t.OriginalStockEqvNotional,
ParticipationRate = t.ParticipationRate,
AnnualizeFactor = t.AnnualizeFactor,
PrincipalRate = t.PrincipalRate ?? 0,
TcValueDate = tc.HappenedDate != null ? tc.HappenedDate : tc.ValueDate,
TcFinalPrice = tc.FinalPrice,
TcUnwindPrice = tc.UnwindPrice,
TcUnwindPricePercent = tc.UnwindPricePercentRate,
TcAmount = tc.Amount,
UnWindNotional = tc.UnwindNotional ?? tc.Notional,
TcUnwindTradeAmount = tc.UnwindTradeAmount,
TcUnwindPercent = tc.UnwindPercentRate,
TcAction = tc.Action,
TcExerciseWay = tc.ExerciseWay,
StructureType = t.StructureType,
IsGroup = t.IsGroup,
GroupTradeType = t.IsGroup == 0 ? "正常交易" : (t.IsGroup == 1 ? "分组主交易" : "分组子交易")
};
var list = query.OrderByDescending(x => x.id).ThenBy(x => x.TcValueDate).ThenBy(x => x.id).ToList();
OtcTradeDetail preData = null;
foreach (var data in list)
{
data.CountRatio = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(data.UnderlyingCode)?.CountRatio;
preData = ProcessData(data, preData);
HandleExportData(data);
}
new TradeExtendService(this).SetTradeExtendWithCnKey(list);
return list;
}
//构建查询条件
private void BuildPredicate(TradeMultiCloseQueryModel queryModel, out Expression<Func<trade, bool>> tdPredicate
, out Expression<Func<trade_cash, bool>> tcPredicate)
{
tdPredicate = PredicateBuilder.Create<trade>(t => t.ClientId > 0);
if (string.IsNullOrEmpty(queryModel.TradeNumber) || (queryModel.UnWindType != "全部" && queryModel.UnWindType != "了结")) //todo:需要重构
{
tdPredicate = tdPredicate.And(t => t.IsGroup != 2);
}
if (queryModel.UserAssets != null || queryModel.UserClients != null)
{
tdPredicate = tdPredicate.And(n => queryModel.UserAssets.Contains(n.AssetId) || queryModel.UserClients.Contains(n.ClientId));
}
if (!queryModel.UseForwardASwap)
{
tdPredicate = tdPredicate.And(n => n.TradeType != "收益互换" && n.TradeType != "远期");
}
if (!string.IsNullOrWhiteSpace(queryModel.TradeStatus))
{
tdPredicate = tdPredicate.And(n => queryModel.TradeStatus.Contains(n.TradeStatus));
}
if (queryModel.TradeDateStart != null)
{
tdPredicate = tdPredicate.And(n => n.TradeDate >= queryModel.TradeDateStart.Value);
}
if (queryModel.TradeDateEnd != null)
{
tdPredicate = tdPredicate.And(n => n.TradeDate <= queryModel.TradeDateEnd.Value);
}
if (queryModel.ExerciseDateStart != null)
{
tdPredicate = tdPredicate.And(n => n.ExerciseDate >= queryModel.ExerciseDateStart.Value);
}
if (queryModel.ExerciseDateEnd != null)
{
tdPredicate = tdPredicate.And(n => n.ExerciseDate <= queryModel.ExerciseDateEnd.Value);
}
if (queryModel.TagIds != null && queryModel.TagIds.Count > 0)
{
var tradeTagIdQuery = from tt in DbContext.trade_tag
where queryModel.TagIds.Contains(tt.TagId)
select tt.TradeId;
tdPredicate = tdPredicate.And(p => tradeTagIdQuery.Contains(p.id));
}
if (!string.IsNullOrWhiteSpace(queryModel.TradeNumber))
{
var TradeNumber = queryModel.TradeNumber.Trim();
if (queryModel.UnWindType == "全部" || queryModel.UnWindType == "了结")
{
tdPredicate = tdPredicate.And(n => n.TradeNumber.Equals(TradeNumber));
}
else
{
tdPredicate = tdPredicate.And(n => n.TradeNumber.Contains(TradeNumber));
}
}
if (!string.IsNullOrWhiteSpace(queryModel.BuySell))
{
var BuySell = queryModel.BuySell.Trim();
tdPredicate = tdPredicate.And(n => n.BuySell == BuySell);
}
if (queryModel.ClientIdList.Any())
{
tdPredicate = tdPredicate.And(n => queryModel.ClientIdList.Contains(n.ClientId));
}
if (!string.IsNullOrWhiteSpace(queryModel.StructureType))
{
tdPredicate = tdPredicate.And(n => n.StructureType.Contains(queryModel.StructureType));
}
if (!string.IsNullOrWhiteSpace(queryModel.TradeTypes))
{
var typeList = queryModel.TradeTypes.Split(',').ToList();
tdPredicate = tdPredicate.And(n => typeList.Contains(n.TradeType) || typeList.Contains(n.StructureType) || (typeList.Contains("黑箱结构") && n.IsGroup == 1));
}
if (queryModel.UnderlyingIdList != null && queryModel.UnderlyingIdList.Any(n => n > 0))
{
tdPredicate = tdPredicate.And(n => queryModel.UnderlyingIdList.Contains(n.UnderlyingId));
}
if (!string.IsNullOrWhiteSpace(queryModel.ExerciseMode))
{
tdPredicate = tdPredicate.And(n => n.ExerciseMode == queryModel.ExerciseMode);
}
//--------------------------------------------------------
tcPredicate = PredicateBuilder.Create<trade_cash>(tc => tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted
&& (tc.Action == "系统操作-行权费" || tc.Action == "系统操作-平仓费" || tc.Action == "系统操作-票息" || tc.Action == "系统操作-互换"));
//了结方式过滤
if (!string.IsNullOrWhiteSpace(queryModel.UnWindType) && queryModel.UnWindType != "全部")
{
if (queryModel.UnWindType == "票息")
{
tcPredicate = tcPredicate.And(x => x.Action == "系统操作-票息");
}
else if (queryModel.UnWindType == "到期")
{
tcPredicate = tcPredicate.And(x => x.ExerciseWay == TradeCashExerciseWayEnum.到期行权 && x.Action != "系统操作-票息");
}
else if (queryModel.UnWindType == "了结")
{
tcPredicate = tcPredicate.And(x => x.Action != "系统操作-票息");
}
else
{
tcPredicate = tcPredicate.And(x => x.ExerciseWay == TradeCashExerciseWayEnum.提前终止行权 && x.Action != "系统操作-票息");
}
}
if (queryModel.TradeCashIdList != null && queryModel.TradeCashIdList.Any(x => x > 0))
{
tcPredicate = tcPredicate.And(tc => queryModel.TradeCashIdList.Contains(tc.id));
}
if (queryModel.UnwindDateStart != null)
{
var UnwindDateStart = queryModel.UnwindDateStart.Value;
tcPredicate = tcPredicate.And(tc => tc.HappenedDate.Value >= UnwindDateStart || tc.ValueDate >= UnwindDateStart);
}
if (queryModel.UnwindDateEnd != null)
{
var UnwindDateEnd = queryModel.UnwindDateEnd.Value;
tcPredicate = tcPredicate.And(tc => tc.ValueDate <= UnwindDateEnd);
}
}
}
}