using BaseOUDAL; using Newtonsoft.Json.Linq; using OfficeOpenXml; using Qdp.Foundation.Utilities; using Qdp.Pricing.Base.Enums; using Qdp.Pricing.Library.Common.Interfaces; using Qdp.Pricing.Library.Options.Products.Asian; using System; using System.Collections.Specialized; using System.Diagnostics.Contracts; using System.Text; using System.Web; using YieldChain.Helpers; using YLErp.Abstract; using YLErp.BLL; using YLErp.BLL.Eod; using YLErp.BLL.EodSettlement; using YLErp.BLL.MarginCalculation; using YLErp.Commons; using YLErp.Configuration; using YLErp.DBModels; using YLErp.DBModels.Abstract; using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.Helpers; using YLErp.Model; using YLErp.Models; using YLErp.Modules.ApiModule.ExportModule; using YLErp.Modules.CalculationModule; using YLErp.Modules.DataProviderModule; using YLErp.Modules.TradeDalModule; using YLErp.Office; using YLErp.Office.Converters; using YLErp.Plugins.TradeDocGenerator; using YLErp.Plugins.TradeDocGenerator.Abstracts; using YLErp.QdpModule; using YLErp.Modules.SwapModule; namespace YLErp.Modules.TradeModule.DocGenerateModule { public class ConfirmationGenerateContext : YLBaseService, ITradeDocGeneratorContext, ITradeConfirmationGeneratotContext { /// /// 生成确认书时,用户选择的资金记录 /// public IEnumerable UserTradeCashIds { get; } /// /// 同步锁 /// private static readonly object _syncLock = new object(); /// /// 确认书编号缓存 处理 确认书生成出重复编号问题,浙期已修改,如果其他公司有类似问题请参照这次提交代码 /// key 是合约编号 /// value[tradecashid,当前时间] 过期时间1h /// 汤旺 /// private static Dictionary ContractCodeCache = new Dictionary(); /// /// [必需]交易记录 /// public OtcTradeBase Trade { get; } public IEnumerable SubTrades { get; } private readonly trade_cash _tradeCash; private readonly List _subTradeCashes = new List(); /// /// [必需]合约业务接口 /// public IContractBLL ContractBLL { get; } /// /// 浮动平仓事件集 /// public readonly List FlowEvents; /// /// 平仓事件集 /// public readonly List AllFlowEvents = new List(); /// /// 交易持仓腿集合 /// public readonly List SwapPositions = new List(); /// /// [必需]期权数据提供接口 /// public ITradeExtendDataProvider TradeDataProvider { get; } readonly string _contractType; public ConfirmationGenerateContext(IEnumerable tradeCashIds, IEnumerable trades, string contractType, OptUserInfo userInfo, DateTime? startDate, DateTime? endDate) : this(((tradeCashIds?.FirstOrDefault()) ?? 0), trades.First(), contractType, userInfo) { Trades = trades.GroupBy(O => O.id).Select(O => O.First()).ToList() ?? throw new ArgumentNullException(nameof(trades)); TradeCashes = trades.GroupBy(O => O.id).ToDictionary(K => K.Key, V => V.Where(O => O.trade_cash != null).Select(O => O.trade_cash).ToList()); var structureTrades = trades.Where(O => O.TradeType == "结构化交易"); var subTrade = new List(); foreach (var item in structureTrades) { if (item.SubTrades != null) { subTrade.AddRange(item.SubTrades); var idArr = TradeCashes[item.id].Select(O => O.id); var obj = item.SubTrades.Where(O => O.trade_cash != null && !idArr.Contains(O.trade_cash.id)).Select(O => O.trade_cash); TradeCashes[item.id].AddRange(obj); } TradeCashes[item.id].RemoveAll(O => O == null); } subTrade = subTrade.GroupBy(O => O.id).Select(O => O.FirstOrDefault()).ToList(); if (tradeCashIds == null || tradeCashIds.Count() == 0) { tradeCashIds = trades.Select(O => (O.trade_cash?.id) ?? 0).Concat(subTrade.Select(O => (O.trade_cash?.id) ?? 0)).ToArray(); } SubTrades = subTrade; UserTradeCashIds = tradeCashIds; StartDate = startDate; EndDate = endDate; } /// /// 构造函数 /// public ConfirmationGenerateContext(int tradeCashId, trade tradeObj, string contractType, OptUserInfo userInfo) : base(userInfo) { Trade = tradeObj ?? throw new ArgumentNullException(nameof(tradeObj)); Trades = new[] { tradeObj }; if (tradeObj.TradeType == "结构化交易") { SubTrades = tradeObj.SubTrades; if (tradeObj.SubTrades != null) { foreach (var trade in tradeObj.SubTrades) { _subTradeCashes.Add(trade.trade_cash ?? throw new ArgumentNullException("trade.SubTrades[].trade_cash")); } } var checkCash = _subTradeCashes.GroupBy(O => $"{O.Action}_{O.Notional}_{O.UnwindNotional}").ToDictionary(K => K.Key, V => 1); if (tradeObj.StructureType == "蝶式组合") { var tradecash = _subTradeCashes.GroupBy(o => new { Action = o.Action, TradeType = o.TradeType }).Select(o => new { Action = o.Key.Action, TradeType = o.Key.TradeType, Notional = o.Sum(s => s.Notional), UnwindNotional = o.Sum(s => s.UnwindNotional) }); checkCash = tradecash.GroupBy(O => $"{O.Action}_{O.Notional}_{O.UnwindNotional}").ToDictionary(K => K.Key, V => 1); } //浙期存在参与率不一致的组合交易,会导致有效数量不一致,黑箱不参与资金检查,例如子交易有现金流交易notioal为0 if (checkCash.Count > 1 && !PS.Config.Is浙期 && tradeObj.IsGroup != 1 && tradeObj.StructureType != "风险逆转" && tradeObj.TradeType != "三领口") { throw new InvalidOperationException("子交易资金记录不匹配!"); } if (tradeCashId == 0) { tradeCashId = _subTradeCashes.FirstOrDefault()?.id ?? 0; } _tradeCash = _subTradeCashes.Where(O => O.id == tradeCashId).FirstOrDefault(); if (tradeObj.IsGroup == 1) { _tradeCash = tradeObj.trade_cash ?? throw new ArgumentNullException(nameof(trade.trade_cash)); } } //else if (tradeObj.TradeType == "结构化交易" && tradeObj.IsGroup == 1) //{ // _tradeCash = tradeObj.trade_cash ?? throw new ArgumentNullException(nameof(trade.trade_cash)); // if (tradeCashId == 0) // { // tradeCashId = tradeObj.trade_cash.id; // } // SubTrades = tradeObj.SubTrades; // foreach (var trade in tradeObj.SubTrades) // { // _subTradeCashes.Add(trade.trade_cash ?? throw new ArgumentNullException("trade.SubTrades[].trade_cash")); // } // var checkCash = _subTradeCashes.GroupBy(O => $"{O.Action}_{O.Notional}_{O.UnwindNotional}").ToDictionary(K => K.Key, V => 1); // if (checkCash.Count > 1) // { // throw new InvalidOperationException("子交易资金记录不匹配!"); // } //} else { // _tradeCash = tradeObj.trade_cash ?? throw new ArgumentNullException(nameof(trade.trade_cash)); // if (tradeCashId == 0) // { tradeCashId = tradeObj.trade_cash.id; } SubTrades = new List() { Trade }; } // UserTradeCashIds = new[] { tradeCashId }; _client = DataCacheProvider.GetClientDataSource().GetData(tradeObj.ClientId) ?? throw new ArgumentNullException(nameof(tradeObj.ClientId)); _contractType = contractType ?? throw new ArgumentNullException(nameof(contractType)); ContractBLL = new TradeContractBLL(this); TradeDataProvider = new TradeExtendDataProvider(this); // TradeCashes = new Dictionary>() { { tradeObj.id, new List { _tradeCash } } }; // TradeCashes[Trade.id].AddRange(_subTradeCashes); // TradeCashes[Trade.id].RemoveAll(O => O == null); string fixing = null; //亚式期权 if (tradeObj.TradeType == "亚式期权") { fixing = AsianOptionFixingService.GetFixingString(tradeObj.trade_cash.ValueDate, tradeObj); fixing = FixingService.AddOrReplaceLastDateSpotPrice(fixing, tradeObj.trade_cash.ValueDate, tradeObj.trade_cash.FinalPrice ?? 0.0); if (PS.Config.Is润和 && tradeObj.trade_cash.CreateTime != null && tradeObj.trade_cash.ValueDate.ToString("yyyy-MM-dd").Equals(tradeObj.trade_cash.CreateTime.OtcFormatDate()) && tradeObj.trade_cash.CreateTime.Value.Hour < 15) { var index = fixing.IndexOf(tradeObj.trade_cash.ValueDate.ToString("yyyy-MM-dd")); if (index >= 0) { fixing = fixing.Remove(index).TrimEnd(';'); } } } Trade.Fixing = fixing; } public ConfirmationGenerateContext(Client client, List flowEvents, List allFlowEvents, List trades, List swapPositions, string contractType, OptUserInfo userInfo) : base(userInfo) { _client = client; _contractType = contractType ?? throw new ArgumentNullException(nameof(contractType)); ContractBLL = new TradeContractBLL(this); TradeDataProvider = new TradeExtendDataProvider(this); Trades = trades; FlowEvents = flowEvents; AllFlowEvents = allFlowEvents; SwapPositions = swapPositions; } /// /// 获取系统配置接口对象 /// public IErpConfig GetErpConfig() { return PS.GetErpConfig(); } /// /// 转换word文档为pdf文档 /// public void ConvertDocToPDF(string wordDocPath, string targetPdfPath) { OfficeFileConverter.ConvertFileFormat(wordDocPath, targetPdfPath); } /// /// 根据Excel文档模板生成文档 /// public void GenerateExcelFromTemplate(string templatePath, Dictionary modelDic, string outputFilePath, bool genPdf = true) { var templaExt = Path.GetExtension(templatePath); var outputExt = Path.GetExtension(outputFilePath); var tmpOutputFilePath = outputFilePath; if (templaExt == ".xlsx") { //特殊处理:使用excel模板生成文档。 tmpOutputFilePath = outputFilePath.Replace(".docx", ".xlsx").Replace(".pdf", ".xlsx"); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; new ExcelTemplateGenerator() .SetTemplateFile(templatePath) .SetTemplateData(modelDic.ToDictionary(n => n.Key, n => (object)n.Value)) .OutputToFile(tmpOutputFilePath); } else { //new ExcelTemplateGenerator().SetTemplateFile(templatePath).SetTemplateData(modelDic).OutputToFile(outputFilePath); } if (genPdf) { var outputPdfFile = FileHelper.ReplaceExtension(tmpOutputFilePath, ".pdf"); OfficeFileConverter.ConvertFileFormat(tmpOutputFilePath, outputPdfFile); } } public void GenerateExcelFromTemplate(string templatePath, Dictionary modelDic, string outputFilePath, bool genPdf = true) { var templaExt = Path.GetExtension(templatePath); var outputExt = Path.GetExtension(outputFilePath); var tmpOutputFilePath = outputFilePath; if (templaExt == ".xlsx") { //特殊处理:使用excel模板生成文档。 tmpOutputFilePath = outputFilePath.Replace(".doc", ".xlsx").Replace(".docx", ".xlsx").Replace(".pdf", ".xlsx"); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; new ExcelTemplateGenerator() .SetTemplateFile(templatePath) .SetTemplateData(modelDic) .OutputToFile(tmpOutputFilePath); } else { //new ExcelTemplateGenerator().SetTemplateFile(templatePath).SetTemplateData(modelDic).OutputToFile(outputFilePath); } if (genPdf) { var outputPdfFile = FileHelper.ReplaceExtension(tmpOutputFilePath, ".pdf"); OfficeFileConverter.ConvertFileFormat(tmpOutputFilePath, outputPdfFile); } } /// /// 根据Word文档模板生成文档 /// public void GenerateDocFromTemplate(string templatePath, Dictionary modelDic, string outputFilePath, bool genPdf = true) { //WordHelper.GenerateFromTemplate(templatePath, modelDic, outputFilePath); var varDic = new JsonVarDic(modelDic); var _outputFilePath = outputFilePath.Replace(".pdf", ".docx"); LogFactory.GetLogger("Word生成").Info($"生成Word文档:{_outputFilePath}"); OfficeFileConverter.ConvertByUsingDocTemplate(templatePath, _outputFilePath, varDic, false); var toPDF = outputFilePath.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase); if (genPdf && toPDF) { LogFactory.GetLogger("Word生成").Info($"转换Word文档为PDF:{_outputFilePath}"); ConvertToPdfHelper.ConvertPDFByApi(HttpUtility.UrlEncode(_outputFilePath), HttpUtility.UrlEncode(outputFilePath)); } } /// /// 获取合成价差期权的商品标的名称 /// public string GetSyntheticUnderlyingName(string underlyingCode) { return synthetic_underlyingBLL.GetUnderlyingTipsInfo(underlyingCode); } /// /// 获取亚式期权行权价 /// /// /// public double? GetAsianStrikePrice(OtcTradeBase trade, DateTime valueDate) { var t = trade as trade; if (trade == null) { throw new TradeDocGenerateException($"交易信息出错 {trade?.TradeNumber}"); } if (t.TradeType == "亚式期权" && t.trade_asian_option == null) { tradeBLL.SetFieldsByTradeType(new[] { t }); } if (t.TradeType != "亚式期权" || t.trade_asian_option.StrikeType == StrikeStyle.Fixed.ToString()) { return trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike; } t.trade_asian_option.Fixings = AsianOptionFixingService.GetFixingString(valueDate, t); var QdpTrade = TradeCalcHelper.GetQdpTrade(t); if (QdpTrade != null && QdpTrade.Instrument != null && QdpTrade.Instrument is IOption opt) { var asianOpt = opt as AsianOption; return asianOpt.ActualStrike; } return null; } /// /// 获取亚式期权现价 /// /// /// public double? GetAsianFinalPrice(OtcTradeBase trade, trade_asian_option asian_option, DateTime valueDate) { if (trade == null || asian_option == null) { throw new TradeDocGenerateException($"交易信息出错 {trade?.TradeNumber}"); } if (trade.TradeType != "亚式期权" || asian_option.StrikeType == StrikeStyle.Fixed.ToString()) { return trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike; } asian_option.Fixings = AsianOptionFixingService.GetFixingString(valueDate, trade, asian_option); var QdpTrade = QdpTradeBuilder.GetAsianOptionTrade(trade, asian_option); if (QdpTrade != null && QdpTrade.Instrument != null && QdpTrade.Instrument is IOption opt) { var asianOpt = opt as AsianOption; return asianOpt.FinalPrice(); } return null; } public DateTime? GetAveragingPeriodStartDate(OtcTradeBase trade) { if (trade.TradeType == "亚式期权") { var asianTrade = DbContext.trade_asian_option.Where(O => O.TradeId == trade.id).FirstOrDefault(); if (asianTrade != null) { return asianTrade.AveragingPeriodStartDate; } } if (trade.TradeType == "远期") { var forwardTrade = DbContext.trade_forward.Where(O => O.TradeId == trade.id).FirstOrDefault(); if (forwardTrade != null) { if (string.IsNullOrWhiteSpace(forwardTrade.ObservationDates)) { //如果为空返回到期日 return trade.ExerciseDate; } var observationDates = forwardTrade.ObservationDates.Split(',').OrderBy(o => o); if (DateTime.TryParse(observationDates.FirstOrDefault(), out var startDate)) { return startDate; } } } return null; } public void DelContractDocument(ITradeContractDocument contractDoc) { var db = DbContextFactory.GetYLDbContext(); var datas = db.trade_contract_r.Where(n => n.ContractCode == contractDoc.Code && n.Type == contractDoc.Type && n.IsValid).ToList(); //db.trade_contract_r.RemoveRange(datas); datas.ForEach(O => O.IsValid = false); var contractDocs = db.trade_contract_document.Where(x => x.Code == contractDoc.Code && x.Type == contractDoc.Type).ToArray(); db.trade_contract_document.RemoveRange(contractDocs); db.SaveChanges(); } /// /// 保存文档生成数据 /// public ITradeContractDocument SaveContractDocument(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null) { var documents = new List(); var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".docx"); var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Word; var tradecashDict = _subTradeCashes.Count == 0 ? new Dictionary>() { { Trade.id, new List() { (_tradeCash?.id ?? 0) } } } : _subTradeCashes.GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); if (Trade.IsGroup == 1) // 黑箱交易需要传主交易和子交易 { tradecashDict[Trade.id] = new List() { _tradeCash.id }; } var trades = new List() { Trade }; if (Trade.TradeType == "结构化交易" && SubTrades.Count() > 1) { trades.AddRange(SubTrades); } documents = SaveContractDocuments(trades, tradecashDict, contractCode, savedOutputFileName, fileType); ContractCodeCache.Remove(contractCode); return documents[0]; } /// /// 保存文档生成数据 /// public List SaveContractDocuments(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null) { var documents = new List(); var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".xlsx"); var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Excel; //var tradecashDict = TradeCashes.ToDictionary(K => K.Key, V => V.Value.Select(O => O.id).ToList()); var tradecashDict = new Dictionary>(); foreach (var item in TradeCashes) { for (var i = 0; i < item.Value.Count; i++) { if (!tradecashDict.TryGetValue(item.Value[i].TradeId, out var value)) { tradecashDict[item.Value[i].TradeId] = new List() { item.Value[i].id }; } else { value.Add(item.Value[i].id); } } } var trades = Trades.ToList(); var structureTrades = Trades.Where(O => O.TradeType == "结构化交易" && O.IsGroup != 1).ToList(); foreach (trade item in structureTrades) { trades.AddRange(item.SubTrades); } documents = SaveContractDocuments(trades, tradecashDict, contractCode, savedOutputFileName, fileType); ContractCodeCache.Remove(contractCode); return documents; } /// /// 保存文档生成数据 /// public List SaveContractDocumentsByEventId(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null) { var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".xlsx"); var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Excel; var documents = SaveContractDocumentsByEventIds(Trades, FlowEvents, contractCode, savedOutputFileName, fileType); ContractCodeCache.Remove(contractCode); return documents; } /// /// 保存文档生成数据 /// /// /// /// /// /// /// /// private List SaveContractDocuments(IEnumerable trades, Dictionary> tradeCashIds, string contractCode, string fileName, string fileType) { lock (_syncLock) { var documents = new List(); var firstTrade = trades.First(); var isGJBuyer = firstTrade.BuySell == "买入"; var nowDate = DateTime.Now; var db = DbContextFactory.GetYLDbContext(); #region 清理历史数据 var tcIds = new List(); foreach (var item in tradeCashIds) { tcIds.AddRange(item.Value); } var tradeIds = trades.Select(x => x.id); //当生成分组主交易确认书时,没有tradeCashId if (_contractType == "交易确认书") { var datas = db.trade_contract_r.Where(O => tradeIds.Contains(O.TradeId) && O.IsValid && O.Type == _contractType).ToList(); datas.ForEach(O => O.IsValid = false); } else { var datas = db.trade_contract_r.Where(O => tcIds.Contains(O.TradeCashId ?? 0) && O.IsValid).ToList(); datas.ForEach(O => O.IsValid = false); } //db.trade_contract_r.RemoveRange(datas); //var codes = datas.Select(O => O.ContractCode); //var contractDocs = db.trade_contract_document.Where(O => codes.Contains(O.Code)).ToArray(); //db.trade_contract_document.RemoveRange(contractDocs); #endregion var contractRecord = db.trade_contract_document.Where(O => O.Code == contractCode && O.Type == _contractType).FirstOrDefault(); if (contractRecord == null) { contractRecord = new trade_contract_document(); db.trade_contract_document.Add(contractRecord); } contractRecord.Code = contractCode; contractRecord.ValueDate = SystemValueDate; contractRecord.BuyerId = isGJBuyer ? 0 : firstTrade.ClientId; contractRecord.BuyerName = isGJBuyer ? (PS.Config.CompanyName ?? "") : firstTrade.ClientName; contractRecord.SellerId = isGJBuyer ? firstTrade.ClientId : 0; contractRecord.SellerName = isGJBuyer ? firstTrade.ClientName : (PS.Config.CompanyName ?? ""); contractRecord.FileType = fileType; contractRecord.Status = ContractStatusEnum.Draft; contractRecord.SourceType = 1; // 系统生成 contractRecord.Paths = "/App_Docs/contractdoc/output/" + fileName; contractRecord.FileName = fileName; contractRecord.StampDocumentFileName = null; contractRecord.SealErrMsg = null; contractRecord.SealResult = null; contractRecord.Comments = null; contractRecord.DayNumber = null; contractRecord.ContractVersion = null; contractRecord.Type = _contractType; contractRecord.OptId = UserId; contractRecord.OptName = UserName; contractRecord.OptDate = nowDate; contractRecord.ClientId = firstTrade.ClientId; contractRecord.StampDocumentFileName = null; contractRecord.SealResult = null; foreach (var item in trades) { if (item.TradeType == "结构化交易" && item.IsGroup == 0) { //var cTrade = trades.First(O => O.ParentTradeId == item.id); //var contractTradeRelation = new trade_contract_r(); //db.trade_contract_r.Add(contractTradeRelation); //contractTradeRelation.TradeId = item.id; //contractTradeRelation.TradeNumber = item.TradeNumber; //contractTradeRelation.ContractCode = contractRecord.Code; //contractTradeRelation.TradeClearCode = contractRecord.Code; //contractTradeRelation.Type = _contractType; //contractTradeRelation.OptId = UserId; //contractTradeRelation.OptName = UserName; //contractTradeRelation.OptDate = nowDate; //contractTradeRelation.TradeCashId = tradeCashIds[cTrade.id][0]; //contractTradeRelation.IsValid = true; //documents.Add(contractRecord); continue; } else { if (tradeCashIds.Any()) { var tcList = tradeCashIds[item.id].Distinct().ToList(); for (var i = 0; i < tcList.Count; i++) { var contractTradeRelation = new trade_contract_r(); db.trade_contract_r.Add(contractTradeRelation); contractTradeRelation.TradeId = item.id; contractTradeRelation.TradeNumber = item.TradeNumber; contractTradeRelation.ContractCode = contractRecord.Code; contractTradeRelation.TradeClearCode = contractRecord.Code; contractTradeRelation.Type = _contractType; contractTradeRelation.OptId = UserId; contractTradeRelation.OptName = UserName; contractTradeRelation.OptDate = nowDate; contractTradeRelation.TradeCashId = tcList[i]; contractTradeRelation.IsValid = true; documents.Add(contractRecord); } } else { var contractTradeRelation = new trade_contract_r(); db.trade_contract_r.Add(contractTradeRelation); contractTradeRelation.TradeId = item.id; contractTradeRelation.TradeNumber = item.TradeNumber; contractTradeRelation.ContractCode = contractRecord.Code; contractTradeRelation.TradeClearCode = contractRecord.Code; contractTradeRelation.Type = _contractType; contractTradeRelation.OptId = UserId; contractTradeRelation.OptName = UserName; contractTradeRelation.OptDate = nowDate; contractTradeRelation.IsValid = true; documents.Add(contractRecord); } } } //var parentIds = trades.Where(O => O.TradeType == "结构化交易").Select(O => O.id).ToHashSet(); ////解决生成子交易确认书时,主交易编号查询不到的问题,在此使用主交易编号创建一条记录; //if (parentIds.Any()) //{ // foreach (var item in parentIds) // { // OtcTradeBase parentTrade = trades.First(O => O.id == item); // var contractTradeRelation = new trade_contract_r(); // db.trade_contract_r.Add(contractTradeRelation); // contractTradeRelation.TradeId = parentTrade.id; // contractTradeRelation.TradeNumber = parentTrade.TradeNumber; // contractTradeRelation.ContractCode = contractRecord.Code; // contractTradeRelation.TradeClearCode = contractRecord.Code; // contractTradeRelation.Type = _contractType; // contractTradeRelation.OptId = OptId; // contractTradeRelation.OptName = OptName; // contractTradeRelation.OptDate = nowDate; // contractTradeRelation.TradeCashId = tradeCashIds[item][0]; // documents.Add(contractRecord); // } //} db.SaveChanges(); return documents; } } /// /// 保存文档生成数据 /// /// /// /// /// /// /// /// private List SaveContractDocumentsByEventIds(IEnumerable trades, List flow_Events, string contractCode, string fileName, string fileType) { lock (_syncLock) { var documents = new List(); var firstTrade = trades.First(); var isGJBuyer = firstTrade.BuySell == "买入"; var nowDate = DateTime.Now; var db = DbContextFactory.GetYLDbContext(); #region 清理历史数据 var flowEventIds = flow_Events.Select(s => s.id).ToList(); var eventDate = flow_Events.First().UnwindDate.Value; var tradeIds = trades.Select(x => x.id); if (_contractType == "交易确认书") { var datas = db.trade_contract_r.Where(O => tradeIds.Contains(O.TradeId) && O.IsValid && O.Type == _contractType).ToList(); datas.ForEach(O => O.IsValid = false); } else { var datas = db.trade_contract_r.Where(O => flowEventIds.Contains(O.SwapFlowEventId ?? 0) && O.IsValid).ToList(); datas.ForEach(O => O.IsValid = false); } #endregion var contractRecord = db.trade_contract_document.Where(O => O.Code == contractCode && O.Type == _contractType).FirstOrDefault(); if (contractRecord == null) { contractRecord = new trade_contract_document(); db.trade_contract_document.Add(contractRecord); } contractRecord.Code = contractCode; contractRecord.ValueDate = eventDate; contractRecord.BuyerId = isGJBuyer ? 0 : firstTrade.ClientId; contractRecord.BuyerName = isGJBuyer ? (PS.Config.CompanyName ?? "") : firstTrade.ClientName; contractRecord.SellerId = isGJBuyer ? firstTrade.ClientId : 0; contractRecord.SellerName = isGJBuyer ? firstTrade.ClientName : (PS.Config.CompanyName ?? ""); contractRecord.FileType = fileType; contractRecord.Status = ContractStatusEnum.Draft; contractRecord.SourceType = 1; // 系统生成 contractRecord.Paths = "/App_Docs/contractdoc/output/" + fileName; contractRecord.FileName = fileName; contractRecord.StampDocumentFileName = null; contractRecord.SealErrMsg = null; contractRecord.SealResult = null; contractRecord.Comments = null; contractRecord.DayNumber = null; contractRecord.ContractVersion = null; contractRecord.Type = _contractType; contractRecord.OptId = UserId; contractRecord.OptName = UserName; contractRecord.OptDate = nowDate; contractRecord.ClientId = firstTrade.ClientId; contractRecord.StampDocumentFileName = null; contractRecord.SealResult = null; foreach (var item in flow_Events) { var contractTradeRelation = new trade_contract_r(); db.trade_contract_r.Add(contractTradeRelation); contractTradeRelation.TradeId = item.SwapTradeId; contractTradeRelation.TradeNumber = item.SwapTradeNo; contractTradeRelation.ContractCode = contractRecord.Code; contractTradeRelation.TradeClearCode = contractRecord.Code; contractTradeRelation.Type = _contractType; contractTradeRelation.OptId = UserId; contractTradeRelation.OptName = UserName; contractTradeRelation.OptDate = nowDate; contractTradeRelation.SwapFlowEventId = item.id; contractTradeRelation.IsValid = true; documents.Add(contractRecord); } db.SaveChanges(); return documents; } } /// /// 获取生成文档的输出路径(物理路径) /// public string GetOutputFilePath(string fileName) { var folder = Path.Combine(OtcAppContext.AppDocsPath, "contractdoc", "output"); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } return Path.Combine(folder, fileName); } //-------------------------------------- // 方法定义--数据获取 //-------------------------------------- Variety _variety; underlying_manager _underlying; Market _market; ClientBankCard _bankcard; ClientDuty _clientduty; Client _client; Dictionary _tradeMetas; /// /// 获取交易关联的客户信息 /// public Client GetClient() { if (_client == null) { _client = DataCacheProvider.GetClientDataSource().GetData(Trade.ClientId); if (_client == null) { throw new ServiceException($"客户(id:{Trade.ClientId},名称:{Trade.ClientName})信息未找到"); } } if (_client.IsDocShowParentName == 1 && _client.ParentId > 0) { var client = DataCacheProvider.GetClientDataSource().GetData(_client.ParentId); _client.Name = client.Name; } return _client; } public Client GetParentClient(int clientId) { var parentClient = new Client(); var client = DataCacheProvider.GetClientDataSource().GetData(clientId); if (client == null) { throw new ServiceException($"客户(id:{clientId})信息未找到"); } if (client.ParentId > 0) { parentClient = DataCacheProvider.GetClientDataSource().GetData(client.ParentId); if (_client == null) { throw new ServiceException($"父客户(id:{client.ParentId})信息未找到"); } } return parentClient; } /// /// 获取交易关联的结算资金信息 /// public ClientSettleBalance GetClientBalance(DateTime date) { var client = GetClient(); var clientbalances = ClientBalanceUtility.GetClientBanlances(new List() { client.id }, DateTime.MinValue, date); return clientbalances.FirstOrDefault(); } public ClientSettleBalance GetClientBalanceByReal(DateTime date) { var client = GetClient(); var clientbalances = new RealTimeClientBanlanceService(UserInfo).GetBanlances(new List() { client.id }, date, calcDate: date); return clientbalances.FirstOrDefault(); } /// /// 获取交易关联的标的 /// public underlying_manager GetTradeUnderlying() { return GetTradeUnderlying(Trade.UnderlyingCode); } /// /// 获取交易关联的标的 /// public underlying_manager GetTradeUnderlying(string underlyingCode) { if (_underlying == null || _underlying.UnderlyingCode != underlyingCode) { _underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); if (_underlying == null) { throw new ServiceException("标的资产信息未找到:" + Trade.UnderlyingCode); } } return _underlying; } /// /// 获取组合标的信息 /// /// /// public SyntheticUnderlying GetSyntheticUnderlying(string code) { return DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(code); } /// /// 获取交易关联的市场信息 /// /// public Market GetMarketInfo() { if (_market == null) { var underlying = GetTradeUnderlying(); _market = DbContext.market.Where(O => O.MarketName == underlying.MarketName).FirstOrDefault(); } if (_market == null) { throw new ServiceException($"标的{GetTradeUnderlying().MarketName}对应的市场信息未找到"); } return _market; } /// /// 获取交易关联的标的对应的品种信息 /// public Variety GetUnderlyingVariety() { if (_variety == null) { var UnderlyingTypeId = GetTradeUnderlying().UnderlyingTypeId; _variety = DbContext.variety.AsNoTracking().FirstOrDefault(x => x.id == UnderlyingTypeId); } if (_variety == null) { throw new ServiceException($"标的{GetTradeUnderlying().UnderlyingCode}对应的品种信息未找到"); } return _variety; } /// /// 获取交易关联的标的对应的品种信息 /// public Variety GetUnderlyingVariety(string underlyingCode) { _variety = null; var UnderlyingTypeId = GetTradeUnderlying(underlyingCode).UnderlyingTypeId; _variety = DbContext.variety.AsNoTracking().FirstOrDefault(x => x.id == UnderlyingTypeId); if (_variety == null) { throw new ServiceException($"标的{GetTradeUnderlying(underlyingCode).UnderlyingCode}对应的品种信息未找到"); } return _variety; } /// /// 获取客户银行卡 /// public ClientBankCard GetClientBankCard(bool throwExceptionIfNotFound = true) { var client = GetClient(); if (_bankcard == null) { _bankcard = DbContextFactory.GetClientDbContext(OptUser).bankcard.OrderByDescending(x => x.OptDate).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && x.ValidState != "InValid"); } if (_bankcard == null && throwExceptionIfNotFound) { throw new ServiceException($"客户{client.Name}对应的银行帐户信息未找到"); } return _bankcard; } /// /// 获取机构客户职责联系人信息 /// public ClientDuty GetClientDuty(bool throwExceptionIfNotFound = true) { var client = GetClient(); if (_clientduty == null) { _clientduty = DbContextFactory.GetClientDbContext(OptUser).clientduty.OrderBy(x => x.id).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && (x.DeadLine == null || x.DeadLine >= valuedateBLL.SystemDate.ValueDate) && x.ContactTypeId.Contains("1")); } if (_clientduty == null) { _clientduty = DbContextFactory.GetClientDbContext(OptUser).clientduty.OrderBy(x => x.id).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && (x.DeadLine == null || x.DeadLine >= valuedateBLL.SystemDate.ValueDate) && x.ContactTypeId.Contains("2")); } if (_clientduty == null && throwExceptionIfNotFound) { throw new ServiceException($"客户{client.Name}对应的机构联系人信息未找到"); } return _clientduty; } /// /// 获取客户法人/联系人 /// public ClientDuty GetClientDuty(int ContactTypeid) { var client = GetClient(); var ClientDuty = DbContextFactory.GetClientDbContext(OptUser).clientduty.Where(x => x.ApprovalOrder < 1 && x.ClientId == client.id && x.ContactTypeId.Contains(ContactTypeid.ToString()) && (x.DeadLine > DateTime.Now || x.DeadLine == null)).FirstOrDefault(); return ClientDuty; } /// /// 获取客户法人/联系人 /// public List GetClientDuties() { var client = GetClient(); var result = DbContextFactory.GetClientDbContext(OptUser).clientduty.Where(x => x.ApprovalOrder < 1 && x.ClientId == client.id && (x.DeadLine > DateTime.Now || x.DeadLine == null)).ToList(); return result; } public List GetContractTypes() { var result = DbContextFactory.GetClientDbContext(OptUser).contactype.ToList(); return result; } /// /// 获取工作日天数 /// public int GetWorkDayCount(DateTime from, DateTime to) { return QdpCalendarHelper.GetWorkDayCount(from, to); } /// /// 获取交易记录元数据 /// /// /// public NameValueCollection GetTradeMetas(int tradeId) { if (_tradeMetas == null) { _tradeMetas = new Dictionary(); } if (!_tradeMetas.ContainsKey(tradeId)) { _tradeMetas[tradeId] = new NameValueCollection(); var datas = DbContext.TradeMeta.Where(n => n.TradeId == tradeId).Select(n => new { n.MetaKey, n.MetaValue }).ToArray(); foreach (var data in datas) { _tradeMetas[tradeId][data.MetaKey] = data.MetaValue; } } return _tradeMetas[tradeId]; } /// /// 获取结构化交易所有行权价 /// /// public double[] GetStructureStrikes() { if (Trade.TradeType != "结构化交易") { return new double[0]; } //var arr = DbContext.trade.Where(n => n.ParentTradeId == Trade.id).Select(n => n.Strike).ToArray(); var arr = new TradeDalService(this).GetStructTradeFromTradeOrEodTrade(new[] { Trade.id }, SystemValueDate).Select(n => n.Strike).ToArray(); return arr.Select(n => n ?? 0).OrderBy(O => O).ToArray(); } /// /// 获取交易的初始预付金 /// public double GetInitialMargin() { //好像并没有使用,暂时注释掉代码逻辑,改为抛出异常。在V3.3及以后版本可以删除 throw new NotImplementedException(); //if (Trade.BuySell == "卖出") //{ // return 0; //} //var variety = GetUnderlyingVariety(); //var underlying = GetTradeUnderlying(); //underlying.QuotationDate = Trade.TradeDate; //var spotPrices = new double[] { Trade.SpotPrice ?? 0 }; //volatility vols = volatilityBLL.GetVols("交易", underlying); //if (!Trade.NoRiskRate.HasValue) //{ // Trade.NoRiskRate = (valuedateBLL.SystemDate.RiskFreeRate ?? 0) * 0.01; //} //var tradeObj = (trade)Trade; //if (tradeObj.TradeType == "结构化交易") //{ // tradeObj.SubTrades = DbContext.trade.Where(n => n.ParentTradeId == Trade.id).ToList(); //} //VolSurfaceInitializerSingleton.InitializeMarketProxy(underlying, vols.VolSurfaceMode, vols.VolTable, OptId.ToString(), false, 0, vols.InterpolationMethod); //var optionValue = OptionCalculator.GetOptionValueResult(OptId.ToString(), underlying, tradeObj, spotPrices, preciseTimeMode: true); ////预付金初始价值=期初期权价值+CashDelta(t)*预付金初始比例(预付金初始比例:两个涨跌停版) ////OTC-8856 Start //var UpLimitValue = variety.UpLimitValue; ////var UpLimitValue = ((Math.Abs(underlying.UpDownLimitValue) > 1e-5) ? underlying.UpDownLimitValue : variety.UpLimitValue); ////End //return (Trade.TradePrice ?? 0) + Math.Abs(optionValue == null ? 0 : optionValue.DeltaCash) * UpLimitValue; } /// /// 确认书文档生成后的处理 /// public bool OnConfirmationGenerated() { //var trade = DbContext.trade.Find(Trade.id); //var childTds = DbContext.trade.Where(x => x.ParentTradeId == Trade.id); //HasGeneratedConfirmBook 已经转换成 Function 不需要修改数据库 验证后可删除 //TradeDalService service = new TradeDalService(this); //var trade = service.GetTradeOrEodTrade(new[] { Trade.id }, ValueDate, true).FirstOrDefault(); //var childTds = service.GetStructTradeFromTradeOrEodTrade(new[] { Trade.id }, ValueDate, true); //trade.HasGeneratedConfirmBook = 1; //foreach (var child in childTds) //{ // child.HasGeneratedConfirmBook = 1; //} return true; } /// /// 获取主交易的资金信息 /// /// public trade_cash GetTradeCash() { return _tradeCash; } public trade_cash GetTradeCashById(int cashId) { return DbContext.trade_cash.Where(O => O.id == cashId).FirstOrDefault(); } public IEnumerable> GetTradeCashes(int tradeId) { //var tradeIds = DbContext.trade.Where(O => O.id == tradeId || O.ParentTradeId == tradeId).Select(O => O.id).ToList(); var tradeIds = new TradeDalService(this).GetTradeOrEodTradeOfTidAPid(new[] { tradeId }, SystemValueDate).Select(O => O.id).ToList(); if (GetErpConfig().Company == CompanyEnum.东莞) { var subTrades = GetSubTrades(tradeId); tradeIds.AddRange(subTrades.Select(n => n.id).ToList()); } IEnumerable cashes = DbContext.trade_cash.Where(O => tradeIds.Contains(O.TradeId) && O.ValidState != ConsGlobal.InValid && !O.IsDeleted).ToList(); var result = new List>(); var dates = cashes.Select(O => O.ValueDate).ToArray(); foreach (var c in cashes) { result.Add(new KeyValuePair( new TradeDalService(this).GetTradeOrEodTrade(new[] { c.TradeId }, c.ValueDate).First(), c)); } return result; } public IEnumerable GetSubTrades(int parentTradeId) { var trades = new TradeDalService(this).GetStructTradeFromTradeOrEodTrade(new[] { parentTradeId }, SystemValueDate).ToList(); return trades; } public OtcTradeBase GetParentTrade(int parentTradeId) { return DbContext.trade.Find(parentTradeId); } public List GetGroupTradeCashs(int parentTradeCashId) { return DbContext.trade_cash.Where(x => x.ParentTradeCashId == parentTradeCashId && x.ValidState != "InValid").ToList(); } /// /// 累计期权id获取转远期的tradecash记录 /// /// /// public List GetConvForwardTradeCash(int tradeId) { var forwardTradeNumberList = DbContext.autocall_observation.Where(n => n.TradeId == tradeId && n.SettlementMode.Contains("转远期")).Select(n => n.ConvTradeNumber).ToList(); var tradeCash = (from cash in DbContext.trade_cash join trade in DbContext.trade on cash.TradeId equals trade.id where trade.ValidState != "InValid" && cash.ValidState != "InValid" && forwardTradeNumberList.Contains(trade.TradeNumber) select cash).ToList(); return tradeCash; } /// /// 获取子交易的资金信息 /// /// public IEnumerable GetSubTradeCashes() { return _subTradeCashes; } public string DateFormat(DateTime date) { var month = date.Month.ToString(); if (date.Month == 10) { month = "A"; } else if (date.Month == 11) { month = "B"; } else if (date.Month == 12) { month = "C"; } var day = date.Day.ToString().PadLeft(2, '0'); return month + day; } public string DoubleFormat(double? value) { if (value == null) { return "0"; } if (Math.Floor(value.Value) == value) { return ((int)value).ToString(); } return value.Value.ToString("f1").Replace('.', 'd'); } public virtual string GenerateContractNo(out string contractIndex) { contractIndex = ""; string contractNo; #region 移除过期缓存 var guoqitime = DateTime.Now.AddHours(-1).Ticks; var liststr = new List(); foreach (var ContractCodeCache in ContractCodeCache) { if (ContractCodeCache.Value[1] - guoqitime < 0) { liststr.Add(ContractCodeCache.Key); } } liststr.ForEach(o => ContractCodeCache.Remove(o)); #endregion contractNo = GenerateGuolianContractNo(); return contractNo; } /// /// 生成国联确认书编号 /// private string GenerateGuolianContractNo() { if (_contractType != ContractTypeEnum.Trade) { return UniqueTimeId.GetStr(); } return Trade.TradeNumber; } public string GenerateWCZDChildrenContractNo(int tId, int tcId) { //所有确认书编号都在trademate里面存取 var contractNo = ""; var showcontractNo = ""; var prefix = GetClient().Number + "-"; var endFlag = ""; var contractC = DbContext.trade_contract_r_number.Where(_ => tId == (_.TradeId) && _.TradeConfirmNumber.StartsWith(prefix) && _.TradeConfirmNumberType == "C"); var currentTrade = DbContext.trade.Where(t => t.id == tId).First(); var tParentId = currentTrade.ParentTradeId > 0 ? currentTrade.ParentTradeId : 0; switch (_contractType) { case ContractTypeEnum.Trade: endFlag = "C"; //是否有父交易 if (currentTrade.ParentTradeId > 0) { contractC = DbContext.trade_contract_r_number.Where(_ => tParentId == (_.TradeParentId) && _.TradeConfirmNumber.StartsWith(prefix) && _.TradeConfirmNumberType == "C"); } if (contractC != null && contractC.Any()) { contractNo = contractC.First().TradeConfirmNumber; break; } else { var endPreFix = ""; //累计转远期特殊处理 if (currentTrade.TradeType == "远期" && (currentTrade.Comments ?? "").Contains("累计期权")) { var AcctradeFirst = DbContext.trade.Where(l => l.TradeNumber == currentTrade.Comments.Replace("累计期权:", "")).First(); //获取父数据的交易确认书编号 var AccParent = DbContext.trade_contract_r_number.Where(_ => AcctradeFirst.id == (_.TradeId) && _.TradeConfirmNumberType == endFlag); if (AccParent != null && AccParent.Any()) { prefix = AccParent.First().TradeConfirmNumber; prefix += "-"; if (AcctradeFirst?.ParentTradeId > 0) { var legs = DbContext.trade.Where(l => l.ParentTradeId == AcctradeFirst.ParentTradeId && AcctradeFirst.id >= l.id).Count(); endPreFix = "-yleg" + legs; } } else { throw new Exception("累计未生成交易确认书,导致远期找不到当前累计确认书编号!"); } } var codes = DbContext.trade_contract_r_number.Where(O => O.TradeConfirmNumber.StartsWith(prefix) && O.TradeConfirmNumber.EndsWith(endPreFix) && O.TradeConfirmNumberType == endFlag).Select(O => O.TradeConfirmNumber).ToHashSet(); var count = codes.Any() ? codes.Select(x => new { number = x.Substring(prefix.Length, (endPreFix).Length) }).Max(x => int.TryParse(x.number, out var num) ? num : 0) : 0; do { count++; contractNo = prefix + (count > 999 ? count.ToString("D4") : count.ToString("D3")) + endPreFix; } while (codes.Where(c => c.StartsWith(prefix) && c.Contains(contractNo) && c.EndsWith(endPreFix)).Any()); break; } case ContractTypeEnum.Clearing: case ContractTypeEnum.UnWind: endFlag = _contractType == ContractTypeEnum.Clearing ? "S" : "U"; if (contractC != null && contractC.Any()) { var contractS_Or_U = DbContext.trade_contract_r_number.Where(O => O.TradeId == tId && O.TradeCashId == tcId && O.TradeConfirmNumber.StartsWith(prefix) && O.TradeConfirmNumberType == endFlag); //是否有父交易 if (currentTrade.ParentTradeId > 0) { contractC = DbContext.trade_contract_r_number.Where(_ => tParentId == (_.TradeParentId) && _.TradeConfirmNumber.StartsWith(prefix) && _.TradeConfirmNumberType == "C"); } if (contractS_Or_U != null && contractS_Or_U.Any()) { contractNo = contractS_Or_U.First().TradeConfirmNumber; showcontractNo = contractS_Or_U.First().ShowTradeConfirmNumber; break; } var tradeCash = GetTradeCash(); if (currentTrade.IsGroup != 2 && currentTrade.ParentTradeId > 0) { //全部平仓一腿 var legs = DbContext.trade.Where(l => l.ParentTradeId == currentTrade.ParentTradeId && currentTrade.id >= l.id).Count(); contractNo = contractC.First().TradeConfirmNumber + "-leg" + legs; } else { contractNo = contractC.First().TradeConfirmNumber; } IEnumerable> trade_Cashes = GetTradeCashes(tId).Where(l => ((l.Value.UnwindType ?? "").Contains("部分") || (l.Value.UnwindType ?? "").Contains("全部")) && l.Value.id < tcId).OrderBy(l => l.Value.id); if (trade_Cashes != null && trade_Cashes.Any()) { showcontractNo = contractNo + "-" + (trade_Cashes.Count() + 1); } else { if (currentTrade.ParentTradeId == 0 || GetTradeCashes(tId).Where(l => (l.Value.UnwindType ?? "").Contains("部分")).Any()) { showcontractNo = contractNo + "-" + 1; } else { showcontractNo = contractNo; } } } else { throw new Exception("交易确认书未生成!"); } break; default: break; } if ((DbContext.trade_contract_r_number.Where(O => O.TradeId == tId && O.TradeParentId == tParentId && O.TradeCashId == tcId && O.TradeConfirmNumberType == endFlag).FirstOrDefault()) == null) { var trade_Contract_R_Number = new trade_contract_r_number() { TradeId = tId, TradeCashId = tcId, TradeConfirmNumber = contractNo, TradeConfirmNumberType = endFlag, TradeParentId = tParentId, ShowTradeConfirmNumber = String.IsNullOrWhiteSpace(showcontractNo) ? contractNo : showcontractNo, }; trade_Contract_R_Number.SetOpt(UserInfo); DbContext.trade_contract_r_number.Add(trade_Contract_R_Number); DbContext.SaveChanges(); } if (_contractType == "交易确认书") { //持仓编号[123,123C],[123,123U] var metaValue = contractNo; var legStr = ""; if (currentTrade.ParentTradeId == 0 && !metaValue.Contains("leg"))//)Trade.ParentTradeId == 0 && !Trade.Comments.Contains("累计期权")) { if ((currentTrade.Comments ?? "").Contains("累计期权")) { legStr += "-yleg1"; } else { legStr += "-leg1"; } } else if (currentTrade.ParentTradeId > 0 && !metaValue.Contains("leg")) { var legs = DbContext.trade.Where(l => l.ParentTradeId == currentTrade.ParentTradeId && tId >= l.id).Count(); legStr += "-leg" + legs; } metaValue += legStr; TradeMeta meta = null; if ((meta = DbContext.TradeMeta.Where(O => O.TradeId == tId && O.MetaKey == ConsTradeMetaKey.ContractCode).FirstOrDefault()) == null) { meta = new TradeMeta { TradeId = tId, MetaKey = ConsTradeMetaKey.ContractCode, MetaValue = metaValue, CreateTime = DateTime.Now }; DbContext.TradeMeta.Add(meta); DbContext.SaveChanges(); } } return ContractTypeEnum.Trade == _contractType ? contractNo : showcontractNo; } public string GetWCZDConfirmNumber(int tId, int tcId, string type) { return DbContext.trade_contract_r_number.Where(O => O.TradeId == tId && O.TradeCashId == tcId && O.TradeConfirmNumberType == type).FirstOrDefault().TradeConfirmNumber; } /// /// 获取价差期权 组合标的最大价格 /// /// public double GetDifferenceMaxPrice() { var query = DbContext.TradeMeta.Where(O => O.TradeId == Trade.id && O.MetaKey == "组合标的").FirstOrDefault(); var syntheticPrice = JsonHelper.Deserialize(query.MetaValue); var differenceMaxPrice = syntheticPrice.SuList.Select(l => l.Price * l.Coefficient).Max(); return differenceMaxPrice; } public int UnwindCount(trade_cash cash) { return UnwindCount(new List() { cash }); } /// /// 当前了结次数 /// public int UnwindCount(List cashes = null) { var num = 0; if (cashes == null) { if (Trade.TradeType != "结构化交易") { cashes = new List() { GetTradeCash() }; } else { cashes = GetSubTradeCashes().ToList(); } } var action = new List() { "系统操作-平仓费", "系统操作-行权费" }; var cashIds = cashes.Select(O => O.TradeId).ToList(); var query = DbContext.trade_cash .Where(O => cashIds.Contains(O.TradeId) && action.Contains(O.Action) && (O.Notional - O.UnwindNotional) > 0.0001 && O.ValidState != ConsGlobal.InValid && !O.IsDeleted); if (cashIds.Count > 1) { #region 检查子交易资金信息 //if (query.GroupBy(O => O.TradeId).Count() != cashIds.Count) //{ throw new ArgumentException("子交易资金记录不匹配"); } var id = cashIds[0]; var tempNum = query.Where(O => O.TradeId == id).Count(); for (var i = 1; i < cashIds.Count; i++) { id = cashIds[i]; var n = query.Where(O => O.TradeId == id).Count(); if (tempNum != n) { throw new ArgumentException("子交易资金记录不匹配"); } } #endregion } if (query.Any()) { var cash = cashes[0]; num = query.Where(O => O.ValueDate <= cash.ValueDate && O.id < cash.id).Count() + 1; } return num; } public IEnumerable Trades { get; private set; } /// /// 一笔交易存在多次平仓记录 /// public IReadOnlyDictionary> TradeCashes { get; private set; } public DateTime? StartDate { get; set; } public DateTime? EndDate { get; set; } //public IClient Client => _client; public List GetClientTrades() { var result = new List(); var cash = GetTradeCash(); var query = from t in DbContext.trade join tc in DbContext.trade_cash on t.id equals tc.TradeId where t.ClientId == _client.id && tc.ValueDate == cash.ValueDate && !tc.IsDeleted select new { t, tc }; switch (_contractType) { case ContractTypeEnum.Trade: query = query.Where(O => O.tc.Action == "系统操作-期权费"); break; case ContractTypeEnum.Clearing: case ContractTypeEnum.UnWind: var actions = new List() { "系统操作-行权费", "系统操作-平仓费" }; query = query.Where(O => actions.Contains(O.tc.Action)); break; default: break; } //result = query.Select(O => O.t).ToList().Cast().ToList(); var tradeIds = query.Select(O => O.t.id).Distinct().ToList();//.Cast().ToList(); result = new TradeDalService(this).GetTradeOrEodTrade(tradeIds, SystemValueDate).Cast().ToList(); return result; } public BaseSystemUser GetTraderUserInfo() { return DbContextFactory.GetErpBaseContext().SystemUsers.Where(O => O.Id == Trade.TraderId).FirstOrDefault(); } public ClientLevel GetClientLevel() { var client = GetClient(); return client == null || client.LevelId == null ? null : DbContextFactory.GetClientDbContext(OptUser).clientlevel.Where(O => O.id == (client.LevelId ?? 0)).FirstOrDefault(); } public client_variety_config GetClient_Variety_Config(int ClientId, int varietyId, DateTime valuedate) { var config = DbContext.client_variety_config.Where(o => o.ClientId == ClientId && o.VarietyId == varietyId && o.ValueDate <= valuedate).OrderByDescending(o => o.ValueDate).FirstOrDefault(); if (config != null) { return config; } config = DbContext.client_variety_config.Where(o => o.ClientId == 0 && o.VarietyId == varietyId && o.ValueDate <= valuedate).OrderByDescending(o => o.ValueDate).FirstOrDefault(); if (config != null) { return config; } throw new ServiceException("该品种在 " + valuedate.ToString("yyyy/MM/dd") + "未维护费率"); } public List CalcMargin(OtcTradeBase trade, double? price) { if (!(trade is trade)) { throw new DocGenerateException("计算预付金时Trade不存在"); } var req = new RunMarginCalculationReq(UserInfo) { tradeList = new List { (trade)trade }, settleDate = trade.UnWindDate.Value, PriceProvider = new SinglePriceProvider(trade.UnderlyingCode, price ?? 0) }; if (trade.IsGroup == 1) { req.tradeList = DbContext.trade.Where(x => x.ParentTradeId == trade.id).ToList(); } return MarginDefault.RunMarginCalculation(req); } public trade_cash_swap GetTradecashswap(int tradecashid) { var trade_cash_swap = DbContext.trade_cash_swap.Where(c => c.TradeCashId == tradecashid).FirstOrDefault(); return trade_cash_swap; } public List GetClient_file() { var result = new List(); result = DbContextFactory.GetClientDbContext(OptUser).client_file.Where(m => m.ApprovalOrder < 1 && m.ClientId == Trade.ClientId && (m.FileTypeName == "主协议附件(PDF)" || m.FileTypeName == "补充协议附件(PDF)" || m.FileTypeName == "履约协议附件(PDF)")).ToList(); return result; } /// /// 3.15删掉 /// /// [Obsolete] public trade_swap GetTrade_Swap() { trade_swap result; result = DbContextFactory.GetYLDbContext().trade_swap.Where(m => m.TradeId == Trade.id).FirstOrDefault(); return result; } /// /// 3.15删掉 /// /// [Obsolete] public trade_snowball Gettrade_snowball() { trade_snowball result; result = DbContextFactory.GetYLDbContext().trade_snowball.Where(m => m.TradeId == Trade.id).FirstOrDefault(); return result; } /// /// 3.15删掉 /// /// [Obsolete] public trade_forward Gettrade_forward() { trade_forward result; result = DbContextFactory.GetYLDbContext().trade_forward.Where(m => m.TradeId == Trade.id).FirstOrDefault(); return result; } public string Gettrade_contract_r() { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == Trade.id && m.Type == "交易确认书" && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public string Gettrade_contract_r(string type) { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == Trade.id && m.Type == type && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public string Gettrade_contract_r(int tradeId, string type) { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == tradeId && m.Type == type && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public string Gettrade_contract_r(string type, int tradeCashId) { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == Trade.id && m.TradeCashId == tradeCashId && m.Type == type && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public Owner_info GetOwner_info(string Condition) { try { var r = DbContextFactory.GetYLDbContext().Owner_Info.Where(m => m.Condition == Condition).FirstOrDefault(); return r; } catch { throw new ServiceException("admin页面没配账户信息"); } } public void GetcontractIndex(string Rule, out string contractIndex) { contractIndex = ContractBLL.GetRuleIndex(Rule).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); } /// /// /// /// 规则 /// 返回的数据 /// 结果字符串中的字符数,等于原始字符数加上任何其他填充字符 public void GetcontractIndex01(string Rule, out string contractIndex, int totalWidth = 2) { contractIndex = ContractBLL.GetRuleIndex(Rule).ToString(); if (totalWidth == 0) { contractIndex = contractIndex.ToString(); } else { contractIndex = contractIndex.ToString().PadLeft(totalWidth, '0'); } } public string TransToForeignWord(string CnWord, string Key) { var result = DbContextFactory.GetYLDbContext().dicForTranslation.Where(o => o.From == CnWord && o.Key == Key).FirstOrDefault(); if (result != null) { return result.To; } return CnWord; } public Currency GetCurrency(string currencyCode) { if (string.IsNullOrWhiteSpace(currencyCode)) { throw new ServiceException("计价币种或结算币种不能为空!"); } var currency = DbContext.currency.Where(o => o.CurrencyCode == currencyCode).FirstOrDefault(); return currency; } public trade_cash_swap GetTradeCash_Swap(int tradeCashId) { if (tradeCashId <= 0) { return null; } var tcs = DbContext.trade_cash_swap.Where(o => o.TradeCashId == tradeCashId).FirstOrDefault(); return tcs; } /// /// 获取货币对汇率 /// /// 计价货币 /// 结算货币 /// public eod_currency_rate GetCurrencyRate(string quoteCurrency, string settlementCurrency, DateTime date) { var rate = new EodModule.EodCurrencyRateService(UserInfo).GetEodCurrencyRate(quoteCurrency, settlementCurrency, date); return rate ?? throw new ServiceException($"未找到货币对'{quoteCurrency}{settlementCurrency}'的结算汇率,取值日期:{date:yyyy/MM/dd}"); } public List GetTradeCashDetails(int tradeCashId) { return DbContext.trade_cash_detail.Where(x => x.TradeCashId == tradeCashId).ToList(); } public DateTime ShiftTradeDate(DateTime now, int shiftDays, string calendarName, bool NeedBothTradeDay = false) { try { var date = QdpCalendarHelper.BizDayShift(now, shiftDays, calendarName); if (NeedBothTradeDay) { date = getBothTradeDay(date); } return date; } catch (Exception e) { throw new ServiceException(now.ToShortDateString() + "未在日历中,请维护日历" + calendarName, e); } } private DateTime getBothTradeDay(DateTime now) { try { var ishoilday = QdpCalendarHelper.IsHoliday(now) || QdpCalendarHelper.IsHoliday(now, "NYB"); if (ishoilday) { var tradeDate = now.AddDays(1); return getBothTradeDay(tradeDate); } return now; } catch (Exception e) { throw new ServiceException(e.Message); } } public ClientMeta GetClientMeta(int ClientId, string MetaKey) { return DbContextFactory.GetClientDbContext(OptUser).ClientMeta.FirstOrDefault(o => o.ClientId == ClientId && o.MetaKey == MetaKey); } /// /// 3.15删掉 /// /// [Obsolete] public trade_swap GetTrade_Swap(int tradeId) { trade_swap result; result = DbContextFactory.GetYLDbContext().trade_swap.Where(m => m.TradeId == tradeId).FirstOrDefault(); return result; } public List GetDictionaryItemList(string dictName) { using (var db = new ErpBaseContext()) { var query = from i in db.DictionaryItems join d in db.Dictionaries on i.DictId equals d.Id where d.Name == dictName orderby i.IndexNum, i.Name select new Models.DictionaryItems { Name = i.Name, ShortName = i.ShortName, IndexNum = i.IndexNum, }; var list = query.ToList(); return list; } } public trade_swap_flow GetSwapFlow(int flowId) { trade_swap_flow result; result = DbContextFactory.GetYLDbContext().trade_swap_flow.Where(m => m.id == flowId).FirstOrDefault(); return result; } /// /// 人民币转大写 /// 该方法直接调用NumberHelper.CmycurD(num) /// /// /// public string CmycurD(double num) { var str = NumberHelper.CmycurD(num); if (str.EndsWith("整") && !str.EndsWith("元整")) { str = str.Remove(str.Length - 1); } return str; } /// /// 当前所有了结次数,包含全部了结 /// /// /// /// public int AllUnwindCount(List cashes = null) { var num = 0; if (cashes == null) { if (Trade.TradeType != "结构化交易") { cashes = new List() { GetTradeCash() }; } else { cashes = GetSubTradeCashes().ToList(); } } var action = new List() { "系统操作-平仓费", "系统操作-行权费" }; var cashIds = cashes.Select(O => O.TradeId).ToList(); var query = DbContext.trade_cash .Where(O => cashIds.Contains(O.TradeId) && action.Contains(O.Action) && O.ValidState != ConsGlobal.InValid && !O.IsDeleted); if (cashIds.Count > 1) { #region 检查子交易资金信息 //if (query.GroupBy(O => O.TradeId).Count() != cashIds.Count) //{ throw new ArgumentException("子交易资金记录不匹配"); } var id = cashIds[0]; var tempNum = query.Where(O => O.TradeId == id).Count(); for (var i = 1; i < cashIds.Count; i++) { id = cashIds[i]; var n = query.Where(O => O.TradeId == id).Count(); if (tempNum != n) { throw new ArgumentException("子交易资金记录不匹配"); } } #endregion } if (query.Any()) { var cash = cashes[0]; num = query.Where(O => O.ValueDate <= cash.ValueDate && O.id < cash.id).Count() + 1; } return num; } /// /// 计算TTM /// public double CalculateTTMDays(DateTime from, DateTime to, int varietyid, bool precisionOfMinute) { return TradeCalcHelper.CalculateTTMDays(from, to, varietyid, precisionOfMinute); } /// /// 获取某交易日之后的交易日 /// /// /// public DateTime GetTradeDate(DateTime date) { return BLL.valuedateBLL.GetNonHoliday(date); } /// /// 获取系统参数配置 /// /// public valuedate GetValuedate() { return DbContext.valuedate.FirstOrDefault(); } public List GetSwapEvents(int tradeId) { return DbContext.swap_event.Where(x => x.SwapTradeId == tradeId && x.Invalid == true).ToList(); } public List GetSwapPositions(int tradeId, bool? IsInitial) { var query = DbContext.swap_position.Where(x => x.SwapTradeId == tradeId && !x.Invalid); if (IsInitial.HasValue) { query = query.Where(x => x.IsInitial == IsInitial); } return query.ToList(); } public List GetSwapPositions(List tradeIds, bool? IsInitial) { var query = DbContext.swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && !x.Invalid); if (IsInitial.HasValue) { query = query.Where(x => x.IsInitial == IsInitial); } return query.ToList(); } public client_marginrate GetClientMarginRate(int clientId) { var clientMarginRateDbSet = DbContext.client_marginrate; var clientMarginRate = clientMarginRateDbSet.Where(x => x.ClientId == clientId)?.FirstOrDefault(); if (clientMarginRate == null) { var client = DataCacheProvider.GetClientDataSource().GetData(clientId); clientMarginRate = clientMarginRateDbSet.Where(x => x.ClientId == 0)?.FirstOrDefault(); } return clientMarginRate; } public List GetFlowEvents() { return FlowEvents; } public List GetAllFlowEvents() { return AllFlowEvents; } public List GetSwapPositions() { return SwapPositions; } public int GetDMASelttementCount(int clientId, DateTime valueDate) { var query = from r in DbContext.trade_contract_r.Where(x => x.Type == ContractTypeEnum.Clearing && x.IsValid == true) join d in DbContext.trade_contract_document.Where(x => x.ValueDate == valueDate && x.ClientId == clientId) on r.ContractCode equals d.Code select r.ContractCode; return query.Distinct().Count(); } public List GetSwapFlows(int tradeId) { return DbContext.swap_flow.Where(x => x.SwapTradeId == tradeId && x.DataState == (int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList(); } public List GetUnderlyings(List underlyingCodes) { return DbContext.underlying_manager.Where(x => underlyingCodes.Contains(x.UnderlyingCode)).AsNoTracking().ToList(); } public List GetTrade_Extends(List tradeIds) { return DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList(); } public List GetFlowEvents(int tradeId, List eventTypes) { return DbContext.swap_flow_event.Where(x => eventTypes.Contains(x.EventType) && x.SwapTradeId == tradeId && x.DataState == (int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList(); } public List GetEodPositions(int tradeId, DateTime valueDate) { return DbContext.eod_swap_position.ActiveByTradeAndDate(tradeId, valueDate).AsNoTracking().ToList(); } public List GetSwapFlowDeals(int tradeId) { return DbContext.swap_flow_deal.Where(x => x.SwapTradeId == tradeId).AsNoTracking().ToList(); } public swap_event GetEvent(long eventId) { return DbContext.swap_event.FirstOrDefault(x => x.id == eventId); } } }