prab-cli 1.2.5 → 1.2.7

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,571 @@
1
+ "use strict";
2
+ /**
3
+ * Trading Signal API Server
4
+ * REST API for crypto trading strategies
5
+ *
6
+ * Free deployment options:
7
+ * - Railway.app (free tier)
8
+ * - Render.com (free tier)
9
+ * - Vercel (serverless)
10
+ * - Fly.io (free tier)
11
+ * - Local: node dist/server/index.js
12
+ */
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Suppress ora spinners in server mode
18
+ process.env.CI = "true";
19
+ const express_1 = __importDefault(require("express"));
20
+ const cors_1 = __importDefault(require("cors"));
21
+ const crypto_1 = require("../lib/crypto");
22
+ const strategy_engine_1 = require("../lib/crypto/strategy-engine");
23
+ const market_analyzer_1 = require("../lib/crypto/market-analyzer");
24
+ const orderblock_strategy_1 = require("../lib/crypto/orderblock-strategy");
25
+ const ict_strategy_1 = require("../lib/crypto/ict-strategy");
26
+ const strategy_1 = require("../lib/crypto/strategy");
27
+ const app = (0, express_1.default)();
28
+ const PORT = process.env.PORT || 3000;
29
+ // CORS Configuration for Vercel
30
+ const corsOptions = {
31
+ origin: "*",
32
+ methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
33
+ allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "Accept"],
34
+ credentials: false,
35
+ };
36
+ // Middleware
37
+ app.use((0, cors_1.default)(corsOptions));
38
+ app.use(express_1.default.json());
39
+ // Handle preflight OPTIONS requests
40
+ app.options("*", (0, cors_1.default)(corsOptions));
41
+ // Manual CORS headers for all responses (backup for serverless)
42
+ app.use((req, res, next) => {
43
+ res.header("Access-Control-Allow-Origin", "*");
44
+ res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
45
+ res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With, Accept");
46
+ if (req.method === "OPTIONS") {
47
+ return res.sendStatus(200);
48
+ }
49
+ next();
50
+ });
51
+ // Request logging
52
+ app.use((req, res, next) => {
53
+ console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
54
+ next();
55
+ });
56
+ // ============================================
57
+ // HEALTH CHECK
58
+ // ============================================
59
+ app.get("/", (req, res) => {
60
+ res.json({
61
+ name: "Crypto Trading Signal API",
62
+ version: "1.0.0",
63
+ status: "running",
64
+ endpoints: {
65
+ signal: "GET /api/signal/:symbol",
66
+ analyze: "GET /api/analyze/:symbol",
67
+ smc: "GET /api/smc/:symbol",
68
+ orderblock: "GET /api/orderblock/:symbol",
69
+ ict: "GET /api/ict/:symbol",
70
+ smart: "GET /api/smart/:symbol - Smart Trend Confluence Strategy",
71
+ strategy: "GET /api/strategy/:symbol",
72
+ price: "GET /api/price/:symbol",
73
+ },
74
+ documentation: "https://github.com/your-repo/trading-api",
75
+ });
76
+ });
77
+ app.get("/health", (req, res) => {
78
+ res.json({ status: "healthy", timestamp: Date.now() });
79
+ });
80
+ // ============================================
81
+ // TRADING SIGNAL ENDPOINTS
82
+ // ============================================
83
+ /**
84
+ * Quick Trading Signal
85
+ * GET /api/signal/:symbol?interval=1h
86
+ */
87
+ app.get("/api/signal/:symbol", async (req, res) => {
88
+ try {
89
+ const { symbol } = req.params;
90
+ const interval = req.query.interval || "1h";
91
+ // Fetch data and generate signal directly (avoid ora spinner issues)
92
+ const data = await (0, crypto_1.fetchCryptoData)(symbol, interval, 250);
93
+ const signal = (0, crypto_1.generateSignal)(data);
94
+ res.json({
95
+ success: true,
96
+ data: {
97
+ symbol: data.symbol,
98
+ price: data.currentPrice,
99
+ priceChange24h: data.priceChangePercent24h,
100
+ signal: signal.signal,
101
+ confidence: signal.confidence,
102
+ stopLoss: signal.stopLoss,
103
+ takeProfit: signal.takeProfit,
104
+ indicators: signal.indicators,
105
+ reasoning: signal.reasoning,
106
+ },
107
+ timestamp: Date.now(),
108
+ });
109
+ }
110
+ catch (error) {
111
+ console.error(`Signal error for ${req.params.symbol}:`, error.message);
112
+ res.status(500).json({
113
+ success: false,
114
+ error: error.message || "Internal server error",
115
+ symbol: req.params.symbol,
116
+ });
117
+ }
118
+ });
119
+ /**
120
+ * Comprehensive Market Analysis
121
+ * GET /api/analyze/:symbol
122
+ */
123
+ app.get("/api/analyze/:symbol", async (req, res) => {
124
+ try {
125
+ const { symbol } = req.params;
126
+ const analysis = await (0, market_analyzer_1.analyzeMarket)(symbol);
127
+ res.json({
128
+ success: true,
129
+ data: {
130
+ symbol: analysis.symbol,
131
+ currentPrice: analysis.currentPrice,
132
+ priceChange24h: analysis.priceChange24h,
133
+ recommendation: analysis.recommendation,
134
+ confidence: analysis.confidence,
135
+ riskLevel: analysis.riskLevel,
136
+ timeframes: analysis.timeframes,
137
+ timeframeAlignment: analysis.timeframeAlignment,
138
+ indicators: analysis.indicators,
139
+ timing: analysis.timing,
140
+ tradeSetup: analysis.tradeSetup,
141
+ marketCondition: analysis.marketCondition,
142
+ reasoning: analysis.reasoning,
143
+ },
144
+ timestamp: Date.now(),
145
+ });
146
+ }
147
+ catch (error) {
148
+ res.status(500).json({
149
+ success: false,
150
+ error: error.message || "Internal server error",
151
+ });
152
+ }
153
+ });
154
+ /**
155
+ * Smart Money Concepts Analysis
156
+ * GET /api/smc/:symbol?interval=4h
157
+ */
158
+ app.get("/api/smc/:symbol", async (req, res) => {
159
+ try {
160
+ const { symbol } = req.params;
161
+ const interval = req.query.interval || "4h";
162
+ const data = await (0, crypto_1.fetchCryptoData)(symbol, interval, 200);
163
+ const smc = (0, crypto_1.analyzeSMC)(data.candles);
164
+ res.json({
165
+ success: true,
166
+ data: {
167
+ symbol: data.symbol,
168
+ currentPrice: data.currentPrice,
169
+ priceChange24h: data.priceChangePercent24h,
170
+ marketStructure: smc.marketStructure,
171
+ orderBlocks: {
172
+ bullish: smc.orderBlocks.bullish,
173
+ bearish: smc.orderBlocks.bearish,
174
+ nearest: smc.orderBlocks.nearest,
175
+ },
176
+ fairValueGaps: {
177
+ bullish: smc.fairValueGaps.bullish,
178
+ bearish: smc.fairValueGaps.bearish,
179
+ unfilled: smc.fairValueGaps.unfilled,
180
+ },
181
+ liquidity: smc.liquidity,
182
+ premiumDiscount: smc.premiumDiscount,
183
+ bias: smc.bias,
184
+ },
185
+ timestamp: Date.now(),
186
+ });
187
+ }
188
+ catch (error) {
189
+ res.status(500).json({
190
+ success: false,
191
+ error: error.message || "Internal server error",
192
+ });
193
+ }
194
+ });
195
+ /**
196
+ * Order Block Strategy
197
+ * GET /api/orderblock/:symbol?interval=4h
198
+ */
199
+ app.get("/api/orderblock/:symbol", async (req, res) => {
200
+ try {
201
+ const { symbol } = req.params;
202
+ const interval = req.query.interval || "4h";
203
+ const result = await (0, orderblock_strategy_1.generateOrderBlockSignal)(symbol, interval);
204
+ res.json({
205
+ success: true,
206
+ data: {
207
+ symbol: result.symbol,
208
+ currentPrice: result.currentPrice,
209
+ signal: result.signal,
210
+ confidence: result.confidence,
211
+ activeOrderBlock: result.activeOB,
212
+ orderBlocks: {
213
+ bullish: result.bullishOBs,
214
+ bearish: result.bearishOBs,
215
+ },
216
+ tradeSetup: {
217
+ entry: result.entry,
218
+ stopLoss: result.stopLoss,
219
+ takeProfit1: result.takeProfit1,
220
+ takeProfit2: result.takeProfit2,
221
+ takeProfit3: result.takeProfit3,
222
+ riskRewardRatio: result.riskRewardRatio,
223
+ },
224
+ context: {
225
+ trend: result.trend,
226
+ premiumDiscount: result.premiumDiscount,
227
+ },
228
+ reasoning: result.reasoning,
229
+ warnings: result.warnings,
230
+ },
231
+ timestamp: result.timestamp,
232
+ });
233
+ }
234
+ catch (error) {
235
+ res.status(500).json({
236
+ success: false,
237
+ error: error.message || "Internal server error",
238
+ });
239
+ }
240
+ });
241
+ /**
242
+ * ICT Strategy
243
+ * GET /api/ict/:symbol?interval=1h
244
+ */
245
+ app.get("/api/ict/:symbol", async (req, res) => {
246
+ try {
247
+ const { symbol } = req.params;
248
+ const interval = req.query.interval || "1h";
249
+ const result = await (0, ict_strategy_1.generateICTSignal)(symbol, interval);
250
+ res.json({
251
+ success: true,
252
+ data: {
253
+ symbol: result.symbol,
254
+ currentPrice: result.currentPrice,
255
+ signal: result.signal,
256
+ confidence: result.confidence,
257
+ modelType: result.modelType,
258
+ killzone: result.killzone,
259
+ inKillzone: result.inKillzone,
260
+ ote: result.ote,
261
+ powerOf3: result.powerOf3,
262
+ marketStructure: result.marketStructure,
263
+ premiumDiscount: result.premiumDiscount,
264
+ displacement: result.displacement,
265
+ breakerBlocks: result.breakerBlocks,
266
+ activeBreaker: result.activeBreaker,
267
+ inducements: result.inducements,
268
+ recentSweep: result.recentSweep,
269
+ tradeSetup: {
270
+ entry: result.entry,
271
+ stopLoss: result.stopLoss,
272
+ takeProfit1: result.takeProfit1,
273
+ takeProfit2: result.takeProfit2,
274
+ takeProfit3: result.takeProfit3,
275
+ riskRewardRatio: result.riskRewardRatio,
276
+ },
277
+ confluenceFactors: result.confluenceFactors,
278
+ reasoning: result.reasoning,
279
+ warnings: result.warnings,
280
+ },
281
+ timestamp: result.timestamp,
282
+ });
283
+ }
284
+ catch (error) {
285
+ res.status(500).json({
286
+ success: false,
287
+ error: error.message || "Internal server error",
288
+ });
289
+ }
290
+ });
291
+ /**
292
+ * Smart Trend Confluence Strategy
293
+ * High-probability trading with multi-timeframe analysis
294
+ * GET /api/smart/:symbol?htf=4h&ltf=1h
295
+ */
296
+ app.get("/api/smart/:symbol", async (req, res) => {
297
+ try {
298
+ const { symbol } = req.params;
299
+ const htfInterval = req.query.htf || "4h";
300
+ const ltfInterval = req.query.ltf || "1h";
301
+ const result = await (0, strategy_1.generateStrategySignal)(symbol, htfInterval, ltfInterval);
302
+ res.json({
303
+ success: true,
304
+ data: {
305
+ symbol: symbol.toUpperCase() + "USDT",
306
+ signal: result.signal,
307
+ direction: result.direction,
308
+ confluenceScore: {
309
+ total: result.score.total,
310
+ meetsMinimum: result.score.meetsMinimum,
311
+ breakdown: result.score.breakdown,
312
+ factors: result.score.factors,
313
+ },
314
+ tradeSetup: {
315
+ entry: result.entry,
316
+ stopLoss: result.stopLoss,
317
+ takeProfit1: result.takeProfit1,
318
+ takeProfit2: result.takeProfit2,
319
+ riskRewardRatio: result.riskRewardRatio,
320
+ },
321
+ timeframes: {
322
+ higher: {
323
+ interval: result.higherTimeframe.interval,
324
+ trend: result.higherTimeframe.trend,
325
+ ema10: result.higherTimeframe.ema10,
326
+ ema20: result.higherTimeframe.ema20,
327
+ ema50: result.higherTimeframe.ema50,
328
+ ema200: result.higherTimeframe.ema200,
329
+ rsi: result.higherTimeframe.rsi,
330
+ },
331
+ lower: {
332
+ interval: result.lowerTimeframe.interval,
333
+ trend: result.lowerTimeframe.trend,
334
+ ema10: result.lowerTimeframe.ema10,
335
+ ema20: result.lowerTimeframe.ema20,
336
+ ema50: result.lowerTimeframe.ema50,
337
+ ema200: result.lowerTimeframe.ema200,
338
+ rsi: result.lowerTimeframe.rsi,
339
+ emaTilt: result.lowerTimeframe.emaTilt,
340
+ },
341
+ },
342
+ pullback: result.pullback,
343
+ candlePattern: result.candlePattern,
344
+ keyLevels: result.keyLevels,
345
+ volume: result.volume,
346
+ reasoning: result.reasoning,
347
+ warnings: result.warnings,
348
+ },
349
+ timestamp: Date.now(),
350
+ });
351
+ }
352
+ catch (error) {
353
+ res.status(500).json({
354
+ success: false,
355
+ error: error.message || "Internal server error",
356
+ });
357
+ }
358
+ });
359
+ /**
360
+ * Full Trading Strategy
361
+ * GET /api/strategy/:symbol?style=moderate&direction=both&leverage=20
362
+ */
363
+ app.get("/api/strategy/:symbol", async (req, res) => {
364
+ try {
365
+ const { symbol } = req.params;
366
+ const style = req.query.style || "moderate";
367
+ const direction = req.query.direction || "both";
368
+ const maxLeverage = parseInt(req.query.leverage) || 20;
369
+ const result = await (0, strategy_engine_1.generateTradeSetup)(symbol, {
370
+ style,
371
+ direction,
372
+ maxLeverage,
373
+ riskPerTrade: 2,
374
+ });
375
+ res.json({
376
+ success: true,
377
+ data: {
378
+ symbol: result.symbol,
379
+ direction: result.direction,
380
+ confidence: result.confidence,
381
+ entry: {
382
+ price: result.entryPrice,
383
+ stopLoss: result.stopLoss,
384
+ takeProfit1: result.takeProfit1,
385
+ takeProfit2: result.takeProfit2,
386
+ takeProfit3: result.takeProfit3,
387
+ },
388
+ riskManagement: {
389
+ recommendedLeverage: result.recommendedLeverage,
390
+ maxLeverage: result.maxLeverage,
391
+ riskRewardRatio: result.riskRewardRatio,
392
+ positionSizePercent: result.positionSizePercent,
393
+ },
394
+ scores: {
395
+ technical: result.technicalScore,
396
+ smc: result.smcScore,
397
+ volumeWhale: result.volumeWhaleScore,
398
+ news: result.newsScore,
399
+ overall: result.overallScore,
400
+ },
401
+ multiTimeframe: {
402
+ alignment: result.mtfAlignment,
403
+ confirmed: result.mtfConfirmed,
404
+ },
405
+ trailingStops: result.trailingStopLevels,
406
+ alert: {
407
+ status: result.alertStatus,
408
+ reasons: result.alertReasons,
409
+ },
410
+ analysis: result.analysis,
411
+ warnings: result.warnings,
412
+ },
413
+ timestamp: result.timestamp,
414
+ });
415
+ }
416
+ catch (error) {
417
+ res.status(500).json({
418
+ success: false,
419
+ error: error.message || "Internal server error",
420
+ });
421
+ }
422
+ });
423
+ /**
424
+ * Price Data
425
+ * GET /api/price/:symbol?interval=1h&limit=100
426
+ */
427
+ app.get("/api/price/:symbol", async (req, res) => {
428
+ try {
429
+ const { symbol } = req.params;
430
+ const interval = req.query.interval || "1h";
431
+ const limit = parseInt(req.query.limit) || 100;
432
+ const data = await (0, crypto_1.fetchCryptoData)(symbol, interval, limit);
433
+ // Calculate 24h high/low/volume from candles
434
+ const recentCandles = data.candles.slice(-24);
435
+ const high24h = Math.max(...recentCandles.map((c) => c.high));
436
+ const low24h = Math.min(...recentCandles.map((c) => c.low));
437
+ const volume24h = recentCandles.reduce((sum, c) => sum + c.volume, 0);
438
+ res.json({
439
+ success: true,
440
+ data: {
441
+ symbol: data.symbol,
442
+ currentPrice: data.currentPrice,
443
+ priceChange24h: data.priceChangePercent24h,
444
+ high24h,
445
+ low24h,
446
+ volume24h,
447
+ candles: data.candles.map((c) => ({
448
+ timestamp: c.timestamp,
449
+ open: c.open,
450
+ high: c.high,
451
+ low: c.low,
452
+ close: c.close,
453
+ volume: c.volume,
454
+ })),
455
+ },
456
+ timestamp: Date.now(),
457
+ });
458
+ }
459
+ catch (error) {
460
+ res.status(500).json({
461
+ success: false,
462
+ error: error.message || "Internal server error",
463
+ });
464
+ }
465
+ });
466
+ /**
467
+ * Batch Analysis - Multiple symbols
468
+ * POST /api/batch/signal
469
+ * Body: { symbols: ["BTC", "ETH", "SOL"], interval: "1h" }
470
+ */
471
+ app.post("/api/batch/signal", async (req, res) => {
472
+ try {
473
+ const { symbols, interval = "1h" } = req.body;
474
+ if (!symbols || !Array.isArray(symbols)) {
475
+ return res.status(400).json({
476
+ success: false,
477
+ error: "symbols array is required",
478
+ });
479
+ }
480
+ const results = await Promise.all(symbols.slice(0, 10).map(async (symbol) => {
481
+ try {
482
+ const data = await (0, crypto_1.fetchCryptoData)(symbol, interval, 250);
483
+ const signal = (0, crypto_1.generateSignal)(data);
484
+ return {
485
+ symbol: data.symbol,
486
+ success: true,
487
+ price: data.currentPrice,
488
+ signal: signal.signal,
489
+ confidence: signal.confidence,
490
+ };
491
+ }
492
+ catch (error) {
493
+ return {
494
+ symbol,
495
+ success: false,
496
+ error: error.message,
497
+ };
498
+ }
499
+ }));
500
+ res.json({
501
+ success: true,
502
+ data: results,
503
+ timestamp: Date.now(),
504
+ });
505
+ }
506
+ catch (error) {
507
+ res.status(500).json({
508
+ success: false,
509
+ error: error.message || "Internal server error",
510
+ });
511
+ }
512
+ });
513
+ // ============================================
514
+ // ERROR HANDLING
515
+ // ============================================
516
+ app.use((req, res) => {
517
+ res.status(404).json({
518
+ success: false,
519
+ error: "Endpoint not found",
520
+ availableEndpoints: [
521
+ "GET /api/signal/:symbol",
522
+ "GET /api/analyze/:symbol",
523
+ "GET /api/smc/:symbol",
524
+ "GET /api/orderblock/:symbol",
525
+ "GET /api/ict/:symbol",
526
+ "GET /api/strategy/:symbol",
527
+ "GET /api/price/:symbol",
528
+ "POST /api/batch/signal",
529
+ ],
530
+ });
531
+ });
532
+ app.use((err, req, res, next) => {
533
+ console.error("Server error:", err);
534
+ res.status(500).json({
535
+ success: false,
536
+ error: "Internal server error",
537
+ });
538
+ });
539
+ // ============================================
540
+ // START SERVER (only when not in serverless)
541
+ // ============================================
542
+ // For Vercel serverless, we export the app without calling listen()
543
+ if (!process.env.VERCEL) {
544
+ app.listen(PORT, () => {
545
+ console.log(`
546
+ ╔═══════════════════════════════════════════════════════════╗
547
+ ║ 🚀 CRYPTO TRADING SIGNAL API SERVER ║
548
+ ╠═══════════════════════════════════════════════════════════╣
549
+ ║ Server running on: http://localhost:${PORT} ║
550
+ ║ ║
551
+ ║ Endpoints: ║
552
+ ║ GET /api/signal/:symbol Quick signal ║
553
+ ║ GET /api/analyze/:symbol Comprehensive analysis ║
554
+ ║ GET /api/smc/:symbol Smart Money Concepts ║
555
+ ║ GET /api/orderblock/:symbol Order Block strategy ║
556
+ ║ GET /api/ict/:symbol ICT strategy ║
557
+ ║ GET /api/strategy/:symbol Full trading strategy ║
558
+ ║ GET /api/price/:symbol Price & candle data ║
559
+ ║ POST /api/batch/signal Batch signals ║
560
+ ║ ║
561
+ ║ Free Deployment: ║
562
+ ║ - Railway.app ║
563
+ ║ - Render.com ║
564
+ ║ - Fly.io ║
565
+ ╚═══════════════════════════════════════════════════════════╝
566
+ `);
567
+ });
568
+ }
569
+ // Export for Vercel serverless
570
+ exports.default = app;
571
+ module.exports = app;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prab-cli",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "AI-powered coding assistant for your terminal. Built with Groq's lightning-fast LLMs, featuring autonomous tool execution, syntax-highlighted output, and git integration.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -10,6 +10,8 @@
10
10
  "scripts": {
11
11
  "build": "tsc",
12
12
  "start": "node dist/index.js",
13
+ "server": "node dist/server/index.js",
14
+ "server:dev": "nodemon --exec ts-node src/server/index.ts",
13
15
  "dev": "ts-node src/index.ts",
14
16
  "dev:watch": "nodemon --exec ts-node src/index.ts",
15
17
  "log": "ts-node src/log-viewer.ts",
@@ -67,20 +69,24 @@
67
69
  "@langchain/core": "^1.1.11",
68
70
  "@langchain/groq": "^1.0.2",
69
71
  "@langchain/openai": "^1.2.2",
70
- "chalk": "^5.6.2",
72
+ "chalk": "^4.1.2",
71
73
  "commander": "^14.0.2",
74
+ "cors": "^2.8.5",
72
75
  "diff": "^8.0.2",
73
76
  "dotenv": "^17.2.3",
77
+ "express": "^4.21.0",
74
78
  "glob": "^13.0.0",
75
79
  "groq-sdk": "^0.37.0",
76
80
  "inquirer": "^13.1.0",
77
- "ora": "^9.0.0",
81
+ "ora": "^5.4.1",
78
82
  "simple-git": "^3.30.0",
79
83
  "zod": "^4.3.5"
80
84
  },
81
85
  "devDependencies": {
82
86
  "@eslint/js": "^9.39.2",
87
+ "@types/cors": "^2.8.17",
83
88
  "@types/diff": "^7.0.2",
89
+ "@types/express": "^4.17.21",
84
90
  "@types/glob": "^8.1.0",
85
91
  "@types/inquirer": "^9.0.9",
86
92
  "@types/node": "^25.0.3",