Files
zszq-trs/YLErpWeb/Controllers/MarginRateSwapController.cs

497 lines
25 KiB
C#

using NPOI.SS.Formula.Functions;
using OfficeOpenXml;
using System;
using YLErp.BLL.EodSettlement;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.EodModule.QueryModule;
using YLErp.Modules.MarginModule;
using YLErp.Modules.SwapModule;
using YLErp.Office;
using static YLErp.Modules.MarginModule.MarginRateSwapService;
namespace YLErp.Web.Controllers
{
public class MarginRateSwapController : BaseController
{
[MyAuthorize("互换簿记预设-互换预付金率维护")]
public ActionResult MarginRateSwapList()
{
var MarginRateSwaps = yldb.client_marginrate.ToList();
GetExtendInfo(MarginRateSwaps);
return View(MarginRateSwaps);
}
[MyAuthorize("互换簿记预设-互换预付金率修改")]
public ActionResult MarginRateSwapEdit(string enid, string type)
{
var id = DecryptInt(enid);
if (id == 0)
{
return View(new client_marginrate() { Type = type });
}
var MarginRateSwap = yldb.client_marginrate.Find(id);
GetExtendInfo(new List<client_marginrate> { MarginRateSwap });
return View(MarginRateSwap);
}
[MyAuthorize("互换簿记预设-互换预付金率修改")]
public JsonResult ImportMagrinRate()
{
if (Request.Form.Files.Count == 0)
{
return JsonError("上传文件不存在");
}
var file = Request.Form.Files[0];
if (!Path.GetExtension(file.FileName).Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
{
return JsonError("请上传Excel(.xlsx)格式文件");
}
using var stream = file.OpenReadStream();
new MarginRateSwapService(CurUser).ImportMarginRate(stream, out var TotalNum, out var SuccessNum);
return Json(new
{
success = true,
totalNum = TotalNum,
successNum = SuccessNum,
});
}
[MyAuthorize("互换簿记预设-互换预付金率修改")]
public JsonResult MarginRateSwapDelete(string enid)
{
var id = DecryptInt(enid);
var MarginRateSwap = yldb.client_marginrate.Find(id);
if (MarginRateSwap == null)
{
throw new ServiceException("数据库中未找到");
}
yldb.client_marginrate.Remove(MarginRateSwap);
yldb.SaveChanges();
return JsonSuccess("已删除");
}
[MyAuthorize("互换簿记预设-互换预付金率修改")]
public JsonResult MarginRateSwapEditJson(client_marginrate MarginRateSwap)
{
MarginRateSwap.InitMarginRate /= 100;
MarginRateSwap.ClosePositionLine /= 100;
MarginRateSwap.WarningLine /= 100;
MarginRateSwap.InitMarginRebateRate /= 100;
MarginRateSwap.AddToMarginRebateRate /= 100;
MarginRateSwap.LongInitMarginRate /= 100;
MarginRateSwap.ShortInitMarginRate /= 100;
MarginRateSwap.MaintenanceRate /= 100;
new MarginRateSwapService(CurUser).saveMarginRate(MarginRateSwap);
return JsonSuccess("已修改");
}
[HttpPost]
public JsonResult MarginRateSwapQuery(MarginRateSwapReq req)
{
var sList = new MarginRateSwapService(CurUser).SearchList(req);
GetExtendInfo(sList.rows);
return Json(sList);
}
private void GetExtendInfo(IEnumerable<client_marginrate> MarginRateSwaps)
{
foreach (var item in MarginRateSwaps)
{
if (item.ClientId != 0)
{
var client = DataCacheProvider.GetClientDataSource().GetData(item.ClientId);
if (client != null)
{
item.ClientName = client.Name;
}
}
var variety = DataCacheProvider.GetVarietyDataSource().GetData(item.VarietyId ?? 0);
if (variety != null)
{
item.VarietyCode = variety.VarietyCode;
item.VarietyName = variety.VarietyName;
}
}
}
public ActionResult MarginRateSwapMonitor()
{
ViewBag.valueDate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd");
return View();
}
[HttpPost]
public JsonResult MarginRateSwapMonitorQuery(MarginRateSwapMonitorReq req)
{
return Json(monitorQuery(req));
}
private List<TradeSwapMarginMonitorModel> monitorQuery(MarginRateSwapMonitorReq req)
{
var valueDate = valuedateBLL.ValueDate;
var tradePredicate = PredicateBuilder.Create<trade>(t => t.TradeStatus.Equals(ConsTrade.确认成交) && t.ValidState != "InValid" && t.TradeType.Equals("收益互换"));
if (req.ClientIds != null && req.ClientIds.Count() > 0)
{
tradePredicate = tradePredicate.And(t => req.ClientIds.Contains(t.ClientId));
}
if (req.AssetIds != null && req.AssetIds.Count() > 0)
{
tradePredicate = tradePredicate.And(t => req.AssetIds.Contains(t.AssetId));
}
if (req.TradeNumber != null)
{
tradePredicate = tradePredicate.And(t => t.TradeNumber.Contains(req.TradeNumber));
}
if (req.DateFromTradeDate != null)
{
tradePredicate = tradePredicate.And(t => t.TradeDate >= req.DateFromTradeDate);
}
if (req.DateToTradeDate != null)
{
tradePredicate = tradePredicate.And(t => t.TradeDate <= req.DateToTradeDate);
}
//获取所有确认成交的收益互换
var query = from trade in yldb.trade.Where(tradePredicate)
join tradeSwap in yldb.trade_swap on trade.id equals tradeSwap.TradeId
join tradeSwapDetailTemp1 in yldb.trade_swap_detail.Where(t => t.ValidState != "InValid" || t.ValidState == null) on tradeSwap.TradeId equals tradeSwapDetailTemp1.TradeId into tradeSwapDetailTemp
from tradeSwapDetail in tradeSwapDetailTemp.DefaultIfEmpty()
join tradeSwapDetailSonTemp1 in yldb.trade_swap_detail on tradeSwap.TradeId equals tradeSwapDetailSonTemp1.ChildTradeId into tradeSwapDetailSonTemp
from tradeSwapDetailSon in tradeSwapDetailSonTemp.DefaultIfEmpty()
where tradeSwapDetailSon == null
select new { trade, tradeSwap, tradeSwapDetail };
if (req.SwapType != null)
{
query = query.Where(t => t.tradeSwap.SwapType.Equals(req.SwapType));
}
if (req.SwapType != null)
{
query = query.Where(t => t.tradeSwap.SwapType.Equals(req.SwapType));
}
var tradeSwapList = query.AsEnumerable().GroupBy(t => new { t.trade.id }).Select(t => new TradeSwapMarginMonitorModel
{
TradeId = t.FirstOrDefault().trade.id,
TradeNumber = t.FirstOrDefault().trade.TradeNumber,
TradeDate = t.FirstOrDefault().trade.TradeDate,
ClientId = t.FirstOrDefault().trade.ClientId,
ClientName = t.FirstOrDefault().trade.ClientName,
AssetId = t.FirstOrDefault().trade.AssetId,
AssetBookName = t.FirstOrDefault().trade.AssetBookName,
SwapType = t.FirstOrDefault().tradeSwap.SwapType,
LongShort = t.FirstOrDefault().tradeSwap.SwapType.Equals(SwapTypeEnum.多空组合.ToString()) ? null : t.FirstOrDefault().tradeSwap.PayLongShort,
StockEqvNotional = t.FirstOrDefault().trade.OriginalStockEqvNotional ?? 0,
tradeAmount = t.FirstOrDefault().trade.OriginalNotional ?? 0,
PositionNotional = t.FirstOrDefault().trade.StockEqvNotional,
PositionAmount = t.FirstOrDefault().trade.Notional,
UnderlyingCode = t.FirstOrDefault().trade.UnderlyingCode,
SpotPrice = t.FirstOrDefault().tradeSwap.PaySpotPrice ?? 0.0,
//Price
InitMarginRate = t.FirstOrDefault().tradeSwap.GetMarginRate ?? 0.0,
InitMargin = (t.FirstOrDefault().tradeSwap.GetMarginRate ?? 0.0) * t.FirstOrDefault().trade.StockEqvNotional,
//PostionProfitLoss
//PositionValue
//PositionMarginRate
//PositionMargin
//CreditOccupy
//Margin
Trade = t.FirstOrDefault().trade,
TradeSwap = t.FirstOrDefault().tradeSwap,
TradeSwapDetails = t.Where(a => a.tradeSwapDetail != null).Select(a => a.tradeSwapDetail).ToList()
}).OrderByDescending(t => new { t.TradeId }).ToList();
#region 交易层面授信暂不计算
////所有客户id列表
//var clientIds = tradeSwapList.Select(t => t.ClientId).Distinct().ToList();
////获取客户所有互换授信信息
//var creditList = yldb.credit.Where(t =>
// clientIds.Contains(t.ClientId ?? 0) && t.ProcessStatus == "已审批" &&
// (!t.CreditDeadLine.HasValue || t.CreditDeadLine >= valueDate) && (!t.CreditStartDate.HasValue || t.CreditStartDate <= valueDate) && (t.DerivativesInvestmentVarieties == null || t.DerivativesInvestmentVarieties.Contains(DerivativesInvestmentVarietiesEnum.场外互换.ToString()))).ToList();
#endregion
//所有客户id列表
var clientIds = tradeSwapList.Select(t => t.ClientId).Distinct().ToList();
//增加clientId=0,默认为全部
clientIds.Add(0);
//获取客户互换预付金预警设置
var marginRateList = yldb.client_marginrate.Where(t => clientIds.Contains(t.ClientId) && t.ValueDate <= valueDate).ToList();
TradeValueResult valueResult;
tradeSwapList.ForEach(t =>
{
//计算利息收入 利息 增强收益
var swapStartDate = (t.Trade.StartDate ?? t.Trade.TradeDate).Value.AddDays(t.TradeSwap.IncludeFirstDay ? -1 : 0);
t.InterestIncome = PayoffSwapCalcService.GetExtraAmountBySwapRate(t.Trade.ClientId, t.Trade.TradeDate, t.TradeSwap.GetSwapTimeAndRate, swapStartDate, valuedateBLL.ValueDate, t.TradeSwap.AnnualDays ?? 0, t.PositionNotional)
- PayoffSwapCalcService.GetExtraAmountBySwapRate(t.Trade.ClientId, t.Trade.TradeDate, t.TradeSwap.PaySwapTimeAndRate, swapStartDate, valuedateBLL.ValueDate, t.TradeSwap.AnnualDays ?? 0, t.PositionNotional);
//手续费
t.Commission = ((t.TradeSwap.GetTradePrice ?? 0) - (t.TradeSwap.PayTradePrice ?? 0)) * (t.Trade.OriginalStockEqvNotional == null ? 1.0 : (t.PositionNotional / t.Trade.OriginalStockEqvNotional.Value));
//预付金率 取Get Pay双向
t.InitMarginRate = (t.TradeSwap.GetMarginRate ?? 0.0) - (t.TradeSwap.PayMarginRate ?? 0);
t.InitMargin = t.InitMarginRate * t.PositionNotional;
t.SpotPrice = t.TradeSwap.IsGetFloatingProfit ? (t.TradeSwap.GetSpotPrice ?? 0.0) : (t.TradeSwap.IsPayFloatingProfit ? (t.TradeSwap.PaySpotPrice ?? 0.0) : 0.0);
if (SwapTypeEnum.多空组合.ToString().Equals(t.SwapType))
{
//浮动收益年化利率
var annualRate = PayoffSwapCalcService.GetAnnualVarIncomeRate(t.TradeSwap, valueDate, null, t.Trade.StartDate.Value, t.Trade.ExerciseDate.Value)??1.0;
var longNotional = 0.0;
var shotNotional = 0.0;
t.FloatingProfitTypeStr = "--";
if (t.TradeSwapDetails != null && t.TradeSwapDetails.Count > 0)
{
t.TradeSwapDetailList = t.TradeSwapDetails.Select(d => new TradeSwapDetailExtend(d)).ToList();
t.TradeSwapDetailList.ForEach(a =>
{
if (a.LongShort == "多头")
{
longNotional += (a.Notional ?? 0.0) * (a.SpotPrice ?? 0.0);
}
else if (a.LongShort == "空头")
{
shotNotional += (a.Notional ?? 0.0) * (a.SpotPrice ?? 0.0);
}
a.price = DataCacheProvider.GetUnderlyingDataSource().GetPrice(a.UnderlyingCode);
a.pv = t.InterestIncome * ((a.Notional ?? 0.0) * (a.SpotPrice ?? 0.0) / t.PositionNotional) + annualRate * (a.price - (a.SpotPrice ?? 0.0)) * (a.Notional ?? 0.0) * ("空头".Equals(a.LongShort) ? -1.0 : 1.0) * (a.IsForGet ? 1 : -1) + (t.TradeSwap.IsTradePriceWhenOpen ? 0 : ((a.TradePrice ?? 0.0) * (a.IsForGet ? -1 : 1)));
a.profitLoss = a.pv + (t.TradeSwap.IsTradePriceWhenOpen ? ((a.TradePrice ?? 0.0) * (a.IsForGet ? -1 : 1)) : 0);
});
t.PositionLongNotional = longNotional;
t.PositionShortNotional = shotNotional;
}
else
{
t.TradeSwapDetailList = new List<TradeSwapDetailExtend>();
}
t.InitMargin = t.InitMarginRate * Math.Max(longNotional, shotNotional);
t.LongShort = string.Format("多头({0}),空头({1})", t.TradeSwapDetailList.Where(a => "多头".Equals(a.LongShort)).Count(), t.TradeSwapDetailList.Where(a => "空头".Equals(a.LongShort)).Count());
t.PositionValue = t.TradeSwapDetailList.Sum(a => a.pv);
t.PostionProfitLoss = t.TradeSwapDetailList.Sum(a => a.profitLoss);
t.PositionMargin = t.InitMargin - t.PositionValue;
t.PositionMarginRate = t.PositionMargin / Math.Max(longNotional, shotNotional);
t.Margin = Math.Max(t.InitMargin - t.PositionMargin, 0);
t.waringLine = t.PositionMarginRate;
t.closepPositionLine = 0.0;
var marginRate1 = marginRateList.Where(a => a.Type.Equals("多空组合") && a.ClientId == t.ClientId).OrderByDescending(a => a.ClientId).ThenByDescending(a => a.ValueDate).FirstOrDefault();
if (marginRateList.Any(a => a.Type.Equals("多空组合") && (a.ClientId == t.ClientId || a.ClientId == 0)))
{
var marginRate = marginRateList.Where(a => a.Type.Equals("多空组合") && (a.ClientId == t.ClientId || a.ClientId == 0)).OrderByDescending(a => a.ClientId).ThenByDescending(a => a.ValueDate).FirstOrDefault();
t.waringLine = marginRate.WarningLine;
t.closepPositionLine = marginRate.ClosePositionLine;
}
}
else
{
t.LongShort = t.TradeSwap.IsGetFloatingProfit ? t.TradeSwap.GetLongShort : (t.TradeSwap.IsPayFloatingProfit ? t.TradeSwap.PayLongShort : "");
t.PositionLongNotional = t.LongShort == "多头" ? t.PositionNotional : 0.0;
t.PositionShortNotional = t.LongShort == "空头" ? t.PositionNotional : 0.0;
valueResult = PayoffSwapCalcService.CalcValue(t.Trade, valueDate, null, false);
t.FloatingProfitTypeStr = t.TradeSwap.IsGetFloatingProfit ? "收取" : "支付";
t.Price = DataCacheProvider.GetUnderlyingDataSource().GetPrice(t.UnderlyingCode);
t.PositionValue = valueResult.Pv;
//t.Commission = valueResult.ExtendInfo.Commission;
//开仓支付手续费是盈亏计算手续费
t.PostionProfitLoss = valueResult.Pv + (t.TradeSwap.IsTradePriceWhenOpen ? (t.Commission) : 0);
t.PositionMargin = t.InitMargin - t.PositionValue;
t.PositionMarginRate = t.PositionNotional == 0 ? 0 : t.PositionMargin / t.PositionNotional;
t.Margin = Math.Max(t.InitMargin - t.PositionMargin, 0);
t.waringLine = t.PositionMarginRate;
t.closepPositionLine = 0.0;
var variety = DataCacheProvider.GetVariety(t.UnderlyingCode);
if (variety != null)
{
if (marginRateList.Any(a => a.Type.Equals("品种") && (a.ClientId == t.ClientId || a.ClientId == 0) && a.VarietyId == variety.id))
{
var marginRate = marginRateList.Where(a => a.Type.Equals("品种") && (a.ClientId == t.ClientId || a.ClientId == 0) && a.VarietyId == variety.id).OrderByDescending(a=>a.ClientId).ThenByDescending(a => a.ValueDate).FirstOrDefault();
t.waringLine = marginRate.WarningLine;
t.closepPositionLine = marginRate.ClosePositionLine;
}
}
}
if (t.PositionMarginRate <= t.closepPositionLine)
{
t.WaringStatus = "达到平仓线";
}
else if (t.PositionMarginRate <= t.waringLine)
{
t.WaringStatus = "达到预警线";
}
else
{
t.Margin = 0.0;//不到预警线不追保
t.WaringStatus = "无预警";
}
});
List<string> underlyingCodes = null;
if (req.VarietyIds != null && req.VarietyIds.Count() > 0)
{
underlyingCodes = (from underlying in yldb.underlying_manager where req.VarietyIds.Contains(underlying.UnderlyingTypeId) select underlying.UnderlyingCode).ToList();
}
if (req.UnderlyingIds != null && req.UnderlyingIds.Count() > 0)
{
underlyingCodes = (from underlying in yldb.underlying_manager where req.UnderlyingIds.Contains(underlying.id) select underlying.UnderlyingCode).ToList();
}
if (underlyingCodes != null && underlyingCodes.Count() > 0)
{
tradeSwapList = tradeSwapList.Where(t => underlyingCodes.Contains(t.Trade.UnderlyingCode) || t.TradeSwapDetails.Any(a => underlyingCodes.Contains(a.UnderlyingCode))).ToList();
}
if (req.WarnningTypes != null && req.WarnningTypes.Count() > 0 && tradeSwapList.Count() > 0)
{
tradeSwapList = tradeSwapList.Where(t => req.WarnningTypes.Contains(t.WaringStatus)).ToList();
}
return tradeSwapList;
}
public ActionResult execlExport(MarginRateSwapMonitorReq req)
{
var sourceFileName = Path.Combine(OtcAppContext.MapPath("~/App_Docs/导出模板/"), "收益互换预付金监控.xlsx");
var list = monitorQuery(req);
var modleDict = new Dictionary<string, object>
{
["Sheet1"] = new
{
InfoList = list.Select(t => new
{
t.TradeNumber,
t.ClientName,
t.AssetBookName,
t.SwapType,
t.LongShort,
TradeDate = t.TradeDate == null ? "" : (t.TradeDate.Value.ToString("yyyy-MM-dd")),
t.StockEqvNotional,
t.tradeAmount,
t.PositionNotional,
t.PositionAmount,
t.UnderlyingCode,
t.SpotPrice,
t.Price,
t.InitMarginRate,
t.PostionProfitLoss,
t.PositionValue,
t.InitMargin,
t.PositionMargin,
t.PositionMarginRate,
t.Margin
}).ToList()
}
};
var result = OtcAppContext.GetExportFileOutputPath($"收益互换预付金监控_{DateTime.Now:yyyyMMddHHmmss}.xlsx");
new ExcelTemplateGenerator().SetTemplateFile(sourceFileName).SetTemplateData(modleDict).OutputToFile(result.PhysicalPath);
return JsonSuccess("收益互换预付金监控成功", result.WebPath);
}
#region 新版互换预付金监控预警
/// <summary>
/// 新版互换预付金监控预警
/// </summary>
/// <returns></returns>
public ActionResult MarginRateSwapMonitorV2()
{
ViewBag.valueDate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd");
var swapMonitorConfgValue = AppManager.GetSwapMonitorValue();
SwapMonitorConfig monitorConfig=new SwapMonitorConfig();
if (!string.IsNullOrEmpty(swapMonitorConfgValue))
{
monitorConfig = JsonHelper.Deserialize<SwapMonitorConfig>(swapMonitorConfgValue);
}
ViewBag.swapMonitorConfg = monitorConfig;
return View();
}
/// <summary>
/// 设置预警线
/// </summary>
/// <param name="swapMonitorConfig"></param>
/// <returns></returns>
[HttpPost]
public JsonResult SetSwapMonitor(SwapMonitorConfig swapMonitorConfig)
{
AppManager.SetSwapMonitorValue(JsonHelper.Serialize(swapMonitorConfig));
return JsonSuccess();
}
/// <summary>
/// 互换预付金监控查询
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public JsonResult MarginRateSwapMonitorQueryV2(SwapMarginMonitorRequest req)
{
var valueDate = valuedateBLL.ValueDate;
var clientPredicate = PredicateBuilder.Create<Client>(x=>x.ProcessStatus=="已开户");
if (req.ClientIds.Any())
{
clientPredicate = clientPredicate.And(d => req.ClientIds.Contains(d.id));
}
if (req.SwapTypes.Any())
{
clientPredicate = clientPredicate.And(d => req.SwapTypes.Contains(d.SwapTradeType??0));
}
var swapMonitorConfgValue = AppManager.GetSwapMonitorValue();
SwapMonitorConfig monitorConfig = new SwapMonitorConfig();
if (!string.IsNullOrEmpty(swapMonitorConfgValue))
{
monitorConfig = JsonHelper.Deserialize<SwapMonitorConfig>(swapMonitorConfgValue);
}
var clientquery = DataCacheProvider.GetClientDataSource().AsQueryable(clientPredicate);
var clientIds= clientquery.Select(s => s.id).ToList();
var reqSort = req.sidx;
var reqSord = req.sord;
var balanceList= ClientBalanceUtility.GetClientBanlances(clientIds, DateTime.MinValue, valueDate);
SearchListResult<ClientSettleBalance> searchList = new SearchListResult<ClientSettleBalance>();
if (req.WarnningTypes.Any())
{
if (req.WarnningTypes.Contains("达到平仓线"))
{
balanceList = balanceList.Where(x => x.MaintenanceLine <= monitorConfig.UnwindLine * 0.01);
}
else if (req.WarnningTypes.Contains("达到预警线"))
{
balanceList = balanceList.Where(x => x.MaintenanceLine <= monitorConfig.WarningLine * 0.01&& x.MaintenanceLine > monitorConfig.UnwindLine * 0.01);
}
else if (req.WarnningTypes.Contains("无预警"))
{
balanceList = balanceList.Where(x => x.MaintenanceLine > monitorConfig.WarningLine * 0.01);
}
}
req.sord = reqSord;
req.sidx=string.IsNullOrEmpty(reqSort)? "ClientNumber" : reqSort;
searchList = balanceList.AsQueryable().ToSearchList(req);
return Json(searchList);
}
/// <summary>
/// 互换预付金监控导出
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public object ExportMarginRateSwapMonitor(SwapMarginMonitorRequest req)
{
req.page = 1;
req.rows = 10000;
var list = MarginRateSwapMonitorQueryV2(req).Value as SearchListResult<ClientSettleBalance>;
var tplFilePath = OtcAppContext.MapPath("/App_Docs");
var sourceFileName = Path.Combine(tplFilePath, "导出模板", "互换预付金监控导出模板.xlsx");
var modelDict = new Dictionary<string, object>();
var model = new { list = list.rows };
modelDict.Add("Sheet1", model);
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
var bytes= new ExcelTemplateGenerator().SetTemplateFile(sourceFileName).SetTemplateData(modelDict).Output();
return File(bytes, xlsxMimeType, $"互换预付金监控导出{DateTime.Now:yyyyMMddHHmmss}.xlsx");
}
#endregion
}
}