using YLErp.Abstract.DataProviders;
using YLErp.BLL;
using YLErp.BLL.MarginCalculation;
using YLErp.Helpers;
namespace YLErp.Modules.EodModule.SettlementModule
{
///
/// 预付金计算
///
class EodWorstClientPayableCalc : EodSettleServiceBase
{
public EodWorstClientPayableCalc(EodSettlementContextBase context) : base(context)
{
}
///
/// 预付金计算
///
public bool WorstClientPayableCalc(List tradeList, List ex_TradeSpans = null)
{
if (tradeList is null)
{
throw new ArgumentNullException(nameof(tradeList));
}
var settleDate = _context.SettleDate;
var req = new RunMarginCalculationReq(UserInfo)
{
tradeList = tradeList,
settleDate = settleDate,
CalcMarginType = Enums.CalcMarginTypeEnum.EodMargin,
volType = PS.Config.IsTradeVol ? _context.Request.VolType : _context.SystemValue.EodSettleVolMode
};
switch (PS.Config.Company)
{
case Configuration.CompanyEnum.国泰君安:
case Configuration.CompanyEnum.瑞达:
case Configuration.CompanyEnum.宏源:
case Configuration.CompanyEnum.弘业:
case Configuration.CompanyEnum.光大光子:
case Configuration.CompanyEnum.海通:
case Configuration.CompanyEnum.广期资本:
case Configuration.CompanyEnum.渤海:
case Configuration.CompanyEnum.中金:
req.PriceProvider = _context.GetEodPriceProvider().GetPriceProvider(SettlementTypeEnum.ClosePrice);
req.settlementType = SettlementTypeEnum.ClosePrice;
break;
default:
req.PriceProvider = _context.GetEodPriceProvider().GetPriceProvider(SettlementTypeEnum.SettlePrice);
req.settlementType = SettlementTypeEnum.SettlePrice;
break;
}
List tradeSpans = new List();
//试算出交易买卖方向反向的tradeSpan
List tradeSpansOtherSide = new List();
//是否单笔预付金与合计预付金计算方式不同 如果不同则调用合计预付金方法 forSingleTrade = false
if (MarginDefault.IsMarginCalcNeedSpecial(req.settleDate))
{
//远期不参与计算预付金逻辑
tradeSpans = MarginDefault.RunMarginCalculation(req.Clone(forOtherSide: false));
//试算出交易买卖方向反向的tradeSpan(目前只有国君有这个需求,做过处理)
tradeSpansOtherSide = MarginDefault.RunMarginCalculation(req.Clone(forOtherSide: true));
}
else
{
tradeSpans = MarginDefault.RunMarginCalculation(req.Clone());
}
#region 额外追保
var clientAdditionalMarginDic = new Dictionary();
var tradeSpanDic = tradeSpans.ToDictionary(t => t.TradeId, t => t.WorstCastClientPayable);
var todayNewPostionList = tradeList.Where(t => t.TradeDate == settleDate).ToList();
var clientGroups = todayNewPostionList.GroupBy(t => t.ClientId);
foreach (var group in clientGroups)
{
var todayNewClientPostionList = group.ToList();
var todayNewTradePositionMargin = Math.Min(todayNewClientPostionList.Sum(t => tradeSpanDic.ContainsKey(t.id) ? ((tradeSpanDic[t.id] ?? 0) * -1) : 0), 0);
//todo:收益互换没有OriginalNotional
var todayNewTradeInitialMargin = Math.Min(todayNewClientPostionList.Sum(t => ((t.OriginalStockEqvNotional * t.Notional / t.OriginalNotional) ?? 0) * (t.BuySell == "买入" ? -1 : 1) * underlying_managerBLL.GetUpLimit(t.UnderlyingCode)), 0);
var todayAdditionalMargin = -1 * Math.Max(Math.Abs(todayNewTradeInitialMargin) - Math.Abs(todayNewTradePositionMargin), 0);
clientAdditionalMarginDic[group.Key] = todayAdditionalMargin;
}
#endregion
var ids = tradeList.Select(l => l.id).Union(tradeSpans.Select(x => x.TradeId)).ToArray();
if (ex_TradeSpans != null)
{
ids = ids.Union(ex_TradeSpans.Select(x => x.TradeId)).ToArray();
}
if (ids.Any())
{
DbContext.BulkDelete($"{nameof(trade_span.ValueDate)}='{settleDate.ToSqlDate()}' and TradeId in ({string.Join(",", ids)})");
}
if (ex_TradeSpans != null && ex_TradeSpans.Count() > 0)
{
tradeSpans.AddRange(ex_TradeSpans);
}
if (tradeSpans != null && tradeSpans.Count > 0)
{
DbContext.trade_span.AddRange(tradeSpans);
}
DbContext.SaveChanges();
//执行客户合计
var clientMarginReq = new CalcClientMarginReq(UserInfo)
{
settleDate = settleDate,
tradeSpans = tradeSpans,
tradeSpansOtherSide = tradeSpansOtherSide,
SpanType = 0,
clientAdditionalMarginDic = clientAdditionalMarginDic,
ClientIds = _context.ClienIds
};
MarginDefault.CalcClientMargin(clientMarginReq);
return true;
}
}
}