@farazirfan/costar-server-executor 1.7.20 → 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,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