Files
zszq-trs/YLErpDAL/Modules/TradeModule/SwapModule/SwapTradeImportService.cs
T

3231 lines
146 KiB
C#

using System.Data;
using System.Globalization;
using System.Text.RegularExpressions;
using YLErp.BLL;
using YLErp.Commons;
using YLErp.Configuration;
using YLErp.CustomizedBizLogic;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Enums;
using YLErp.Enums;
using YLErp.Model.Enum;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.EodModule;
using YLErp.Modules.TradeModule.OrderModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.SwapModule
{
public class SwapTradeImportService : TradeServiceBase
{
public SwapTradeImportService(YLBaseService baseService) : base(baseService)
{
}
public SwapTradeImportService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 从excel文件中导入场外期权交易
/// </summary>
public void ImportSwapTradesFromExcel(Stream streamIn, out int totalNum, out int successNum)
{
if (PS.Config.Company == CompanyEnum.山西)
{
ImportFromExcelSX(streamIn, out totalNum, out successNum);
}
else
{
ImportFromExcel(streamIn, out totalNum, out successNum);
}
}
#region 普通互换交易导入
/// <summary>
/// 导入交易
/// </summary>
/// <param name="streamIn"></param>
/// <param name="totalNum">当前文件中的目标期权总条数</param>
/// <param name="successNum">成功入库的数量</param>
public void ImportFromExcel(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
var groupTradeList = new List<OtcOptionTradeFullEx>();
var structureTradeList = new List<OtcOptionTradeFullEx>();
try
{
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 3)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowTopTypeReader(table);
rowIndex = 2;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(2))
{
using (var trans = BeginTransaction())
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
reader.SetDataRow(row);
//映射导入数据到交易对象
HandleTrade(reader);
successNum++;
trans.Commit();
}
}
}
catch (ServiceException se)
{
if (se.Tag != null)
{
throw;
}
throw new ServiceException($"已成功导入{successNum}条;\n第{rowIndex}行,{se.Message}");
}
catch (Exception ex)
{
LogFactory.GetLogger("导入期权交易").Error(ex);
throw new ServiceException($"已成功导入{successNum}条,\n第{rowIndex}行,发生错误:{ex.Message}", ex);
}
}
/// <summary>
/// 导入交易
/// </summary>
/// <param name="streamIn"></param>
/// <param name="totalNum">当前文件中的目标期权总条数</param>
/// <param name="successNum">成功入库的数量</param>
public void ImportToEndSwapTradesFromExcel(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
try
{
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowReader(table, 0);
rowIndex = 1;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
{
using (var trans = BeginTransaction())
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
reader.SetDataRow(row);
HandleToEndSwapTrade(reader);
successNum++;
trans.Commit();
}
}
}
catch (ServiceException se)
{
if (se.Tag != null)
{
throw;
}
throw new ServiceException($"已成功导入{successNum}条;\n第{rowIndex}行,{se.Message}");
}
catch (Exception ex)
{
LogFactory.GetLogger("导入收益互换了结").Error(ex);
throw new ServiceException($"已成功导入{successNum}条,\n第{rowIndex}行,发生错误:{ex.Message}", ex);
}
}
private trade HandleTrade(DataRowTopTypeReader reader)
{
var td = new trade();
td.trade_swap = new trade_swap();
//基本要素
td.TradeNumber = reader.GetString("交易编号", false);
td.AssetBookName = reader.GetString("簿记账户名称", true);
td.TraderName = reader.GetString("交易员名称", true);
new OtcOptionSaveChecker(this).CheckAssetBook(td).CheckTrader(td);
td.TradeType = "收益互换";
td.ClientName = reader.GetString("交易对手方名称", true);
if (string.IsNullOrWhiteSpace(td.ClientName))
{
throw new ServiceException("交易对手方名称 必须填写");
}
//交易日期
td.TradeDate = reader.GetDate("成交日期", true);
td.StartDate = reader.GetDate("开始日期", true);
td.ExerciseDate = reader.GetDate("到期日期", true);
td.SettlementDate = td.ExerciseDate;
td.StockEqvNotional = reader.GetDouble("名义本金", true) ?? 0;
td.trade_swap.AnnualDays = reader.GetInt("年化天数", true);
td.trade_swap.AnnualVarIncome = reader.GetString("浮动收益年化", true) == "是";
td.trade_swap.RateCalcMode = GetRateCalcMode(reader.GetString("计息方式", true));
td.trade_swap.IsTradePriceWhenOpen = reader.GetString("是否开仓时收取开仓费", true) == "是";
td.trade_swap.IsShare = reader.GetString("收费基本单位", true) == "手数";
var ExchangeRate = reader.GetDouble("汇率", false);
td.Comments = reader.GetString("备注", false);
var clientQuery = DbContextFactory.GetClientDbContext(OptUser).client.AsQueryable();
if (!string.IsNullOrWhiteSpace(td.ClientName))
{
clientQuery = clientQuery.Where(c => c.Name == td.ClientName);
}
var client = clientQuery.Select(n => new { n.id, n.SettlementCurrency, n.DerivativesInvestmentVarieties,n.IsCentralClearing,n.CentralClearingPaltform,n.TradingPaltform }).FirstOrDefault();
if (client == null)
{
throw new ServiceException($"交易对手方不存在,客户名称:{td.ClientName}");
}
else
{
if (!string.IsNullOrEmpty(client.IsCentralClearing))
{
td.MetaDic.Add("中央对手方清算", client.IsCentralClearing);
}
if (!string.IsNullOrEmpty(client.IsCentralClearing))
{
td.MetaDic.Add("中央清算平台", client.CentralClearingPaltform);
}
if (!string.IsNullOrEmpty(client.IsCentralClearing))
{
td.MetaDic.Add("交易平台", client.TradingPaltform);
}
if (!client.DerivativesInvestmentVarieties.Contains((int)DerivativesInvestmentVarietiesEnum.场外互换 + ""))
{
throw new ServiceException($"客户:{td.ClientName}未设置交易种类“场外互换”,无法生成互换交易!");
}
}
td.ClientId = client.id;
td.SettlementCurrency = client.SettlementCurrency;
td.OpponentRole = "甲方";
var um = new underlying_manager();
var singleFee = 0.0;
#region 交易员收取信息读取
reader.SetTopType("交易员收取");
td.trade_swap.GetLongShort = reader.GetString("多头空头", false);
if (!string.IsNullOrWhiteSpace(td.trade_swap.GetLongShort))
{
td.trade_swap.IsGetFloatingProfit = true;
td.trade_swap.GetUnderlyingCode = reader.GetString("标的代码", true);
um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.trade_swap.GetUnderlyingCode);
if (um == null)
{
throw new ServiceException($"{td.trade_swap.GetUnderlyingCode} 不存在,请先新建标的再导入");
}
td.trade_swap.GetUnderlyingId = um.id;
td.UnderlyingId = um.id;
td.UnderlyingCode = um.UnderlyingCode;
td.UnderlyingName = um.UnderlyingName;
td.UnderlyingInstrumentType = um.UnderlyingInstrumentType;
if (!td.trade_swap.IsShare)
{
td.trade_swap.GetNotional = reader.GetDouble("份额/手数", true);
td.trade_swap.GetTradeAmount = td.trade_swap.GetNotional / um.CountRatio;
td.trade_swap.GetLot = td.trade_swap.GetNotional / um.ContractSize;
}
else
{
td.trade_swap.GetLot = reader.GetDouble("份额/手数", true);
td.trade_swap.GetNotional = td.trade_swap.GetLot * um.ContractSize;
td.trade_swap.GetTradeAmount = td.trade_swap.GetNotional / um.CountRatio;
}
td.Notional = td.trade_swap.GetNotional ?? 0;
td.TradeAmount = td.trade_swap.GetTradeAmount ?? 0;
td.Lots = td.trade_swap.GetLot;
//判断是否组合标的
var synthetic = DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(um.UnderlyingCode);
//读取组合标的
if (synthetic != null)
{
reader.SetTopType("组合标的");
var sulist = new List<UnderlyingPriceModel>(4);
var model = synthetic.GetSyntheticPriceModel();
var codeSet = model.SuList.Select(n => n.UnderlyingCode).ToHashSet(StringComparer.OrdinalIgnoreCase);
for (var i = 1; i <= 4; i++)
{
var code = reader.GetString("标的" + i + "_代码");
if (string.IsNullOrWhiteSpace(code))
{
continue;
}
if (!codeSet.Remove(code))
{
throw new ServiceException($"[组合标的]标的{i}_代码 填写错误,组合标的中不存在此标的:{code}");
}
model.SuList.First(n => n.UnderlyingCode.Equals(code, StringComparison.OrdinalIgnoreCase)).Price = reader.GetDouble("标的" + i + "_价格", true).Value;
}
if (codeSet.Any())
{
throw new ServiceException("[组合标的]未填写完整");
}
td.trade_swap.GetSpotPrice = model.Price = model.SuList.Sum(n => n.Coefficient * n.Price) + model.Constant;
td.MetaDic["组合标的"] = JsonHelper.ToJson(model);
}
else
{
td.trade_swap.GetSpotPrice = reader.GetDouble("期初标的价格", true);
}
td.SpotPrice = td.trade_swap.GetSpotPrice;
}
else
{
var str = reader.GetString("单位交易费用", true);
if (!string.IsNullOrWhiteSpace(str))
{
var percent = str.EndsWith("%");
if (percent)
{
var strTrim = str.TrimEnd('%');
if (double.TryParse(strTrim, out var num))
{
td.trade_swap.GetUnAnnualRate = num / 100;
}
else
{
throw new ServiceException($"[交易员收取]单位交易费用 填写错误:{str}");
}
}
else
{
if (double.TryParse(str, out var num))
{
singleFee = num;
}
else
{
throw new ServiceException($"[交易员收取]单位交易费用 填写错误:{str}");
}
}
}
}
td.trade_swap.GetSwapRate = reader.GetPercent("互换利率(年化)", false) ?? 0;
if (td.trade_swap.GetSwapRate != 0)
{
td.trade_swap.GetSwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";" + td.trade_swap.GetSwapRate;
}
td.trade_swap.GetMarginRate = reader.GetPercent("初始预付金率", false) ?? 0;
#endregion
#region 交易员支付信息读取
reader.SetTopType("交易员支付");
td.trade_swap.PayLongShort = reader.GetString("多头空头", false);
if (!string.IsNullOrWhiteSpace(td.trade_swap.PayLongShort))
{
td.trade_swap.IsPayFloatingProfit = true;
td.trade_swap.PayUnderlyingCode = reader.GetString("标的代码", true);
um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.trade_swap.PayUnderlyingCode);
if (um == null)
{
throw new ServiceException($"{td.trade_swap.PayUnderlyingCode} 不存在,请先新建标的再导入");
}
td.trade_swap.PayUnderlyingId = um.id;
td.UnderlyingId = um.id;
td.UnderlyingCode = um.UnderlyingCode;
td.UnderlyingName = um.UnderlyingName;
td.UnderlyingInstrumentType = um.UnderlyingInstrumentType;
if (!td.trade_swap.IsShare)
{
td.trade_swap.PayNotional = reader.GetDouble("份额/手数", true);
td.trade_swap.PayTradeAmount = td.trade_swap.PayNotional / um.CountRatio;
td.trade_swap.PayLot = td.trade_swap.PayNotional / um.ContractSize;
}
else
{
td.trade_swap.PayLot = reader.GetDouble("份额/手数", true);
td.trade_swap.PayNotional = td.trade_swap.PayLot * um.ContractSize;
td.trade_swap.PayTradeAmount = td.trade_swap.PayNotional / um.CountRatio;
}
td.Notional = td.trade_swap.PayNotional ?? 0;
td.TradeAmount = td.trade_swap.PayTradeAmount ?? 0;
td.Lots = td.trade_swap.PayLot;
//判断是否组合标的
var synthetic = DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(um.UnderlyingCode);
//读取组合标的
if (synthetic != null)
{
reader.SetTopType("组合标的");
var sulist = new List<UnderlyingPriceModel>(4);
var model = synthetic.GetSyntheticPriceModel();
var codeSet = model.SuList.Select(n => n.UnderlyingCode).ToHashSet(StringComparer.OrdinalIgnoreCase);
for (var i = 1; i <= 4; i++)
{
var code = reader.GetString("标的" + i + "_代码");
if (string.IsNullOrWhiteSpace(code))
{
continue;
}
if (!codeSet.Remove(code))
{
throw new ServiceException($"[组合标的]标的{i}_代码 填写错误,组合标的中不存在此标的:{code}");
}
model.SuList.First(n => n.UnderlyingCode.Equals(code, StringComparison.OrdinalIgnoreCase)).Price = reader.GetDouble("标的" + i + "_价格", true).Value;
}
if (codeSet.Any())
{
throw new ServiceException("[组合标的]未填写完整");
}
td.trade_swap.PaySpotPrice = model.Price = model.SuList.Sum(n => n.Coefficient * n.Price) + model.Constant;
td.MetaDic["组合标的2"] = JsonHelper.ToJson(model);
}
else
{
td.trade_swap.PaySpotPrice = reader.GetDouble("期初标的价格", true);
}
td.SpotPrice = td.trade_swap.PaySpotPrice;
}
else
{
var str = reader.GetString("单位交易费用", true);
if (!string.IsNullOrWhiteSpace(str))
{
var percent = str.EndsWith("%");
if (percent)
{
var strTrim = str.TrimEnd('%');
if (double.TryParse(strTrim, out var num))
{
td.trade_swap.PayUnAnnualRate = num / 100;
}
else
{
throw new ServiceException($"[交易员支付]单位交易费用 填写错误:{str}");
}
}
else
{
if (double.TryParse(str, out var num))
{
singleFee = num;
}
else
{
throw new ServiceException($"[交易员支付]单位交易费用 填写错误:{str}");
}
}
}
}
td.trade_swap.PaySwapRate = reader.GetPercent("互换利率(年化)", false) ?? 0;
if (td.trade_swap.PaySwapRate != 0)
{
td.trade_swap.PaySwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";" + td.trade_swap.PaySwapRate;
}
td.trade_swap.PayMarginRate = reader.GetPercent("初始预付金率", false) ?? 0;
#endregion
if ((string.IsNullOrWhiteSpace(td.trade_swap.GetLongShort) && string.IsNullOrWhiteSpace(td.trade_swap.PayLongShort)) || (!string.IsNullOrWhiteSpace(td.trade_swap.GetLongShort) && !string.IsNullOrWhiteSpace(td.trade_swap.PayLongShort)))
{
throw new ServiceException($"注意“交易员收取”和“交易员支付”不可同时为浮动收益或利息收益!");
}
//币种
var underlyingModel = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
td.QuoteCurrency = DataCacheProvider.GetVarietyDataSource().GetData(underlyingModel.UnderlyingTypeId).QuoteCurrency;
if (ExchangeRate != null)
{
if (td.QuoteCurrency != "CNY" && (!string.IsNullOrEmpty(td.QuoteCurrency)))
{
td.MetaDic.Add("ExchangeRate", ExchangeRate.ToString());
}
}
if (td.trade_swap.IsGetFloatingProfit)
{
if (!td.trade_swap.IsShare)
{
td.trade_swap.PaySingleFee = singleFee * um.ContractSize;
}
else
{
td.trade_swap.PaySingleFee = singleFee;
}
}
else
{
if (!td.trade_swap.IsShare)
{
td.trade_swap.GetSingleFee = singleFee * um.ContractSize;
}
else
{
td.trade_swap.GetSingleFee = singleFee;
}
}
var variety = DataCacheProvider.GetVariety(td.UnderlyingCode);
if (variety == null)
{
throw new ServiceException($"该标的[{td.UnderlyingCode}]对应的品种在系统中不存在");
}
else
{
if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any())
{
throw new ServiceException($"标的代码[{td.UnderlyingCode}]对应的品种币种不能为空");
}
else
{
td.QuoteCurrency = variety.QuoteCurrency;
}
var market = DataCacheProvider.GetMarketDataSource().AsQueryable().FirstOrDefault(x => x.MarketName == variety.TradingMarket);
if (QdpCalendarHelper.IsHoliday((DateTime)td.TradeDate, string.IsNullOrWhiteSpace(market?.CalendarName) ? "chn" : market?.CalendarName))
{
throw new ServiceException("成交日期:" + td.TradeDate + ",不能为节假日");
}
if (QdpCalendarHelper.IsHoliday((DateTime)td.ExerciseDate, string.IsNullOrWhiteSpace(market?.CalendarName) ? "chn" : market?.CalendarName))
{
throw new ServiceException("到期日期:" + td.ExerciseDate + ",不能为节假日");
}
if (td.TradeDate > td.ExerciseDate)
{
throw new ServiceException("到期日期不能早于成交日期");
}
}
reader.SetTopType("了结信息");
var action = reader.GetString("了结方式", false);
var hasSettleMode = !string.IsNullOrWhiteSpace(action);
InnerSaveSwapTrade(td, hasSettleMode, false);
#region 了结信息
if (hasSettleMode)
{
td.UnWindDate = reader.GetDate("了结日期", true);
if (action == "互换" && td.UnWindDate != td.ExerciseDate)
{
throw new ServiceException($"只支持到期日互换,了结日期[{td.UnWindDate}]和到日期[{td.ExerciseDate}]不一致");
}
td.FinalPrice = reader.GetDouble("了结标的价格", false);
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider((DateTime)td.UnWindDate);
if (td.FinalPrice == null)
{
td.FinalPrice = eodpriceProvider.GetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice);//平仓当天标的价格;
}
var annualFee = reader.GetDouble("利息金额", false);
var costFee = reader.GetDouble("平仓手续费", false);
UnwindSwapTradeCashHandle(td, action, annualFee, costFee);
}
#endregion
//记录审核日志
DbContext.TradeAuditLog.Add(new TradeAuditLog
{
TradeId = td.id,
Changes = null,
DataType = "00",
OptId = UserId,
OptName = UserName,
OptDate = OptDate,
OptType = "导入交易",
AuditFlag = TradeAuditFlag.operation
});
DbContext.SaveChanges();
return td;
}
private trade HandleToEndSwapTrade(DataRowReader reader)
{
var tradeNumnr = reader.GetString("交易编号", false);
var td = new trade();
var tdTable = DbContext.trade.FirstOrDefault(a => a.TradeNumber == tradeNumnr);
if (tdTable == null)
{
throw new ServiceException($"此交易编号[{td.TradeNumber}]不存在");
}
if (tdTable.TradeStatus != ConsTrade.确认成交)
{
throw new ServiceException("只有交易状态为‘确认成交’,才能进行批量了结导入");
}
td = tdTable;
td.trade_cash = new trade_cash();
td.trade_cash.UnwindStockEqvNotional = reader.GetDouble("了结名义本金", false) ?? 0;
td.trade_cash.UnwindPercentRate = reader.GetPercent("了结比例", false) ?? 0;
if (td.trade_cash.UnwindStockEqvNotional == 0 && td.trade_cash.UnwindPercentRate == 0)
{
throw new ServiceException($"交易编号[{td.TradeNumber}]中,了结名义本金与了结比例,必须填写一个值");
}
td.UnWindDate = reader.GetDate("了结日期", true);
var variety = DataCacheProvider.GetVariety(td.UnderlyingCode);
if (variety == null)
{
throw new ServiceException($"该标的[{td.UnderlyingCode}]对应的品种在系统中不存在");
}
else
{
var market = DataCacheProvider.GetMarketDataSource().AsQueryable().FirstOrDefault(x => x.MarketName == variety.TradingMarket);
if (QdpCalendarHelper.IsHoliday((DateTime)td.UnWindDate, string.IsNullOrWhiteSpace(market?.CalendarName) ? "chn" : market?.CalendarName))
{
throw new ServiceException("了结日期:" + td.UnWindDate + ",不能为节假日");
}
}
if (td.TradeDate > td.UnWindDate)
{
throw new ServiceException("了结日期必须要大于或等于成交日期");
}
if (td.UnWindDate > td.ExerciseDate)
{
throw new ServiceException("了结日期必须要小于或等于到期日期");
}
if (td.UnWindDate > valuedateBLL.ValueDate)
{
throw new ServiceException("了结日期必须要小于或等于系统日期");
}
td.FinalPrice = reader.GetDouble("了结标的价格", false);
var annualFeePay = reader.GetDouble("[支付]利息金额", false);
var annualFeeGet = reader.GetDouble("[收取]利息金额", false);
var costFee = reader.GetDouble("平仓手续费", false);
UnwindSwapTradeCashHandle(td, annualFeeGet, annualFeePay, costFee);
return td;
}
/// <summary>
/// 写入交易记录
/// </summary>
/// <param name="td">交易记录</param>
/// <param name="hasSettleMode">是否存在了结方式</param>
/// <param name="isHistoryImport">是否历史导入</param>
/// <exception cref="ServiceException"></exception>
private void InnerSaveSwapTrade(trade td, bool hasSettleMode = true, bool isHistoryImport = true)
{
td.TradeStatus = ConsTrade.确认成交;
if (!isHistoryImport && !hasSettleMode)
{
td.TradeStatus = ConsTrade.新增待确认;
}
if (string.IsNullOrWhiteSpace(td.TradeNumber))
{
td.TradeNumber = BizLogicSingleton.Instance.GenerateTradeNumberBeforeConfirm(td, DbContext);
}
else
{
if (DbContext.trade.Any(x => x.TradeNumber == td.TradeNumber))
{
throw new ServiceException($"存在重复的交易编号[{td.TradeNumber}]");
}
}
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.TradeDate.Value, seekPreday: true);
var tradePriceQuote = 0.0;
if (td.trade_swap.IsPayFloatingProfit)
{
tradePriceQuote = ((td.trade_swap.GetSingleFee ?? 0) * (td.Lots ?? 0) + td.StockEqvNotional * (td.trade_swap.GetUnAnnualRate ?? 0)).FormatValue(2);
td.trade_swap.GetTradePrice = tradePriceQuote;
if (td.trade_swap.IsTradePriceWhenOpen)
{
td.TradePrice = (tradePriceQuote * currencyRate).FormatValue(2);
}
else
{
tradePriceQuote = 0;
}
td.BuySell = "卖出";
}
else
{
tradePriceQuote = ((td.trade_swap.PaySingleFee ?? 0) * (td.Lots ?? 0) + td.StockEqvNotional * (td.trade_swap.PayUnAnnualRate ?? 0)).FormatValue(2);
td.trade_swap.PayTradePrice = tradePriceQuote;
if (td.trade_swap.IsTradePriceWhenOpen)
{
td.TradePrice = (tradePriceQuote * currencyRate).FormatValue(2);
}
else
{
tradePriceQuote = 0;
}
td.BuySell = "买入";
}
td.OriginalNotional = td.Notional;
td.OriginalStockEqvNotional = td.StockEqvNotional;
td.StockEqvNotionalReal = td.StockEqvNotionalReal;
td.IsUsePremiumRate = true;
td.MarginTemplateName = null;
td.MarginType = MarginTypeEnum.DEFAULT;
td.IsTradePricePayType = true;
td.TradeSource = TradeSourceEnum.导入交易.ToString();
td.OptId = UserId;
td.OptName = UserName;
td.OptDate = DateTime.Now;
SetDBModelCreator(td);
DbContext.trade.Add(td);
DbContext.SaveChanges();
td.trade_swap.TradeId = td.id;
td.trade_swap.SwapType = "普通";
td.trade_swap.OptId = UserId;
td.trade_swap.OptName = UserName;
td.trade_swap.OptDate = DateTime.Now;
DbContext.trade_swap.Add(td.trade_swap);
SaveTradeMeta(td);
if (isHistoryImport || hasSettleMode)
{
var tc = new trade_cash
{
ValidState = "Valid"
};
DbContext.trade_cash.Add(tc);
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = DateTime.Now;
tc.Action = ClientCashInCashOut.系统操作_期权费;
tc.Amount = (td.TradePrice ?? 0) * (td.BuySell == "买入" ? -1 : 1);
tc.QuoteAmount = tradePriceQuote * (td.BuySell == "买入" ? -1 : 1);
tc.CurrencyRate = currencyRate;
tc.ExceciseType = "现金";
tc.TradeId = td.id;
tc.ValueDate = td.TradeDate.Value;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.Status = TradeCashStatusEnum.已执行;
tc.TradeType = td.BuySell;
DbContext.SaveChanges();
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = tc.Amount,
QuoteAmount = tc.QuoteAmount,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString(),
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now
};
DbContext.trade_cash_detail.Add(tcdGet);
}
DbContext.SaveChanges();
}
private void SaveTradeMeta(trade t)
{
if (t != null && t.MetaDic != null && t.MetaDic.Count() > 0)
{
foreach (var kv in t.MetaDic)
{
if (!string.IsNullOrEmpty(kv.Value))
{
AddTradeMeta(false, t.id, kv.Key, kv.Value);
}
}
}
}
/// <summary>
/// 了结导入数据处理
/// </summary>
/// <param name="td"></param>
/// <param name="annualFee"></param>
/// <param name="costFee"></param>
private void UnwindSwapTradeCashHandle(trade td, double? annualFeeGet, double? annualFeePay, double? costFee)
{
var client = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
if (td.FinalPrice == null)
{
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider((DateTime)td.UnWindDate);
if (eodpriceProvider.TryGetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice, out var price))
{
td.FinalPrice = price;
}
else
{
throw new ServiceException($"未找到{td.UnderlyingCode}在{td.UnWindDate?.ToString("yyyy.M.d")}对应的收盘价");
}
}
td.trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == td.id);
var unwindType = "部分平仓";
//获取平仓比例
if (td.trade_cash.UnwindPercentRate == 0 || (td.trade_cash.UnwindStockEqvNotional != 0 && td.trade_cash.UnwindPercentRate != 0))
{
if (td.StockEqvNotional <= td.trade_cash.UnwindStockEqvNotional + 1e-10)
{
td.trade_cash.UnwindStockEqvNotional = td.StockEqvNotional;
unwindType = "全部平仓";
}
td.trade_cash.UnwindPercentRate = td.trade_cash.UnwindStockEqvNotional / td.OriginalStockEqvNotional;
}
else if ((td.StockEqvNotional / td.OriginalStockEqvNotional) <= td.trade_cash.UnwindPercentRate + 1e-10)
{
td.trade_cash.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
td.trade_cash.UnwindStockEqvNotional = td.StockEqvNotional;
unwindType = "全部平仓";
}
if (td.trade_cash.UnwindStockEqvNotional == 0)
{
if ((td.StockEqvNotional / td.OriginalStockEqvNotional) <= td.trade_cash.UnwindPercentRate + 1e-10)
{
td.trade_cash.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
unwindType = "全部平仓";
}
td.trade_cash.UnwindStockEqvNotional = (double)(td.OriginalStockEqvNotional * td.trade_cash.UnwindPercentRate);
}
else if (td.StockEqvNotional <= td.trade_cash.UnwindStockEqvNotional + 1e-10)
{
td.trade_cash.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
td.trade_cash.UnwindStockEqvNotional = td.StockEqvNotional;
unwindType = "全部平仓";
}
//增加现金交割交易记录
var tc = new trade_cash();
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = OptDate;
tc.ExceciseType = "现金";
tc.TradeType = td.BuySell;
tc.CallPut = td.CallPut;
tc.IsLastAction = true;
tc.TradeId = td.id;
tc.FinalPrice = td.FinalPrice;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.UnwindType = unwindType;
tc.UnwindNotional = td.trade_cash.UnwindPercentRate * td.OriginalNotional;
tc.UnwindTradeAmount = tc.UnwindNotional / um.CountRatio;
tc.UnwindPercentRate = td.trade_cash.UnwindPercentRate;
tc.NotionalPercentRate = tc.UnwindPercentRate;
if (td.trade_swap.IsPayFloatingProfit)
{
var tradeCashs = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= td.UnWindDate);
var tradeCashIds = tradeCashs.Select(x => x.id);
var tradeCash = tradeCashs.OrderByDescending(y => y.id).FirstOrDefault();
var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == td.id && tradeCashIds.Contains(x.TradeCashId)).ToArray();
var tradeCashSwap = tradeCash != null ? cashSwaps.FirstOrDefault(x => x.TradeCashId == tradeCash.id) : null;
//取最后一次手动收益;
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto);
var lastManualCash = lastManualCashSwap != null ? tradeCashs.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(td, td.trade_swap, tradeCashSwap?.PayFinalPrice ?? td.SpotPrice ?? 0
, td.FinalPrice ?? 0, td.trade_cash.UnwindStockEqvNotional ?? 0, td.UnWindDate.Value, tradeCash?.ValueDate);
DateTime endDate;
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsGetFloatingProfit, out endDate);
var extraAmountGetQuote = annualFeeGet ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, td.trade_cash.UnwindStockEqvNotional ?? 0);
var costFeeGetQuote = costFee ?? 0;
var costTradePriceGetQuote = 0.0;
if (!td.trade_swap.IsTradePriceWhenOpen)
{
costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, true, true);
}
var quoteAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: quoteAmount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var initialAmountPay = (initialAmountPayQuote * currencyRate).FormatValue(2);
var extraAmountGet = (extraAmountGetQuote * currencyRate).FormatValue(2);
var costFeeGet = (costFeeGetQuote * currencyRate).FormatValue(2);
var costTradePriceGet = (costTradePriceGetQuote * currencyRate).FormatValue(2);
tc.CurrencyRate = currencyRate;
tc.Action = ClientCashInCashOut.系统操作_平仓费;
tc.IsLastAction = td.Notional <= 0 ? true : false;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
td.StockEqvNotional -= (double)(td.OriginalStockEqvNotional * tc.UnwindPercentRate);
td.Notional -= (double)(td.OriginalNotional * tc.UnwindPercentRate);
td.TradeAmount = td.Notional / um.CountRatio;
td.UnWindNotional = tc.UnwindNotional;
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : (tc.UnwindType == "全部平仓" ? "已平仓" : td.TradeStatus);
td.HasPartialUnWind = tc.UnwindType == "部分平仓" ? 1 : 0;
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.PayStartPrice = td.trade_swap.PayFinalPrice ?? td.trade_swap.PaySpotPrice;
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
trade_cash_swap.PayInitialAmount = initialAmountPay;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsPayFloatingProfit, out endDate);
var extraAmountPayQuote = annualFeePay ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.PaySwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, td.trade_cash.UnwindStockEqvNotional ?? 0);
var extraAmountPay = (extraAmountPayQuote * currencyRate).FormatValue(2);
trade_cash_swap.PayExtraAmount = extraAmountPay;
trade_cash_swap.PayAmount = trade_cash_swap.PayInitialAmount + extraAmountPay;
trade_cash_swap.GetExtraAmount = extraAmountGet;
trade_cash_swap.GetCostFee = costFeeGet + costTradePriceGet;
trade_cash_swap.GetAmount = (trade_cash_swap.GetExtraAmount ?? 0) + (trade_cash_swap.GetCostFee ?? 0);
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
tc.Amount = (trade_cash_swap.GetAmount ?? 0) - (trade_cash_swap.PayAmount ?? 0);
tc.QuoteAmount = tc.Amount;
DbContext.trade_cash.Add(tc);
DbContext.SaveChanges();
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
DbContext.SaveChanges();
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = extraAmountGet - extraAmountPay,
QuoteAmount = extraAmountGetQuote - extraAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = costFeeGet,
QuoteAmount = costFeeGetQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = costTradePriceGet,
QuoteAmount = costTradePriceGetQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -initialAmountPay,
QuoteAmount = -initialAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
else
{
var tradeCashs = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= td.UnWindDate);
var tradeCashIds = tradeCashs.Select(x => x.id);
var tradeCash = tradeCashs.OrderByDescending(y => y.id).FirstOrDefault();
var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == td.id && tradeCashIds.Contains(x.TradeCashId)).ToArray();
var tradeCashSwap = tradeCash != null ? cashSwaps.FirstOrDefault(x => x.TradeCashId == tradeCash.id) : null;
//取最后一次手动收益;
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto);
var lastManualCash = lastManualCashSwap != null ? tradeCashs.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
var initialAmountGetQuote = PayoffSwapCalcService.GetInitialAmountSwapGet(td, td.trade_swap, tradeCashSwap?.GetFinalPrice ?? td.SpotPrice ?? 0
, td.FinalPrice ?? 0, td.trade_cash.UnwindStockEqvNotional ?? 0, td.UnWindDate.Value, tradeCash?.ValueDate);
DateTime endDate;
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsPayFloatingProfit, out endDate);
var extraAmountPayQuote = annualFeePay ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.PaySwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, td.trade_cash.UnwindStockEqvNotional ?? 0);
var costFeePayQuote = costFee ?? 0;
var costTradePricePayQuote = 0.0;
if (!td.trade_swap.IsTradePriceWhenOpen)
{
costTradePricePayQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, false, true);
}
var quoteAmount = initialAmountGetQuote - extraAmountPayQuote - costFeePayQuote - costTradePricePayQuote;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: quoteAmount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var initialAmountGet = (initialAmountGetQuote * currencyRate).FormatValue(2);
var extraAmountPay = (extraAmountPayQuote * currencyRate).FormatValue(2);
var costFeePay = (costFeePayQuote * currencyRate).FormatValue(2);
var costTradePricePay = (costTradePricePayQuote * currencyRate).FormatValue(2);
tc.CurrencyRate = currencyRate;
tc.Action = ClientCashInCashOut.系统操作_平仓费;
tc.IsLastAction = td.Notional <= 0 ? true : false;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
td.StockEqvNotional -= (double)(td.OriginalStockEqvNotional * tc.UnwindPercentRate);
td.Notional -= (double)(td.OriginalNotional * tc.UnwindPercentRate);
td.TradeAmount = td.Notional / um.CountRatio;
td.UnWindNotional = tc.UnwindNotional;
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : (tc.UnwindType == "全部平仓" ? "已平仓" : td.TradeStatus);
td.HasPartialUnWind = tc.UnwindType == "部分平仓" ? 1 : 0;
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.GetStartPrice = td.trade_swap.GetFinalPrice ?? td.trade_swap.GetSpotPrice;
trade_cash_swap.GetFinalPrice = tc.FinalPrice;
trade_cash_swap.GetInitialAmount = initialAmountGet;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsGetFloatingProfit, out endDate);
var extraAmountGetQuote = annualFeeGet ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, td.trade_cash.UnwindStockEqvNotional ?? 0);
var extraAmountGet = (extraAmountGetQuote * currencyRate).FormatValue(2);
trade_cash_swap.GetExtraAmount = extraAmountGet;
trade_cash_swap.GetAmount = initialAmountGet + extraAmountGet;
trade_cash_swap.PayExtraAmount = extraAmountPay;
trade_cash_swap.PayCostFee = costFeePay + costTradePricePay;
trade_cash_swap.PayAmount = (trade_cash_swap.PayExtraAmount ?? 0) + (trade_cash_swap.PayCostFee ?? 0);
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
tc.Amount = (trade_cash_swap.GetAmount ?? 0) - (trade_cash_swap.PayAmount ?? 0);
tc.QuoteAmount = tc.Amount;
DbContext.trade_cash.Add(tc);
DbContext.SaveChanges();
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
DbContext.SaveChanges();
var tcdExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = extraAmountGet - extraAmountPay,
QuoteAmount = extraAmountGetQuote - extraAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdExtraAmount);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -costFeePay,
QuoteAmount = -costFeePayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -costTradePricePay,
QuoteAmount = -costTradePricePayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = initialAmountGet,
QuoteAmount = initialAmountGetQuote,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var auditLog = new TradeAuditLog
{
TradeId = tc.TradeId,
Changes = null,
DataType = "00",
OptType = "批量了结-平仓",
OptId = UserId,
OptName = UserName,
OptDate = OptDate,
AuditFlag = TradeAuditFlag.operation
};
//记录审核日志
DbContext.TradeAuditLog.Add(auditLog);
DbContext.SaveChanges();
}
private void UnwindSwapTradeCashHandle(trade td, string action, double? annualFee, double? costFee)
{
var client = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
//增加现金交割交易记录
var tc = new trade_cash();
DbContext.trade_cash.Add(tc);
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = OptDate;
tc.ExceciseType = "现金";
tc.TradeType = td.BuySell;
tc.CallPut = td.CallPut;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.IsLastAction = true;
tc.TradeId = td.id;
tc.FinalPrice = td.FinalPrice;
tc.UnwindType = "全部平仓";
tc.UnwindNotional = td.Notional;
tc.UnwindTradeAmount = td.TradeAmount;
tc.UnwindPercentRate = 1;
tc.NotionalPercentRate = tc.UnwindPercentRate;
if (td.trade_swap.IsPayFloatingProfit)
{
var tradeCashs = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= td.UnWindDate);
var tradeCashIds = tradeCashs.Select(x => x.id);
var tradeCash = tradeCashs.OrderByDescending(y => y.id).FirstOrDefault();
var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == td.id && tradeCashIds.Contains(x.TradeCashId)).ToArray();
var tradeCashSwap = tradeCash != null ? cashSwaps.FirstOrDefault(x => x.TradeCashId == tradeCash.id) : null;
//取最后一次手动收益;
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto);
var lastManualCash = lastManualCashSwap != null ? tradeCashs.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(td, td.trade_swap, tradeCashSwap?.PayFinalPrice ?? td.SpotPrice ?? 0
, td.FinalPrice ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0), td.UnWindDate.Value, tradeCash?.ValueDate);
DateTime endDate;
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsGetFloatingProfit, out endDate);
var extraAmountGetQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsPayFloatingProfit, out endDate);
var extraAmountPayQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.PaySwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
var costFeeGetQuote = costFee ?? 0;
var costTradePriceGetQuote = 0.0;
if (!td.trade_swap.IsTradePriceWhenOpen)
{
costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, true, true);
}
var quoteAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote - extraAmountPayQuote;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: quoteAmount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var extraAmountPay = (extraAmountPayQuote * currencyRate).FormatValue(2);
var initialAmountPay = (initialAmountPayQuote * currencyRate).FormatValue(2);
var extraAmountGet = (extraAmountGetQuote * currencyRate).FormatValue(2);
var costFeeGet = (costFeeGetQuote * currencyRate).FormatValue(2);
var costTradePriceGet = (costTradePriceGetQuote * currencyRate).FormatValue(2);
td.TradeStatus = td.UnWindDate.Value == td.ExerciseDate ? "已到期" : "已平仓";
td.StockEqvNotional = 0;
td.Notional = 0;
td.TradeAmount = 0;
td.UnWindNotional = tc.UnwindNotional;
tc.Amount = extraAmountGet + costFeeGet + costTradePriceGet - initialAmountPay - extraAmountPay;
tc.QuoteAmount = quoteAmount;
tc.CurrencyRate = currencyRate;
tc.Action = action == "平仓" ? ClientCashInCashOut.系统操作_平仓费 : ClientCashInCashOut.系统操作_互换;
tc.IsLastAction = true;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = td.UnWindDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
DbContext.SaveChanges();
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
trade_cash_swap.PayExtraAmount = extraAmountPay;
trade_cash_swap.PayInitialAmount = initialAmountPay;
trade_cash_swap.PayAmount = extraAmountPay + initialAmountPay;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.GetExtraAmount = extraAmountGet;
trade_cash_swap.GetCostFee = costFeeGet + costTradePriceGet;
trade_cash_swap.GetAmount = extraAmountGet + costFeeGet + costTradePriceGet;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = extraAmountGet - extraAmountPay,
QuoteAmount = extraAmountGetQuote - extraAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdExtraAmount);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = costFeeGet,
QuoteAmount = costFeeGetQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = costTradePriceGet,
QuoteAmount = costTradePriceGetQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdInitialAmountPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -initialAmountPay,
QuoteAmount = -initialAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdInitialAmountPay);
}
else
{
var tradeCashs = DbContext.trade_cash.Where(y => y.TradeId == td.id && y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= td.UnWindDate);
var tradeCashIds = tradeCashs.Select(x => x.id);
var tradeCash = tradeCashs.OrderByDescending(y => y.id).FirstOrDefault();
var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == td.id && tradeCashIds.Contains(x.TradeCashId)).ToArray();
var tradeCashSwap = tradeCash != null ? cashSwaps.FirstOrDefault(x => x.TradeCashId == tradeCash.id) : null;
//取最后一次手动收益;
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto);
var lastManualCash = lastManualCashSwap != null ? tradeCashs.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
var initialAmountGetQuote = PayoffSwapCalcService.GetInitialAmountSwapGet(td, td.trade_swap, tradeCashSwap?.GetFinalPrice ?? td.SpotPrice ?? 0
, td.FinalPrice ?? 0, td.OriginalStockEqvNotional ?? 0, td.UnWindDate.Value, tradeCash?.ValueDate);
DateTime endDate;
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsPayFloatingProfit, out endDate);
var extraAmountPayQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.PaySwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(td, td.trade_swap, td.UnWindDate.Value, tradeCash, lastManualCash, td.trade_swap.IsGetFloatingProfit, out endDate);
var extraAmountGetQuote = annualFee ?? PayoffSwapCalcService.GetExtraAmountBySwapRate(td.ClientId, td.TradeDate, td.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, td.trade_swap.AnnualDays ?? 0, (td.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
var costFeePayQuote = costFee ?? 0;
var costTradePricePayQuote = 0.0;
if (!td.trade_swap.IsTradePriceWhenOpen)
{
costTradePricePayQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, false, true);
}
var quoteAmount = initialAmountGetQuote + extraAmountGetQuote - extraAmountPayQuote - costFeePayQuote - costTradePricePayQuote;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: quoteAmount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var extraAmountGet = (extraAmountGetQuote * currencyRate).FormatValue(2);
var initialAmountGet = (initialAmountGetQuote * currencyRate).FormatValue(2);
var extraAmountPay = (extraAmountPayQuote * currencyRate).FormatValue(2);
var costFeePay = (costFeePayQuote * currencyRate).FormatValue(2);
var costTradePricePay = (costTradePricePayQuote * currencyRate).FormatValue(2);
tc.Amount = initialAmountGet + extraAmountGet - extraAmountPay - costFeePay - costTradePricePay;
tc.QuoteAmount = quoteAmount;
tc.CurrencyRate = currencyRate;
tc.Action = action == "平仓" ? ClientCashInCashOut.系统操作_平仓费 : ClientCashInCashOut.系统操作_互换;
tc.IsLastAction = true;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = td.UnWindDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
DbContext.SaveChanges();
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : "已平仓";
td.StockEqvNotional = 0;
td.Notional = 0;
td.TradeAmount = 0;
td.UnWindNotional = tc.UnwindNotional;
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.GetStartPrice = trade_swap.GetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.GetFinalPrice = tc.FinalPrice;
trade_cash_swap.GetInitialAmount = initialAmountGet;
trade_cash_swap.GetExtraAmount = extraAmountGet;
trade_cash_swap.GetAmount = initialAmountGet + extraAmountGet;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.PayExtraAmount = extraAmountPay;
trade_cash_swap.PayCostFee = costFeePay + costTradePricePay;
trade_cash_swap.PayAmount = extraAmountPay + costFeePay + costTradePricePay;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdExtraAmount = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = extraAmountGet - extraAmountPay,
QuoteAmount = extraAmountGetQuote - extraAmountPayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdExtraAmount);
var tcdCostFeePay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -costFeePay,
QuoteAmount = -costFeePayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeePay);
var tcdCostTradePricePay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = -costTradePricePay,
QuoteAmount = -costTradePricePayQuote,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePricePay);
var tcdInitialAmountGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = initialAmountGet,
QuoteAmount = initialAmountGetQuote,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdInitialAmountGet);
}
DbContext.SaveChanges();
}
#endregion
#region 互换交易历史导入
/// <summary>
/// 导入交易
/// </summary>
/// <param name="streamIn"></param>
/// <param name="totalNum">当前文件中的目标期权总条数</param>
/// <param name="successNum">成功入库的数量</param>
public void ImportSwapTradeHistroyDataFromExcel(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
var groupTradeList = new List<OtcOptionTradeFullEx>();
var structureTradeList = new List<OtcOptionTradeFullEx>();
try
{
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 3)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowTopTypeReader(table);
rowIndex = 2;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(2))
{
using (var trans = BeginTransaction())
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
reader.SetDataRow(row);
//映射导入数据到交易对象
HandleSwapTradeHistroyData(reader);
successNum++;
trans.Commit();
}
}
}
catch (ServiceException se)
{
if (se.Tag != null)
{
throw;
}
throw new ServiceException($"已成功导入{successNum}条;\n第{rowIndex}行,{se.Message}");
}
catch (Exception ex)
{
LogFactory.GetLogger("导入期权交易").Error(ex);
throw new ServiceException($"已成功导入{successNum}条,\n第{rowIndex}行,发生错误:{ex.Message}", ex);
}
}
private trade HandleSwapTradeHistroyData(DataRowTopTypeReader reader)
{
var td = new trade();
td.trade_swap = new trade_swap();
//基本要素
td.TradeNumber = reader.GetString("交易编号", false);
td.AssetBookName = reader.GetString("簿记账户名称", true);
td.TraderName = reader.GetString("交易员名称", true);
new OtcOptionSaveChecker(this).CheckAssetBook(td).CheckTrader(td);
td.TradeType = "收益互换";
td.ClientName = reader.GetString("交易对手方名称", true);
if (string.IsNullOrWhiteSpace(td.ClientName))
{
throw new ServiceException("交易对手方名称 必须填写");
}
//交易日期
td.TradeDate = reader.GetDate("成交日期", true);
td.StartDate = reader.GetDate("开始日期", true);
td.ExerciseDate = reader.GetDate("到期日期", true);
td.SettlementDate = td.ExerciseDate;
td.StockEqvNotional = reader.GetDouble("名义本金", true) ?? 0;
td.trade_swap.AnnualDays = reader.GetInt("年化天数", true);
td.trade_swap.AnnualVarIncome = reader.GetString("浮动收益年化", true) == "是";
td.trade_swap.RateCalcMode = GetRateCalcMode(reader.GetString("计息方式", true));
td.trade_swap.IsTradePriceWhenOpen = reader.GetString("是否开仓时收取开仓费", true) == "是";
td.trade_swap.IsShare = reader.GetString("收费基本单位", true) == "手数";
var ExchangeRate = reader.GetDouble("汇率", false);
td.Comments = reader.GetString("备注", false);
var clientQuery = DbContextFactory.GetClientDbContext(OptUser).client.AsQueryable();
if (!string.IsNullOrWhiteSpace(td.ClientName))
{
clientQuery = clientQuery.Where(c => c.Name == td.ClientName);
}
var client = clientQuery.Select(n => new { n.id, n.SettlementCurrency }).FirstOrDefault();
if (client == null)
{
throw new ServiceException($"交易对手方不存在,客户名称:{td.ClientName}");
}
td.ClientId = client.id;
td.SettlementCurrency = client.SettlementCurrency;
td.OpponentRole = "乙方";
var um = new underlying_manager();
var singleFee = 0.0;
#region 交易员收取信息读取
reader.SetTopType("交易员收取");
td.trade_swap.GetLongShort = reader.GetString("多头空头", false);
if (!string.IsNullOrWhiteSpace(td.trade_swap.GetLongShort))
{
td.trade_swap.IsGetFloatingProfit = true;
td.trade_swap.GetUnderlyingCode = reader.GetString("标的代码", true);
um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.trade_swap.GetUnderlyingCode);
if (um == null)
{
throw new ServiceException($"{td.trade_swap.GetUnderlyingCode} 不存在,请先新建标的再导入");
}
td.trade_swap.GetUnderlyingId = um.id;
td.UnderlyingId = um.id;
td.UnderlyingCode = um.UnderlyingCode;
td.UnderlyingName = um.UnderlyingName;
td.UnderlyingInstrumentType = um.UnderlyingInstrumentType;
if (!td.trade_swap.IsShare)
{
td.trade_swap.GetNotional = reader.GetDouble("份额/手数", true);
td.trade_swap.GetTradeAmount = td.trade_swap.GetNotional / um.CountRatio;
td.trade_swap.GetLot = td.trade_swap.GetNotional / um.ContractSize;
}
else
{
td.trade_swap.GetLot = reader.GetDouble("份额/手数", true);
td.trade_swap.GetNotional = td.trade_swap.GetLot * um.ContractSize;
td.trade_swap.GetTradeAmount = td.trade_swap.GetNotional / um.CountRatio;
}
td.Notional = td.trade_swap.GetNotional ?? 0;
td.TradeAmount = td.trade_swap.GetTradeAmount ?? 0;
td.Lots = td.trade_swap.GetLot;
//判断是否组合标的
var synthetic = DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(um.UnderlyingCode);
//读取组合标的
if (synthetic != null)
{
reader.SetTopType("组合标的");
var sulist = new List<UnderlyingPriceModel>(4);
var model = synthetic.GetSyntheticPriceModel();
var codeSet = model.SuList.Select(n => n.UnderlyingCode).ToHashSet(StringComparer.OrdinalIgnoreCase);
for (var i = 1; i <= 4; i++)
{
var code = reader.GetString("标的" + i + "_代码");
if (string.IsNullOrWhiteSpace(code))
{
continue;
}
if (!codeSet.Remove(code))
{
throw new ServiceException($"[组合标的]标的{i}_代码 填写错误,组合标的中不存在此标的:{code}");
}
model.SuList.First(n => n.UnderlyingCode.Equals(code, StringComparison.OrdinalIgnoreCase)).Price = reader.GetDouble("标的" + i + "_价格", true).Value;
}
if (codeSet.Any())
{
throw new ServiceException("[组合标的]未填写完整");
}
td.trade_swap.GetSpotPrice = model.Price = model.SuList.Sum(n => n.Coefficient * n.Price) + model.Constant;
td.MetaDic["组合标的"] = JsonHelper.ToJson(model);
}
else
{
td.trade_swap.GetSpotPrice = reader.GetDouble("期初标的价格", true);
}
td.SpotPrice = td.trade_swap.GetSpotPrice;
}
else
{
var str = reader.GetString("单位交易费用", true);
if (!string.IsNullOrWhiteSpace(str))
{
var percent = str.EndsWith("%");
if (percent)
{
var strTrim = str.TrimEnd('%');
if (double.TryParse(strTrim, out var num))
{
td.trade_swap.GetUnAnnualRate = num / 100;
}
else
{
throw new ServiceException($"[交易员收取]单位交易费用 填写错误:{str}");
}
}
else
{
if (double.TryParse(str, out var num))
{
singleFee = num;
}
else
{
throw new ServiceException($"[交易员收取]单位交易费用 填写错误:{str}");
}
}
}
}
td.trade_swap.GetSwapRate = reader.GetPercent("互换利率(年化)", false) ?? 0;
if (td.trade_swap.GetSwapRate >= 0)
{
td.trade_swap.GetSwapTimeAndRate = td.ExerciseDate + ";" + td.trade_swap.GetSwapRate;
}
td.trade_swap.GetMarginRate = reader.GetPercent("初始预付金率", false) ?? 0;
#endregion
#region 交易员支付信息读取
reader.SetTopType("交易员支付");
td.trade_swap.PayLongShort = reader.GetString("多头空头", false);
if (!string.IsNullOrWhiteSpace(td.trade_swap.PayLongShort))
{
td.trade_swap.IsPayFloatingProfit = true;
td.trade_swap.PayUnderlyingCode = reader.GetString("标的代码", true);
um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.trade_swap.PayUnderlyingCode);
if (um == null)
{
throw new ServiceException($"{td.trade_swap.PayUnderlyingCode} 不存在,请先新建标的再导入");
}
td.trade_swap.PayUnderlyingId = um.id;
td.UnderlyingId = um.id;
td.UnderlyingCode = um.UnderlyingCode;
td.UnderlyingName = um.UnderlyingName;
td.UnderlyingInstrumentType = um.UnderlyingInstrumentType;
if (!td.trade_swap.IsShare)
{
td.trade_swap.PayNotional = reader.GetDouble("份额/手数", true);
td.trade_swap.PayTradeAmount = td.trade_swap.PayNotional / um.CountRatio;
td.trade_swap.PayLot = td.trade_swap.PayNotional / um.ContractSize;
}
else
{
td.trade_swap.PayLot = reader.GetDouble("份额/手数", true);
td.trade_swap.PayNotional = td.trade_swap.PayLot * um.ContractSize;
td.trade_swap.PayTradeAmount = td.trade_swap.PayNotional / um.CountRatio;
}
td.Notional = td.trade_swap.PayNotional ?? 0;
td.TradeAmount = td.trade_swap.PayTradeAmount ?? 0;
td.Lots = td.trade_swap.PayLot;
//判断是否组合标的
var synthetic = DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(um.UnderlyingCode);
//读取组合标的
if (synthetic != null)
{
reader.SetTopType("组合标的");
var sulist = new List<UnderlyingPriceModel>(4);
var model = synthetic.GetSyntheticPriceModel();
var codeSet = model.SuList.Select(n => n.UnderlyingCode).ToHashSet(StringComparer.OrdinalIgnoreCase);
for (var i = 1; i <= 4; i++)
{
var code = reader.GetString("标的" + i + "_代码");
if (string.IsNullOrWhiteSpace(code))
{
continue;
}
if (!codeSet.Remove(code))
{
throw new ServiceException($"[组合标的]标的{i}_代码 填写错误,组合标的中不存在此标的:{code}");
}
model.SuList.First(n => n.UnderlyingCode.Equals(code, StringComparison.OrdinalIgnoreCase)).Price = reader.GetDouble("标的" + i + "_价格", true).Value;
}
if (codeSet.Any())
{
throw new ServiceException("[组合标的]未填写完整");
}
td.trade_swap.PaySpotPrice = model.Price = model.SuList.Sum(n => n.Coefficient * n.Price) + model.Constant;
td.MetaDic["组合标的2"] = JsonHelper.ToJson(model);
}
else
{
td.trade_swap.PaySpotPrice = reader.GetDouble("期初标的价格", true);
}
td.SpotPrice = td.trade_swap.PaySpotPrice;
}
else
{
var str = reader.GetString("单位交易费用", true);
if (!string.IsNullOrWhiteSpace(str))
{
var percent = str.EndsWith("%");
if (percent)
{
var strTrim = str.TrimEnd('%');
if (double.TryParse(strTrim, out var num))
{
td.trade_swap.PayUnAnnualRate = num / 100;
}
else
{
throw new ServiceException($"[交易员支付]单位交易费用 填写错误:{str}");
}
}
else
{
if (double.TryParse(str, out var num))
{
singleFee = num;
}
else
{
throw new ServiceException($"[交易员支付]单位交易费用 填写错误:{str}");
}
}
}
}
td.trade_swap.PaySwapRate = reader.GetPercent("互换利率(年化)", false) ?? 0;
if (td.trade_swap.PaySwapRate >= 0)
{
td.trade_swap.PaySwapTimeAndRate = td.ExerciseDate + ";" + td.trade_swap.PaySwapRate;
}
td.trade_swap.PayMarginRate = reader.GetPercent("初始预付金率", false) ?? 0;
#endregion
if ((string.IsNullOrWhiteSpace(td.trade_swap.GetLongShort) && string.IsNullOrWhiteSpace(td.trade_swap.PayLongShort))||(!string.IsNullOrWhiteSpace(td.trade_swap.GetLongShort) && !string.IsNullOrWhiteSpace(td.trade_swap.PayLongShort)))
{
throw new ServiceException($"注意“交易员收取”和“交易员支付”不可同时为浮动收益或利息收益!");
}
var underlyingModel = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
td.QuoteCurrency = DataCacheProvider.GetVarietyDataSource().GetData(underlyingModel.UnderlyingTypeId).QuoteCurrency;
if (ExchangeRate != null)
{
if (td.QuoteCurrency != "CNY" && (!string.IsNullOrEmpty(td.QuoteCurrency)))
{
td.MetaDic.Add("ExchangeRate", ExchangeRate.ToString());
}
}
if (td.trade_swap.IsGetFloatingProfit)
{
if (!td.trade_swap.IsShare)
{
td.trade_swap.PaySingleFee = singleFee * um.ContractSize;
}
else
{
td.trade_swap.PaySingleFee = singleFee;
}
}
else
{
if (!td.trade_swap.IsShare)
{
td.trade_swap.GetSingleFee = singleFee * um.ContractSize;
}
else
{
td.trade_swap.GetSingleFee = singleFee;
}
}
var variety = DataCacheProvider.GetVariety(td.UnderlyingCode);
if (variety == null)
{
throw new ServiceException($"该标的[{td.UnderlyingCode}]对应的品种在系统中不存在");
}
else
{
if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any())
{
throw new ServiceException($"标的代码[{td.UnderlyingCode}]对应的品种币种不能为空");
}
else
{
td.QuoteCurrency = variety.QuoteCurrency;
}
var market = DataCacheProvider.GetMarketDataSource().AsQueryable().FirstOrDefault(x => x.MarketName == variety.TradingMarket);
if (QdpCalendarHelper.IsHoliday((DateTime)td.TradeDate, string.IsNullOrWhiteSpace(market?.CalendarName) ? "chn" : market?.CalendarName))
{
throw new ServiceException("成交日期:" + td.TradeDate + ",不能为节假日");
}
if (QdpCalendarHelper.IsHoliday((DateTime)td.ExerciseDate, string.IsNullOrWhiteSpace(market?.CalendarName) ? "chn" : market?.CalendarName))
{
throw new ServiceException("到期日期:" + td.ExerciseDate + ",不能为节假日");
}
if (td.TradeDate > td.ExerciseDate)
{
throw new ServiceException("到期日期不能早于成交日期");
}
}
InnerSaveSwapTrade(td);
#region 了结信息
reader.SetTopType("了结信息");
var action = reader.GetString("了结方式", false);
if (!string.IsNullOrWhiteSpace(action))
{
td.UnWindDate = reader.GetDate("了结日期", true);
if (action == "互换" && td.UnWindDate != td.ExerciseDate)
{
throw new ServiceException($"只支持到期日互换,了结日期[{td.UnWindDate}]和到日期[{td.ExerciseDate}]不一致");
}
td.FinalPrice = reader.GetDouble("了结标的价格", false);
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider((DateTime)td.UnWindDate);
if (td.FinalPrice == null)
{
td.FinalPrice = eodpriceProvider.GetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice);//平仓当天标的价格;
}
var toEndAmount = reader.GetDouble("了结总额", false);
UnwindSwapTradeCashHandle(td, action, toEndAmount);
}
#endregion
//记录审核日志
DbContext.TradeAuditLog.Add(new TradeAuditLog
{
TradeId = td.id,
Changes = null,
DataType = "00",
OptId = UserId,
OptName = UserName,
OptDate = OptDate,
OptType = "导入交易",
AuditFlag = TradeAuditFlag.operation
});
DbContext.SaveChanges();
return td;
}
private void UnwindSwapTradeCashHandle(trade td, string action, double? toEndAmount)
{
var client = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
//增加现金交割交易记录
var tc = new trade_cash();
DbContext.trade_cash.Add(tc);
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = OptDate;
tc.ExceciseType = "现金";
tc.TradeType = td.BuySell;
tc.CallPut = td.CallPut;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.IsLastAction = true;
tc.TradeId = td.id;
tc.FinalPrice = td.FinalPrice;
tc.UnwindType = "全部平仓";
tc.UnwindNotional = td.Notional;
tc.UnwindTradeAmount = td.TradeAmount;
tc.UnwindPercentRate = 1;
tc.NotionalPercentRate = tc.UnwindPercentRate;
var Amount = toEndAmount ?? 0;
if (td.trade_swap.IsPayFloatingProfit)
{
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
td.TradeStatus = td.UnWindDate.Value == td.ExerciseDate ? "已到期" : "已平仓";
td.StockEqvNotional = 0;
td.Notional = 0;
td.TradeAmount = 0;
td.UnWindNotional = tc.UnwindNotional;
tc.Amount = Amount;
tc.QuoteAmount = Amount / currencyRate;
tc.CurrencyRate = currencyRate;
tc.Action = action == "平仓" ? ClientCashInCashOut.系统操作_平仓费 : ClientCashInCashOut.系统操作_互换;
tc.IsLastAction = true;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = td.UnWindDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
DbContext.SaveChanges();
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
trade_cash_swap.PayInitialAmount = -Amount;
trade_cash_swap.PayAmount = -Amount;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.GetExtraAmount = 0;
trade_cash_swap.GetCostFee = 0;
trade_cash_swap.GetAmount = 0;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = Amount,
QuoteAmount = Amount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
else
{
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
tc.Amount = Amount;
tc.QuoteAmount = Amount / currencyRate;
tc.CurrencyRate = currencyRate;
tc.Action = action == "平仓" ? ClientCashInCashOut.系统操作_平仓费 : ClientCashInCashOut.系统操作_互换;
tc.IsLastAction = true;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = td.UnWindDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
DbContext.SaveChanges();
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : "已平仓";
td.StockEqvNotional = 0;
td.Notional = 0;
td.TradeAmount = 0;
td.UnWindNotional = tc.UnwindNotional;
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.GetStartPrice = trade_swap.GetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.GetFinalPrice = tc.FinalPrice;
trade_cash_swap.GetInitialAmount = Amount;
trade_cash_swap.GetAmount = Amount;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.PayExtraAmount = 0;
trade_cash_swap.PayCostFee = 0;
trade_cash_swap.PayAmount = 0;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = Amount,
QuoteAmount = Amount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
DbContext.SaveChanges();
}
/// <summary>
/// 导入了结历史数据交易
/// </summary>
/// <param name="streamIn"></param>
/// <param name="totalNum">当前文件中的目标期权总条数</param>
/// <param name="successNum">成功入库的数量</param>
public void ImportToEndSwapTradeHistroyDataFromExcel(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
try
{
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowReader(table, 0);
rowIndex = 1;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
{
using (var trans = BeginTransaction())
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
reader.SetDataRow(row);
HandleToEndSwapTradeHistroyData(reader);
successNum++;
trans.Commit();
}
}
}
catch (ServiceException se)
{
if (se.Tag != null)
{
throw;
}
throw new ServiceException($"已成功导入{successNum}条;\n第{rowIndex}行,{se.Message}");
}
catch (Exception ex)
{
LogFactory.GetLogger("导入收益互换了结").Error(ex);
throw new ServiceException($"已成功导入{successNum}条,\n第{rowIndex}行,发生错误:{ex.Message}", ex);
}
}
private trade HandleToEndSwapTradeHistroyData(DataRowReader reader)
{
var tradeNumnr = reader.GetString("交易编号", false);
var td = new trade();
var tdTable = DbContext.trade.FirstOrDefault(a => a.TradeNumber == tradeNumnr);
if (tdTable == null)
{
throw new ServiceException($"此交易编号[{td.TradeNumber}]不存在");
}
if (tdTable.TradeStatus != ConsTrade.确认成交)
{
throw new ServiceException("只有交易状态为‘确认成交’,才能进行批量了结导入");
}
td = tdTable;
td.trade_cash = new trade_cash();
td.trade_cash.UnwindPercentRate = reader.GetPercent("了结比例", false) ?? 0;
td.trade_cash.UnwindStockEqvNotional = reader.GetDouble("了结名义本金", false) ?? 0;
if (td.trade_cash.UnwindStockEqvNotional == 0 && td.trade_cash.UnwindPercentRate == 0)
{
throw new ServiceException($"交易编号[{td.TradeNumber}]中,了结名义本金与了结比例,必须填写一个值");
}
td.UnWindDate = reader.GetDate("了结日期", true);
var variety = DataCacheProvider.GetVariety(td.UnderlyingCode);
if (variety == null)
{
throw new ServiceException($"该标的[{td.UnderlyingCode}]对应的品种在系统中不存在");
}
else
{
var market = DataCacheProvider.GetMarketDataSource().AsQueryable().FirstOrDefault(x => x.MarketName == variety.TradingMarket);
if (QdpCalendarHelper.IsHoliday((DateTime)td.UnWindDate, string.IsNullOrWhiteSpace(market?.CalendarName) ? "chn" : market?.CalendarName))
{
throw new ServiceException("了结日期:" + td.UnWindDate + ",不能为节假日");
}
}
if (td.TradeDate > td.UnWindDate)
{
throw new ServiceException("了结日期必须要大于或等于成交日期");
}
if (td.UnWindDate > td.ExerciseDate)
{
throw new ServiceException("了结日期必须要小于或等于到期日期");
}
if (td.UnWindDate > valuedateBLL.ValueDate)
{
throw new ServiceException("了结日期必须要小于或等于系统日期");
}
td.FinalPrice = reader.GetDouble("了结标的价格", false);
var toEndAmount = reader.GetDouble("了结总额", false);
UnwindSwapTradeCashHandle(td, toEndAmount ?? 0);
return td;
}
/// <summary>
/// 了结导入数据处理
/// </summary>
/// <param name="td"></param>
/// <param name="annualFee"></param>
/// <param name="costFee"></param>
private void UnwindSwapTradeCashHandle(trade td, double Amount)
{
var client = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
if (td.FinalPrice == null)
{
var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider((DateTime)td.UnWindDate);
td.FinalPrice = eodpriceProvider.GetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice);//平仓当天标的价格;
}
td.trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == td.id);
var unwindType = "部分平仓";
//获取平仓比例
if (td.trade_cash.UnwindPercentRate == 0 || (td.trade_cash.UnwindStockEqvNotional != 0 && td.trade_cash.UnwindPercentRate != 0))
{
if (td.StockEqvNotional <= td.trade_cash.UnwindStockEqvNotional + 1e-10)
{
td.trade_cash.UnwindStockEqvNotional = td.StockEqvNotional;
unwindType = "全部平仓";
}
td.trade_cash.UnwindPercentRate = td.trade_cash.UnwindStockEqvNotional / td.OriginalStockEqvNotional;
}
else if ((td.StockEqvNotional / td.OriginalStockEqvNotional) <= td.trade_cash.UnwindPercentRate + 1e-10)
{
td.trade_cash.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
td.trade_cash.UnwindStockEqvNotional = td.StockEqvNotional;
unwindType = "全部平仓";
}
if (td.trade_cash.UnwindStockEqvNotional == 0)
{
if ((td.StockEqvNotional / td.OriginalStockEqvNotional) <= td.trade_cash.UnwindPercentRate + 1e-10)
{
td.trade_cash.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
unwindType = "全部平仓";
}
td.trade_cash.UnwindStockEqvNotional = (double)(td.OriginalStockEqvNotional * td.trade_cash.UnwindPercentRate);
}
else if (td.StockEqvNotional <= td.trade_cash.UnwindStockEqvNotional + 1e-10)
{
td.trade_cash.UnwindStockEqvNotional = td.StockEqvNotional;
td.trade_cash.UnwindPercentRate = td.StockEqvNotional / td.OriginalStockEqvNotional;
unwindType = "全部平仓";
}
//增加现金交割交易记录
var tc = new trade_cash();
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = OptDate;
tc.ExceciseType = "现金";
tc.TradeType = td.BuySell;
tc.CallPut = td.CallPut;
tc.IsLastAction = true;
tc.TradeId = td.id;
tc.FinalPrice = td.FinalPrice;
tc.Notional = td.Notional;
tc.TradeAmount = td.TradeAmount;
tc.UnwindType = unwindType;
tc.UnwindNotional = td.trade_cash.UnwindPercentRate * td.OriginalNotional;
tc.UnwindTradeAmount = tc.UnwindNotional / um.CountRatio;
tc.UnwindPercentRate = td.trade_cash.UnwindPercentRate;
tc.NotionalPercentRate = tc.UnwindPercentRate;
if (td.trade_swap.IsPayFloatingProfit)
{
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
tc.CurrencyRate = currencyRate;
tc.Action = ClientCashInCashOut.系统操作_平仓费;
tc.IsLastAction = td.Notional <= 0 ? true : false;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
td.StockEqvNotional -= (double)(td.OriginalStockEqvNotional * tc.UnwindPercentRate);
td.Notional -= (double)(td.OriginalNotional * tc.UnwindPercentRate);
td.TradeAmount = td.Notional / um.CountRatio;
td.UnWindNotional = tc.UnwindNotional;
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : (tc.UnwindType == "全部平仓" ? "已平仓" : td.TradeStatus);
td.HasPartialUnWind = tc.UnwindType == "部分平仓" ? 1 : 0;
DbContext.trade_cash.Add(tc);
DbContext.SaveChanges();
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice;
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
trade_cash_swap.PayInitialAmount = -Amount;
trade_cash_swap.PayAmount = -Amount;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.GetExtraAmount = 0;
trade_cash_swap.GetCostFee = 0;
trade_cash_swap.GetAmount = 0;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
tc.Amount = (trade_cash_swap.GetAmount ?? 0) - (trade_cash_swap.PayAmount ?? 0);
tc.QuoteAmount = tc.Amount;
DbContext.trade_cash_swap.Add(trade_cash_swap);
DbContext.SaveChanges();
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = Amount,
QuoteAmount = Amount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
else
{
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.UnWindDate.Value, seekPreday: true, currencyRateType: Amount < 0 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
tc.CurrencyRate = currencyRate;
tc.Action = ClientCashInCashOut.系统操作_平仓费;
tc.IsLastAction = td.Notional <= 0 ? true : false;
tc.Status = TradeCashStatusEnum.已执行;
tc.ValueDate = td.UnWindDate.Value;
tc.ValidState = "Valid";
tc.ExerciseWay = TradeCashExerciseWayEnum.提前终止行权;
td.StockEqvNotional -= (double)(td.OriginalStockEqvNotional * tc.UnwindPercentRate);
td.Notional -= (double)(td.OriginalNotional * tc.UnwindPercentRate);
td.TradeAmount = td.Notional / um.CountRatio;
td.UnWindNotional = tc.UnwindNotional;
td.TradeStatus = tc.ValueDate == td.ExerciseDate ? "已到期" : (tc.UnwindType == "全部平仓" ? "已平仓" : td.TradeStatus);
td.HasPartialUnWind = tc.UnwindType == "部分平仓" ? 1 : 0;
DbContext.trade_cash.Add(tc);
DbContext.SaveChanges();
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId);
var trade_cash_swap = new trade_cash_swap();
trade_cash_swap.StartDate = td.StartDate.Value;
trade_cash_swap.GetStartPrice = trade_swap.GetFinalPrice ?? trade_swap.GetSpotPrice;
trade_cash_swap.GetFinalPrice = tc.FinalPrice;
trade_cash_swap.GetInitialAmount = Amount;
trade_cash_swap.GetAmount = Amount;
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.GetSwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.PayExtraAmount = 0;
trade_cash_swap.PayCostFee = 0;
trade_cash_swap.PayAmount = 0;
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(td.trade_swap.PaySwapTimeAndRate, td.UnWindDate.Value);
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
tc.Amount = (trade_cash_swap.GetAmount ?? 0) - (trade_cash_swap.PayAmount ?? 0);
tc.QuoteAmount = tc.Amount;
DbContext.trade_cash_swap.Add(trade_cash_swap);
DbContext.SaveChanges();
var tcdGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.利息.ToString()
};
DbContext.trade_cash_detail.Add(tcdGet);
var tcdCostFeeGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
var tcdCostTradePriceGet = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = 0,
QuoteAmount = 0,
ValueDate = tc.ValueDate,
IsForGet = true,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
};
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
var tcdPay = new trade_cash_detail
{
TradeId = tc.TradeId,
TradeCashId = tc.id,
Action = tc.Action,
Amount = Amount,
QuoteAmount = Amount,
ValueDate = tc.ValueDate,
IsForGet = false,
OptId = tc.OptId,
OptName = tc.OptName,
OptDate = DateTime.Now,
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
};
DbContext.trade_cash_detail.Add(tcdPay);
}
//增加出入金记录
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
var auditLog = new TradeAuditLog
{
TradeId = tc.TradeId,
Changes = null,
DataType = "00",
OptType = "批量了结-平仓",
OptId = UserId,
OptName = UserName,
OptDate = OptDate,
AuditFlag = TradeAuditFlag.operation
};
//记录审核日志
DbContext.TradeAuditLog.Add(auditLog);
DbContext.SaveChanges();
}
#endregion
#region 山西互换交易导入
private void ImportFromExcelSX(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowReader(table, 0);
rowIndex = 1;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
{
rowIndex++;
reader.SetDataRow(row);
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
var importSwap = MapSwap(reader, out var amount, out var getAmount, out var payAmount);
var saveChecker = new OtcOptionSaveChecker(this).CheckBasic(importSwap);
//簿记、交易员、交易对手
saveChecker.CheckAssetBook(importSwap).CheckTrader(importSwap);
if (importSwap != null)
{
var saveTrade = new TradeSaveService(OptUser).SaveTrade(importSwap, TradeSourceEnum.导入交易);
var trade = DbContext.trade.Find(importSwap.id);
trade.trade_swap = saveTrade.trade_swap;
trade.TradeOldStatus = trade.TradeStatus;
trade.TradeStatus = ConsTrade.确认成交;
new ClientCashInCashOutService(this).SaveClientCashInCashOut(trade);
if (trade.UnWindDate == trade.SettlementDate)
{
trade.TradeStatus = ConsTrade.已到期;
}
else
{
trade.TradeStatus = ConsTrade.已平仓;
}
var tc = new trade_cash();
DbContext.trade_cash.Add(tc);
tc.StartDate = trade.StartDate.Value;
tc.ValidState = "Valid";
tc.OptId = UserId;
tc.OptName = UserName;
tc.OptDate = OptDate;
tc.ExceciseType = "现金";
tc.TradeType = trade.BuySell;
tc.CallPut = trade.CallPut;
tc.Strike = trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike;
tc.Notional = trade.Notional;
tc.TradeAmount = trade.Amount;
tc.IsLastAction = true;
tc.Amount = amount;
//1.远期存入平仓时算出的预付金占用成本
//2.部分行权时候的额外金额
tc.ExtraAmount = 0;
tc.UnwindPrice = trade.FinalPrice;
tc.TradeId = trade.id;
tc.FinalPrice = trade.FinalPrice;
tc.SpotPrice = trade.TradePrice;
tc.HappenedDate = trade.UnWindDate;
tc.UnwindType = "全部平仓";
tc.UnwindPercentRate = 1;
tc.UnwindNotional = trade.Notional;
tc.UnwindTradeAmount = trade.TradeAmount;
tc.Action = ClientCashInCashOut.系统操作_平仓费;
tc.Status = DBModels.Enums.TradeCashStatusEnum.已执行;
tc.ValueDate = trade.UnWindDate.Value;
DbContext.SaveChanges();
var ee = new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(trade, tc, tc.ValueDate);
var swapTrade = trade.trade_swap;
var trade_cash_swap = new trade_cash_swap()
{
GetAmount = getAmount,
PayAmount = payAmount
};
trade_cash_swap.StartDate = tc.StartDate;
if (swapTrade.IsGetFloatingProfit)
{
trade_cash_swap.GetStartPrice = swapTrade.GetSpotPrice ?? 0;
trade_cash_swap.GetFinalPrice = swapTrade.GetFinalPrice ?? 0;
}
if (swapTrade.IsPayFloatingProfit)
{
trade_cash_swap.PayStartPrice = swapTrade.PaySpotPrice ?? 0;
trade_cash_swap.PayFinalPrice = swapTrade.PayFinalPrice ?? 0;
}
trade_cash_swap.TradeId = tc.TradeId;
trade_cash_swap.TradeCashId = tc.id;
trade_cash_swap.OptId = tc.OptId;
trade_cash_swap.OptName = tc.OptName;
trade_cash_swap.OptDate = DateTime.Now;
DbContext.trade_cash_swap.Add(trade_cash_swap);
//终止 trade_cash
DbContext.SaveChanges();
successNum++;
}
//结算 trade cash
}
}
private trade MapSwap(DataRowReader reader, out double winLoss, out double getAmount, out double payAmount)
{
var td = new trade();
//基本要素
td.TradeNumber = reader.GetString("交易确认书编号(双方约定)", false);
td.AssetBookName = reader.GetString("簿记账户", true);
td.TraderName = reader.GetString("交易员", true);
td.TradeType = "收益互换";
td.ClientName = reader.GetString("交易对手方", true);
if (string.IsNullOrWhiteSpace(td.ClientName))
{
throw new ServiceException("交易对手方名称 必须填写");
}
//交易日期
td.TradeDate = reader.GetDate("起始日", true);
td.ExerciseDate = reader.GetDate("到期日", true);
td.StartDate = td.TradeDate;
//结算日期
td.SettlementDate = td.ExerciseDate;
td.StockEqvNotional = reader.GetDouble("名义本金(人民币)", true) ?? 0;
td.MarginTemplateName = null;
td.UnWindDate = reader.GetDate("提前终止日/终止日", true);
td.Comments = reader.GetString("备注", false);
//td.UnderlyingName = reader.GetString("标的名称", true);
td.UnderlyingCode = reader.GetString("标的代码", true);
var clientQuery = DbContextFactory.GetClientDbContext(OptUser).client.AsQueryable();
if (!string.IsNullOrWhiteSpace(td.ClientName))
{
clientQuery = clientQuery.Where(c => c.Name == td.ClientName);
}
var client = clientQuery.Select(n => new { n.id, n.DerivativesInvestmentVarieties }).FirstOrDefault();
if (client == null)
{
throw new ServiceException($"交易对手方不存在,ClientName:{td.ClientName}");
}
else
{
if (!client.DerivativesInvestmentVarieties.Contains((int)DerivativesInvestmentVarietiesEnum.场外互换 + ""))
{
throw new ServiceException($"客户:{td.ClientName}未设置交易种类“场外互换”,无法生成互换交易!");
}
}
td.ClientId = client.id;
var um = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().FirstOrDefault(o => o.UnderlyingCode == td.UnderlyingCode);
if (um == null)
{
throw new ServiceException($"{td.UnderlyingCode} 不存在,请先新建标的再导入");
}
else
{
td.UnderlyingId = um.id;
td.UnderlyingCode = um.UnderlyingCode;
td.UnderlyingName = um.UnderlyingName;
}
//币种
var underlyingModel = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
td.QuoteCurrency = DataCacheProvider.GetVarietyDataSource().GetData(underlyingModel.UnderlyingTypeId).QuoteCurrency;
var ExchangeRate = reader.GetDouble("汇率", false);
if (ExchangeRate != null)
{
if (td.QuoteCurrency != "CNY" && (!string.IsNullOrEmpty(td.QuoteCurrency)))
{
td.MetaDic.Add("ExchangeRate", ExchangeRate.ToString());
}
}
//td.MetaDic = new Dictionary<string, string>() {
// { "组合标的", "" },
// { "组合标的2", "" },
// { "交易场所", "" },
// { "清算机构", "" },
// { "主协议编号", "" },
// { "补充协议编号", "" }};
td.OpponentRole = "甲方";
double.TryParse(Regex.Match(reader.GetString("标的数量", false), @"^\d+((\,\d{3})+)?(\.\d+)?").Value, out var notional);
double.TryParse(Regex.Match(reader.GetString("标的初始价格", false), @"^\d+((\,\d{3})+)?(\.\d+)?").Value, out var spotPrice);
double.TryParse(Regex.Match(reader.GetString("标的提前终止日/终止日价格", false), @"^\d+((\,\d{3})+)?(\.\d+)?").Value, out var finalPrice);
td.Notional = notional;
td.TradeAmount = notional;
td.OriginalNotional = notional;
td.SpotPrice = spotPrice;
td.FinalPrice = finalPrice;
var swapTrade = new trade_swap();
swapTrade.RateCalcMode = GetRateCalcMode(reader.GetString("计息方式", true));
swapTrade.AnnualDays = reader.GetInt("年化天数", true);
swapTrade.AnnualVarIncome = reader.GetString("浮动收益年化", true) == "是";
swapTrade.GetSwapRate = reader.GetPercent("我方收取互换利率(年化)", false) ?? 0;
swapTrade.PaySwapRate = reader.GetPercent("我方支付互换利率(年化)", false) ?? 0;
if (swapTrade.GetSwapRate >= 0)
{
swapTrade.GetSwapTimeAndRate = td.ExerciseDate + ";" + swapTrade.GetSwapRate;
}
if (swapTrade.PaySwapRate >= 0)
{
swapTrade.PaySwapTimeAndRate = td.ExerciseDate + ";" + swapTrade.PaySwapRate;
}
swapTrade.GetLongShort = reader.GetString("我方收取浮动收益", false);
swapTrade.PayLongShort = reader.GetString("我方支付浮动收益", false);
if (!string.IsNullOrWhiteSpace(swapTrade.GetLongShort))
{
swapTrade.GetUnderlyingCode = td.UnderlyingCode;
swapTrade.GetUnderlyingId = td.UnderlyingId;
swapTrade.IsGetFloatingProfit = true;
swapTrade.GetNotional = notional;
swapTrade.GetTradeAmount = notional;
swapTrade.GetSpotPrice = spotPrice;
swapTrade.GetFinalPrice = finalPrice;
}
else
{
swapTrade.IsGetFloatingProfit = false;
}
if (!string.IsNullOrWhiteSpace(swapTrade.PayLongShort))
{
swapTrade.PayUnderlyingCode = td.UnderlyingCode;
swapTrade.PayUnderlyingId = td.UnderlyingId;
swapTrade.IsPayFloatingProfit = true;
swapTrade.PayNotional = notional;
swapTrade.PayTradeAmount = notional;
swapTrade.PaySpotPrice = spotPrice;
swapTrade.PayFinalPrice = finalPrice;
}
else
{
swapTrade.IsPayFloatingProfit = false;
}
winLoss = reader.GetDouble("我方损益", true) ?? 0;
getAmount = reader.GetDouble("我方收取现金流", false) ?? 0;
payAmount = reader.GetDouble("我方支付现金流", false) ?? 0;
//swapTrade. = winLoss >= 0 :
/*
data["UnderlyingId"] = data["trade_swap.PayUnderlyingId"];
data["UnderlyingCode"] = data["trade_swap.PayUnderlyingCode"];
*/
td.trade_swap = swapTrade;
return td;
}
#endregion
public void UploadClientVarietyConfig(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowReader(table, 0);
rowIndex = 1;
totalNum = table.Rows.Count - rowIndex;
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
{
rowIndex++;
reader.SetDataRow(row);
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
totalNum--;
continue;
}
var config = MapClientVarietyConfig(reader);
if (config != null)
{
successNum++;
}
}
}
private client_variety_config MapClientVarietyConfig(DataRowReader reader)
{
var clientNumber = reader.GetString("客户编号", true);
var varietyCode = reader.GetString("品种代码", true);
var client = ClientModule.ClientDataQueryService.GetClientByNumber(clientNumber);
if (client == null)
{
throw new ServiceException($"该客户[{clientNumber}]在系统中不存在");
}
var variety = DbContext.variety.Where(o => o.VarietyCode == varietyCode || o.VarietyName == varietyCode).FirstOrDefault();
if (variety == null)
{
throw new ServiceException($"该品种[{varietyCode}]在系统中不存在");
}
var config = new client_variety_config()
{
ValueDate = reader.GetDate("生效日期", true).Value,
ClientId = client.id,
VarietyId = variety.id,
SingleFee = reader.GetDouble("按手数收费", false) ?? 0,
UnAnnualRate = reader.GetPercent("按名义本金收费", false) ?? 0,
AnnualRate = reader.GetPercent("年化利率", false) ?? 0,
AnnualDays = reader.GetInt("年化天数", false) ?? 365,
Multiple = reader.GetDouble("倍数", false) ?? 0,
OptId = UserId,
OptName = UserName,
OptDate = DateTime.Now
};
if (DbContext.client_variety_config.Any(x => x.ClientId == config.ClientId && x.VarietyId == config.VarietyId && x.ValueDate == config.ValueDate))
{
throw new Exception($"同一客户[{clientNumber}]同一品种[{varietyCode}]不支持在同一天[{config.ValueDate.ToString("yyyy-MM-dd")}]有多条配置记录");
}
if (config.SingleFee > 0 && config.UnAnnualRate > 0)
{
throw new Exception($"按手数收费和按名义本金收费不能同时设置");
}
var types = new List<int>();
if (config.SingleFee != 0)
{
types.Add(1);
}
if (config.AnnualRate != 0)
{
types.Add(2);
}
if (config.UnAnnualRate != 0)
{
types.Add(3);
}
config.FeeType = string.Join(",", types);
DbContext.client_variety_config.Add(config);
DbContext.SaveChanges();
return config;
}
#region---内部业务类----
class DataRowTopTypeReader
{
DataRow _row;
readonly Dictionary<string, int> _colMap;
public DataRowTopTypeReader(DataTable table)
{
var colCount = table.Columns.Count;
_colMap = new Dictionary<string, int>(colCount, StringComparer.OrdinalIgnoreCase);
var row1 = table.Rows[0];
var row2 = table.Rows[1];
var preCol1 = string.Empty;
for (var index = 0; index < colCount; index++)
{
var col1 = row1[index]?.ToString()?.Trim();
var col2 = row2[index]?.ToString();
if (string.IsNullOrWhiteSpace(col2))
{
continue;
}
if (!string.IsNullOrWhiteSpace(col1))
{
preCol1 = col1;
}
col2 = col2.Replace("%", "").Trim();
_colMap[preCol1 + col2] = index;
}
}
public string TopType { get; private set; }
/// <summary>
/// 设置datarow
/// </summary>
public void SetDataRow(DataRow row)
{
_row = row;
TopType = "基本要素";
}
/// <summary>
/// 设置顶部类型
/// </summary>
public void SetTopType(string type)
{
TopType = type;
}
public string GetString(string fieldName, bool required = false)
{
var str = _colMap.TryGetValue(TopType + fieldName, out var colIndex) ? _row[colIndex]?.ToString()?.Trim() : null;
if (required && string.IsNullOrWhiteSpace(str))
{
throw new ServiceException($"[{TopType}]{fieldName} 必须填写");
}
return str;
}
public int? GetInt(string fieldName, bool required)
{
var str = GetString(fieldName, required);
if (!required && string.IsNullOrEmpty(str))
{
return null;
}
return int.TryParse(str, out var num) ? num : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
public double? GetDoubleOrPercent(string fieldName, bool required, bool percent)
{
var str = GetString(fieldName, required);
if (!required && string.IsNullOrWhiteSpace(str))
{
return null;
}
if (percent && (percent = str.EndsWith("%")))
{
str = str.TrimEnd('%');
}
return double.TryParse(str, out var num) ? (percent ? num / 100 : num) : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
public double? GetDouble(string fieldName, bool required = false)
{
var str = GetString(fieldName, required);
if (!required && string.IsNullOrWhiteSpace(str))
{
return null;
}
return double.TryParse(str, out var num) ? num : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
//为了兼容模板修改导致的字段名称改变问题
public double? GetDouble(string fieldName, string fieldName2, bool required = false)
{
var str = GetString(fieldName, false) ?? GetString(fieldName2, false);
if (string.IsNullOrWhiteSpace(str))
{
return required ? throw new ServiceException($"[{TopType}]{fieldName} 必须填写") : (double?)null;
}
return double.TryParse(str, out var num) ? num : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
public double? GetPercent(string fieldName, bool required = false)
{
var str = GetString(fieldName, required);
if (!required && string.IsNullOrWhiteSpace(str))
{
return null;
}
var percent = str.EndsWith("%");
if (percent)
{
str = str.TrimEnd('%');
}
return double.TryParse(str, out var num) ? (percent ? num / 100 : num) : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
/// <summary>
/// 获取日期(不包括时间)
/// </summary>
public DateTime? GetDate(string fieldName, bool required = false)
{
var str = GetString(fieldName, required);
if (!required && string.IsNullOrWhiteSpace(str))
{
return null;
}
if (str.Length == 8 && Regex.IsMatch(str, @"^\d+$"))
{
return DateTime.TryParseExact(str, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt2) ? dt2 : throw new ServiceException($"{fieldName} 填写错误:{str}");
}
return DateTime.TryParse(str, out var dt) ? dt.Date : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
/// <summary>
///
/// </summary>
public int? GetInt32(string fieldName, bool required = false)
{
var str = GetString(fieldName, required);
if (!required && string.IsNullOrWhiteSpace(str))
{
return null;
}
return int.TryParse(str, out var num) ? num : throw new ServiceException($"[{TopType}]{fieldName} 填写错误:{str}");
}
}
#endregion
}
}