Files
zszq-trs/YLErpDAL/Modules/ExchangeTradeModule/ExchangeTradeImportService.cs
T

232 lines
8.6 KiB
C#

using System.Data;
using YLErp.BLL;
using YLErp.Commons;
using YLErp.DBModels.Enums;
using YLErp.Modules.CalculationModule;
namespace YLErp.Modules.ExchangeTradeModule
{
/// <summary>
/// 场内交易导入服务
/// </summary>
public class ExchangeTradeImportService : ExchangeTradeSaveServiceBase
{
public ExchangeTradeImportService(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 导入交易
/// </summary>
public int ImportExcel(Stream streamIn, out int TotalNum, out int SuccessNum)
{
var rowIndex = 0;
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);
rowIndex = 1;
TotalNum = table.Rows.Count;
var tradePositions = new List<ExchangeTrade>();
foreach (var row in table.Rows.Cast<DataRow>())
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
continue;
}
reader.SetDataRow(row);
var dto = MapTrade(reader);
var td = PrepareSave(dto);
DbContext.ExchangeTrade.Add(td);
ExchangeTrade tdp;
if (string.IsNullOrWhiteSpace(td.OptionCode))
{
tdp = tradePositions.Where(o => o.AssetBookId == td.AssetBookId && o.TradeType == td.TradeType && o.OptionCode == null && o.UnderlyingCode == td.UnderlyingCode && o.TradeSide.Substring(0, 2) == td.TradeSide.Substring(0, 2)).FirstOrDefault();
}
else
{
tdp = tradePositions.Where(o => o.AssetBookId == td.AssetBookId && o.TradeType == td.TradeType && td.OptionCode == o.OptionCode && o.UnderlyingCode == td.UnderlyingCode && o.TradeSide.Substring(0, 2) == td.TradeSide.Substring(0, 2)).FirstOrDefault();
}
var sign = TradeCalcHelper.GetSign(td.TradeSide);
//汇总exchangeTrade
if (tdp != null)
{
tdp.TradeLots = td.TradeLots * sign + tdp.TradeLots;
tdp.Notional = td.Notional * sign + tdp.Notional;
tdp.TradeSinglePrice += td.TradeLots * td.TradeSinglePrice * sign;
tdp.Commission += td.Commission;
}
else
{
tdp = td.Clone();
tdp.TradeSide = td.TradeSide.StartsWith("多头") ? "多头开仓" : "空头平仓";
tdp.TradeLots *= sign;
tdp.Notional *= sign;
tdp.TradeSinglePrice *= tdp.TradeLots;
tradePositions.Add(tdp);
}
}
foreach (var td in tradePositions)
{
td.TradeSinglePrice = Math.Abs(td.TradeLots) > 1e-5 ? td.TradeSinglePrice / td.TradeLots : 0;
SaveExchangeTradePosition(td);
}
SuccessNum = TotalNum;
return DbContext.SaveChanges();
}
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);
}
}
//将req转换交易对象
private ExchangeTrade PrepareSave(ExchangeTradeDto dto)
{
SetDBModelOpt(dto);
var contractSize = 0d;
if (dto.TradeType == "场内期权")
{
SetTradeOptionInfo(dto, dto.UnderlyingCode, out var option);
contractSize = option.ContractSize;
}
//标的信息
SetTradeUnderlyingInfo(dto, dto.UnderlyingCode, out var um);
//验证股票结构类型,只能股票标的,商品期货只能期货
switch (dto.TradeType)
{
case "股票":
if (!um.CalcTypeIsStock())
{
throw new ServiceException("股票交易类型必须使用股票标的");
}
break;
case "商品期货":
if (!um.IsFutures())
{
throw new ServiceException("商品期货交易类型必须填写期货标的");
}
break;
case "商品现货":
if (!um.IsCommoditySpot())
{
throw new ServiceException("商品现货交易类型必须填写商品现货标的");
}
break;
case "信用债":
case "利率债":
case "其它债券":
if (!um.IsBond())
{
throw new ServiceException(dto.TradeType+"交易类型必须填写债券标的");
}
dto.TradeSinglePrice /= 100;
break;
}
//交易数量
SetTradeLotsInfo(dto, dto.TradeLots, contractSize < 1 ? um.ContractSize : contractSize, um.UnderlyingTypeId);
//簿记和对冲账户
SetAssetAndExchangeAccount(dto, dto.AssetBookName, dto.ExchangeAccountCode, um.UnderlyingTypeId);
//交易员信息
dto.TraderId = UserId;
dto.TraderName = UserName;
dto.TradeSource = "导入交易";
dto.IsValid = true;
dto.CreateTime = DateTime.Now;
return YLAutoMapper.Map<ExchangeTrade>(dto);
}
private ExchangeTradeDto MapTrade(DataRowReader reader)
{
var dto = new ExchangeTradeDto
{
TradeType = reader.GetString("交易类型", true)
};
dto.TradeType = CheckTradeType(dto.TradeType);
dto.TradeNumber = reader.GetString("交易编号", false);
if (string.IsNullOrWhiteSpace(dto.TradeNumber))
{
dto.TradeNumber = DateTime.Now.ToString("yyyyMMddHHmmssfff");
}
dto.AssetBookName = reader.GetString("簿记账户", false);
dto.ExchangeAccountCode = reader.GetString("对冲账户", false);
if (string.IsNullOrWhiteSpace(dto.AssetBookName) && string.IsNullOrWhiteSpace(dto.ExchangeAccountCode))
{
throw new ServiceException("簿记账户和对冲账户 至少填写一个");
}
dto.UnderlyingCode = reader.GetString("交易标的", true).ToUpperInvariant();
dto.TradeSide = reader.GetString("交易方向", true);
if (!ConsGlobal.TradeSide.IsValid(dto.TradeSide))
{
throw new ServiceException("交易方向未能识别:" + dto.TradeSide);
}
dto.TradeDate = reader.GetDate("交易日期", true).Value;
if (dto.TradeDate > valuedateBLL.ValueDate)
{
throw new ServiceException("交易日期 不能大于系统日期:" + valuedateBLL.ValueDate.ToString("yyyy-MM-dd"));
}
dto.TradeLots = Math.Abs(reader.GetDouble("成交手数", true).Value);
dto.TradeSinglePrice = reader.GetDouble("成交单价", true).Value;
if (dto.TradeLots < 1e-5)
{
throw new ServiceException("成交手数 必须大于0:" + dto.TradeLots);
}
var commission = reader.GetDouble("手续费", false);
if (commission.HasValue)
{
dto.Commission = commission.Value;
dto.CommissionType = CommissionType.手动录入;
}
else
{
dto.CommissionType = CommissionType.系统计算;
}
dto.Comments = reader.GetString("备注", false);
return dto;
}
}
}