Home > Enterprise >  Java sorting by spread between two BigDecimal
Java sorting by spread between two BigDecimal

Time:01-30

Please help with sorting in Java. I have a simple example (looks like this). I need to sort list by the difference between two BigDecimals.

My Data class (I cut getters)

    public class Quotation {
    private final long id;
    private final BigDecimal askPrice;
    private final BigDecimal bidPrice;

    public Quotation(long id, BigDecimal bidPrice, BigDecimal askPrice) {
        this.id = id;
        this.askPrice = askPrice;
        this.bidPrice = bidPrice;
    }
    }

Here we store our records.

        storeQuotation(new Quotation(1000,new BigDecimal("99"), new BigDecimal("104")));
        storeQuotation(new Quotation(1001,new BigDecimal("69"), new BigDecimal("72")));
        storeQuotation(new Quotation(1002,new BigDecimal("65"), new BigDecimal("69")));
        storeQuotation(new Quotation(1003,new BigDecimal("70"), new BigDecimal("71")));
        storeQuotation(new Quotation(1004,new BigDecimal("71"), new BigDecimal("73")));
        storeQuotation(new Quotation(1005,new BigDecimal("90"), new BigDecimal("95")));
        storeQuotation(new Quotation(1006,new BigDecimal("92"), new BigDecimal("93")));
        storeQuotation(new Quotation(1007,new BigDecimal("94"), new BigDecimal("98")));
        storeQuotation(new Quotation(1008,new BigDecimal("90"), new BigDecimal("92")));
        storeQuotation(new Quotation(1009,new BigDecimal("92"), new BigDecimal("95")));
out - Not Sorted
    id - 1000.   Bid - 99.   Ask - 104.   Spread = 5
    id - 1001.   Bid - 69.   Ask - 72.   Spread = 3
    id - 1002.   Bid - 65.   Ask - 69.   Spread = 4
    id - 1003.   Bid - 70.   Ask - 71.   Spread = 1
    id - 1004.   Bid - 71.   Ask - 73.   Spread = 2
    id - 1005.   Bid - 90.   Ask - 95.   Spread = 5
    id - 1006.   Bid - 92.   Ask - 93.   Spread = 1
    id - 1007.   Bid - 94.   Ask - 98.   Spread = 4
    id - 1008.   Bid - 90.   Ask - 92.   Spread = 2
    id - 1009.   Bid - 92.   Ask - 95.   Spread = 3

And I just need to sort this list by the difference between bidPrice and askPrice. I tried this method...

    public static List<Quotation> getSpreadsList(boolean decreasing) {
        List<Quotation> sortedBySpread = QuotationsStoreImpl.quotationList;

        Collections.sort(sortedBySpread, (a, b) ->
     (a.getBidPrice().intValue() - b.getAskPrice().intValue()));

//        sortedBySpread.sort((a, b) -> 
//    (a.getBidPrice().intValue() - b.getAskPrice().intValue()));

        if (decreasing) {
            Collections.reverse(sortedBySpread);
        }
        return sortedBySpread;
    }
    }

But without success...

out - Sorted
    id - 1002.   Bid - 65.   Ask - 69.   Spread = 4
    id - 1003.   Bid - 70.   Ask - 71.   Spread = 1
    id - 1004.   Bid - 71.   Ask - 73.   Spread = 2
    id - 1001.   Bid - 69.   Ask - 72.   Spread = 3
    id - 1008.   Bid - 90.   Ask - 92.   Spread = 2
    id - 1009.   Bid - 92.   Ask - 95.   Spread = 3
    id - 1006.   Bid - 92.   Ask - 93.   Spread = 1
    id - 1007.   Bid - 94.   Ask - 98.   Spread = 4
    id - 1005.   Bid - 90.   Ask - 95.   Spread = 5
    id - 1000.   Bid - 99.   Ask - 104.   Spread = 5

The list is mixed but not sorted according to my criteria ! Spread not sorted !

How can I sort this list correct, by spread ?

I don't have much experience in java. And all my attempts have come to nothing.

CodePudding user response:

Collections.sort(sortedBySpread, (a, b) -> (a.getBidPrice().intValue() - b.getAskPrice().intValue())); does some math that makes little since since it subtracts the ask from the bid of two different quotes.

Instead you should calculate the spread of a and then subtract the spread of b:

Collections.sort(sortedBySpread, (a, b) -> (a.getBidPrice().intValue() - a.getAskPrice().intValue()) - (b.getBidPrice().intValue() - b.getAskPrice().intValue()));

Generally this could be expanded into the following to make it more clear what is going on:

Collections.sort(sortedBySpread, (Quotation a, Quotation b) -> {
    int spreadA = a.getBidPrice().intValue() - a.getAskPrice().intValue();
    int spreadB = b.getBidPrice().intValue() - b.getAskPrice().intValue();
    return spreadA - spreadB;
});

But starting with the first snippet IntelliJ suggest the arguably far cleaner solution

Collections.sort(sortedBySpread, Comparator.comparingInt(a -> (a.getBidPrice().intValue() - a.getAskPrice().intValue())));

And going from there it might make sense to have a getSpread on Quotation:

public int getSpread() {
    return bidPrice.intValue() - askPrice.intValue();
}

which would then allow

Collections.sort(sortedBySpread, Comparator.comparingInt(Quotation::getSpread));

And finally

sortedBySpread.sort(Comparator.comparingInt(Quotation::getSpread));

without the need for Collections.sort.

CodePudding user response:

For demo, I put your values in a list. I also added the following to your class.

public BigDecimal getSpread() {
       return askPrice.subtract(bidPrice);
}
public String toString() {
       return "id - %d    bid - %6.2f     ask - %6.2f     spread - %6.2f".formatted(id, bidPrice, askPrice,getSpread());   
}

The data

 List<Quotation> quotes = new ArrayList<>(List.of(
   (new Quotation(1000,new BigDecimal("99"), new BigDecimal("104"))),
   (new Quotation(1001,new BigDecimal("69"), new BigDecimal("72"))),
   (new Quotation(1002,new BigDecimal("65"), new BigDecimal("69"))),
   (new Quotation(1003,new BigDecimal("70"), new BigDecimal("71"))),
   (new Quotation(1004,new BigDecimal("71"), new BigDecimal("73"))),
   (new Quotation(1005,new BigDecimal("90"), new BigDecimal("95"))),
   (new Quotation(1006,new BigDecimal("92"), new BigDecimal("93"))),
   (new Quotation(1007,new BigDecimal("94"), new BigDecimal("98"))),
   (new Quotation(1008,new BigDecimal("90"), new BigDecimal("92"))),
   (new Quotation(1009,new BigDecimal("92"), new BigDecimal("95")))));

The sorting part is simple. Just use a comparator, referencing the spread.

quotes.sort(Comparator.comparing(Quotation::getSpread));

And print

for(Quotation q : quotes) {
    System.out.println(q);
} 

Prints

id - 1003    bid -  70.00     ask -  71.00     spread -   1.00
id - 1006    bid -  92.00     ask -  93.00     spread -   1.00
id - 1004    bid -  71.00     ask -  73.00     spread -   2.00
id - 1008    bid -  90.00     ask -  92.00     spread -   2.00
id - 1001    bid -  69.00     ask -  72.00     spread -   3.00
id - 1009    bid -  92.00     ask -  95.00     spread -   3.00
id - 1002    bid -  65.00     ask -  69.00     spread -   4.00
id - 1007    bid -  94.00     ask -  98.00     spread -   4.00
id - 1000    bid -  99.00     ask - 104.00     spread -   5.00
id - 1005    bid -  90.00     ask -  95.00     spread -   5.00

      
  • Related