Files
zszq-trs/YLErpDAL/Helpers/Dv01Helper.cs
T
hjhan 818619bc70 补充DV01计算工具的注释:明确输出单位为万元及入参单位
Dv01Helper.CalcDv01 与业界标准一致,但输出单位是万元而非元,且
PosiQuantity须为元面值单位。原注释未说明这些口径,易导致误读。
补充:
- 类注释:写明公式等价业界标准DV01(元)/10000,输出万元
- posiQuantity入参:标注须为元面值单位
- vobp入参:标注为每100元面值1bp的价格变动
- 返回值:标注单位为万元
- 券面总额计算行:标注交易数量单位为元面值

仅注释改动,不改逻辑。
2026-06-25 19:15:27 +08:00

55 lines
2.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using YLErp.DBModels;
using YLErp.DBModels.Enums;
using YLErp.Modules;
namespace YLErp.Helpers
{
/// <summary>
/// DV01计算工具类
/// 公式: DV01(万元) = 方向 * (持仓面值(万元) / 单位面值) * 中债基点价值
/// 等价业界标准: DV01(元) = 持仓面值(元) / 100 * vobp,本方法输出为该值的 1/10000(即万元)。
/// 注意: PosiQuantity 入参须为"元面值"单位(由 PosiNotionalValue/PosiGrossPrice 反推);
/// 单位面值默认 100,取自 UnderlyingBond.Pricevobp 为"每100元面值1bp的价格变动"。
/// </summary>
public static class Dv01Helper
{
/// <summary>
/// 计算DV01
/// </summary>
/// <param name="underlyingCode">标的代码</param>
/// <param name="posiQuantity">持仓数量,须为"元面值"单位(如1000000=100万元面值)</param>
/// <param name="posiDirection">收支方向: 1=收取, 2=支付</param>
/// <param name="positionType">多空方向: 1=多头, 2=空头</param>
/// <param name="vobp">中债基点价值(每100元面值,收益率变动1bp的价格变动)</param>
/// <returns>DV01值,单位为"万元"</returns>
public static decimal CalcDv01(string underlyingCode, decimal posiQuantity, int posiDirection, int positionType, decimal vobp)
{
if (vobp == 0 || posiQuantity == 0) return 0;
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
if (um == null || !um.IsBond()) return 0;
// 方向: 支付多头=-1, 收取多头=1, 支付空头=1, 收取空头=-1
// = (PosiDirection==收取?1:-1) * (PositionType==多头?1:-1)
int direction = (posiDirection == (int)SwapDirectionEnum.收取 ? 1 : -1)
* (positionType == (int)PositionTypeFlag.Long ? 1 : -1);
// 券面总额(万元) = 交易数量(元面值) / 10000
double faceValueWan = Convert.ToDouble(posiQuantity) / 10000d;
// 单位面值, 默认100
decimal unitFaceValue = 100m;
if (!string.IsNullOrEmpty(um.ExJson))
{
var bond = JsonHelper.Deserialize<UnderlyingBond>(um.ExJson);
if (bond?.Price != null && bond.Price != 0)
unitFaceValue = bond.Price.Value;
}
decimal result = Convert.ToDecimal(direction * (faceValueWan / Convert.ToDouble(unitFaceValue)) * Convert.ToDouble(vobp));
return Math.Round(result, 4);
}
}
}