@farazirfan/costar-server-executor 1.7.28 → 1.7.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,201 @@
1
+ # OKX API Reference
2
+
3
+ > Agent-editable. Add notes and quirks as you discover them.
4
+ > Last updated: Initial version
5
+
6
+ ## SDK: okx-api (npm)
7
+
8
+ ```bash
9
+ npm install okx-api
10
+ ```
11
+
12
+ Three client classes:
13
+ - `RestClient` — REST API calls
14
+ - `WebsocketClient` — Event-driven streaming (tickers, candles, book, orders, positions)
15
+ - `WebsocketAPIClient` — Promise-based order placement over WebSocket
16
+
17
+ ## REST Client — Key Methods
18
+
19
+ ### Account & Balance
20
+
21
+ | Method | Description |
22
+ |--------|-------------|
23
+ | `client.getBalance()` | All currency balances (available, frozen, equity) |
24
+ | `client.getPositions()` | Open positions (margin/futures) |
25
+ | `client.getPositionsHistory()` | Closed positions history |
26
+ | `client.getAccountPositionRisk()` | Position risk details |
27
+ | `client.getAccountConfiguration()` | Account mode, level, position mode |
28
+ | `client.setLeverage(params)` | Set leverage for an instrument |
29
+ | `client.getLeverage(params)` | Get current leverage |
30
+ | `client.getMaxBuySellAmount(params)` | Max buy/sell for an instrument |
31
+ | `client.getMaxAvailableTradableAmount(params)` | Max available to trade |
32
+ | `client.getMaxWithdrawals()` | Max withdrawal amounts |
33
+ | `client.getFeeRates({ instType })` | Fee tier — maker/taker rates |
34
+ | `client.getAccountRateLimit()` | Current rate limit usage |
35
+
36
+ ### Market Data
37
+
38
+ | Method | Description |
39
+ |--------|-------------|
40
+ | `client.getTicker({ instId })` | Current price, volume, bid/ask |
41
+ | `client.getTickers({ instType })` | All tickers for an instrument type |
42
+ | `client.getOrderBook({ instId, sz })` | Order book depth (sz = levels) |
43
+ | `client.getCandles({ instId, bar, limit })` | OHLCV candlestick data |
44
+ | `client.getCandlesHistory({ instId, bar, limit })` | Historical candles |
45
+ | `client.getTrades({ instId, limit })` | Recent trades |
46
+ | `client.getTradesHistory({ instId })` | Historical trades |
47
+ | `client.get24hrTotalVolume()` | Platform-wide 24h volume |
48
+
49
+ ### Orders
50
+
51
+ | Method | Description |
52
+ |--------|-------------|
53
+ | `client.submitOrder(params)` | Place a single order |
54
+ | `client.submitMultipleOrders(params[])` | Place up to 20 orders at once |
55
+ | `client.cancelOrder(params)` | Cancel a single order |
56
+ | `client.cancelMultipleOrders(params[])` | Cancel multiple orders |
57
+ | `client.amendOrder(params)` | Modify an existing order |
58
+ | `client.amendMultipleOrders(params[])` | Modify multiple orders |
59
+ | `client.closePositions(params)` | Close an open position |
60
+ | `client.getOrderDetails({ instId, ordId })` | Get single order details |
61
+ | `client.getOrderList({ instType })` | Open/pending orders |
62
+ | `client.getOrderHistory({ instType })` | 7-day order history |
63
+ | `client.getOrderHistoryArchive({ instType })` | 3-month history |
64
+ | `client.getFills({ instType })` | Recent trade fills |
65
+ | `client.getFillsHistory({ instType })` | Historical fills |
66
+
67
+ ### Algo Orders
68
+
69
+ | Method | Description |
70
+ |--------|-------------|
71
+ | `client.placeAlgoOrder(params)` | Place TP/SL, trailing stop, trigger, iceberg, TWAP |
72
+ | `client.cancelAlgoOrder(params)` | Cancel algo order |
73
+ | `client.amendAlgoOrder(params)` | Modify algo order |
74
+ | `client.getAlgoOrderDetails(params)` | Algo order details |
75
+ | `client.getAlgoOrderList(params)` | Active algo orders |
76
+ | `client.getAlgoOrderHistory(params)` | Algo order history |
77
+
78
+ ### Public / Instrument Data
79
+
80
+ | Method | Description |
81
+ |--------|-------------|
82
+ | `client.getInstruments({ instType })` | List all instruments of a type |
83
+ | `client.getFundingRate({ instId })` | Current funding rate (perpetuals) |
84
+ | `client.getFundingRateHistory({ instId })` | Historical funding rates |
85
+ | `client.getMarkPrice({ instType })` | Mark prices |
86
+ | `client.getOpenInterest({ instType })` | Open interest data |
87
+ | `client.getExchangeRate()` | USD/CNY exchange rate |
88
+ | `client.getIndexTickers({ instId })` | Index tickers |
89
+
90
+ ### Asset Management
91
+
92
+ | Method | Description |
93
+ |--------|-------------|
94
+ | `client.getCurrencies()` | All supported currencies |
95
+ | `client.fundsTransfer(params)` | Transfer between accounts |
96
+ | `client.getDepositHistory()` | Deposit history |
97
+ | `client.getWithdrawalHistory()` | Withdrawal history |
98
+
99
+ ## Candlestick Bar Values
100
+
101
+ | Value | Period |
102
+ |-------|--------|
103
+ | `1m` | 1 minute |
104
+ | `3m` | 3 minutes |
105
+ | `5m` | 5 minutes |
106
+ | `15m` | 15 minutes |
107
+ | `30m` | 30 minutes |
108
+ | `1H` | 1 hour |
109
+ | `2H` | 2 hours |
110
+ | `4H` | 4 hours |
111
+ | `6H` | 6 hours |
112
+ | `12H` | 12 hours |
113
+ | `1D` | 1 day |
114
+ | `1W` | 1 week |
115
+ | `1M` | 1 month |
116
+
117
+ ## Response Format
118
+
119
+ OKX REST API wraps all responses:
120
+ ```json
121
+ {
122
+ "code": "0",
123
+ "msg": "",
124
+ "data": [...]
125
+ }
126
+ ```
127
+
128
+ The `okx-api` package unwraps this — methods return the `data` array directly. On failure, it throws the full error response.
129
+
130
+ For order submission, check `response[0].sCode`:
131
+ ```typescript
132
+ const result = await client.submitOrder({...});
133
+ if (result[0].sCode === '0') {
134
+ // Success — result[0].ordId has the order ID
135
+ } else {
136
+ // Failed — result[0].sCode is error code, result[0].sMsg is message
137
+ }
138
+ ```
139
+
140
+ ## Common Error Codes
141
+
142
+ | sCode | Meaning | Fix |
143
+ |-------|---------|-----|
144
+ | `0` | Success | — |
145
+ | `51000` | Parameter error | Check required params |
146
+ | `51001` | Instrument ID doesn't exist | Verify instId |
147
+ | `51004` | Insufficient balance | Check available balance |
148
+ | `51008` | Order placement not allowed | Check account mode/permissions |
149
+ | `51010` | Order size below minimum | Check instrument minimum |
150
+ | `51020` | Order count exceeds limit | Reduce concurrent orders |
151
+ | `51100` | Margin account issue | Check margin settings |
152
+ | `51400` | Position doesn't exist | Verify position before closing |
153
+
154
+ ## Rate Limits
155
+
156
+ | Category | Limit |
157
+ |----------|-------|
158
+ | Order placement | 60 requests/2s per instrument |
159
+ | Batch orders | 300 orders/2s |
160
+ | Order cancel | 60 requests/2s per instrument |
161
+ | Market data | 20 requests/2s |
162
+ | Account data | 10 requests/2s |
163
+
164
+ Rate limits are per-instrument for trading endpoints. Use `getAccountRateLimit()` to check current usage.
165
+
166
+ ## WebSocket Channels
167
+
168
+ ### Public (no auth)
169
+
170
+ | Channel | Description |
171
+ |---------|-------------|
172
+ | `tickers` | Real-time price/volume |
173
+ | `candle1m`, `candle5m`, `candle1H`, etc. | Candlestick updates |
174
+ | `books`, `books5`, `books50-l2` | Order book depth |
175
+ | `trades` | Real-time trades |
176
+ | `funding-rate` | Funding rate updates |
177
+ | `mark-price` | Mark price updates |
178
+ | `open-interest` | Open interest |
179
+ | `instruments` | Instrument changes |
180
+ | `liquidation-orders` | Liquidation events |
181
+
182
+ ### Private (auth required)
183
+
184
+ | Channel | Description |
185
+ |---------|-------------|
186
+ | `account` | Balance updates |
187
+ | `positions` | Position changes |
188
+ | `balance_and_position` | Combined balance + position |
189
+ | `orders` | Order status changes |
190
+ | `orders-algo` | Algo order updates |
191
+ | `liquidation-warning` | Liquidation warnings |
192
+
193
+ ## Multi-Region Support
194
+
195
+ ```typescript
196
+ // Global (default)
197
+ const client = new RestClient({ apiKey, apiSecret, apiPass });
198
+
199
+ // European Economic Area
200
+ const client = new RestClient({ apiKey, apiSecret, apiPass, market: 'EEA' });
201
+ ```
@@ -0,0 +1,251 @@
1
+ # OKX Order Types — Complete Reference
2
+
3
+ > Agent-editable. Update with patterns and quirks discovered from real trading.
4
+ > Last updated: Initial version
5
+
6
+ ## Core Order Parameters
7
+
8
+ Every order requires these fields:
9
+
10
+ | Parameter | Type | Description |
11
+ |-----------|------|-------------|
12
+ | `instId` | string | Instrument ID (e.g., `'BTC-USDT'`) |
13
+ | `tdMode` | string | Trade mode: `'cash'`, `'cross'`, `'isolated'` |
14
+ | `side` | string | `'buy'` or `'sell'` |
15
+ | `ordType` | string | Order type (see below) |
16
+ | `sz` | string | Size/quantity |
17
+
18
+ ## Trade Modes
19
+
20
+ | Mode | Description | Use Case |
21
+ |------|-------------|----------|
22
+ | `cash` | Spot trading, no leverage | Simple buy/sell |
23
+ | `cross` | Cross margin — all balance as collateral | Futures, margin trading |
24
+ | `isolated` | Isolated margin — set per position | Risk-limited margin positions |
25
+
26
+ ## Order Types
27
+
28
+ ### Market Orders
29
+
30
+ ```typescript
31
+ // Market buy — spend 100 USDT
32
+ await client.submitOrder({
33
+ instId: 'BTC-USDT',
34
+ tdMode: 'cash',
35
+ side: 'buy',
36
+ ordType: 'market',
37
+ sz: '100',
38
+ tgtCcy: 'quote_ccy', // sz is in USDT
39
+ });
40
+
41
+ // Market buy — buy exactly 0.001 BTC
42
+ await client.submitOrder({
43
+ instId: 'BTC-USDT',
44
+ tdMode: 'cash',
45
+ side: 'buy',
46
+ ordType: 'market',
47
+ sz: '0.001',
48
+ tgtCcy: 'base_ccy', // sz is in BTC
49
+ });
50
+
51
+ // Market sell — sell 0.001 BTC
52
+ await client.submitOrder({
53
+ instId: 'BTC-USDT',
54
+ tdMode: 'cash',
55
+ side: 'sell',
56
+ ordType: 'market',
57
+ sz: '0.001',
58
+ });
59
+ ```
60
+
61
+ - `tgtCcy: 'quote_ccy'` — size is in quote currency (USDT). Use for "spend X dollars" buys.
62
+ - `tgtCcy: 'base_ccy'` — size is in base currency (BTC). Use for exact quantity.
63
+ - For sells, `tgtCcy` defaults to `base_ccy`.
64
+
65
+ ### Limit Orders
66
+
67
+ ```typescript
68
+ // Limit buy
69
+ await client.submitOrder({
70
+ instId: 'BTC-USDT',
71
+ tdMode: 'cash',
72
+ side: 'buy',
73
+ ordType: 'limit',
74
+ sz: '0.001',
75
+ px: '95000',
76
+ });
77
+
78
+ // Post-only limit (maker only — lower fees)
79
+ await client.submitOrder({
80
+ instId: 'BTC-USDT',
81
+ tdMode: 'cash',
82
+ side: 'buy',
83
+ ordType: 'post_only',
84
+ sz: '0.001',
85
+ px: '95000',
86
+ });
87
+ ```
88
+
89
+ ### Fill-or-Kill / Immediate-or-Cancel
90
+
91
+ ```typescript
92
+ // FOK — fill entire order or cancel
93
+ await client.submitOrder({
94
+ instId: 'BTC-USDT',
95
+ tdMode: 'cash',
96
+ side: 'buy',
97
+ ordType: 'fok',
98
+ sz: '0.001',
99
+ px: '100000',
100
+ });
101
+
102
+ // IOC — fill what you can, cancel the rest
103
+ await client.submitOrder({
104
+ instId: 'BTC-USDT',
105
+ tdMode: 'cash',
106
+ side: 'buy',
107
+ ordType: 'ioc',
108
+ sz: '0.001',
109
+ px: '100000',
110
+ });
111
+
112
+ // Optimal limit IOC — best available price
113
+ await client.submitOrder({
114
+ instId: 'BTC-USDT',
115
+ tdMode: 'cash',
116
+ side: 'buy',
117
+ ordType: 'optimal_limit_ioc',
118
+ sz: '0.001',
119
+ });
120
+ ```
121
+
122
+ ## Algo Orders (TP/SL, Trailing Stop, Trigger)
123
+
124
+ Algo orders use `placeAlgoOrder()` instead of `submitOrder()`.
125
+
126
+ ### Take-Profit / Stop-Loss (OCO)
127
+
128
+ ```typescript
129
+ // TP at 105k, SL at 93k (market execution on trigger)
130
+ await client.placeAlgoOrder({
131
+ instId: 'BTC-USDT',
132
+ tdMode: 'cash',
133
+ side: 'sell',
134
+ ordType: 'oco',
135
+ sz: '0.001',
136
+ tpTriggerPx: '105000',
137
+ tpOrdPx: '-1', // -1 = market price at trigger
138
+ slTriggerPx: '93000',
139
+ slOrdPx: '-1',
140
+ });
141
+ ```
142
+
143
+ ### Take-Profit Only
144
+
145
+ ```typescript
146
+ await client.placeAlgoOrder({
147
+ instId: 'BTC-USDT',
148
+ tdMode: 'cash',
149
+ side: 'sell',
150
+ ordType: 'conditional',
151
+ sz: '0.001',
152
+ tpTriggerPx: '105000',
153
+ tpOrdPx: '-1',
154
+ });
155
+ ```
156
+
157
+ ### Stop-Loss Only
158
+
159
+ ```typescript
160
+ await client.placeAlgoOrder({
161
+ instId: 'BTC-USDT',
162
+ tdMode: 'cash',
163
+ side: 'sell',
164
+ ordType: 'conditional',
165
+ sz: '0.001',
166
+ slTriggerPx: '93000',
167
+ slOrdPx: '-1',
168
+ });
169
+ ```
170
+
171
+ ### Trigger Order (Stop Order)
172
+
173
+ ```typescript
174
+ await client.placeAlgoOrder({
175
+ instId: 'BTC-USDT',
176
+ tdMode: 'cash',
177
+ side: 'buy',
178
+ ordType: 'trigger',
179
+ sz: '0.001',
180
+ triggerPx: '100000',
181
+ orderPx: '-1', // -1 = market, or set limit price
182
+ triggerPxType: 'last', // 'last', 'index', or 'mark'
183
+ });
184
+ ```
185
+
186
+ ### Trailing Stop
187
+
188
+ ```typescript
189
+ await client.placeAlgoOrder({
190
+ instId: 'BTC-USDT',
191
+ tdMode: 'cash',
192
+ side: 'sell',
193
+ ordType: 'move_order_stop',
194
+ sz: '0.001',
195
+ callbackRatio: '0.05', // 5% trailing distance
196
+ // or callbackSpread: '500' for fixed $ distance
197
+ activePx: '100000', // activation price (optional)
198
+ });
199
+ ```
200
+
201
+ ## Order States
202
+
203
+ | State | Meaning |
204
+ |-------|---------|
205
+ | `live` | Active on order book |
206
+ | `partially_filled` | Partially executed |
207
+ | `filled` | Completely executed |
208
+ | `canceled` | Cancelled |
209
+ | `mmp_canceled` | Market maker protection cancelled |
210
+
211
+ ## Response Handling
212
+
213
+ ```typescript
214
+ const result = await client.submitOrder({...});
215
+
216
+ // result is an array — check first element
217
+ if (result[0].sCode === '0') {
218
+ console.log(`Order placed: ${result[0].ordId}`);
219
+
220
+ // Get full order details
221
+ const details = await client.getOrderDetails({
222
+ instId: 'BTC-USDT',
223
+ ordId: result[0].ordId,
224
+ });
225
+ console.log(`State: ${details[0].state}, Filled: ${details[0].fillSz} @ ${details[0].avgPx}`);
226
+ } else {
227
+ console.error(`Failed: [${result[0].sCode}] ${result[0].sMsg}`);
228
+ }
229
+ ```
230
+
231
+ ## Batch Orders (Up to 20)
232
+
233
+ ```typescript
234
+ const results = await client.submitMultipleOrders([
235
+ { instId: 'BTC-USDT', tdMode: 'cash', side: 'buy', ordType: 'limit', sz: '0.001', px: '94000' },
236
+ { instId: 'BTC-USDT', tdMode: 'cash', side: 'buy', ordType: 'limit', sz: '0.001', px: '93000' },
237
+ { instId: 'ETH-USDT', tdMode: 'cash', side: 'buy', ordType: 'limit', sz: '0.01', px: '3000' },
238
+ ]);
239
+ // Each result[i] has its own sCode/sMsg
240
+ ```
241
+
242
+ ## Key Gotchas
243
+
244
+ 1. **All values are strings**: `'100'` not `100`
245
+ 2. **`tgtCcy` matters for market buys**: `'quote_ccy'` = spend X USDT, `'base_ccy'` = buy X BTC
246
+ 3. **Check `sCode === '0'`**: Non-zero means failure, even if no exception thrown
247
+ 4. **`tdMode` is always required**: `'cash'` for spot, `'cross'`/`'isolated'` for margin
248
+ 5. **OKX uses USDT pairs**: `BTC-USDT` not `BTC-USD`
249
+ 6. **Algo orders use `placeAlgoOrder()`**: NOT `submitOrder()`
250
+ 7. **`-1` as price**: Means market execution for algo order trigger prices
251
+ 8. **Batch limit**: Up to 20 orders per batch request
@@ -0,0 +1,128 @@
1
+ # OKX Trading Products
2
+
3
+ > Agent-editable. Add notes about products as you trade them.
4
+ > Last updated: Initial version
5
+
6
+ ## Instrument ID Format
7
+
8
+ - Spot: `{BASE}-{QUOTE}` → `BTC-USDT`, `ETH-USDT`
9
+ - Perpetual swap: `{BASE}-{QUOTE}-SWAP` → `BTC-USDT-SWAP`
10
+ - Futures: `{BASE}-{QUOTE}-{EXPIRY}` → `BTC-USDT-250328`
11
+ - Options: `{BASE}-{QUOTE}-{EXPIRY}-{STRIKE}-{C/P}` → `BTC-USD-250328-100000-C`
12
+
13
+ ## Instrument Types
14
+
15
+ | instType | Description |
16
+ |----------|-------------|
17
+ | `SPOT` | Spot trading |
18
+ | `MARGIN` | Margin trading |
19
+ | `SWAP` | Perpetual swaps |
20
+ | `FUTURES` | Delivery futures |
21
+ | `OPTION` | Options |
22
+
23
+ ## Common Spot Pairs (High Liquidity)
24
+
25
+ | Instrument ID | Base | Quote | Notes |
26
+ |---------------|------|-------|-------|
27
+ | `BTC-USDT` | Bitcoin | USDT | Most liquid on OKX |
28
+ | `ETH-USDT` | Ethereum | USDT | Second most liquid |
29
+ | `SOL-USDT` | Solana | USDT | High volatility |
30
+ | `DOGE-USDT` | Dogecoin | USDT | |
31
+ | `XRP-USDT` | Ripple | USDT | |
32
+ | `ADA-USDT` | Cardano | USDT | |
33
+ | `AVAX-USDT` | Avalanche | USDT | |
34
+ | `LINK-USDT` | Chainlink | USDT | |
35
+ | `DOT-USDT` | Polkadot | USDT | |
36
+ | `MATIC-USDT` | Polygon | USDT | |
37
+ | `UNI-USDT` | Uniswap | USDT | |
38
+ | `LTC-USDT` | Litecoin | USDT | |
39
+ | `OP-USDT` | Optimism | USDT | |
40
+ | `ARB-USDT` | Arbitrum | USDT | |
41
+ | `PEPE-USDT` | Pepe | USDT | Meme coin |
42
+ | `WIF-USDT` | dogwifhat | USDT | Meme coin |
43
+
44
+ ### BTC Pairs
45
+
46
+ | Instrument ID | Notes |
47
+ |---------------|-------|
48
+ | `ETH-BTC` | ETH/BTC ratio |
49
+ | `SOL-BTC` | SOL/BTC ratio |
50
+
51
+ ### USDC Pairs
52
+
53
+ | Instrument ID | Notes |
54
+ |---------------|-------|
55
+ | `BTC-USDC` | BTC against USDC |
56
+ | `ETH-USDC` | ETH against USDC |
57
+
58
+ ## Common Perpetual Swaps
59
+
60
+ | Instrument ID | Notes |
61
+ |---------------|-------|
62
+ | `BTC-USDT-SWAP` | BTC perpetual (USDT settled) |
63
+ | `ETH-USDT-SWAP` | ETH perpetual (USDT settled) |
64
+ | `SOL-USDT-SWAP` | SOL perpetual |
65
+ | `BTC-USD-SWAP` | BTC perpetual (coin-margined) |
66
+
67
+ ## Discovering Instruments
68
+
69
+ Always verify instrument availability before trading:
70
+
71
+ ```typescript
72
+ // List all spot instruments
73
+ const instruments = await client.getInstruments({ instType: 'SPOT' });
74
+
75
+ // Filter for USDT pairs
76
+ const usdtPairs = instruments.filter(i => i.quoteCcy === 'USDT' && i.state === 'live');
77
+
78
+ // Get specific instrument details
79
+ const btcUsdt = instruments.find(i => i.instId === 'BTC-USDT');
80
+ // Returns: lotSz, minSz, tickSz, state, etc.
81
+ ```
82
+
83
+ ## Key Instrument Fields
84
+
85
+ | Field | Description | Important For |
86
+ |-------|-------------|---------------|
87
+ | `instId` | Instrument ID | Order placement |
88
+ | `minSz` | Minimum order size | Validating order size |
89
+ | `lotSz` | Size increment / lot size | Rounding order size |
90
+ | `tickSz` | Price tick size | Rounding limit prices |
91
+ | `state` | `live`, `suspend`, `preopen` | Check before ordering |
92
+ | `quoteCcy` | Quote currency | Identifying pair type |
93
+ | `baseCcy` | Base currency | Identifying pair type |
94
+ | `ctVal` | Contract value (derivatives) | Calculating position size |
95
+ | `lever` | Max leverage | Margin trading limits |
96
+
97
+ ## Pre-Trade Checklist
98
+
99
+ Before placing any order on an instrument:
100
+
101
+ 1. **Verify instrument exists**: `getInstruments({ instType: 'SPOT' })` and find it
102
+ 2. **Check `state === 'live'`** — suspended instruments can't be traded
103
+ 3. **Verify order size >= `minSz`**
104
+ 4. **Round size to `lotSz` precision** — OKX rejects orders with wrong precision
105
+ 5. **Round price to `tickSz` precision** — same for limit prices
106
+ 6. **For perpetuals**: check funding rate and open interest before entry
107
+
108
+ ## OKX vs Coinbase — Key Differences
109
+
110
+ | Aspect | OKX | Coinbase |
111
+ |--------|-----|----------|
112
+ | Quote currency | USDT (mostly) | USD |
113
+ | Instrument format | `BTC-USDT` | `BTC-USD` |
114
+ | Perpetuals | Yes (`BTC-USDT-SWAP`) | No |
115
+ | Options | Yes | No |
116
+ | Margin trading | Yes (cross/isolated) | Limited |
117
+ | Fees | Lower (maker ~0.08%, taker ~0.1%) | Higher (maker ~0.4%, taker ~0.6%) |
118
+ | Algo orders | TP/SL, trailing, trigger, iceberg, TWAP | Stop-limit, bracket |
119
+ | Batch orders | Up to 20 | No |
120
+
121
+ ## Product Notes from Trading
122
+
123
+ *(Add observations as you trade different pairs)*
124
+ <!--
125
+ - [DATE] INSTRUMENT: observation about spreads, liquidity, or behavior
126
+ Example:
127
+ - [2026-02-18] BTC-USDT: Excellent liquidity, tight spreads even during high vol.
128
+ -->