GRIDNET OS Market Making Development Report (Part 3)

Community Update: Making Our Market Maker Smarter & More Resilient

Hello everyone,

We’re excited to share some key improvements we’re working on for our market-making bot. Our primary focus is on enhancing its intelligence and security, especially against aggressive, high-frequency trading bots that can attempt to manipulate market prices.

The “Why”: Defending Against Pump & Dump Tactics

Sophisticated bots can try to exploit automated market makers like ours. A common tactic is a rapid “pump and dump,” where they execute a series of fast trades to create artificial price movements. They aim to trick our bot into placing orders at unfavorable prices, which they can then immediately trade against for a quick profit at our expense.

For example, an attacker might fill our sell orders to push the price up, wait for our bot to automatically place new buy orders in the newly created price gap, and then immediately dump their assets onto our new, higher-priced buy orders. Our upcoming upgrades are designed to specifically counter these manipulative patterns.

Here’s a breakdown of what we’re implementing:

1. Smarter Spread Management: Resisting the Pull (Passive Defense)

  • What it is: Instead of always re-centering our main buy/sell spread on the latest market price, the bot will now remember its previous position.

  • The Rationale: This is our core strategic defense. If the market is suddenly pushed up (a pump), our bot will anchor its new orders closer to its old, stable position, refusing to chase the inflated price. The same happens in reverse during a dump. This makes it much harder for attackers to “lead” our bot into placing orders exactly where they want them. It forces them to expend more capital for less effect, making the attack unprofitable.

2. Active Defense: A “Tactical Pause” After a Fill

  • What it is: Whenever one of our orders is filled, the bot will now automatically and instantly pause the placement of new non-essential limit orders on that same side (e.g., if a sell order is filled, new sell orders are paused).

  • The Rationale: This is a crucial, low-latency active defense. It gives our primary spread management logic (from point #1) a moment to analyze the situation and reposition our defenses intelligently, rather than instantly rushing to fill the price gap. This breaks the rhythm of the classic “fill-and-dump” combo by introducing a deliberate, protective delay that foils the attacker’s high-speed strategy. Essential operations like flashing orders and the spread repositioning itself are exempt from this pause.

3. Safer Self-Trading: Aborting High-Cost Operations

  • What it is: The bot periodically performs self-trades to meet exchange requirements for trading volume and frequency. We’re upgrading the stability check for these operations.

  • The Rationale: Attackers can see our pending self-trade orders and place their own orders in the way, hoping we’ll buy from them at an inflated price instead of from ourselves. The upgraded logic now scans the order book right before completing a self-trade. It calculates the “cost” of any intervening third-party orders. If this cost is too high, the bot will abort the operation and try again later. This prevents attackers from hijacking our own compliance mechanisms for their profit.

How It All Works Together: A Layered Defense

Think of these upgrades as a multi-layered defense system:

  • The Smarter Spread Management is our strategic foundation, making the bot fundamentally more resilient.

  • The Tactical Pause is our immediate, reflexive defense that activates on contact, disrupting high-frequency attacks.

  • The Safer Self-Trading secures our internal operations from being turned against us.

These changes will make our bot not just tougher, but smarter—able to better distinguish between genuine market activity and manipulative patterns. We are committed to continuously improving our systems to protect our operations and ensure long-term, stable performance.

Thank you for your continued support and trust.

Best regards,

The Wizardly Market Making Team
(creators of legendary Liquidius Maximus market making suite)

What follows is an internal mamo related to incorporation of a real-time Market Pressure Sensor module.

"""
================================================================================
          ARCHITECTURAL MEMO: ANTI-MANIPULATION & DEFENSE SYSTEM
================================================================================

This document outlines the architecture of the bot's advanced defense system,
designed to protect against high-frequency pump-and-dump and sandwich attacks.
The system is built on a race-condition-free, sequential event processing model
that ensures data consistency and enables both real-time tactical responses and
long-term strategic analysis.

---------------------------------
I. CORE PHILOSOPHY & CHALLENGES
---------------------------------

The primary challenge in defending against market manipulation is correlating
public market data with our own private actions. An attacker's actions are visible
on the public trade feed, while our own trades are confirmed through a separate,
private feed. These two data streams are not synchronized, creating a critical
race condition:

  - A public trade appears instantly. Is it the start of a hostile pump, or is
    it simply our own legitimate market order executing?
  - The private confirmation that the trade was ours may arrive milliseconds or
    even seconds later due to network latency.

A naive system would either react too slowly (waiting for private confirmation)
or react incorrectly (treating its own trades as hostile). This architecture
solves this problem by centralizing all data ingestion and processing.

---------------------------------
II. SYSTEM ARCHITECTURE & MODULE ROLES
---------------------------------

The defense system is composed of three key modules working in concert:

1.  **OrderManagementSystem (OMS) - The Central Nervous System:**
    -   **Role:** The OMS is the exclusive gateway for all real-time exchange data.
        It is the *only* component that maintains active WebSocket connections for
        both the PUBLIC (trades) and PRIVATE (our orders, our fills, balances) streams.
    -   **Data Funnel:** All incoming messages from both WebSockets are immediately
        placed onto a single, thread-safe `_event_queue`. This transforms concurrent,
        unpredictable network events into a strict, sequential (first-in, first-out)
        stream of work.
    -   **Event Processor:** A dedicated background thread (`_process_event_queue`)
        consumes events from this queue one at a time. This is the cornerstone of the
        race-condition-free design, as it guarantees that public and private events
        are handled atomically and in a deterministic order.

2.  **MarketPressureSensor (in MarketDataEngine) - The Sensory Organ:**
    -   **Role:** This is a purely analytical, passive engine. It has NO network
        connections and NO background threads. Its sole purpose is to receive
        fully processed `MarketTrade` objects from the OMS and update its internal
        metrics.
    -   **Data Flow:** It is a "subscriber" to the OMS's processed trade data. The
        OMS calls its `process_trade()` method for every single trade that occurs
        on the market.
    -   **Intelligence:** It maintains two key perspectives:
        a. **Short-Term Pressure (Tactical):** Calculates 0-100 "pump" and "dump"
           scores based on the taker activity in a very short, rolling time window
           (e.g., 5 seconds). This is used for immediate threat detection.
        b. **Long-Term Holdings (Strategic):** Tracks an estimate of the total
           assets accumulated by hostile actors over a much longer window (e.g.,
           30 minutes). This provides context on the potential severity of a future dump.

3.  **SandwichDefenseTracker (in OrderManagementSystem) - The Immune System:**
    -   **Role:** This is the decision-making and action-taking component. It uses
        the intelligence provided by the `MarketPressureSensor` to decide if, when,
        and how to react to a perceived threat.
    -   **Data Flow:** It queries the `MarketPressureSensor` for its latest scores
        and estimates. It also receives high-level market data (like the best bid
        and order book snapshot) from the `MarketDataEngine`.
    -   **Actions:** When its confidence in an attack is high, it executes defensive
        protocols:
        - Cancels all vulnerable buy orders.
        - Imposes temporary trading restrictions.
        - Decides whether to perform a "Passive Defense" (letting the market
          self-correct) or an "Active Defense" (executing a market sell to
          forcibly restore the price).

---------------------------------
III. THE EVENT LIFECYCLE: SOLVING THE RACE CONDITION
---------------------------------

This is the critical data flow that prevents race conditions.

1.  **Event Arrival:** A trade occurs on the exchange.
    - The `XTPublicWSClient` receives the public trade message.
    - Milliseconds later, the `XTPrivateWSClient` receives the private fill confirmation.
    - Both handlers do NOTHING but put their raw message onto the central `_event_queue`
      in the `OrderManagementSystem`.

2.  **Sequential Processing:** The `_event_processor_thread` picks up events from the
    queue one by one. Let's assume the public event arrived first.

3.  **Handling a Public Trade (`_handle_public_trade_event`):**
    - The event is parsed into a `MarketTrade` object.
    - **Hostility-First Principle:** The trade's `is_own_trade` flag is left as `False`.
    - The trade is immediately sent to `market_pressure_sensor.process_trade()`.
      The sensor instantly updates its scores and hostile holdings estimate, assuming
      the trade was an attack. This ensures the fastest possible defensive posture.
    - The `MarketTrade` object is stored in a temporary buffer, `_pending_public_trades`,
      awaiting potential private confirmation.

4.  **Handling a Private Trade (`_handle_private_trade_event`):**
    - The processor thread pulls the private fill message from the queue.
    - It extracts the unique `trade_id`.
    - It searches the `_pending_public_trades` buffer for a public trade with the
      matching `trade_id`.
    - **The Correction:** If a match is found:
        a. The `is_own_trade` flag on the buffered `MarketTrade` object is set to `True`.
        b. `market_pressure_sensor.process_trade()` is called *again* with this
           now-corrected object. The sensor's logic sees the `is_own_trade=True`
           flag and retroactively reverses the trade's contribution to the
           hostile holdings estimate.
    - The main `_on_trade_event` handler is then called to update the bot's internal
      order fill status, as it always has.

**Outcome:** This sequence guarantees that even if the public data arrives first,
the system is immediately defended. When the private confirmation arrives, the
long-term strategic view is corrected without ever compromising the real-time
tactical response. The race condition is resolved through serialized processing
and retroactive state correction.

================================================================================
"""

Technical memo regarding two main web-socket event handlers follows:

"""
==========================================================================================
    TECHNICAL MEMO: RACE-CONDITION-FREE WEBSOCKET EVENT HANDLING ARCHITECTURE
==========================================================================================

This document details the architecture of the OMS's real-time event handlers,
`_on_order_event` and `_on_trade_event`. The design is critically engineered to
handle the asynchronous, non-guaranteed nature of WebSocket messages from the
exchange, ensuring data consistency, eliminating race conditions, and enabling
both immediate tactical responses and long-term state accuracy.

---------------------------------
I. The Core Problem: Asynchronous & Separate Data Feeds
---------------------------------

The exchange provides two distinct but related private WebSocket topics:

1.  **`order` Topic:** This is the **authoritative source of truth for an order's
    STATE**. It fires whenever an order is created, its status changes (e.g., from
    NEW to PARTIALLY_FILLED), or it reaches a terminal state (FILLED, CANCELED).
    It provides the complete picture: status, total executed quantity, remaining
    quantity, etc.

2.  **`trade` Topic:** This is the **authoritative source of truth for a single
    EXECUTION (a fill)**. It fires for each individual trade that occurs against
    one of our orders. It provides the specifics of that one fill (price, quantity)
    but crucially LACKS the overall order status.

The challenge is that these events are not synchronized. A `trade` event for a
fill might arrive before or after the corresponding `order` event that updates the
status to PARTIALLY_FILLED. This architecture is designed to handle this ambiguity
robustly by assigning strict, non-overlapping responsibilities to each handler.

---------------------------------
II. Separation of Concerns: The Guiding Principle
---------------------------------

To prevent inconsistent state and logical errors, each handler is given a precise
and exclusive set of responsibilities.

**`_on_trade_event` is responsible ONLY for FILL-RELATED actions:**
    -   Recording the individual trade for historical analysis (`_ingest_trades`).
    -   Incrementing the `executed_qty` and decrementing `remaining_qty` in our
        local order records. This provides an immediate, low-latency reflection
        of the fill.
    -   Calculating "first-fill latency" as this is the first moment we are aware
        of an execution.
    -   Triggering **immediate, time-critical defenses** that depend on a fill,
        such as Flashing Orders Protection (FOP) or flagging the need for spread
        reconciliation.

**`_on_order_event` is responsible ONLY for STATE-RELATED actions:**
    -   Updating the `status` field of our local order records. This is the only
        place the status is ever changed.
    -   Synchronizing our local `executed_qty` and `remaining_qty` with the
        authoritative values from the exchange, correcting any potential drift.
    -   Calculating "first-touch latency" on the first non-`NEW` status update.
    -   Making the final decision to **remove an order from active tracking** when
        it reaches a truly terminal state (FILLED, CANCELED, REJECTED). It
        correctly understands that for flashing orders, `CANCELED` is part of a
        cycle and not a terminal state.

This strict division ensures there is no ambiguity. A `trade` event updates numbers,
an `order` event updates status labels and performs final cleanup.

---------------------------------
III. Expected Event Flow & Handler Interaction
---------------------------------

Understanding the typical sequence of events is key to verifying the logic.

**A. For a standard LIMIT Order:**

1.  **Placement:** We send a `POST /v4/order` request.
2.  **`order` Event (NEW):** The exchange accepts the order. We receive an `order`
    event with `st: "NEW"`.
    -   `_on_order_event` fires, creating the initial record in `active_orders`
        and `order_history`.
3.  **A Taker Hits Our Order:** A market order on the other side fills part of our order.
4.  **`trade` Event (Fill):** We receive a `trade` event for the partial fill.
    -   `_on_trade_event` fires. It increments `executed_qty`, calculates
        first-fill latency, and triggers any relevant defenses (like FOP). It
        **does not** change the order's status.
5.  **`order` Event (PARTIALLY_FILLED):** Immediately after the trade, we receive an
    `order` event with `st: "PARTIALLY_FILLED"`.
    -   `_on_order_event` fires. It updates the status to `PARTIALLY_FILLED` and
        resynchronizes the quantities with the authoritative values from this
        event.
6.  **Final Fill or Cancellation:** The order is either fully filled or canceled.
7.  **`trade` Event (Final Fill - Optional):** If filled, a final `trade` event arrives.
    -   `_on_trade_event` fires, updating the quantities for the last time.
8.  **`order` Event (FILLED/CANCELED):** We receive the final `order` event with
    `st: "FILLED"` or `st: "CANCELED"`.
    -   `_on_order_event` fires. It updates the status to its terminal state,
        identifies that the order should be removed, and removes it from the
        live `active_orders` list.

**B. For a MARKET Order (as you correctly identified):**

Market orders are atomic and their lifecycle is compressed. The exchange matching
engine processes them immediately.

1.  **Placement:** We send a `POST /v4/order` request for a market order.
2.  **`order` Event (FILLED):** The exchange immediately executes the order against
    the book. The *first* and *only* `order` event we receive will have the final
    status `st: "FILLED"`. It will also contain the final `executedQty` (`eq`) and
    average price (`ap`).
    -   `_on_order_event` fires. It creates the order record in our tracking and
        immediately marks it as `FILLED`. Because it's a terminal state for a
        non-flashing order, it might be added and removed from `active_orders`
        in the same function call, which is correct behavior.
3.  **`trade` Event(s) (Fill(s)):** Immediately following the `order` event, we will
    receive one or more `trade` events, corresponding to each individual fill
    that made up the market order's execution.
    -   `_on_trade_event` fires for each fill. It will find the (already `FILLED`)
        order in `order_history` and record the trade details. Its updates to
        `executed_qty` are redundant but harmless, as the final authoritative
        quantity was already set by the `order` event.

This architecture correctly handles both scenarios because it does not rely on
a specific event order. It processes the information that each event type is
authoritative for, whenever it arrives.

==========================================================================================
"""

1. Introduction & Situation Report

This memo outlines a critical, high-priority evolution of our bot’s defense systems. The changes detailed here are a direct response to a series of sophisticated, systematic attacks observed on the GNC/USDT pair on the XT.com exchange.

For the initial eight hours of our latest market-making session, the bot performed exceptionally well, maintaining tight spreads, ensuring compliance, and operating within expected parameters. However, following this stable period, we observed the re-emergence of hostile high-frequency trading bots. These actors were not engaged in simple arbitrage but were executing a highly targeted strategy designed to exploit the predictable, rules-based logic of our RiskManagementSystem.

After a thorough forensic analysis of the trading data, we have reverse-engineered the attacker’s playbook. We are now implementing Project Cerberus, a multi-layered defensive upgrade designed to make our bot’s risk response context-aware and fundamentally unpredictable to outside observers.

2. The Attack Vector: Exploiting the Rebalancing Reflex

The core vulnerability was not a bug in our order placement or a flaw in our existing SandwichDefenseTracker. Instead, the attackers identified and exploited our bot’s automated rebalancing and stop-loss logic.

The attack followed a devastatingly effective four-phase loop:

  1. Phase A - The Flash Crash (Manipulation): The attacker executes a rapid, high-volume market sell to artificially crash the price. This is designed to inflict an immediate, significant paper loss on our portfolio.

  2. Phase B - The Trigger (Exploitation): Our RiskManagementSystem, operating correctly under its programmed rules, detects that the portfolio’s PnL has crossed its stop-loss threshold (e.g., -5%). It dutifully initiates a rebalancing action to correct the inventory imbalance. This action is a predictable market buy.

  3. Phase C - The Trap (Profit-Taking): The attacker, having anticipated our bot’s reaction, immediately reverses the market with an aggressive pump. They become the seller, filling our bot’s rebalancing market buy orders at artificially inflated prices.

  4. Phase D - The Reset: The attacker allows the market to stabilize, knowing our bot will now place new resting sell orders (to offload the GNC it just bought high). They can then dump the price again to hit these orders, completing the profitable cycle for them, and repeating the attack.

Essentially, the attackers turned our bot’s self-preservation mechanism into an on-demand liquidity tool for their profit-taking. Our SandwichDefenseTracker was ineffective because the attack did not target our resting limit orders; it targeted our high-level risk management brain, forcing it to place aggressive market orders.

3. The Solution: Implementing Adversarial Awareness

To neutralize this threat, we are elevating our defense from a simple order-level protection to a systemic, context-aware posture. The RiskManagementSystem will no longer operate in a vacuum. It will be integrated directly with our real-time market pressure analytics.

Step 1: Connecting the Sensor to the Brain

The RiskManagementSystem will be given a direct reference to the MarketPressureSensor. This provides our high-level strategic logic with the low-level, real-time tactical view it was missing.

Step 2: The “Cerberus” Gatekeeper

We will implement a new private method within the RiskManagementSystem named _is_safe_to_execute_taker_order(). This function will act as a critical gatekeeper for any action that places an aggressive market order (stop-loss, rebalancing, exposure adjustment, etc.).

Before executing, this gatekeeper will query the MarketPressureSensor to answer one question: “Is the market currently being manipulated?”

It will block the action if:

  • The sensor detects that a full-blown Pump & Dump sequence is active.

  • The sensor’s short-term Pump Score is critically high, indicating immediate, one-sided buying pressure.

Step 3: Integrating the Gatekeeper into All Risk Actions

The _is_safe_to_execute_taker_order() check will be placed at the very beginning of every function within risk_management.py that can result in a market order. This includes:

  • execute_stop_loss()

  • rebalance_position()

  • adjust_exposure()

  • execute_quote_stop_loss_classic()

  • execute_base_stop_loss_classic()

4. Impact and Expected Outcome

This implementation fundamentally breaks the attacker’s feedback loop.

  • Predictability Removed: The attacker can no longer guarantee that inducing a loss will result in our bot placing a market order. Our bot’s response is now conditional on the market’s health.

  • The Trap is Disarmed: When the attacker initiates their flash crash, the sensor’s scores will become highly abnormal. The Cerberus gatekeeper will detect this and prevent the rebalancing market buy from ever being placed.

  • Attacker is Stranded: The attacker is left holding a position after manipulating the price, but their expected counterparty (our bot) has intelligently refused to participate. Their ability to profitably exit the manipulation is severely hampered.