using BaseOUDAL;
using Dapper;
using YLErp.BLL;
using YLErp.DBModels.Consts;
using YLErp.Model;
using YLErp.Model.Enum;
using YLErp.Modules.SalesModule;
using YLErp.Modules.TagModule;
using YLErp.Modules.TradeModule.OrderModule;
using YLErp.QdpModule;
namespace YLErp.Modules.TradeModule.ForwardModule
{
///
/// 远期交易服务
///
public class TradeForwardService : TradeServiceBase
{
public TradeForwardService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 查询trade
///
public SearchListResult SearchList(TradeReq req, bool isUnionToday = false, bool isExerciseDateReport = false)
{
var query = CreateTradeQuery(req, isUnionToday, isExerciseDateReport);
var gsum = new tradeGridSum();
if (query.Where(x => x.TradeStatus != "已执行" && x.TradeStatus != "已到期" && x.TradeStatus != "已平仓").Any())
{
gsum.TradeAmountSum = query.Where(x => x.TradeStatus != "已执行" && x.TradeStatus != "已到期" && x.TradeStatus != "已平仓")?.Sum(q => q.TradeAmount);
}
var retListResult = query.ToSearchList(req);
retListResult.Sum = gsum;
//获取销售提成信息
foreach (var item in retListResult.rows)
{
item.SalesCommission = new SalesCommissionDataService(OptUser).GetTradeCommissionInfo(item.id);
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && item.SalesCommission?.Commission != null)
{
item.SalesCommission.Commission = item.SalesCommission.Commission * item.SalesCommission.SalesIds.Count();
}
item.UnderlyingName = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(item.UnderlyingCode).UnderlyingName;
}
return retListResult;
}
private IQueryable CreateTradeQuery(TradeReq req, bool isUnionToday = false, bool isExerciseDateReport = false)
{
var predicate = PredicateBuilder.Create(t => t.ValidState != "InValid" && t.TradeType == "远期");
if (req.UserAssets != null && req.UserClients != null)
{
predicate = predicate.And(t => req.UserAssets.Contains(t.AssetId) || req.UserClients.Contains(t.ClientId));
}
var query = DbContext.trade.Where(predicate);
if (!string.IsNullOrEmpty(req.ContractCode))
{
query = from source in query
join tcrConfirm in DbContext.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid) on new { id = source.ParentTradeId > 0 ? source.ParentTradeId : source.id } equals new { id = tcrConfirm.TradeId } into tcrConfirms
from tcrConfirm in tcrConfirms.DefaultIfEmpty()
where tcrConfirm.ContractCode.Contains(req.ContractCode)
select source;
}
if (!string.IsNullOrEmpty(req.UnderlyingAssetClass))
{
query = query.Where(d => d.UnderlyingAssetClass.Contains(req.UnderlyingAssetClass));
}
if (!string.IsNullOrEmpty(req.UnderlyingInstrumentTypes))
{
query = query.Where(d => req.UnderlyingInstrumentTypesList.Contains(d.UnderlyingInstrumentType));
}
if (!string.IsNullOrEmpty(req.OptIds))
{
query = query.Where(d => req.OptIdsList.Contains(d.OptId + ""));
}
if (!string.IsNullOrEmpty(req.Comments))
{
query = query.Where(d => d.Comments.Contains(req.Comments));
}
if (!string.IsNullOrEmpty(req.UnderlyingIds))
{
query = query.Where(d => req.UnderlyingIdsInt.Contains(d.UnderlyingId));
}
if (!string.IsNullOrEmpty(req.TradeIds))
{
query = query.Where(d => req.TradeIdList.Contains(d.id));
}
//获取当日成交的数据
//当日成交包括操作日期和交易日为当前系统日期的数据
if (req.TabIndex == (int)TradeTabIndexEnum.今日成交)
{
var optDateStart = valuedateBLL.ValueDate;
var optDateEnd = valuedateBLL.ValueDate.AddDays(1);
var tradeDateStart = valuedateBLL.ValueDate;
var tradeDateEnd = valuedateBLL.ValueDate.AddDays(1);
query = query.Where(d => (d.TradeDate >= tradeDateStart && d.TradeDate < tradeDateEnd) || (d.OptDate >= optDateStart && d.OptDate < tradeDateEnd));
}
else
{
if (req.TradeDateStart != DateTime.MinValue)
{
query = query.Where(d => d.TradeDate >= req.TradeDateStart);
}
if (req.TradeDateEnd != DateTime.MinValue)
{
var TradeDateTemp = req.TradeDateEnd.AddDays(1);
query = query.Where(d => d.TradeDate < TradeDateTemp);
}
if (req.OptDateStart != DateTime.MinValue)
{
query = query.Where(d => d.OptDate >= req.OptDateStart);
}
if (req.OptDateEnd != DateTime.MinValue)
{
var OptDateTemp = req.OptDateEnd.AddDays(1);
query = query.Where(d => d.OptDate < OptDateTemp);
}
}
//获取当日到期日数据
if (req.TabIndex == (int)TradeTabIndexEnum.今日到期)
{
query = query.Where(d => d.ExerciseDate == valuedateBLL.ValueDate);
}
//获取明日到期日数据
else if (req.TabIndex == (int)TradeTabIndexEnum.明日到期)
{
var tommorow = QdpCalendarHelper.GetNonHoliday(valuedateBLL.ValueDate.AddDays(1));
query = query.Where(d => d.ExerciseDate == tommorow);
}
else
{
if (req.ExerciseDateEnd == null)
{
req.ExerciseDateEnd = DateTime.MaxValue;
}
if (req.ExerciseDateStart == null)
{
req.ExerciseDateStart = DateTime.MinValue;
}
if (isExerciseDateReport)
{
query = query.Where(d => d.ExerciseDate >= req.ExerciseDateStart && d.ExerciseDate <= req.ExerciseDateEnd);
}
else
{
query = query.Where(d => d.ExerciseDate == null || (d.ExerciseDate >= req.ExerciseDateStart && d.ExerciseDate <= req.ExerciseDateEnd));
}
}
if (!string.IsNullOrEmpty(req.TraderNames))
{
query = query.Where(d => req.TraderNamesList.Contains(d.TraderId));
}
if (!string.IsNullOrEmpty(req.TradeNumber))
{
query = query.Where(d => d.TradeNumber == req.TradeNumber || d.TradeNumber.Contains(req.TradeNumber));
}
if (req.ClientId != null)
{
query = query.Where(d => d.ClientId == req.ClientId);
}
if (!string.IsNullOrEmpty(req.ClientName))
{
query = query.Where(d => d.ClientName.Contains(req.ClientName));
}
if (!string.IsNullOrEmpty(req.UnderlyingCode))
{
query = query.Where(d => d.UnderlyingCode.Contains(req.UnderlyingCode));
}
if (req.UnderlyingCodeList != null)
{
query = query.Where(d => req.UnderlyingCodeList.Contains(d.UnderlyingCode));
}
if (req.UnderlyingId != null)
{
query = query.Where(d => d.UnderlyingId == req.UnderlyingId);
}
if (!string.IsNullOrEmpty(req.BuySell))
{
query = query.Where(d => d.BuySell.Contains(req.BuySell));
}
if (!string.IsNullOrEmpty(req.OptionType))
{
query = query.Where(d => d.OptionType == req.OptionType);
}
if (req.StartDateStart != DateTime.MinValue)
{
query = query.Where(d => d.StartDate >= req.StartDateStart);
}
if (req.StartDateEnd != DateTime.MinValue)
{
var StartDateTemp = req.StartDateEnd.AddDays(1);
query = query.Where(d => d.StartDate < StartDateTemp);
}
//过滤已平仓,已到期,已执行数据
else if (req.TabIndex == (int)TradeTabIndexEnum.今日到期 || req.TabIndex == (int)TradeTabIndexEnum.明日到期)
{
query = query.Where(d => d.TradeStatus != ConsTrade.已平仓 && d.TradeStatus != ConsTrade.已到期 && d.TradeStatus != ConsTrade.已执行);
}
if (!string.IsNullOrEmpty(req.TradeStatus))
{
var statuses = req.TradeStatus.Split(',').ToList();
query = query.Where(d => statuses.Contains(d.TradeStatus));
}
if (req.TradeStatusList != null)
{
query = query.Where(d => req.TradeStatusList.Contains(d.TradeStatus));
}
if (req.AssetIdList.Any())
{
query = query.Where(d => req.AssetIdList.Contains(d.AssetId));
}
if (req.ClientIdsInt.Any())
{
query = query.Where(d => req.ClientIdsInt.Contains(d.ClientId));
}
if (!string.IsNullOrEmpty(req.OptName))
{
query = query.Where(d => d.OptName.Contains(req.OptName));
}
if (req.TagIds != null && req.TagIds.Count > 0)
{
var tradeTagIdQuery = from tt in DbContext.trade_tag
where req.TagIds.Contains(tt.TagId)
select tt.TradeId;
query = query.Where(p => tradeTagIdQuery.Contains(p.id));
}
query = query.Where(d => !d.ValidState.Equals("InValid"));
if (string.IsNullOrEmpty(req.sidx))
{
req.sidx = "id";
req.sord = "desc";
}
if (isUnionToday)
{
var todaybalanceStatus = new List { "已到期", "已执行", "已平仓" };
var curDate = valuedateBLL.ValueDate;
//+ trade今天被exercise/expire的option. 排序按照optDate,从新到旧排
query = query.Union(from s in DbContext.trade where s.ClientId == req.ClientId && todaybalanceStatus.Contains(s.TradeStatus) && s.OptDate >= curDate select s);
}
query = query.OrderByDescending(s => s.OptDate);
return query;
}
///
/// 获取数据详情
///
public OtcTradeForward GetDetail(int id)
{
var tdResult = DbContext.Database.GetDbConnection().Query("select * from trade where id=" + id).FirstOrDefault();
if (tdResult == null)
{
return null;
}
var forward = DbContext.trade_forward.FirstOrDefault(n => n.TradeId == id);
if (forward == null)
{
throw new ServiceException("交易数据损坏,扩展数据未找到");
}
YLAutoMapper.Map(forward, tdResult);
tdResult.MetaDic = new TradeMetaService(this).GetTradeMeta(tdResult.id);
if (!tdResult.MetaDic.ContainsKey("IsSupplyForwardValue"))
{
if (PS.Config.ErpElement.ForwardValueIsSupplyOrPay == YLErp.Configuration.Enums.ForwardValueIsSupplyOrPay.Type2)
{
tdResult.MetaDic.Add("IsSupplyForwardValue", "-1");
}
else
{
tdResult.MetaDic.Add("IsSupplyForwardValue", "0");
}
}
tdResult.VarietyId = UnderlyingDataProvider.GetUnderlying(tdResult.UnderlyingCode)?.UnderlyingTypeId ?? 0;
var un = UnderlyingDataProvider.GetUnderlying(tdResult.UnderlyingId);
if (un != null && un.IsSynthetic() && !tdResult.MetaDic.ContainsKey("组合标的"))
{
var synthetic = UnderlyingDataProvider.GetSyntheticUnderlying(tdResult.UnderlyingCode);
if (synthetic != null)
{
tdResult.MetaDic["组合标的"] = synthetic.GetSyntheticPriceModel().ToJson();
}
}
tdResult.SalesCommission = new SalesCommissionDataService(this).GetTradeCommissionInfo(tdResult.id);
return tdResult;
}
///
/// 删除交易
///
public void InValidTrade(int id)
{
var r = DbContext.trade.Find(id);
if (r == null)
{
throw new ServiceException("找不到交易信息");
}
r.ValidState = ConsGlobal.InValid;
if (!string.IsNullOrWhiteSpace(r.TradeNumber))
{
var contractBll = new TradeContractBLL(UserId, UserName);
contractBll.DeleteConfirmBook(r.id);
if (r.TradeNumber.StartsWith("CW"))
{
r.TradeNumber = r.TradeNumber.Replace("CW", "XX");
}
else //if (PS.Config.Is光大光子)
{
r.TradeNumber = r.TradeNumber.Insert(0, "XX");
}
}
//设置相关提成失效
new SalesCommissionDataService(OptUser).SetCommissionInVaild(r.id);
RemoveEodTradeAndFutureInfo(false, r.id, DateTime.MinValue);
new DealModule.TradeConfirmService(this).EditReportStatus(r.id);
AddTradeOperationHistoryAndSetParentTradeInfo(false, r, "删除交易");
//删除所有trade关联表中数据
DbContext.SaveChanges();
}
///
/// 保存交易
///
public trade SaveData(OtcTradeForward req)
{
req.TradeType = "远期";
var td = TradeConverter.ConvertForward(req);
td = new TradeSaveService(this).SaveTrade(td, TradeSourceEnum.系统交易);
var variety = UnderlyingDataProvider.GetVariety(td.UnderlyingCode);
if (variety != null)
{
td.QuoteUnit = variety.QuoteUnit;
td.QuoteUnitSingle = variety.QuoteUnitSingle;
}
using (var tagService = new TagService(OptUser))
{
tagService.SetTradeTagForTradeEdit(new TagModule.Dto.SetTradeTagForTradeEditRequest
{
TradeId = td.id,
Tags = req.Tags
});
}
return td;
}
public TradeCheckModel GetCheckTrade(int? id)
{
var service = new TradeMetaService(this);
var model = new TradeCheckModel
{
Trade = DbContext.trade.FirstOrDefault(n => n.id == id)
};
if (model.Trade == null)
{
throw new ServiceException("没有找到数据");
}
var forward = DbContext.trade_forward.FirstOrDefault(t => t.TradeId == model.Trade.id);
if (forward == null)
{
throw new ServiceException("没有找到远期数据");
}
model.Trade.trade_forward = forward;
model.UnderlyingInfo = UnderlyingDataProvider.GetUnderlying(model.Trade.UnderlyingCode);
var tradeCheck = DbContext.trade_check.FirstOrDefault(t => t.TradeId == model.Trade.id && t.ValidState != "InValid");
if (tradeCheck != null)
{
model.diffList = TradeCheckUtil.GetDiffs(model.Trade, tradeCheck.TradeModel);
model.Trade.ExerciseDate = tradeCheck.TradeModel.ExerciseDate;
model.Trade.TradeDate = tradeCheck.TradeModel.TradeDate;
model.Trade.SettlementDate = tradeCheck.TradeModel.SettlementDate;
model.Trade.Strike = tradeCheck.TradeModel.Strike;
model.Trade.TradeAmount = tradeCheck.TradeModel.TradeAmount;
model.Trade.TradeSinglePrice = tradeCheck.TradeModel.TradeSinglePrice;
model.Trade.TradeDate = tradeCheck.TradeModel.TradeDate;
model.Trade.SpotPrice = tradeCheck.TradeModel.SpotPrice;
model.Trade.StockEqvNotional = tradeCheck.TradeModel.StockEqvNotional;
model.Trade.TradeOpenVolatility = tradeCheck.TradeModel.TradeOpenVolatility;
model.Trade.TradeCloseVolatility = tradeCheck.TradeModel.TradeCloseVolatility;
model.Trade.NumOfSmoothingDays = tradeCheck.TradeModel.NumOfSmoothingDays;
model.Trade.TradePrice = tradeCheck.TradeModel.TradePrice;
model.Trade.BuySell = tradeCheck.TradeModel.BuySell;
model.Trade.ExerciseMode = tradeCheck.TradeModel.ExerciseMode;
model.Trade.OptionType = tradeCheck.TradeModel.OptionType;
model.Trade.SettlementType = tradeCheck.TradeModel.SettlementType;
model.Trade.Lots = tradeCheck.TradeModel.Lots;
model.Trade.SalesCommission = new SalesCommissionDataService(OptUser).GetTradeCommissionInfo(model.Trade.id);
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1")
{//计提法只支持百分比;
if (model.Trade.SalesCommission.Commission.Normalize() == 0)
{
model.Trade.SalesCommission.Commission = 1;
model.Trade.SalesCommission.CommissionFixed = false;
}
else
{
model.Trade.SalesCommission.Commission = model.Trade.SalesCommission.Commission * model.Trade.SalesCommission.SalesIds.Count();
}
}
model.Trade.NoRiskRate = tradeCheck.TradeModel.NoRiskRate;
model.Trade.trade_forward = tradeCheck.TradeModel.trade_forward;
model.Trade.MetaDic = service.GetTradeMeta(model.Trade.id);
if (model.Trade.MetaDic.ContainsKey("ActualExerciseDate") && DateTime.TryParse(model.Trade.MetaDic["ActualExerciseDate"],out DateTime ActualExerciseDate))
{
model.Trade.ActualExerciseDate = ActualExerciseDate;
}
return model;
}
model.Trade.ExerciseDate = null;
model.Trade.Strike = null;
model.Trade.TradeAmount = 0;
model.Trade.TradeSinglePrice = null;
model.Trade.TradeDate = null;
model.Trade.SpotPrice = null;
model.Trade.StockEqvNotional = 0;
model.Trade.TradeOpenVolatility = null;
model.Trade.TradeCloseVolatility = null;
model.Trade.NumOfSmoothingDays = null;
model.Trade.TradePrice = null;
model.Trade.BuySell = null;
model.Trade.ExerciseMode = null;
model.Trade.OptionType = null;
model.Trade.SettlementType = 0;
model.Trade.Lots = null;
model.Trade.SalesCommission = new SalesCommissionDataService(OptUser).GetTradeCommissionInfo(model.Trade.id);
if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1")
{//计提法只支持百分比;
if (model.Trade.SalesCommission.Commission.Normalize() == 0)
{
model.Trade.SalesCommission.Commission = 1;
model.Trade.SalesCommission.CommissionFixed = false;
}
else
{
model.Trade.SalesCommission.Commission = model.Trade.SalesCommission.Commission * model.Trade.SalesCommission.SalesIds.Count();
}
}
//将无风险利率和年华预付金利率数值从小数转换百分数
model.Trade.NoRiskRate *= 100;
forward.AnnualMarginRate *= 100;
forward.OpenCommission = 0;
model.Trade.trade_forward = forward;
model.Trade.MetaDic = service.GetTradeMeta(model.Trade.id);
if (model.Trade.MetaDic.ContainsKey("ActualExerciseDate") && DateTime.TryParse(model.Trade.MetaDic["ActualExerciseDate"], out DateTime newActualExerciseDate))
{
model.Trade.ActualExerciseDate = newActualExerciseDate;
}
return model;
}
}
public class TradeCheckModel
{
///
/// 交易信息
///
public trade Trade { get; set; }
///
/// 标的信息
///
public underlying_manager UnderlyingInfo { get; set; }
public HashSet diffList { get; set; }
///
/// 是否显示初始预付金
///
public bool ShowInitialMargin => valuedateBLL.SystemDate.CanSetInitialMargin;
}
}