Files
zszq-trs/YLErpDAL/Modules/SuperviseReportModule/ChangJiangReport/Service/SuperviseReportPositionService.cs
T
2024-05-09 14:06:26 +08:00

345 lines
15 KiB
C#

using BaseOUDAL;
using MathNet.Numerics;
using System.Linq.Dynamic.Core;
using YLErp.Commons;
using YLErp.Model;
using YLErp.Modules.DataProviderModule;
namespace YLErp.Modules.SuperviseReportModule.ChangJiangReport.Service
{
public class SuperviseReportPositionService : YLBaseService
{
public SuperviseReportPositionService(OptUserInfo userInfo) : base(userInfo)
{
}
public SuperviseReportPositionService(YLBaseService baseService) : base(baseService)
{
}
/// <summary>
/// 从数据库中查询场外业务持仓信息
/// <para>长江数据采集用</para>
/// </summary>
public SearchListResult<SupervisePositionDbModel> SearchSuperviseReportList(SuperviseReportReq req)
{
if (string.IsNullOrWhiteSpace(req.sidx)) { req.sidx = nameof(SupervisePositionDbModel.id); }
var query = from db in DbContext.SuperviseReportPosition
where db.ValueDate == req.ValueDate
select db;
switch (req.DataSource)
{
case "不为零":
query = query.Where(O => !(O.DeltaCash == 0 && O.GammaCash == 0 && O.HoldCash == 0 && O.PositionPnl == 0 && O.StockEqvNotional == 0 && O.TradePrice == 0));
break;
case "全量":
default:
break;
}
return query.ToSearchList(req);
}
/// <summary>
/// 保存场外业务持仓信息到数据库
/// <para>长江数据采集用</para>
/// </summary>
/// <param name="valueDate">数据日期</param>
public int SaveReportData(DateTime valueDate, string exposureDataSourceType = null, bool clearExsitings = false)
{
var models = DbContext.SuperviseReportPosition.Where(a => a.ValueDate == valueDate);
if (models.Any())
{
if (!clearExsitings)
{
return 0;
}
SupervisePositionDbModel t;
DbContext.BulkDelete<SupervisePositionDbModel>($"{nameof(t.ValueDate)}='{valueDate:yyyy-MM-dd}'");
}
IQueryable<EodTradeRisk> tRisk;
var useClosePrice = true;
switch (exposureDataSourceType)
{
default:
tRisk = DbContext.eod_trade_risk_hedgevol;
break;
case "收盘价+持仓波动率":
tRisk = DbContext.eod_trade_risk;
break;
case "结算价+持仓波动率":
useClosePrice = false;
tRisk = DbContext.eod_trade_risk_s;
break;
case "结算价+对冲波动率":
useClosePrice = false;
tRisk = DbContext.eod_trade_risk_hedgevol_s;
break;
}
//长江-依文文2022-04-20 提出需要排除新基差簿记的交易;
var bookIds = DbContext.assetunit.Where(O => O.Name.Contains("新基差")).Select(O => O.id);
var query = from position in DbContext.eod_trade_position
join risk in tRisk
on new
{
position.ValueDate,
HedgeUniqueCode = position.HedgeUniqueCode + "_" + position.TradeId,
} equals new
{
risk.ValueDate,
HedgeUniqueCode = risk.HedgeUniqueCode + "_" + risk.TradeId,
} into tempRisk
from risk in tempRisk.DefaultIfEmpty()
join trade in DbContext.eod_trade
on new
{
position.ValueDate,
position.TradeId
} equals new
{
trade.ValueDate,
trade.TradeId
} into tempTrade
from trade in tempTrade.DefaultIfEmpty()
where position.ValueDate == valueDate && position.TradeType != "现金流交易" && !bookIds.Contains(position.BookId)
select new
{
risk,
position.Pv,
position.Cost,
position.Amount,
position.BuySell,
position.TradeType,
position.PositionPnL,
position.PositionType,
position.UnderlyingCode,
position.ExchangeOptionCode,
eodTrade = trade,
};
var objs = new List<SupervisePositionDbModel>();
var positionTypes = new List<string>() { "卖出", "多头平仓", "空头开仓" };
var tradeTypes = new List<string>() { "远期", "收益互换" };
var priceProvider = new EodPriceProvider(valueDate, isDiviendPrice: false);
foreach (var item in query)
{
var trade = item.eodTrade?.trade;
var variety = DataCacheProvider.GetVariety(item.UnderlyingCode);
var obj = new SupervisePositionDbModel();
obj.ValueDate = valueDate;
if (trade == null || ConsTrade.TradeTypesForHedge.Contains(trade.TradeType))
{
obj.Trade_Number = "";
priceProvider.TryGetEodPrice(item.UnderlyingCode, out var eodPrice);
var price = eodPrice?.GetPrice(SettlementTypeEnum.SettlePrice) ?? 0;
obj.StockEqvNotional = Math.Abs(price * item.Amount);
obj.BusinessType = "场外期权成交自主对冲";
obj.TradeType = item.TradeType;
obj.ClientName = variety.TradingMarket;
obj.DeltaCash = item.risk?.DeltaCash ?? 0;
if (item.TradeType == "场内期权")
{
var exchangeOptionInfo = DataCacheProvider.GetExchangeListOptionDataSource().GetData(item.ExchangeOptionCode);//ExchangeOptionCode场内标的
obj.StockEqvNotional = Math.Abs(exchangeOptionInfo.Strike * item.Amount);
if (positionTypes.Contains(item.BuySell))
{
obj.BuySell = "卖出";
obj.HoldCash = obj.StockEqvNotional * variety.Margin ?? 0;
}
else
{
obj.BuySell = "买入";
obj.HoldCash = 0;
}
obj.TradePrice = -item.Cost;
}
else
{
obj.HoldCash = obj.StockEqvNotional * variety.Margin ?? 0;
obj.Amount = Math.Abs(item.Amount);
if (useClosePrice)
{
price = eodPrice?.GetPrice(SettlementTypeEnum.ClosePrice) ?? 0; ;
}
obj.DeltaCash = item.Amount * price;
if (item.PositionType == "long")
{
obj.BuySell = "买入";
}
else
{
obj.BuySell = "卖出";
}
obj.isFutures = true;
}
}
else
{
if (!ConsTrade.LiveTradeStatusList.Contains(trade.TradeStatus))
{
continue;
}
var type = (trade.Comments?.Trim().FirstOrDefault() ?? '0').ToString();
//1.套利和通道业务
//2.场外期权成交自主对冲
//3.商业类和政策类保险 + 期货
//4.交易所项目;
//5.融资业务
switch (type)
{
case "1":
obj.BusinessType = "套利业务";
break;
case "3":
obj.BusinessType = "商业类和政策类保险 + 期货";
break;
case "4":
obj.BusinessType = "交易所项目";
break;
case "5":
obj.BusinessType = "其他业务";
break;
case "2":
default:
obj.BusinessType = "场外期权成交自主对冲";
break;
}
obj.Trade_Number = trade.TradeNumber;
obj.ClientName = trade.ClientName;
obj.BuySell = trade.BuySell;
if (tradeTypes.Contains(trade.TradeType))
{
obj.TradeType = trade.StructureType ?? trade.TradeType;
}
else
{
obj.TradeType = trade.ExerciseModeCn + trade.OptionType;
}
var strike = (trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike) ?? 0;
if (trade.TradeType == "收益互换")
{
strike = trade.SpotPrice ?? 0;
}
obj.StockEqvNotional = strike * trade.Notional;
obj.TradeId = trade.id;
obj.TradePrice = (trade.TradePrice * (trade.StockEqvNotional / trade.OriginalStockEqvNotional) * (trade.BuySell == "买入" ? -1 : 1)) ?? 0;
obj.DeltaCash = item.risk?.DeltaCash ?? 0;
}
obj.Project = $"{variety.VarietyName}{obj.BusinessType}";
obj.VarietyCode = variety.VarietyCode;
obj.UnderlyingCode = item.UnderlyingCode;
obj.PositionPnl = item.PositionPnL;
obj.GammaCash = item.risk?.GammaCash ?? 0;
obj.ExchangeOptionCode = item.ExchangeOptionCode;
objs.Add(obj);
}
var listGroup = objs.GroupBy(O => $"{O.Project}_{O.ClientName}_{O.BuySell}_{O.TradeType}_{O.ExchangeOptionCode ?? O.UnderlyingCode}_{O.TradeId}")
.ToDictionary(K => K.Key);
var futureAmountInfos = new Dictionary<string, SupervisePositionDbModel>();
var dict =
objs.GroupBy(O => $"{O.Project}_{O.ClientName}_{O.BuySell}_{O.TradeType}_{O.ExchangeOptionCode ?? O.UnderlyingCode}_{O.TradeId}")
.ToDictionary(K => K.Key,
V =>
{
var obj = V.First();
var i = 0;
V.ToList().ForEach(O =>
{
i++;
if (i == 1)
{ return; }
obj.StockEqvNotional += O.StockEqvNotional;
obj.TradePrice += O.TradePrice;
obj.PositionPnl += O.PositionPnl;
if (O.isFutures)
{
obj.HoldCash += O.HoldCash;
obj.Amount += O.Amount;
}
else if (O.TradeType == "场内期权")
{
obj.HoldCash += O.HoldCash;
}
obj.DeltaCash += O.DeltaCash;
obj.GammaCash += O.GammaCash;
});
if (obj.isFutures)
{
if (!futureAmountInfos.ContainsKey(obj.UnderlyingCode))
{
futureAmountInfos[obj.UnderlyingCode] = obj;
return obj;
}
if (futureAmountInfos[obj.UnderlyingCode].Amount > obj.Amount)
{
obj.HoldCash = 0;
}
else
{
futureAmountInfos[obj.UnderlyingCode].HoldCash = 0;
}
}
obj.HoldCash = OtcFormatHelper.FormatValue(obj.HoldCash, 6);
obj.TradePrice = OtcFormatHelper.FormatValue(obj.TradePrice, 6);
obj.StockEqvNotional = OtcFormatHelper.FormatValue(obj.StockEqvNotional, 6);
obj.PositionPnl = OtcFormatHelper.FormatValue(obj.PositionPnl, 6);
obj.DeltaCash = OtcFormatHelper.FormatValue(obj.DeltaCash, 6);
obj.GammaCash = OtcFormatHelper.FormatValue(obj.GammaCash, 6);
return obj;
});
var list = dict.Values.OrderBy(O => $"{O.Project}_{O.ClientName}_{O.BuySell}_{O.TradeType}_{O.ExchangeOptionCode ?? O.UnderlyingCode}_{O.TradeId}").ToList();
if (list.Any())
{
DbContext.SuperviseReportPosition.AddRange(list);
return DbContext.SaveChanges();
}
return 0;
}
public void BatchSupervisePosition(List<int> Ids, DateTime ValueDate, bool IsAll, string Type)
{
var predicate = PredicateBuilder.True<SupervisePositionDbModel>().And(a => a.ValueDate == ValueDate);
if (!IsAll)//非全选
{
predicate = predicate.And(a => Ids.Contains(a.id));
}
using (var db = DbContextFactory.GetYLDbContext())
{
var clietnCashs = db.SuperviseReportPosition.Where(predicate);
if (clietnCashs.Any())
{
if (Type == "update")//更新确认状态
{
foreach (var item in clietnCashs)
{
item.Status = true;
}
}
else
{
db.SuperviseReportPosition.RemoveRange(clietnCashs);
}
}
else
{
throw new ServiceException("没有数据进行批量操作");
}
db.SaveChanges();
}
}
}
}