douren8379 2013-05-29 09:07
浏览 38
已采纳

PHP修改了Dietz返回函数给出了错误的结果

I wrote my own modified dietz return function to calculate the return on a portfolio with external cash movements. It seems to work correctly when compared to an excel solution but I have come accross a case where the result is wrong. My function returns 0.23% when the correct result is 0.30%.

Here is the function:

//Calculates the Modified-Dietz return given arrays of MIMO.
//MIMO is an associative array of dates to values
function modDietz($startDate, $endDate, $BMV, $EMV, $MIMO){
    if( strtotime($startDate) !== false ){
    //Date was passed as a string; convert it to php date
    $startDate = strtotime($startDate);
    }
    if( strtotime($endDate) !== false ){
    //Date was passed as a string; convert it to php date
    $endDate = strtotime($endDate);
    }

    //Convert seconds to days
    $CD = ($startDate - $endDate)/(60*60*24); 

    $i = 0;
    $SumWiFi = 0;
    $F = 0;
    foreach ($MIMO as $date=>$Fi){
        if( strtotime($date) !== false ){
          //Date was passed as a string; convert it to php date
          $date = strtotime($date);
        }
        //Only take into account the MIMO if it falls between the start and end dates.
        if ($date >= $startDate && $date <= $endDate){
            $Di = ($date - $startDate) / (60*60*24);
            $Wi = ($CD - $Di) / $CD;
            $SumWiFi += $Wi * $Fi;
            $F += $Fi;
        }
    }
    if ($BMV + $SumWiFi != 0) {
        return ($EMV - $BMV - $F)/($BMV + $SumWiFi);
    } else {
        return 0;
    }
}

And here is the data I fed it which is giving the wrong result:

Dates:
Array
(
    [0] => 2013-04-30
    [1] => 2013-03-31
)

Values:
Array
(
    [2013-03-31] => 4990430.0
    [2013-04-30] => 5991710.1
)

MIMO:
Array
(
    [2013-04-19] => -600.0
    [2013-04-23] => 1000000.0
    [2013-04-29] => -13750
)

This is the line that produces the result:

$mdReturn = modDietz($dates[1], $dates[0], $values[$dates[1]], $values[$dates[0]], $mimo);

I have a feeling the Money-Out on the 29th might be the cause - I'm not too sure of the best way to handle the dates in this function. At the moment I just use string-to-date on strings passed as format yyyy-mm-dd as shown in the above arrays.

Any idea where I'm going wrong here?

  • 写回答

1条回答 默认 最新

  • dqyhj2014 2013-05-29 09:58
    关注

    I think Mark Baker is right, try this:

    function modDietz(DateTime $startDate, DateTime $endDate, $BMV, $EMV, $MIMO){
        $CD = $startDate->diff($endDate);
        $SumWiFi = 0;
        $F = 0;
        foreach ($MIMO as $date=>$Fi){
            $date = new DateTime($date);
            //Only take into account the MIMO if it falls between the start and end dates.
            if ($date >= $startDate && $date <= $endDate){
                $Di = $date->diff($startDate);
                $Wi = ($CD->d - $Di->d) / $CD->d;
                $SumWiFi += $Wi * $Fi;
                $F += $Fi;
            }
        }
        if ($BMV + $SumWiFi != 0) {
            return ($EMV - $BMV - $F)/($BMV + $SumWiFi);
        } else {
            return 0;
        }
    }
    $mimo = array(
        '2013-04-19' => -600.0,
        '2013-04-23' => 1000000.0,
        '2013-04-29' => -13750,
    );
    $startDate = new DateTime('2013-03-31');
    $endDate = new DateTime('2013-04-30');
    $result = modDietz($startDate, $endDate, 4990430.0, 5991710.1, $mimo);
    // 0.0029925034725645
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条