232 lines
8.6 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|