using BaseOUDAL; using YLErp.DBModels.Enums; using YLErp.DBModels.Helpers; using YLErp.Model.Enum; namespace YLErp.Modules.ExchangeTradeModule { /// /// 标的交易保存服务 /// public class ExchangeTradeSaveService : ExchangeTradeSaveServiceBase { public ExchangeTradeSaveService(YLBaseService baseService) : base(baseService) { } public ExchangeTradeSaveService(OptUserInfo userInfo) : base(userInfo) { } public ExchangeTrade Save(ExchangeTrade req, TradeSourceEnum source) { var isAddNew = req.id == 0; Prepare(req, source, isAddNew); if (isAddNew) { DbContext.ExchangeTrade.Add(req); SaveExchangeTradePosition(req, null); DbContext.SaveChanges(); return req; } else { var dbTrade = DbContext.ExchangeTrade.Find(req.id); if (dbTrade == null) { throw new ServiceException("保存失败,数据不存在"); } req.CreateTime = dbTrade.CreateTime; req.TradeNumber = dbTrade.TradeNumber; if (req.IsValid) { SaveExchangeTradePosition(req, dbTrade); } else { InValidTrade(req.id); } UpdateEntity(dbTrade, req); DbContext.SaveChanges(); return dbTrade; } } private void Prepare(ExchangeTrade req, TradeSourceEnum source, bool isAddNew) { if (string.IsNullOrWhiteSpace(req.TradeType)) { throw new ServiceException("交易类型 必须填写"); } if (!ConsTrade.TradeTypesForHedge.Contains(req.TradeType)&&!ConsTrade.BondTypeList.Contains(req.TradeType)) { throw new ServiceException("程序错误,标的交易类型不支持:" + req.TradeType); } //准备交易保存 PrepareSave(req); req.OptId = UserId; req.OptName = UserName; req.OptDate = OptDate; if (isAddNew) { req.TradeSource = source.ToString(); if (string.IsNullOrWhiteSpace(req.TradeNumber)) { req.TradeNumber = DateTime.Now.ToString("yyyyMMddHHmmssfff"); } req.IsValid = true; req.CreateTime = DateTime.Now; } } //准备交易基础信息(标的、簿记、交易日期) private void PrepareSave(ExchangeTrade req) { if (req.TradeDate.Year < 2000) { throw new ServiceException("交易日期 填写错误:" + req.TradeDate.ToString("yyyy-MM-dd")); } ExchangeListOption exOption = null; if (req.TradeType == "场内期权") { SetTradeOptionInfo(req, req.OptionCode, out exOption); } //标的信息 SetTradeUnderlyingInfo(req, req.UnderlyingCode, out var um); //-------------------------------------- // 簿记帐户 //-------------------------------------- if (req.AssetBookId < 1) { throw new ServiceException("请选择簿记账户"); } var assetUnit = DbContext.assetunit.Where(n => n.id == req.AssetBookId) .Select(n => new AssetUnitDto { id = n.id, Name = n.Name, BookCategory = n.BookCategory, TraderIds = n.TraderIds, UserGroup = n.UserGroup }).FirstOrDefault(); if (assetUnit == null) { throw new ServiceException("簿记账户不存在"); } //-------------------------------------- // 交易员信息 //-------------------------------------- //有交易员id,通过id查名字 if (req.TraderId > 0) { req.TraderName = UserBLL.GetNameById(req.TraderId); } else { //当前登录用户作为交易员 req.TraderId = UserId; req.TraderName = UserName; } //-------------------------------------- // 对冲帐户 //-------------------------------------- if (req.ExchangeAccountId > 0) { req.ExchangeAccountCode = DbContext.exchange_account.Where(n => n.id == req.ExchangeAccountId).Select(n => n.AccountCode).FirstOrDefault(); } //-------------------------------------- // 检查交易权限 //-------------------------------------- if (req.TraderId < 1) { throw new ServiceException("请选择交易员"); } //不检查:必须是交易员角色 //不检查:交易用户组必须和簿记账户一致 //不检查:交易员不在所选簿记中,请重新选择簿记 //不检查:交易员具有交易标的的交易权限 //-------------------------------------- // 手续费 //-------------------------------------- switch (req.CommissionType) { case CommissionType.不收取: case CommissionType.系统计算: req.Commission = 0; break; default: if (req.Commission < 0) { throw new ServiceException("请填写有效的交易手续费"); } break; } //2020-09-11 改为以TradeAmount为主 if (req.TradeAmount < 1e-5) { throw new ServiceException("交易数量必须大于0"); } if (req.TradeType != "场内期权") { req.Notional = req.TradeAmount * um.CountRatio; req.TradeLots = req.Notional / um.ContractSize; } else { req.Notional = req.TradeAmount; req.TradeLots = req.Notional / (exOption.ContractSize < 1 ? um.ContractSize : exOption.ContractSize); } //验证股票结构类型,只能股票标的,商品期货只能期货 switch (req.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 "场内期权": break; } if (req.TradeType != "场内期权") { req.OptionType = string.Empty; } } /// /// 删除交易 /// public void InValidTrade(int id) { var dbTrade = DbContext.ExchangeTrade.Find(id); if (dbTrade == null) { throw new ServiceException("找不到交易信息"); } dbTrade.IsValid = false; //清除对冲交易持仓 var para = PrepareTradePositionParam(dbTrade); var dbPosition = DbContext.TradePosition.FirstOrDefault(para.predicate); if (dbPosition != null) { var dbNotional = TradeHelper.GetPositionNotional(para.tradeSide, dbTrade.Notional); dbPosition.Position -= dbNotional; dbPosition.PositionCost -= dbNotional * dbTrade.TradeSinglePrice; dbPosition.UpdateTime = OptDate; } DbContext.SaveChanges(); } } }