none
Erro en cálculo de IRR RRS feed

  • Pregunta

  • Buenas tardes, 

    tenemos una función para calcular la TIR de un cashflow que nos funciona correctamente desde hace mucho tiempo y para una casuística muy amplia, pero hoy hemos encontrado un caso donde nos arroja un error de:

    "System.ArgumentException. Los argumentos no son válidos en Microsoft.VivualBasic.Financial.IRR...."

    A nuestra función le pasamos dos arrays de 533 posiciones, y cuando hacemos un cambio en una de las posiciones, concrétamente en la nº 348, nos devuelve el error, si en esa posición tenemos como valor 11564290,56 funciona y nos da un aTIR de -21,57, en cambio si el valor para la posición 348 lo cambiamos a -16545690 es cuando nos devuelve el error.

    Por favor, Alguien sabe qué está ocurriendo y cómo podemos solucionarlo ??, muchas gracias.

    Os paso la tabla que da una tir de -21,67, si en esta tabla cambiamos el valor de Array(348) a -16545690 es cuando tenemos el error, todos los elementos cuyo índice no aparecen es porque tienen valor 0, y el contenido de este post no me permite poner un mensaje tan largo

    Array (0) -> -1201337,01
    Array (50) -> -487994,11
    Array (75) -> -279780,82
    Array (96) -> -7723369,86
    Array (104) -> -4092900
    Array (152) -> -81000,97
    Array (168) -> -271210,96
    Array (182) -> 126403,29
    Array (198) -> -504000
    Array (229) -> -2395833,33
    Array (246) -> -3270025,79
    Array (247) -> -1862606
    Array (261) -> -265315,07
    Array (264) -> -35275,61
    Array (275) -> -3426041,65
    Array (276) -> -396188,49
    Array (287) -> 167838,8
    Array (303) -> -5806608,01
    Array (317) -> -4176000
    Array (336) -> -1049374
    Array (345) -> -3068263,01
    Array (348) -> 11564290,56
    Array (372) -> 244380,84
    Array (373) -> 244380,84
    Array (392) -> 7979,14
    Array (436) -> 1071210,96
    Array (453) -> 151090,66
    Array (461) -> 3321428,57
    Array (476) -> 1910367,02
    Array (482) -> 880000
    Array (524) -> 608737,64
    Array (530) -> 5224312,04
    Array (532) -> 9095601,28

    lunes, 1 de febrero de 2016 15:19

Respuestas

  • "JJDop" escribió:

    > ... no entiendo del todo la respuesta, estoy convencido de que la secuencia de valores
    > dentro del cashflow es la correcta, pero lo que no acabo de entender es por qué está
    > limitado el valor que podemos utilizar en ese elemento del array ...

    Lo ignoro por completo. Mi respuesta está basada en la sección Comentarios que aparece en la ayuda del método Financial.IRR:

    [...]
    Comentarios

    La tasa interna de retorno es el tipo de interés recibido por una inversión consistente en pagos y cobros que se producen a intervalos regulares.

    La función IRR utiliza el orden de los valores de la matriz para interpretar el orden de los pagos y cobros. Asegúrese de indicar los valores de los pagos y cobros siguiendo la secuencia correcta. No es necesario que el flujo de caja en cada período sea fijo, como sería en el caso de una anualidad.

    IRR se calcula por iteración. Comenzando con el valor de Guess, IRR, realiza un cálculo cíclico hasta que el resultado tiene una precisión del 0,00001 por ciento. Si IRR no puede encontrar un resultado después de 20 intentos, se produce un error.
    [...]

    > ... o al menos cómo podemos evitar que salga ese error

    Para evitar el error tendrías que especificar una secuencia correcta de valores. ¿Cuáles? Pues sinceramente no lo sé. Y para atrapar el error, lo harías como atraparías cualquier otro tipo de error diferente, encerrando el código de llamada entre un bloque Try ... Catch ... End Try:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                tirAnual = (1 + (Math.Round(IRR(cashFlow, guess) * 100, 8) / 100)) ^ 365 - 1
    
            Catch ex As ArgumentException
                ' Lo más seguro es que la ArgumentException la haya producido el método IRR.
                '
                ' Ejecutar aquí el código que proceda.
                '
                ' ...
    
            Catch ex As Exception
                ' Se ha producido otro Exception diferente a una ArgumentException.
                '
                ' Ejecutar aquí el código que proceda.
                '
                ' ...
    
            End Try
    
        End Sub

    > Como comentaba anteriormente, utilizando en Excel esos datos si funciona
    > la TIR, pero hay que darle un valor -0.1 al guess

    Entonces es diferente a la función Financial.IRR del espacio de nombres Microsof.VisualBasic, porque en ésta última, si se omite el parámetro Guess, por defecto tomará el valor 0,1 (10 por ciento), y si es menor o igual a -1, se generará una ArgumentException.

    Insisto en que la prueba que he realizado, y según los valores que has facilitado, el valor mínimo que puedo establecer es el -3993257; cualquier otro inferior a él obtengo la ArgumentException.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.




    lunes, 1 de febrero de 2016 20:07
    Moderador

Todas las respuestas

  • "JJDop" preguntó:

    > tenemos una función para calcular la TIR de un cashflow que nos funciona correctamente
    > desde hace mucho tiempo y para una casuística muy amplia, pero hoy hemos encontrado un
    > caso donde nos arroja un error de:
    >
    > "System.ArgumentException. Los argumentos no son válidos en Microsoft.VivualBasic.Financial.IRR...."
    >

    Hola:

    Según el contenido de la ayuda del método Financial.IRR, éste devolverá una excepción del tipo ArgumentException si los valores Double de los argumentos de la matriz no son válidos, el valor especificado para el segundo parámetro (Guess) es menor o igual a -1, o si después de 20 intentos la función IRR no puede encontrar un resultado.

    Asimismo se indica que «la función IRR utiliza el orden de los valores de la matriz para interpretar el orden de los pagos y cobros. Asegúrese de indicar los valores de los pagos y cobros siguiendo la secuencia correcta

    ¿Has verificado que los valores (tanto del Array como del valor Guess) que le pasas al método IRR, cumplen los requisitos que se indican en la ayuda?

    Financial.IRR (Método)

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    lunes, 1 de febrero de 2016 15:54
    Moderador
  • Hola Enrique.

    Gracias por tu respuesta.

    Si, el valor de Guess es 0, pero también he probado con -0.1 ya que al hacer el cálculo en Excel y cambiando el valor de guess a -0.1 funciona. Respecto a lo de los 20 intentos, no sé cómo controlarlo, aunque es extraño dado que solo con cambiar el valor de la posición 348 ya arroja el error.

    La formula final que utilizamos es:

    tirAnual = (1 + (Math.Round(IRR(cashFlow, guess) * 100, 8) / 100)) ^ 365 - 1


    lunes, 1 de febrero de 2016 16:08
  • "JJDop" escribió:

    > La formula final que utilizamos es:
    >
    > tirAnual = (1 + (Math.Round(IRR(cashFlow, guess) * 100, 8) / 100)) ^ 365 - 1

    Por la descripción del mensaje de error que has publicado, entiendo que el mismo lo desencadena la función IRR.

    > Respecto a lo de los 20 intentos, no sé cómo controlarlo, aunque es extraño
    > dado que solo con cambiar el valor de la posición 348 ya arroja el error.

    Eso no se puede controlar porque es un procedimiento interno que hace la propia función con los valores de la matriz proporcionada, y me da que pensar que error lo recibes porque el valor no está en la secuencia correcta, de hecho, acabo de realizar una prueba con los valores que has indicado, y el valor mínimo que puedo establecer es el siguiente:

     
       cashFlow(348) = -3993257D ' --> Valor Double

    Si especifico el valor -3993258D ya obtengo la ArgumentException.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    lunes, 1 de febrero de 2016 17:18
    Moderador
  • Perdona  Enrique, pero no entiendo del todo la respuesta, estoy convencido de que la secuencia de valores dentro del cashflow es la correcta, pero lo que no acabo de entender es por qué está limitado el valor que podemos utilizar en ese elemento del array o al menos cómo podemos evitar que salga ese error. Como comentaba anteriormente, utilizando en Excel esos datos si funciona la TIR, pero hay que darle un valor -0.1 al guess

    Por favor, nos puedes indicar cómo resolverlo? es muy importante

    Gracias de nuevo

    lunes, 1 de febrero de 2016 18:11
  • "JJDop" escribió:

    > ... no entiendo del todo la respuesta, estoy convencido de que la secuencia de valores
    > dentro del cashflow es la correcta, pero lo que no acabo de entender es por qué está
    > limitado el valor que podemos utilizar en ese elemento del array ...

    Lo ignoro por completo. Mi respuesta está basada en la sección Comentarios que aparece en la ayuda del método Financial.IRR:

    [...]
    Comentarios

    La tasa interna de retorno es el tipo de interés recibido por una inversión consistente en pagos y cobros que se producen a intervalos regulares.

    La función IRR utiliza el orden de los valores de la matriz para interpretar el orden de los pagos y cobros. Asegúrese de indicar los valores de los pagos y cobros siguiendo la secuencia correcta. No es necesario que el flujo de caja en cada período sea fijo, como sería en el caso de una anualidad.

    IRR se calcula por iteración. Comenzando con el valor de Guess, IRR, realiza un cálculo cíclico hasta que el resultado tiene una precisión del 0,00001 por ciento. Si IRR no puede encontrar un resultado después de 20 intentos, se produce un error.
    [...]

    > ... o al menos cómo podemos evitar que salga ese error

    Para evitar el error tendrías que especificar una secuencia correcta de valores. ¿Cuáles? Pues sinceramente no lo sé. Y para atrapar el error, lo harías como atraparías cualquier otro tipo de error diferente, encerrando el código de llamada entre un bloque Try ... Catch ... End Try:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                tirAnual = (1 + (Math.Round(IRR(cashFlow, guess) * 100, 8) / 100)) ^ 365 - 1
    
            Catch ex As ArgumentException
                ' Lo más seguro es que la ArgumentException la haya producido el método IRR.
                '
                ' Ejecutar aquí el código que proceda.
                '
                ' ...
    
            Catch ex As Exception
                ' Se ha producido otro Exception diferente a una ArgumentException.
                '
                ' Ejecutar aquí el código que proceda.
                '
                ' ...
    
            End Try
    
        End Sub

    > Como comentaba anteriormente, utilizando en Excel esos datos si funciona
    > la TIR, pero hay que darle un valor -0.1 al guess

    Entonces es diferente a la función Financial.IRR del espacio de nombres Microsof.VisualBasic, porque en ésta última, si se omite el parámetro Guess, por defecto tomará el valor 0,1 (10 por ciento), y si es menor o igual a -1, se generará una ArgumentException.

    Insisto en que la prueba que he realizado, y según los valores que has facilitado, el valor mínimo que puedo establecer es el -3993257; cualquier otro inferior a él obtengo la ArgumentException.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.




    lunes, 1 de febrero de 2016 20:07
    Moderador