1454 lines
68 KiB
C#
1454 lines
68 KiB
C#
using System.Data;
|
|
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
using YLErp.BLL;
|
|
using YLErp.Commons;
|
|
using YLErp.CustomizedBizLogic;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.DBModels.Enums;
|
|
using YLErp.DBModels.Helpers;
|
|
using YLErp.Enums;
|
|
using YLErp.Model.Enum;
|
|
using YLErp.Modules.CalculationModule;
|
|
using YLErp.Modules.EodModule;
|
|
using YLErp.Modules.TradeModule.OrderModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.SwapModule
|
|
{
|
|
/// <summary>
|
|
/// 场外期权交易导入服务
|
|
/// </summary>
|
|
public class SwapTradeFlowImportService : TradeServiceBase
|
|
{
|
|
public SwapTradeFlowImportService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
|
|
}
|
|
|
|
public SwapTradeFlowImportService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导入交易
|
|
/// </summary>
|
|
/// <param name="streamIn"></param>
|
|
/// <param name="totalNum">当前文件中的目标期权总条数</param>
|
|
/// <param name="successNum">成功入库的数量</param>
|
|
public void ImportSwapTradeFlowFromExcel(Stream streamIn, out int totalNum, out int successNum)
|
|
{
|
|
totalNum = 0;
|
|
successNum = 0;
|
|
|
|
var rowIndex = 0;
|
|
var tradeFlowIds = new List<int>();
|
|
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);
|
|
|
|
rowIndex = 1;
|
|
totalNum = table.Rows.Count - rowIndex;
|
|
|
|
using (var trans = BeginTransaction())
|
|
{
|
|
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
|
|
{
|
|
rowIndex++;
|
|
|
|
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
|
|
{
|
|
totalNum--;
|
|
continue;
|
|
}
|
|
|
|
reader.SetDataRow(row);
|
|
|
|
//映射导入数据到交易对象
|
|
var tradeFlow = MapSwapTradeFlow(reader);
|
|
tradeFlowIds.Add(tradeFlow.id);
|
|
|
|
HandleSwapTrade(tradeFlow);
|
|
tradeFlow.Status = "已完成";
|
|
DbContext.SaveChanges();
|
|
|
|
successNum++;
|
|
}
|
|
|
|
trans.Commit();
|
|
}
|
|
|
|
//generateSettleDocument(trade_Cashes);
|
|
//生成确认书
|
|
//new ConfirmationGenerateService(this).Generate(tradeIds, "PDF");
|
|
}
|
|
catch (ServiceException se)
|
|
{
|
|
if (se.Tag != null)
|
|
{
|
|
throw;
|
|
}
|
|
|
|
throw new ServiceException($"第{rowIndex}行,{se.Message}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger("导入互换交易").Error(ex);
|
|
throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导入交易
|
|
/// </summary>
|
|
/// <param name="streamIn"></param>
|
|
/// <param name="totalNum">当前文件中的目标期权总条数</param>
|
|
/// <param name="successNum">成功入库的数量</param>
|
|
public void ImportSwapTradeFlowGroupFromExcel(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);
|
|
|
|
rowIndex = 1;
|
|
totalNum = table.Rows.Count - rowIndex;
|
|
|
|
using (var trans = BeginTransaction())
|
|
{
|
|
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
|
|
{
|
|
rowIndex++;
|
|
|
|
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
|
|
{
|
|
totalNum--;
|
|
continue;
|
|
}
|
|
|
|
reader.SetDataRow(row);
|
|
|
|
//映射导入数据到交易对象
|
|
MapSwapTradeFlowGroup(reader);
|
|
|
|
successNum++;
|
|
}
|
|
|
|
trans.Commit();
|
|
}
|
|
}
|
|
catch (ServiceException se)
|
|
{
|
|
if (se.Tag != null)
|
|
{
|
|
throw;
|
|
}
|
|
|
|
throw new ServiceException($"第{rowIndex}行,{se.Message}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger("导入互换交易").Error(ex);
|
|
throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导入交易
|
|
/// </summary>
|
|
/// <param name="streamIn"></param>
|
|
/// <param name="totalNum">当前文件中的目标期权总条数</param>
|
|
/// <param name="successNum">成功入库的数量</param>
|
|
public void ImportTradeFlowHistoryFromExcel(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);
|
|
|
|
rowIndex = 1;
|
|
totalNum = table.Rows.Count - rowIndex;
|
|
|
|
using (var trans = BeginTransaction())
|
|
{
|
|
foreach (var row in table.Rows.Cast<DataRow>().Skip(1))
|
|
{
|
|
rowIndex++;
|
|
|
|
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
|
|
{
|
|
totalNum--;
|
|
continue;
|
|
}
|
|
|
|
reader.SetDataRow(row);
|
|
|
|
var clientName = reader.GetString("客户名称");
|
|
var client = ClientModule.ClientDataQueryService.GetClient(clientName);
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException($"客户{clientName}不存在");
|
|
}
|
|
|
|
var tradeFlowHistory = new trade_flow_history()
|
|
{
|
|
ClientId = client.id,
|
|
ContractId = reader.GetString("交易编码"),
|
|
FlagExpired = reader.GetString("是否到期"),
|
|
QuoteCurrency = reader.GetString("计价货币"),
|
|
SettleCurrency = reader.GetString("结算货币"),
|
|
TradeDate = reader.GetDate("交易日"),
|
|
ExpireDate = reader.GetDate("到期日"),
|
|
SettleDate = reader.GetDate("交割日(LME Prompt)"),
|
|
Direction = reader.GetString("客户买/卖"),
|
|
PremiumDate = reader.GetDate("权利金日"),
|
|
PremiumCNY = reader.GetDouble("期权费¥"),
|
|
TradeType = reader.GetString("衍生品类型"),
|
|
UnderlyingCode = reader.GetString("标的代码"),
|
|
InitialLots = reader.GetDouble("初始开仓手数"),
|
|
Lots = reader.GetDouble("剩余手数"),
|
|
Size = reader.GetDouble("合约乘数"),
|
|
InitialSpotPrice = reader.GetDouble("初始价格"),
|
|
InitialRate = reader.GetDouble("初始汇率"),
|
|
SpotPrice = reader.GetDouble("最新价格"),
|
|
Rate = reader.GetDouble("最新汇率"),
|
|
CommissionRate = reader.GetString("佣金费率"),
|
|
EstimateCommision = reader.GetDouble("预估佣金¥"),
|
|
AnnualRate = reader.GetPercent("年化手续费率"),//
|
|
EstimateAnnualFee = reader.GetDouble("预估年化手续费¥"),
|
|
FloatingWinLossQuote = reader.GetDouble("浮动收益(计价货币)"),
|
|
FloatingWinLoss = reader.GetDouble("浮动收益(结算货币)"),//
|
|
UnRealizedPnl = reader.GetDouble("未实现收益(结算货币)"),
|
|
RealizedPnl = reader.GetDouble("已实现收益(结算货币)"),
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = DateTime.Now
|
|
};
|
|
checkFlowHis(tradeFlowHistory);
|
|
DbContext.trade_flow_history.Add(tradeFlowHistory);
|
|
DbContext.SaveChanges();
|
|
|
|
successNum++;
|
|
}
|
|
|
|
trans.Commit();
|
|
}
|
|
}
|
|
catch (ServiceException se)
|
|
{
|
|
if (se.Tag != null)
|
|
{
|
|
throw;
|
|
}
|
|
|
|
throw new ServiceException($"第{rowIndex}行,{se.Message}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger("导入历史交易流水").Error(ex);
|
|
throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
public bool checkFlowHis(trade_flow_history req)
|
|
{
|
|
if (DbContext.trade_flow_history.Any(o => o.ContractId == req.ContractId))
|
|
{
|
|
throw new ServiceException($"历史交易已存在{req.ContractId}");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
public void HandleSwapTrade(trade_swap_flow tradeFlow)
|
|
{
|
|
var importTrade = MapSwapTradeHandle(tradeFlow);
|
|
var tradeSwapPositionsOtherSide = (from td in DbContext.trade
|
|
join ts in DbContext.trade_swap
|
|
on td.id equals ts.TradeId
|
|
where td.ClientId == importTrade.ClientId && td.UnderlyingId == importTrade.UnderlyingId && td.TradeStatus == ConsTrade.确认成交 && td.ParentTradeId == 0 && td.ValidState != "InValid" && ts.SwapType != "多空组合" && ts.PayLongShort != importTrade.trade_swap.PayLongShort && td.TradeDate <= importTrade.TradeDate
|
|
select new { td, ts }).ToList().OrderBy(x => x.td.TradeDate);
|
|
|
|
if (tradeSwapPositionsOtherSide.Any())
|
|
{
|
|
//按时间顺序一次平仓
|
|
foreach (var item in tradeSwapPositionsOtherSide)
|
|
{
|
|
if (importTrade.Notional > 0)
|
|
{
|
|
item.td.trade_swap = item.ts;
|
|
UnwindSwapTrade(item.td, importTrade);
|
|
}
|
|
}
|
|
|
|
//如果存续反向交易均被平仓,新增交易还有剩余部分,需要重新开仓
|
|
if (importTrade.Notional > 0)
|
|
{
|
|
InnerSaveSwapTrade(importTrade);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//无反向存续交易,则直接开仓
|
|
InnerSaveSwapTrade(importTrade);
|
|
}
|
|
}
|
|
|
|
private void InnerSaveSwapTrade(trade importTrade)
|
|
{
|
|
var varitey = DataCacheProvider.GetVariety(importTrade.UnderlyingCode);
|
|
|
|
double marginRate = 0d;
|
|
|
|
if (PS.Config.Company == Configuration.CompanyEnum.中金)
|
|
{
|
|
var credit = DbContext.credit.FirstOrDefault(x => x.CreditStartDate <= importTrade.TradeDate && x.CreditDeadLine >= importTrade.TradeDate && x.ClientId == importTrade.ClientId && x.ProcessStatus == "已审批");
|
|
var hasCredit = credit != null && credit.PFECredit > 0;
|
|
var clientVarietyMarginRate = DbContext.client_variety_marginrate.Where(x => x.ClientId == importTrade.ClientId && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
|
if (clientVarietyMarginRate == null)
|
|
{
|
|
clientVarietyMarginRate = DbContext.client_variety_marginrate.Where(x => x.ClientId == 0 && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
|
}
|
|
if (clientVarietyMarginRate == null)
|
|
{
|
|
throw new ServiceException($"该客户[{importTrade.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{importTrade.TradeDate}]相关的预付金率配置");
|
|
}
|
|
|
|
marginRate = hasCredit ? clientVarietyMarginRate.LowMarginRate : clientVarietyMarginRate.HighMarginRate;
|
|
}
|
|
else
|
|
{
|
|
var clientMarginRate = DbContext.client_marginrate.Where(x => x.ClientId == importTrade.ClientId && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
|
if (clientMarginRate == null)
|
|
{
|
|
clientMarginRate = DbContext.client_marginrate.Where(x => x.ClientId == 0 && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
|
}
|
|
if (clientMarginRate == null)
|
|
{
|
|
throw new ServiceException($"该客户[{importTrade.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{importTrade.TradeDate}]相关的预付金率配置");
|
|
}
|
|
|
|
marginRate = clientMarginRate.InitMarginRate;
|
|
}
|
|
|
|
|
|
importTrade.TradeStatus = ConsTrade.确认成交;
|
|
importTrade.TradeNumber = BizLogicSingleton.Instance.GenerateTradeNumberBeforeConfirm(importTrade, DbContext);
|
|
|
|
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(importTrade.QuoteCurrency, importTrade.SettlementCurrency, importTrade.TradeDate.Value, seekPreday: importTrade.TradeDate.Value == valuedateBLL.ValueDate);
|
|
var tradePriceQuote = 0.0;
|
|
if (importTrade.trade_swap.IsTradePriceWhenOpen)
|
|
{
|
|
tradePriceQuote = ((importTrade.trade_swap.GetSingleFee ?? 0) * (importTrade.Lots ?? 0) + importTrade.StockEqvNotional * (importTrade.trade_swap.GetUnAnnualRate ?? 0)).FormatValue(2);
|
|
importTrade.TradePrice = (tradePriceQuote * currencyRate).FormatValue(2);
|
|
}
|
|
|
|
importTrade.InitialMargin = marginRate * importTrade.StockEqvNotional;
|
|
importTrade.OriginalNotional = importTrade.Notional;
|
|
importTrade.OriginalStockEqvNotional = importTrade.StockEqvNotional;
|
|
importTrade.StockEqvNotionalReal = importTrade.StockEqvNotionalReal;
|
|
importTrade.trade_swap.RateCalcMode = "01";
|
|
importTrade.IsUsePremiumRate = true;
|
|
importTrade.MarginTemplateName = "系统默认";
|
|
importTrade.MarginType = MarginTypeEnum.DEFAULT;
|
|
importTrade.IsTradePricePayType = true;
|
|
importTrade.TradeSource = TradeSourceEnum.导入交易.ToString();
|
|
importTrade.OptId = UserId;
|
|
importTrade.OptName = UserName;
|
|
importTrade.OptDate = DateTime.Now;
|
|
SetDBModelCreator(importTrade);
|
|
DbContext.trade.Add(importTrade);
|
|
DbContext.SaveChanges();
|
|
importTrade.trade_swap.GetTradePrice = (importTrade.trade_swap.GetSingleFee ?? 0) * (importTrade.Lots ?? 0) + (importTrade.trade_swap.GetUnAnnualRate ?? 0) * importTrade.StockEqvNotional;
|
|
importTrade.trade_swap.GetMarginRate = marginRate;
|
|
importTrade.trade_swap.TradeId = importTrade.id;
|
|
importTrade.trade_swap.PaySpotPrice = importTrade.SpotPrice;
|
|
importTrade.trade_swap.PayUnderlyingId = importTrade.UnderlyingId;
|
|
importTrade.trade_swap.PayUnderlyingCode = importTrade.UnderlyingCode;
|
|
importTrade.trade_swap.PayNotional = importTrade.Notional;
|
|
importTrade.trade_swap.PayTradeAmount = importTrade.TradeAmount;
|
|
importTrade.trade_swap.IsPayFloatingProfit = true;
|
|
importTrade.trade_swap.SwapType = "普通";
|
|
importTrade.trade_swap.OptId = UserId;
|
|
importTrade.trade_swap.OptName = UserName;
|
|
importTrade.trade_swap.OptDate = DateTime.Now;
|
|
DbContext.trade_swap.Add(importTrade.trade_swap);
|
|
|
|
SaveTradeMeta(importTrade);
|
|
|
|
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 = (importTrade.TradePrice ?? 0) * (importTrade.BuySell == "买入" ? -1 : 1);
|
|
tc.QuoteAmount = tradePriceQuote * (importTrade.BuySell == "买入" ? -1 : 1);
|
|
tc.CurrencyRate = currencyRate;
|
|
tc.ExceciseType = "现金";
|
|
tc.TradeId = importTrade.id;
|
|
tc.ValueDate = importTrade.TradeDate.Value;
|
|
tc.Notional = importTrade.Notional;
|
|
tc.TradeAmount = importTrade.TradeAmount;
|
|
tc.Status = TradeCashStatusEnum.已执行;
|
|
tc.TradeType = importTrade.BuySell;
|
|
DbContext.SaveChanges();
|
|
|
|
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(importTrade, 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 UnwindSwapTrade(trade tradePosition, trade tradeImport)
|
|
{
|
|
var unwindType = tradePosition.Notional > tradeImport.Notional ? "部分平仓" : "全部平仓";
|
|
|
|
if (tradePosition.trade_swap.SettlementPayType == 0)
|
|
{
|
|
UnwindSwapTradeCashHandle(tradePosition, tradeImport, unwindType);
|
|
}
|
|
else if (tradePosition.trade_swap.SettlementPayType == 1)
|
|
{
|
|
UnwindSwapTradeCashPreHandle(tradePosition, tradeImport, unwindType);
|
|
}
|
|
|
|
SaveTradeOperationHistory(tradePosition, "互换导入平仓");
|
|
|
|
//删除E/Bod数据
|
|
RemoveEodTradeAndFutureInfo(true, tradePosition.id, tradeImport.TradeDate.Value);
|
|
}
|
|
|
|
private void UnwindSwapTradeCashHandle(trade tradePosition, trade tradeImport, string unwindType)
|
|
{
|
|
var tradeCashs = DbContext.trade_cash.Where(x => x.TradeId == tradePosition.id && x.ValidState != "InValid");
|
|
var num = tradeCashs.Where(x => x.Action != ClientCashInCashOut.系统操作_期权费).Count() + 1;
|
|
var tradeCashList = tradeCashs.Where(y => y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tradeImport.TradeDate.Value);
|
|
var tradeCashIds = tradeCashList.Select(x => x.id);
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(tradePosition.ClientId);
|
|
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(tradePosition.QuoteCurrency, tradePosition.SettlementCurrency, tradeImport.TradeDate.Value, seekPreday: tradeImport.TradeDate.Value == valuedateBLL.ValueDate);
|
|
var currencyRateTradeDate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(tradePosition.QuoteCurrency, tradePosition.SettlementCurrency, tradePosition.TradeDate.Value, seekPreday: tradePosition.TradeDate.Value == valuedateBLL.ValueDate);
|
|
|
|
//增加现金交割交易记录
|
|
var tc = new trade_cash();
|
|
DbContext.trade_cash.Add(tc);
|
|
|
|
tc.OptId = UserId;
|
|
tc.OptName = UserName;
|
|
tc.OptDate = OptDate;
|
|
tc.ExceciseType = "现金";
|
|
tc.TradeType = tradePosition.BuySell;
|
|
tc.CallPut = tradePosition.CallPut;
|
|
tc.Notional = tradePosition.Notional;
|
|
tc.TradeAmount = tradePosition.TradeAmount;
|
|
tc.IsLastAction = unwindType == "全部平仓";
|
|
tc.TradeId = tradePosition.id;
|
|
tc.FinalPrice = tradeImport.SpotPrice;
|
|
tc.UnwindType = unwindType;
|
|
if (tc.UnwindType == "全部平仓")
|
|
{
|
|
tc.UnwindNotional = tradePosition.Notional;
|
|
tc.UnwindTradeAmount = tradePosition.TradeAmount;
|
|
tc.UnwindPercentRate = tradePosition.Notional / tradePosition.OriginalNotional;
|
|
}
|
|
else
|
|
{
|
|
tc.UnwindNotional = tradeImport.Notional;
|
|
tc.UnwindTradeAmount = tradeImport.TradeAmount;
|
|
tc.UnwindPercentRate = tradeImport.Notional / tradePosition.OriginalNotional;
|
|
}
|
|
tc.NotionalPercentRate = tc.UnwindPercentRate;
|
|
|
|
tradeBLL.SetFieldsByTradeType(tradePosition);
|
|
var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(tradePosition, tradePosition.trade_swap, tradePosition.trade_swap.PaySpotPrice ?? 0
|
|
, tradeImport.SpotPrice ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0), tradeImport.TradeDate.Value, null);
|
|
var initialAmountPay = (initialAmountPayQuote * currencyRate).FormatValue(2);
|
|
var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == tradePosition.id && tradeCashIds.Contains(x.TradeCashId)).ToArray();
|
|
//取最后一次手动收益;
|
|
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto);
|
|
var lastManualCash = lastManualCashSwap != null ? tradeCashList.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
|
|
DateTime endDate;
|
|
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(tradePosition, tradePosition.trade_swap, tradeImport.TradeDate.Value, null, lastManualCash, tradePosition.trade_swap.IsGetFloatingProfit, out endDate);
|
|
|
|
var extraAmountGetQuote = PayoffSwapCalcService.GetExtraAmountBySwapRate(tradePosition.ClientId, tradePosition.TradeDate, tradePosition.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, tradePosition.trade_swap.AnnualDays ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0));
|
|
var extraAmountGet = extraAmountGetQuote * (PS.Config.Company == Configuration.CompanyEnum.中金 && client.BoundSide == BoundSideEnum.南向 ? currencyRateTradeDate : currencyRate);
|
|
var costFeeGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradeImport, tc, true, false);
|
|
var costFeeGet = (costFeeGetQuote * currencyRate).FormatValue(2);
|
|
var costTradePriceGetQuote = 0.0;
|
|
var costTradePriceGet = 0.0;
|
|
if (!tradePosition.trade_swap.IsTradePriceWhenOpen)
|
|
{
|
|
costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradePosition, tc, true, true);
|
|
costTradePriceGet = (costTradePriceGetQuote * currencyRate).FormatValue(2);
|
|
}
|
|
tc.Amount = extraAmountGet + costFeeGet + costTradePriceGet - initialAmountPay;
|
|
tc.QuoteAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote;
|
|
tc.CurrencyRate = currencyRate;
|
|
tc.Action = ClientCashInCashOut.系统操作_平仓费;
|
|
tc.Status = TradeCashStatusEnum.已执行;
|
|
tc.ValueDate = tradeImport.TradeDate.Value;
|
|
tc.ValidState = "Valid";
|
|
tc.ExerciseWay = tradeImport.TradeDate == tradePosition.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
|
|
if (client.BoundSide == BoundSideEnum.北向)
|
|
{
|
|
tc.Number = tradePosition.TradeNumber + "_UW_" + num;
|
|
}
|
|
DbContext.SaveChanges();
|
|
|
|
if (unwindType == "全部平仓")
|
|
{
|
|
tradePosition.TradeStatus = "已平仓";
|
|
}
|
|
else
|
|
{
|
|
tradePosition.HasPartialUnWind = 1;
|
|
}
|
|
tradePosition.UnWindDate = tc.ValueDate;
|
|
tradePosition.StockEqvNotional -= (tradePosition.SpotPrice ?? 0) * (tc.UnwindNotional ?? 0);
|
|
tradePosition.Notional -= tc.UnwindNotional ?? 0;
|
|
tradePosition.TradeAmount -= tc.UnwindTradeAmount ?? 0;
|
|
tradePosition.UnWindNotional = tc.UnwindNotional;
|
|
//增加出入金记录
|
|
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(tradePosition, 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 = tradePosition.StartDate.Value;
|
|
trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice;
|
|
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
|
|
trade_cash_swap.PayInitialAmount = initialAmountPay;
|
|
trade_cash_swap.PayAmount = initialAmountPay;
|
|
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.PaySwapTimeAndRate, tradePosition.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(tradePosition.trade_swap.GetSwapTimeAndRate, tradePosition.UnWindDate.Value);
|
|
trade_cash_swap.TradeId = tc.TradeId;
|
|
trade_cash_swap.TradeCashId = tc.id;
|
|
trade_cash_swap.FlowId = tradeImport.trade_swap.FlowId;
|
|
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 = extraAmountGet,
|
|
QuoteAmount = extraAmountGetQuote,
|
|
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);
|
|
|
|
tradeImport.Notional -= tc.UnwindNotional ?? 0;
|
|
tradeImport.TradeAmount -= tc.UnwindTradeAmount ?? 0;
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeImport.UnderlyingCode);
|
|
tradeImport.Lots -= tc.UnwindNotional / underlying.ContractSize;
|
|
tradeImport.StockEqvNotional -= (tc.UnwindNotional ?? 0) * (tradeImport.SpotPrice ?? 0);
|
|
|
|
DbContext.SaveChanges();
|
|
}
|
|
|
|
private void UnwindSwapTradeCashPreHandle(trade tradePosition, trade tradeImport, string unwindType)
|
|
{
|
|
var tradeCashPres = DbContext.trade_cash_pre.Where(x => x.TradeId == tradePosition.id && x.ValidState != "InValid");
|
|
var tradeCashPreList= tradeCashPres.Where(y => y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tradeImport.TradeDate.Value);
|
|
var num = tradeCashPres.Where(x => x.Action != ClientCashInCashOut.系统操作_期权费).Count() + 1;
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(tradePosition.ClientId);
|
|
//增加Pre现金交割交易记录
|
|
var tcPre = new trade_cash_pre();
|
|
DbContext.trade_cash_pre.Add(tcPre);
|
|
|
|
tcPre.OptId = UserId;
|
|
tcPre.OptName = UserName;
|
|
tcPre.OptDate = OptDate;
|
|
tcPre.ExceciseType = "现金";
|
|
tcPre.TradeType = tradePosition.BuySell;
|
|
tcPre.CallPut = tradePosition.CallPut;
|
|
tcPre.Notional = tradePosition.Notional;
|
|
tcPre.TradeAmount = tradePosition.TradeAmount;
|
|
tcPre.IsLastAction = unwindType == "全部平仓";
|
|
tcPre.TradeId = tradePosition.id;
|
|
tcPre.FinalPrice = tradeImport.SpotPrice;
|
|
tcPre.UnwindType = unwindType;
|
|
if (tcPre.UnwindType == "全部平仓")
|
|
{
|
|
tcPre.UnwindNotional = tradePosition.Notional;
|
|
tcPre.UnwindTradeAmount = tradePosition.TradeAmount;
|
|
tcPre.UnwindPercentRate = tradePosition.Notional / tradePosition.OriginalNotional;
|
|
}
|
|
else
|
|
{
|
|
tcPre.UnwindNotional = tradeImport.Notional;
|
|
tcPre.UnwindTradeAmount = tradeImport.TradeAmount;
|
|
tcPre.UnwindPercentRate = tradeImport.Notional / tradePosition.OriginalNotional;
|
|
}
|
|
tcPre.NotionalPercentRate = tcPre.UnwindPercentRate;
|
|
|
|
tradeBLL.SetFieldsByTradeType(tradePosition);
|
|
var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(tradePosition, tradePosition.trade_swap, tradePosition.trade_swap.PaySpotPrice ?? 0
|
|
, tradeImport.SpotPrice ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tcPre.UnwindPercentRate ?? 0), tradeImport.TradeDate.Value, null);
|
|
var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == tradePosition.id).ToArray();
|
|
//取最后一次手动收益;
|
|
var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto);
|
|
var lastManualCash = lastManualCashSwap != null ? tradeCashPreList.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null;
|
|
DateTime endDate;
|
|
var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDatePre(tradePosition, tradePosition.trade_swap, tradeImport.TradeDate.Value, null, lastManualCash, tradePosition.trade_swap.IsGetFloatingProfit, out endDate);
|
|
|
|
var extraAmountGetQuote = PayoffSwapCalcService.GetExtraAmountBySwapRate(tradePosition.ClientId, tradePosition.TradeDate, tradePosition.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, tradePosition.trade_swap.AnnualDays ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tcPre.UnwindPercentRate ?? 0));
|
|
var tradeCash = new trade_cash() { UnwindNotional = tcPre.UnwindNotional, UnwindTradeAmount = tcPre.UnwindTradeAmount, UnwindPercentRate = tcPre.UnwindPercentRate, FinalPrice = tcPre.FinalPrice };
|
|
var costFeeGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradeImport, tradeCash, true, false);
|
|
var costTradePriceGetQuote = 0.0;
|
|
if (!tradePosition.trade_swap.IsTradePriceWhenOpen)
|
|
{
|
|
costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradePosition, tradeCash, true, true);
|
|
}
|
|
tcPre.Amount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote;
|
|
|
|
tcPre.Action = ClientCashInCashOut.系统操作_平仓费;
|
|
tcPre.Status = TradeCashStatusEnum.已执行;
|
|
tcPre.ValueDate = tradePosition.SettlementDate.Value;
|
|
tcPre.HappenedDate = tradeImport.TradeDate.Value;
|
|
tcPre.ValidState = "Valid";
|
|
tcPre.ExerciseWay = TradeCashExerciseWayEnum.到期行权;
|
|
tcPre.IsFinished = false;
|
|
if (client.BoundSide == BoundSideEnum.北向)
|
|
{
|
|
tcPre.Number = tradePosition.TradeNumber + "_UW_" + num;
|
|
}
|
|
DbContext.SaveChanges();
|
|
|
|
if (unwindType == "全部平仓")
|
|
{
|
|
tradePosition.TradeStatus = "已平仓";
|
|
}
|
|
else
|
|
{
|
|
tradePosition.HasPartialUnWind = 1;
|
|
}
|
|
tradePosition.UnWindDate = tcPre.HappenedDate;
|
|
tradePosition.StockEqvNotional -= (tradePosition.SpotPrice ?? 0) * (tcPre.UnwindNotional ?? 0);
|
|
tradePosition.Notional -= tcPre.UnwindNotional ?? 0;
|
|
tradePosition.TradeAmount -= tcPre.UnwindTradeAmount ?? 0;
|
|
tradePosition.UnWindNotional = tcPre.UnwindNotional;
|
|
|
|
var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tcPre.TradeId);
|
|
var trade_cash_swap = new trade_cash_swap();
|
|
trade_cash_swap.StartDate = tradePosition.StartDate.Value;
|
|
trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice;
|
|
trade_cash_swap.PayFinalPrice = tcPre.FinalPrice;
|
|
trade_cash_swap.PayInitialAmount = initialAmountPayQuote;
|
|
trade_cash_swap.PayAmount = initialAmountPayQuote;
|
|
trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.PaySwapTimeAndRate, tradePosition.UnWindDate.Value);
|
|
trade_cash_swap.GetExtraAmount = extraAmountGetQuote;
|
|
trade_cash_swap.GetCostFee = costFeeGetQuote + costTradePriceGetQuote;
|
|
trade_cash_swap.GetAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote;
|
|
trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.GetSwapTimeAndRate, tradePosition.UnWindDate.Value);
|
|
trade_cash_swap.TradeId = tcPre.TradeId;
|
|
trade_cash_swap.TradeCashPreId = tcPre.id;
|
|
trade_cash_swap.FlowId = tradeImport.trade_swap.FlowId;
|
|
trade_cash_swap.OptId = tcPre.OptId;
|
|
trade_cash_swap.OptName = tcPre.OptName;
|
|
trade_cash_swap.OptDate = DateTime.Now;
|
|
DbContext.trade_cash_swap.Add(trade_cash_swap);
|
|
|
|
var tcdGet = new trade_cash_detail
|
|
{
|
|
TradeId = tcPre.TradeId,
|
|
TradeCashPreId = tcPre.id,
|
|
Action = tcPre.Action,
|
|
QuoteAmount = extraAmountGetQuote,
|
|
ValueDate = tcPre.ValueDate,
|
|
IsForGet = true,
|
|
OptId = tcPre.OptId,
|
|
OptName = tcPre.OptName,
|
|
OptDate = DateTime.Now,
|
|
TradeCashType = TradeCashTypeEnum.利息.ToString()
|
|
};
|
|
DbContext.trade_cash_detail.Add(tcdGet);
|
|
|
|
var tcdCostFeeGet = new trade_cash_detail
|
|
{
|
|
TradeId = tcPre.TradeId,
|
|
TradeCashPreId = tcPre.id,
|
|
Action = tcPre.Action,
|
|
QuoteAmount = costFeeGetQuote,
|
|
ValueDate = tcPre.ValueDate,
|
|
IsForGet = true,
|
|
OptId = tcPre.OptId,
|
|
OptName = tcPre.OptName,
|
|
OptDate = DateTime.Now,
|
|
TradeCashType = TradeCashTypeEnum.了结手续费.ToString()
|
|
};
|
|
DbContext.trade_cash_detail.Add(tcdCostFeeGet);
|
|
|
|
var tcdCostTradePriceGet = new trade_cash_detail
|
|
{
|
|
TradeId = tcPre.TradeId,
|
|
TradeCashPreId = tcPre.id,
|
|
Action = tcPre.Action,
|
|
QuoteAmount = costTradePriceGetQuote,
|
|
ValueDate = tcPre.ValueDate,
|
|
IsForGet = true,
|
|
OptId = tcPre.OptId,
|
|
OptName = tcPre.OptName,
|
|
OptDate = DateTime.Now,
|
|
TradeCashType = TradeCashTypeEnum.开仓手续费.ToString()
|
|
};
|
|
DbContext.trade_cash_detail.Add(tcdCostTradePriceGet);
|
|
|
|
var tcdPay = new trade_cash_detail
|
|
{
|
|
TradeId = tcPre.TradeId,
|
|
TradeCashPreId = tcPre.id,
|
|
Action = tcPre.Action,
|
|
QuoteAmount = -initialAmountPayQuote,
|
|
ValueDate = tcPre.ValueDate,
|
|
IsForGet = false,
|
|
OptId = tcPre.OptId,
|
|
OptName = tcPre.OptName,
|
|
OptDate = DateTime.Now,
|
|
TradeCashType = TradeCashTypeEnum.浮动收益.ToString()
|
|
};
|
|
DbContext.trade_cash_detail.Add(tcdPay);
|
|
DbContext.SaveChanges();
|
|
|
|
tradeImport.Notional -= tcPre.UnwindNotional ?? 0;
|
|
tradeImport.TradeAmount -= tcPre.UnwindTradeAmount ?? 0;
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeImport.UnderlyingCode);
|
|
tradeImport.Lots -= tcPre.UnwindNotional / underlying.ContractSize;
|
|
|
|
DbContext.SaveChanges();
|
|
}
|
|
|
|
private trade_swap_flow MapSwapTradeFlow(DataRowReader reader)
|
|
{
|
|
var needCostFee = reader.GetString("是否收取手续费");
|
|
var isTradePriceWhenOpen = reader.GetString("是否开仓时收取手续费");
|
|
var isNight = reader.GetString("是否夜盘");
|
|
var swapFlow = new trade_swap_flow()
|
|
{
|
|
TradeDate = reader.GetDate("交易日", true),
|
|
StartDate = reader.GetDate("北京时间自然日", true),
|
|
ExerciseDate = reader.GetDate("到期日"),
|
|
SettlementDate = reader.GetDate("结算日"),
|
|
BuySell = reader.GetString("买卖方向", true),
|
|
AssetUnitName = reader.GetString("簿记账户"),
|
|
ClientNumber = reader.GetString("客户编号", true),
|
|
ClientShortName = reader.GetString("客户简称"),
|
|
UnderlyingCode = reader.GetString("标的全称", true),
|
|
Lots = reader.GetDouble("手数", true).Value,
|
|
SpotPrice = reader.GetDouble("价格", true),
|
|
SingleFee = reader.GetDouble("按手数收费", false),
|
|
UnAnnualRate = reader.GetDouble("按名义本金收费", false),
|
|
ClearingAgency = reader.GetString("清算机构"),
|
|
NeedCostFee = needCostFee == "否" || needCostFee == "N" ? false : true,
|
|
IsTradePriceWhenOpen = isTradePriceWhenOpen == "是" || isTradePriceWhenOpen == "Y" ? true : false,
|
|
IsNight = isNight == "是" || isNight == "Y" ? true : false,
|
|
Comments = reader.GetString("备注"),
|
|
Number = "",
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = DateTime.Now
|
|
};
|
|
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlow.UnderlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]在系统中不存在");
|
|
}
|
|
else
|
|
{
|
|
if (swapFlow.ExerciseDate == null)
|
|
{
|
|
swapFlow.ExerciseDate = underlying.MaturityDate;
|
|
}
|
|
if (swapFlow.ExerciseDate == null)
|
|
{
|
|
throw new ServiceException($"客户编号[{swapFlow.ClientNumber}]标的代码[{swapFlow.UnderlyingCode}]到期日不能为空");
|
|
}
|
|
if (swapFlow.SettlementDate == null)
|
|
{
|
|
swapFlow.SettlementDate = underlying.CloseDate;
|
|
}
|
|
if (swapFlow.AssetUnitName == null)
|
|
{
|
|
swapFlow.AssetUnitName = string.Empty;
|
|
}
|
|
if (swapFlow.SettlementDate != null && swapFlow.SettlementDate < swapFlow.ExerciseDate)
|
|
{
|
|
throw new ServiceException($"客户编号[{swapFlow.ClientNumber}]标的代码[{swapFlow.UnderlyingCode}]的结算日期不应该小于到期日");
|
|
}
|
|
}
|
|
|
|
var variety = DataCacheProvider.GetVariety(swapFlow.UnderlyingCode);
|
|
if (variety == null)
|
|
{
|
|
throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]对应的品种在系统中不存在");
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any())
|
|
{
|
|
throw new ServiceException($"标的代码[{swapFlow.UnderlyingCode}]对应的品种币种不能为空");
|
|
}
|
|
else
|
|
{
|
|
swapFlow.QuoteCurrency = variety.QuoteCurrency;
|
|
}
|
|
}
|
|
|
|
swapFlow.Number = new BizLogicZJ().GenerateFlowNumber(swapFlow, DbContext);
|
|
SetDBModelCreator(swapFlow);
|
|
DbContext.trade_swap_flow.Add(swapFlow);
|
|
DbContext.SaveChanges();
|
|
|
|
return swapFlow;
|
|
}
|
|
|
|
private trade_swap_flow MapSwapTradeFlowGroup(DataRowReader reader)
|
|
{
|
|
var tradeAmount = reader.GetDouble("数量", false);
|
|
var lots = reader.GetDouble("手数", false);
|
|
var stockEqvNotional = reader.GetDouble("名义本金", false);
|
|
var swapFlow = new trade_swap_flow()
|
|
{
|
|
TradeNumber = reader.GetString("交易编号", true),
|
|
TradeDate = reader.GetDate("交易日", true),
|
|
UnderlyingCode = reader.GetString("标的代码", true),
|
|
BuySell = reader.GetString("买卖方向", true),
|
|
SpotPrice = reader.GetDouble("价格", true),
|
|
SingleFee = reader.GetDouble("按手数收费", false),
|
|
UnAnnualRate = reader.GetDouble("按名义本金收费", false),
|
|
NeedCostFee = true,
|
|
IsTradePriceWhenOpen = true,
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = DateTime.Now,
|
|
CreatorId = UserId,
|
|
CreatorName = UserName,
|
|
CreateDate = DateTime.Now
|
|
};
|
|
swapFlow.StartDate = swapFlow.TradeDate;
|
|
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlow.UnderlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]在系统中不存在");
|
|
}
|
|
else
|
|
{
|
|
|
|
if (stockEqvNotional != null && swapFlow.SpotPrice != 0)
|
|
{
|
|
tradeAmount = stockEqvNotional / swapFlow.SpotPrice;
|
|
}
|
|
|
|
if (tradeAmount != null)
|
|
{
|
|
lots = tradeAmount * underlying.CountRatio / underlying.ContractSize;
|
|
}
|
|
|
|
if (lots == null)
|
|
{
|
|
throw new ServiceException($"数量手数名义本金不能同时为空");
|
|
}
|
|
else
|
|
{
|
|
swapFlow.Lots = lots.Value;
|
|
}
|
|
}
|
|
|
|
var variety = DataCacheProvider.GetVariety(swapFlow.UnderlyingCode);
|
|
if (variety == null)
|
|
{
|
|
throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]对应的品种在系统中不存在");
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any())
|
|
{
|
|
throw new ServiceException($"标的代码[{swapFlow.UnderlyingCode}]对应的品种币种不能为空");
|
|
}
|
|
else
|
|
{
|
|
swapFlow.QuoteCurrency = variety.QuoteCurrency;
|
|
}
|
|
}
|
|
|
|
DbContext.trade_swap_flow.Add(swapFlow);
|
|
DbContext.SaveChanges();
|
|
|
|
return swapFlow;
|
|
}
|
|
|
|
private trade MapSwapTradeHandle(trade_swap_flow swapFlow)
|
|
{
|
|
var client = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(n => swapFlow.ClientNumber.Equals(n.Number, StringComparison.OrdinalIgnoreCase));
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException($"该客户编号[{swapFlow.ClientNumber}]在系统中不存在");
|
|
}
|
|
|
|
if (!client.DerivativesInvestmentVarieties.Contains((int)DerivativesInvestmentVarietiesEnum.场外互换 + ""))
|
|
{
|
|
throw new ServiceException($"客户:{client.Name}未设置交易种类“场外互换”,无法生成互换交易!");
|
|
}
|
|
|
|
if (swapFlow.Lots <= 0)
|
|
{
|
|
throw new ServiceException($"客户[{swapFlow.ClientNumber}]对应的流水手数[{swapFlow.Lots}]需要为正数");
|
|
}
|
|
|
|
var td = new trade
|
|
{
|
|
TradeDate = swapFlow.TradeDate,
|
|
StartDate = swapFlow.StartDate,
|
|
ExerciseDate = swapFlow.ExerciseDate,
|
|
SettlementDate = swapFlow.SettlementDate == null ? swapFlow.ExerciseDate : swapFlow.SettlementDate,
|
|
BuySell = "卖出",
|
|
TradeType = "收益互换",
|
|
StructureType = "收益互换",
|
|
ClientId = client.id,
|
|
ClientName = client.Name,
|
|
QuoteCurrency = swapFlow.QuoteCurrency,
|
|
SettlementCurrency = client.SettlementCurrency,
|
|
UnderlyingCode = swapFlow.UnderlyingCode,
|
|
SpotPrice = swapFlow.SpotPrice,
|
|
Lots = swapFlow.Lots,
|
|
IsNight = swapFlow.IsNight,
|
|
OpponentRole = "甲方",
|
|
MarginType = MarginTypeEnum.DEFAULT,
|
|
trade_swap = new trade_swap()
|
|
{
|
|
FlowId = swapFlow.id
|
|
}
|
|
};
|
|
|
|
td.MetaDic["交易场所"] = "柜台市场";
|
|
if (string.IsNullOrWhiteSpace(swapFlow.ClearingAgency) && string.IsNullOrWhiteSpace(client.ClearingAgency))
|
|
{
|
|
throw new ServiceException($"该流水需要维护清算机构信息或该客户[{td.ClientName}]需要维护清算机构信息");
|
|
}
|
|
td.MetaDic["清算机构"] = string.IsNullOrWhiteSpace(swapFlow.ClearingAgency) ? client.ClearingAgency : swapFlow.ClearingAgency;
|
|
//if (string.IsNullOrWhiteSpace(client.MainProtocolCode))
|
|
//{
|
|
// throw new ServiceException($"该客户[{td.ClientName}]需要维护主协议编号信息");
|
|
//}
|
|
td.MetaDic["主协议编号"] = client.MainProtocolCode;
|
|
//if (string.IsNullOrWhiteSpace(client.SupProtocolCode))
|
|
//{
|
|
// throw new ServiceException($"该客户[{td.ClientName}]需要维护补充协议编号信息");
|
|
//}
|
|
td.MetaDic["补充协议编号"] = client.SupProtocolCode;
|
|
|
|
var varitey = DataCacheProvider.GetVariety(td.UnderlyingCode);
|
|
var clientVarietyConfig = DbContext.client_variety_config.Where(x => x.ClientId == td.ClientId && x.VarietyId == varitey.id && x.ValueDate <= td.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault();
|
|
if (clientVarietyConfig == null)
|
|
{
|
|
throw new ServiceException($"该客户[{td.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{td.TradeDate}]相关的收费参数配置");
|
|
}
|
|
|
|
//标的代码(必需)
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"该标的代码[{td.UnderlyingCode}]在系统中不存在");
|
|
}
|
|
else
|
|
{
|
|
td.UnderlyingId = underlying.id;
|
|
td.UnderlyingAssetClass = underlying.UnderlyingType;
|
|
td.MaturityDate = underlying.MaturityDate;
|
|
|
|
if (td.ExerciseDate == null)
|
|
{
|
|
td.ExerciseDate = underlying.MaturityDate;
|
|
swapFlow.ExerciseDate = underlying.MaturityDate;
|
|
}
|
|
td.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType;
|
|
td.UnderlyingAssetName = underlying.UnderlyingName;
|
|
}
|
|
if (td.ExerciseDate == null)
|
|
{
|
|
throw new ServiceException($"客户编号[{swapFlow.ClientNumber}]标的代码[{swapFlow.UnderlyingCode}]到期日不能为空");
|
|
}
|
|
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(underlying.UnderlyingTypeId);
|
|
//交易份额
|
|
td.Notional = (td.Lots ?? 0) * underlying.ContractSize;
|
|
td.TradeAmount = td.Notional / variety.CountRatio;
|
|
td.OriginalNotional = td.Notional;
|
|
td.StockEqvNotional = (td.SpotPrice ?? 0) * td.Notional;
|
|
td.StockEqvNotionalReal = td.StockEqvNotional;
|
|
td.OriginalStockEqvNotional = td.StockEqvNotional;
|
|
td.PrincipalRate = 0;
|
|
td.ParticipationRate = 1;
|
|
|
|
var assetUnit = DataCacheProvider.GetAssetUnitDataSource().AsQueryable().FirstOrDefault(x => ("," + x.TraderIds + ",").Contains("," + UserId + ","));
|
|
if (!string.IsNullOrWhiteSpace(swapFlow.AssetUnitName))
|
|
{
|
|
assetUnit = DataCacheProvider.GetAssetUnitDataSource().AsQueryable().FirstOrDefault(x => x.Name == swapFlow.AssetUnitName);
|
|
if (assetUnit == null)
|
|
{
|
|
throw new ServiceException($"不存在该簿记账户[{swapFlow.AssetUnitName}]");
|
|
}
|
|
}
|
|
if (assetUnit == null)
|
|
{
|
|
throw new ServiceException($"不存在和交易员[{UserName}]匹配的簿记账户");
|
|
}
|
|
td.AssetId = assetUnit.id;
|
|
td.AssetBookName = assetUnit.Name;
|
|
td.TraderId = UserId;
|
|
td.TraderName = UserName;
|
|
|
|
td.trade_swap.GetSwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";" + (clientVarietyConfig?.AnnualRate ?? 0).ToString();
|
|
td.trade_swap.PaySwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";0";
|
|
//0代表了结时支付,1代表结算日支付
|
|
td.trade_swap.SettlementPayType = swapFlow.SettlementDate == null ? 0 : 1;
|
|
td.trade_swap.IsTradePriceWhenOpen = swapFlow.IsTradePriceWhenOpen;
|
|
var isAnnualSet = swapFlow.SingleFee != null || swapFlow.UnAnnualRate != null;
|
|
td.trade_swap.GetSingleFee = swapFlow.NeedCostFee ? (isAnnualSet ? (swapFlow.SingleFee ?? 0) : clientVarietyConfig?.SingleFee) : 0;
|
|
td.trade_swap.GetUnAnnualRate = swapFlow.NeedCostFee ? (isAnnualSet ? (swapFlow.UnAnnualRate ?? 0) : clientVarietyConfig?.UnAnnualRate) : 0;
|
|
td.trade_swap.AnnualDays = clientVarietyConfig?.AnnualDays;
|
|
//交易方向
|
|
var longshort = swapFlow.BuySell;
|
|
switch (longshort)
|
|
{
|
|
case "买入":
|
|
case "B":
|
|
td.trade_swap.PayLongShort = "多头";
|
|
break;
|
|
case "卖出":
|
|
case "S":
|
|
td.trade_swap.PayLongShort = "空头";
|
|
break;
|
|
default:
|
|
throw new ServiceException("买卖方向 填写错误:" + longshort);
|
|
}
|
|
|
|
return td;
|
|
}
|
|
|
|
public void BackSwapTradeByTradeFlow(trade_swap_flow flow)
|
|
{
|
|
var client = ClientModule.ClientDataQueryService.GetClientByNumber(flow.ClientNumber);
|
|
|
|
var tradeCashList = (from tradeCash in DbContext.trade_cash
|
|
join trade in DbContext.trade
|
|
on tradeCash.TradeId equals trade.id
|
|
join tradeSwap in DbContext.trade_swap
|
|
on trade.id equals tradeSwap.TradeId
|
|
join tradeCashSwap in DbContext.trade_cash_swap
|
|
on tradeCash.id equals tradeCashSwap.TradeCashId
|
|
where trade.UnderlyingCode == flow.UnderlyingCode && tradeSwap.OriginalTradeId == null && trade.ClientId == client.id && (tradeCashSwap.FlowId >= flow.id && tradeCash.ValueDate == flow.TradeDate || tradeCash.ValueDate > flow.TradeDate)
|
|
select new { tradeCash, tradeCashSwap }).OrderByDescending(x => x.tradeCash.id).ToList();
|
|
|
|
tradeCashList.ForEach(x =>
|
|
{
|
|
var trade = DbContext.trade.Find(x.tradeCash.TradeId);
|
|
trade.Notional = x.tradeCash.Notional;
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(trade.VarietyId ?? 0);
|
|
if (variety != null && variety.CountRatio != 0)
|
|
{
|
|
trade.TradeAmount = x.tradeCash.Notional / variety.CountRatio;
|
|
}
|
|
else
|
|
{
|
|
trade.TradeAmount = x.tradeCash.Notional;
|
|
}
|
|
|
|
trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor);
|
|
//分步回退时将倒数第二条平仓记录赋值给trade
|
|
var lastSecondTradeCash = DbContext.trade_cash.Where(y => y.TradeId == x.tradeCash.TradeId && y.id < x.tradeCash.id && y.ValidState != "InValid" && y.Action != "系统操作-期权费").OrderByDescending(y => y.id).FirstOrDefault();
|
|
if (lastSecondTradeCash != null && lastSecondTradeCash.Action == "系统操作-平仓费")
|
|
{
|
|
trade.UnWindDate = lastSecondTradeCash.ValueDate;
|
|
trade.FinalPrice = lastSecondTradeCash.FinalPrice;
|
|
trade.UnWindNotional = lastSecondTradeCash.UnwindNotional;
|
|
trade.UnWindPrice = lastSecondTradeCash.UnwindPrice;
|
|
trade.HasPartialUnWind = 1;
|
|
}
|
|
else
|
|
{
|
|
trade.UnWindDate = null;
|
|
trade.FinalPrice = null;
|
|
trade.UnWindNotional = null;
|
|
trade.UnWindPrice = null;
|
|
trade.HasPartialUnWind = null;
|
|
}
|
|
trade.CheckStatus = null;
|
|
trade.OptId = UserId;
|
|
trade.OptName = UserName;
|
|
trade.OptDate = DateTime.Now;
|
|
trade.TradeStatus = ConsTrade.确认成交;
|
|
trade.ProcessOrderId = 0;
|
|
trade.ProcessOptDate = null;
|
|
trade.ProcessStatus = null;
|
|
DbContext.SaveChanges();
|
|
|
|
RemoveEodTradeAndFutureInfo(true, trade.id, x.tradeCash.ValueDate, new List<int>() { x.tradeCash.id });
|
|
AddTradeOperationHistoryAndSetParentTradeInfo(true, trade, "修改交易流水");
|
|
});
|
|
|
|
var tradeCashPreList = (from tradeCashPre in DbContext.trade_cash_pre
|
|
join tradeCashSwap in DbContext.trade_cash_swap
|
|
on tradeCashPre.id equals tradeCashSwap.TradeCashPreId
|
|
where tradeCashSwap.FlowId == flow.id
|
|
select new { tradeCashPre, tradeCashSwap }).ToList();
|
|
|
|
tradeCashPreList.ForEach(x =>
|
|
{
|
|
var trade = DbContext.trade.Find(x.tradeCashPre.TradeId);
|
|
trade.Notional = x.tradeCashPre.Notional;
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(trade.VarietyId ?? 0);
|
|
if (variety != null && variety.CountRatio != 0)
|
|
{
|
|
trade.TradeAmount = x.tradeCashPre.Notional / variety.CountRatio;
|
|
}
|
|
else
|
|
{
|
|
trade.TradeAmount = x.tradeCashPre.Notional;
|
|
}
|
|
|
|
trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor);
|
|
//分步回退时将倒数第二条平仓记录赋值给trade
|
|
var lastSecondTradeCashPre = DbContext.trade_cash_pre.Where(y => y.TradeId == x.tradeCashPre.TradeId && y.id < x.tradeCashPre.id && y.ValidState != "InValid" && y.Action != "系统操作-期权费").OrderByDescending(y => y.id).FirstOrDefault();
|
|
if (lastSecondTradeCashPre != null && lastSecondTradeCashPre.Action == "系统操作-平仓费")
|
|
{
|
|
trade.UnWindDate = lastSecondTradeCashPre.HappenedDate;
|
|
trade.FinalPrice = lastSecondTradeCashPre.FinalPrice;
|
|
trade.UnWindNotional = lastSecondTradeCashPre.UnwindNotional;
|
|
trade.UnWindPrice = lastSecondTradeCashPre.UnwindPrice;
|
|
trade.HasPartialUnWind = 1;
|
|
}
|
|
else
|
|
{
|
|
trade.UnWindDate = null;
|
|
trade.FinalPrice = null;
|
|
trade.UnWindNotional = null;
|
|
trade.UnWindPrice = null;
|
|
trade.HasPartialUnWind = null;
|
|
}
|
|
trade.CheckStatus = null;
|
|
trade.OptId = UserId;
|
|
trade.OptName = UserName;
|
|
trade.OptDate = DateTime.Now;
|
|
trade.TradeStatus = ConsTrade.确认成交;
|
|
trade.ProcessOrderId = 0;
|
|
trade.ProcessOptDate = null;
|
|
trade.ProcessStatus = null;
|
|
DbContext.SaveChanges();
|
|
|
|
var tradeCashPreIds = DbContext.trade_cash_pre.Where(y => y.TradeId == x.tradeCashPre.TradeId && y.id >= x.tradeCashPre.id).Select(y => y.id).ToList();
|
|
RemoveEodTradeAndFutureInfo(true, trade.id, x.tradeCashPre.HappenedDate ?? x.tradeCashPre.ValueDate, tradeCashPreIds: tradeCashPreIds);
|
|
AddTradeOperationHistoryAndSetParentTradeInfo(true, trade, "修改交易流水");
|
|
});
|
|
|
|
var tradeList = (from trade in DbContext.trade
|
|
join swap in DbContext.trade_swap
|
|
on trade.id equals swap.TradeId
|
|
where trade.UnderlyingCode == flow.UnderlyingCode && swap.OriginalTradeId == null && trade.ClientId == client.id && (swap.FlowId >= flow.id && trade.TradeDate == flow.TradeDate || trade.TradeDate > flow.TradeDate) && trade.ValidState != "InValid"
|
|
select new { trade, swap }).ToList();
|
|
var baseService = new TradeServiceBase(UserInfo, DbContext);
|
|
tradeList.ForEach(x => new TradeInvalidService(baseService).InvalidTrade(x.trade.id, false));
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//public void generateSettleDocument(List<trade_cash> cashes)
|
|
//{
|
|
// if (cashes.Count() > 0)
|
|
// {
|
|
// var clientTradeDict =
|
|
// cashes.GroupBy(O => O.ClientName + "|" + O.ValueDate)
|
|
// .ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
// foreach (var tradeCashs in clientTradeDict)
|
|
// {
|
|
// var clienName = cashes.FirstOrDefault().ClientName;
|
|
// var client = DbContextFactory.GetClientDbContext(OptUser).client.Where(o => o.Name == clienName).FirstOrDefault();
|
|
// if (client != null && client.BoundSide == BoundSideEnum.北向)
|
|
// {
|
|
// foreach (var tc in tradeCashs.Value)
|
|
// {
|
|
// new RDBatchEndBillGenerateService(OptUser)
|
|
// .Generate(new List<int> { tc }, null, "PDF", OptUser.UserId, OptUser.UserName).ToList();
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// new RDBatchEndBillGenerateService(OptUser)
|
|
// .Generate(tradeCashs.Value, null, "PDF", OptUser.UserId, OptUser.UserName).ToList();
|
|
// }
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
#region---内部业务类----
|
|
|
|
class DataRowReader
|
|
{
|
|
DataRow _row;
|
|
|
|
readonly Dictionary<string, int> _colMap;
|
|
|
|
public DataRowReader(DataTable table)
|
|
{
|
|
var colCount = table.Columns.Count;
|
|
|
|
_colMap = new Dictionary<string, int>(colCount, StringComparer.OrdinalIgnoreCase);
|
|
|
|
var row1 = table.Rows[0];
|
|
var preCol1 = string.Empty;
|
|
|
|
for (var index = 0; index < colCount; index++)
|
|
{
|
|
var col1 = row1[index]?.ToString()?.Trim();
|
|
if (!string.IsNullOrWhiteSpace(col1))
|
|
{
|
|
preCol1 = col1;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
_colMap[preCol1] = index;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置datarow
|
|
/// </summary>
|
|
public void SetDataRow(DataRow row)
|
|
{
|
|
_row = row;
|
|
}
|
|
|
|
public string GetString(string fieldName, bool required = false)
|
|
{
|
|
var str = _colMap.TryGetValue(fieldName, out var colIndex) ? _row[colIndex]?.ToString()?.Trim() : null;
|
|
|
|
if (required && string.IsNullOrWhiteSpace(str))
|
|
{
|
|
throw new ServiceException($"{fieldName} 必须填写");
|
|
}
|
|
|
|
return 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($"{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($"{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($"{fieldName} 必须填写") : (double?)null;
|
|
}
|
|
|
|
return double.TryParse(str, out var num) ? num : throw new ServiceException($"{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($"{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($"{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($"{fieldName} 填写错误:{str}");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|