java-xirr icon indicating copy to clipboard operation
java-xirr copied to clipboard

Error - Newton-Raphson failed to converge within 10000 iterations

Open thiagokuniwake opened this issue 3 years ago • 3 comments

My code test that is with error and version xirr is latest(1.2):

` @Test public void xirrTestXirrTestTest(){ Double rate = new Xirr(getMockTransactionsXirr()).xirr();

    System.out.println(rate);
}

private List<Transaction> getMockTransactionsXirr() {
    List<Transaction> listTransaction = new ArrayList<>();

    var listMain = Arrays.asList(getMockAnticipations().split("\n"));

    Map<String, Long> mapTransactions = new HashMap<>();

    for (String line : listMain) {
        var listA = Arrays.asList(line.split(";"));

        if (mapTransactions.containsKey(listA.get(1))) {
            var value = mapTransactions.get(listA.get(1));
            value += Long.valueOf(listA.get(0));

            mapTransactions.put(listA.get(1), value);
        } else {
            mapTransactions.put(listA.get(1), Long.valueOf(listA.get(0)));
        }
    }

    mapTransactions.forEach((k, v) -> listTransaction.add(new Transaction(v, k)));

    listTransaction.add(new Transaction(-22900, "2022-01-04"));

    return listTransaction;
}

private String getMockAnticipations() {
    return "1646;2022-11-18\n" +
            "52;2022-01-20\n" +
            "1358;2022-09-19\n" +
            "1793;2022-12-19\n" +
            "248;2022-01-17\n" +
            "973;2022-01-17\n" +
            "1502;2022-10-19\n" +
            "1221;2022-08-22\n" +
            "1833;2022-02-02\n" +
            "461;2022-03-23\n" +
            "299;2022-01-24\n" +
            "19570;2022-02-02\n" +
            "915;2022-06-21\n" +
            "1617;2022-01-31\n" +
            "770;2022-05-23\n" +
            "1064;2022-07-21\n" +
            "24;2022-01-21\n" +
            "614;2022-04-22";
}`

thiagokuniwake avatar Mar 25 '22 21:03 thiagokuniwake

Have you tried using a custom guess? That the algorithm does not converge for a particular set of data is not (necessarily) a bug.

RayDeCampo avatar Mar 26 '22 00:03 RayDeCampo

RayDeCampo, thanks to respond! I not tried using a custom guess! How i can using a custom guess? Have a document to explain it?

thiagokuniwake avatar Mar 26 '22 14:03 thiagokuniwake

Use the Builder, see XirrBuilderTest for some examples.

https://github.com/RayDeCampo/java-xirr/blob/master/src/test/java/org/decampo/xirr/XirrBuilderTest.java

RayDeCampo avatar Mar 26 '22 14:03 RayDeCampo

grate test and could I have some info how to implement mocks from this test in service level for example

private List<Transaction> transactions;

        DoubleUnaryOperator
            op
            = DoubleUnaryOperator.identity();

    final double xirr = Xirr.builder().withNewtonRaphsonBuilder(
            NewtonRaphson.builder()
                    .withIterations(10000)
                    .withTolerance(0.001)
                    .withDerivative(op)
                    .withFunction(op))
            .withGuess(3)
            .withTransactions(
            transactions).xirr();
			

this implementation throws 10000 iterations

WojciechKorban avatar Feb 28 '23 13:02 WojciechKorban

I'm sorry @WojciechKorban I'm not really sure what you are asking in terms of mocking.

FYI, it doesn't make sense to set the derivative or function on the NewtonRaphsonBuilder that is going to be used by Xirr as they will be overwritten.

RayDeCampo avatar Mar 01 '23 01:03 RayDeCampo

Hi Thank you for your quick response my question is in the test https://github.com/RayDeCampo/java-xirr/blob/master/src/test/java/org/decampo/xirr/XirrBuilderTest.java

we are mocking the behavior of NewtonRaphson Builder

private NewtonRaphson.Builder setUpNewtonRaphsonBuilder()
{
    final NewtonRaphson.Builder builder = mock(NewtonRaphson.Builder.class);
    when(builder.withFunction(any())).thenReturn(builder);
    when(builder.withDerivative(any())).thenReturn(builder);
    return builder;
}

to avoid this issue my Question is how can I get this behavior in the service layer? Do I need to pass a NewtonRaphson.builder() like in the code in my earlier post if so could you provide me with info on how to initialize NewtonRaphson or do I need to do something else to calculate metric without Newton-Raphson failing to converge within 10000

WojciechKorban avatar Mar 02 '23 12:03 WojciechKorban

If you are talking about production code when you refer to the service layer, then you don't want to do any mocking. If you have a particular set of transactions that are failing to converge, you can try a series of different guesses.

RayDeCampo avatar Mar 02 '23 22:03 RayDeCampo

ok thank you for response

WojciechKorban avatar Mar 08 '23 09:03 WojciechKorban