@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.
- package/dist/web-server.d.ts.map +1 -1
- package/dist/web-server.js +99 -0
- package/dist/web-server.js.map +1 -1
- package/package.json +1 -1
- package/public/index.html +203 -0
- package/skills/coinbase/LEARNING.md +117 -0
- package/skills/coinbase/SKILL.md +217 -0
- package/skills/coinbase/references/api-reference.md +124 -0
- package/skills/coinbase/references/order-types.md +150 -0
- package/skills/coinbase/references/products.md +93 -0
- package/skills/coinbase/scripts/coinbase-trade.ts +274 -0
- package/skills/trading/SKILL.md +2 -4
|
@@ -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
|
+
});
|
package/skills/trading/SKILL.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|