如何在C#应用程序中获得Excel YearFrac function的相同结果?
计算两个日期(start_date和end_date)之间的整天数表示的年份分数。使用YEARFRAC工作表函数来确定一年的利益或分配给特定条款的义务的比例。
答案 0 :(得分:2)
这是一个很好的snippet。
YearFrac功能的算法实际上非常复杂。也许this article可以为您提供更多详细信息。
答案 1 :(得分:1)
您可以直接使用Excel的功能来计算YearFrac
。微软称you are not supposed to use it,但效果很好。如果您需要与Excel 100%兼容,这个解决方案很难被击败。您需要在项目中添加对Microsoft.Office.Interop.Excel
的引用,以便编译此代码。
static void Main() {
var excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.WorksheetFunction wsf = excel.WorksheetFunction;
var start = new DateTime(1999, 11, 1);
var end = new DateTime(1999, 1, 11);
for (var basis = 0; basis != 5; basis++) {
Console.WriteLine(wsf.YearFrac(start, end, basis));
}
}
答案 2 :(得分:0)
YEARFRAC的签名是YEARFRAC(Date startDate,Date endDate,int convention)。计算YEARFRAC的方法取决于惯例。
对于约定= 2,YEARFRAC将使用ACT / 360方法计算YEARFRAC。可以在svn.finmath.net找到ACT / 360的实施,具体为DayCountConvention_ACT_360.java
对于约定= 3,YEARFRAC将使用ACT / 365方法计算YEARFRAC。可以在svn.finmath.net专门找到ACT / 365的实现 DayCountConvention_ACT_365.java
对于约定= 4,YEARFRAC将使用30E / 360方法计算YEARFRAC。可以在svn.finmath.net找到30E / 360的实现,特别是DayCountConvention_30E_360.java
对于惯例= 1,文件声称YEARFRAC是使用ACT / ACT惯例计算的。但是,有多个版本的ACT / ACT,我相信许多金融产品的标准是ACT / ACT ISDA。我发现YEARFRAC与ACT / ACT IDSA大会相差不多!可在DayCountConvention_ACT_ACT_ISDA.java
找到ACT / ACT IDSA的实施我还没有检查过其他行为/动作版本,但我不会依赖YEARFRAC ACT / ACT的仿真,当时不清楚他们实施的是什么样的方法......
答案 3 :(得分:0)
我可以建议:
public static double Yearfrac(DateTime startDate,DateTime endDate,DayCount daycount=DayCount.ActAct)
{
var nbDaysInPeriod = (double)(endDate - startDate).Days;
switch(daycount)
{
case (DayCount.Act360):
return nbDaysInPeriod / (double)360;
case (DayCount.Act365):
return nbDaysInPeriod / (double)365;
case (DayCount.ActAct):
return GetActAct(startDate,endDate);
case (DayCount.Days360):
var result = (endDate.Year - startDate.Year) * 360.0 + (endDate.Month - startDate.Month) * 30.0 + (Math.Min(endDate.Day, 30.0) - Math.Min(startDate.Day, 30.0));
return result/360;
default:
return nbDaysInPeriod / (double)365;
}
}
public static double GetActAct(DateTime startDate, DateTime endDate)
{
// Reproduce Excel Yearfrac as per http://www.dwheeler.com/yearfrac/excel-ooxml-yearfrac.pdf
var nbDaysInPeriod = (double)(endDate - startDate).Days;
if(startDate.Year==endDate.Year || (endDate.Year-1==startDate.Year&&(startDate.Month>endDate.Month||startDate.Month==endDate.Month&&(startDate.Day>=endDate.Day))))
{
var den = 365.0;
if (startDate.Year == endDate.Year && DateTime.IsLeapYear(startDate.Year))
{
den++;
}
else
{
if (endDate.Day == 29 && endDate.Month == 2)
{
den++;
}
else
{
if (DateTime.IsLeapYear(startDate.Year))
{
var feb = new DateTime(startDate.Year, 2, 29);
if (startDate<=feb && feb<=endDate) den++;
}
else
{
if (DateTime.IsLeapYear(endDate.Year))
{
var feb = new DateTime(endDate.Year, 2, 29);
if (startDate <= feb && feb <= endDate) den++;
}
}
}
}
}
else
{
var nbYears = endDate.Year - startDate.Year+1;
var den = nbYears * 365.0;
for (var i=0;i<nbYears;i++)
{
if (DateTime.IsLeapYear(startDate.Year + i)) den++;
}
den /= nbYears;
return nbDaysInPeriod / den;
}
return nbDaysInPeriod / 365.0;
}