@farazirfan/costar-server-executor 1.7.19 → 1.7.21

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,150 @@
1
+ # Coinbase Order Types — Complete Reference
2
+
3
+ > Agent-editable. Update with patterns and quirks discovered from real trading.
4
+ > Last updated: Initial version
5
+
6
+ ## Order Configuration Keys
7
+
8
+ Every order uses `order_configuration` with exactly ONE of these keys:
9
+
10
+ ### Market Orders (Immediate Execution)
11
+
12
+ **`market_market_ioc`** — Market Immediate-or-Cancel (most common)
13
+ ```typescript
14
+ // Buy by dollar amount (quote currency)
15
+ order_configuration: {
16
+ market_market_ioc: { quote_size: '100.00' } // spend $100
17
+ }
18
+
19
+ // Sell by quantity (base currency)
20
+ order_configuration: {
21
+ market_market_ioc: { base_size: '0.5' } // sell 0.5 ETH
22
+ }
23
+ ```
24
+ - Use `quote_size` for BUY (how much USD to spend)
25
+ - Use `base_size` for SELL (how many units to sell)
26
+ - Can use `base_size` for BUY too (buy exact amount of asset)
27
+
28
+ ### Limit Orders
29
+
30
+ **`limit_limit_gtc`** — Good Till Cancelled
31
+ ```typescript
32
+ order_configuration: {
33
+ limit_limit_gtc: {
34
+ base_size: '0.001',
35
+ limit_price: '95000.00',
36
+ post_only: false, // true = maker only (lower fees)
37
+ }
38
+ }
39
+ ```
40
+
41
+ **`limit_limit_gtd`** — Good Till Date (expires)
42
+ ```typescript
43
+ order_configuration: {
44
+ limit_limit_gtd: {
45
+ base_size: '0.001',
46
+ limit_price: '95000.00',
47
+ end_time: '2026-03-01T00:00:00Z', // RFC3339
48
+ post_only: false,
49
+ }
50
+ }
51
+ ```
52
+
53
+ **`limit_limit_fok`** — Fill or Kill (all or nothing)
54
+ ```typescript
55
+ order_configuration: {
56
+ limit_limit_fok: {
57
+ base_size: '0.001',
58
+ limit_price: '95000.00',
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Stop-Limit Orders
64
+
65
+ **`stop_limit_stop_limit_gtc`** — Stop-Limit GTC
66
+ ```typescript
67
+ // Stop-loss sell: triggers when price drops to stop_price
68
+ order_configuration: {
69
+ stop_limit_stop_limit_gtc: {
70
+ base_size: '0.001',
71
+ limit_price: '93000.00', // limit order price after trigger
72
+ stop_price: '94000.00', // trigger price
73
+ stop_direction: 'STOP_DIRECTION_STOP_DOWN', // triggers when price goes DOWN
74
+ }
75
+ }
76
+
77
+ // Stop-buy: triggers when price rises to stop_price
78
+ order_configuration: {
79
+ stop_limit_stop_limit_gtc: {
80
+ base_size: '0.001',
81
+ limit_price: '101000.00',
82
+ stop_price: '100000.00',
83
+ stop_direction: 'STOP_DIRECTION_STOP_UP',
84
+ }
85
+ }
86
+ ```
87
+
88
+ **`stop_limit_stop_limit_gtd`** — Stop-Limit with expiry (same fields + `end_time`)
89
+
90
+ ### Bracket Orders (Entry + Take-Profit + Stop-Loss)
91
+
92
+ **`trigger_bracket_gtc`** — Bracket GTC
93
+ ```typescript
94
+ order_configuration: {
95
+ trigger_bracket_gtc: {
96
+ base_size: '0.001',
97
+ limit_price: '105000.00', // take-profit price
98
+ stop_trigger_price: '93000.00', // stop-loss trigger
99
+ }
100
+ }
101
+ ```
102
+
103
+ **`trigger_bracket_gtd`** — Bracket with expiry (same fields + `end_time`)
104
+
105
+ ### Smart Order Router
106
+
107
+ **`sor_limit_ioc`** — SOR Limit IOC (routes across venues for best price)
108
+ ```typescript
109
+ order_configuration: {
110
+ sor_limit_ioc: {
111
+ base_size: '0.001',
112
+ limit_price: '100000.00',
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## Stop Direction Values
118
+
119
+ | Value | Meaning | Use Case |
120
+ |-------|---------|----------|
121
+ | `STOP_DIRECTION_STOP_DOWN` | Trigger when price drops below stop | Stop-loss for long positions |
122
+ | `STOP_DIRECTION_STOP_UP` | Trigger when price rises above stop | Stop-loss for shorts, breakout buys |
123
+
124
+ ## Order Sides
125
+
126
+ | Side | Meaning |
127
+ |------|---------|
128
+ | `BUY` | Buy base currency, spend quote currency |
129
+ | `SELL` | Sell base currency, receive quote currency |
130
+
131
+ ## Order Statuses
132
+
133
+ | Status | Meaning |
134
+ |--------|---------|
135
+ | `PENDING` | Order received, not yet on book |
136
+ | `OPEN` | Active on order book |
137
+ | `FILLED` | Completely filled |
138
+ | `CANCELLED` | Cancelled by user or system |
139
+ | `EXPIRED` | GTD order expired |
140
+ | `FAILED` | Order rejected |
141
+ | `UNKNOWN_ORDER_STATUS` | Unknown |
142
+
143
+ ## Key Gotchas
144
+
145
+ 1. **All numeric values must be strings**: `"100.00"` not `100`
146
+ 2. **Market buys use `quote_size`** (dollar amount), **market sells use `base_size`** (quantity)
147
+ 3. **HTTP 200 doesn't mean success**: Always check `response.success === true`
148
+ 4. **Duplicate `client_order_id`**: Returns existing order, doesn't create new one
149
+ 5. **`post_only: true`**: Ensures you're a maker (lower fees) but order may be rejected if it would immediately fill
150
+ 6. **Minimum order sizes**: Vary by product. Check `base_min_size` in product details.
@@ -0,0 +1,93 @@
1
+ # Coinbase Trading Products
2
+
3
+ > Agent-editable. Add notes about products as you trade them.
4
+ > Last updated: Initial version
5
+
6
+ ## Product ID Format
7
+
8
+ Always `{BASE}-{QUOTE}`, e.g. `BTC-USD`, `ETH-USD`
9
+
10
+ ## Common Trading Pairs
11
+
12
+ ### Major Crypto (High Liquidity)
13
+
14
+ | Product ID | Base | Quote | Notes |
15
+ |-----------|------|-------|-------|
16
+ | `BTC-USD` | Bitcoin | USD | Most liquid, tightest spreads |
17
+ | `ETH-USD` | Ethereum | USD | Second most liquid |
18
+ | `SOL-USD` | Solana | USD | High volatility |
19
+ | `DOGE-USD` | Dogecoin | USD | Meme coin, volatile |
20
+ | `XRP-USD` | Ripple | USD | |
21
+ | `ADA-USD` | Cardano | USD | |
22
+ | `AVAX-USD` | Avalanche | USD | |
23
+ | `LINK-USD` | Chainlink | USD | |
24
+ | `DOT-USD` | Polkadot | USD | |
25
+ | `MATIC-USD` | Polygon | USD | |
26
+ | `UNI-USD` | Uniswap | USD | |
27
+ | `LTC-USD` | Litecoin | USD | |
28
+
29
+ ### Stablecoins
30
+
31
+ | Product ID | Base | Quote | Notes |
32
+ |-----------|------|-------|-------|
33
+ | `USDT-USD` | Tether | USD | |
34
+ | `BTC-USDT` | Bitcoin | Tether | |
35
+ | `ETH-USDT` | Ethereum | Tether | |
36
+
37
+ ### Crypto-to-Crypto
38
+
39
+ | Product ID | Base | Quote | Notes |
40
+ |-----------|------|-------|-------|
41
+ | `ETH-BTC` | Ethereum | Bitcoin | ETH/BTC ratio trading |
42
+ | `SOL-BTC` | Solana | Bitcoin | |
43
+
44
+ ## Discovering Products
45
+
46
+ Always verify product availability before trading:
47
+
48
+ ```typescript
49
+ // List all products
50
+ const products = await client.getProducts({});
51
+
52
+ // Filter for USD pairs
53
+ const usdPairs = products.products.filter(p => p.quote_currency_id === 'USD');
54
+
55
+ // Get specific product details
56
+ const btc = await client.getProduct({ product_id: 'BTC-USD' });
57
+ // Returns: price, volume_24h, price_percentage_change_24h,
58
+ // base_min_size, base_max_size, quote_min_size, quote_increment, etc.
59
+ ```
60
+
61
+ ## Key Product Fields
62
+
63
+ | Field | Description | Important For |
64
+ |-------|-------------|---------------|
65
+ | `price` | Current price | All orders |
66
+ | `base_min_size` | Minimum base order size | Validating order size |
67
+ | `base_max_size` | Maximum base order size | Validating order size |
68
+ | `quote_min_size` | Minimum quote order size | Market buy minimum |
69
+ | `quote_increment` | Price precision | Formatting limit prices |
70
+ | `base_increment` | Size precision | Formatting order sizes |
71
+ | `status` | Product trading status | Check before ordering |
72
+ | `trading_disabled` | Whether trading is halted | Check before ordering |
73
+ | `volume_24h` | 24-hour trading volume | Liquidity assessment |
74
+
75
+ ## Pre-Trade Checklist
76
+
77
+ Before placing any order on a product:
78
+
79
+ 1. **Verify product exists**: `getProduct({ product_id })`
80
+ 2. **Check `trading_disabled !== true`**
81
+ 3. **Check `status === 'online'`**
82
+ 4. **Verify order size >= `base_min_size`** (for base_size orders)
83
+ 5. **Verify order size >= `quote_min_size`** (for quote_size orders)
84
+ 6. **Round to correct precision** using `base_increment` / `quote_increment`
85
+
86
+ ## Product Notes from Trading
87
+
88
+ *(Add observations as you trade different pairs)*
89
+ <!--
90
+ - [DATE] PRODUCT: observation about spreads, liquidity, or behavior
91
+ Example:
92
+ - [2026-02-14] BTC-USD: Spreads widen significantly during weekends. Avoid large market orders Sat/Sun.
93
+ -->
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * Coinbase Trade Helper — CLI tool for common Coinbase operations.
4
+ * Agent can use this directly or create new scripts based on this pattern.
5
+ *
6
+ * Usage:
7
+ * npx tsx scripts/coinbase-trade.ts balances
8
+ * npx tsx scripts/coinbase-trade.ts price BTC-USD
9
+ * npx tsx scripts/coinbase-trade.ts preview buy BTC-USD 100
10
+ * npx tsx scripts/coinbase-trade.ts market-buy BTC-USD 100
11
+ * npx tsx scripts/coinbase-trade.ts market-sell BTC-USD 0.001
12
+ * npx tsx scripts/coinbase-trade.ts limit-buy BTC-USD 0.001 95000
13
+ * npx tsx scripts/coinbase-trade.ts limit-sell BTC-USD 0.001 105000
14
+ * npx tsx scripts/coinbase-trade.ts status <order-id>
15
+ * npx tsx scripts/coinbase-trade.ts cancel <order-id>
16
+ * npx tsx scripts/coinbase-trade.ts open-orders
17
+ * npx tsx scripts/coinbase-trade.ts products
18
+ * npx tsx scripts/coinbase-trade.ts fees
19
+ *
20
+ * Requires: COINBASE_API_KEY and COINBASE_API_SECRET env vars
21
+ * Install: npm install coinbase-api
22
+ */
23
+
24
+ import { CBAdvancedTradeClient } from 'coinbase-api';
25
+ import * as crypto from 'crypto';
26
+
27
+ // --- Init Client ---
28
+
29
+ const apiKey = process.env.COINBASE_API_KEY;
30
+ const apiSecret = process.env.COINBASE_API_SECRET;
31
+
32
+ if (!apiKey || !apiSecret) {
33
+ console.error('ERROR: COINBASE_API_KEY and COINBASE_API_SECRET must be set');
34
+ process.exit(1);
35
+ }
36
+
37
+ const client = new CBAdvancedTradeClient({
38
+ apiKey,
39
+ apiSecret,
40
+ });
41
+
42
+ // --- Commands ---
43
+
44
+ const [command, ...args] = process.argv.slice(2);
45
+
46
+ async function run() {
47
+ switch (command) {
48
+ case 'balances':
49
+ return showBalances();
50
+ case 'price':
51
+ return showPrice(args[0]);
52
+ case 'preview':
53
+ return previewOrder(args[0], args[1], args[2]);
54
+ case 'market-buy':
55
+ return marketBuy(args[0], args[1]);
56
+ case 'market-sell':
57
+ return marketSell(args[0], args[1]);
58
+ case 'limit-buy':
59
+ return limitBuy(args[0], args[1], args[2]);
60
+ case 'limit-sell':
61
+ return limitSell(args[0], args[1], args[2]);
62
+ case 'status':
63
+ return orderStatus(args[0]);
64
+ case 'cancel':
65
+ return cancelOrder(args[0]);
66
+ case 'open-orders':
67
+ return openOrders();
68
+ case 'products':
69
+ return listProducts();
70
+ case 'fees':
71
+ return showFees();
72
+ default:
73
+ console.log(`Unknown command: ${command}`);
74
+ console.log('Commands: balances, price, preview, market-buy, market-sell, limit-buy, limit-sell, status, cancel, open-orders, products, fees');
75
+ process.exit(1);
76
+ }
77
+ }
78
+
79
+ async function showBalances() {
80
+ const accounts = await client.getAccounts();
81
+ const nonZero = accounts.accounts.filter(
82
+ (a: any) => parseFloat(a.available_balance.value) > 0 || parseFloat(a.hold?.value || '0') > 0
83
+ );
84
+ console.log(JSON.stringify(nonZero.map((a: any) => ({
85
+ currency: a.currency,
86
+ available: a.available_balance.value,
87
+ hold: a.hold?.value || '0',
88
+ })), null, 2));
89
+ }
90
+
91
+ async function showPrice(productId: string) {
92
+ if (!productId) { console.error('Usage: price <product-id>'); process.exit(1); }
93
+ const product = await client.getProduct({ product_id: productId });
94
+ const spread = await client.getBestBidAsk({ product_ids: [productId] });
95
+ console.log(JSON.stringify({
96
+ product_id: productId,
97
+ price: product.price,
98
+ change_24h: product.price_percentage_change_24h + '%',
99
+ volume_24h: product.volume_24h,
100
+ bid: spread.pricebooks?.[0]?.bids?.[0]?.price,
101
+ ask: spread.pricebooks?.[0]?.asks?.[0]?.price,
102
+ base_min_size: product.base_min_size,
103
+ quote_min_size: product.quote_min_size,
104
+ }, null, 2));
105
+ }
106
+
107
+ async function previewOrder(side: string, productId: string, amount: string) {
108
+ if (!side || !productId || !amount) {
109
+ console.error('Usage: preview <buy|sell> <product-id> <amount>');
110
+ process.exit(1);
111
+ }
112
+ const isBuy = side.toUpperCase() === 'BUY';
113
+ const preview = await client.previewOrder({
114
+ product_id: productId,
115
+ side: isBuy ? 'BUY' : 'SELL',
116
+ order_configuration: {
117
+ market_market_ioc: isBuy
118
+ ? { quote_size: amount }
119
+ : { base_size: amount },
120
+ },
121
+ });
122
+ console.log(JSON.stringify(preview, null, 2));
123
+ }
124
+
125
+ async function marketBuy(productId: string, quoteSize: string) {
126
+ if (!productId || !quoteSize) {
127
+ console.error('Usage: market-buy <product-id> <usd-amount>');
128
+ process.exit(1);
129
+ }
130
+ const order = await client.submitOrder({
131
+ client_order_id: crypto.randomUUID(),
132
+ product_id: productId,
133
+ side: 'BUY',
134
+ order_configuration: {
135
+ market_market_ioc: { quote_size: quoteSize },
136
+ },
137
+ });
138
+ console.log(JSON.stringify(order, null, 2));
139
+ if (order.success) {
140
+ const status = await client.getOrder({
141
+ order_id: order.success_response.order_id,
142
+ });
143
+ console.log('\nFill details:');
144
+ console.log(JSON.stringify({
145
+ order_id: status.order.order_id,
146
+ status: status.order.status,
147
+ filled_size: status.order.filled_size,
148
+ filled_value: status.order.filled_value,
149
+ average_filled_price: status.order.average_filled_price,
150
+ total_fees: status.order.total_fees,
151
+ }, null, 2));
152
+ }
153
+ }
154
+
155
+ async function marketSell(productId: string, baseSize: string) {
156
+ if (!productId || !baseSize) {
157
+ console.error('Usage: market-sell <product-id> <base-amount>');
158
+ process.exit(1);
159
+ }
160
+ const order = await client.submitOrder({
161
+ client_order_id: crypto.randomUUID(),
162
+ product_id: productId,
163
+ side: 'SELL',
164
+ order_configuration: {
165
+ market_market_ioc: { base_size: baseSize },
166
+ },
167
+ });
168
+ console.log(JSON.stringify(order, null, 2));
169
+ if (order.success) {
170
+ const status = await client.getOrder({
171
+ order_id: order.success_response.order_id,
172
+ });
173
+ console.log('\nFill details:');
174
+ console.log(JSON.stringify({
175
+ order_id: status.order.order_id,
176
+ status: status.order.status,
177
+ filled_size: status.order.filled_size,
178
+ filled_value: status.order.filled_value,
179
+ average_filled_price: status.order.average_filled_price,
180
+ total_fees: status.order.total_fees,
181
+ }, null, 2));
182
+ }
183
+ }
184
+
185
+ async function limitBuy(productId: string, baseSize: string, limitPrice: string) {
186
+ if (!productId || !baseSize || !limitPrice) {
187
+ console.error('Usage: limit-buy <product-id> <base-size> <limit-price>');
188
+ process.exit(1);
189
+ }
190
+ const order = await client.submitOrder({
191
+ client_order_id: crypto.randomUUID(),
192
+ product_id: productId,
193
+ side: 'BUY',
194
+ order_configuration: {
195
+ limit_limit_gtc: {
196
+ base_size: baseSize,
197
+ limit_price: limitPrice,
198
+ post_only: false,
199
+ },
200
+ },
201
+ });
202
+ console.log(JSON.stringify(order, null, 2));
203
+ }
204
+
205
+ async function limitSell(productId: string, baseSize: string, limitPrice: string) {
206
+ if (!productId || !baseSize || !limitPrice) {
207
+ console.error('Usage: limit-sell <product-id> <base-size> <limit-price>');
208
+ process.exit(1);
209
+ }
210
+ const order = await client.submitOrder({
211
+ client_order_id: crypto.randomUUID(),
212
+ product_id: productId,
213
+ side: 'SELL',
214
+ order_configuration: {
215
+ limit_limit_gtc: {
216
+ base_size: baseSize,
217
+ limit_price: limitPrice,
218
+ post_only: false,
219
+ },
220
+ },
221
+ });
222
+ console.log(JSON.stringify(order, null, 2));
223
+ }
224
+
225
+ async function orderStatus(orderId: string) {
226
+ if (!orderId) { console.error('Usage: status <order-id>'); process.exit(1); }
227
+ const order = await client.getOrder({ order_id: orderId });
228
+ console.log(JSON.stringify(order, null, 2));
229
+ }
230
+
231
+ async function cancelOrder(orderId: string) {
232
+ if (!orderId) { console.error('Usage: cancel <order-id>'); process.exit(1); }
233
+ const result = await client.cancelOrders({ order_ids: [orderId] });
234
+ console.log(JSON.stringify(result, null, 2));
235
+ }
236
+
237
+ async function openOrders() {
238
+ const orders = await client.getOrders({ order_status: ['OPEN', 'PENDING'] });
239
+ console.log(JSON.stringify(orders.orders?.map((o: any) => ({
240
+ order_id: o.order_id,
241
+ product_id: o.product_id,
242
+ side: o.side,
243
+ status: o.status,
244
+ created_time: o.created_time,
245
+ order_configuration: o.order_configuration,
246
+ })) || [], null, 2));
247
+ }
248
+
249
+ async function listProducts() {
250
+ const products = await client.getProducts({});
251
+ const usdPairs = products.products
252
+ .filter((p: any) => p.quote_currency_id === 'USD' && !p.trading_disabled)
253
+ .sort((a: any, b: any) => parseFloat(b.volume_24h || '0') - parseFloat(a.volume_24h || '0'))
254
+ .slice(0, 30);
255
+ console.log(JSON.stringify(usdPairs.map((p: any) => ({
256
+ product_id: p.product_id,
257
+ price: p.price,
258
+ change_24h: p.price_percentage_change_24h + '%',
259
+ volume_24h: p.volume_24h,
260
+ base_min_size: p.base_min_size,
261
+ quote_min_size: p.quote_min_size,
262
+ })), null, 2));
263
+ }
264
+
265
+ async function showFees() {
266
+ const summary = await client.getTransactionSummary({});
267
+ console.log(JSON.stringify(summary, null, 2));
268
+ }
269
+
270
+ // --- Run ---
271
+ run().catch((err) => {
272
+ console.error('Error:', err.message || err);
273
+ process.exit(1);
274
+ });
@@ -54,7 +54,7 @@ Task Progress:
54
54
  - [ ] Step 5: Choose strategy based on regime + learnings
55
55
  - [ ] Step 6: Calculate position size and risk parameters
56
56
  - [ ] Step 7: Define entry, stop-loss, and take-profit
57
- - [ ] Step 8: Execute trade (present plan to user first)
57
+ - [ ] Step 8: Execute trade
58
58
  - [ ] Step 9: Monitor and manage position
59
59
  - [ ] Step 10: Log trade and UPDATE LEARNING.md
60
60
  ```
@@ -135,9 +135,7 @@ Every trade MUST have BEFORE entry:
135
135
 
136
136
  ### Step 8: Execute
137
137
 
138
- Present the trade plan to the user with: asset, direction, entry/stop/target, position size, dollar risk, R:R ratio, rationale, confidence level.
139
-
140
- **Always wait for user confirmation before executing.**
138
+ Execute the trade based on your analysis. Log the trade plan: asset, direction, entry/stop/target, position size, dollar risk, R:R ratio, rationale, confidence level.
141
139
 
142
140
  ### Step 9: Monitor
143
141