TRS-ZS-566、TRS-ZS-568 客户保证金率需求完成
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using YieldChain.Commons;
|
||||
using YLErp.Cache;
|
||||
using YLErp.Commons;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.UnderlyingModule
|
||||
{
|
||||
@@ -7,6 +14,11 @@ namespace YLErp.Modules.UnderlyingModule
|
||||
/// </summary>
|
||||
public static class UnderlyingHelper
|
||||
{
|
||||
readonly static IYLCache ylCache;
|
||||
static UnderlyingHelper()
|
||||
{
|
||||
ylCache = YLServiceLocator.ServiceProvider.GetService<IYLCache>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取组合标的品种对象
|
||||
/// </summary>
|
||||
@@ -59,6 +71,115 @@ namespace YLErp.Modules.UnderlyingModule
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据客户ID、标的代码和计算日期计算适用的保证金率
|
||||
/// </summary>
|
||||
/// <param name="clientId">客户ID</param>
|
||||
/// <param name="underlyingCode">标的代码</param>
|
||||
/// <param name="valueDate">计算日期</param>
|
||||
/// <returns>适用的保证金率配置,包含初始保证金率和维持保证金率</returns>
|
||||
public static client_margin_detail GetApplicableMarginRate(int clientId, string underlyingCode, DateTime valueDate)
|
||||
{
|
||||
if (string.IsNullOrEmpty(underlyingCode))
|
||||
return null;
|
||||
|
||||
string cacheKey = $"Otc:ClientMarginRate:{clientId}:{underlyingCode}:{valueDate:yyyyMMdd}";
|
||||
try
|
||||
{
|
||||
if (ylCache!=null)
|
||||
{
|
||||
// 1. 先查Redis
|
||||
var cacheDetail = ylCache.StringGetWithNoPrefix<client_margin_detail>(cacheKey);
|
||||
if (cacheDetail != null)
|
||||
return cacheDetail;
|
||||
}
|
||||
|
||||
|
||||
// 2. 查数据库
|
||||
string applicableTerm = GetApplicableMarginTerm(underlyingCode, valueDate);
|
||||
var marginConfig = GetClientMarginConfig(clientId, valueDate);
|
||||
if (marginConfig == null)
|
||||
return null;
|
||||
var marginDetail = GetMarginDetailByTerm(marginConfig.id, applicableTerm);
|
||||
|
||||
// 3. 放入Redis
|
||||
if (marginDetail != null&& ylCache != null)
|
||||
{
|
||||
ylCache.StringSetWithNoPrefix<client_margin_detail>(cacheKey, marginDetail,TimeSpan.FromHours(3));
|
||||
}
|
||||
|
||||
return marginDetail;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFactory.GetLogger("UnderlyingHelper").Error($"计算保证金率时发生异常: {ex.Message}", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取客户保证金配置
|
||||
/// </summary>
|
||||
/// <param name="clientId">客户ID</param>
|
||||
/// <param name="valueDate">估值日期</param>
|
||||
/// <returns>客户保证金配置</returns>
|
||||
private static client_margin_config GetClientMarginConfig(int clientId, DateTime valueDate)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var context = DbContextFactory.GetYLDbContext())
|
||||
{
|
||||
// 查找指定日期有效的客户保证金配置
|
||||
var config = context.clientMarginConfig
|
||||
.Where(c => c.client_id == clientId && c.value_date <= valueDate)
|
||||
.OrderByDescending(c => c.value_date)
|
||||
.FirstOrDefault();
|
||||
// 找不到,查找通用的那条
|
||||
if (config==null)
|
||||
{
|
||||
config = context.clientMarginConfig
|
||||
.Where(c => c.client_id == 0 && c.value_date <= valueDate)
|
||||
.OrderByDescending(c => c.value_date)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"获取客户保证金配置时发生异常: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据配置ID和期限获取保证金率详情
|
||||
/// </summary>
|
||||
/// <param name="configId">配置ID</param>
|
||||
/// <param name="bondTerm">债券期限</param>
|
||||
/// <returns>保证金率详情</returns>
|
||||
private static client_margin_detail GetMarginDetailByTerm(int configId, string bondTerm)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var context = DbContextFactory.GetYLDbContext())
|
||||
{
|
||||
var details = context.clientMarginDetail
|
||||
.Where(d => d.config_id == configId).ToList();
|
||||
var detail = details.FirstOrDefault(d => d.bond_term == bondTerm);
|
||||
if (detail==null&& !string.IsNullOrEmpty(bondTerm))
|
||||
{
|
||||
detail=details.FirstOrDefault(d => string.IsNullOrEmpty(d.bond_term));
|
||||
}
|
||||
return detail;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"获取保证金率详情时发生异常: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取篮子标的品种对象
|
||||
@@ -124,5 +245,149 @@ namespace YLErp.Modules.UnderlyingModule
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取债券的期限,计算日期一定要小于原日期
|
||||
/// </summary>
|
||||
/// <param name="calcDate">计算日期</param>
|
||||
/// <param name="sourceDate">原日期</param>
|
||||
/// <returns>返回3.12格式</returns>
|
||||
public static double? getYearTerm(DateTime? calcDate, DateTime? sourceDate)
|
||||
{
|
||||
if (!calcDate.HasValue)
|
||||
{
|
||||
return null;//不限
|
||||
}
|
||||
if (sourceDate.HasValue)
|
||||
{
|
||||
if (calcDate > sourceDate)
|
||||
{
|
||||
throw new ArgumentException("计算日期必须小于原日期", nameof(calcDate));
|
||||
}
|
||||
//计算sourceDate与calcDate年限差
|
||||
int yearDiff = sourceDate.Value.Year - calcDate.Value.Year;
|
||||
int monthDiff = sourceDate.Value.Month - calcDate.Value.Month;
|
||||
int dayDiff = sourceDate.Value.Day - calcDate.Value.Day;
|
||||
|
||||
// 如果月差为负,说明还没到整年,需要向前借一年
|
||||
if (monthDiff < 0)
|
||||
{
|
||||
yearDiff -= 1;
|
||||
monthDiff += 12;
|
||||
}
|
||||
|
||||
// 如果天数为负,说明还没到整月,需要向前借一个月
|
||||
if (dayDiff < 0)
|
||||
{
|
||||
monthDiff -= 1;
|
||||
if (monthDiff < 0)
|
||||
{
|
||||
yearDiff -= 1;
|
||||
monthDiff += 12;
|
||||
}
|
||||
}
|
||||
|
||||
double yearTerm = yearDiff + monthDiff / 12.0;
|
||||
return yearTerm;
|
||||
}
|
||||
return null;//不限
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据标的发行年限和剩余期限计算适用保证金率
|
||||
/// 规则表格:
|
||||
/// | 剩余期限(年) | 发行期限(年) | 则适用于 |
|
||||
/// |------------------|---------------|----------|
|
||||
/// | (0.00,2.00] | 不限 | 2年 |
|
||||
/// | (2.00,2.25] | <5 | 2年 |
|
||||
/// | (2.00,2.25] | >=5 | 5年 |
|
||||
/// | (2.25,5.00] | 不限 | 5年 |
|
||||
/// | (5.00,5.25] | <7 | 5年 |
|
||||
/// | (5.00,5.25] | >=7 | 10年 |
|
||||
/// | (5.25,25.00] | 不限 | 10年 |
|
||||
/// | (25.00,30.00] | 不限 | 30年 |
|
||||
/// </summary>
|
||||
/// <param name="underlyingCode">标的代码</param>
|
||||
/// <param name="valueDate">估值日期</param>
|
||||
/// <returns>适用的保证金率期限,如果不适用则返回空字符串</returns>
|
||||
public static string GetApplicableMarginTerm(string underlyingCode, DateTime valueDate)
|
||||
{
|
||||
if (string.IsNullOrEmpty(underlyingCode))
|
||||
return ConsMarginTerm.Default;
|
||||
|
||||
try
|
||||
{
|
||||
// 获取标的信息
|
||||
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
|
||||
if (underlying == null || !underlying.MaturityDate.HasValue)
|
||||
return ConsMarginTerm.Default;
|
||||
|
||||
// 计算发行年限(从上市日期到到期日期)
|
||||
var issueTermYears = getYearTerm(underlying.OpenDate, underlying.MaturityDate);
|
||||
|
||||
// 计算剩余期限(从估值日期到到期日期)
|
||||
var remainingTermYears = getYearTerm(valueDate, underlying.MaturityDate);
|
||||
|
||||
// 根据业务规则确定适用的保证金率期限
|
||||
return DetermineMarginTerm(issueTermYears, remainingTermYears);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 记录异常日志
|
||||
Console.WriteLine($"计算保证金率期限时发生异常: {ex.Message}");
|
||||
return ConsMarginTerm.Default;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据发行年限和剩余年限确定适用的保证金率期限
|
||||
/// 规则表格:
|
||||
/// | 剩余期限(年) | 发行期限(年) | 则适用于 |
|
||||
/// |------------------|---------------|----------|
|
||||
/// | (0.00,2.00] | 不限 | 2年 |
|
||||
/// | (2.00,2.25] | <5 | 2年 |
|
||||
/// | (2.00,2.25] | >=5 | 5年 |
|
||||
/// | (2.25,5.00] | 不限 | 5年 |
|
||||
/// | (5.00,5.25] | <7 | 5年 |
|
||||
/// | (5.00,5.25] | >=7 | 10年 |
|
||||
/// | (5.25,25.00] | 不限 | 10年 |
|
||||
/// | (25.00,30.00] | 不限 | 30年 |
|
||||
/// 说明:发行年限为null或0时视为“不限”
|
||||
/// </summary>
|
||||
private static string DetermineMarginTerm(double? issueYears, double? remainingYears)
|
||||
{
|
||||
// (0.00,2.00]年 不限 2年
|
||||
if (remainingYears > 0.00 && remainingYears <= 2.00)
|
||||
return ConsMarginTerm.TwoYear;
|
||||
|
||||
// (2.00,2.25] <5 2年
|
||||
if (remainingYears > 2.00 && remainingYears <= 2.25 && issueYears.HasValue && issueYears < 5)
|
||||
return ConsMarginTerm.TwoYear;
|
||||
|
||||
// (2.00,2.25] >=5 5年
|
||||
if (remainingYears > 2.00 && remainingYears <= 2.25 && issueYears.HasValue && issueYears >= 5)
|
||||
return ConsMarginTerm.FiveYear;
|
||||
|
||||
// (2.25,5.00] 不限 5年
|
||||
if (remainingYears > 2.25 && remainingYears <= 5.00)
|
||||
return ConsMarginTerm.FiveYear;
|
||||
|
||||
// (5.00,5.25] <7 5年
|
||||
if (remainingYears > 5.00 && remainingYears <= 5.25 && issueYears.HasValue && issueYears < 7)
|
||||
return ConsMarginTerm.FiveYear;
|
||||
|
||||
// (5.00,5.25] >=7 10年
|
||||
if (remainingYears > 5.00 && remainingYears <= 5.25 && issueYears.HasValue && issueYears >= 7)
|
||||
return ConsMarginTerm.TenYear;
|
||||
|
||||
// (5.25,25.00] 不限 10年
|
||||
if (remainingYears > 5.25 && remainingYears <= 25.00)
|
||||
return ConsMarginTerm.TenYear;
|
||||
|
||||
// (25.00,30.00] 不限 30年
|
||||
if (remainingYears > 25.00 && remainingYears <= 30.00)
|
||||
return ConsMarginTerm.ThirtyYear;
|
||||
|
||||
// 其他情况返回默认
|
||||
return ConsMarginTerm.Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user