606 lines
15 KiB
Markdown
606 lines
15 KiB
Markdown
|
|
# PINK BingX Simplification Spec
|
||
|
|
|
||
|
|
Status: Draft for implementation review
|
||
|
|
Date: 2026-05-22
|
||
|
|
Owner: Runtime / Trading Systems
|
||
|
|
Scope: PINK only, with BLUE parity preserved for algorithm comparison
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This spec defines a simplified live-trading architecture for PINK that:
|
||
|
|
|
||
|
|
1. Preserves the BLUE algorithm exactly.
|
||
|
|
2. Makes every engine action observable.
|
||
|
|
3. Uses the exchange as the authoritative source of live position truth.
|
||
|
|
4. Reuses the existing data structures needed for BLUE/PINK comparison.
|
||
|
|
5. Reduces hidden state and duplicate decision paths.
|
||
|
|
6. Keeps PINK mechanically comparable to BLUE wherever the exchange model allows it.
|
||
|
|
|
||
|
|
This document does **not** change the signal math, thresholds, or TP/exit logic.
|
||
|
|
It only simplifies how those decisions move through the system and how they are recorded.
|
||
|
|
Where BingX semantics differ from BLUE's historical execution surface, the difference must be isolated behind the execution boundary rather than pushed into the engine.
|
||
|
|
|
||
|
|
## 2. Design Goals
|
||
|
|
|
||
|
|
The architecture must satisfy all of the following:
|
||
|
|
|
||
|
|
- Faithfulness to BLUE's original algorithm.
|
||
|
|
- Full observability of actions as:
|
||
|
|
- fired
|
||
|
|
- requested
|
||
|
|
- sent
|
||
|
|
- acknowledged
|
||
|
|
- executed
|
||
|
|
- reflected on BingX
|
||
|
|
- Minimal complexity.
|
||
|
|
- Maximum reuse of existing tables, maps, and record shapes.
|
||
|
|
- Clean comparability between BLUE and PINK.
|
||
|
|
- No second domain-level truth source.
|
||
|
|
|
||
|
|
## 3. Non-Goals
|
||
|
|
|
||
|
|
This spec does not:
|
||
|
|
|
||
|
|
- Change the trading signal formula.
|
||
|
|
- Change the TP value or exit semantics.
|
||
|
|
- Add a second live source of truth.
|
||
|
|
- Replace supervisor with a new process manager.
|
||
|
|
- Introduce a new order ledger when existing tables can be reused.
|
||
|
|
|
||
|
|
## 4. Core Principle
|
||
|
|
|
||
|
|
PINK must be exchange-led.
|
||
|
|
|
||
|
|
That means:
|
||
|
|
|
||
|
|
- BingX position state is authoritative for whether the slot is open.
|
||
|
|
- BingX open-order state is authoritative for whether an exit is pending.
|
||
|
|
- Account state is a projection of confirmed exchange events.
|
||
|
|
- Local engine state is a projection of exchange state plus decision metadata.
|
||
|
|
- ClickHouse is the durable audit trail.
|
||
|
|
- Hazelcast is the live control/state bus.
|
||
|
|
- The TUI is a derived view only.
|
||
|
|
|
||
|
|
If local state and BingX state disagree, the system must reconcile toward BingX.
|
||
|
|
|
||
|
|
BLUE comparability rule:
|
||
|
|
|
||
|
|
- The engine-side lifecycle, state names, and record shapes should remain BLUE-compatible unless BingX makes that impossible.
|
||
|
|
- Any unavoidable exchange-specific deviation must be isolated in the execution adapter and event normalization path.
|
||
|
|
- The engine itself should remain oblivious to BingX quirks except for the minimal authority rules needed to stay safe.
|
||
|
|
|
||
|
|
## 5. Minimal State Model
|
||
|
|
|
||
|
|
The system should keep only these live state categories:
|
||
|
|
|
||
|
|
- Decision state
|
||
|
|
- what the engine decided
|
||
|
|
- Order state
|
||
|
|
- what was requested and acknowledged
|
||
|
|
- Position state
|
||
|
|
- what BingX currently holds
|
||
|
|
- Account state
|
||
|
|
- capital, leverage, open notional
|
||
|
|
- Terminal trade state
|
||
|
|
- completed trades only
|
||
|
|
|
||
|
|
Everything else should be derived from those categories.
|
||
|
|
|
||
|
|
The simplification target is not "remove layers entirely".
|
||
|
|
It is "make the layers explicit and narrow":
|
||
|
|
|
||
|
|
```text
|
||
|
|
engine intent
|
||
|
|
-> execution facade
|
||
|
|
-> exchange adapter
|
||
|
|
-> exchange
|
||
|
|
-> event normalization
|
||
|
|
-> durable ledger
|
||
|
|
```
|
||
|
|
|
||
|
|
The `execution facade` is where BLUE-compatible semantics are preserved.
|
||
|
|
The `exchange adapter` is where BingX-specific request/response shapes live.
|
||
|
|
`event normalization` is a thin technical return channel inside the execution boundary:
|
||
|
|
|
||
|
|
- dedupe exchange callbacks
|
||
|
|
- normalize terminal states
|
||
|
|
- map exchange facts into canonical trade/account events
|
||
|
|
- update projections and durable rows
|
||
|
|
|
||
|
|
It is not a separate policy or trading layer.
|
||
|
|
|
||
|
|
This spec uses the following DITA split:
|
||
|
|
|
||
|
|
- `Decision`
|
||
|
|
- pure signal evaluation
|
||
|
|
- `Intent`
|
||
|
|
- candidate selection and sizing proposal
|
||
|
|
- `Trade`
|
||
|
|
- single-slot lifecycle state machine
|
||
|
|
- `Account`
|
||
|
|
- projection of confirmed execution facts
|
||
|
|
|
||
|
|
## 6. Existing Data Structures to Reuse
|
||
|
|
|
||
|
|
This spec reuses the current structures instead of introducing parallel ones.
|
||
|
|
|
||
|
|
### 6.1 ClickHouse tables
|
||
|
|
|
||
|
|
- `dolphin_pink.position_state`
|
||
|
|
- lifecycle source for open and closed trade status
|
||
|
|
- `dolphin_pink.trade_events`
|
||
|
|
- terminal ledger for completed trades
|
||
|
|
- `dolphin_pink.account_events`
|
||
|
|
- capital and exposure snapshots
|
||
|
|
- `dolphin_pink.v7_decision_events`
|
||
|
|
- decision trail
|
||
|
|
- `dolphin_pink.adaptive_exit_shadow`
|
||
|
|
- shadow-only exit analysis
|
||
|
|
|
||
|
|
### 6.2 Hazelcast maps
|
||
|
|
|
||
|
|
- `DOLPHIN_STATE_PINK`
|
||
|
|
- `DOLPHIN_PNL_PINK`
|
||
|
|
- `DOLPHIN_FEATURES`
|
||
|
|
- `DOLPHIN_SAFETY`
|
||
|
|
- `DOLPHIN_HEARTBEAT`
|
||
|
|
|
||
|
|
### 6.3 Exchange-side sources
|
||
|
|
|
||
|
|
- `user/positions`
|
||
|
|
- `trade/openOrders`
|
||
|
|
- `trade/allOrders`
|
||
|
|
- `trade/allFillOrders`
|
||
|
|
|
||
|
|
## 7. Authoritative Precedence
|
||
|
|
|
||
|
|
Live truth must be resolved in this order:
|
||
|
|
|
||
|
|
```text
|
||
|
|
BingX user/positions
|
||
|
|
↓
|
||
|
|
BingX trade/openOrders
|
||
|
|
↓
|
||
|
|
BingX journal snapshot
|
||
|
|
↓
|
||
|
|
ClickHouse account_events / position_state
|
||
|
|
↓
|
||
|
|
Hazelcast engine snapshot
|
||
|
|
↓
|
||
|
|
Supervisor log fallback
|
||
|
|
```
|
||
|
|
|
||
|
|
Rules:
|
||
|
|
|
||
|
|
- The first matching live BingX signal wins.
|
||
|
|
- Local snapshots may lag and must not override BingX.
|
||
|
|
- Log parsing is a last resort only.
|
||
|
|
|
||
|
|
For BLUE comparability:
|
||
|
|
|
||
|
|
- The adapter must emit the same semantic milestones BLUE would expose, even if the physical exchange response is different.
|
||
|
|
- If BingX cannot express a BLUE milestone exactly, preserve the closest semantic equivalent and annotate the deviation in the event payload.
|
||
|
|
|
||
|
|
## 8. High-Level Data Flow
|
||
|
|
|
||
|
|
```text
|
||
|
|
+------------------+
|
||
|
|
| Binance data |
|
||
|
|
| / HZ features |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+------------------+
|
||
|
|
| DolphinActor |
|
||
|
|
| (BLUE logic) |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+------------------+
|
||
|
|
| NDAlphaEngine |
|
||
|
|
| single slot only |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
decision / request
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+------------------+
|
||
|
|
| Execution facade |
|
||
|
|
| BLUE-compatible |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
exchange-specific request
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+------------------+
|
||
|
|
| BingXExecClient |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+------------------+
|
||
|
|
| BingX VST |
|
||
|
|
| positions/orders |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
poll / ack / fill / close
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+------------------+
|
||
|
|
| journal snapshot |
|
||
|
|
+---------+--------+
|
||
|
|
|
|
||
|
|
v
|
||
|
|
+----------------+----------------+
|
||
|
|
| ClickHouse + Hazelcast + TUI |
|
||
|
|
+---------------------------------+
|
||
|
|
```
|
||
|
|
|
||
|
|
## 9. Order Lifecycle
|
||
|
|
|
||
|
|
The system should treat every trade as a simple state machine.
|
||
|
|
|
||
|
|
```text
|
||
|
|
EMPTY
|
||
|
|
|
|
||
|
|
v
|
||
|
|
DECISION_CREATED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
ORDER_REQUESTED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
ORDER_SENT
|
||
|
|
|
|
||
|
|
v
|
||
|
|
ORDER_ACKNOWLEDGED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
POSITION_OPENED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
POSITION_UPDATED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
EXIT_REQUESTED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
EXIT_SENT
|
||
|
|
|
|
||
|
|
v
|
||
|
|
EXIT_ACKNOWLEDGED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
POSITION_CLOSED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
TRADE_TERMINAL_WRITTEN
|
||
|
|
|
|
||
|
|
v
|
||
|
|
EMPTY
|
||
|
|
```
|
||
|
|
|
||
|
|
Rules:
|
||
|
|
|
||
|
|
- A trade is not "closed" until BingX no longer reports the position.
|
||
|
|
- A terminal close row is not optional.
|
||
|
|
- The close row must be written after exchange-event normalization confirms terminality, not before.
|
||
|
|
|
||
|
|
## 10. Open / Update / Close Mechanics
|
||
|
|
|
||
|
|
### 10.1 Open
|
||
|
|
|
||
|
|
1. Engine produces a decision.
|
||
|
|
2. Actor converts it into an intent.
|
||
|
|
3. Execution facade normalizes the request into a BLUE-compatible action record.
|
||
|
|
4. Execution client submits the request to BingX.
|
||
|
|
5. BingX acknowledges or rejects.
|
||
|
|
6. BingX position becomes authoritative once open.
|
||
|
|
7. Event normalization updates `position_state` and account projections.
|
||
|
|
|
||
|
|
### 10.2 Update
|
||
|
|
|
||
|
|
1. Execution client polls `openOrders`.
|
||
|
|
2. Execution facade records the requested action.
|
||
|
|
3. Execution client polls `user/positions`.
|
||
|
|
4. Execution client refreshes account state.
|
||
|
|
5. Journal snapshot is persisted.
|
||
|
|
6. ClickHouse rows are appended.
|
||
|
|
7. Hazelcast state is refreshed.
|
||
|
|
8. TUI renders the derived result.
|
||
|
|
|
||
|
|
### 10.3 Close
|
||
|
|
|
||
|
|
1. Engine or exit manager requests exit.
|
||
|
|
2. Execution facade normalizes the exit into the same lifecycle that BLUE would represent.
|
||
|
|
3. Exit order is submitted reduce-only.
|
||
|
|
4. BingX confirms fill or terminal state.
|
||
|
|
5. Exchange position disappears.
|
||
|
|
6. Event normalization emits the terminal close fact.
|
||
|
|
7. `trade_events` close row is written.
|
||
|
|
8. `position_state` is updated to closed.
|
||
|
|
|
||
|
|
## 11. Reconciliation Model
|
||
|
|
|
||
|
|
In this spec, "reconciliation" is not a first-class domain layer.
|
||
|
|
It is the thin adapter-side return path that converts BingX facts into canonical events and projections.
|
||
|
|
|
||
|
|
The simplified model is:
|
||
|
|
|
||
|
|
```text
|
||
|
|
engine intent
|
||
|
|
-> exchange submission
|
||
|
|
-> exchange state
|
||
|
|
-> event normalization
|
||
|
|
-> durable ledger
|
||
|
|
```
|
||
|
|
|
||
|
|
Not:
|
||
|
|
|
||
|
|
```text
|
||
|
|
engine intent
|
||
|
|
-> local inferred close
|
||
|
|
-> maybe exchange close later
|
||
|
|
```
|
||
|
|
|
||
|
|
The second pattern is what creates ghost closes and confusing TUI state.
|
||
|
|
|
||
|
|
The return path must remain thin and mostly transparent:
|
||
|
|
|
||
|
|
- confirm what BingX actually did
|
||
|
|
- translate exchange reality into canonical engine state and durable ledger rows
|
||
|
|
- backfill only the minimum terminal bookkeeping needed to keep the audit trail complete
|
||
|
|
|
||
|
|
It must not:
|
||
|
|
|
||
|
|
- make trading decisions
|
||
|
|
- invent or reinterpret strategy state
|
||
|
|
- act as a second policy layer
|
||
|
|
- override engine intent except where required to reflect BingX authority
|
||
|
|
|
||
|
|
In other words:
|
||
|
|
|
||
|
|
```text
|
||
|
|
policy lives in the engine
|
||
|
|
translation lives in the execution boundary
|
||
|
|
truth lives on BingX
|
||
|
|
```
|
||
|
|
|
||
|
|
If the return path starts shaping strategy behavior, the architecture has drifted.
|
||
|
|
|
||
|
|
## 12. ClickHouse Accounting Contract
|
||
|
|
|
||
|
|
### 12.1 `account_events`
|
||
|
|
|
||
|
|
This table must represent the latest authoritative snapshot of:
|
||
|
|
|
||
|
|
- capital
|
||
|
|
- open positions
|
||
|
|
- open notional
|
||
|
|
- leverage
|
||
|
|
- fills metadata
|
||
|
|
|
||
|
|
It is not the source of truth for execution. It is the projection of confirmed execution facts and the best table for capital-path replay.
|
||
|
|
|
||
|
|
### 12.2 `position_state`
|
||
|
|
|
||
|
|
This table must represent per-trade lifecycle state.
|
||
|
|
|
||
|
|
Required lifecycle states:
|
||
|
|
|
||
|
|
- `OPEN`
|
||
|
|
- `EXIT_REQUESTED`
|
||
|
|
- `EXIT_ACKED`
|
||
|
|
- `CLOSED`
|
||
|
|
- `RECONCILED`
|
||
|
|
|
||
|
|
This table is the canonical lifecycle projection, not a second engine.
|
||
|
|
|
||
|
|
### 12.3 `trade_events`
|
||
|
|
|
||
|
|
This table must represent terminal closed trades only.
|
||
|
|
|
||
|
|
Rules:
|
||
|
|
|
||
|
|
- one terminal row per completed trade
|
||
|
|
- dedupe by `trade_id`
|
||
|
|
- never infer a close row from a fill snapshot alone
|
||
|
|
|
||
|
|
### 12.4 `status_snapshots`
|
||
|
|
|
||
|
|
When capital replay is needed, `status_snapshots` remains the preferred capital-path source because it captures:
|
||
|
|
|
||
|
|
- capital
|
||
|
|
- posture
|
||
|
|
- `trades_executed`
|
||
|
|
- `rm`
|
||
|
|
- `vol_ok`
|
||
|
|
- related snapshot state
|
||
|
|
|
||
|
|
`trade_events` alone is not enough for capital replay.
|
||
|
|
|
||
|
|
## 13. PINK and BLUE Comparison Rules
|
||
|
|
|
||
|
|
PINK must remain structurally comparable to BLUE.
|
||
|
|
|
||
|
|
That means:
|
||
|
|
|
||
|
|
- same trade identity model
|
||
|
|
- same key fields for open/close events
|
||
|
|
- same exit reason vocabulary
|
||
|
|
- same capital accounting semantics
|
||
|
|
- same bar and hold semantics
|
||
|
|
|
||
|
|
Namespace differences are allowed.
|
||
|
|
Semantic differences are not.
|
||
|
|
|
||
|
|
The DITA split must stay semantically compatible with BLUE:
|
||
|
|
|
||
|
|
- decision semantics preserved
|
||
|
|
- intent selection preserved
|
||
|
|
- trade lifecycle compatible
|
||
|
|
- account projection comparable
|
||
|
|
- return-channel normalization exchange-specific only
|
||
|
|
|
||
|
|
## 14. Simplification Rules
|
||
|
|
|
||
|
|
To reduce bugs, do the following:
|
||
|
|
|
||
|
|
### 14.1 Keep one authoritative open-slot view
|
||
|
|
|
||
|
|
Do not maintain competing local definitions of "open trade".
|
||
|
|
|
||
|
|
### 14.2 Stop inventing closed trades in the TUI
|
||
|
|
|
||
|
|
The TUI may display:
|
||
|
|
|
||
|
|
- open positions
|
||
|
|
- terminal trades
|
||
|
|
- fills
|
||
|
|
|
||
|
|
It must not convert fills into fake closes.
|
||
|
|
|
||
|
|
### 14.3 Remove recovery ambiguity
|
||
|
|
|
||
|
|
At startup:
|
||
|
|
|
||
|
|
- BingX positions are imported
|
||
|
|
- stale local slots are cleared
|
||
|
|
- journal state is restored only when it does not contradict BingX
|
||
|
|
- account projection is rebuilt from confirmed exchange facts, not from intent history
|
||
|
|
|
||
|
|
### 14.4 Keep the event trail append-only
|
||
|
|
|
||
|
|
If a state needs correction, emit a new event.
|
||
|
|
Do not rewrite history.
|
||
|
|
|
||
|
|
## 15. ASCII Failure Modes
|
||
|
|
|
||
|
|
### 15.1 Ghost close
|
||
|
|
|
||
|
|
```text
|
||
|
|
EXIT_REQUESTED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
EXIT_SENT
|
||
|
|
|
|
||
|
|
+--> local snapshot says CLOSED
|
||
|
|
|
|
||
|
|
+--> BingX still shows position OPEN
|
||
|
|
|
|
||
|
|
v
|
||
|
|
BUG: local UI looks flat, exchange is not flat
|
||
|
|
```
|
||
|
|
|
||
|
|
### 15.2 Missing terminal row
|
||
|
|
|
||
|
|
```text
|
||
|
|
EXIT_ACKNOWLEDGED
|
||
|
|
|
|
||
|
|
v
|
||
|
|
POSITION_CLOSED on BingX
|
||
|
|
|
|
||
|
|
v
|
||
|
|
trade_events row missing
|
||
|
|
|
|
||
|
|
v
|
||
|
|
BUG: replay/debug cannot prove the close
|
||
|
|
```
|
||
|
|
|
||
|
|
### 15.3 Duplicate ledger row
|
||
|
|
|
||
|
|
```text
|
||
|
|
trade_events insert
|
||
|
|
|
|
||
|
|
+--> duplicate insert for same trade_id
|
||
|
|
|
|
||
|
|
v
|
||
|
|
BUG: replay capital is overstated unless deduped
|
||
|
|
```
|
||
|
|
|
||
|
|
## 16. Acceptance Criteria
|
||
|
|
|
||
|
|
The simplification is acceptable only if all of the following hold:
|
||
|
|
|
||
|
|
1. BLUE algorithm behavior is preserved exactly.
|
||
|
|
2. PINK trades can be compared to BLUE trades using the same structures.
|
||
|
|
3. Every order action is visible in the trail.
|
||
|
|
4. Every close can be traced to BingX terminal state.
|
||
|
|
5. TUI never invents a close.
|
||
|
|
6. Capital replay can be reconstructed from `status_snapshots` plus deduped trade rows.
|
||
|
|
7. BingX remains the authoritative open-position source.
|
||
|
|
|
||
|
|
## 17. Implementation Boundaries
|
||
|
|
|
||
|
|
The following are the expected boundaries for any implementation work:
|
||
|
|
|
||
|
|
- Launcher layer
|
||
|
|
- namespace wiring only
|
||
|
|
- Actor layer
|
||
|
|
- engine-slot projection and adapter ingress
|
||
|
|
- Execution facade layer
|
||
|
|
- BLUE-compatible action normalization
|
||
|
|
- order lifecycle event emission
|
||
|
|
- BingX execution layer
|
||
|
|
- order submit / poll / reconcile / snapshot
|
||
|
|
- Journal layer
|
||
|
|
- durable bridge into ClickHouse
|
||
|
|
- Observability layer
|
||
|
|
- derived display only
|
||
|
|
|
||
|
|
The return path should be treated as a translation boundary, not a policy boundary.
|
||
|
|
Its ideal steady state is nearly invisible.
|
||
|
|
|
||
|
|
Any new BingX-specific behavior should go in the execution or adapter-ingress path, not in the engine decision logic.
|
||
|
|
|
||
|
|
## 18. Recommended Simplified Architecture
|
||
|
|
|
||
|
|
```text
|
||
|
|
[decision]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[intent]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[trade FSM]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[execution adapter]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[BingX order/position]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[event normalization]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[ClickHouse account + trade ledger]
|
||
|
|
|
|
||
|
|
v
|
||
|
|
[TUI / replay]
|
||
|
|
```
|
||
|
|
|
||
|
|
This is the simplest version that still preserves BLUE faithfulness and auditability.
|
||
|
|
|
||
|
|
## 19. Open Questions
|
||
|
|
|
||
|
|
These are implementation questions, not design blockers:
|
||
|
|
|
||
|
|
- Should PINK `trade_events` remain fully separate from BLUE-compatible schema, or only namespace-tagged?
|
||
|
|
- Should the TUI use `account_events` or `position_state` as the primary open-trade panel source?
|
||
|
|
- Should `position_state` become the canonical lifecycle table for all live strategies, or only PINK first?
|
||
|
|
- Should any exchange callback normalization be shared with BLUE, or remain PINK-only until parity is proven?
|
||
|
|
|
||
|
|
## 20. Final Decision
|
||
|
|
|
||
|
|
The target simplification is:
|
||
|
|
|
||
|
|
- one engine
|
||
|
|
- one exchange authority
|
||
|
|
- one append-only audit trail
|
||
|
|
- one derived TUI
|
||
|
|
- one replay path
|
||
|
|
|
||
|
|
Anything that introduces a second truth source should be removed or demoted.
|
||
|
|
|
||
|
|
Reconciliation, if the term is retained at all, should mean only the thin adapter-side normalization of BingX facts into canonical events and account projection. It should not exist as a policy layer.
|