fintech-algorithms
Using a coding agent? Give it the skill: npx skills add IslamBaraka90/Fintech-Algorithms-Library What it does →

Self-Trade Prevention

Install and import#

bash
npm install fintech-algorithms
ts
import { selfTradePrevention } from "fintech-algorithms/matching-engines-and-venue-logic/order-controls/self-trade-prevention";

Signature#

selfTradePrevention(incoming_order, resting_orders, mode)

Stops a participant trading with itself — required by most venues, and the *mode* determines who loses their order. Cancel-newest, cancel-oldest and cancel-both give materially different outcomes for queue position.

Parameters#

NameTypeNotes
incoming_orderOrderThe aggressing order with its participant identifier.
resting_ordersOrder[]Resting orders that would otherwise match.
modestringPrevention mode — cancel newest, cancel oldest, cancel both, or decrement.

Returns#

{ action, cancelled, remaining, mode, … }

Which orders were cancelled and which survive, under the mode applied.

Errors#

  • When the mode is unrecognised — throws

Complexity: time O(resting), space O(cancelled).

Worked example#

executed Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.

Input#

incoming_order
{
  "order_id": "IN-1",
  "side": "buy",
  "price_atoms": 1000200,
  "quantity": 600,
  "participant_id": "P-1",
  "stp_group": "G-1"
}
resting_orders
[
  {
    "order_id": "R-EXT-1",
    "side": "sell",
    "price_atoms": 1000000,
    "quantity": 150,
    "participant_id": "P-EXT",
    "stp_group": "G-X",
    "sequence": 1
  },
  {
    "order_id": "R-SELF",
    "side": "sell",
    "price_atoms": 1000100,
    "quantity": 220,
    "participant_id": "P-1",
    "stp_group": "G-1",
    "sequence": 2
  },
  {
    "order_id": "R-EXT-2",
    "side": "sell",
    "price_atoms": 1000200,
    "quantity": 300,
    "participant_id": "P-EXT",
    "stp_group": "G-X",
    "sequence": 3
  }
]
mode
"cancel_newest"

Call#

selfTradePrevention(incoming_order, resting_orders, mode)

Returns#

object with 11 fields: mode, incoming_order_id, original_incoming_quantity, external_executed_quantity, prevented_self_quantity, canceled_incoming_quantity, canceled_resting_quantity, remaining_incoming_quantity, …

{
  "mode": "cancel_newest",
  "incoming_order_id": "IN-1",
  "original_incoming_quantity": 600,
  "external_executed_quantity": 150,
  "prevented_self_quantity": 220,
  "canceled_incoming_quantity": 450,
  "canceled_resting_quantity": 0,
  "remaining_incoming_quantity": 0,
  "events": [
    {
      "action": "execute-external",
      "incoming_order_id": "IN-1",
      "resting_order_id": "R-EXT-1",
      "quantity": 150,
      "price_atoms": 1000000
    },
    {
      "action": "cancel-incoming",
      "incoming_order_id": "IN-1",
      "resting_order_id": "R-SELF",
      "prevented_quantity": 220
    }
  ],
  "resting_orders": [
    {
      "order_id": "R-SELF",
      "side": "sell",
      "price_atoms": 1000100,
      "quantity": 220,
      "participant_id": "P-1",
      "stp_group": "G-1",
      "sequence": 2
    },
    {
      "order_id": "R-EXT-2",
      "side": "sell",
      "price_atoms": 1000200,
      "quantity": 300,
      "participant_id": "P-EXT",
      "stp_group": "G-X",
      "sequence": 3
    }
  ],
  "state": "self-trade-prevented"
}

Other exports#

This module also exports tickSizeValidation, priceBandValidation, cancelOnDisconnect, fatFingerLimit, circuitBreakerTrigger, calculate. Every module additionally exports run as an alias of its primary function, and a meta object carrying its catalog id, domain, family, shape and article URL.

Diagrams#

Self-Trade Prevention — system map

Calculation flow#

Self-Trade Prevention calculation flow
flowchart LR
    S1["Sort marketable contra orders by pricetime"]
    S2["Execute external interest normally"]
    S3["At a matching STP group apply the selected mode"]
    S4["Emit every cancellation decrement and execution"]
    S5["Return the residual book"]
    S1 --> S2
    S2 --> S3
    S3 --> S4
    S4 --> S5
    S5 --> D{"first sameparticipant and samegroup encounter"}
    D --> O["prevented_self_quantity + diagnostics"]
    O --> A["Audit: Prevented self quantity is never reported as execution"]

How it works#

This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.

Read the article →

References#

The rest of the Order Controls family#