890 lines
38 KiB
C#
890 lines
38 KiB
C#
using BaseOUDAL;
|
|
using System.Data;
|
|
using YLErp.BLL;
|
|
using YLErp.Commons;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.DBModels.Enums;
|
|
using YLErp.Enums;
|
|
using YLErp.Model.Enum;
|
|
using YLErp.Modules.CalculationModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.SwapModule
|
|
{
|
|
public class SwapTradeFlowMoreImportService : TradeServiceBase
|
|
{
|
|
public SwapTradeFlowMoreImportService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
|
|
}
|
|
|
|
public SwapTradeFlowMoreImportService(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 = 1;
|
|
try
|
|
{
|
|
var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 1);
|
|
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 1)
|
|
{
|
|
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
|
|
}
|
|
|
|
var table = ds.Tables[0];
|
|
var reader = new DataRowReader(table);
|
|
|
|
totalNum = table.Rows.Count;
|
|
|
|
using (var trans = BeginTransaction())
|
|
{
|
|
foreach (var row in table.Rows.Cast<DataRow>())
|
|
{
|
|
rowIndex++;
|
|
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
|
|
{
|
|
totalNum--;
|
|
continue;
|
|
}
|
|
reader.SetDataRow(row);
|
|
//映射导入数据到交易对象
|
|
var tradeFlow = MapSwapTrade(reader);
|
|
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);
|
|
}
|
|
}
|
|
|
|
private trade_swap_flow_more MapSwapTrade(DataRowReader reader)
|
|
{
|
|
var swapFlow = new trade_swap_flow_more();
|
|
|
|
swapFlow.ClientNumber = reader.GetString("客户编号", false);
|
|
swapFlow.ClientName = reader.GetString("客户名称", false);
|
|
swapFlow.UnderlyingCode = reader.GetString("标的代码", false);
|
|
swapFlow.UnderlyingName = reader.GetString("标的名称", false);
|
|
swapFlow.TraderName = reader.GetString("交易员", true);
|
|
swapFlow.AssetBookName = reader.GetString("簿记账户", true);
|
|
swapFlow.Notional = reader.GetDouble("成交数量", true) ?? 0;
|
|
swapFlow.BuySell = reader.GetString("交易方向", true);
|
|
swapFlow.TradeNumber = reader.GetString("交易编号", true);
|
|
|
|
swapFlow.TradeDate = reader.GetDate("开始日期", true);
|
|
swapFlow.ExerciseDate = reader.GetDate("到期日期", true);
|
|
|
|
swapFlow.Price = reader.GetDouble("期初标的价格", true) ?? 0;
|
|
swapFlow.CurrencyRate = reader.GetDouble("汇率", false) ?? 1;
|
|
swapFlow.AnnualRate = reader.GetDouble("利率", false);
|
|
swapFlow.TotalFee = reader.GetDouble("手续费", false);
|
|
swapFlow.MargeRate = reader.GetDouble("预付金率", false);
|
|
|
|
if (swapFlow.BuySell == "平仓")
|
|
{
|
|
swapFlow.UnwindDate = reader.GetDate("平仓日期", true);
|
|
swapFlow.UnwindPrice = reader.GetDouble("平仓价格", false);
|
|
swapFlow.UnwindNotional = reader.GetDouble("平仓数量", true) ?? 0;
|
|
swapFlow.FixedIncome = reader.GetDouble("固定收益", false);
|
|
swapFlow.Amount = reader.GetDouble("实现盈亏", false);
|
|
}
|
|
|
|
CheckAssignmentSwapTradeFlow(swapFlow);
|
|
|
|
swapFlow.OptId = UserId;
|
|
swapFlow.OptName = UserName;
|
|
swapFlow.OptDate = DateTime.Now;
|
|
|
|
DbContext.trade_swap_flow_more.Add(swapFlow);
|
|
DbContext.SaveChanges();
|
|
return swapFlow;
|
|
}
|
|
|
|
private void CheckNotNullSwapTradeFlow(TradeSwapFlowRequestModel model)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(model.TraderName))
|
|
{
|
|
throw new ServiceException($"交易员不能为空");
|
|
}
|
|
if (string.IsNullOrWhiteSpace(model.AssetBookName))
|
|
{
|
|
throw new ServiceException($"簿记账户不能为空");
|
|
}
|
|
if (string.IsNullOrWhiteSpace(model.BuySell))
|
|
{
|
|
throw new ServiceException($"交易方向不能为空");
|
|
}
|
|
if (string.IsNullOrWhiteSpace(model.TradeNumber))
|
|
{
|
|
throw new ServiceException($"交易编号不能为空");
|
|
}
|
|
if (model.Notional == 0)
|
|
{
|
|
throw new ServiceException($"成交数量不能为0");
|
|
}
|
|
if (!model.TradeDate.HasValue)
|
|
{
|
|
throw new ServiceException($"开始日期不能为空");
|
|
}
|
|
if (!model.ExerciseDate.HasValue)
|
|
{
|
|
throw new ServiceException($"到期日期不能为空");
|
|
}
|
|
if (!model.OpenPrice.HasValue)
|
|
{
|
|
throw new ServiceException($"标的价格不能为空");
|
|
}
|
|
if (model.BuySell == "平仓")
|
|
{
|
|
if (!model.UnwindDate.HasValue)
|
|
{
|
|
throw new ServiceException($"平仓日期不能为空");
|
|
}
|
|
if (!model.UnwindPrice.HasValue)
|
|
{
|
|
throw new ServiceException($"平仓价格不能为空");
|
|
}
|
|
if (!model.UnwindNotional.HasValue)
|
|
{
|
|
throw new ServiceException($"平仓数量不能为空");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckAssignmentSwapTradeFlow(trade_swap_flow_more model)
|
|
{
|
|
string clientNumber = model.ClientNumber;
|
|
string clientName = model.ClientName;
|
|
if (!string.IsNullOrWhiteSpace(clientNumber))
|
|
{
|
|
var client = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(n => clientNumber.Equals(n.Number, StringComparison.OrdinalIgnoreCase));
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException($"该客户编号[{clientNumber}]在系统中不存在");
|
|
}
|
|
model.ClientNumber = client.Number;
|
|
model.ClientId = client.id;
|
|
}
|
|
else if (!string.IsNullOrWhiteSpace(clientName))
|
|
{
|
|
var client = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(n => clientName.Equals(n.Name, StringComparison.OrdinalIgnoreCase));
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException($"该客户名称[{clientName}]在系统中不存在");
|
|
}
|
|
model.ClientNumber = client.Number;
|
|
model.ClientId = client.id;
|
|
}
|
|
else
|
|
{
|
|
throw new ServiceException($"客户编号和客户名称不能同时为空");
|
|
}
|
|
|
|
string underlyingCode = model.UnderlyingCode;
|
|
string underlyingName = model.UnderlyingName;
|
|
if (!string.IsNullOrWhiteSpace(underlyingCode))
|
|
{
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"该标的代码[{underlyingCode}]在系统中不存在");
|
|
}
|
|
model.UnderlyingCode = underlying.UnderlyingCode;
|
|
}
|
|
else if (!string.IsNullOrWhiteSpace(underlyingName))
|
|
{
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().FirstOrDefault(n => underlyingName.Equals(n.UnderlyingName, StringComparison.OrdinalIgnoreCase));
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"该标的名称[{underlyingName}]在系统中不存在");
|
|
}
|
|
model.UnderlyingCode = underlying.UnderlyingCode;
|
|
}
|
|
else
|
|
{
|
|
throw new ServiceException($"标的代码和标的名称不能同时为空");
|
|
}
|
|
|
|
string traderName = model.TraderName;
|
|
var traders = UserBLL.GetUsersByPosition().FirstOrDefault(x => x.Name == traderName);
|
|
if (traders == null)
|
|
{
|
|
throw new ServiceException($"该交易员[{traderName}]在系统中不存在");
|
|
}
|
|
model.TraderId = traders.Id;
|
|
model.TraderName = traders.Name;
|
|
|
|
string assetBookName = model.AssetBookName;
|
|
var assetUnit = DataCacheProvider.GetAssetUnitDataSource().AsQueryable().FirstOrDefault(x => x.Name == assetBookName);
|
|
if (assetUnit == null)
|
|
{
|
|
throw new ServiceException($"该簿记账户[{assetBookName}]在系统中不存在");
|
|
}
|
|
else
|
|
{
|
|
if (!("," + assetUnit.TraderIds + ",").Contains("," + model.TraderId + ","))
|
|
{
|
|
throw new ServiceException($"该交易员[{model.TraderName}]不在簿记账户[{assetBookName}]中");
|
|
}
|
|
}
|
|
model.AssetId = assetUnit.id;
|
|
model.AssetBookName = assetUnit.Name;
|
|
|
|
double notional = model.Notional;
|
|
if (notional == 0)
|
|
{
|
|
throw new ServiceException($"成交数量不能为0");
|
|
}
|
|
string longShort = notional > 0 ? "多头" : "空头";
|
|
model.LongShort = longShort;
|
|
model.Notional = notional;
|
|
|
|
if (model.BuySell == "开仓")
|
|
{
|
|
if (DbContext.trade.Where(x => x.TradeNumber == model.TradeNumber && x.ValidState != "InValid").Any())
|
|
{
|
|
throw new ServiceException($"该交易已存在,编号[{model.TradeNumber}]");
|
|
}
|
|
if (DbContext.trade_swap_flow_more.Where(x => x.TradeNumber == model.TradeNumber && !x.IsDelete).Any())
|
|
{
|
|
throw new ServiceException($"开仓流水已存在该交易编号,编号[{model.TradeNumber}]");
|
|
}
|
|
}
|
|
|
|
if (model.BuySell == "平仓")
|
|
{
|
|
if (model.UnwindNotional == 0)
|
|
{
|
|
throw new ServiceException($"平仓数量不能为0");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 互换流水api导入
|
|
/// </summary>
|
|
/// <param name="reader"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ServiceException"></exception>
|
|
public trade_swap_flow_more SwapTradeFlow(TradeSwapFlowRequestModel model)
|
|
{
|
|
CheckNotNullSwapTradeFlow(model);
|
|
|
|
var swapFlow = new trade_swap_flow_more();
|
|
|
|
swapFlow.ClientNumber = model.ClientNumber;
|
|
swapFlow.ClientName = model.ClientName;
|
|
swapFlow.UnderlyingCode = model.UnderlyingCode;
|
|
swapFlow.UnderlyingName = model.UnderlyingName;
|
|
swapFlow.TraderName = model.TraderName;
|
|
swapFlow.AssetBookName = model.AssetBookName;
|
|
swapFlow.Notional = model.Notional;
|
|
swapFlow.BuySell = model.BuySell;
|
|
swapFlow.TradeNumber = model.TradeNumber;
|
|
|
|
swapFlow.TradeDate = model.TradeDate;
|
|
swapFlow.ExerciseDate = model.ExerciseDate;
|
|
|
|
swapFlow.Price = model.OpenPrice ?? 0;
|
|
swapFlow.CurrencyRate = model.CurrencyRate ?? 1;
|
|
swapFlow.AnnualRate = model.AnnualRate;
|
|
swapFlow.TotalFee = model.TotalFee;
|
|
swapFlow.MargeRate = model.MargeRate;
|
|
|
|
if (swapFlow.BuySell == "平仓")
|
|
{
|
|
swapFlow.UnwindDate = model.UnwindDate;
|
|
swapFlow.UnwindPrice = model.UnwindPrice;
|
|
swapFlow.UnwindNotional = model.UnwindNotional;
|
|
swapFlow.FixedIncome = model.FixedIncome;
|
|
swapFlow.Amount = model.Amount;
|
|
}
|
|
|
|
CheckAssignmentSwapTradeFlow(swapFlow);
|
|
|
|
swapFlow.OptId = UserId;
|
|
swapFlow.OptName = UserName;
|
|
swapFlow.OptDate = DateTime.Now;
|
|
|
|
DbContext.trade_swap_flow_more.Add(swapFlow);
|
|
DbContext.SaveChanges();
|
|
return swapFlow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 合成交易
|
|
/// </summary>
|
|
/// <param name="TradeNumber"></param>
|
|
/// <param name="tradeFlow"></param>
|
|
public void HandleSwapTrade(string TradeNumber)
|
|
{
|
|
using (var trans = BeginTransaction())
|
|
{
|
|
var tradeFlow = DbContext.trade_swap_flow_more.Where(x => !x.IsCompose && !x.IsDelete && x.TradeNumber == TradeNumber).ToList();
|
|
|
|
trade td = DbContext.trade.Where(x => x.TradeNumber == TradeNumber && x.ValidState != "InValid")?.FirstOrDefault();
|
|
if (td == null && !tradeFlow.Where(x => x.BuySell == "开仓").Any())
|
|
{
|
|
throw new ServiceException($"该交易不存在开仓流水,编号[{TradeNumber}]");
|
|
}
|
|
if (td != null && tradeFlow.Where(x => x.BuySell == "开仓").Any())
|
|
{
|
|
throw new ServiceException($"该交易重复,编号[{TradeNumber}]");
|
|
}
|
|
if (td != null)
|
|
{
|
|
tradeBLL.SetFieldsByTradeType(td);
|
|
}
|
|
if (tradeFlow.Where(x => x.BuySell == "开仓").Any())
|
|
{
|
|
var tradeflow = tradeFlow.Where(x => x.BuySell == "开仓").FirstOrDefault();
|
|
td = MapSwapTradeHandle(tradeflow);
|
|
InnerSaveSwapTrade(td, tradeflow);
|
|
}
|
|
if (tradeFlow.Where(x => x.BuySell == "平仓").Any())
|
|
{
|
|
var tradeflow = tradeFlow.Where(x => x.BuySell == "平仓").OrderBy(x => x.UnwindDate).ToList();
|
|
foreach (var item in tradeflow)
|
|
{
|
|
if (td.TradeStatus != "确认成交")
|
|
{
|
|
throw new ServiceException($"交易不允许平仓,编号[{TradeNumber}]");
|
|
}
|
|
UnwindSwapTrade(td, item);
|
|
}
|
|
}
|
|
tradeFlow.ForEach(x =>
|
|
{
|
|
x.IsCompose = true;
|
|
x.OptDate = DateTime.Now;
|
|
x.OptName = UserName;
|
|
x.OptId = UserId;
|
|
});
|
|
DbContext.SaveChanges();
|
|
trans.Commit();
|
|
}
|
|
}
|
|
|
|
private trade MapSwapTradeHandle(trade_swap_flow_more swapFlow)
|
|
{
|
|
var client = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(n => swapFlow.ClientNumber.Equals(n.Number, StringComparison.OrdinalIgnoreCase));
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException($"该客户编号[{swapFlow.ClientNumber}]在系统中不存在");
|
|
}
|
|
|
|
trade td = new trade
|
|
{
|
|
ClientId = client.id,
|
|
ClientName = client.Name,
|
|
TradeNumber = swapFlow.TradeNumber,
|
|
UnderlyingCode = swapFlow.UnderlyingCode,
|
|
TradeDate = swapFlow.TradeDate,
|
|
StartDate = swapFlow.TradeDate,
|
|
ExerciseDate = swapFlow.ExerciseDate,
|
|
SettlementDate = swapFlow.ExerciseDate,
|
|
SpotPrice = swapFlow.Price,
|
|
Notional = Math.Abs(swapFlow.Notional),
|
|
AssetId = swapFlow.AssetId,
|
|
AssetBookName = swapFlow.AssetBookName,
|
|
TraderId = swapFlow.TraderId,
|
|
TraderName = swapFlow.TraderName,
|
|
TradeType = "收益互换",
|
|
StructureType = "收益互换",
|
|
OpponentRole = "甲方",
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = DateTime.Now,
|
|
TradeSource = TradeSourceEnum.导入交易.ToString(),
|
|
TradeStatus = ConsTrade.确认成交,
|
|
};
|
|
|
|
td.MetaDic["交易场所"] = "柜台市场";
|
|
if (!string.IsNullOrWhiteSpace(client.ClearingAgency))
|
|
{
|
|
td.MetaDic["清算机构"] = client.ClearingAgency;
|
|
}
|
|
td.MetaDic["主协议编号"] = client.MainProtocolCode;
|
|
td.MetaDic["补充协议编号"] = client.SupProtocolCode;
|
|
td.SettlementCurrency = client.SettlementCurrency ?? "CNY";
|
|
|
|
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;
|
|
td.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType;
|
|
td.UnderlyingAssetName = underlying.UnderlyingName;
|
|
}
|
|
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(underlying.UnderlyingTypeId);
|
|
td.QuoteCurrency = variety.QuoteCurrency ?? "CNY";
|
|
//交易份额--名义本金
|
|
td.Lots = td.Notional / 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.trade_swap.IsTradePriceWhenOpen = false; // 导入默认值
|
|
td.TradePrice = 0;
|
|
if (swapFlow.AnnualRate > 0)
|
|
{
|
|
td.trade_swap.GetSwapRate = swapFlow.AnnualRate ?? 0;
|
|
td.trade_swap.GetSwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";" + td.trade_swap.GetSwapRate;
|
|
|
|
td.trade_swap.IsGetFloatingProfit = false;
|
|
td.trade_swap.IsPayFloatingProfit = true;
|
|
td.trade_swap.PayLongShort = swapFlow.LongShort == "多头" ? "空头" : "多头";
|
|
td.trade_swap.PayUnderlyingId = td.UnderlyingId;
|
|
td.trade_swap.PayUnderlyingCode = td.UnderlyingCode;
|
|
td.trade_swap.PaySpotPrice = td.SpotPrice;
|
|
td.trade_swap.PayNotional = td.Notional;
|
|
td.trade_swap.PayLot = td.Lots;
|
|
td.trade_swap.PayTradeAmount = td.TradeAmount;
|
|
td.trade_swap.GetTradePrice = swapFlow.TotalFee;
|
|
td.trade_swap.GetSingleFee = swapFlow.TotalFee / td.Lots;
|
|
}
|
|
else
|
|
{
|
|
td.trade_swap.PaySwapRate = -swapFlow.AnnualRate ?? 0;
|
|
td.trade_swap.PaySwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";" + td.trade_swap.PaySwapRate;
|
|
|
|
td.trade_swap.IsGetFloatingProfit = true;
|
|
td.trade_swap.IsPayFloatingProfit = false;
|
|
td.trade_swap.GetLongShort = swapFlow.LongShort;
|
|
td.trade_swap.GetUnderlyingId = td.UnderlyingId;
|
|
td.trade_swap.GetUnderlyingCode = td.UnderlyingCode;
|
|
td.trade_swap.GetSpotPrice = td.SpotPrice;
|
|
td.trade_swap.GetNotional = td.Notional;
|
|
td.trade_swap.GetLot = td.Lots;
|
|
td.trade_swap.GetTradeAmount = td.TradeAmount;
|
|
td.trade_swap.PayTradePrice = -(swapFlow.TotalFee);
|
|
td.trade_swap.PaySingleFee = -(swapFlow.TotalFee / td.Lots);
|
|
}
|
|
if (swapFlow.MargeRate > 0)
|
|
{
|
|
td.trade_swap.GetMarginRate = swapFlow.MargeRate;
|
|
}
|
|
else
|
|
{
|
|
td.trade_swap.PayMarginRate = -swapFlow.MargeRate;
|
|
}
|
|
td.BuySell = td.TradePrice == 0 ? td.trade_swap.IsPayFloatingProfit == true ? "卖出" : "买入" : td.TradePrice > 0 ? "卖出" : "买入";
|
|
|
|
td.trade_swap.RateCalcMode = "01";
|
|
|
|
return td;
|
|
}
|
|
|
|
private void InnerSaveSwapTrade(trade importTrade, trade_swap_flow_more tradeflow)
|
|
{
|
|
importTrade.IsUsePremiumRate = true;
|
|
importTrade.IsTradePricePayType = true;
|
|
importTrade.PrincipalRate = 0;
|
|
importTrade.ParticipationRate = 1;
|
|
|
|
//预付金
|
|
importTrade.MarginTemplateName = null;
|
|
importTrade.MarginType = MarginTypeEnum.DEFAULT;
|
|
|
|
SetDBModelCreator(importTrade);
|
|
DbContext.trade.Add(importTrade);
|
|
DbContext.SaveChanges();
|
|
|
|
importTrade.trade_swap.TradeId = importTrade.id;
|
|
importTrade.trade_swap.SwapType = "普通";
|
|
importTrade.trade_swap.OptId = UserId;
|
|
importTrade.trade_swap.OptName = UserName;
|
|
importTrade.trade_swap.OptDate = DateTime.Now;
|
|
importTrade.trade_swap.SettlementPayType = 0;
|
|
importTrade.trade_swap.FlowId = tradeflow.id;
|
|
importTrade.trade_swap.AnnualDays = 365;
|
|
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.系统操作_期权费;
|
|
//默认开仓不收取手续费 -- 期权费为0
|
|
tc.Amount = 0;
|
|
tc.QuoteAmount = 0;
|
|
tc.CurrencyRate = tradeflow.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 td, trade_swap_flow_more tradeflow)
|
|
{
|
|
UnwindSwapTradeCashHandle(td, tradeflow);
|
|
|
|
SaveTradeOperationHistory(td, "互换导入合成交易");
|
|
|
|
RemoveEodTradeAndFutureInfo(true, td.id, tradeflow.UnwindDate.Value);
|
|
}
|
|
|
|
private void UnwindSwapTradeCashHandle(trade td, trade_swap_flow_more tradeflow)
|
|
{
|
|
var unwindNotional = Math.Abs(tradeflow.UnwindNotional ?? 0);
|
|
var unwindType = td.Notional > unwindNotional ? "部分平仓" : "全部平仓";
|
|
|
|
var maxValueDate = DbContext.trade_cash.Where(x => x.TradeId == td.id && x.ValidState != "InValid" && x.Action != ClientCashInCashOut.系统操作_期权费).OrderByDescending(x => x.ValueDate).Select(x => x.ValueDate)?.FirstOrDefault();
|
|
if (maxValueDate != null && maxValueDate > tradeflow.UnwindDate)
|
|
{
|
|
throw new ServiceException($"平仓日期({tradeflow.UnwindDate})不能小于历史平仓日期({maxValueDate})");
|
|
}
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(td.ClientId);
|
|
var underly = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingId);
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(underly.UnderlyingTypeId);
|
|
var currencyRate = (tradeflow.CurrencyRate ?? 1);
|
|
|
|
//增加现金交割交易记录
|
|
var tc = new trade_cash();
|
|
DbContext.trade_cash.Add(tc);
|
|
|
|
tc.OptId = UserId;
|
|
tc.OptName = UserName;
|
|
tc.OptDate = DateTime.Now;
|
|
tc.TradeId = td.id;
|
|
tc.ExceciseType = "现金";
|
|
tc.TradeType = td.BuySell;
|
|
tc.CallPut = td.CallPut;
|
|
tc.Notional = td.Notional;
|
|
tc.TradeAmount = td.TradeAmount;
|
|
tc.IsLastAction = unwindType == "全部平仓";
|
|
tc.FinalPrice = td.SpotPrice;
|
|
tc.UnwindType = unwindType;
|
|
tc.UnwindPrice = Math.Abs(tradeflow.UnwindPrice ?? 0);
|
|
tc.CurrencyRate = currencyRate;
|
|
|
|
if (tc.UnwindType == "全部平仓")
|
|
{
|
|
tc.UnwindNotional = td.Notional;
|
|
tc.UnwindTradeAmount = td.TradeAmount;
|
|
tc.UnwindPercentRate = td.Notional / td.OriginalNotional;
|
|
}
|
|
else
|
|
{
|
|
tc.UnwindNotional = unwindNotional;
|
|
tc.UnwindTradeAmount = unwindNotional / variety.CountRatio;
|
|
tc.UnwindPercentRate = unwindNotional / td.OriginalNotional;
|
|
}
|
|
|
|
// 开仓默认不收取手续费
|
|
var costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(td, td, tc, td.trade_swap.IsPayFloatingProfit ? true : false, true);
|
|
var costTradePriceGet = costTradePriceGetQuote * currencyRate;
|
|
var costFeeGetQuote = (tradeflow.TotalFee ?? 0);
|
|
var costFeeGet = costFeeGetQuote * currencyRate;
|
|
var amountQuote = (tradeflow.Amount ?? 0);
|
|
var amount = amountQuote * currencyRate;
|
|
var FixedIncomeQuote = (tradeflow.FixedIncome ?? 0);
|
|
var FixedIncome = FixedIncomeQuote * currencyRate;
|
|
var initialAmountPayQuote = amountQuote - costFeeGetQuote - costTradePriceGetQuote - FixedIncomeQuote;
|
|
var initialAmountPay = initialAmountPayQuote * currencyRate;
|
|
|
|
tc.NotionalPercentRate = tc.UnwindPercentRate;
|
|
tc.Action = ClientCashInCashOut.系统操作_平仓费;
|
|
tc.Status = TradeCashStatusEnum.已执行;
|
|
tc.Amount = amount;
|
|
tc.QuoteAmount = amountQuote;
|
|
tc.ValueDate = tradeflow.UnwindDate ?? DateTime.Today;
|
|
tc.ValidState = "Valid";
|
|
tc.ExerciseWay = tc.ValueDate == td.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权;
|
|
|
|
DbContext.SaveChanges();
|
|
|
|
if (unwindType == "全部平仓")
|
|
{
|
|
td.TradeStatus = "已平仓";
|
|
}
|
|
else
|
|
{
|
|
td.HasPartialUnWind = 1;
|
|
}
|
|
td.UnWindDate = tc.ValueDate;
|
|
td.StockEqvNotional -= (td.SpotPrice ?? 0) * (tc.UnwindNotional ?? 0);
|
|
td.Notional -= tc.UnwindNotional ?? 0;
|
|
td.Lots = td.Notional / underly.ContractSize;
|
|
td.TradeAmount -= tc.UnwindTradeAmount ?? 0;
|
|
td.UnWindNotional = (td.UnWindNotional ?? 0) + tc.UnwindNotional;
|
|
//增加出入金记录
|
|
new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(td, tc, tc.ValueDate);
|
|
|
|
var trade_cash_swap = new trade_cash_swap();
|
|
trade_cash_swap.StartDate = td.StartDate.Value;
|
|
|
|
var costFeesum = costFeeGet + costTradePriceGet;
|
|
if (FixedIncomeQuote > 0)
|
|
{
|
|
trade_cash_swap.GetExtraAmount = FixedIncomeQuote;
|
|
}
|
|
else
|
|
{
|
|
trade_cash_swap.PayExtraAmount = -FixedIncomeQuote;
|
|
}
|
|
if (td.trade_swap.IsPayFloatingProfit)
|
|
{
|
|
trade_cash_swap.PayInitialAmount = -initialAmountPay;
|
|
trade_cash_swap.PayStartPrice = td.trade_swap.PayFinalPrice ?? td.trade_swap.PaySpotPrice;
|
|
trade_cash_swap.PayFinalPrice = tc.FinalPrice;
|
|
trade_cash_swap.GetCostFee = costFeesum;
|
|
}
|
|
else
|
|
{
|
|
trade_cash_swap.GetInitialAmount = initialAmountPay;
|
|
trade_cash_swap.GetStartPrice = td.trade_swap.PayFinalPrice ?? td.trade_swap.GetSpotPrice;
|
|
trade_cash_swap.GetFinalPrice = tc.FinalPrice;
|
|
trade_cash_swap.PayCostFee = -costFeesum;
|
|
}
|
|
trade_cash_swap.GetAmount = trade_cash_swap.GetInitialAmount + (trade_cash_swap.GetExtraAmount ?? 0) * currencyRate + (trade_cash_swap.GetCostFee ?? 0);
|
|
trade_cash_swap.PayAmount = trade_cash_swap.PayInitialAmount + (trade_cash_swap.PayExtraAmount ?? 0) * currencyRate + (trade_cash_swap.PayCostFee ?? 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;
|
|
trade_cash_swap.FlowId = tradeflow.id;
|
|
DbContext.trade_cash_swap.Add(trade_cash_swap);
|
|
|
|
var tcdFixed = new trade_cash_detail
|
|
{
|
|
TradeId = tc.TradeId,
|
|
TradeCashId = tc.id,
|
|
Action = tc.Action,
|
|
Amount = FixedIncome,
|
|
QuoteAmount = FixedIncomeQuote,
|
|
ValueDate = tc.ValueDate,
|
|
IsForGet = false,
|
|
OptId = tc.OptId,
|
|
OptName = tc.OptName,
|
|
OptDate = DateTime.Now,
|
|
TradeCashType = TradeCashTypeEnum.利息.ToString()
|
|
};
|
|
DbContext.trade_cash_detail.Add(tcdFixed);
|
|
|
|
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 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 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);
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdateCurrencyRate(IEnumerable<int> ids, double CurrencyRate)
|
|
{
|
|
if (ids is null || !ids.Any(n => n > 0))
|
|
{
|
|
throw new ArgumentException("tradeids 参数无效", nameof(ids));
|
|
}
|
|
using (var trans = BeginTransaction())
|
|
{
|
|
var idSet = ids.ToHashSet();
|
|
|
|
var tradeFlow = DbContext.trade_swap_flow_more.Where(x => idSet.Contains(x.id)).ToList();
|
|
tradeFlow.ForEach(x =>
|
|
{
|
|
x.CurrencyRate = CurrencyRate;
|
|
x.OptDate = DateTime.Now;
|
|
x.OptName = UserName;
|
|
x.OptId = UserId;
|
|
});
|
|
|
|
//开仓 -- 开仓默认不收手续费
|
|
var tradeid_Open = DbContext.trade_swap.Where(x => idSet.Contains(x.FlowId ?? 0)).Select(x => x.TradeId).ToHashSet();
|
|
if (tradeid_Open.Any())
|
|
{
|
|
var trade_cash_Open = DbContext.trade_cash.Where(x => tradeid_Open.Contains(x.TradeId) && x.ValidState != "InValid" && x.Action == ClientCashInCashOut.系统操作_期权费).ToList();
|
|
trade_cash_Open.ForEach(x =>
|
|
{
|
|
x.CurrencyRate = CurrencyRate;
|
|
x.OptDate = DateTime.Now;
|
|
x.OptName = UserName;
|
|
x.OptId = UserId;
|
|
});
|
|
}
|
|
|
|
//平仓
|
|
var trade_cash_swap = DbContext.trade_cash_swap.Where(x => idSet.Contains(x.FlowId ?? 0)).ToList();
|
|
if (trade_cash_swap.Any())
|
|
{
|
|
List<TradeAuditLog> tradeAudits = new List<TradeAuditLog>();
|
|
trade_cash_swap.ForEach(x =>
|
|
{
|
|
x.GetAmount = x.GetInitialAmount + (x.GetExtraAmount ?? 0) * CurrencyRate + (x.GetCostFee ?? 0);
|
|
x.PayAmount = x.PayInitialAmount + (x.PayExtraAmount ?? 0) * CurrencyRate + (x.PayCostFee ?? 0);
|
|
});
|
|
var trade_cash_id_Un = trade_cash_swap.Select(x => x.TradeCashId).ToHashSet();
|
|
var trade_cash_Un = DbContext.trade_cash.Where(x => trade_cash_id_Un.Contains(x.id) && x.ValidState != "InValid" && x.Action != ClientCashInCashOut.系统操作_期权费).ToList();
|
|
foreach (var item in trade_cash_Un)
|
|
{
|
|
var changsStr = "trade_cash.id:" + item.id + "; 汇率:" + (item.CurrencyRate ?? 0).ToString("0.0000") + "改为" + CurrencyRate.ToString("0.0000");
|
|
TradeAuditLog log = new TradeAuditLog()
|
|
{
|
|
TradeId = item.TradeId,
|
|
AuditFlag = TradeAuditFlag.operation,
|
|
OptType = "修改平仓汇率",
|
|
Changes = changsStr,
|
|
DataType = "00",
|
|
OptId = UserId,
|
|
OptName = UserName,
|
|
OptDate = OptDate
|
|
};
|
|
tradeAudits.Add(log);
|
|
item.CurrencyRate = CurrencyRate;
|
|
item.Amount = (item.QuoteAmount ?? 0) * CurrencyRate;
|
|
item.OptDate = DateTime.Now;
|
|
item.OptName = UserName;
|
|
item.OptId = UserId;
|
|
}
|
|
|
|
var ClientCashInCashOuts = DbContext.ClientCashInCashOut.Where(x => trade_cash_id_Un.Contains(x.TradeCashId)).ToList();
|
|
ClientCashInCashOuts.ForEach(x =>
|
|
{
|
|
var Amount = trade_cash_Un.FirstOrDefault(y => y.id == x.TradeCashId).Amount;
|
|
x.Money = -Amount;
|
|
});
|
|
var trade_cash_detail = DbContext.trade_cash_detail.Where(x => trade_cash_id_Un.Contains(x.TradeCashId)).ToList();
|
|
trade_cash_detail.ForEach(x =>
|
|
{
|
|
x.Amount = (x.QuoteAmount ?? 0) * CurrencyRate;
|
|
x.OptDate = DateTime.Now;
|
|
x.OptName = UserName;
|
|
x.OptId = UserId;
|
|
});
|
|
DbContext.TradeAuditLog.AddRange(tradeAudits);
|
|
}
|
|
DbContext.SaveChanges();
|
|
trans.Commit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|