1676 lines
77 KiB
C#
1676 lines
77 KiB
C#
using BaseOUDAL;
|
||
using Newtonsoft.Json;
|
||
using System.ComponentModel.DataAnnotations.Schema;
|
||
using System.Reflection;
|
||
using YLErp.BLL;
|
||
using YLErp.Configuration;
|
||
using YLErp.Helpers;
|
||
using YLErp.Model.Enum;
|
||
using YLErp.Modules.CalculationModule;
|
||
|
||
namespace YLErp.Modules.EodModule.SettlementModule
|
||
{
|
||
/// <summary>
|
||
/// 客户结算
|
||
/// </summary>
|
||
public class EodClientBalanceCalcV2 : EodSettleServiceBaseV2
|
||
{
|
||
readonly DateTime balanceDate;
|
||
readonly double marginRatio, marginMaxRatio;
|
||
readonly MyComparer _myComparer;
|
||
|
||
public EodClientBalanceCalcV2(EodSettlementContextV2 context, bool compareMode = false) : base(context)
|
||
{
|
||
balanceDate = _context.SettleDate;
|
||
|
||
//保证金可取上浮比率
|
||
marginRatio = _context.SystemValue.MarginRatio ?? 0.15;
|
||
marginMaxRatio = marginRatio + 0.02;
|
||
|
||
DbContext.Database.SetCommandTimeout(600);
|
||
|
||
if (compareMode)
|
||
{
|
||
_myComparer = new MyComparer();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 客户结算
|
||
/// </summary>
|
||
public void ClientBalanceCalc()
|
||
{
|
||
var reqClientIds = _context.Request.ClientIds;
|
||
var preBalanceDate = _context.PreSettleDate;
|
||
var clientDb = DbContextFactory.GetClientDbContext(OptUser);
|
||
|
||
//获取所有客户信息
|
||
var clients = GetClients(clientDb, reqClientIds);
|
||
|
||
//获取客户所有交易信息(所及为客户所有确认交易,以及当日平仓或者当日执行的交易)
|
||
var trades = _context.OtcTrades;
|
||
|
||
//获取所有用户当日Eod_Risk
|
||
IQueryable<EodTradeRisk> eodRiskList = null;
|
||
//循环客户信息计算客户资金信息
|
||
IQueryable<EodTradePosition> eodpnlList = null;
|
||
if (PS.Config.Is国投)
|
||
{
|
||
eodRiskList = DbContext.eod_trade_risk_openvol.Where(t => t.ValueDate == balanceDate);
|
||
eodpnlList = DbContext.eod_trade_position_openvol.Where(t => t.ValueDate == balanceDate);
|
||
}
|
||
else if (PS.Config.Company == CompanyEnum.格林大华)
|
||
{
|
||
eodRiskList = DbContext.eod_trade_risk.Where(t => t.ValueDate == balanceDate);
|
||
eodpnlList = DbContext.eod_trade_position.Where(t => t.ValueDate == balanceDate);
|
||
}
|
||
else
|
||
{
|
||
eodRiskList = DbContext.eod_trade_risk.Where(t => t.ValueDate == balanceDate);
|
||
eodpnlList = DbContext.eod_trade_position.Where(t => t.ValueDate == balanceDate);
|
||
}
|
||
|
||
List<int> frozenClientIdList = null, normalClientIdList = null;
|
||
|
||
if (_context.IsCurrentDay)
|
||
{
|
||
frozenClientIdList = new List<int>(50);
|
||
normalClientIdList = new List<int>(50);
|
||
}
|
||
|
||
var newClientBalanceDaily = new List<ClientBalanceDaily>(100);
|
||
|
||
foreach (var client in clients)
|
||
{
|
||
_context.CancellationToken.ThrowIfCancellationRequested();
|
||
|
||
var daily = ProcessClientBalance(client, _context.OtcTrades, eodpnlList, eodRiskList);
|
||
|
||
newClientBalanceDaily.Add(daily);
|
||
|
||
if (_context.IsCurrentDay)
|
||
{
|
||
if (daily.State == "冻结")
|
||
{
|
||
if (client.PendingMarginCallPayment != 1)
|
||
{
|
||
frozenClientIdList.Add(daily.ClientId);
|
||
}
|
||
}
|
||
else if (daily.State == "正常")
|
||
{
|
||
if (client.PendingMarginCallPayment != 0)
|
||
{
|
||
normalClientIdList.Add(daily.ClientId);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (_myComparer != null)
|
||
{
|
||
var dataOld = DbContext.ClientBalanceDaily.FirstOrDefault(n => n.BalanceDate == balanceDate && n.ClientId == client.id);
|
||
_myComparer.Compare(client, daily, dataOld);
|
||
}
|
||
}
|
||
|
||
if (_myComparer != null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
#region DB删除历史数据 增加当日数据
|
||
|
||
//删除 当日导入的old日数据
|
||
ClientBalanceDaily ct1;
|
||
if (reqClientIds == null)
|
||
{
|
||
DbContext.BulkDelete<ClientBalanceDaily>($"{nameof(ct1.BalanceDate)}='{balanceDate.ToSqlDate()}'");
|
||
}
|
||
else
|
||
{
|
||
DbContext.BulkDelete<ClientBalanceDaily>(
|
||
$"{nameof(ct1.BalanceDate)}='{balanceDate.ToSqlDate()}' AND {nameof(ct1.ClientId)} in @clientIds"
|
||
, new { clientIds = reqClientIds });
|
||
}
|
||
|
||
DbContext.ClientBalanceDaily.AddRange(newClientBalanceDaily);
|
||
DbContext.SaveChanges();
|
||
#endregion
|
||
|
||
//更新客户表是否追保
|
||
if (_context.IsCurrentDay)
|
||
{
|
||
var sql = "";
|
||
|
||
if (frozenClientIdList.Count > 0)
|
||
{
|
||
sql = string.Format("update client set PendingMarginCallPayment=1 where id in ({0});"
|
||
, string.Join(",", frozenClientIdList));
|
||
}
|
||
|
||
if (normalClientIdList.Count > 0)
|
||
{
|
||
sql += string.Format("update client set PendingMarginCallPayment=0 where id in ({0});"
|
||
, string.Join(",", normalClientIdList));
|
||
}
|
||
if (!string.IsNullOrWhiteSpace(sql))
|
||
{
|
||
clientDb.Database.ExecuteSqlRaw(sql);
|
||
}
|
||
}
|
||
}
|
||
|
||
//计算客户资金
|
||
private ClientBalanceDaily ProcessClientBalance(ClientDto client, IEnumerable<trade> todayTrades, IQueryable<EodTradePosition> eodpnlList, IQueryable<EodTradeRisk> eodRiskList)
|
||
{
|
||
var preDaily = client.PreDaily;
|
||
var eodPriceProvider = _context.GetEodPriceProvider().GetPriceProvider();
|
||
|
||
var fundObject = new FundObject();
|
||
var currencyCodes = _context.CurrencyCodes;
|
||
var currencyProvider = _context.EodCurrencyProvider;
|
||
|
||
var underlyDataSource = DataCacheProvider.GetUnderlyingDataSource();
|
||
var varietyDataSource = DataCacheProvider.GetVarietyDataSource();
|
||
|
||
foreach (var currencyCode in currencyCodes)
|
||
{
|
||
fundObject.InFund.Add(currencyCode, 0);
|
||
fundObject.OutFund.Add(currencyCode, 0);
|
||
fundObject.NetFund.Add(currencyCode, 0);
|
||
fundObject.InFundOther.Add(currencyCode, 0);
|
||
fundObject.OutFundOther.Add(currencyCode, 0);
|
||
fundObject.OtherFund.Add(currencyCode, 0);
|
||
fundObject.TodayRemainFund.Add(currencyCode, 0);
|
||
fundObject.LastDayRemainFund.Add(currencyCode, 0);
|
||
}
|
||
|
||
#region 变量初始化
|
||
|
||
//入金
|
||
var inFund = 0.0;
|
||
//出金
|
||
var outFund = 0.0;
|
||
//其他收入
|
||
var inFundOther = 0.0;
|
||
//其他支出
|
||
var outFundOther = 0.0;
|
||
//当日浮动盈亏
|
||
var CurrPnl = 0.0;
|
||
//期权空头浮动盈利=∑max(期权空头持仓*(期权合约成本价-期权合约现价), 0) 从客户角度看的
|
||
var ClientSellPositionPnl = 0.0;
|
||
//今日可用资金
|
||
var CurrAvailAmount = 0.0;
|
||
//今日可用资金
|
||
var LastDayAvailAmount = 0.0;
|
||
//当日资金变动
|
||
var CurrChangeAmount = 0.0;
|
||
//资信等级
|
||
//credit_rating creditRating = null;
|
||
//授信额度
|
||
var lineOfCredit = 0.0;
|
||
//用户持仓价值
|
||
double? clientPv;
|
||
double? roundedClientPv;
|
||
//用户卖出部分持仓价值
|
||
double? clientSellPv;
|
||
//客户持仓交易预付金总和,客户买入为正,客户卖出为负
|
||
double? PrepaymentAmount;
|
||
//期权费收支
|
||
var OptionPremium = 0.0;
|
||
//期权费收支--互换
|
||
var OptionPremiumSwap = 0.0;
|
||
//结算收支(平仓行权)
|
||
var SettlementBalance = 0.0;
|
||
//平仓收支
|
||
var UnwindBalance = 0.0;
|
||
//行权收支
|
||
var ExerciseBalance = 0.0;
|
||
//实现盈亏
|
||
var WinLoss = 0.0;
|
||
//持仓期权费净额(客户角度卖出为负,买入为正)
|
||
var PositionPremiumNetCash = 0.0;
|
||
//权利金冻结(当日该客户所有持仓的卖出期权权利金)
|
||
var SellTradePrice = 0.0;
|
||
// 期初持仓交易净额
|
||
var LastDayPositionPremiumNetCash = 0.0;
|
||
//潜在行权盈余
|
||
var PotentialSurpluses = 0.0;
|
||
//权利金应付应收 总额
|
||
//var FrozenAndCopeWithExpirePremium = 0.0;
|
||
//净资金流入,其他资金,票息,互换收益,保证金余额,冻结权利金(未到期支付),冻结资金
|
||
double NetFund = 0.0, OtherFund = 0.0, Coupon = 0.0, SwapBalance = 0.0, MarginBalance, FrozenPremium, FrozenBalance = 0.0;
|
||
//应付到期权利金,应付存续权利金,应收存续权力金,了结权利金
|
||
double CopeWithExpirePremium, CopeWithLastPremium, ReceivablePremium, EndPremium = 0.0;
|
||
//未了结名义成交金额
|
||
var TotalNominal = 0.0;
|
||
//应付保证金,可提取保证金
|
||
double PayableMargin = 0d, AdvisableMargin = 0d, DeltaMargin = 0d, SwapPayableMargin = 0.0;
|
||
//双向保证金
|
||
var TwoSideMargin = 0.0;
|
||
var OtherSideMargin = 0.0;
|
||
var MySideMargin = 0.0;
|
||
//额外追保
|
||
var AdditionalMargin = 0.0;
|
||
//追保金额
|
||
var Margin = 0.0;
|
||
//昨日抵押品价值
|
||
var LastGuaranteesTotalAmount = 0.0;
|
||
//持仓名义本金规模
|
||
var AvailableStockEqvNotional = 0.0;
|
||
//潜在风险暴露
|
||
var PFE = 0d;
|
||
//
|
||
ClientBalanceDaily clientbalancedaily = null;
|
||
#endregion
|
||
|
||
#region 客户授信 资信等级 客户昨日现金 clientbalancedaily对象初始化
|
||
|
||
//获取客户授信
|
||
lineOfCredit = client.CreditSum;
|
||
|
||
clientbalancedaily = new ClientBalanceDaily()
|
||
{
|
||
ClientId = client.id,
|
||
ClientName = client.Name,
|
||
ClientNumber = client.Number,
|
||
BalanceDate = balanceDate
|
||
};
|
||
|
||
//获取用户最后结算日可用资金
|
||
if (preDaily != null)
|
||
{
|
||
if (!string.IsNullOrEmpty(preDaily.FundJson))
|
||
{
|
||
preDaily.FundObject = JsonConvert.DeserializeObject<FundObject>(preDaily.FundJson);
|
||
|
||
if (preDaily.FundObject.InFund.Count() == 1 && preDaily.FundObject.InFund.ContainsKey(string.Empty) && currencyCodes.FirstOrDefault() != string.Empty)
|
||
{
|
||
if (string.IsNullOrEmpty(client.SettlementCurrency))
|
||
{
|
||
throw new Exception("客户:" + client.Name + "未配置结算币种");
|
||
}
|
||
preDaily.FundObject.InFund.Add(client.SettlementCurrency, preDaily.InFund ?? 0);
|
||
preDaily.FundObject.InFundSum.Add(client.SettlementCurrency, preDaily.InFundSum ?? 0);
|
||
preDaily.FundObject.OutFund.Add(client.SettlementCurrency, preDaily.OutFund ?? 0);
|
||
preDaily.FundObject.OutFundSum.Add(client.SettlementCurrency, preDaily.OutFundSum ?? 0);
|
||
preDaily.FundObject.NetFund.Add(client.SettlementCurrency, preDaily.NetFund ?? 0);
|
||
preDaily.FundObject.NetFundSum.Add(client.SettlementCurrency, preDaily.NetFundSum ?? 0);
|
||
preDaily.FundObject.OtherFund.Add(client.SettlementCurrency, preDaily.OtherFund ?? 0);
|
||
preDaily.FundObject.OtherFundSum.Add(client.SettlementCurrency, preDaily.OtherFundSum ?? 0);
|
||
preDaily.FundObject.TodayRemainFund.Add(client.SettlementCurrency, preDaily.ToDayRemainFund ?? 0);
|
||
}
|
||
|
||
foreach (var currencyCode in currencyCodes)
|
||
{
|
||
if (preDaily.FundObject.TodayRemainFund.ContainsKey(currencyCode))
|
||
{
|
||
fundObject.LastDayRemainFund[currencyCode] = preDaily.FundObject.TodayRemainFund[currencyCode];
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
preDaily.FundObject = new FundObject() { };
|
||
if (currencyCodes.Count() == 1 && currencyCodes.FirstOrDefault() == string.Empty)
|
||
{
|
||
preDaily.FundObject = new FundObject();
|
||
preDaily.FundObject.InFund.Add(string.Empty, preDaily.InFund ?? 0);
|
||
preDaily.FundObject.InFundSum.Add(string.Empty, preDaily.InFundSum ?? 0);
|
||
preDaily.FundObject.OutFund.Add(string.Empty, preDaily.OutFund ?? 0);
|
||
preDaily.FundObject.OutFundSum.Add(string.Empty, preDaily.OutFundSum ?? 0);
|
||
preDaily.FundObject.NetFund.Add(string.Empty, preDaily.NetFund ?? 0);
|
||
preDaily.FundObject.NetFundSum.Add(string.Empty, preDaily.NetFundSum ?? 0);
|
||
preDaily.FundObject.OtherFund.Add(string.Empty, preDaily.OtherFund ?? 0);
|
||
preDaily.FundObject.OtherFundSum.Add(string.Empty, preDaily.OtherFundSum ?? 0);
|
||
fundObject.LastDayRemainFund[string.Empty] = preDaily.ToDayRemainFund ?? 0;
|
||
}
|
||
else
|
||
{
|
||
preDaily.FundObject.InFund.Add(client.SettlementCurrency, preDaily.InFund ?? 0);
|
||
preDaily.FundObject.InFundSum.Add(client.SettlementCurrency, preDaily.InFundSum ?? 0);
|
||
preDaily.FundObject.OutFund.Add(client.SettlementCurrency, preDaily.OutFund ?? 0);
|
||
preDaily.FundObject.OutFundSum.Add(client.SettlementCurrency, preDaily.OutFundSum ?? 0);
|
||
preDaily.FundObject.NetFund.Add(client.SettlementCurrency, preDaily.NetFund ?? 0);
|
||
preDaily.FundObject.NetFundSum.Add(client.SettlementCurrency, preDaily.NetFundSum ?? 0);
|
||
preDaily.FundObject.OtherFund.Add(client.SettlementCurrency, preDaily.OtherFund ?? 0);
|
||
preDaily.FundObject.OtherFundSum.Add(client.SettlementCurrency, preDaily.OtherFundSum ?? 0);
|
||
fundObject.LastDayRemainFund[client.SettlementCurrency] = preDaily.ToDayRemainFund ?? 0;
|
||
}
|
||
}
|
||
|
||
LastDayPositionPremiumNetCash = preDaily.PositionPremiumNetCash ?? 0.0;
|
||
LastGuaranteesTotalAmount = preDaily.TodayRemianFundProduct ?? 0.0;
|
||
}
|
||
AvailableStockEqvNotional = client.CreditStockEqvNotionalSum -
|
||
(todayTrades.Where(O => ConsTrade.PositionTradeStatusList.Contains(O.TradeStatus) && O.ClientId == client.id).Sum(O => (double?)O.StockEqvNotional) ?? 0.0);
|
||
#endregion
|
||
|
||
#region 出金 入金 当日可用资金计算
|
||
|
||
//获取客户所有出入金列表
|
||
if (client.EntryexitList != null)
|
||
{
|
||
var tradeCashGroupIds = client.EntryexitList.Where(y => y.IsGroup == 1).Select(y => y.TradeCashId).ToArray();
|
||
var tradeCashGroups = DbContext.trade_cash.Where(x => tradeCashGroupIds.Contains(x.id));
|
||
foreach (var clientEntryexit in client.EntryexitList)
|
||
{
|
||
if (null == clientEntryexit.Direction)
|
||
{
|
||
throw new Exception("客户:" + client.Name + "有一条出入记录存在出入金方向存在问题!");
|
||
}
|
||
|
||
if (clientEntryexit.CurrencyCode == null)
|
||
{
|
||
clientEntryexit.CurrencyCode = "";
|
||
}
|
||
//之前单币种环境改为多币种环境后历史数据为""和配置的币种匹配不上
|
||
if (currencyCodes.Count() >= 1 && string.IsNullOrWhiteSpace(clientEntryexit.CurrencyCode))
|
||
{
|
||
if (currencyCodes.Contains("CNY"))
|
||
{
|
||
clientEntryexit.CurrencyCode = "CNY";
|
||
}
|
||
else if (currencyCodes.Contains("RMB"))
|
||
{
|
||
clientEntryexit.CurrencyCode = "RMB";
|
||
}
|
||
}
|
||
|
||
if (clientEntryexit.Direction.Equals("入金"))
|
||
{
|
||
if (fundObject.InFund.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.InFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.InFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
|
||
if (fundObject.NetFund.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.NetFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.NetFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
}
|
||
else if (clientEntryexit.Direction.Equals("出金"))
|
||
{
|
||
if (fundObject.OutFund.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.OutFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.OutFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
|
||
|
||
if (fundObject.NetFund.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.NetFund[clientEntryexit.CurrencyCode] -= clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.NetFund.Add(clientEntryexit.CurrencyCode, -clientEntryexit.Money ?? 0);
|
||
}
|
||
}
|
||
else if (clientEntryexit.Direction.Equals("其他收入"))
|
||
{
|
||
if (fundObject.InFundOther.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.InFundOther[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.InFundOther.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
|
||
if (fundObject.OtherFund.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.OtherFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.OtherFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
|
||
}
|
||
else if (clientEntryexit.Direction.Equals("其他支出"))
|
||
{
|
||
if (fundObject.OutFundOther.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.OutFundOther[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.OutFundOther.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
|
||
if (fundObject.OtherFund.ContainsKey(clientEntryexit.CurrencyCode))
|
||
{
|
||
fundObject.OtherFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0;
|
||
}
|
||
else
|
||
{
|
||
fundObject.OtherFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (ClientCashInCashOut.系统操作_期权费.Equals(clientEntryexit.Action))
|
||
{
|
||
//CurrPnl += clientEntryexit.Money ?? 0.0;
|
||
CurrChangeAmount += clientEntryexit.Money ?? 0.0;
|
||
OptionPremium += clientEntryexit.Money ?? 0.0;
|
||
}
|
||
//黑箱了结资金按照主交易来进行归类
|
||
else if ((ClientCashInCashOut.系统操作_行权费.Equals(clientEntryexit.Action) || ClientCashInCashOut.系统操作_平仓费.Equals(clientEntryexit.Action)) && clientEntryexit.IsGroup != 2)
|
||
{
|
||
var money = clientEntryexit.Money ?? 0;
|
||
//如果是黑箱主交易了结资金(主交易Money没有赋值),取对应tradeCash数据
|
||
if (money == 0 && clientEntryexit.IsGroup == 1)
|
||
{
|
||
var tradeCash = tradeCashGroups.FirstOrDefault(x => x.id == clientEntryexit.TradeCashId);
|
||
money = -(tradeCash?.Amount ?? 0);
|
||
}
|
||
|
||
//CurrPnl += money;
|
||
CurrChangeAmount += money;
|
||
SettlementBalance += money;
|
||
if (ClientCashInCashOut.系统操作_平仓费.Equals(clientEntryexit.Action))
|
||
{
|
||
UnwindBalance += money;
|
||
}
|
||
else
|
||
{
|
||
ExerciseBalance += money;
|
||
}
|
||
}
|
||
else if (ClientCashInCashOut.系统操作_票息.Equals(clientEntryexit.Action))
|
||
{
|
||
var money = clientEntryexit.Money ?? 0;
|
||
//如果是黑箱主交易了结资金(主交易Money没有赋值),取对应tradeCash数据
|
||
if (money == 0 && clientEntryexit.IsGroup == 1)
|
||
{
|
||
var tradeCash = tradeCashGroups.FirstOrDefault(x => x.id == clientEntryexit.TradeCashId);
|
||
money = -(tradeCash?.Amount ?? 0);
|
||
}
|
||
|
||
CurrChangeAmount += money;
|
||
Coupon += money;
|
||
}
|
||
}
|
||
if (ClientCashInCashOut.已确认.Equals(clientEntryexit.State))
|
||
{
|
||
clientEntryexit.SettleDate = balanceDate;
|
||
clientEntryexit.State = ClientCashInCashOut.已结算;
|
||
}
|
||
}
|
||
}
|
||
|
||
//获取客户所有出入金列表
|
||
if (client.EntryexitSwapList != null)
|
||
{
|
||
foreach (var clientEntryexit in client.EntryexitSwapList)
|
||
{
|
||
if (null == clientEntryexit.Direction)
|
||
{
|
||
throw new Exception("客户:" + client.Name + "有一条出入记录存在出入金方向存在问题!");
|
||
}
|
||
|
||
if (clientEntryexit.CurrencyCode == null)
|
||
{
|
||
clientEntryexit.CurrencyCode = "";
|
||
}
|
||
//之前单币种环境改为多币种环境后历史数据为""和配置的币种匹配不上
|
||
if (currencyCodes.Count() >= 1 && string.IsNullOrWhiteSpace(clientEntryexit.CurrencyCode))
|
||
{
|
||
if (currencyCodes.Contains("CNY"))
|
||
{
|
||
clientEntryexit.CurrencyCode = "CNY";
|
||
}
|
||
else if (currencyCodes.Contains("RMB"))
|
||
{
|
||
clientEntryexit.CurrencyCode = "RMB";
|
||
}
|
||
}
|
||
|
||
if (ClientCashInCashOut.系统操作_期权费.Equals(clientEntryexit.Action))
|
||
{
|
||
CurrChangeAmount += clientEntryexit.Money ?? 0.0;
|
||
OptionPremiumSwap += clientEntryexit.Money ?? 0.0;
|
||
}
|
||
else if (ClientCashInCashOut.系统操作_平仓费.Equals(clientEntryexit.Action))
|
||
{
|
||
CurrChangeAmount += clientEntryexit.Money ?? 0.0;
|
||
SwapBalance += clientEntryexit.Money ?? 0.0;
|
||
}
|
||
else if (ClientCashInCashOut.系统操作_互换.Equals(clientEntryexit.Action))
|
||
{
|
||
CurrChangeAmount += clientEntryexit.Money ?? 0.0;
|
||
SwapBalance += clientEntryexit.Money ?? 0.0;
|
||
}
|
||
if (ClientCashInCashOut.已确认.Equals(clientEntryexit.State))
|
||
{
|
||
clientEntryexit.SettleDate = balanceDate;
|
||
clientEntryexit.State = ClientCashInCashOut.已结算;
|
||
}
|
||
}
|
||
}
|
||
|
||
foreach (var item in currencyCodes)
|
||
{
|
||
if (fundObject.TodayRemainFund.ContainsKey(item))
|
||
{
|
||
fundObject.TodayRemainFund[item] = fundObject.LastDayRemainFund[item] + fundObject.NetFund[item] + fundObject.OtherFund[item];
|
||
}
|
||
else
|
||
{
|
||
fundObject.TodayRemainFund.Add(item, fundObject.LastDayRemainFund[item] + fundObject.NetFund[item] + fundObject.OtherFund[item]);
|
||
}
|
||
|
||
if ((client.SettlementCurrency ?? "CNY") == item || item == "")
|
||
{
|
||
fundObject.TodayRemainFund[item] += CurrChangeAmount;
|
||
}
|
||
|
||
var rateObj = new eod_currency_rate
|
||
{
|
||
Rate = 1,
|
||
SellRate = 1,
|
||
BuyRate = 1,
|
||
ForeignCurrency = item,
|
||
LocalCurrency = client.SettlementCurrency,
|
||
};
|
||
|
||
if (PS.Config.ErpElement.SupportMultiCurrency)
|
||
{
|
||
currencyProvider.TryGetCurrencyRate(item, client.SettlementCurrency, out rateObj);
|
||
if (rateObj == null)
|
||
{
|
||
_context.RaiseError("结算客户资金", $"[{client.Name}]找不到汇率:{item}{client.SettlementCurrency}");
|
||
}
|
||
}
|
||
|
||
CurrAvailAmount += fundObject.TodayRemainFund[item] * rateObj.Rate;
|
||
LastDayAvailAmount += fundObject.LastDayRemainFund[item] * rateObj.Rate;
|
||
inFund += fundObject.InFund[item] * rateObj.Rate;
|
||
outFund += fundObject.OutFund[item] * rateObj.Rate;
|
||
NetFund += fundObject.NetFund[item] * rateObj.Rate;
|
||
inFundOther += fundObject.InFundOther[item] * rateObj.Rate;
|
||
outFundOther += fundObject.OutFundOther[item] * rateObj.Rate;
|
||
OtherFund += fundObject.OtherFund[item] * rateObj.Rate;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 抵押品
|
||
//抵押品资金价值
|
||
var GuaranteesTotalAmount = 0.0;
|
||
if (client.ClientProductList != null)
|
||
{
|
||
foreach (var t in client.ClientProductList)
|
||
{
|
||
if (!t.UnderlyingId.HasValue || string.IsNullOrEmpty(t.UnderlyingCode))
|
||
{
|
||
throw new Exception($"抵押品,出入金单号[{t.ProductNumber}]标的ID[{t.UnderlyingId}]未找到对应标的基本信息!");
|
||
}
|
||
if (eodPriceProvider.TryGetPrice(t.UnderlyingCode, out var price))
|
||
{
|
||
GuaranteesTotalAmount += (t.ProductAmount ?? 0) * (t.Rate ?? 0.0) * price;
|
||
}
|
||
else
|
||
{
|
||
throw new Exception($"抵押品,出入金单号[{t.ProductNumber}]标的[{t.UnderlyingCode}]在{balanceDate:yyyy-MM-dd}收盘价不存在!");
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 当日冻结权利金 当日应收权利金 潜在行权盈余 持仓市值 持仓Pnl
|
||
//持仓交易
|
||
var positionTrades = todayTrades.Where(t => t.TradeStatus.Equals(ConsTrade.确认成交) && t.ClientId == client.id).ToList();
|
||
//var tradeIds = clientTrades.Where(t => t.ClientId == client.id).Select(t => t.id).ToList();
|
||
//获取所有持仓交易ids
|
||
var positionTradeIds = positionTrades == null || positionTrades.Count == 0 ? new List<int>() : positionTrades.Select(t => t.id).ToList();
|
||
//获取客户冻结资金
|
||
var clientFrozenFund = client.FrozenFunds;
|
||
//当前持仓并且未到支付日的卖出交易(客户为买入,渠道为卖出)则为冻结的权利金
|
||
//FrozenPremium = positionTrade == null || positionTrade.Count == 0 ? 0.0 : (positionTrade.Where(t => t.PremiumPayDate > balanceDate && t.BuySell == "卖出").Sum(t => t.TradePrice ?? 0.0));
|
||
FrozenPremium = clientFrozenFund.FrozenPayableOptionMoney;
|
||
//应收存续权利金
|
||
//ReceivablePremium = positionTrade == null || positionTrade.Count == 0 ? 0.0 : (positionTrade.Where(t => t.PremiumPayDate > balanceDate && t.BuySell == "买入").Sum(t => t.TradePrice ?? 0.0));
|
||
ReceivablePremium = clientFrozenFund.FrozenReceivableOptionMoney;
|
||
//冻结保证金(绝对值)
|
||
var FrozenMarginMoney = clientFrozenFund.FrozenMarginMoney;
|
||
//冻结资金=冻结权利金+到期停牌股票名义金额×6.5%*30/365(默认收取一个月资金利息,多追少补) //todo 此处需要增加股票停复牌信息,同时检查到期交易不能默认执行到期
|
||
//FrozenBalance = FrozenPremium;
|
||
//应付到期权利金
|
||
CopeWithExpirePremium = OptionPremium + OptionPremiumSwap;
|
||
//应付存续权利金
|
||
CopeWithLastPremium = FrozenPremium;
|
||
//获取客户持仓交易的pv以及浮动盈亏
|
||
var eodpnlQuery = eodpnlList.Where(t => positionTradeIds.Contains(t.TradeId)).ToArray();
|
||
//未了结名义成交金额 todo //持仓的买入 以及卖出是否都统计
|
||
TotalNominal = positionTrades == null || positionTrades.Count == 0 ? 0 : positionTrades.Sum(t => t.UnderlyingInstrumentType == "Stock" ? t.StockEqvNotional : (t.Notional * (t.SpotPrice ?? 0.0)));
|
||
//计算潜在客户行权盈余 max{名义成交金额*(标的当日结算价-标的初始价格)/行权价格, 0}
|
||
foreach (var t in positionTrades)
|
||
{
|
||
if (t.TradeType != "现金流交易")
|
||
{
|
||
var spotPrice = t.SpotPrice ?? t.SpotPrice ?? 0.0;
|
||
var nominal = t.UnderlyingInstrumentType == "Stock" ? t.StockEqvNotional : (t.Notional * spotPrice);
|
||
if (!eodPriceProvider.TryGetPrice(t.UnderlyingCode, out var nowPrice))
|
||
{
|
||
throw new Exception($"找不到收盘价({t.UnderlyingCode}),无法结算!");
|
||
}
|
||
var Strike = t.IsMoneynessOptionData ? ((t.Strike ?? 0) * t.SpotPrice ?? 0) : t.Strike ?? 0;
|
||
//如果期初价格未0则已份额计算潜在行权盈余
|
||
if (spotPrice == 0)
|
||
{
|
||
PotentialSurpluses += Math.Max(Strike == 0 ? 0 : (t.Notional * (nowPrice - Strike) * ("Call".Equals(t.CallPut) ? 1 : -1)), 0) * TradeCalcHelper.GetSign(t.BuySell) * -1;
|
||
}
|
||
else
|
||
{
|
||
PotentialSurpluses += Math.Max(Strike == 0 ? 0 : (nominal * (nowPrice - Strike) / spotPrice * ("Call".Equals(t.CallPut) ? 1 : -1)), 0) * TradeCalcHelper.GetSign(t.BuySell) * -1;
|
||
}
|
||
}
|
||
if (t.BuySell == "买入")
|
||
{
|
||
var um = underlyDataSource.GetData(t.UnderlyingCode);
|
||
//deltaS/S
|
||
var rate = um?.DeltaS_S ?? 0;
|
||
if (!rate.IsNormalize())
|
||
{
|
||
var variety = varietyDataSource.GetData(um.CommodityCode);
|
||
if (ConsGlobal.InstrumentType.IsStockIndex(um?.UnderlyingInstrumentType) || ConsGlobal.InstrumentType.IsStockIF(um?.UnderlyingInstrumentType))
|
||
{
|
||
rate = variety.UpLimitValue;
|
||
}
|
||
else
|
||
{
|
||
rate = variety.Margin ?? 0;
|
||
}
|
||
}
|
||
var risk = eodRiskList.Where(O => O.TradeId == t.id).FirstOrDefault();
|
||
var pfe1 = t.StockEqvNotional == 0 ? (t.Notional * t.SpotPrice ?? 0) : t.StockEqvNotional;
|
||
|
||
var pfe2 = risk != null ? Math.Abs(risk.DeltaCash) * rate + 0.5 * 100 * rate * rate * Math.Abs(Math.Min(risk.GammaCash, 0)) : 0;
|
||
PFE += Math.Min(pfe1, pfe2);
|
||
}
|
||
}
|
||
|
||
//todo:收益互换没有OriginalNotional
|
||
PositionPremiumNetCash = positionTrades.Sum(t => -TradeCalcHelper.GetSign(t.BuySell) * ((t.TradePrice ?? 0) * (t.OriginalNotional != null && t.OriginalNotional != 0 ? t.Notional / t.OriginalNotional.Value : 1)));
|
||
|
||
//现金流交易没有份额的概念
|
||
SellTradePrice = positionTrades.Where(x => x.BuySell == "买入").Sum(
|
||
t => t.OriginalNotional.HasValue && t.OriginalNotional > 0 ? (t.TradePrice ?? 0) * t.Notional / t.OriginalNotional.Value : (t.TradePrice ?? 0));
|
||
|
||
//客户持仓交易预付金总和,客户买入为正,客户卖出为负
|
||
PrepaymentAmount = positionTrades.Sum(x => x.StockEqvNotional * (x.trade_snowball?.PrepaymentRatio ?? 0) * (x.BuySell == "卖出" ? 1 : -1));
|
||
|
||
if (client.TodayTradeCashList != null && client.TodayTradeCashList.Any())
|
||
{
|
||
WinLoss = client.TodayTradeCashList.Sum(tc =>
|
||
{
|
||
var cost = 0d;
|
||
if (tc.TradeType != "远期")
|
||
{
|
||
cost = TradeCalcHelper.GetSign(tc.BuySell) * tc.TradePrice * tc.TcUnwindPercentRateSum;
|
||
}
|
||
else
|
||
{
|
||
cost = -tc.TradePrice * tc.TcUnwindPercentRateSum;//远期开仓总费用占比
|
||
}
|
||
return cost - tc.TcAmountSum.OtcFormatValue(OtcFormatFlag.tradePrice);
|
||
});
|
||
|
||
//了结开仓费用
|
||
EndPremium = client.TodayTradeCashList.Sum(tc =>
|
||
{
|
||
var cost = 0d;
|
||
if (tc.TradeType != "远期")
|
||
{
|
||
cost = TradeCalcHelper.GetSign(tc.BuySell) * tc.TradePrice * tc.TcUnwindPercentRateSum;
|
||
}
|
||
else
|
||
{
|
||
cost = -tc.TradePrice * tc.TcUnwindPercentRateSum;//远期开仓总费用占比
|
||
}
|
||
return cost;
|
||
});
|
||
}
|
||
|
||
var eodPnlSum = new EodPnlSum();
|
||
|
||
if (eodpnlQuery.Any())
|
||
{
|
||
//todo: eodpnlQuery 确认成交的持仓数据 LastPvSum,TotalPnlSum 当天了结的没有计算
|
||
foreach (var x in eodpnlQuery)
|
||
{
|
||
eodPnlSum.LastPvSum -= x.LastPv;
|
||
eodPnlSum.PvSum -= x.Pv;
|
||
if (x.BuySell == "买入")
|
||
{
|
||
eodPnlSum.SellPvSum -= x.Pv;
|
||
}
|
||
eodPnlSum.RoundedPvSum -= x.RoundedPv;
|
||
eodPnlSum.TotalPnlSum -= x.TotalPnL;
|
||
eodPnlSum.PositionPnlSum -= x.PositionPnL;
|
||
eodPnlSum.RoundedPositionPnlSum -= x.RoundedPositionPnL;
|
||
|
||
//期权空头浮动盈利=∑max(期权空头持仓*(期权合约成本价-期权合约现价), 0) 从客户角度看的, 结构化交易需要将两条腿的空头Pnl合计
|
||
if (x.TradeType != "结构化交易" && x.ParentTradeId == 0 && x.BuySell == "买入")
|
||
{
|
||
ClientSellPositionPnl += Math.Max(-x.PositionPnL, 0);
|
||
}
|
||
}
|
||
|
||
if (_context.SystemValue.PotentialSurplusCalcMode == valuedate.PotentialSurplusCalcMode_Pv)
|
||
{
|
||
PotentialSurpluses = eodPnlSum.PvSum;
|
||
}
|
||
}
|
||
|
||
if (eodpnlList.Where(t => t.ClientId == client.id).Any())
|
||
{
|
||
eodPnlSum.DailyPnLSum = eodpnlList.Where(t => t.ClientId == client.id).Sum(q => q.DailyPnL) * (-1);//当日浮动盈亏
|
||
}
|
||
|
||
//合计持仓浮动盈亏
|
||
CurrPnl = eodPnlSum.DailyPnLSum;
|
||
|
||
clientPv = eodPnlSum.PvSum;
|
||
roundedClientPv = eodPnlSum.RoundedPvSum;
|
||
clientSellPv = eodPnlSum.SellPvSum;
|
||
#endregion
|
||
|
||
#region 应缴保证金 保证金余额 可取保证金 追保额度
|
||
//获取tradespan 追保金额 = (当日资金余额 - 维持保证金) + 授信额度
|
||
var clientSpan = client.ClientSpan;
|
||
if (clientSpan != null)
|
||
{
|
||
PayableMargin = clientSpan.WorstCastClientPayable ?? 0d;
|
||
DeltaMargin = clientSpan.DeltaMargin ?? 0d;
|
||
SwapPayableMargin = clientSpan.SwapWorstCastClientPayable ?? 0d;
|
||
TwoSideMargin = clientSpan.TwoSideMargin ?? 0d;
|
||
OtherSideMargin = clientSpan.OtherSideMargin ?? 0d;
|
||
MySideMargin = clientSpan.MySideMargin ?? 0d;
|
||
AdditionalMargin = (clientSpan.AdditionalWorstCastClientPayable) ?? 0d;
|
||
}
|
||
|
||
//冻结资金
|
||
FrozenBalance = ReceivablePremium - FrozenPremium - (clientFrozenFund.OutFunds + clientFrozenFund.RedeemFunds) - FrozenMarginMoney;
|
||
//保证金余额
|
||
MarginBalance = CurrAvailAmount + GuaranteesTotalAmount + FrozenBalance;
|
||
|
||
if (PS.Config.Is申万)
|
||
{
|
||
//期权空头浮动盈亏
|
||
MarginBalance -= ClientSellPositionPnl;
|
||
|
||
//空头持仓市值
|
||
MarginBalance -= Math.Abs((clientSellPv ?? 0));
|
||
}
|
||
else
|
||
{
|
||
//判断潜在行权盈余是否计入保证金余额
|
||
if ((valuedateBLL.SystemDate.IsPotentialSurplusUseMargin ?? 0) == 1)
|
||
{
|
||
MarginBalance += PotentialSurpluses;
|
||
}
|
||
}
|
||
//可取保证金为保证金余额 - 应缴保证金(上浮2%)
|
||
AdvisableMargin = Math.Max(MarginBalance + PayableMargin * marginMaxRatio / marginRatio, 0);
|
||
|
||
//计算追保金额 维持保证金带方向 所以计算追保金额是 为相加
|
||
var IsTradeCredit = (client.IsTradeCredit ?? 0) == 1;
|
||
//是否期权费授信
|
||
if (IsTradeCredit)
|
||
{
|
||
//期权费授信可以支付权利金 则保证金余额未0时 资金从
|
||
Margin = Math.Min(MarginBalance + lineOfCredit + PayableMargin, 0);
|
||
}
|
||
else
|
||
{
|
||
//期权费授信不可以支付权利金时
|
||
Margin = Math.Min(Math.Max(MarginBalance, 0) + lineOfCredit + PayableMargin, 0) + Math.Min(MarginBalance, 0);
|
||
}
|
||
#endregion
|
||
|
||
#region 国君收益互换--导入持仓
|
||
|
||
if (client.eodPositionSwapMannual != null && client.eodPositionSwapMannual.Any())
|
||
{
|
||
double swapMargin = 0.0;
|
||
double swappv = 0.0;
|
||
double swappnl = 0.0;
|
||
foreach (var x in client.eodPositionSwapMannual)
|
||
{
|
||
var underly = underlyDataSource.GetData(x.UnderlyingCode);
|
||
var variety = varietyDataSource.GetData(underly.UnderlyingTypeId);
|
||
|
||
currencyProvider.TryGetCurrencyRate(variety.QuoteCurrency, client.SettlementCurrency, out var rateObj);
|
||
//保证金导入是客户方向,其他值是交易员方向
|
||
swapMargin += (x.Margin) * rateObj.Rate;
|
||
swappv += (-x.PositionPnl + x.TotalFee) * rateObj.Rate;
|
||
swappnl += (-x.PositionPnl * rateObj.Rate);
|
||
}
|
||
PayableMargin -= swapMargin;
|
||
clientPv = (clientPv ?? 0) + swappv;
|
||
roundedClientPv = (roundedClientPv ?? 0) + swappv;
|
||
eodPnlSum.PositionPnlSum += swappnl;
|
||
eodPnlSum.RoundedPositionPnlSum += swappnl;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ClientBalacedaily ClientBalace对象赋值
|
||
//if (client.BoundSide == BoundSideEnum.南向 && clientSpan != null)
|
||
//{
|
||
// var credit = DbContext.credit.FirstOrDefault(x => x.CreditStartDate <= balanceDate && x.CreditDeadLine >= balanceDate && x.ClientId == client.id && x.ProcessStatus == "已审批");
|
||
// var PFECredit = credit != null ? credit.PFECredit : 0;
|
||
// clientSpan.PFEUsed = Math.Max(Math.Min((clientSpan.PFEUsed ?? 0) - CurrAvailAmount, PFECredit ?? 0), 0);
|
||
//}
|
||
clientbalancedaily.ToDayRemainFund = CurrAvailAmount;
|
||
clientbalancedaily.LastDayRemainFund = LastDayAvailAmount;
|
||
clientbalancedaily.PositionPremiumNetCash = PositionPremiumNetCash;
|
||
clientbalancedaily.SellTradePrice = SellTradePrice;
|
||
clientbalancedaily.LastDayPositionPremiumNetCash = LastDayPositionPremiumNetCash;
|
||
clientbalancedaily.WinLoss = WinLoss;
|
||
clientbalancedaily.InFund = inFund;
|
||
clientbalancedaily.OutFund = outFund;
|
||
clientbalancedaily.InFundOther = inFundOther;
|
||
clientbalancedaily.OutFundOther = outFundOther;
|
||
clientbalancedaily.BalanceDate = balanceDate;
|
||
clientbalancedaily.DayGainLoss = CurrPnl;
|
||
clientbalancedaily.PositionPnl = eodPnlSum.PositionPnlSum;
|
||
clientbalancedaily.RoundedPositionPnl = eodPnlSum.RoundedPositionPnlSum;
|
||
clientbalancedaily.ClientSellPositionPnl = ClientSellPositionPnl;
|
||
clientbalancedaily.TotalPnl = eodPnlSum.TotalPnlSum;
|
||
clientbalancedaily.DailyPnl = eodPnlSum.DailyPnLSum;
|
||
clientbalancedaily.OptionPremium = OptionPremium;
|
||
clientbalancedaily.OptionPremiumSwap = OptionPremiumSwap;
|
||
clientbalancedaily.SettlementBalance = SettlementBalance;
|
||
clientbalancedaily.UnwindBalance = UnwindBalance;
|
||
clientbalancedaily.Coupon = Coupon;
|
||
clientbalancedaily.SwapBalance = SwapBalance;
|
||
clientbalancedaily.ExerciseBalance = ExerciseBalance;
|
||
clientbalancedaily.AdvisableMargin = AdvisableMargin;
|
||
clientbalancedaily.TotalNominal = TotalNominal;
|
||
clientbalancedaily.Pv = clientPv ?? 0;
|
||
clientbalancedaily.RoundedPv = roundedClientPv ?? 0;
|
||
clientbalancedaily.SellPv = clientSellPv ?? 0;
|
||
clientbalancedaily.PrepaymentAmount = PrepaymentAmount;
|
||
clientbalancedaily.CopeWithLastPremium = CopeWithLastPremium;
|
||
clientbalancedaily.CopeWithExpirePremium = CopeWithExpirePremium;
|
||
clientbalancedaily.EndPremium = EndPremium;
|
||
clientbalancedaily.FrozenBalance = FrozenBalance;
|
||
clientbalancedaily.FrozenPremium = FrozenPremium;
|
||
clientbalancedaily.FrozenOutFund = clientFrozenFund.OutFunds;
|
||
clientbalancedaily.FrozenRedeemFunds = clientFrozenFund.RedeemFunds;
|
||
clientbalancedaily.MarginBalance = MarginBalance;
|
||
clientbalancedaily.NetFund = NetFund;
|
||
clientbalancedaily.OtherFund = OtherFund;
|
||
clientbalancedaily.IsTradeCredit = IsTradeCredit;
|
||
clientbalancedaily.Credit = lineOfCredit;
|
||
clientbalancedaily.CashDeposit = PayableMargin;
|
||
clientbalancedaily.PayableMargin = PayableMargin;
|
||
clientbalancedaily.DeltaMargin = DeltaMargin;
|
||
clientbalancedaily.SwapPayableMargin = SwapPayableMargin;
|
||
clientbalancedaily.TwoSideMargin = TwoSideMargin;
|
||
clientbalancedaily.OtherSideMargin = OtherSideMargin;
|
||
clientbalancedaily.MySideMargin = MySideMargin;
|
||
clientbalancedaily.IsPayableMarginManual = clientSpan?.ModifiedFlag;
|
||
clientbalancedaily.FrozenMarginMoney = FrozenMarginMoney;
|
||
clientbalancedaily.Margin = Margin;
|
||
clientbalancedaily.TodayRemianFundProduct = GuaranteesTotalAmount;
|
||
clientbalancedaily.CashInCashOutProductChange = GuaranteesTotalAmount - LastGuaranteesTotalAmount;
|
||
clientbalancedaily.PotentialSurpluses = PotentialSurpluses;
|
||
clientbalancedaily.OptId = UserId;
|
||
clientbalancedaily.OptName = UserName;
|
||
clientbalancedaily.OptDate = DateTime.Now;
|
||
clientbalancedaily.AdditionalMargin = AdditionalMargin;
|
||
clientbalancedaily.AvailableStockEqvNotional = AvailableStockEqvNotional;
|
||
clientbalancedaily.PFE = PFE;
|
||
clientbalancedaily.EAD = Math.Max(PFE - (clientbalancedaily.Pv ?? 0) - (clientbalancedaily.ToDayRemainFund ?? 0), 0);
|
||
if (PS.Config.Is厦门象屿)
|
||
{
|
||
var xmxyClient = new XiaMenXiangYuClientInfo
|
||
{
|
||
ClientId = client.id,
|
||
ClientName = client.Name,
|
||
ClientNumber = client.Number,
|
||
FundThreshold = client.FundThreshold
|
||
};
|
||
new XiaMenXiangYuCashService(this).ExecuteV2(xmxyClient, clientbalancedaily, fundObject, out var InOutFund, _context.SettleDate, positionTrades.Count);
|
||
NetFund += InOutFund;
|
||
MarginBalance += InOutFund;
|
||
}
|
||
|
||
clientbalancedaily.FundObject = fundObject;
|
||
clientbalancedaily.FundJson = JsonHelper.Serialize(fundObject);
|
||
|
||
#endregion
|
||
|
||
#region 客户冻结状态
|
||
//如果应付资金总额PayableFund大于0 则设置client
|
||
//PayableFund => Math.Max(ClosedTradePayableFund + PositionTradePayableFund + MarginByPayableMarginCalc, 0);
|
||
var ToDayRemainFund = clientbalancedaily.ToDayRemainFund ?? 0;
|
||
//var PositionPremiumNetCash = clientbalancedaily.PositionPremiumNetCash ?? 0;
|
||
//请知道d1、d2、d3含义的注释一下
|
||
var d1 = Math.Min(ToDayRemainFund + PositionPremiumNetCash, 0);
|
||
var d2 = Math.Max(PositionPremiumNetCash - Math.Max(ToDayRemainFund + PositionPremiumNetCash, 0), 0);
|
||
var d3 = -(clientbalancedaily.PayableMargin ?? 0.0) - Math.Max(ToDayRemainFund - d1 + d2, 0)
|
||
- (clientbalancedaily.TodayRemianFundProduct ?? 0.0) - (clientbalancedaily.Credit ?? 0.0);
|
||
if (Math.Max(-d1 + d2 + d3, 0) > 0)
|
||
{
|
||
clientbalancedaily.State = "冻结";
|
||
}
|
||
else
|
||
{
|
||
//如果计算追保金额小于等于0则解冻
|
||
clientbalancedaily.State = "正常";
|
||
}
|
||
#endregion
|
||
|
||
#region 结算合计
|
||
|
||
clientbalancedaily.OptionPremiumSum = clientbalancedaily.OptionPremium;
|
||
clientbalancedaily.OptionPremiumSwapSum = clientbalancedaily.OptionPremiumSwap;
|
||
clientbalancedaily.SettlementBalanceSum = clientbalancedaily.SettlementBalance;
|
||
clientbalancedaily.UnwindBalanceSum = clientbalancedaily.UnwindBalance;
|
||
clientbalancedaily.ExerciseBalanceSum = clientbalancedaily.ExerciseBalance;
|
||
clientbalancedaily.CouponSum = clientbalancedaily.Coupon;
|
||
clientbalancedaily.SwapBalanceSum = clientbalancedaily.SwapBalance;
|
||
clientbalancedaily.WinLossSum = clientbalancedaily.WinLoss;
|
||
clientbalancedaily.EndPremiumSum = clientbalancedaily.EndPremium;
|
||
clientbalancedaily.CashInCashOutProductChangeSum = clientbalancedaily.CashInCashOutProductChange;
|
||
|
||
if (preDaily != null)
|
||
{
|
||
clientbalancedaily.NetFundSum = 0;
|
||
clientbalancedaily.InFundSum = 0;
|
||
clientbalancedaily.OutFundSum = 0;
|
||
clientbalancedaily.OtherFundSum = 0;
|
||
foreach (var item in currencyCodes)
|
||
{
|
||
var rateObj = new eod_currency_rate
|
||
{
|
||
Rate = 1,
|
||
SellRate = 1,
|
||
BuyRate = 1,
|
||
ForeignCurrency = item,
|
||
LocalCurrency = client.SettlementCurrency,
|
||
};
|
||
|
||
if (PS.Config.ErpElement.SupportMultiCurrency)
|
||
{
|
||
currencyProvider.TryGetCurrencyRate(item, client.SettlementCurrency, out rateObj);
|
||
if (rateObj == null)
|
||
{
|
||
_context.RaiseError("结算客户资金", $"[{client.Name}]找不到汇率:{item}{client.SettlementCurrency}");
|
||
}
|
||
}
|
||
|
||
preDaily.FundObject.NetFundSum.TryGetValue(item, out var preNetFundSum);
|
||
clientbalancedaily.FundObject.NetFund.TryGetValue(item, out var netFundToday);
|
||
clientbalancedaily.FundObject.NetFundSum[item] = preNetFundSum + netFundToday;
|
||
clientbalancedaily.NetFundSum += clientbalancedaily.FundObject.NetFundSum[item] * rateObj.Rate;
|
||
|
||
preDaily.FundObject.InFundSum.TryGetValue(item, out var preInFundSum);
|
||
clientbalancedaily.FundObject.InFund.TryGetValue(item, out var inFundToday);
|
||
clientbalancedaily.FundObject.InFundSum[item] = preInFundSum + inFundToday;
|
||
clientbalancedaily.InFundSum += clientbalancedaily.FundObject.InFundSum[item] * rateObj.Rate;
|
||
|
||
preDaily.FundObject.OutFundSum.TryGetValue(item, out var preOutFundSum);
|
||
clientbalancedaily.FundObject.OutFund.TryGetValue(item, out var outFundToday);
|
||
clientbalancedaily.FundObject.OutFundSum[item] = preOutFundSum + outFundToday;
|
||
clientbalancedaily.OutFundSum += clientbalancedaily.FundObject.OutFundSum[item] * rateObj.Rate;
|
||
|
||
preDaily.FundObject.OtherFundSum.TryGetValue(item, out var preOtherFundSum);
|
||
clientbalancedaily.FundObject.OtherFund.TryGetValue(item, out var otherFundToday);
|
||
clientbalancedaily.FundObject.OtherFundSum[item] = preOtherFundSum + otherFundToday;
|
||
clientbalancedaily.OtherFundSum += clientbalancedaily.FundObject.OtherFundSum[item] * rateObj.Rate;
|
||
}
|
||
clientbalancedaily.OptionPremiumSum += preDaily.OptionPremiumSum;
|
||
clientbalancedaily.OptionPremiumSwapSum += (preDaily.OptionPremiumSwapSum ?? 0);
|
||
clientbalancedaily.SettlementBalanceSum += preDaily.SettlementBalanceSum;
|
||
clientbalancedaily.UnwindBalanceSum += preDaily.UnwindBalanceSum;
|
||
clientbalancedaily.ExerciseBalanceSum += preDaily.ExerciseBalanceSum;
|
||
clientbalancedaily.CouponSum += preDaily.CouponSum;
|
||
clientbalancedaily.SwapBalanceSum += preDaily.SwapBalanceSum;
|
||
clientbalancedaily.WinLossSum += preDaily.WinLossSum;
|
||
clientbalancedaily.EndPremiumSum += (preDaily.EndPremiumSum ?? 0);
|
||
clientbalancedaily.CashInCashOutProductChangeSum += preDaily.CashInCashOutProductChangeSum;
|
||
}
|
||
else
|
||
{
|
||
clientbalancedaily.FundObject.NetFundSum = clientbalancedaily.FundObject.NetFund;
|
||
clientbalancedaily.FundObject.InFundSum = clientbalancedaily.FundObject.InFund;
|
||
clientbalancedaily.FundObject.OutFundSum = clientbalancedaily.FundObject.OutFund;
|
||
clientbalancedaily.FundObject.OtherFundSum = clientbalancedaily.FundObject.OtherFund;
|
||
|
||
clientbalancedaily.NetFundSum = clientbalancedaily.NetFund;
|
||
clientbalancedaily.InFundSum = clientbalancedaily.InFund;
|
||
clientbalancedaily.OutFundSum = clientbalancedaily.OutFund;
|
||
clientbalancedaily.OtherFundSum = clientbalancedaily.OtherFund;
|
||
}
|
||
|
||
#endregion
|
||
|
||
clientbalancedaily.FundJson = JsonHelper.Serialize(clientbalancedaily.FundObject);
|
||
|
||
return clientbalancedaily;
|
||
}
|
||
|
||
//获取客户信息
|
||
private IEnumerable<ClientDto> GetClients(ClientDBContext clientDb, IEnumerable<int> reqClientIds)
|
||
{
|
||
var balanceDate = _context.SettleDate;
|
||
var preBalanceDate = _context.PreSettleDate;
|
||
|
||
if (reqClientIds != null && !reqClientIds.Any(n => n > 0))
|
||
{
|
||
reqClientIds = null;
|
||
}
|
||
|
||
//获取所有客户信息
|
||
|
||
var clientPrediate = PredicateBuilder.Create<Client>(t => t.ProcessStatus != "未提交");
|
||
if (reqClientIds != null)
|
||
{
|
||
clientPrediate = clientPrediate.And(t => reqClientIds.Contains(t.id));
|
||
}
|
||
var isHistory = balanceDate != DateTime.Today;
|
||
var clientDic = clientDb.client.Where(clientPrediate).Select(n => new ClientDto
|
||
{
|
||
id = n.id,
|
||
Name = n.Name,
|
||
Number = n.Number,
|
||
IsTradeCredit = n.IsTradeCredit,
|
||
FundThreshold = isHistory ? 0 : n.FundThreshold,
|
||
PendingMarginCallPayment = n.PendingMarginCallPayment ?? 0,
|
||
SettlementCurrency = n.SettlementCurrency
|
||
}).ToDictionary(n => n.id);
|
||
|
||
if (isHistory)
|
||
{
|
||
var fundThresholdDict =
|
||
clientDb.client_Axis_Fundthresholds
|
||
.Where(x => x.ValueDate <= balanceDate)
|
||
.AsEnumerable()
|
||
.GroupBy(O => O.ClientId)
|
||
.ToDictionary(
|
||
K => K.Key,
|
||
V => V.OrderByDescending(O => O.ValueDate).FirstOrDefault());
|
||
foreach (var item in fundThresholdDict)
|
||
{
|
||
if (clientDic.TryGetValue(item.Key, out var obj))
|
||
{
|
||
obj.FundThreshold = item.Value.FundThreshold;
|
||
}
|
||
}
|
||
}
|
||
|
||
var allClientIds = clientDic.Keys.ToArray();
|
||
|
||
#region 获取上日客户资金结算
|
||
|
||
var preDailyPredicate = PredicateBuilder.Create<ClientBalanceDaily>(t => t.BalanceDate == preBalanceDate);
|
||
if (reqClientIds != null)
|
||
{
|
||
preDailyPredicate = preDailyPredicate.And(t => reqClientIds.Contains(t.ClientId));
|
||
}
|
||
var preDailyList = DbContext.ClientBalanceDaily.Where(preDailyPredicate).ToArray();
|
||
foreach (var preDaily in preDailyList)
|
||
{
|
||
if (clientDic.TryGetValue(preDaily.ClientId, out var client))
|
||
{
|
||
client.PreDaily = preDaily;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 获取所有客户授信
|
||
|
||
var creditPredicate = PredicateBuilder.Create<CreditTable>(t => t.ClientId != null && t.ProcessStatus == "已审批"
|
||
&& (!t.CreditDeadLine.HasValue || t.CreditDeadLine >= balanceDate)
|
||
&& (!t.CreditStartDate.HasValue || t.CreditStartDate <= balanceDate));
|
||
if (reqClientIds != null)
|
||
{
|
||
creditPredicate = creditPredicate.And(t => allClientIds.Contains(t.ClientId.Value));
|
||
}
|
||
var creditQuery = from c in DbContext.credit.Where(creditPredicate)
|
||
group c by c.ClientId into g
|
||
select new
|
||
{
|
||
ClientId = g.Key,
|
||
CreditSum = g.Sum(t => t.Credit ?? 0),
|
||
CreditStockEqvNotionalSum = g.Sum(t => t.StockEqvNotional ?? 0)
|
||
};
|
||
var creditList = creditQuery.ToArray();
|
||
foreach (var credit in creditList)
|
||
{
|
||
if (clientDic.TryGetValue(credit.ClientId.Value, out var client))
|
||
{
|
||
client.CreditSum = credit.CreditSum;
|
||
client.CreditStockEqvNotionalSum = credit.CreditStockEqvNotionalSum;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 出入金记录 获取上个结算日到当前结算日之间的所有已结算和已确认的出入金(包含周末的出入金)
|
||
|
||
var newValuedate = balanceDate.AddDays(1);
|
||
var lastBalanceDateAddOne = preBalanceDate.AddDays(1);
|
||
|
||
var entryexitPredicate = PredicateBuilder.Create<ClientCashInCashOut>(t => t.ClientId != null && t.ValidState != "InValid"
|
||
&& t.HappenDate >= lastBalanceDateAddOne && t.HappenDate < newValuedate
|
||
&& (t.State == ClientCashInCashOut.已结算 || t.State == ClientCashInCashOut.已确认));
|
||
if (reqClientIds != null)
|
||
{
|
||
entryexitPredicate = entryexitPredicate.And(t => allClientIds.Contains(t.ClientId.Value));
|
||
}
|
||
var entryexits = (from cash in DbContext.ClientCashInCashOut.Where(entryexitPredicate)
|
||
join trade in DbContext.trade on cash.TradeId equals trade.id into trade
|
||
from td in trade.DefaultIfEmpty()
|
||
where td.TradeType != "收益互换"
|
||
select cash).ToLookup(n => n.ClientId.Value);
|
||
|
||
var entryexits_swap = (from cash in DbContext.ClientCashInCashOut.Where(entryexitPredicate)
|
||
join trade in DbContext.trade.Where(x => x.TradeType == "收益互换") on cash.TradeId equals trade.id
|
||
select cash).ToLookup(n => n.ClientId.Value);
|
||
|
||
foreach (var lookup in entryexits)
|
||
{
|
||
if (clientDic.TryGetValue(lookup.Key, out var client))
|
||
{
|
||
client.EntryexitList = lookup.ToArray();
|
||
}
|
||
}
|
||
|
||
foreach (var lookup in entryexits_swap)
|
||
{
|
||
if (clientDic.TryGetValue(lookup.Key, out var client))
|
||
{
|
||
client.EntryexitSwapList = lookup.ToArray();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 获取客户所有现存(抵押状态)抵押品信息
|
||
|
||
var clientProductPredicate = PredicateBuilder.Create<clientcashincashout_product>(product =>
|
||
product.HappenDate < newValuedate
|
||
&& (product.Status == Clientcashincashout_productStatusEnum.抵押.ToString() && product.OptStatus == ClientCashInCashOut.已确认
|
||
|| product.Status == Clientcashincashout_productStatusEnum.赎回.ToString() && product.OptStatus != ClientCashInCashOut.已确认
|
||
|| product.Status == Clientcashincashout_productStatusEnum.赎回.ToString() && product.OptStatus == ClientCashInCashOut.已确认 && product.BackDate >= newValuedate)
|
||
);
|
||
if (reqClientIds != null)
|
||
{
|
||
clientProductPredicate = clientProductPredicate.And(t => allClientIds.Contains(t.ClientId));
|
||
}
|
||
var clientProductQuery = from product in DbContext.clientcashincashout_product.Where(clientProductPredicate)
|
||
join um in DbContext.underlying_manager on product.UnderlyingId equals um.id into um_t
|
||
from um in um_t.DefaultIfEmpty()
|
||
select new ClientProductDto
|
||
{
|
||
ProductNumber = product.Number,
|
||
ClientId = product.ClientId,
|
||
UnderlyingId = product.UnderlyingId,
|
||
UnderlyingCode = um.UnderlyingCode,
|
||
ProductAmount = product.ProductAmount,
|
||
Rate = product.Rate
|
||
};
|
||
var clientProductLookup = clientProductQuery.ToLookup(n => n.ClientId);
|
||
|
||
foreach (var lookup in clientProductLookup)
|
||
{
|
||
if (clientDic.TryGetValue(lookup.Key, out var client))
|
||
{
|
||
client.ClientProductList = lookup.ToArray();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 客户保证金
|
||
|
||
var clientSpanPredicate = PredicateBuilder.Create<ClientSpan>(t => t.ValueDate == balanceDate && t.SpanType == ClientSpan.SpanType_Eod);
|
||
if (reqClientIds != null)
|
||
{
|
||
clientSpanPredicate = clientSpanPredicate.And(t => allClientIds.Contains(t.ClientId));
|
||
}
|
||
var clientSpanList = DbContext.client_span.Where(clientSpanPredicate).Select(n => new ClientSpanDto
|
||
{
|
||
ClientId = n.ClientId,
|
||
AdditionalWorstCastClientPayable = n.AdditionalWorstCastClientPayable,
|
||
MySideMargin = n.MySideMargin,
|
||
OtherSideMargin = n.OtherSideMargin,
|
||
TwoSideMargin = n.TwoSideMargin,
|
||
WorstCastClientPayable = n.WorstCastClientPayable,
|
||
DeltaMargin = n.DeltaMargin,
|
||
SwapWorstCastClientPayable = n.SwapWorstCastClientPayable,
|
||
ModifiedFlag = n.ModifiedFlag
|
||
}).ToArray();
|
||
foreach (var spanDto in clientSpanList)
|
||
{
|
||
if (clientDic.TryGetValue(spanDto.ClientId, out var client))
|
||
{
|
||
client.ClientSpan = spanDto;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
//获取冻结资金信息
|
||
var clientFrozenFunds = new ClientFrozenFundsService(this).GetDatas(balanceDate, allClientIds);
|
||
foreach (var kv in clientFrozenFunds)
|
||
{
|
||
if (clientDic.TryGetValue(kv.Key, out var client))
|
||
{
|
||
client.FrozenFunds = kv.Value;
|
||
}
|
||
}
|
||
|
||
//获取结算日相关的资金了结记录
|
||
var todayTcSumLookup = GetFinishedTradeCashSumList(reqClientIds).ToLookup(n => n.ClientId);
|
||
foreach (var lookup in todayTcSumLookup)
|
||
{
|
||
if (clientDic.TryGetValue(lookup.Key, out var client))
|
||
{
|
||
client.TodayTradeCashList = lookup.ToArray();
|
||
}
|
||
}
|
||
|
||
var EodPositionSwapMannual = DbContext.eod_trade_position_swap_mannual.Where(x => x.ValueDate == balanceDate).ToLookup(n => n.ClientId);
|
||
foreach (var lookup in EodPositionSwapMannual)
|
||
{
|
||
if (clientDic.TryGetValue(lookup.Key, out var client))
|
||
{
|
||
client.eodPositionSwapMannual = lookup.ToArray();
|
||
}
|
||
}
|
||
|
||
//返回数据结果
|
||
return clientDic.Values;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取结算日相关的资金了结记录
|
||
/// </summary>
|
||
private IEnumerable<TodayTradeCashDto> GetFinishedTradeCashSumList(IEnumerable<int> reqClientIds)
|
||
{
|
||
var balanceDate = _context.SettleDate;
|
||
|
||
//如果前一天是假日,要显示包含假日的交易
|
||
var preday = balanceDate.AddDays(-1);
|
||
|
||
//获取上一个交易日的下一天(例如收盘日是周一,上一个交易日就是周五,他的下一天就是周六,获取的是周六)
|
||
var nonHolidayAddOne = valuedateBLL.GetNonHolidayDefore(preday).AddDays(1);
|
||
var tcActions = new string[] {
|
||
ClientCashInCashOut.系统操作_平仓费,
|
||
ClientCashInCashOut.系统操作_行权费,
|
||
ClientCashInCashOut.系统操作_互换,
|
||
ClientCashInCashOut.系统操作_票息,
|
||
ClientCashInCashOut.人工操作_其他
|
||
};
|
||
|
||
var tdPredicate = PredicateBuilder.Create<trade>(t => t.ClientId > 0 && t.ValidState != ConsGlobal.InValid && t.IsGroup != 1);
|
||
if (reqClientIds != null)
|
||
{
|
||
tdPredicate = tdPredicate.And(t => reqClientIds.Contains(t.ClientId));
|
||
}
|
||
|
||
var tcQuery = from tc in DbContext.trade_cash
|
||
where (tc.ValueDate >= nonHolidayAddOne && tc.ValueDate <= balanceDate && tc.HappenedDate == null
|
||
|| tc.HappenedDate >= nonHolidayAddOne && tc.HappenedDate <= balanceDate)
|
||
&& tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted
|
||
&& tcActions.Contains(tc.Action)
|
||
group tc by tc.TradeId into g
|
||
select new
|
||
{
|
||
TradeId = g.Key,
|
||
AmountSum = g.Sum(n => n.Amount),
|
||
UnwindPercentRateSum = g.Sum(n => n.UnwindPercentRate ?? 0)
|
||
};
|
||
|
||
|
||
var query = from tc in tcQuery
|
||
join t in DbContext.trade.Where(tdPredicate) on tc.TradeId equals t.id
|
||
select new TodayTradeCashDto
|
||
{
|
||
TradeId = tc.TradeId,
|
||
ClientId = t.ClientId,
|
||
TradeType = t.TradeType,
|
||
BuySell = t.BuySell,
|
||
TradePrice = t.TradePrice ?? 0,
|
||
TcAmountSum = tc.AmountSum,
|
||
TcUnwindPercentRateSum = tc.UnwindPercentRateSum
|
||
};
|
||
|
||
return query.ToArray();
|
||
}
|
||
|
||
#region----InnerClass----
|
||
|
||
|
||
class ClientSpanDto
|
||
{
|
||
public int ClientId { get; set; }
|
||
|
||
public double? WorstCastClientPayable { get; set; }
|
||
public double? DeltaMargin { get; set; }
|
||
|
||
public double? SwapWorstCastClientPayable { get; set; }
|
||
|
||
public double? TwoSideMargin { get; set; }
|
||
|
||
public double? OtherSideMargin { get; set; }
|
||
|
||
public double? MySideMargin { get; set; }
|
||
|
||
public double? AdditionalWorstCastClientPayable { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否人工修改过
|
||
/// </summary>
|
||
public bool ModifiedFlag { get; set; }
|
||
}
|
||
|
||
class ClientProductDto
|
||
{
|
||
public int ClientId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 抵押记录编号
|
||
/// </summary>
|
||
public string ProductNumber { get; set; }
|
||
|
||
public int? UnderlyingId { get; set; }
|
||
|
||
public string UnderlyingCode { get; set; }
|
||
|
||
/// <summary>
|
||
/// 质押数量
|
||
/// </summary>
|
||
public double? ProductAmount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 质押率
|
||
/// </summary>
|
||
public double? Rate { get; set; }
|
||
}
|
||
|
||
class TodayTradeCashDto
|
||
{
|
||
public int TradeId { get; set; }
|
||
|
||
public int ClientId { get; set; }
|
||
|
||
public string TradeType { get; set; }
|
||
|
||
public string BuySell { get; set; }
|
||
|
||
public double TradePrice { get; set; }
|
||
|
||
public double TcAmountSum { get; set; }
|
||
|
||
public double TcUnwindPercentRateSum { get; set; }
|
||
}
|
||
|
||
class ClientDto
|
||
{
|
||
public int id { get; set; }
|
||
|
||
public string Name { get; set; }
|
||
|
||
public string Number { get; set; }
|
||
|
||
public string SettlementCurrency { get; set; }
|
||
|
||
public int? IsTradeCredit { get; set; }
|
||
|
||
/// <summary>
|
||
/// 资金限额
|
||
/// </summary>
|
||
public double? FundThreshold { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否追保
|
||
/// </summary>
|
||
public double PendingMarginCallPayment { get; set; }
|
||
|
||
//-----授信-----
|
||
|
||
/// <summary>
|
||
/// 客户授信合计
|
||
/// </summary>
|
||
public double CreditSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 客户授信名义本金合计
|
||
/// </summary>
|
||
public double CreditStockEqvNotionalSum { get; set; }
|
||
|
||
//-----其他-----
|
||
|
||
/// <summary>
|
||
/// 上日结算数据
|
||
/// </summary>
|
||
public ClientBalanceDaily PreDaily { get; set; }
|
||
|
||
/// <summary>
|
||
/// 客户保证金
|
||
/// </summary>
|
||
public ClientSpanDto ClientSpan { get; set; }
|
||
|
||
/// <summary>
|
||
/// 这个需要保持数据追踪状态以便更新数据库数据
|
||
/// </summary>
|
||
public IEnumerable<ClientCashInCashOut> EntryexitList { get; set; }
|
||
|
||
/// <summary>
|
||
/// 这个需要保持数据追踪状态以便更新数据库数据
|
||
/// </summary>
|
||
public IEnumerable<ClientCashInCashOut> EntryexitSwapList { get; set; }
|
||
|
||
/// <summary>
|
||
/// 抵押品信息
|
||
/// </summary>
|
||
public IEnumerable<ClientProductDto> ClientProductList { get; set; }
|
||
|
||
/// <summary>
|
||
/// 冻结资金汇总
|
||
/// </summary>
|
||
public ClientFrozenFunds FrozenFunds { get; set; }
|
||
|
||
/// <summary>
|
||
/// 客户关联交易资金记录
|
||
/// </summary>
|
||
public IEnumerable<TodayTradeCashDto> TodayTradeCashList { get; set; }
|
||
|
||
//获取客户导入的所有持仓信息 -- 收益互换(国君)
|
||
public IEnumerable<eod_trade_position_swap_mannual> eodPositionSwapMannual { get; set; }
|
||
}
|
||
|
||
class EodPnlSum
|
||
{
|
||
/// <summary>
|
||
/// 昨日价值
|
||
/// </summary>
|
||
public double LastPvSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日价值
|
||
/// </summary>
|
||
public double PvSum { get; set; }
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
public double SellPvSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日四舍五入价值
|
||
/// </summary>
|
||
public double RoundedPvSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日浮动盈亏
|
||
/// </summary>
|
||
public double DailyPnLSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日持仓盈亏
|
||
/// </summary>
|
||
public double PositionPnlSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日四舍五入持仓盈亏
|
||
/// </summary>
|
||
public double RoundedPositionPnlSum { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当日累积总盈亏
|
||
/// </summary>
|
||
public double TotalPnlSum { get; set; }
|
||
}
|
||
|
||
class MyComparer
|
||
{
|
||
PropertyInfo[] _props;
|
||
|
||
readonly List<string> _diffList;
|
||
readonly HashSet<string> _ignorePropNames;
|
||
|
||
public MyComparer()
|
||
{
|
||
ClientBalanceDaily ct;
|
||
_ignorePropNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
|
||
nameof(ct.id),
|
||
nameof(ct.OptId),
|
||
nameof(ct.OptDate),
|
||
nameof(ct.OptName),
|
||
};
|
||
|
||
_diffList = new List<string>(20);
|
||
}
|
||
|
||
public void Compare(ClientDto client, ClientBalanceDaily dataNew, ClientBalanceDaily dataOld)
|
||
{
|
||
if (dataNew is null)
|
||
{
|
||
throw new ArgumentNullException(nameof(dataNew));
|
||
}
|
||
|
||
if (dataOld is null)
|
||
{
|
||
throw new Exception("旧数据不存在");
|
||
}
|
||
|
||
_diffList.Clear();
|
||
|
||
if (string.IsNullOrEmpty(dataOld.State))
|
||
{
|
||
dataOld.State = "正常";
|
||
}
|
||
var dd = new[] { dataNew.FrozenRedeemFunds, dataOld.FrozenRedeemFunds };
|
||
|
||
ReviseData(dataNew);
|
||
ReviseData(dataOld);
|
||
|
||
if (_props == null)
|
||
{
|
||
_props = typeof(ClientBalanceDaily).GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||
.Where(p =>
|
||
{
|
||
return !_ignorePropNames.Contains(p.Name)
|
||
&& p.CanWrite && p.CanRead
|
||
&& p.GetIndexParameters().Length < 1
|
||
&& !p.GetCustomAttributes<NotMappedAttribute>().Any();
|
||
}).ToArray();
|
||
}
|
||
|
||
foreach (var p in _props)
|
||
{
|
||
var objNew = p.GetValue(dataNew);
|
||
var objOld = p.GetValue(dataOld);
|
||
var strNew = string.Empty;
|
||
var strOld = string.Empty;
|
||
if (p.PropertyType == typeof(double))
|
||
{
|
||
strNew = ((double)objNew).ToString("F6");
|
||
strOld = ((double)objOld).ToString("F6");
|
||
}
|
||
else if (p.PropertyType == typeof(double?))
|
||
{
|
||
if (objNew != null)
|
||
{
|
||
strNew = ((double?)objNew).Value.ToString("F6");
|
||
}
|
||
if (objOld != null)
|
||
{
|
||
strOld = ((double?)objOld).Value.ToString("F6");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (objNew != null)
|
||
{
|
||
strNew = objNew.ToString();
|
||
}
|
||
if (objOld != null)
|
||
{
|
||
strOld = objOld.ToString();
|
||
}
|
||
}
|
||
|
||
if (strNew != strOld)
|
||
{
|
||
_diffList.Add($"字段名:{p.Name},新数据:{strNew},旧数据:{strOld}");
|
||
}
|
||
}
|
||
|
||
if (_diffList.Any())
|
||
{
|
||
var diffstr = string.Join(Environment.NewLine, _diffList.ToArray());
|
||
throw new Exception($"[{client.id},{client.Name}]新旧数据不一致:\r\n{diffstr}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"[{client.id},{client.Name}]新旧数据一致");
|
||
}
|
||
}
|
||
|
||
private void ReviseData(ClientBalanceDaily data)
|
||
{
|
||
//因为抵押品是按照实时行情处理的所以需要去除这部分的影响
|
||
data.FrozenBalance += data.FrozenRedeemFunds;
|
||
data.MarginBalance += data.FrozenRedeemFunds;
|
||
if (data.AdvisableMargin > 0)
|
||
{
|
||
data.AdvisableMargin += data.FrozenRedeemFunds;
|
||
}
|
||
if (data.Margin < 0)
|
||
{
|
||
data.Margin += data.FrozenRedeemFunds;
|
||
}
|
||
data.FrozenRedeemFunds = 0;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|
||
|
||
//计算渠道方合计 |