Skip to content

Sorting algorithm

A sorting algorithm orders complete records by a chosen key. See stable price ties, ascending and descending order, Python copy versus mutation, and ordering assumptions.

A sorting algorithm rearranges records into a specified order while preserving the records themselves. In quant work, it can put prices into a ladder, signals into a ranking or observations into chronological order. The essential contract is twofold: the output follows the ordering rule, and it contains every input record with the same multiplicity. Sorting alone neither removes duplicates nor combines observations. NIST defines sorting through these ordering and permutation requirements.
The key is the value used to order each record. Price, timestamp and signal score are different keys; ascending means smallest first, while descending means largest first. Choose that rule before choosing an algorithm.

One price key, two directions

Consider three fictional records in this input sequence: A at 101 USD, B at 99 USD and C at 101 USD. Sorting by ascending price puts B first. A and C tie, so the price key alone does not determine their relative order.

A stable sort preserves the input order among records with equal keys. Here A precedes C, so a stable ascending sort returns B, A, C. A stable descending sort returns A, C, B: it reverses the price direction while retaining A before C. Python guarantees stability for both directions. Python Sorting HOWTO: stability and reverse ordering.
Fictional records A at 101 USD, B at 99 USD and C at 101 USD become B, A, C in stable ascending order and A, C, B in stable descending order. A remains before C.
Fictional records A at 101 USD, B at 99 USD and C at 101 USD become B, A, C in stable ascending order and A, C, B in stable descending order. A remains before C.
The same three records, ordered by one price key. Highlighted A and C retain their input order because their keys are equal.
Stability preserves an order that already exists; it does not establish order-book priority. If the input was assembled from several feeds, A appearing before C need not mean A arrived first at an exchange. A time-priority rule needs the relevant venue's rules and authoritative sequencing data. Likewise, reproducible alphabetical ties in a signal ranking need an explicit secondary symbol key if the incoming sequence can change.

A sorted result or a changed list?

In Python, sorted() creates a new list. list.sort() changes the existing list and returns None. Both accept a key function; this example moves complete records, keeping IDs attached to prices. Python's list sorting contract.
records = [ {"id": "A", "price": 101}, {"id": "B", "price": 99}, {"id": "C", "price": 101}, ] ascending = sorted(records, key=lambda row: row["price"]) descending = sorted(records, key=lambda row: row["price"], reverse=True) print([row["id"] for row in ascending]) # ['B', 'A', 'C'] print([row["id"] for row in descending]) # ['A', 'C', 'B'] print([row["id"] for row in records]) # ['A', 'B', 'C'] working = records.copy() result = working.sort(key=lambda row: row["price"]) print([row["id"] for row in working], result) # ['B', 'A', 'C'] None
The new lists still refer to the same record dictionaries: changing a dictionary through one list is visible through the others. A new outer list is not a deep copy. Also, reverse=True is not equivalent to reversing the entire ascending result: that would reverse tied A and C as well.

The ordering assumptions matter

A comparison-based sort needs keys with a consistent ordering. Python compares sorting keys using <; mixed incompatible types can raise TypeError. Floating-point NaN values compare unordered, so a price column containing NaNs does not acquire a meaningful numeric order merely because sorting completes. Decide whether to reject, exclude or explicitly position missing values before ranking them. Python documents these unorderable-value cases.
Time complexity depends on the algorithm and assumptions. Ordinary insertion sort has quadratic worst-case work; an O(nlog⁡n)O(n\log n) bound cannot be assumed for an arbitrary sorting algorithm. Comparing expensive keys, moving large records and using additional memory also affect the choice. Python's key function is evaluated once per record, but computing those keys still has a cost. NIST's insertion-sort entry and the sorting overview explain why workload and storage matter.
For the underlying growth-rate reasoning, Algorithms, Growth Rates, and Asymptotic Notation uses insertion sort to separate best and worst cases. The public page is a preview; the full lesson requires membership.

Sources

Last updated
  • algorithms
  • python
  • sorting
  • stability
  • data ordering
← Back to the glossaryBack to top ↑