1180 lines
66 KiB
C#
1180 lines
66 KiB
C#
using Newtonsoft.Json;
|
|
using OfficeOpenXml;
|
|
using System.Text.RegularExpressions;
|
|
using YLErp.BLL;
|
|
using YLErp.BLL.Eod;
|
|
using YLErp.BLL.EodSettlement;
|
|
using YLErp.Enums;
|
|
using YLErp.Helpers;
|
|
using YLErp.Model;
|
|
using YLErp.Modules.ClientModule;
|
|
using YLErp.Modules.DataCacheModule;
|
|
using YLErp.Modules.DataProviderModule;
|
|
using YLErp.Modules.ReportModule.SettlementReportModule;
|
|
using YLErp.Office;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.ReportModule
|
|
{
|
|
/// <summary>
|
|
/// 结算报告服务
|
|
/// </summary>
|
|
public class SettlementReportForZJService : YLBaseService
|
|
{
|
|
public SettlementReportForZJService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
public ClientDingShiReport_ZJ GetReportData(DingShiReportEmail emailData, IEnumerable<int> userAssetUnits, string template = "")
|
|
{
|
|
//todo 获取模板
|
|
var report = new ClientDingShiReport_ZJ() { ReportEnd = emailData.To };
|
|
var client = report.client = DataCacheProvider.GetClientDataSource().GetData(emailData.ClientId);
|
|
if (string.IsNullOrWhiteSpace(report.client.SettlementCurrency))
|
|
{
|
|
throw new ServiceException("客户未设置结算币种!");
|
|
}
|
|
#region 合计
|
|
var clientBalance = ClientBalanceUtility.GetClientBanlances(new List<int> { emailData.ClientId }, emailData.From, emailData.To, IsClientBalanceGap: false, IsGetOuterMarginGap: false, ParentFlag: emailData.ParentFlag).FirstOrDefault();
|
|
|
|
var clientspan = DbContext.client_span.FirstOrDefault(o => o.ClientId == client.id && o.ValueDate == emailData.To);
|
|
|
|
if (clientspan == null)
|
|
{
|
|
clientspan = new ClientSpan();
|
|
}
|
|
|
|
var clientCredit = DbContext.credit.FirstOrDefault(o => o.ClientId == client.id && o.CreditStartDate <= emailData.To && o.CreditDeadLine >= emailData.To && o.ProcessOrderId == -2);
|
|
|
|
var credit = clientCredit == null ? 0 : clientCredit.Credit ?? 0;
|
|
|
|
report.summaryReportModel = new SummaryReportModel()
|
|
{
|
|
ClientName = report.client.Name,
|
|
ReportDate = report.ReportEnd,
|
|
RemainCash = clientBalance.AmountFund,
|
|
MarginRequiement = clientspan.IM ?? 0,
|
|
QuoteMarginRequiement = 0,
|
|
CashQuotaLeft = 0,
|
|
UnRealizedPnl = 0,
|
|
QuoteUnRealized = 0,
|
|
CurrencyRate = 0,
|
|
IM = clientspan.IM ?? 0,
|
|
VM = (clientspan.VM ?? 0) + (clientspan.Commission ?? 0),
|
|
Deduct = clientspan.Deduct ?? 0,
|
|
PFEUsed = clientspan.PFEUsed ?? 0,
|
|
Credit = clientCredit == null ? 0 : clientCredit.Credit ?? 0,
|
|
PFECredit = clientCredit == null ? 0 : clientCredit.PFECredit ?? 0,
|
|
PayableFund = clientBalance.PayableFundTotal,
|
|
AvailableFund = 0,
|
|
Margin = -clientBalance.Margin,
|
|
|
|
//PositionPv = clientBalance.PositionPv,
|
|
SettlementCurrency = report.client.SettlementCurrency,
|
|
};
|
|
#endregion
|
|
if (client.BoundSide == BoundSideEnum.北向)
|
|
{
|
|
if (clientBalance.FundJson == null)
|
|
{
|
|
throw new ServiceException("客户多币种资金明细为空,请重新收盘后再试");
|
|
}
|
|
var fund = JsonConvert.DeserializeObject<FundObject>(clientBalance.FundJson);
|
|
report.summaryReportModel.QuotaCurrency = "CNH";
|
|
//北向需要的是USD转CNH的汇率,所以这里倒过来了,相应的用到这个汇率是用的除
|
|
report.summaryReportModel.CurrencyRate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(report.summaryReportModel.SettlementCurrency, report.summaryReportModel.QuotaCurrency, report.ReportEnd);
|
|
report.summaryReportModel.QuoteMarginRequiement = report.summaryReportModel.MarginRequiement * report.summaryReportModel.CurrencyRate;
|
|
report.summaryReportModel.QuoteCash = fund.TodayRemainFund.ContainsKey(report.summaryReportModel.QuotaCurrency) ? fund.TodayRemainFund[report.summaryReportModel.QuotaCurrency] : 0;
|
|
report.summaryReportModel.SettleCash = fund.TodayRemainFund.ContainsKey(report.summaryReportModel.SettlementCurrency) ? fund.TodayRemainFund[report.summaryReportModel.SettlementCurrency] : 0;
|
|
}
|
|
|
|
|
|
#region 持仓明细
|
|
var spanReq = new TradeSpanReq { ClientId = emailData.ClientId, ValueDate = emailData.To, ParentFlag = emailData.ParentFlag };
|
|
report.swap_position = clientTradePositionQueryList(spanReq, userAssetUnits);
|
|
|
|
report.summaryReportModel.QuoteUnRealized = report.swap_position.Sum(o => (o.UnrealizedPnl - o.Commision - o.AnnualFee));
|
|
report.summaryReportModel.UnRealizedPnl = report.summaryReportModel.QuoteUnRealized / report.summaryReportModel.CurrencyRate;
|
|
#endregion
|
|
|
|
#region 资金明细
|
|
var req = new EntryExitReq() { ClientId = emailData.ClientId, HappenDateStart = emailData.From, HappenDateEnd = emailData.To, ParentFlag = emailData.ParentFlag };
|
|
report.cash_records = SearchListExtendOnly(req, report.summaryReportModel.SettlementCurrency, report.summaryReportModel.QuotaCurrency, client.BoundSide);
|
|
report.cash_records.SettlementCurrency = report.client.SettlementCurrency;
|
|
|
|
#endregion
|
|
report.summaryReportModel.CashQuotaLeft = report.summaryReportModel.RemainCash;
|
|
if (!(report.client.AgreementBookType ?? true))
|
|
{
|
|
report.summaryReportModel.CashQuotaLeft += (report.summaryReportModel.UnRealizedPnl - report.summaryReportModel.MarginRequiement);
|
|
//双向 = cash + UnRealized Pnl - Margin Requiement
|
|
|
|
}
|
|
else
|
|
{
|
|
report.summaryReportModel.CashQuotaLeft += Math.Min(0, report.summaryReportModel.UnRealizedPnl) - report.summaryReportModel.MarginRequiement;
|
|
//单向 = cash + Min(0 , UnRealized Pnl- Margin Requiement)
|
|
}
|
|
|
|
if (client.BoundSide == BoundSideEnum.北向)
|
|
{
|
|
#region 平仓明细
|
|
report.swap_unwind = clientTradeUnwindQueryList(emailData, userAssetUnits, BoundSideEnum.北向);
|
|
#endregion
|
|
|
|
}
|
|
else
|
|
{
|
|
#region 标的持仓
|
|
report.underlying_positon = getClientUnderlyingPosition(report.swap_position, emailData.To);
|
|
#endregion
|
|
|
|
#region 流水记录
|
|
report.summaryReportModel.swap_flow = clientTradeFlowQueryList(emailData.To, userAssetUnits, client);
|
|
report.summaryReportModel.UnRealizedPnl = report.summaryReportModel.swap_flow.Sum(o => o.UnrealizedPnl ?? 0);
|
|
|
|
report.summaryReportModel.MarginRequiement = report.summaryReportModel.VM + report.summaryReportModel.IM;
|
|
report.summaryReportModel.AvailableFund = report.summaryReportModel.RemainCash - report.summaryReportModel.MarginRequiement;
|
|
#endregion
|
|
|
|
#region 今日开平仓
|
|
report.today_swap = clientTradeUnwindQueryList(emailData, userAssetUnits, BoundSideEnum.南向);
|
|
#endregion
|
|
|
|
#region 历史交易
|
|
report = GetHistoryInfo(report);
|
|
#endregion
|
|
}
|
|
|
|
report.Title = emailData.Title;
|
|
report.downloadFilePath = emailData.DownloadFilePath;
|
|
return report;
|
|
}
|
|
public (EmailTradeConfirmResultType status, string message) SendSettlementReports(DingShiReportEmail emailData, ClientDingShiReport_ZJ report, string template, List<string> recevier = null)
|
|
{
|
|
string message = null;
|
|
var attachFiles = new List<string>();
|
|
|
|
emailData.FileTypes.ForEach(type =>
|
|
{
|
|
if (type.@checked)
|
|
{
|
|
var filepath = GenerateFileEntry(report);
|
|
if (!string.IsNullOrEmpty(filepath))
|
|
{
|
|
attachFiles.Add(filepath);
|
|
}
|
|
}
|
|
});
|
|
|
|
//刘总认为追保无需检查用户银行卡
|
|
//var bankcard = ClientDataProvider.GetBankCard(report.client.id);
|
|
//if (bankcard == null && report.FundReportModel.PayableFund > 0)
|
|
//{
|
|
// throw new Exception(report.client.Name + "未配置银行卡信息!");
|
|
//}
|
|
|
|
// 要向该客户的所有订阅了邮件通知的人员发送邮件
|
|
var emails = ClientDataQueryService.GetClientEmails(report.client.id, false, recevier);
|
|
var status = EmailTradeConfirmResultType.Succeed;
|
|
if (emails.All(o => string.IsNullOrWhiteSpace(o)))
|
|
{
|
|
status = EmailTradeConfirmResultType.NoEmailSetting;
|
|
}
|
|
else
|
|
{
|
|
emails = emails.Where(o => !string.IsNullOrWhiteSpace(o));
|
|
|
|
var title = DBCacheManager.Single.GetStr(CacheTable.ClientBalanceReportTiltle, template);
|
|
if (string.IsNullOrWhiteSpace(title))
|
|
{
|
|
throw new ServiceException(template + "模板标题设置为空,无法发送");
|
|
}
|
|
var detail = DBCacheManager.Single.GetStr(CacheTable.MarginLuoKuanDesc, template);
|
|
title = ReplaceWildcard(title, report);
|
|
detail = ReplaceWildcard(detail, report);
|
|
var mailFrom = DBCacheManager.Single.GetStr(CacheTable.TradeMarketSendUser, template);
|
|
if (string.IsNullOrWhiteSpace(mailFrom))
|
|
{
|
|
mailFrom = DBCacheManager.Single.GetStr(CacheTable.TradeMarketSendUser);
|
|
}
|
|
|
|
message = EmailHelper.SendMail(string.Join(";", emails), title, detail, true, attachFiles, emailData.CCEmail, mailFrom);
|
|
|
|
if (!string.IsNullOrEmpty(message))
|
|
{
|
|
status = EmailTradeConfirmResultType.EmailSentFailed;
|
|
}
|
|
}
|
|
return (status, message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 持仓明细
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private List<PositionTradeModel> clientTradePositionQueryList(TradeSpanReq req, IEnumerable<int> userAssetUnits)
|
|
{
|
|
if (req.ClientId == null || req.ValueDate == null)
|
|
{
|
|
return new List<PositionTradeModel>();
|
|
}
|
|
|
|
var positionList = new ClientPositionQueryService(this).SearchPositionListAll(req, userAssetUnits);
|
|
//未了结远期
|
|
var UnSettledForwards = DbContext.trade_cash_pre.Where(o => o.ValueDate > req.ValueDate && o.HappenedDate <= req.ValueDate).ToList();
|
|
var UnSettledTradeIds = UnSettledForwards.Select(o => o.TradeId).Distinct().ToList();
|
|
var queryList = (from t in DbContext.trade.Where(o => UnSettledTradeIds.Contains(o.id) && o.ClientId == req.ClientId)
|
|
select new eod_position
|
|
{
|
|
TradeId = t.id,
|
|
tradeOrigin = t,
|
|
TradeJson = "",
|
|
ValueDate = req.ValueDate,
|
|
UnderlyingCode = t.UnderlyingCode
|
|
}).ToList();
|
|
positionList.AddRange(queryList);
|
|
// eod_trade_position_swap
|
|
var underlyingPriceProvider = new EodPriceProvider(req.ValueDate ?? DateTime.Now);
|
|
var result = positionList.Select(x =>
|
|
{
|
|
if (UnSettledTradeIds.Contains(x.TradeId))
|
|
{
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(x.UnderlyingCode);
|
|
x.CountRatio = um.CountRatio;
|
|
x.ContractSize = um.ContractSize;
|
|
x.QuoteUnitSingle = um.QuoteUnitString;
|
|
x.BBGTicker = um.BBGTicker;
|
|
x.UnderlyingPrice = um.Price;
|
|
new TradeModule.TradeExtendService(this).SetTradeExtend(new List<trade> { x.tradeOrigin });
|
|
if (req.ValueDate != DateTime.Now.Date)
|
|
{
|
|
x.UnderlyingPrice = underlyingPriceProvider.GetPrice(x.UnderlyingCode, SettlementTypeEnum.ClosePrice);
|
|
}
|
|
}
|
|
var model = new PositionTradeModel()
|
|
{
|
|
trade = x.trade,
|
|
TodayPrice = x.UnderlyingPrice ?? 0,
|
|
BBGTicker = x.BBGTicker,
|
|
ContractSize = x.ContractSize,
|
|
AnnualFee = 0,
|
|
Commision = 0,
|
|
PriceDate = x.ValueDate ?? DateTime.Now,
|
|
UnrealizedPnl = 0,
|
|
BuySell = x.trade.trade_swap.PayLongShort == "多头" ? "Buy" : "Sell",
|
|
Amount = (x.Lots) ?? 0 * (x.trade.trade_swap.PayLongShort == "多头" ? 1 : -1),
|
|
UnwindLots = ((x.trade.OriginalNotional ?? 0) - x.trade.Notional) / x.ContractSize * (x.trade.trade_swap.PayLongShort == "多头" ? -1 : 1)
|
|
};
|
|
|
|
return model;
|
|
}).ToList();
|
|
|
|
foreach (var item in result)
|
|
{
|
|
item.Amount = item.Amount * (item.BuySell == "Buy" ? 1 : -1);
|
|
var eod_trade_position_swap = DbContext.eod_trade_position_swap.FirstOrDefault(o => o.TradeId == item.trade.id && o.ValueDate == req.ValueDate);
|
|
if (eod_trade_position_swap != null)
|
|
{
|
|
item.AnnualFee = eod_trade_position_swap.QuoteAnnualFee;
|
|
item.Commision = eod_trade_position_swap.QuoteCommission;
|
|
item.UnrealizedPnl = eod_trade_position_swap.QuoteFloatingWinLoss * -1;
|
|
item.StlAnnualFee = eod_trade_position_swap.AnnualFee;
|
|
item.StlCommision = eod_trade_position_swap.Commission;
|
|
item.StlUnrealizedPnl = eod_trade_position_swap.FloatingWinLoss * -1;
|
|
}
|
|
//平仓未实现
|
|
var tc_pres = DbContext.trade_cash_pre.Where(o => o.TradeId == item.trade.id && o.ValueDate > req.ValueDate && o.HappenedDate <= req.ValueDate).ToList();
|
|
if (tc_pres != null && tc_pres.Count() > 0)
|
|
{
|
|
foreach (var tc_pre in tc_pres)
|
|
{
|
|
//var rate = tradeFlow.Rate ?? 1;
|
|
var cash_details = DbContext.trade_cash_detail.Where(o => o.TradeCashPreId == tc_pre.id && o.ValueDate > req.ValueDate).ToList();
|
|
item.AnnualFee += cash_details.Where(o => o.TradeCashType == "利息").Sum(o => o.QuoteAmount ?? 0);
|
|
item.Commision += cash_details.Where(o => o.TradeCashType == "开仓手续费").Sum(o => o.QuoteAmount ?? 0) + cash_details.Where(o => o.TradeCashType == "了结手续费").Sum(o => o.QuoteAmount ?? 0);
|
|
item.UnrealizedPnl += cash_details.Where(o => o.TradeCashType == "浮动收益").Sum(o => o.QuoteAmount ?? 0) * -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 平仓明细
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private List<UnwindCashModel> clientTradeUnwindQueryList(DingShiReportEmail emailData, IEnumerable<int> userAssetUnits, BoundSideEnum boundSide)
|
|
{
|
|
var actions = new List<string> { ClientCashInCashOut.系统操作_平仓费 };
|
|
var unwindData = from t in DbContext.trade
|
|
where t.ClientId == emailData.ClientId && t.TradeDate <= emailData.To && t.ValidState != "InValid"
|
|
join tc in DbContext.trade_cash
|
|
on t.id equals tc.TradeId
|
|
where ((tc.HappenedDate != null && tc.HappenedDate <= emailData.To) || (tc.HappenedDate == null && tc.ValueDate <= emailData.To))
|
|
&& tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted
|
|
join um in DbContext.underlying_manager
|
|
on t.UnderlyingCode equals um.UnderlyingCode
|
|
select new UnwindCashModel
|
|
{
|
|
trade = t,
|
|
tc = tc,
|
|
BBGTicker = um.BBGTicker,
|
|
ContractSize = um.ContractSize,
|
|
RealizedPnl = 0,
|
|
Commision = 0,
|
|
AnnualFee = 0,
|
|
Amount = (t.Lots ?? 0) * (tc.UnwindPercentRate ?? 1),
|
|
TradeType = "swap",
|
|
UnderlyingCode = t.UnderlyingCode,
|
|
UnwindPrice = tc.FinalPrice ?? 0,
|
|
UnwindDate = tc.HappenedDate ?? tc.ValueDate,
|
|
Action = "unwind",
|
|
TradeDate = t.TradeDate,
|
|
SpotPrice = t.SpotPrice ?? 0,
|
|
ExerciseDate = t.ExerciseDate,
|
|
};
|
|
var tradeIds = unwindData.Select(o => o.trade.id).Distinct().ToList();
|
|
if (boundSide == BoundSideEnum.北向)
|
|
{
|
|
unwindData = unwindData.Where(o => actions.Contains(o.tc.Action));
|
|
}
|
|
if (boundSide == BoundSideEnum.南向)
|
|
{
|
|
unwindData = unwindData.Where(o => o.tc.HappenedDate == emailData.To || (o.tc.HappenedDate == null && o.tc.ValueDate == emailData.To));
|
|
}
|
|
var ret = unwindData.ToList();
|
|
if (userAssetUnits != null && userAssetUnits.Count() > 1)
|
|
{
|
|
ret = ret.Where(o => userAssetUnits.Contains(o.trade.AssetId)).ToList();
|
|
}
|
|
|
|
foreach (var item in ret)
|
|
{
|
|
var trade_cash_details = DbContext.trade_cash_detail.Where(o => o.TradeCashId == item.tc.id).ToList();
|
|
var CloseCommision = trade_cash_details.Where(o => o.TradeCashType == "了结手续费").Any() ? trade_cash_details.Where(o => o.TradeCashType == "了结手续费").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
var OpenCommision = trade_cash_details.Where(o => o.TradeCashType == "开仓手续费").Any() ? trade_cash_details.Where(o => o.TradeCashType == "开仓手续费").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
item.RealizedPnl = (trade_cash_details.Where(o => o.TradeCashType == "浮动收益").Any() ? trade_cash_details.Where(o => o.TradeCashType == "浮动收益").Sum(o => o.QuoteAmount ?? 0) : 0) * -1;
|
|
item.Commision = OpenCommision + CloseCommision;
|
|
item.AnnualFee = trade_cash_details.Where(o => o.TradeCashType == "利息").Any() ? trade_cash_details.Where(o => o.TradeCashType == "利息").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
new TradeModule.TradeExtendService(this).SetTradeExtend(new List<trade> { item.trade });
|
|
item.BuySell = item.trade.trade_swap.PayLongShort == "多头" ? "Buy" : "Sell";
|
|
item.Amount = item.Amount * (item.BuySell == "Buy" ? 1 : -1);
|
|
if (boundSide == BoundSideEnum.南向)
|
|
{
|
|
item.BuySell = item.BuySell[0].ToString();
|
|
item.Rate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(item.QuoteCurrency, "CNY", emailData.To);
|
|
|
|
//var um = DataCacheProvider.GetUnderlyingDataSource().GetData(flow.UnderlyingCode);
|
|
if (item.tc.Action == ClientCashInCashOut.系统操作_期权费)
|
|
{
|
|
item.Action = "open";
|
|
var flowId = DbContext.trade_swap.FirstOrDefault(o => o.TradeId == item.tc.TradeId)?.FlowId;
|
|
var flow = DbContext.trade_swap_flow.FirstOrDefault(o => o.id == flowId);
|
|
item.flowNumber = flow.Number;
|
|
item.ExerciseDate = flow.ExerciseDate;
|
|
item.CloseDate = flow.SettlementDate;
|
|
}
|
|
else
|
|
{
|
|
var flowId = DbContext.trade_cash_swap.FirstOrDefault(o => o.TradeCashId == item.tc.id)?.FlowId;
|
|
var flow = DbContext.trade_swap_flow.FirstOrDefault(o => o.id == flowId);
|
|
item.flowNumber = flow.Number;
|
|
item.ExerciseDate = flow.ExerciseDate;
|
|
item.BuySell = item.BuySell == "B" ? "S" : "B";
|
|
item.TradeDate = item.UnwindDate;
|
|
item.Amount *= -1;
|
|
item.SpotPrice = item.tc.FinalPrice ?? 0;
|
|
item.CloseDate = flow.SettlementDate;
|
|
}
|
|
}
|
|
}
|
|
var tc_pres = DbContext.trade_cash_pre.Where(o => o.HappenedDate <= emailData.To && o.ValueDate > emailData.To && tradeIds.Contains(o.TradeId)).Distinct().ToList();
|
|
if (boundSide == BoundSideEnum.南向)
|
|
{
|
|
tc_pres = tc_pres.Where(o => o.HappenedDate == emailData.To).ToList();
|
|
}
|
|
foreach (var item in tc_pres)
|
|
{
|
|
var flowId = DbContext.trade_cash_swap.FirstOrDefault(o => o.TradeCashPreId == item.id)?.FlowId;
|
|
var flow = DbContext.trade_swap_flow.FirstOrDefault(o => o.id == flowId);
|
|
//如果收完结算日的盘,tradeCash就已经有了,这里避免重复
|
|
if (ret.Any(o => o.flowNumber == flow.Number))
|
|
{
|
|
continue;
|
|
}
|
|
var t = DbContext.trade.Find(item.TradeId);
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(t.UnderlyingCode);
|
|
var unwindCash = new UnwindCashModel
|
|
{
|
|
trade = t,
|
|
tc = null,
|
|
BBGTicker = um.BBGTicker,
|
|
ContractSize = um.ContractSize,
|
|
RealizedPnl = 0,
|
|
Commision = 0,
|
|
AnnualFee = 0,
|
|
Amount = (t.Lots ?? 0) * (item.UnwindPercentRate ?? 1),
|
|
TradeType = "swap",
|
|
UnderlyingCode = t.UnderlyingCode,
|
|
UnwindPrice = item.FinalPrice ?? 0,
|
|
UnwindDate = flow.TradeDate ?? DateTime.MinValue,
|
|
Action = "unwind",
|
|
TradeDate = t.TradeDate,
|
|
SpotPrice = t.SpotPrice ?? 0,
|
|
ExerciseDate = t.ExerciseDate,
|
|
};
|
|
var trade_cash_details = DbContext.trade_cash_detail.Where(o => o.TradeCashPreId == item.id).ToList();
|
|
var CloseCommision = trade_cash_details.Where(o => o.TradeCashType == "了结手续费").Any() ? trade_cash_details.Where(o => o.TradeCashType == "了结手续费").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
var OpenCommision = trade_cash_details.Where(o => o.TradeCashType == "开仓手续费").Any() ? trade_cash_details.Where(o => o.TradeCashType == "开仓手续费").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
unwindCash.RealizedPnl = (trade_cash_details.Where(o => o.TradeCashType == "浮动收益").Any() ? trade_cash_details.Where(o => o.TradeCashType == "浮动收益").Sum(o => o.QuoteAmount ?? 0) : 0) * -1;
|
|
unwindCash.Commision = OpenCommision + CloseCommision;
|
|
unwindCash.AnnualFee = trade_cash_details.Where(o => o.TradeCashType == "利息").Any() ? trade_cash_details.Where(o => o.TradeCashType == "利息").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
new TradeModule.TradeExtendService(this).SetTradeExtend(new List<trade> { t });
|
|
unwindCash.BuySell = t.trade_swap.PayLongShort == "多头" ? "Buy" : "Sell";
|
|
unwindCash.Amount = unwindCash.Amount * (unwindCash.BuySell == "Buy" ? 1 : -1);
|
|
if (boundSide == BoundSideEnum.南向)
|
|
{
|
|
unwindCash.BuySell = unwindCash.BuySell[0].ToString();
|
|
unwindCash.BuySell = unwindCash.BuySell == "B" ? "S" : "B";
|
|
unwindCash.Rate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(unwindCash.QuoteCurrency, "CNY", emailData.To);
|
|
|
|
//var um = DataCacheProvider.GetUnderlyingDataSource().GetData(flow.UnderlyingCode);
|
|
|
|
unwindCash.flowNumber = flow.Number;
|
|
unwindCash.ExerciseDate = flow.ExerciseDate;
|
|
unwindCash.TradeDate = unwindCash.UnwindDate;
|
|
unwindCash.Amount *= -1;
|
|
unwindCash.SpotPrice = item.FinalPrice ?? 0;
|
|
unwindCash.CloseDate = flow.SettlementDate;
|
|
|
|
}
|
|
ret.Add(unwindCash);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 客户流水
|
|
/// </summary>
|
|
private List<TradeFlowModel> clientTradeFlowQueryList(DateTime endDate, IEnumerable<int> userAssetUnits, Client client, bool extendInfo = false, bool canUsePreRate = false)
|
|
{
|
|
var ret = new List<TradeFlowModel>();
|
|
var PriceProvider = new EodPriceProvider(endDate).Initialize().GetPriceProvider();
|
|
var flowData = from flow in DbContext.trade_swap_flow
|
|
where (flow.StartDate <= endDate && flow.ClientNumber == client.Number)
|
|
join swaps in (from swap in DbContext.trade_swap join trade in DbContext.trade on swap.TradeId equals trade.id where trade.ValidState != "InValid" select swap)
|
|
on flow.id equals swaps.FlowId
|
|
into swaps
|
|
from swap in swaps.DefaultIfEmpty()
|
|
join eod_trades in DbContext.eod_trade
|
|
on swap.TradeId equals eod_trades.TradeId
|
|
into eod_trades
|
|
from eod_trade in eod_trades.Where(o => o.ValueDate == endDate).DefaultIfEmpty()
|
|
join cash_swaps in DbContext.trade_cash_swap
|
|
on flow.id equals cash_swaps.FlowId
|
|
into cash_swaps
|
|
from cash_swap in cash_swaps.DefaultIfEmpty()
|
|
join tradeCashPres in DbContext.trade_cash_pre
|
|
on swap.TradeId equals tradeCashPres.TradeId
|
|
into tradeCashPres
|
|
from tradeCashPre in tradeCashPres.Where(o => o.ValueDate > endDate && o.HappenedDate <= endDate).DefaultIfEmpty()
|
|
join tradeCashs in DbContext.trade_cash
|
|
on cash_swap.TradeCashId equals tradeCashs.id
|
|
into tradeCashs
|
|
from tradeCash in tradeCashs.DefaultIfEmpty()
|
|
join ums in DbContext.underlying_manager
|
|
on flow.UnderlyingCode equals ums.UnderlyingCode
|
|
into ums
|
|
from um in ums.DefaultIfEmpty()
|
|
select new
|
|
{
|
|
flow,
|
|
eod_trade,
|
|
cash_swap,
|
|
swap,
|
|
tradeCashPre,
|
|
tradeCash,
|
|
um
|
|
};
|
|
var data = flowData.GroupBy(o => o.flow).ToDictionary(o => o.Key, o => o.ToList());
|
|
var tradeIds = flowData.Where(o => o.swap != null).Select(o => o.swap.TradeId).ToList();
|
|
var notSettledForward = flowData.Where(o => o.tradeCashPre != null).Select(o => o.tradeCashPre.TradeId).ToList();
|
|
var trades = DbContext.trade.Where(o => tradeIds.Contains(o.id)).ToList();
|
|
var cashDetails_all = DbContext.trade_cash_detail.Where(o => tradeIds.Contains(o.TradeId)).ToList();
|
|
var tcs_all = DbContext.trade_cash.Where(o => tradeIds.Contains(o.TradeId) && o.ValueDate <= endDate).ToList();
|
|
|
|
foreach (var item in data)
|
|
{
|
|
var variety = DataCacheProvider.GetVariety(item.Key.UnderlyingCode);
|
|
var um = item.Value[0].um;
|
|
if (um == null)
|
|
{
|
|
ret.Add(new TradeFlowModel
|
|
{
|
|
ClientName = client.Name,
|
|
id = item.Key.id,
|
|
Amount = item.Key.Lots * (item.Key.BuySell == "B" ? 1 : -1),
|
|
AnnualRate = 0,
|
|
BBGTicker = "",
|
|
BuySell = "客户" + (item.Key.BuySell == "B" ? "买入" : "卖出"),
|
|
Contract = item.Key.UnderlyingCode,
|
|
ContractSize = 0,
|
|
QuoteCurrency = "",
|
|
ExerciseDate = item.Key.ExerciseDate,
|
|
FlowNumber = item.Key.Number,
|
|
CloseDate = item.Key.SettlementDate,
|
|
SettlementCurrency = client.SettlementCurrency,
|
|
UnderlyingCode = item.Key.UnderlyingCode,
|
|
TradeDate = item.Key.TradeDate,
|
|
TradeType = "swap",
|
|
RemainAmount = 0,
|
|
RealizedPnl = 0,
|
|
});
|
|
continue;
|
|
}
|
|
var eod_trade = item.Value.FirstOrDefault(o => o.eod_trade != null)?.eod_trade;
|
|
var cash_swap = item.Value.FirstOrDefault(o => o.cash_swap != null)?.cash_swap;
|
|
var swap = item.Value.FirstOrDefault(o => o.swap != null)?.swap;
|
|
var tc_pres = item.Value.Where(o => o.tradeCashPre != null).Select(o => o.tradeCashPre).Distinct();
|
|
var tradeId = swap != null ? swap.TradeId :
|
|
item.Value.Any(o => o.tradeCash != null) ? item.Value.FirstOrDefault(o => o.tradeCash != null).tradeCash.TradeId :
|
|
tc_pres.Any() ? tc_pres.FirstOrDefault().TradeId :
|
|
cash_swap?.TradeId;
|
|
var t = trades.FirstOrDefault(o => o.id == tradeId);
|
|
var QCurrency = t != null ? t.QuoteCurrency : variety.QuoteCurrency;
|
|
var tradeFlow = new TradeFlowModel()
|
|
{
|
|
ClientName = client.Name,
|
|
id = item.Key.id,
|
|
Amount = item.Key.Lots * (item.Key.BuySell == "B" ? 1 : -1),
|
|
AnnualRate = 0,
|
|
BBGTicker = um.BBGTicker,
|
|
BuySell = "客户" + (item.Key.BuySell == "B" ? "买入" : "卖出"),
|
|
Contract = item.Key.UnderlyingCode,
|
|
ContractSize = um.ContractSize,
|
|
QuoteCurrency = QCurrency,
|
|
ExerciseDate = item.Key.ExerciseDate,
|
|
StartDate = item.Key.StartDate,
|
|
FlowNumber = item.Key.Number,
|
|
CloseDate = item.Key.SettlementDate,
|
|
SettlementCurrency = client.SettlementCurrency,
|
|
UnderlyingCode = item.Key.UnderlyingCode,
|
|
TradeDate = item.Key.TradeDate,
|
|
TradeType = "swap",
|
|
RemainAmount = 0,
|
|
RealizedPnl = 0,
|
|
AnnualFee = 0,
|
|
Commision = 0,
|
|
QuoteFloatFee = 0,
|
|
FloatFee = 0,
|
|
IsOpen = false,
|
|
};
|
|
|
|
tradeFlow.FlagExpd = "expired";
|
|
//找到开仓那笔的结算日
|
|
if (tradeId != null && tradeId != 0)
|
|
{
|
|
var dic = data.FirstOrDefault(o => o.Value.Any(x => (x.eod_trade != null && x.eod_trade.TradeId == tradeId) || (x.swap != null && x.swap.TradeId == tradeId)));
|
|
var stlDate = item.Key.SettlementDate;
|
|
if (dic.Key != null)
|
|
{
|
|
stlDate = dic.Key.SettlementDate;
|
|
}
|
|
|
|
//到结算日才算expired
|
|
if (stlDate != null && stlDate > endDate)
|
|
{
|
|
tradeFlow.FlagExpd = "active";
|
|
}
|
|
}
|
|
|
|
tradeFlow.SpotPrice = item.Key.SpotPrice;
|
|
|
|
if (item.Key.QuoteCurrency != client.SettlementCurrency)
|
|
{
|
|
tradeFlow.Rate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(tradeFlow.QuoteCurrency, client.SettlementCurrency, endDate, canUsePreRate);
|
|
tradeFlow.initRate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(tradeFlow.QuoteCurrency, client.SettlementCurrency, tradeFlow.TradeDate ?? DateTime.Now, canUsePreRate);
|
|
}
|
|
var config = DbContext.client_variety_config.Where(o => o.ClientId == client.id && o.VarietyId == variety.id && o.ValueDate <= item.Key.TradeDate).OrderByDescending(o => o.ValueDate).FirstOrDefault();
|
|
|
|
if (config == null)
|
|
{
|
|
throw new ServiceException($"{client.Name} - {variety.ShortName} 在 {item.Key.TradeDate} 无收费配置");
|
|
}
|
|
tradeFlow.AnnualRate = config.AnnualRate;
|
|
if (item.Key.NeedCostFee)
|
|
{
|
|
tradeFlow.CommisionRate = config.UnAnnualRate == 0 ? config.SingleFee.ToString() : config.UnAnnualRate.OtcFormatPercent();
|
|
}
|
|
else
|
|
{
|
|
tradeFlow.CommisionRate = "0";
|
|
}
|
|
|
|
//远期未到期的也要进去
|
|
if (eod_trade != null || (swap != null && notSettledForward.Contains(swap.id)))
|
|
{
|
|
if (eod_trade != null)
|
|
{
|
|
if (eod_trade.trade.TradeStatus == "确认成交")
|
|
{
|
|
|
|
tradeFlow.FlagExpd = "active";
|
|
var eod_trade_position_swap = DbContext.eod_trade_position_swap.FirstOrDefault(o => o.TradeId == eod_trade.TradeId && o.ValueDate == endDate);
|
|
if (eod_trade_position_swap != null)
|
|
{
|
|
tradeFlow.AnnualFee = eod_trade_position_swap.AnnualFee * -1;
|
|
tradeFlow.Commision = eod_trade_position_swap.Commission * -1;
|
|
tradeFlow.QuoteFloatFee = eod_trade_position_swap.QuoteFloatingWinLoss * -1;
|
|
tradeFlow.FloatFee = eod_trade_position_swap.FloatingWinLoss * -1;
|
|
tradeFlow.UnrealizedPnl = tradeFlow.AnnualFee + tradeFlow.Commision + tradeFlow.FloatFee;
|
|
}
|
|
}
|
|
|
|
tradeFlow.RemainAmount = eod_trade.trade.Notional / um.ContractSize * (item.Key.BuySell == "B" ? 1 : -1);
|
|
}
|
|
|
|
|
|
if (tc_pres != null && tc_pres.Count() > 0)
|
|
{
|
|
foreach (var tc_pre in tc_pres)
|
|
{
|
|
var rate = tradeFlow.Rate ?? 1;
|
|
var cash_details = cashDetails_all.Where(o => o.TradeCashPreId == tc_pre.id && o.ValueDate > endDate).ToList();
|
|
var Annual_Fee = cash_details.Where(o => o.TradeCashType == "利息").Sum(o => o.QuoteAmount ?? 0);
|
|
var Commision = cash_details.Where(o => o.TradeCashType == "开仓手续费").Sum(o => o.QuoteAmount ?? 0) + cash_details.Where(o => o.TradeCashType == "了结手续费").Sum(o => o.QuoteAmount ?? 0);
|
|
var FloatFee = cash_details.Where(o => o.TradeCashType == "浮动收益").Sum(o => o.QuoteAmount ?? 0);
|
|
tradeFlow.AnnualFee += Annual_Fee * rate * -1;
|
|
tradeFlow.Commision += Commision * rate * -1;
|
|
tradeFlow.QuoteFloatFee += FloatFee * -1;
|
|
tradeFlow.FloatFee += FloatFee * rate * -1;
|
|
}
|
|
tradeFlow.UnrealizedPnl = tradeFlow.AnnualFee + tradeFlow.Commision + tradeFlow.FloatFee;
|
|
}
|
|
tradeFlow.TodayPrice = PriceProvider.GetPrice(item.Key.UnderlyingCode);
|
|
|
|
}
|
|
if (swap != null)
|
|
{
|
|
|
|
var tcs = tcs_all.Where(o => o.TradeId == swap.TradeId && o.ValueDate <= endDate).ToList();
|
|
if (tcs != null && tcs.Count() > 0)
|
|
{
|
|
tradeFlow.RealizedPnl = tcs.Sum(o => o.Amount) * -1;
|
|
}
|
|
if (extendInfo)
|
|
{
|
|
tradeFlow.IsOpen = true;
|
|
tradeFlow.AssetName = t.AssetBookName;
|
|
tradeFlow.OriginStockEqvNotion = t.OriginalStockEqvNotional ?? 0;
|
|
tradeFlow.TradeNumber = t.TradeNumber;
|
|
tradeFlow.CommisionSingleFee = config.SingleFee;
|
|
tradeFlow.CommisionRateShow = config.UnAnnualRate;
|
|
tradeFlow.RemainStockEqvNotion = t.TradeStatus == "确认成交" ? t.StockEqvNotional : 0;
|
|
var tcIds = tcs.Select(o => o.id);
|
|
var cash_details = DbContext.trade_cash_detail.Where(o => tcIds.Contains(o.TradeCashId) && o.ValueDate <= endDate).ToList();
|
|
var Annual_Fee = cash_details.Where(o => o.TradeCashType == "利息").Sum(o => o.QuoteAmount ?? 0);
|
|
var Commision = cash_details.Where(o => o.TradeCashType == "开仓手续费").Sum(o => o.QuoteAmount ?? 0) + cash_details.Where(o => o.TradeCashType == "了结手续费").Sum(o => o.QuoteAmount ?? 0);
|
|
tradeFlow.UnwindCommision = Commision;
|
|
tradeFlow.UnwindAnnualFee = Annual_Fee;
|
|
}
|
|
}
|
|
ret.Add(tradeFlow);
|
|
}
|
|
ret = ret.OrderByDescending(o => o.TradeDate).ToList();
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 标的汇总
|
|
/// </summary>
|
|
private List<PositionUnderlyingModel> getClientUnderlyingPosition(List<PositionTradeModel> swap_position, DateTime endDate)
|
|
{
|
|
var ret = new List<PositionUnderlyingModel>();
|
|
var settlementCurrency = "CNY";
|
|
var umDic = swap_position.GroupBy(o => o.UnderlyingCode).ToDictionary(o => o.Key);
|
|
foreach (var item in umDic)
|
|
{
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(item.Key);
|
|
var variety = DataCacheProvider.GetVariety(item.Key);
|
|
var Rate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(variety.QuoteCurrency, settlementCurrency, endDate);
|
|
var position = new PositionUnderlyingModel()
|
|
{
|
|
Amount = item.Value.Sum(o => (o.Amount + o.UnwindLots)),
|
|
//StockEqvNotional = item.Value.Sum(o => o.trade.StockEqvNotional * Rate),
|
|
CloseDate = um.CloseDate,
|
|
ContractSize = um.ContractSize,
|
|
QuoteCurrency = variety.QuoteCurrency,
|
|
Rate = Rate,
|
|
UnderlyingCode = um.UnderlyingCode,
|
|
UnderlyingName = um.UnderlyingName,
|
|
//FloatFee = item.Value.Sum(o => o.StlUnrealizedPnl),
|
|
MaturityDate = um.MaturityDate,
|
|
QuoteFloatFee = item.Value.Sum(o => o.UnrealizedPnl),
|
|
QuoteUnrealized = item.Value.Sum(o => o.UnrealizedPnl - o.Commision - o.AnnualFee),
|
|
TodayPrice = item.Value.FirstOrDefault().TodayPrice
|
|
};
|
|
position.StockEqvNotional = Math.Abs(position.Amount) * position.ContractSize * position.TodayPrice * position.Rate;
|
|
position.UnrealizedPnl = position.QuoteUnrealized * Rate;
|
|
position.FloatFee = position.QuoteFloatFee * Rate;
|
|
ret.Add(position);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 资金明细
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private CashInCashOutModel SearchListExtendOnly(EntryExitReq req, string SettlementCurrency, string QuotaCurrency, BoundSideEnum side, bool canUsePreRate = false)
|
|
{
|
|
var result = new CashInCashOutModel();
|
|
result.cashes = new List<Cash_Record>();
|
|
req.State = "已确认,已结算";
|
|
req.Direction = $"入金,出金,其他收入,其他支出";
|
|
req.TradeAction =
|
|
$"{ClientCashInCashOut.系统操作_行权费},{ClientCashInCashOut.系统操作_平仓费},{ClientCashInCashOut.系统操作_期权费},{ClientCashInCashOut.系统操作_票息},{ClientCashInCashOut.系统操作_互换}";
|
|
req.IsMoneyNotEqualsZero = true;
|
|
var sList = new EntryExitBLL().SearchListExtendOnly(req);
|
|
|
|
foreach (var item in sList)
|
|
{
|
|
var tc = DbContext.trade_cash.Find(item.TradeCashId);
|
|
var trade_cash_details = DbContext.trade_cash_detail.Where(o => o.TradeCashId == item.TradeCashId && o.TradeCashId != 0);
|
|
var RealizedPnl = (trade_cash_details.Where(o => o.TradeCashType == "浮动收益").Any() ? trade_cash_details.Where(o => o.TradeCashType == "浮动收益").Sum(o => o.QuoteAmount ?? 0) : 0) * -1;
|
|
var CloseCommision = trade_cash_details.Where(o => o.TradeCashType == "了结手续费").Any() ? trade_cash_details.Where(o => o.TradeCashType == "了结手续费").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
var OpenCommision = trade_cash_details.Where(o => o.TradeCashType == "开仓手续费").Any() ? trade_cash_details.Where(o => o.TradeCashType == "开仓手续费").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
var AnnualFee = trade_cash_details.Where(o => o.TradeCashType == "利息").Any() ? trade_cash_details.Where(o => o.TradeCashType == "利息").Sum(o => o.QuoteAmount ?? 0) : 0;
|
|
//北向需要的是USD转CNH的汇率,所以这里倒过来了,相应的用到这个汇率是用的除
|
|
var rate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(SettlementCurrency, QuotaCurrency, item.HappenDate ?? DateTime.Now, canUsePreRate);//待讨论
|
|
result.cashes.Add(new Cash_Record()
|
|
{
|
|
cash = item,
|
|
tc = tc,
|
|
AnnualFee = AnnualFee,
|
|
Commision = CloseCommision + OpenCommision,
|
|
CurrencyRate = rate,
|
|
EndBalance = 0,
|
|
RealizedPnl = RealizedPnl,
|
|
ValueDate = item.HappenDate
|
|
});
|
|
}
|
|
if (side == BoundSideEnum.北向)
|
|
{
|
|
result.cashes = result.cashes.OrderBy(o => o.ValueDate).ThenBy(o => o.cash.id).ToList();
|
|
}
|
|
else
|
|
{
|
|
result.cashes = result.cashes.OrderBy(o => o.OptDate).ThenBy(o => o.ValueDate).ToList();
|
|
}
|
|
|
|
for (var i = 0; i < result.cashes.Count; i++)
|
|
{
|
|
var item = result.cashes[i];
|
|
item.ClientName = req.ClientName;
|
|
if (item.tc == null)
|
|
{
|
|
item.CashInFlow = item.cash.Money ?? 0;
|
|
if (item.cash.DirectionType == "支出")
|
|
{
|
|
item.CashInFlow = Math.Abs(item.CashInFlow) * -1;
|
|
item.CashType = "出金";
|
|
}
|
|
else
|
|
{
|
|
item.CashInFlow = Math.Abs(item.CashInFlow);
|
|
item.CashType = "入金";
|
|
}
|
|
item.flowNumber = "银行流水";
|
|
}
|
|
else
|
|
{
|
|
if (item.tc.Action == ClientCashInCashOut.系统操作_期权费)
|
|
{
|
|
var flowId = DbContext.trade_swap.FirstOrDefault(o => o.TradeId == item.tc.TradeId)?.FlowId;
|
|
item.flowNumber = DbContext.trade_swap_flow.FirstOrDefault(o => o.id == flowId)?.Number;
|
|
item.CashType = "期权费";
|
|
}
|
|
else
|
|
{
|
|
var flowId = DbContext.trade_cash_swap.FirstOrDefault(o => o.TradeCashId == item.tc.id)?.FlowId;
|
|
item.flowNumber = DbContext.trade_swap_flow.FirstOrDefault(o => o.id == flowId)?.Number;
|
|
item.CashType = "结算金额";
|
|
}
|
|
}
|
|
if (item.cash.CurrencyCode != SettlementCurrency)
|
|
{
|
|
//北向需要的是USD转CNH的汇率,所以这里倒过来了,相应的用到这个汇率是用的除
|
|
var rate = new EodModule.EodCurrencyRateService(UserInfo).
|
|
GetCurrencyRate(SettlementCurrency, item.cash.CurrencyCode, req.HappenDateEnd, canUsePreRate);
|
|
item.CashInFlow /= rate;
|
|
}
|
|
//var TradeCashes = (item.RealizedPnl - item.Commision - item.AnnualFee) / item.CurrencyRate;
|
|
item.CashMovement = item.CashInFlow == 0 && item.tc != null ? (item.tc.Amount * -1) : item.CashInFlow;
|
|
if (i == 0)
|
|
{
|
|
item.EndBalance = item.CashMovement;
|
|
}
|
|
else
|
|
{
|
|
item.EndBalance = result.cashes[i - 1].EndBalance + item.CashMovement;
|
|
}
|
|
item.OptDate = item.cash.OptDate;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 历史数据
|
|
/// </summary>
|
|
private ClientDingShiReport_ZJ GetHistoryInfo(ClientDingShiReport_ZJ report)
|
|
{
|
|
var flowReq = new TradeFlowReq() { ClientIds = new List<int>() { report.client.id }, TradeDateEnd = report.ReportEnd };
|
|
var tradeFlowHis = new TradeModule.SwapModule.TradeSwapService(OptUser).SearchFlowHistoryList(flowReq);
|
|
var cashReq = new ClientCashInCashOutHistoryReq() { ClientIds = new List<int>() { report.client.id }, HappenDateEnd = report.ReportEnd };
|
|
var clientCashes = new ClientCashModule.ClientCashInCashOutHistoryService(OptUser).SearchClientCashInCashOutHistoryList(cashReq);
|
|
|
|
foreach (var item in tradeFlowHis.rows)
|
|
{
|
|
report.summaryReportModel.swap_flow.Add(new TradeFlowModel()
|
|
{
|
|
FlowNumber = item.ContractId,
|
|
FlagExpd = item.FlagExpired,
|
|
QuoteCurrency = item.QuoteCurrency,
|
|
SettlementCurrency = item.SettleCurrency,
|
|
TradeDate = item.TradeDate,
|
|
ExerciseDate = item.ExpireDate,
|
|
CloseDate = item.SettleDate,
|
|
BuySell = item.Direction,
|
|
PrmDate = item.PremiumDate,
|
|
PremCNY = item.PremiumCNY,
|
|
TradeType = item.TradeType,
|
|
UnderlyingCode = item.UnderlyingCode,
|
|
Amount = item.InitialLots,
|
|
RemainAmount = item.Lots,
|
|
ContractSize = item.Size,
|
|
SpotPrice = item.InitialSpotPrice,
|
|
TodayPrice = item.SpotPrice,
|
|
initRate = item.InitialRate,
|
|
Rate = item.Rate,
|
|
Commision = item.EstimateCommision,
|
|
CommisionRate = item.CommissionRate,
|
|
AnnualFee = item.EstimateAnnualFee,
|
|
AnnualRate = item.AnnualRate,
|
|
FloatFee = item.FloatingWinLoss,
|
|
QuoteFloatFee = item.FloatingWinLossQuote,
|
|
UnrealizedPnl = item.UnRealizedPnl,
|
|
RealizedPnl = item.RealizedPnl
|
|
});
|
|
}
|
|
|
|
foreach (var item in clientCashes.rows)
|
|
{
|
|
report.cash_records.cashes.Add(new Cash_Record()
|
|
{
|
|
OptDate = item.ValueDate,
|
|
ValueDate = item.HappenDate,
|
|
flowNumber = item.ContractId,
|
|
CashMovement = item.Amount ?? 0,
|
|
CashType = item.Action
|
|
});
|
|
}
|
|
|
|
return report;
|
|
}
|
|
|
|
public string GenerateFileEntry(ClientDingShiReport_ZJ report)
|
|
{
|
|
var tempFolder = OtcAppContext.MapPath("~/App_Docs/Temp/结算报告");
|
|
var targetPath = string.IsNullOrEmpty(report.downloadFilePath) ? Path.Combine(tempFolder, report.ReportEnd.ToString("yyyyMMdd")) : report.downloadFilePath;
|
|
if (!Directory.Exists(targetPath))
|
|
{
|
|
Directory.CreateDirectory(targetPath);
|
|
}
|
|
var clientName = string.IsNullOrEmpty(report.client.Abbreviation) ? report.client.Name : report.client.Abbreviation;
|
|
var fileName = report.ReportFrom == DateTime.MinValue ? $"持仓报告_{report.ReportEnd:yyyyMMdd}_{clientName}" : $"持仓报告_{report.ReportFrom:yyyyMMdd}_{report.ReportEnd:yyyyMMdd}_{clientName}";
|
|
var targetFileName = Path.Combine(targetPath, $"{fileName}.xlsx");
|
|
var modelDict = new Dictionary<string, object>();
|
|
var sourcePath = "";
|
|
var sourceFileName = "";
|
|
if (report.client.BoundSide == BoundSideEnum.北向)
|
|
{
|
|
|
|
modelDict.Add("Summary", report.summaryReportModel);
|
|
modelDict.Add("Holding Details", report.swap_position);
|
|
modelDict.Add("Unwind Trade Details", report.swap_unwind);
|
|
modelDict.Add("Cash Statement", report.cash_records);
|
|
|
|
|
|
sourcePath = OtcAppContext.MapPath("~/App_Docs/导出模板");
|
|
sourceFileName = Path.Combine(sourcePath, "北向估值单模板.xlsx");
|
|
}
|
|
else
|
|
{
|
|
modelDict.Add("Report_CptyBalance", report.summaryReportModel);
|
|
modelDict.Add("Holdings", report.underlying_positon);
|
|
modelDict.Add("Trades_today", report.today_swap);
|
|
modelDict.Add("Report_CptyCashFlow", report.cash_records);
|
|
|
|
|
|
sourcePath = OtcAppContext.MapPath("~/App_Docs/导出模板");
|
|
sourceFileName = Path.Combine(sourcePath, "南向估值单模板.xlsx");
|
|
}
|
|
var pdffile = ExcelTemplate.GeneratePDFFromExeclTemplate(sourcePath, sourceFileName, modelDict, targetPath, targetFileName
|
|
, shouldDeleteSheet: true, needToPdf: false, callback: new GenerateExcelCallback(this)
|
|
{
|
|
report = report
|
|
}.Callback);
|
|
|
|
return Path.Combine(targetPath, targetFileName);
|
|
|
|
}
|
|
|
|
public string ReplaceWildcard(string input, ClientDingShiReport_ZJ report)
|
|
{
|
|
if (!string.IsNullOrEmpty(input))
|
|
{
|
|
input = Regex.Replace(input, @"\{\{(.*?)\}\}", m =>
|
|
{
|
|
switch (m.Groups[1].Value)
|
|
{
|
|
case "客户名称": return report.client.Name;
|
|
case "客户编号": return report.client.Number;
|
|
case "支付截止时间": return QdpCalendarHelper.GetNonHoliday(DateTime.Now < DateTime.Now.Date.AddHours(9).AddMinutes(30) ? DateTime.Now : DateTime.Now.AddDays(1)).ToString("yyyy年MM月dd日") + "上午9:30";
|
|
case "追保金额": return report.summaryReportModel.Margin.ToString("0.00");
|
|
case "大写追保金额": return NumberHelper.CmycurD(report.summaryReportModel.Margin);
|
|
case "应付资金总额": return report.summaryReportModel.PayableFund.ToString("0.00");
|
|
case "大写应付资金总额": return NumberHelper.CmycurD(report.summaryReportModel.PayableFund);
|
|
case "发送日期": return DateTime.Now.ToString("yyyy-MM-dd");
|
|
case "预付金占用": return report.summaryReportModel.MarginRequiement.ToString("0.00");
|
|
case "可用资金": return report.summaryReportModel.AvailableFund.ToString("0.00");
|
|
case "授信额度": return report.summaryReportModel.Credit.ToString("0.00");
|
|
//case "应付了结交易款": return report.FundReportModel.ClosedTradePayableFundString;
|
|
//case "应付存续交易款": return report.FundReportModel.PositionTradePayableFundString;
|
|
//case "存续交易期权费净额": return report.FundReportModel.PositionPremiumNetCashString;
|
|
//case "可取资金": return report.FundReportModel.DesirableFundString;
|
|
case "起始日期": return report.ReportFrom.ToString("yyyy-MM-dd");
|
|
case "结束日期": return report.ReportEnd.ToString("yyyy-MM-dd");
|
|
default: return string.Empty;
|
|
}
|
|
});
|
|
}
|
|
return input;
|
|
}
|
|
|
|
class GenerateExcelCallback : YLBaseService
|
|
{
|
|
public ClientDingShiReport_ZJ report;
|
|
|
|
public GenerateExcelCallback(YLBaseService baseService) : base(baseService)
|
|
{
|
|
|
|
}
|
|
|
|
public void Callback(ExcelWorksheets sheets)
|
|
{ }
|
|
}
|
|
|
|
public byte[] exportFlowInfo()
|
|
{
|
|
var endDate = EodOperationBase.GetLastSettlementDate(valuedateBLL.ValueDate);
|
|
var clients = DbContextFactory.GetClientDbContext(OptUser).client.Where(o => o.BoundSide == BoundSideEnum.南向 && o.ProcessOrderId == -2).ToList();
|
|
var result = new List<TradeFlowModel>();
|
|
foreach (var item in clients)
|
|
{
|
|
var clientFlowList = clientTradeFlowQueryList(endDate, null, item, canUsePreRate: true);
|
|
result.AddRange(clientFlowList);
|
|
}
|
|
//客户名称 交易编码 是否到期 计价货币 结算货币 交易日 到期日 交割日(LME Prompt) 客户买/卖
|
|
//权利金日 期权费¥ 衍生品类型 标的代码 初始开仓手数 剩余手数 合约乘数 初始价格
|
|
//初始汇率 最新价格 最新汇率 佣金费率 预估佣金¥ 年化手续费率 预估年化手续费¥
|
|
//浮动收益(计价货币) 浮动收益(结算货币) 未实现收益(结算货币) 已实现收益(结算货币)
|
|
|
|
var dc = new List<Commons.ExcelHelper.DataColumnModel>
|
|
{
|
|
new Commons.ExcelHelper.DataColumnModel("客户名称", "ClientName"),
|
|
new Commons.ExcelHelper.DataColumnModel("交易编码", "FlowNumber"),
|
|
new Commons.ExcelHelper.DataColumnModel("是否到期", "FlagExpd"),
|
|
new Commons.ExcelHelper.DataColumnModel("计价货币", "QuoteCurrency"),
|
|
new Commons.ExcelHelper.DataColumnModel("结算货币", "SettlementCurrency"),
|
|
new Commons.ExcelHelper.DataColumnModel("交易日", "TradeDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("到期日", "ExerciseDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("交割日(LME Prompt)", "CloseDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("客户买/卖", "BuySell"),
|
|
new Commons.ExcelHelper.DataColumnModel("权利金日", "PrmDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("期权费¥", "PremCNY"),
|
|
new Commons.ExcelHelper.DataColumnModel("衍生品类型", "TradeType"),
|
|
new Commons.ExcelHelper.DataColumnModel("标的代码", "UnderlyingCode"),
|
|
new Commons.ExcelHelper.DataColumnModel("初始开仓手数", "Amount"),
|
|
new Commons.ExcelHelper.DataColumnModel("剩余手数", "RemainAmount"),
|
|
new Commons.ExcelHelper.DataColumnModel("合约乘数", "ContractSize"),
|
|
new Commons.ExcelHelper.DataColumnModel("初始价格", "SpotPrice"),
|
|
new Commons.ExcelHelper.DataColumnModel("初始汇率", "initRate"),
|
|
new Commons.ExcelHelper.DataColumnModel("最新价格", "TodayPrice"),
|
|
new Commons.ExcelHelper.DataColumnModel("最新汇率", "Rate"),
|
|
new Commons.ExcelHelper.DataColumnModel("佣金费率", "CommisionRate"),
|
|
new Commons.ExcelHelper.DataColumnModel("预估佣金¥", "Commision"),
|
|
new Commons.ExcelHelper.DataColumnModel("年化手续费率", "AnnualRate"),
|
|
new Commons.ExcelHelper.DataColumnModel("预估年化手续费¥", "AnnualFee"),
|
|
new Commons.ExcelHelper.DataColumnModel("浮动收益(计价货币)", "QuoteFloatFee"),
|
|
new Commons.ExcelHelper.DataColumnModel("浮动收益(结算货币)", "FloatFee"),
|
|
new Commons.ExcelHelper.DataColumnModel("未实现收益(结算货币)", "UnrealizedPnl"),
|
|
new Commons.ExcelHelper.DataColumnModel("已实现收益(结算货币)", "RealizedPnl"),
|
|
};
|
|
new Commons.ExcelHelper().ListToExcel<TradeFlowModel>(dc.ToArray(), result, "Sheet1", true, out var buffer);
|
|
return buffer;
|
|
}
|
|
|
|
public byte[] exportCashInfo()
|
|
{
|
|
var endDate = EodOperationBase.GetLastSettlementDate(valuedateBLL.ValueDate);
|
|
var clients = DbContextFactory.GetClientDbContext(OptUser).client.Where(o => o.BoundSide == BoundSideEnum.南向 && o.ProcessOrderId == -2).ToList();
|
|
var result = new List<Cash_Record>();
|
|
foreach (var item in clients)
|
|
{
|
|
var req = new EntryExitReq() { ClientId = item.id, HappenDateEnd = endDate, ClientName = item.Name };
|
|
var cashRet = SearchListExtendOnly(req, item.SettlementCurrency, "CNY", item.BoundSide, true);
|
|
result.AddRange(cashRet.cashes);
|
|
}
|
|
|
|
var dc = new List<Commons.ExcelHelper.DataColumnModel>
|
|
{
|
|
new Commons.ExcelHelper.DataColumnModel("客户名称", "ClientName"),
|
|
new Commons.ExcelHelper.DataColumnModel("记录日期", "OptDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("发生日期", "ValueDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("资金金额", "CashMovement"),
|
|
new Commons.ExcelHelper.DataColumnModel("资金科目", "CashType"),
|
|
new Commons.ExcelHelper.DataColumnModel("交易编码", "flowNumber"),
|
|
};
|
|
new Commons.ExcelHelper().ListToExcel<Cash_Record>(dc.ToArray(), result, "Sheet1", true, out var buffer);
|
|
return buffer;
|
|
}
|
|
|
|
public byte[] exportOpenFlow()
|
|
{
|
|
var clients = DbContextFactory.GetClientDbContext(OptUser).client.Where(o => o.ProcessOrderId == -2).ToList();
|
|
var result = new List<TradeFlowModel>();
|
|
foreach (var item in clients)
|
|
{
|
|
var endDate = EodOperationBase.GetLastSettlementDate(valuedateBLL.ValueDate);
|
|
var clientFlowList = clientTradeFlowQueryList(endDate, null, item, true, true).Where(o => o.IsOpen).ToList();
|
|
clientFlowList.ForEach(o => o.boundSide = item.BoundSide);
|
|
result.AddRange(clientFlowList);
|
|
}
|
|
var dc = new List<Commons.ExcelHelper.DataColumnModel>
|
|
{
|
|
//资金流向 簿记账户 交易状态 结构类型 流水编号 合约编号 客户名称
|
|
//计价货币 标的 初始名义本金 期初数量 交易日期 开始日期 到期日期
|
|
//结算日 期初价格 佣金费率 年化手续费率 交易方向 结算货币
|
|
//合约乘数 初始汇率 预估佣金(结算) 实收佣金(结算) 预估年化手续费(结算)
|
|
//实收年化手续费(结算) 剩余数量 未实现收益(结算货币) 已实现盈亏(结算) 剩余名义本金(结算)
|
|
|
|
new Commons.ExcelHelper.DataColumnModel("资金流向", "BoundSideDesc"),
|
|
new Commons.ExcelHelper.DataColumnModel("簿记账户", "AssetName"),
|
|
new Commons.ExcelHelper.DataColumnModel("交易状态", "FlagExpd"),
|
|
new Commons.ExcelHelper.DataColumnModel("结构类型", "TradeType"),
|
|
new Commons.ExcelHelper.DataColumnModel("流水编号", "FlowNumber"),
|
|
new Commons.ExcelHelper.DataColumnModel("合约编号", "TradeNumber"),
|
|
new Commons.ExcelHelper.DataColumnModel("客户名称", "ClientName"),
|
|
new Commons.ExcelHelper.DataColumnModel("计价货币", "QuoteCurrency"),
|
|
new Commons.ExcelHelper.DataColumnModel("标的", "UnderlyingCode"),
|
|
new Commons.ExcelHelper.DataColumnModel("初始名义本金", "OriginStockEqvNotion"),
|
|
new Commons.ExcelHelper.DataColumnModel("初始开仓手数", "Amount"),
|
|
new Commons.ExcelHelper.DataColumnModel("交易日期", "TradeDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("开始日期", "StartDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("到期日期", "ExerciseDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("结算日", "CloseDate"),
|
|
new Commons.ExcelHelper.DataColumnModel("期初价格", "SpotPrice"),
|
|
new Commons.ExcelHelper.DataColumnModel("佣金费率", "CommisionRateShow"),
|
|
new Commons.ExcelHelper.DataColumnModel("佣金单手费用", "CommisionSingleFee"),
|
|
new Commons.ExcelHelper.DataColumnModel("年化手续费率", "AnnualRate"),
|
|
new Commons.ExcelHelper.DataColumnModel("交易方向", "BuySell"),
|
|
new Commons.ExcelHelper.DataColumnModel("结算货币", "SettlementCurrency"),
|
|
new Commons.ExcelHelper.DataColumnModel("合约乘数", "ContractSize"),
|
|
new Commons.ExcelHelper.DataColumnModel("预估佣金(结算)", "Commision"),
|
|
new Commons.ExcelHelper.DataColumnModel("实收佣金(结算)", "UnwindCommision"),
|
|
new Commons.ExcelHelper.DataColumnModel("初始汇率", "initRate"),
|
|
new Commons.ExcelHelper.DataColumnModel("预估年化手续费(结算) ", "AnnualFee"),
|
|
new Commons.ExcelHelper.DataColumnModel("实收年化手续费(结算) ", "UnwindAnnualFee"),
|
|
new Commons.ExcelHelper.DataColumnModel("剩余数量", "RemainAmount"),
|
|
new Commons.ExcelHelper.DataColumnModel("未实现收益(结算货币)", "UnrealizedPnl"),
|
|
new Commons.ExcelHelper.DataColumnModel("已实现收益(结算货币)", "RealizedPnl"),
|
|
new Commons.ExcelHelper.DataColumnModel("剩余名义本金", "RemainStockEqvNotion"),
|
|
};
|
|
new Commons.ExcelHelper().ListToExcel<TradeFlowModel>(dc.ToArray(), result, "Sheet1", true, out var buffer);
|
|
return buffer;
|
|
}
|
|
|
|
public byte[] exportClientCashRemian(DateTime reportDate)
|
|
{
|
|
var clients = DbContextFactory.GetClientDbContext(OptUser).client.Where(o => o.ProcessOrderId == -2).ToList();
|
|
var lastBalanceDate = BLL.Eod.EodOperationBase.GetLastSettlementDate(reportDate);
|
|
var clientRemians = new List<clientCashRemian>();
|
|
var balances = DbContext.ClientBalanceDaily.Where(o => o.BalanceDate == reportDate).ToArray();
|
|
foreach (var client in clients)
|
|
{
|
|
var dic = new Dictionary<string, double>();
|
|
if (reportDate <= lastBalanceDate)
|
|
{
|
|
var balance = balances.FirstOrDefault(o => o.ClientId == client.id);
|
|
if (balance != null)
|
|
{
|
|
var fundObject = JsonConvert.DeserializeObject<FundObject>(balance.FundJson);
|
|
dic = fundObject.TodayRemainFund;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dic = new EntryExitBLL().getClientCash(client.id);
|
|
}
|
|
if (dic != null && (dic.ContainsKey("USD") || dic.ContainsKey("CNY")))
|
|
{
|
|
clientRemians.Add(new clientCashRemian
|
|
{
|
|
ClientNumber = client.Number,
|
|
ClientName = client.Name,
|
|
RemainUSD = dic["USD"],
|
|
RemainRMB = dic["CNY"],
|
|
reportDateStr = reportDate.ToString("yyyy-MM-dd"),
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
var dc = new List<Commons.ExcelHelper.DataColumnModel>
|
|
{
|
|
new Commons.ExcelHelper.DataColumnModel("客户名称", "ClientName"),
|
|
new Commons.ExcelHelper.DataColumnModel("客户编码", "ClientNumber"),
|
|
new Commons.ExcelHelper.DataColumnModel("日终余额USD", "RemainUSD"),
|
|
new Commons.ExcelHelper.DataColumnModel("日终余额CNY", "RemainRMB"),
|
|
new Commons.ExcelHelper.DataColumnModel("日期", "reportDateStr"),
|
|
};
|
|
new Commons.ExcelHelper().ListToExcel<clientCashRemian>(dc.ToArray(), clientRemians, "Sheet1", true, out var buffer);
|
|
return buffer;
|
|
}
|
|
|
|
private class clientCashRemian
|
|
{
|
|
public string ClientName { get; set; }
|
|
|
|
public string ClientNumber { get; set; }
|
|
|
|
public double RemainUSD { get; set; }
|
|
|
|
public double RemainRMB { get; set; }
|
|
|
|
public string reportDateStr { get; set; }
|
|
}
|
|
}
|
|
}
|