Files
zszq-trs/YLErpDAL/BLL/EodSettlement/ClientBalanceUtility.cs
T
2025-04-23 15:37:55 +08:00

1481 lines
82 KiB
C#

using BaseOUDAL;
using YLErp.BLL.Eod;
using YLErp.DBModels.Enums;
using YLErp.Model;
using YLErp.Models;
using YLErp.Modules;
using YLErp.Modules.ClientModule;
namespace YLErp.BLL.EodSettlement
{
/// <summary>
/// 客户结算信息工具类
/// </summary>
public class ClientBalanceUtility
{
/// <summary>
/// 获取startDate至endDate 所有客户结算信息统计
/// </summary>
public static IEnumerable<ClientSettleBalance> GetAllClientBanlances(DateTime startDate, DateTime endDate, bool IsGetOuterMarginGap = false
, Abstract.IDataSource<ClientMainInfo> clientDataSource = null)
{
using var db = DbContextFactory.GetClientDbContext(null);
var clientIds = db.client.Where(s => s.ProcessStatus != "未提交").Select(n => n.id).ToList();
return GetClientBanlances(
clientIdList: clientIds,
startDate: startDate,
endDate: endDate,
IsGetOuterMarginGap: IsGetOuterMarginGap,
clientDataSource: clientDataSource);
}
/// <summary>
/// 获取startDate至endDate 客户结算信息统计
/// </summary>
public static IEnumerable<ClientSettleBalance> GetClientBanlances(List<int> clientIdList
, DateTime startDate, DateTime endDate, bool IsClientBalanceGap = false, bool IsGetOuterMarginGap = false, bool ParentFlag = false
, Abstract.IDataSource<ClientMainInfo> clientDataSource = null)
{
if (startDate > endDate)
{
throw new ArgumentException("startDate不能大于endDate");
}
if (null == clientIdList || !clientIdList.Any())
{
return Enumerable.Empty<ClientSettleBalance>();
}
var returnClientId = clientIdList[0];
if (ParentFlag)
{
clientIdList = GetSubclientId(clientIdList[0]);
}
//一些客户在下面没有关联的数据,在这里直接赋值
var dic = clientIdList.ToHashSet().ToDictionary(n => n, m => new ClientSettleBalance
{
ClientId = m,
ValueDate = endDate,
});
foreach (var clientId in clientIdList)
{
var balance = dic[clientId];
var client = DataCacheProvider.GetClientDataSource().GetData(clientId);
balance.DesirableRate = client?.DesirableRate ?? 0;
balance.CreditCanApplySwap = client?.creditCanApplySwap ?? false;
balance.ClientType = client?.SwapTradeType ?? 0;
}
if (PS.Config.Is广期资本)
{
Dictionary<int, int?> samePeerDic = null;
using (var clientDb = DbContextFactory.GetClientDbContext(null))
{
samePeerDic = clientDb.client.AsNoTracking().Where(p => clientIdList.Contains(p.id)).ToDictionary(p => p.id, p => p.SamePeer);
}
samePeerDic ??= new Dictionary<int, int?>();
foreach (var kv in dic)
{
kv.Value.SamePeer = samePeerDic.ContainsKey(kv.Key) ? samePeerDic[kv.Key] ?? 0 : 0;
}
}
if (PS.Config.Is宏源)
{
Dictionary<int, double?> ratio1Dic = null;
using (var clientDb = DbContextFactory.GetClientDbContext(null))
{
ratio1Dic = (from c in clientDb.client
join cl in clientDb.clientlevel on c.LevelId equals cl.id into t_cl
from temp in t_cl.DefaultIfEmpty()
where clientIdList.Contains(c.id)
select new { Id = c.id, Ratio1 = temp == null ? null : temp.Ratio1 }).ToDictionary(p => p.Id, p => p.Ratio1);
}
ratio1Dic ??= new Dictionary<int, double?>();
foreach (var kv in dic)
{
kv.Value.Ratio1 = ratio1Dic.ContainsKey(kv.Key) ? ratio1Dic[kv.Key] ?? 1.0 : 1.0;
}
}
var clientIdS = new List<int>();
clientIdS.AddRange(clientIdList);
using (var db = new YLContext())
{
//系统交易日
var valuedate = valuedateBLL.ValueDate;
var lastpushLog = db.push_log.Where(x => x.data_type == (int)SwapPushDataEnum.日终估值获取 && x.data_state == (int)SwapPushDataStateEnum.接收处理成功&&x.create_time> valuedate).OrderByDescending(o => o.create_time).FirstOrDefault();
//获取根据系统时间
var lastBalanceDate = EodOperationBase.GetLastSettlementDate(valuedate);
// 获取定义文件预付金率设置
var clientMarginTemplates = db.client_marginrate.Where(x => x.ValueDate <= endDate).OrderByDescending(o => o.ValueDate).AsNoTracking().ToList();
var lastDate = lastBalanceDate;
//查询历史记录
if (startDate <= lastBalanceDate)
{
if (endDate < lastBalanceDate)
{
lastDate = db.ClientBalanceDaily.Where(n => n.BalanceDate <= endDate)
.Max(n => n.BalanceDate) ?? DateTime.MinValue;
}
var sumQuery = from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate && clientIdS.Contains(t.ClientId)
select new ClientSettleBalance
{
ClientId = t.ClientId,
NetFund = t.NetFundSum ?? 0,
InFund = t.InFundSum ?? 0,
OutFund = t.OutFundSum ?? 0,
OtherFund = t.OtherFundSum ?? 0,
OptionPremium = t.OptionPremiumSum ?? 0,
OptionPremiumSwap = t.OptionPremiumSwapSum ?? 0,
SettlementBalance = t.SettlementBalanceSum ?? 0,
UnwindBalance = t.UnwindBalanceSum ?? 0,
SwapBalance = t.SwapBalanceSum ?? 0,
Coupon = t.CouponSum ?? 0,
ExerciseBalance = t.ExerciseBalanceSum ?? 0,
CashInCashOutProductChange = t.CashInCashOutProductChangeSum ?? 0,
WinLoss = t.WinLossSum ?? 0,
EndPremiumSum = t.EndPremiumSum ?? 0,
FundJson = t.FundJson,
PFE = t.PFE,
EAD = t.EAD,
LastSettlemetTime=t.OptDate
};
var sumDatas = sumQuery.ToArray();
//获取结束日期那一天的Sum总值
//例如2018-08-08到2019-08-08:区间段sum值 = sum(2019-08-08) - sum(2018-08-08)
//此处取的是sum(2019-08-08)
foreach (var data in sumDatas)
{
var balance = dic[data.ClientId];
balance.NetFund = data.NetFund;
balance.InFund = data.InFund;
balance.OutFund = data.OutFund;
balance.OtherFund = data.OtherFund;
balance.OptionPremium = data.OptionPremium;
balance.OptionPremiumSwap = data.OptionPremiumSwap;
balance.OptionPremiumAndSwapSum = data.OptionPremium + data.OptionPremiumSwap;
balance.EndPremiumSum = data.EndPremiumSum;
balance.SettlementBalance = data.SettlementBalance;
balance.UnwindBalance = data.UnwindBalance;
balance.ExerciseBalance = data.ExerciseBalance;
balance.SwapBalance = data.SwapBalance;
balance.Coupon = data.Coupon;
balance.CashInCashOutProductChange = data.CashInCashOutProductChange;
balance.WinLoss = data.WinLoss;
//起始时间 有值 和 WinLoss 区分 -- 国投不含当天
balance.WinLossSum = data.WinLoss;
balance.FundJson = data.FundJson;
balance.PFE = data.PFE;
balance.EAD = data.EAD;
balance.LastSettlemetTime = endDate <= lastDate? data.LastSettlemetTime:null;
balance.LastHTSettlemetTime = lastpushLog==null?"未同步": lastpushLog.update_time.ToString("yyyy-MM-dd HH:mm:ss");
}
}
//--------------------------------------------
// 期末资金信息(取最新结算日当日信息)
//--------------------------------------------
//当日客户资金
if (valuedate > lastBalanceDate && lastBalanceDate < endDate)
{
var todayClientBalance = new RealTimeClientBanlanceService(OptUserInfo.SystemUser)
.GetBanlances(clientIdS, startDate > lastBalanceDate ? startDate : lastBalanceDate.AddDays(1), endDate);
foreach (var data in todayClientBalance)
{
data.TdWinLoss = data.WinLoss; //当日实现盈亏
if (dic.TryGetValue(data.ClientId, out var balance))
{
data.NetFund += balance.NetFund;
data.InFund += balance.InFund;
data.OutFund += balance.OutFund;
data.OtherFund += balance.OtherFund;
data.OptionPremium += balance.OptionPremium;
data.OptionPremiumSwap += balance.OptionPremiumSwap;
data.OptionPremiumAndSwapSum += balance.OptionPremium + balance.OptionPremiumSwap;
data.EndPremiumSum += balance.EndPremiumSum;
data.SettlementBalance += balance.SettlementBalance;
data.UnwindBalance += balance.UnwindBalance;
data.ExerciseBalance += balance.ExerciseBalance;
data.SwapBalance += balance.SwapBalance;
data.Coupon += balance.Coupon;
data.CashInCashOutProductChange += balance.CashInCashOutProductChange;
data.WinLoss += balance.WinLoss;
//data.AvailableStockEqvNotional = balance.AvailableStockEqvNotional;
data.LastSettlemetTime = balance.LastSettlemetTime;
data.LastHTSettlemetTime = balance.LastHTSettlemetTime;
}
dic[data.ClientId] = data;
data.UpdateDate = DateTime.Now;
data.IsLatestDate = true;
}
}
else
{
var endQuery = from t in db.ClientBalanceDaily
join cs in db.client_span.Where(eod_cs => eod_cs.SpanType == ClientSpan.SpanType_Eod) on new { t.ClientId, ValueDate = t.BalanceDate } equals new { cs.ClientId, cs.ValueDate }
into eodClientSpan
from cs in eodClientSpan.DefaultIfEmpty()
where t.BalanceDate == lastDate
&& clientIdS.Contains(t.ClientId)
select new
{
ClientId = t.ClientId,
FreezePremium = t.FrozenPremium ?? 0.0,
ReceivablesPremium = 0.0,
AmountFund = t.ToDayRemainFund ?? 0.0,
GuaranteesTotalAmount = t.TodayRemianFundProduct ?? 0.0,
//仅用于广期资本可用资金计算
//可用资金1 = 净入金 + 已实现盈亏 + 浮动盈亏 - 次日最大亏损;
//可用资金2 = 净入金 + 已实现盈亏 - 持仓期初净支付权利金;
//可用资金 = min(可用资金1,可用资金2);
AvailableAmount1 = (t.NetFundSum ?? 0) + (t.WinLossSum ?? 0) + (t.PositionPnl ?? 0) + (cs.WorstCastClientPayable ?? 0),
AvailableAmount2 = (t.NetFundSum ?? 0) + (t.WinLossSum ?? 0) - (t.OptionPremiumSum ?? 0) - (t.OptionPremiumSwapSum ?? 0),
AvailableAmount = (t.MarginBalance ?? 0.0) + (t.PayableMargin ?? 0.0) - (t.FrozenMarginMoney ?? 0.0) - (t.TodayRemianFundProduct ?? 0.0),//t.FrozenMarginMoney是通道业务显示所用到的
TotalCredit = t.Credit ?? 0.0,
PayableMargin = t.PayableMargin ?? 0.0,
DeltaMargin = t.DeltaMargin ?? 0d,
SwapPayableMargin = t.SwapPayableMargin ?? 0.0,
SwapUnPayableMargin = t.SwapUnPayableMargin ?? 0.0,
TwoSideMargin = t.TwoSideMargin ?? 0.0,
OtherSideMargin = t.OtherSideMargin ?? 0.0,
MySideMargin = t.MySideMargin ?? 0.0,
MaintenanceMargin = cs.VariationMargin ?? 0.0,
IsPayableMarginManual = t.IsPayableMarginManual,
IsPayableMarginLock = cs == null ? false : cs.ModifiedFlag,
FrozenMarginMoney = t.FrozenMarginMoney ?? 0.0,
FrozenOutFund = t.FrozenOutFund ?? 0.0,
MarginBalance = t.MarginBalance ?? 0.0,
Coupon = t.Coupon ?? 0.0,
SwapBalance = t.SwapBalance ?? 0.0,
Margin = t.Margin ?? 0.0,
//IsTradeCredit = t.IsTradeCredit ?? c.IsTradeCredit == 1,
TodayNewMargin = 0,
PositionPv = t.Pv ?? 0,
RoundedPositionPv = t.RoundedPv ?? 0,
SellPv = t.SellPv ?? 0,
PrepaymentAmount = t.PrepaymentAmount ?? 0.0,
DaliyPnl = t.DailyPnl ?? 0,
PositionPnl = t.PositionPnl ?? 0,
RoundedPositionPnl = t.RoundedPositionPnl ?? 0,
ClientSellPositionPnl = t.ClientSellPositionPnl ?? 0,
PositionPremiumNetCash = t.PositionPremiumNetCash ?? 0,
LastDayPositionPremiumNetCash = t.LastDayPositionPremiumNetCash ?? 0,
SellTradePrice = t.SellTradePrice,
AvailableStockEqvNotional = t.AvailableStockEqvNotional ?? 0,
FrozenBalance = t.FrozenBalance ?? 0,
TdWinLoss = t.WinLoss,
MarginJson = cs.PVJsons,
MaintenanceLine = t.MaintenanceLine,
TotalNominal=t.TotalNominal,
InFundSum = t.InFundSum,
OutFundSum = t.OutFundSum,
VmInFundSum = t.vm_in_fund_sum,
VmOutFundSum = t.vm_out_fund_sum,
};
var endDatas = endQuery.ToArray();
foreach (var data in endDatas)
{
if (dic.TryGetValue(data.ClientId, out var balance))
{
var client = DataCacheProvider.GetClientDataSource().GetData(data.ClientId);
var lasttoDay = EodOperationBase.GetLastSettlementDate(lastDate, true);
var lastClientBalanceDaily = db.ClientBalanceDaily.Where(a => a.BalanceDate == lasttoDay && a.ClientId == data.ClientId).FirstOrDefault();
var marginRate = GetClientMarginRate(data.ClientId, clientMarginTemplates);
balance.FrozenBalance = data.FrozenBalance;
balance.FreezePremium = data.FreezePremium;
balance.ReceivablesPremium = data.ReceivablesPremium;
balance.AmountFund = data.AmountFund;
balance.TotalCredit = data.TotalCredit;
balance.PayableMargin = data.PayableMargin;
balance.GuaranteesTotalAmount = data.GuaranteesTotalAmount;
balance.FrozenMarginMoney = data.FrozenMarginMoney;
balance.DaliyPnl = data.DaliyPnl;
balance.RoundedDaliyPnl = data.RoundedPositionPnl - (lastClientBalanceDaily?.RoundedPositionPnl ?? 0);
balance.PositionPnl = data.PositionPnl;
balance.RoundedPositionPnl = data.RoundedPositionPnl;
balance.DeltaMargin = data.DeltaMargin;
balance.SwapPayableMargin = data.SwapPayableMargin;
balance.SwapUnMargin = data.SwapUnPayableMargin;
balance.TwoSideMargin = data.TwoSideMargin;
balance.OtherSideMargin = data.OtherSideMargin;
balance.MySideMargin = data.MySideMargin;
balance.MaintenanceMargin=data.MaintenanceMargin;
balance.IsPayableMarginManual = data.IsPayableMarginManual;
balance.IsPayableMarginLock = data.IsPayableMarginLock;
balance.FrozenMarginMoney = data.FrozenMarginMoney;
balance.FrozenOutFund = data.FrozenOutFund;
balance.MarginBalance = data.MarginBalance;
balance.Margin = data.Margin;
balance.UpdateDate = DateTime.Now;
balance.IsTradeCredit = client?.IsTradeCredit == 1;
balance.TodayNewMargin = data.TodayNewMargin;
balance.PositionPv = data.PositionPv;
balance.RoundedPositionPv = data.RoundedPositionPv;
balance.SellPv = data.SellPv;
balance.PrepaymentAmount = data.PrepaymentAmount;
balance.ClientSellPositionPnl = data.ClientSellPositionPnl;
balance.PositionPremiumNetCash = data.PositionPremiumNetCash;
balance.SellTradePrice = data.SellTradePrice ?? 0;
balance.LastDayPositionPremiumNetCash = data.LastDayPositionPremiumNetCash;
balance.MarginOptionType = client?.MarginOptionType ?? 0;
balance.IsLatestDate = true;
balance.IsEodData = true;
balance.TdWinLoss = data.TdWinLoss ?? 0;
balance.AvailableStockEqvNotional = data.AvailableStockEqvNotional;
balance.MarginJson = data.MarginJson;
balance.ClientType = client.SwapTradeType ?? 0;
balance.ClientName = client.Name;
balance.MaintenanceLine = data.MaintenanceLine ?? 0;
balance.PositionNotionalPrincipal = data.TotalNominal??0;
balance.OutFundSum = data.OutFundSum ?? 0;
balance.InFundSum = data.InFundSum ?? 0;
balance.VmInFundSum = data.VmInFundSum ?? 0;
balance.VmOutFundSum = data.VmOutFundSum ?? 0;
//预付金金额=期末结存-初始预付金金额
balance.MarginBalance = balance.AmountFund - balance.MySideMargin;
// 可用资金 = 期末结存 - 追保账户余额 - 初始保证金
balance.AvailableAmount = balance.MarginBalance - (balance.VmInFundSum - balance.VmOutFundSum);
// 是否追保=盯市金额小于维持保证金额
balance.NeedAddMargin = balance.SwapMarketAmount < balance.MaintenanceMargin;
// 追保金额=初始保证金金额-盯市金额
balance.MarginByPayableMarginTotal = balance.NeedAddMargin ? (balance.MySideMargin - balance.SwapMarketAmount):0;
// 可取资金=Math.Max(期末结存-min(持仓盈亏,0)-初始保证金,0)
balance.DesirableFund = Math.Max(balance.MarginBalance + Math.Min(balance.RoundedPositionPnl, 0),0);
}
}
}
//--------------------------------------------
//对出入金,权利金,结算收支,实现盈亏,抵押品变化区间段sum处理
//例如2018-08-08到2019-08-08:区间段sum值 = sum(2019-08-08) - sum(2018-08-07)
//--------------------------------------------
if (startDate <= lastBalanceDate)
{
//默认期初结存为0
foreach (var balance1 in dic.Values)
{
balance1.LastDayRemainFund = 0;
balance1.LastDayRemainFundWithProduct = 0;
balance1.LastGuaranteesTotalAmount = 0;
balance1.LastDayPositionPremiumNetCash = 0;
}
//该判断代表起始时间是选择了的,而不是空,需要区间逻辑处理
if (startDate.Year > 2008)
{
var query = from t in db.ClientBalanceDaily
where t.BalanceDate >= startDate && t.BalanceDate <= endDate
&& clientIdS.Contains(t.ClientId)
group t by t.ClientId into g
select new
{
ClientId = g.Key,
BalanceDate = g.Min(n => n.BalanceDate)
};
var startQuery = from t in db.ClientBalanceDaily
join t2 in query on new { t.ClientId, t.BalanceDate } equals new { t2.ClientId, t2.BalanceDate }
select new
{
ClientId = t.ClientId,
LastDayRemainFund = t.LastDayRemainFund ?? 0,
TodayRemianFundProduct = t.TodayRemianFundProduct ?? 0,
CashInCashOutProductChange = t.CashInCashOutProductChange ?? 0,
LastDayPositionPremiumNetCash = t.LastDayPositionPremiumNetCash ?? 0,
//此处取上一日的sum,例如sum(2018-08-07)
NetFundSum = (t.NetFundSum ?? 0) - (t.NetFund ?? 0),
InFundSum = (t.InFundSum ?? 0) - (t.InFund ?? 0),
OutFundSum = (t.OutFundSum ?? 0) - (t.OutFund ?? 0),
OtherFundSum = (t.OtherFundSum ?? 0) - (t.OtherFund ?? 0),
OptionPremiumSum = (t.OptionPremiumSum ?? 0) - (t.OptionPremium ?? 0),
OptionPremiumSwapSum = (t.OptionPremiumSwapSum ?? 0) - (t.OptionPremiumSwap ?? 0),
SettlementBalanceSum = (t.SettlementBalanceSum ?? 0) - (t.SettlementBalance ?? 0),
UnwindBalanceSum = (t.UnwindBalanceSum ?? 0) - (t.UnwindBalance ?? 0),
ExerciseBalanceSum = (t.ExerciseBalanceSum ?? 0) - (t.ExerciseBalance ?? 0),
SwapBalanceSum = (t.SwapBalanceSum ?? 0) - (t.SwapBalance ?? 0),
CouponSum = (t.CouponSum ?? 0) - (t.Coupon ?? 0),
WinLossSum = (t.WinLossSum ?? 0) - (t.WinLoss ?? 0),
CashInCashOutProductChangeSum = (t.CashInCashOutProductChange ?? 0) - (t.CashInCashOutProductChange ?? 0),
};
var startDatas = startQuery.ToArray();
foreach (var data in startDatas)
{
if (dic.TryGetValue(data.ClientId, out var balance))
{
balance.LastDayRemainFund = data.LastDayRemainFund;
balance.LastDayRemainFundWithProduct = data.LastDayRemainFund + data.TodayRemianFundProduct - data.CashInCashOutProductChange;
balance.LastGuaranteesTotalAmount = data.TodayRemianFundProduct - data.CashInCashOutProductChange;
balance.LastDayPositionPremiumNetCash = data.LastDayPositionPremiumNetCash;
//例如2018-08-08到2019-08-08:区间段sum值 = sum(2019-08-08) - sum(2018-08-07)
balance.NetFund -= data.NetFundSum;
balance.InFund -= data.InFundSum;
balance.OutFund -= data.OutFundSum;
balance.OtherFund -= data.OtherFundSum;
balance.OptionPremium -= data.OptionPremiumSum;
balance.OptionPremiumSwap -= data.OptionPremiumSwapSum;
balance.OptionPremiumAndSwapSum -= data.OptionPremiumSum + data.OptionPremiumSwapSum;
balance.SettlementBalance -= data.SettlementBalanceSum;
balance.UnwindBalance -= data.UnwindBalanceSum;
balance.ExerciseBalance -= data.ExerciseBalanceSum;
balance.SwapBalance -= data.SwapBalanceSum;
balance.Coupon -= data.CouponSum;
balance.CashInCashOutProductChange -= data.CashInCashOutProductChangeSum;
balance.WinLoss -= data.WinLossSum;
balance.WinLossSum -= balance.WinLoss;
}
}
}
}
var gapList = db.ClientBalanceGap.Where(c => clientIdS.Contains(c.ClientId) && c.ValueDate == endDate).ToList();
gapList ??= new List<ClientBalanceGap>();
if (IsClientBalanceGap || IsGetOuterMarginGap)
{
var ClientBalanceGap = new ClientBalanceGap();
foreach (var item in dic.Values)
{
if (IsClientBalanceGap)
{
ClientBalanceGap = gapList.FirstOrDefault(c => c.ClientId == item.ClientId && c.ValueDate == endDate && !c.IsImportOuterMargin);
}
if (IsGetOuterMarginGap)
{
ClientBalanceGap = gapList.FirstOrDefault(c => c.ClientId == item.ClientId && c.ValueDate == endDate && c.IsImportOuterMargin);
}
if (ClientBalanceGap != null)
{
if (IsClientBalanceGap)
{
item.ClientBalanceGap = ClientBalanceGap;
item.IsGap = true;
item.AmountFund += ClientBalanceGap.ToDayRemainFund ?? 0;
item.AvailableAmount += (ClientBalanceGap.ToDayRemainFund ?? 0) - (ClientBalanceGap.PayableMargin ?? 0);
item.NetFund += ClientBalanceGap.NetFund ?? 0;
item.OptionPremium += ClientBalanceGap.OptionPremium ?? 0;
item.OptionPremiumSwap += ClientBalanceGap.OptionPremiumSwap ?? 0;
item.OptionPremiumAndSwapSum += ClientBalanceGap.OptionPremium ?? 0;
item.OptionPremiumAndSwapSum += ClientBalanceGap.OptionPremiumSwap ?? 0;
item.SettlementBalance += ClientBalanceGap.SettlementBalance ?? 0;
item.Coupon += ClientBalanceGap.Coupon ?? 0;
item.SwapBalance += ClientBalanceGap.SwapBalance ?? 0;
item.OtherFund += ClientBalanceGap.OtherFund ?? 0;
item.TotalCredit += ClientBalanceGap.Credit ?? 0;
//if (ClientBalanceGap.PayableFund != null && ClientBalanceGap.PayableFund != 0)
//{
// item.PayableFund += ClientBalanceGap.PayableFund ?? 0;
//}
//else
//{
// item.MarginByPayableMargin += ClientBalanceGap.MarginByPayableMargin ?? 0;
//}
item.WinLoss += ClientBalanceGap.WinLoss ?? 0;
item.PositionPnl += ClientBalanceGap.PositionPnl ?? 0;
item.RoundedPositionPnl += ClientBalanceGap.PositionPnl ?? 0;
item.PositionPv += ClientBalanceGap.PositionPv ?? 0;
item.RoundedPositionPv += ClientBalanceGap.PositionPv ?? 0;
}
if (IsGetOuterMarginGap)
{
item.ClientBalanceGap = ClientBalanceGap;
//(ClientBalanceGap.PayableMargin ?? 0)正数代表客户应付预付金
//item.PayableMargin负数代表客户应付预付金
//(ClientBalanceGap.PayableMargin ?? 0) + item.PayableMargin代表客户支付预付金的差额
item.AvailableAmount += (ClientBalanceGap.ToDayRemainFund ?? 0) - ((ClientBalanceGap.PayableMargin ?? 0) + item.PayableMargin);
item.IsGap = true;
}
}
}
}
//return dic.Values;
}
using (var clientDB = new ClientDBContext())
{
var balance1 = dic[returnClientId];
if (!clientDB.client_Axis_Fundthresholds.Where(x => x.ClientId == returnClientId).Any() || endDate == DateTime.Today)
{
balance1.FundThreshold = clientDB.client.Where(n => n.id == returnClientId).Select(n => n.FundThreshold).FirstOrDefault();
}
else
{
balance1.FundThreshold = clientDB.client_Axis_Fundthresholds.Where(x => x.ValueDate <= endDate && x.ClientId == returnClientId).OrderByDescending(x => x.ValueDate)?.FirstOrDefault()?.FundThreshold;
}
}
if (clientDataSource != null)
{
foreach (var item in dic.Values)
{
var client = clientDataSource.GetData(item.ClientId);
item.ClientNumber = client?.Number;
item.ClientName = client?.Name;
}
}
else
{
foreach (var item in dic.Values)
{
var client = DataCacheProvider.GetClientDataSource().GetData(item.ClientId);
item.ClientNumber = client?.Number;
item.ClientName = client?.Name;
}
}
if (dic.Values != null && dic.Values.Count > 0)
{
if (PS.Config.Is宏源 || PS.Config.Company == Configuration.CompanyEnum.广发商贸)
{
//宏源 二次计算预付金占用及相关数据
//var clientIds = new List<int>();
//foreach (var item in dic.Values)
//{
// clientIds.Add(item.ClientId);
//}
var marginFactorDict = new ClientMarginTemplateService(OptUserInfo.SystemUser).GetMarginFactorDict(endDate, clientIdList, true);
dic.Values.ToList().ForEach(p => p.ReCaculatePayableMargin(p.ClientId, marginFactorDict));
}
}
//当是单一客户的时候,或者包含子级 执行新的字段返回,其他来源使用原来字段
if (ParentFlag || clientIdList.Count() == 1)
{
var DicTotal = dic[returnClientId];
#region 循环统计所有客户
foreach (var dc in dic)
{
#region 所有客户数据进行累加
if (dc.Key == returnClientId)
{
DicTotal.OptionPremiumAndUnwindBalanceTotal = DicTotal.OptionPremiumAndUnwindBalance;
DicTotal.MinusPayableMarginTotal = DicTotal.MinusPayableMargin;
DicTotal.TotalMarginTotal = DicTotal.TotalMargin;
DicTotal.RoundedTotalAmountTotal = DicTotal.RoundedTotalAmount;
DicTotal.TotalAmountTotal = DicTotal.TotalAmount;
DicTotal.MarginByPayableMarginTotal = DicTotal.MarginByPayableMarginTotal;
//if (PS.Config.Is广期资本)
//{
// DicTotal.MarginByPayableMarginTotal = Math.Max(-DicTotal.AvailableAmount, 0);
//}
DicTotal.ClosedTradePayableFundTotal = DicTotal.ClosedTradePayableFund;
DicTotal.PositionTradePayableFundTotal = DicTotal.PositionTradePayableFund;
DicTotal.PayableFundTotal = DicTotal.PayableFund;
DicTotal.DesirableFundTotal = DicTotal.DesirableFund;
DicTotal.TotalNetSettlementTotal = DicTotal.TotalNetSettlement;
DicTotal.IsLatestDate = true;
continue;
}
DicTotal.SettlementBalance += dc.Value.SettlementBalance;
DicTotal.LastDayRemainFund += dc.Value.LastDayRemainFund;
DicTotal.NetFund += dc.Value.NetFund;
DicTotal.InFund += dc.Value.InFund;
DicTotal.OutFund += dc.Value.OutFund;
DicTotal.OptionPremium += dc.Value.OptionPremium;
DicTotal.OptionPremiumSwap += dc.Value.OptionPremiumSwap;
DicTotal.OptionPremiumAndSwapSum += dc.Value.OptionPremiumAndSwapSum;
DicTotal.OtherFund += dc.Value.OtherFund;
DicTotal.Coupon += dc.Value.Coupon;
DicTotal.SwapBalance += dc.Value.SwapBalance;
DicTotal.OptionPremiumAndUnwindBalanceTotal += dc.Value.OptionPremiumAndUnwindBalance;
DicTotal.ExerciseBalance += dc.Value.ExerciseBalance;
DicTotal.AmountFund += dc.Value.AmountFund;
DicTotal.GuaranteesTotalAmount += dc.Value.GuaranteesTotalAmount;
DicTotal.MinusPayableMarginTotal += dc.Value.MinusPayableMargin;
DicTotal.AvailableAmount += dc.Value.AvailableAmount;
DicTotal.TotalMarginTotal += dc.Value.TotalMargin;
DicTotal.TotalCredit += dc.Value.TotalCredit;
DicTotal.WinLoss += dc.Value.WinLoss;
DicTotal.TdWinLoss += dc.Value.TdWinLoss;
DicTotal.PositionPremiumNetCash += dc.Value.PositionPremiumNetCash;
DicTotal.RoundedPositionPv += dc.Value.RoundedPositionPv;
DicTotal.PositionPv += dc.Value.PositionPv;
DicTotal.RoundedPositionPnl += dc.Value.RoundedPositionPnl;
DicTotal.PositionPnl += dc.Value.PositionPnl;
DicTotal.RoundedTotalAmountTotal += dc.Value.RoundedTotalAmount;
DicTotal.TotalAmountTotal += dc.Value.TotalAmount;
DicTotal.MarginByPayableMarginTotal += dc.Value.MarginByPayableMarginTotal;
DicTotal.ClosedTradePayableFundTotal += dc.Value.ClosedTradePayableFund;
DicTotal.PositionTradePayableFundTotal += dc.Value.PositionTradePayableFund;
DicTotal.PayableFundTotal += dc.Value.PayableFund;
DicTotal.DesirableFundTotal += dc.Value.DesirableFund;
DicTotal.SellTradePrice += dc.Value.SellTradePrice;
DicTotal.ClientSellPositionPnl += dc.Value.ClientSellPositionPnl;
DicTotal.TotalNetSettlementTotal += dc.Value.TotalNetSettlement;
DicTotal.MarginBalance += dc.Value.MarginBalance;
DicTotal.FrozenMarginMoney += dc.Value.FrozenMarginMoney;
DicTotal.FrozenRedeemFunds += dc.Value.FrozenRedeemFunds;
//DicTotal.FundThreshold += dc.Value.FundThreshold;
#endregion
}
#endregion
}
return dic.Values;
}
/// <summary>
/// 获取历史交易中追保金额不为0的客户ids(排除对系统日实时的数据的筛选)
/// </summary>
/// <param name="searchDate"></param>
/// <returns></returns>
public static List<int> GetHaveMarginAmount(DateTime searchDate, string MarginShownType = "default")
{
//获取根据系统时间
var lastDate = searchDate;// EodOperationBase.GetLastSettlementDate(DateTime.Now.Date);
var clientlist = new List<int>();
var baseQuery = new List<Pairs>();
using var db = new YLContext();
switch (MarginShownType)
{
case "default":
baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate
select new Pairs
{
tdaily = t,
tgap = null
}).ToList();
break;
case "ClientBalanceGap":
baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate
join tgap in db.ClientBalanceGap.Where(o => !o.IsImportOuterMargin && o.ValueDate == lastDate)
on new { t.ClientId, date = t.BalanceDate ?? DateTime.MinValue }
equals new { tgap.ClientId, date = tgap.ValueDate } into tempTgap
from tgap in tempTgap.DefaultIfEmpty()
select new Pairs
{
tdaily = t,
tgap = tgap
}).ToList();
break;
case "GetOuterMargin":
baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate
join tgap in db.ClientBalanceGap.Where(o => o.IsImportOuterMargin && o.ValueDate == lastDate)
on new { t.ClientId, date = t.BalanceDate ?? DateTime.MinValue }
equals new { tgap.ClientId, date = tgap.ValueDate } into tempTgap
from tgap in tempTgap.DefaultIfEmpty()
select new Pairs
{
tdaily = t,
tgap = tgap
}).ToList();
break;
}
if (PS.Config.Is广期资本)
{
//同业客户:期末结存+持仓盈亏-冻结+授信+质押市值<0,追保
//非同业客户:期末结存 + 持仓盈亏 - 预付金占用 - 冻结 + 授信 + 质押市值 < 0,追保
if (baseQuery == null || baseQuery.Count == 0)
{
return clientlist;
}
var clientIds = baseQuery.Select(p => p.tdaily.ClientId).Distinct().ToList();
//List<ClientSamePeerDto> samePeerList = null;
Dictionary<int, int?> samePeerDic = null;
using (var clientDb = DbContextFactory.GetClientDbContext(null))
{
samePeerDic = clientDb.client.AsNoTracking().Where(p => clientIds.Contains(p.id)).ToDictionary(p => p.id, p => p.SamePeer);
}
samePeerDic ??= new Dictionary<int, int?>();
foreach (var t in baseQuery)
{
var clientId = t.tdaily.ClientId;
var clientSettleBalance = new ClientSettleBalance
{
AmountFund = t.tdaily.ToDayRemainFund ?? 0.0,
GuaranteesTotalAmount = t.tdaily.TodayRemianFundProduct ?? 0.0,
PositionPnl = t.tdaily.PositionPnl ?? 0.0,
FreezePremium = t.tdaily.FrozenPremium ?? 0.0,
FrozenOutFund = t.tdaily.FrozenOutFund ?? 0.0,
FrozenRedeemFunds = t.tdaily.FrozenRedeemFunds ?? 0.0,
FrozenMarginMoney = t.tdaily.FrozenMarginMoney ?? 0.0,
TotalCredit = t.tdaily.Credit ?? 0.0,
PayableMargin = t.tdaily.PayableMargin ?? 0.0,
PositionPremiumNetCash = t.tdaily.PositionPremiumNetCash ?? 0.0,
};
if (t.tgap != null)
{
clientSettleBalance.ClientBalanceGap = t.tgap;
clientSettleBalance.IsGap = true;
}
clientSettleBalance.SamePeer = samePeerDic.ContainsKey(clientId) ? samePeerDic[clientId] ?? 0 : 0;
if (clientSettleBalance.OtherMarginByPayableMargin < 0)
{
clientlist.Add(clientId);
}
}
}
else
{
//-PayableMargin - Math.Max(AmountFund + ClosedTradePayableFund + PositionTradePayableFund, 0) - GuaranteesTotalAmount - TotalCredit
//ClosedTradePayableFund: -1 * Math.Min(AmountFund + PositionPremiumNetCash, 0)
//PositionTradePayableFund: Math.Max(PositionPremiumNetCash - Math.Max(AmountFund + PositionPremiumNetCash, 0), 0)
foreach (var t in baseQuery)
{
var clientId = t.tdaily.ClientId;
double MarginPayableMargin = 0;
if (t.tgap != null)
{
if (t.tgap.MarginByPayableMargin != null && t.tgap.MarginByPayableMargin != 0)
{
MarginPayableMargin = -(t.tdaily.PayableMargin ?? 0.0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
- Math.Min((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0), 0)
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0), 0), 0), 0)
- (t.tdaily.TodayRemianFundProduct ?? 0.0)
- (t.tdaily.Credit ?? 0.0)
+ (t.tgap.MarginByPayableMargin ?? 0);
}
else
{
MarginPayableMargin = -((t.tdaily.PayableMargin ?? 0.0) - (t.tgap.PayableMargin ?? 0))
- Math.Max((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0)
- Math.Min((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0), 0)
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0), 0), 0), 0)
- ((t.tdaily.TodayRemianFundProduct ?? 0.0) + (t.tgap.ToDayRemainFund ?? 0))
- ((t.tdaily.Credit ?? 0.0) + (t.tgap.Credit ?? 0));
}
}
else
{
MarginPayableMargin = -(t.tdaily.PayableMargin ?? 0.0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
- Math.Min((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0), 0)
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0), 0), 0), 0)
- (t.tdaily.TodayRemianFundProduct ?? 0.0)
- (t.tdaily.Credit ?? 0.0);
}
if (MarginPayableMargin > 1e-3)
{
clientlist.Add(clientId);
}
}
}
return clientlist;
}
/// <summary>
/// 获取当前客户中总资产小于1的客户ids(排除对系统日实时的数据的筛选)
/// </summary>
public static List<int> GetTotalAssetClientIds(DateTime value)
{
List<int> result = null;
using (var db = new YLContext())
{
var tempList = db.ClientBalanceDaily.Where(O => O.BalanceDate == value).AsEnumerable();
if (PS.Config.IsPVRounded)
{
result = tempList.Where(O => (O.RoundedTotalAmount ?? 0) > 1).Select(O => O.ClientId).ToList();
}
else
{
result = tempList.Where(O => (O.TotalAmount ?? 0) > 1).Select(O => O.ClientId).ToList();
}
}
return result;
}
/// <summary>
/// 获取历史交易中应付资金总额不为0的客户ids(排除对系统日实时的数据的筛选)
/// </summary>
public static List<int> GetHavePayableFund(DateTime searchDate, string MarginShownType = "default")
{
//获取根据系统时间
var lastDate = searchDate;// EodOperationBase.GetLastSettlementDate(DateTime.Now.Date);
using var db = new YLContext();
var clientlist = new List<int>();
var baseQuery = new List<Pairs>();
switch (MarginShownType)
{
case "default":
baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate
select new Pairs
{
tdaily = t,
tgap = null
}).ToList();
break;
case "ClientBalanceGap":
baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate
join tgap in db.ClientBalanceGap.Where(o => !o.IsImportOuterMargin && o.ValueDate == lastDate)
on new { t.ClientId, date = t.BalanceDate ?? DateTime.MinValue }
equals new { tgap.ClientId, date = tgap.ValueDate } into tempTgap
from tgap in tempTgap.DefaultIfEmpty()
select new Pairs
{
tdaily = t,
tgap = tgap
}).ToList();
break;
case "GetOuterMargin":
baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == lastDate
join tgap in db.ClientBalanceGap.Where(o => o.IsImportOuterMargin && o.ValueDate == lastDate)
on new { t.ClientId, date = t.BalanceDate ?? DateTime.MinValue }
equals new { tgap.ClientId, date = tgap.ValueDate } into tempTgap
from tgap in tempTgap.DefaultIfEmpty()
select new Pairs
{
tdaily = t,
tgap = tgap
}).ToList();
break;
}
foreach (var t in baseQuery)
{
var ClientId = t.tdaily.ClientId;
double PayableFund = 0;
if (t.tgap != null)
{
if (t.tgap.PayableFund != null && t.tgap.PayableFund != 0)
{
PayableFund = Math.Max(
(-Math.Min((t.tdaily.ToDayRemainFund + t.tdaily.PositionPremiumNetCash) ?? 0, 0))
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
, 0)
+ Math.Max(-(t.tdaily.PayableMargin ?? 0.0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
- Math.Min((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
, 0)
, 0)
- (t.tdaily.TodayRemianFundProduct ?? 0.0)
- (t.tdaily.Credit ?? 0.0), 0)
, 0)
+ (t.tgap == null ? 0 : t.tgap.PayableFund ?? 0);
}
else
{
PayableFund = Math.Max(
(-Math.Min(((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0) + t.tdaily.PositionPremiumNetCash) ?? 0, 0))
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
, 0)
+ Math.Max(-((t.tdaily.PayableMargin ?? 0.0) - (t.tgap.PayableMargin ?? 0))
- Math.Max((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0)
- Math.Min((t.tdaily.ToDayRemainFund ?? 0) + (t.tgap.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0 + (t.tgap.ToDayRemainFund ?? 0))
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
, 0)
, 0)
- (t.tdaily.TodayRemianFundProduct ?? 0.0)
- ((t.tdaily.Credit ?? 0.0) + (t.tgap.Credit ?? 0)), 0)
, 0);
}
}
else
{
PayableFund = Math.Max(
(-Math.Min((t.tdaily.ToDayRemainFund + t.tdaily.PositionPremiumNetCash) ?? 0, 0))
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
, 0)
+ Math.Max(-(t.tdaily.PayableMargin ?? 0.0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
- Math.Min((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
+ Math.Max((t.tdaily.PositionPremiumNetCash ?? 0)
- Math.Max((t.tdaily.ToDayRemainFund ?? 0)
+ (t.tdaily.PositionPremiumNetCash ?? 0)
, 0)
, 0)
, 0)
- (t.tdaily.TodayRemianFundProduct ?? 0.0)
- (t.tdaily.Credit ?? 0.0), 0)
, 0);
}
if (PayableFund > 1)
{
clientlist.Add(ClientId);
}
}
return clientlist;
}
/// <summary>
/// 对传入的客户进行指定日期有持仓记录的筛选(排除对系统日实时的数据的筛选)
/// </summary>
public static List<int> GetHavePositionClientIds(DateTime searchDate)
{
using var db = new YLContext();
var query = from eodpos in db.eod_trade_position
where eodpos.ValueDate == searchDate
&& eodpos.ClientId > 0
&& eodpos.TradeId > 0
select eodpos.ClientId;
return query.Distinct().ToList();
}
/// <summary>
/// 进行指定日期应付了结交易款是否大于1元的筛选(排除对系统日实时的数据的筛选)
/// </summary>
public static List<int> GetClosePayableFundClientIds(DateTime searchDate, string MarginShownType = "default")
{
using var db = new YLContext();
var clientlist = new List<int>();
var baseQuery = (from t in db.ClientBalanceDaily
where t.BalanceDate == searchDate
select t.ClientId).Distinct().ToList();
var IsGap = false;
var IsOuter = false;
if (MarginShownType == "ClientBalanceGap")
{
IsGap = true;
}
if (MarginShownType == "GetOuterMargin")
{
IsOuter = true;
}
var balances = GetClientBanlances(baseQuery, searchDate, searchDate, IsGap, IsOuter);
foreach (var item in balances)
{
if (item.ClosedTradePayableFund >= 1)
{
clientlist.Add(item.ClientId);
}
}
return clientlist;
}
/// <summary>
///
/// </summary>
public static IEnumerable<ClientSettleBalance> GetClientRiskMonitor(List<int> clientIdList, DateTime searchDate, string marginShownType)
{
if (null == clientIdList || !clientIdList.Any())
{
return null;
}
//获取根据系统时间
var lastBalanceDate = EodOperationBase.GetLastSettlementDate(DateTime.Now.Date);
//系统交易日
var valuedate = valuedateBLL.ValueDate;
using var db = new YLContext();
var IsGap = false;
var IsOuter = false;
if (marginShownType == "ClientBalanceGap")
{
IsGap = true;
}
if (marginShownType == "GetOuterMargin")
{
IsOuter = true;
}
//db.SetDebugLog();
var lastClientBalances = GetClientBanlances(clientIdList, DateTime.MinValue, searchDate, IsGap, IsOuter);
//历史查询,部分交易信息重新计算
if (valuedate <= lastBalanceDate || valuedate > searchDate)
{
//----------------------------------------
// 所有交易合计
//----------------------------------------
var allTradeQuery = from t in db.trade
where t.TradeDate <= searchDate
&& t.ValidState != "InValid"
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2
&& clientIdList.Contains(t.ClientId)
&& ConsTrade.TradeStatusAfterConfirmed.Contains(t.TradeStatus)
select new
{
t.ClientId,
OriginalStockEqvNotional = t.OriginalStockEqvNotional > 0 ? t.OriginalStockEqvNotional.Value :
(t.SpotPrice ?? 0.0) * (t.OriginalNotional ?? 0),
BuyCount = t.BuySell == "买入" ? 0 : 1,//从客户角度看
SellCount = t.BuySell == "卖出" ? 0 : 1,//从客户角度看
TodayCount = t.TradeDate == searchDate ? 1 : 0
};
var allTradeQuerySum = from t in allTradeQuery
group t by t.ClientId into g
select new
{
ClientId = g.Key,
SellNotionalPrincipal = g.Sum(a => a.SellCount * a.OriginalStockEqvNotional),
BuyNotionalPrincipal = g.Sum(a => a.BuyCount * a.OriginalStockEqvNotional),
BuyCount = g.Sum(n => n.BuyCount),
SellCount = g.Sum(n => n.SellCount),
TodayCount = g.Sum(n => n.TodayCount),
TodayNotionalPrincipal = g.Sum(n => n.TodayCount * n.OriginalStockEqvNotional)
};
var tradeSumDic = allTradeQuerySum.ToDictionary(n => n.ClientId);
//----------------------------------------
// 交易结算预付金统计
//----------------------------------------
//组合交易和结构化交易获取的是父亲交易(不包含子交易)
var tradeOriginQuery = from x in db.trade
where x.ParentTradeId == 0
&& x.ValidState != ConsGlobal.InValid
select x;
var eodTradePositionQuery = from eodTradePosition in db.eod_trade_position
where eodTradePosition.ValueDate == searchDate &&
clientIdList.Contains(eodTradePosition.ClientId)
select eodTradePosition;
//组合交易和结构化交易获取的是父亲交易(不包含子交易)
var eodTradeQuery = from eodTrade in db.eod_trade
join tradeOrigin in tradeOriginQuery on eodTrade.TradeId equals tradeOrigin.id
where eodTrade.ValueDate == searchDate
&& clientIdList.Contains(eodTrade.ClientId)
&& ConsTrade.NeedMarginTradeStatusList.Contains(eodTrade.TradeStatus)
select new { eodTrade.TradeId, et = new xodTradeBase() { TradeJson = eodTrade.TradeJson } };
var positionQuery = from eodTradePosition in eodTradePositionQuery
join eodTrade in db.eod_trade on eodTradePosition.TradeId equals eodTrade.TradeId
where eodTrade.ValueDate == searchDate
&& clientIdList.Contains(eodTrade.ClientId)
&& ConsTrade.NeedMarginTradeStatusList.Contains(eodTrade.TradeStatus)
select new
{
eodTrade.TradeId,
ClientId = eodTrade.ClientId,
et = new xodTradeBase() { TradeJson = eodTrade.TradeJson },
underlyprice = eodTradePosition.UnderlyingPrice,
};
var positionQuerySum = from eodTradePosition in eodTradePositionQuery
group eodTradePosition by eodTradePosition.ClientId into g
select new
{
ClientId = g.Key,
//Margin = g.Sum(n => (n.BuySell == "买入" ? -1 : 0) * n.Margin),
//增加收益互换只计算主交易主交易限制,收益互换暂不考虑买卖反向
Margin = g.Sum(n => (((n.BuySell == "买入" && n.TradeType != "收益互换") || (n.TradeType == "收益互换" && n.ParentTradeId == 0)) ? -1 : 0) * n.Margin),
// 收益互换预付金
SwapMargin = g.Sum(n => ((n.TradeType == "收益互换" && n.ParentTradeId == 0) ? -1 : 0) * n.Margin),
// 收益互换预付金容忍金额
SwapUnMargin = g.Sum(n => ((n.TradeType == "收益互换" && n.ParentTradeId == 0) ? -1 : 0) * n.SwapUnMargin),
};
var eodTrades = eodTradeQuery.ToList().Select(o => new { o.et.trade.ClientId, o.et.trade });
var positionSumDic = positionQuerySum.ToDictionary(n => n.ClientId);
var positionDic = positionQuery.ToList();
//----------------------------------------
// 新交易统计
//----------------------------------------
var newTradeQuery = from t in db.trade
where t.TradeDate == searchDate
&& t.ValidState != "InValid"
&& (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2
&& clientIdList.Contains(t.ClientId)
&& ConsTrade.TradeStatusAfterConfirmed.Contains(t.TradeStatus)
select new
{
t.id,
notionalPrincipal = t.OriginalStockEqvNotional > 0
? ((t.OriginalStockEqvNotional * t.Notional / t.OriginalNotional) ?? 0)
: (t.SpotPrice ?? 0.0) * t.Notional
};
var todayPostionQuery = from eodTradePosition in eodTradePositionQuery
join trad in newTradeQuery on eodTradePosition.TradeId equals trad.id
select new ClientBalanceEx
{
ClientId = eodTradePosition.ClientId,
UnderlyingCode = eodTradePosition.UnderlyingCode
};
var todayPostionList = todayPostionQuery.ToArray();
var todayPostionSumQuery = from t in todayPostionList
group t by t.ClientId into g
select new ClientBalanceEx
{
ClientId = g.Key
};
var todayPostionSumDic = todayPostionSumQuery.ToDictionary(n => n.ClientId);
var tradePostionMarginQuery = from eodTradePosition in eodTradePositionQuery
select new ClientBalanceEx
{
ClientId = eodTradePosition.ClientId,
BuyerPositionMargin = eodTradePosition.Margin * (eodTradePosition.BuySell == "买入" ? 1 : 0),
};
var tradePostionMarginSumQuery = from t in tradePostionMarginQuery
group t by t.ClientId into g
select new ClientBalanceEx
{
ClientId = g.Key,
BuyerPositionMargin = g.Sum(n => n.BuyerPositionMargin),
};
var tradePostionMarginSumDic = tradePostionMarginSumQuery.ToDictionary(n => n.ClientId);
//----------------------------------------
//
//----------------------------------------
foreach (var balance in lastClientBalances)
{
if (tradeSumDic.TryGetValue(balance.ClientId, out var dicItem))
{
balance.SellNotionalPrincipal = dicItem.SellNotionalPrincipal;
balance.BuyNotionalPrincipal = dicItem.BuyNotionalPrincipal;
balance.BuyCount = dicItem.BuyCount;
balance.SellCount = dicItem.SellCount;
balance.TradeCount = dicItem.TodayCount;
balance.TodayNotionalPrincipal = dicItem.TodayNotionalPrincipal;
balance.TotalNotionalPrincipal = balance.SellNotionalPrincipal + balance.BuyNotionalPrincipal;
balance.TotalTradeCount = balance.BuyCount + balance.SellCount;
}
if (positionSumDic.TryGetValue(balance.ClientId, out var dicItem2))
{
balance.TodayNewMargin = dicItem2.Margin;
}
balance.PositionCount = eodTrades.Where(x => x.ClientId == balance.ClientId).Count();
balance.SellerPositionPremium = eodTrades.Where(o => o.ClientId == balance.ClientId).Sum(o => (o.trade.TradePrice ?? 0) * (o.trade.BuySell == "买入" ? 0 : 1));
balance.PositionNotionalPrincipal = eodTrades.Where(o => o.ClientId == balance.ClientId).Sum(o => o.trade.StockEqvNotional);
if (tradePostionMarginSumDic.TryGetValue(balance.ClientId, out var dicItem4))
{
balance.BuyerPositionMargin = dicItem4.BuyerPositionMargin;
}
if (IsOuter)
{
balance.MySideMargin = balance.PayableMargin;
}
}
}
if (searchDate > lastBalanceDate)
{
//get nowTime SellerPositionPremium BuyerPositionMargin
//get postion trade
var suspensionUnderlyingIdList = DataCacheProvider.GetUnderlyingDataSource().AsQueryable()
.Where(t => t.UnderlyingStatus == underlying_manager.Status_Suspension).Select(t => t.id).ToList();
var predicate = PredicateBuilder.Create<trade>(t => t.ClientId > 0
&& ConsTrade.NeedMarginTradeStatusList.Contains(t.TradeStatus)
&& (t.TradeType != "结构化交易" && t.IsGroup != 1 || t.IsGroup == 1 && t.TradeType == "结构化交易")
&& (t.IsGroup != 2 || t.IsGroup == 2 && t.TradeType == "收益互换")
&& t.ValidState != ConsGlobal.InValid
&& (t.ExerciseDate >= searchDate || suspensionUnderlyingIdList.Contains(t.UnderlyingId)));
if (clientIdList != null && clientIdList.Count() > 0)
{
predicate = predicate.And(t => clientIdList.Contains(t.ClientId));
}
var positionTradeQuery = from t in db.trade.Where(predicate)
join i in db.intraday_trade_position
on t.id equals i.TradeId
join risk in db.realtime_trade_risk.Where(tr => tr.ValueDate == searchDate && tr.VolType == "持仓") on t.id equals risk.TradeId into risks
from risk in risks.DefaultIfEmpty()
select new ClientBalanceEx
{
ClientId = t.ClientId,
SellerPositionPremium = (t.TradePrice ?? 0) * (t.BuySell == "买入" ? 0 : 1),
BuyerPositionMargin = i.Margin * (t.BuySell == "买入" ? 1 : 0),
PositionNotionalPrincipal = t.StockEqvNotional,
};
var positionTradeSumQuery = from t in positionTradeQuery
group t by t.ClientId into g
select new ClientBalanceEx
{
ClientId = g.Key,
SellerPositionPremium = g.Sum(n => n.SellerPositionPremium),
BuyerPositionMargin = g.Sum(n => n.BuyerPositionMargin),
PositionNotionalPrincipal = g.Sum(n => n.PositionNotionalPrincipal),
};
var tradePostionMarginSumDic = positionTradeSumQuery.ToDictionary(n => n.ClientId);
foreach (var balance in lastClientBalances)
{
if (tradePostionMarginSumDic.TryGetValue(balance.ClientId, out var dicItem1))
{
balance.SellerPositionPremium = dicItem1.SellerPositionPremium;
balance.BuyerPositionMargin = dicItem1.BuyerPositionMargin;
balance.PositionNotionalPrincipal = dicItem1.PositionNotionalPrincipal;
}
}
//
}
return lastClientBalances;
}
/// <summary>
/// 为山西固收而写,因为GetClientBanlances已经拿了历史跟最新,不需要再判断是历史还是最新
/// </summary>
/// <param name="clientIdList"></param>
/// <param name="searchDate"></param>
/// <param name="marginShownType"></param>
/// <returns></returns>
public static IEnumerable<ClientSettleBalance> GetClientRiskMonitorForShanXiGuShou(List<int> clientIdList, DateTime searchDate, string marginShownType)
{
if (null == clientIdList || !clientIdList.Any())
{
return null;
}
//获取根据系统时间
var lastBalanceDate = EodOperationBase.GetLastSettlementDate(DateTime.Now.Date);
//系统交易日
var valuedate = valuedateBLL.ValueDate;
using var db = new YLContext();
var IsGap = false;
var IsOuter = false;
if (marginShownType == "ClientBalanceGap")
{
IsGap = true;
}
if (marginShownType == "GetOuterMargin")
{
IsOuter = true;
}
var lastClientBalances = GetClientBanlances(clientIdList, DateTime.MinValue, searchDate, IsGap, IsOuter);
if (valuedate <= lastBalanceDate || valuedate > searchDate)
{
//----------------------------------------
// 所有交易合计
//----------------------------------------
var allTradeQuery = from t in db.trade
where t.TradeDate <= searchDate
&& t.ValidState != "InValid"
&& t.TradeType == "收益互换"
&& clientIdList.Contains(t.ClientId)
&& ConsTrade.TradeStatusAfterConfirmed.Contains(t.TradeStatus)
select new
{
t.id,
t.ClientId,
OriginalStockEqvNotional = t.OriginalStockEqvNotional > 0 ? t.OriginalStockEqvNotional.Value :
(t.SpotPrice ?? 0.0) * (t.OriginalNotional ?? 0),
BuyCount = t.BuySell == "买入" ? 0 : 1,//从客户角度看
SellCount = t.BuySell == "卖出" ? 0 : 1,//从客户角度看
TodayCount = t.TradeDate == searchDate ? 1 : 0
};
var allTradeQuerySum = from t in allTradeQuery
group t by t.ClientId into g
select new
{
ClientId = g.Key,
SellNotionalPrincipal = g.Sum(a => a.SellCount * a.OriginalStockEqvNotional),
BuyNotionalPrincipal = g.Sum(a => a.BuyCount * a.OriginalStockEqvNotional),
BuyCount = g.Sum(n => n.BuyCount),
SellCount = g.Sum(n => n.SellCount),
TodayCount = g.Sum(n => n.TodayCount),
TodayNotionalPrincipal = g.Sum(n => n.TodayCount * n.OriginalStockEqvNotional)
};
var tradeSumDic = allTradeQuerySum.ToDictionary(n => n.ClientId);
var tradePosiQuery = from t in allTradeQuery
join p in db.eod_swap_position on t.id equals p.SwapTradeId
where !p.Invalid
select new
{
t.id,
t.ClientId,
p
};
foreach (var balance in lastClientBalances)
{
if (tradeSumDic.TryGetValue(balance.ClientId, out var dicItem))
{
balance.SellNotionalPrincipal = dicItem.SellNotionalPrincipal;
balance.BuyNotionalPrincipal = dicItem.BuyNotionalPrincipal;
balance.BuyCount = dicItem.BuyCount;
balance.SellCount = dicItem.SellCount;
balance.TradeCount = dicItem.TodayCount;
balance.TodayNotionalPrincipal = dicItem.TodayNotionalPrincipal;
balance.TotalNotionalPrincipal = balance.SellNotionalPrincipal + balance.BuyNotionalPrincipal;
balance.TotalTradeCount = balance.BuyCount + balance.SellCount;
}
var clientTradePosiQuery = tradePosiQuery.Where(x => x.ClientId == balance.ClientId && x.p.PosiQuantity > 0 && x.p.ValueDate == searchDate);
balance.PositionCount = clientTradePosiQuery.Select(s=>s.id).Distinct().Count();
var PosiNotionalValue = clientTradePosiQuery.Sum(o => o.p.PosiNotionalValue);
balance.PositionNotionalPrincipal = Convert.ToDouble(PosiNotionalValue);
}
}
return lastClientBalances;
}
/// <summary>
/// 获取预付金率设置
/// </summary>
/// <param name="clientId"></param>
/// <param name="clientMarginTemplates"></param>
/// <returns></returns>
private static client_marginrate GetClientMarginRate(int clientId, List<client_marginrate> clientMarginTemplates)
{
var marinRate = clientMarginTemplates.Where(x => x.ClientId == clientId ).FirstOrDefault();
if (marinRate == null)
{
marinRate = clientMarginTemplates.Where(x => x.ClientId == 0).FirstOrDefault();
}
if (marinRate == null)
{
marinRate = new client_marginrate
{
InitMarginRate = 1,
MaintenanceRate = 1,
};
}
return marinRate;
}
class ClientBalanceEx : ClientSettleBalance
{
public string UnderlyingCode { get; set; }
}
class Pairs
{
public ClientBalanceDaily tdaily { get; set; }
public ClientBalanceGap tgap { get; set; }
}
/// <summary>
/// 获取所有子客户id
/// </summary>
public static List<int> GetSubclientId(int id)
{
return InnerGetSubclientId(id, new HashSet<int>());
}
private static List<int> InnerGetSubclientId(int id, HashSet<int> checkSet)
{
checkSet ??= new HashSet<int>();
if (!checkSet.Add(id))
{
checkSet.Clear();
var pid = id;
var list = new List<string>();
for (var i = 0; i < 100; i++)
{
if (pid <= 0 || !checkSet.Add(pid)) break;
var client = DataCacheProvider.GetClientDataSource().GetData(pid);
if (client == null)
{
break;
}
else
{
list.Add(client.Name);
pid = client.ParentId;
}
}
if (list.Count > 0)
{
list.Add(list[0]);
}
throw new ServiceFaultException("客户父子关系产生了循环依赖:" + string.Join("->", list));
}
var result = new List<int>() { id };
var clientIdList = DataCacheProvider.GetClientDataSource().AsQueryable(O => O.ParentId == id).Select(O => O.id).ToList();
foreach (var c in clientIdList)
{
result.AddRange(InnerGetSubclientId(c, checkSet));
}
return result;
}
}
}