Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java sorting by spread between two BigDecimal

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.

like image 790
Anatolii Avatar asked Aug 29 '26 23:08

Anatolii


2 Answers

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.

like image 176
luk2302 Avatar answered Aug 31 '26 14:08

luk2302


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

      
like image 31
WJS Avatar answered Aug 31 '26 15:08

WJS



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!