1980 lines
86 KiB
C#
1980 lines
86 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 生成确认书时,用户选择的资金记录
|
||
/// </summary>
|
||
public IEnumerable<int> UserTradeCashIds { get; }
|
||
|
||
/// <summary>
|
||
/// 同步锁
|
||
/// </summary>
|
||
private static readonly object _syncLock = new object();
|
||
/// <summary>
|
||
/// 确认书编号缓存 处理 确认书生成出重复编号问题,浙期已修改,如果其他公司有类似问题请参照这次提交代码
|
||
/// key 是合约编号
|
||
/// value[tradecashid,当前时间] 过期时间1h
|
||
/// 汤旺
|
||
/// </summary>
|
||
private static Dictionary<string, long[]> ContractCodeCache = new Dictionary<string, long[]>();
|
||
|
||
/// <summary>
|
||
/// [必需]交易记录
|
||
/// </summary>
|
||
public OtcTradeBase Trade { get; }
|
||
|
||
public IEnumerable<OtcTradeBase> SubTrades { get; }
|
||
|
||
private readonly trade_cash _tradeCash;
|
||
|
||
private readonly List<trade_cash> _subTradeCashes = new List<trade_cash>();
|
||
|
||
/// <summary>
|
||
/// [必需]合约业务接口
|
||
/// </summary>
|
||
public IContractBLL ContractBLL { get; }
|
||
/// <summary>
|
||
/// 浮动平仓事件集
|
||
/// </summary>
|
||
public readonly List<swap_flow_event> FlowEvents;
|
||
/// <summary>
|
||
/// 平仓事件集
|
||
/// </summary>
|
||
public readonly List<swap_flow_event> AllFlowEvents = new List<swap_flow_event>();
|
||
/// <summary>
|
||
/// 交易持仓腿集合
|
||
/// </summary>
|
||
public readonly List<swap_position> SwapPositions = new List<swap_position>();
|
||
/// <summary>
|
||
/// [必需]期权数据提供接口
|
||
/// </summary>
|
||
public ITradeExtendDataProvider TradeDataProvider { get; }
|
||
|
||
readonly string _contractType;
|
||
|
||
public ConfirmationGenerateContext(IEnumerable<int> tradeCashIds, IEnumerable<trade> 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<trade>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
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<OtcTradeBase>() { 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<int, List<trade_cash>>() { { tradeObj.id, new List<trade_cash> { _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<swap_flow_event> flowEvents, List<swap_flow_event> allFlowEvents, List<trade> trades, List<swap_position> 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取系统配置接口对象
|
||
/// </summary>
|
||
public IErpConfig GetErpConfig()
|
||
{
|
||
return PS.GetErpConfig();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换word文档为pdf文档
|
||
/// </summary>
|
||
public void ConvertDocToPDF(string wordDocPath, string targetPdfPath)
|
||
{
|
||
OfficeFileConverter.ConvertFileFormat(wordDocPath, targetPdfPath);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据Excel文档模板生成文档
|
||
/// </summary>
|
||
public void GenerateExcelFromTemplate(string templatePath, Dictionary<string, JToken> 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<string, object> 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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据Word文档模板生成文档
|
||
/// </summary>
|
||
public void GenerateDocFromTemplate(string templatePath, Dictionary<string, JToken> 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));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取合成价差期权的商品标的名称
|
||
/// </summary>
|
||
public string GetSyntheticUnderlyingName(string underlyingCode)
|
||
{
|
||
return synthetic_underlyingBLL.GetUnderlyingTipsInfo(underlyingCode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取亚式期权行权价
|
||
/// </summary>
|
||
/// <param name="trade"></param>
|
||
/// <returns></returns>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取亚式期权现价
|
||
/// </summary>
|
||
/// <param name="trade"></param>
|
||
/// <returns></returns>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存文档生成数据
|
||
/// </summary>
|
||
public ITradeContractDocument SaveContractDocument(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null)
|
||
{
|
||
var documents = new List<ITradeContractDocument>();
|
||
var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".docx");
|
||
var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Word;
|
||
var tradecashDict = _subTradeCashes.Count == 0 ? new Dictionary<int, List<int>>() { { Trade.id, new List<int>() { (_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<int>() { _tradeCash.id };
|
||
}
|
||
var trades = new List<OtcTradeBase>() { Trade };
|
||
if (Trade.TradeType == "结构化交易" && SubTrades.Count() > 1)
|
||
{ trades.AddRange(SubTrades); }
|
||
documents = SaveContractDocuments(trades, tradecashDict, contractCode, savedOutputFileName, fileType);
|
||
ContractCodeCache.Remove(contractCode);
|
||
return documents[0];
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存文档生成数据
|
||
/// </summary>
|
||
public List<ITradeContractDocument> SaveContractDocuments(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null)
|
||
{
|
||
var documents = new List<ITradeContractDocument>();
|
||
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<int, List<int>>();
|
||
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<int>() { 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;
|
||
}
|
||
/// <summary>
|
||
/// 保存文档生成数据
|
||
/// </summary>
|
||
public List<ITradeContractDocument> 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;
|
||
}
|
||
/// <summary>
|
||
/// 保存文档生成数据
|
||
/// </summary>
|
||
/// <param name="trade"></param>
|
||
/// <param name="trades"></param>
|
||
/// <param name="tradeCashIds"></param>
|
||
/// <param name="contractCode"></param>
|
||
/// <param name="fileName"></param>
|
||
/// <param name="fileType"></param>
|
||
/// <returns></returns>
|
||
private List<ITradeContractDocument> SaveContractDocuments(IEnumerable<OtcTradeBase> trades, Dictionary<int, List<int>> tradeCashIds, string contractCode, string fileName, string fileType)
|
||
{
|
||
lock (_syncLock)
|
||
{
|
||
var documents = new List<ITradeContractDocument>();
|
||
var firstTrade = trades.First();
|
||
var isGJBuyer = firstTrade.BuySell == "买入";
|
||
var nowDate = DateTime.Now;
|
||
var db = DbContextFactory.GetYLDbContext();
|
||
|
||
#region 清理历史数据
|
||
|
||
var tcIds = new List<int>();
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存文档生成数据
|
||
/// </summary>
|
||
/// <param name="trade"></param>
|
||
/// <param name="trades"></param>
|
||
/// <param name="tradeCashIds"></param>
|
||
/// <param name="contractCode"></param>
|
||
/// <param name="fileName"></param>
|
||
/// <param name="fileType"></param>
|
||
/// <returns></returns>
|
||
private List<ITradeContractDocument> SaveContractDocumentsByEventIds(IEnumerable<OtcTradeBase> trades, List<swap_flow_event> flow_Events, string contractCode, string fileName, string fileType)
|
||
{
|
||
lock (_syncLock)
|
||
{
|
||
var documents = new List<ITradeContractDocument>();
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取生成文档的输出路径(物理路径)
|
||
/// </summary>
|
||
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<int, NameValueCollection> _tradeMetas;
|
||
|
||
/// <summary>
|
||
/// 获取交易关联的客户信息
|
||
/// </summary>
|
||
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;
|
||
}
|
||
/// <summary>
|
||
/// 获取交易关联的结算资金信息
|
||
/// </summary>
|
||
public ClientSettleBalance GetClientBalance(DateTime date)
|
||
{
|
||
var client = GetClient();
|
||
var clientbalances = ClientBalanceUtility.GetClientBanlances(new List<int>() { client.id }, DateTime.MinValue, date);
|
||
return clientbalances.FirstOrDefault();
|
||
}
|
||
public ClientSettleBalance GetClientBalanceByReal(DateTime date)
|
||
{
|
||
var client = GetClient();
|
||
var clientbalances = new RealTimeClientBanlanceService(UserInfo).GetBanlances(new List<int>() { client.id }, date, calcDate: date);
|
||
return clientbalances.FirstOrDefault();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取交易关联的标的
|
||
/// </summary>
|
||
public underlying_manager GetTradeUnderlying()
|
||
{
|
||
return GetTradeUnderlying(Trade.UnderlyingCode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取交易关联的标的
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取组合标的信息
|
||
/// </summary>
|
||
/// <param name="code"></param>
|
||
/// <returns></returns>
|
||
public SyntheticUnderlying GetSyntheticUnderlying(string code)
|
||
{
|
||
return DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(code);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取交易关联的市场信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取交易关联的标的对应的品种信息
|
||
/// </summary>
|
||
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;
|
||
}
|
||
/// <summary>
|
||
/// 获取交易关联的标的对应的品种信息
|
||
/// </summary>
|
||
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;
|
||
}
|
||
/// <summary>
|
||
/// 获取客户银行卡
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取机构客户职责联系人信息
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取客户法人/联系人
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取客户法人/联系人
|
||
/// </summary>
|
||
public List<ClientDuty> 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<contactype> GetContractTypes()
|
||
{
|
||
var result = DbContextFactory.GetClientDbContext(OptUser).contactype.ToList();
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取工作日天数
|
||
/// </summary>
|
||
public int GetWorkDayCount(DateTime from, DateTime to)
|
||
{
|
||
return QdpCalendarHelper.GetWorkDayCount(from, to);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取交易记录元数据
|
||
/// </summary>
|
||
/// <param name="tradeId"></param>
|
||
/// <returns></returns>
|
||
public NameValueCollection GetTradeMetas(int tradeId)
|
||
{
|
||
if (_tradeMetas == null)
|
||
{
|
||
_tradeMetas = new Dictionary<int, NameValueCollection>();
|
||
}
|
||
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];
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取结构化交易所有行权价
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取交易的初始预付金
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 确认书文档生成后的处理
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取主交易的资金信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public trade_cash GetTradeCash()
|
||
{
|
||
return _tradeCash;
|
||
}
|
||
public trade_cash GetTradeCashById(int cashId)
|
||
{
|
||
return DbContext.trade_cash.Where(O => O.id == cashId).FirstOrDefault();
|
||
|
||
}
|
||
public IEnumerable<KeyValuePair<OtcTrade, trade_cash>> 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<trade_cash> cashes = DbContext.trade_cash.Where(O => tradeIds.Contains(O.TradeId) && O.ValidState != ConsGlobal.InValid && !O.IsDeleted).ToList();
|
||
var result = new List<KeyValuePair<OtcTrade, trade_cash>>();
|
||
var dates = cashes.Select(O => O.ValueDate).ToArray();
|
||
|
||
foreach (var c in cashes)
|
||
{
|
||
result.Add(new KeyValuePair<OtcTrade, trade_cash>(
|
||
new TradeDalService(this).GetTradeOrEodTrade(new[] { c.TradeId }, c.ValueDate).First(),
|
||
c));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
public IEnumerable<OtcTrade> 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<trade_cash> GetGroupTradeCashs(int parentTradeCashId)
|
||
{
|
||
return DbContext.trade_cash.Where(x => x.ParentTradeCashId == parentTradeCashId && x.ValidState != "InValid").ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 累计期权id获取转远期的tradecash记录
|
||
/// </summary>
|
||
/// <param name="tradeId"></param>
|
||
/// <returns></returns>
|
||
public List<trade_cash> 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;
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取子交易的资金信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public IEnumerable<trade_cash> 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<string>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成国联确认书编号
|
||
/// </summary>
|
||
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<KeyValuePair<OtcTrade, trade_cash>> 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;
|
||
}
|
||
/// <summary>
|
||
/// 获取价差期权 组合标的最大价格
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public double GetDifferenceMaxPrice()
|
||
{
|
||
var query = DbContext.TradeMeta.Where(O => O.TradeId == Trade.id && O.MetaKey == "组合标的").FirstOrDefault();
|
||
var syntheticPrice = JsonHelper.Deserialize<SyntheticPriceModel>(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<trade_cash>() { cash });
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前了结次数
|
||
/// </summary>
|
||
public int UnwindCount(List<trade_cash> cashes = null)
|
||
{
|
||
var num = 0;
|
||
if (cashes == null)
|
||
{
|
||
if (Trade.TradeType != "结构化交易")
|
||
{ cashes = new List<trade_cash>() { GetTradeCash() }; }
|
||
else
|
||
{ cashes = GetSubTradeCashes().ToList(); }
|
||
}
|
||
var action = new List<string>() { "系统操作-平仓费", "系统操作-行权费" };
|
||
|
||
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<OtcTrade> Trades { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 一笔交易存在多次平仓记录
|
||
/// </summary>
|
||
public IReadOnlyDictionary<int, List<trade_cash>> TradeCashes { get; private set; }
|
||
|
||
public DateTime? StartDate { get; set; }
|
||
|
||
public DateTime? EndDate { get; set; }
|
||
|
||
//public IClient Client => _client;
|
||
|
||
public List<OtcTradeBase> GetClientTrades()
|
||
{
|
||
var result = new List<OtcTradeBase>();
|
||
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<string>() { "系统操作-行权费", "系统操作-平仓费" };
|
||
query = query.Where(O => actions.Contains(O.tc.Action));
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
//result = query.Select(O => O.t).ToList().Cast<OtcTradeBase>().ToList();
|
||
var tradeIds = query.Select(O => O.t.id).Distinct().ToList();//.Cast<OtcTradeBase>().ToList();
|
||
result = new TradeDalService(this).GetTradeOrEodTrade(tradeIds, SystemValueDate).Cast<OtcTradeBase>().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<trade_span> CalcMargin(OtcTradeBase trade, double? price)
|
||
{
|
||
if (!(trade is trade))
|
||
{
|
||
throw new DocGenerateException("计算预付金时Trade不存在");
|
||
}
|
||
|
||
var req = new RunMarginCalculationReq(UserInfo)
|
||
{
|
||
tradeList = new List<trade> { (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<client_file> GetClient_file()
|
||
{
|
||
var result = new List<client_file>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 3.15删掉
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[Obsolete]
|
||
public trade_swap GetTrade_Swap()
|
||
{
|
||
trade_swap result;
|
||
result = DbContextFactory.GetYLDbContext().trade_swap.Where(m => m.TradeId == Trade.id).FirstOrDefault();
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 3.15删掉
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[Obsolete]
|
||
public trade_snowball Gettrade_snowball()
|
||
{
|
||
trade_snowball result;
|
||
result = DbContextFactory.GetYLDbContext().trade_snowball.Where(m => m.TradeId == Trade.id).FirstOrDefault();
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 3.15删掉
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[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');
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="Rule">规则</param>
|
||
/// <param name="contractIndex">返回的数据</param>
|
||
/// <param name="totalWidth"> 结果字符串中的字符数,等于原始字符数加上任何其他填充字符</param>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取货币对汇率
|
||
/// </summary>
|
||
/// <param name="baseCurrency">计价货币</param>
|
||
/// <param name="quoteCurrency">结算货币</param>
|
||
/// <param name="date"></param>
|
||
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<trade_cash_detail> 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 3.15删掉
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[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<DictionaryItems> 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 人民币转大写
|
||
/// <para>该方法直接调用NumberHelper.CmycurD(num)</para>
|
||
/// </summary>
|
||
/// <param name="num"></param>
|
||
/// <returns></returns>
|
||
public string CmycurD(double num)
|
||
{
|
||
var str = NumberHelper.CmycurD(num);
|
||
if (str.EndsWith("整") && !str.EndsWith("元整"))
|
||
{
|
||
str = str.Remove(str.Length - 1);
|
||
}
|
||
return str;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前所有了结次数,包含全部了结
|
||
/// </summary>
|
||
/// <param name="cashes"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
public int AllUnwindCount(List<trade_cash> cashes = null)
|
||
{
|
||
var num = 0;
|
||
if (cashes == null)
|
||
{
|
||
if (Trade.TradeType != "结构化交易")
|
||
{ cashes = new List<trade_cash>() { GetTradeCash() }; }
|
||
else
|
||
{ cashes = GetSubTradeCashes().ToList(); }
|
||
}
|
||
var action = new List<string>() { "系统操作-平仓费", "系统操作-行权费" };
|
||
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算TTM
|
||
/// </summary>
|
||
public double CalculateTTMDays(DateTime from, DateTime to, int varietyid, bool precisionOfMinute)
|
||
{
|
||
return TradeCalcHelper.CalculateTTMDays(from, to, varietyid, precisionOfMinute);
|
||
}
|
||
/// <summary>
|
||
/// 获取某交易日之后的交易日
|
||
/// </summary>
|
||
/// <param name="date"></param>
|
||
/// <returns></returns>
|
||
public DateTime GetTradeDate(DateTime date)
|
||
{
|
||
return BLL.valuedateBLL.GetNonHoliday(date);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取系统参数配置
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public valuedate GetValuedate()
|
||
{
|
||
return DbContext.valuedate.FirstOrDefault();
|
||
}
|
||
|
||
public List<swap_event> GetSwapEvents(int tradeId)
|
||
{
|
||
return DbContext.swap_event.Where(x => x.SwapTradeId == tradeId && x.Invalid == true).ToList();
|
||
}
|
||
|
||
public List<swap_position> 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<swap_position> GetSwapPositions(List<int> 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<swap_flow_event> GetFlowEvents()
|
||
{
|
||
return FlowEvents;
|
||
}
|
||
|
||
public List<swap_flow_event> GetAllFlowEvents()
|
||
{
|
||
return AllFlowEvents;
|
||
}
|
||
|
||
public List<swap_position> 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<swap_flow> GetSwapFlows(int tradeId)
|
||
{
|
||
return DbContext.swap_flow.Where(x => x.SwapTradeId == tradeId && x.DataState == (int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList();
|
||
}
|
||
|
||
public List<underlying_manager> GetUnderlyings(List<string> underlyingCodes)
|
||
{
|
||
return DbContext.underlying_manager.Where(x => underlyingCodes.Contains(x.UnderlyingCode)).AsNoTracking().ToList();
|
||
}
|
||
public List<trade_extend> GetTrade_Extends(List<int> tradeIds)
|
||
{
|
||
return DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
|
||
}
|
||
public List<swap_flow_event> GetFlowEvents(int tradeId, List<int> eventTypes)
|
||
{
|
||
return DbContext.swap_flow_event.Where(x => eventTypes.Contains(x.EventType) && x.SwapTradeId == tradeId && x.DataState == (int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList();
|
||
}
|
||
public List<eod_swap_position> GetEodPositions(int tradeId, DateTime valueDate)
|
||
{
|
||
return DbContext.eod_swap_position.ActiveByTradeAndDate(tradeId, valueDate).AsNoTracking().ToList();
|
||
}
|
||
|
||
public List<SwapFlowDeal> 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);
|
||
}
|
||
}
|
||
}
|