prab-cli 1.2.5 → 1.2.6

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/index.js CHANGED
@@ -172,6 +172,48 @@ program
172
172
  .action(async (options) => {
173
173
  await (0, crypto_1.runCryptoNews)(options.coin);
174
174
  });
175
+ // Smart trading strategy
176
+ program
177
+ .command("strategy <crypto>")
178
+ .description("Generate smart trading strategy with entry, exit, and leverage")
179
+ .option("-s, --style <style>", "Trading style: conservative, moderate, aggressive", "moderate")
180
+ .option("-l, --leverage <number>", "Maximum leverage allowed", "20")
181
+ .option("-d, --direction <direction>", "Trade direction: both, long, short", "both")
182
+ .action(async (crypto, options) => {
183
+ const style = ["conservative", "moderate", "aggressive"].includes(options.style)
184
+ ? options.style
185
+ : "moderate";
186
+ const maxLeverage = Math.min(parseInt(options.leverage) || 20, 100);
187
+ const direction = ["both", "long", "short"].includes(options.direction)
188
+ ? options.direction
189
+ : "both";
190
+ await (0, crypto_1.runStrategy)(crypto, { style, maxLeverage, direction });
191
+ });
192
+ // Order Block trading strategy
193
+ program
194
+ .command("orderblock <crypto>")
195
+ .alias("ob")
196
+ .description("Order Block trading strategy with BUY/SELL signals based on OB zones")
197
+ .option("-i, --interval <interval>", "Time interval (15m, 1h, 4h, 1d)", "4h")
198
+ .action(async (crypto, options) => {
199
+ const validIntervals = ["15m", "1h", "4h", "1d"];
200
+ const interval = validIntervals.includes(options.interval)
201
+ ? options.interval
202
+ : "4h";
203
+ await (0, crypto_1.runOrderBlockStrategy)(crypto, interval);
204
+ });
205
+ // ICT (Inner Circle Trader) Strategy
206
+ program
207
+ .command("ict <crypto>")
208
+ .description("ICT trading strategy - Killzones, OTE, Breakers, Silver Bullet, AMD")
209
+ .option("-i, --interval <interval>", "Time interval (15m, 1h, 4h)", "1h")
210
+ .action(async (crypto, options) => {
211
+ const validIntervals = ["15m", "1h", "4h"];
212
+ const interval = validIntervals.includes(options.interval)
213
+ ? options.interval
214
+ : "1h";
215
+ await (0, crypto_1.runICTStrategy)(crypto, interval);
216
+ });
175
217
  // Model management commands
176
218
  program
177
219
  .command("model")
@@ -336,7 +378,12 @@ program.action(async () => {
336
378
  default: "btc",
337
379
  },
338
380
  ]);
339
- await (0, crypto_1.comprehensiveAnalysis)(cryptoSymbol);
381
+ try {
382
+ await (0, crypto_1.comprehensiveAnalysis)(cryptoSymbol);
383
+ }
384
+ catch (err) {
385
+ // Error already handled in comprehensiveAnalysis
386
+ }
340
387
  break;
341
388
  }
342
389
  case "signal": {
@@ -359,7 +406,12 @@ program.action(async () => {
359
406
  { name: "1 Day", value: "1d" },
360
407
  ],
361
408
  });
362
- await (0, crypto_1.fullSignal)(cryptoSymbol, intervalChoice);
409
+ try {
410
+ await (0, crypto_1.fullSignal)(cryptoSymbol, intervalChoice);
411
+ }
412
+ catch (err) {
413
+ // Error already handled in fullSignal
414
+ }
363
415
  break;
364
416
  }
365
417
  case "whale": {
@@ -418,6 +470,86 @@ program.action(async () => {
418
470
  await (0, crypto_1.runCryptoNews)(coinFilter);
419
471
  break;
420
472
  }
473
+ case "strategy": {
474
+ // Prompt for crypto symbol
475
+ const { strategySymbol } = await inquirer_1.default.prompt([
476
+ {
477
+ type: "input",
478
+ name: "strategySymbol",
479
+ message: "Enter cryptocurrency symbol (e.g., btc, eth, sol):",
480
+ default: "btc",
481
+ },
482
+ ]);
483
+ // Prompt for trading style
484
+ const styleChoice = await (0, select_1.default)({
485
+ message: "Select your trading style:",
486
+ choices: [
487
+ { name: "Conservative (5-10x leverage, wider stops)", value: "conservative" },
488
+ { name: "Moderate (10-20x leverage, balanced) - Recommended", value: "moderate" },
489
+ { name: "Aggressive (20-50x leverage, tighter stops)", value: "aggressive" },
490
+ ],
491
+ });
492
+ // Prompt for direction
493
+ const directionChoice = await (0, select_1.default)({
494
+ message: "Trade direction:",
495
+ choices: [
496
+ { name: "Both Long & Short", value: "both" },
497
+ { name: "Long Only", value: "long" },
498
+ { name: "Short Only", value: "short" },
499
+ ],
500
+ });
501
+ await (0, crypto_1.runStrategy)(strategySymbol, {
502
+ style: styleChoice,
503
+ direction: directionChoice,
504
+ maxLeverage: styleChoice === "conservative" ? 10 : styleChoice === "moderate" ? 20 : 50,
505
+ });
506
+ break;
507
+ }
508
+ case "orderblock": {
509
+ // Prompt for crypto symbol
510
+ const { obSymbol } = await inquirer_1.default.prompt([
511
+ {
512
+ type: "input",
513
+ name: "obSymbol",
514
+ message: "Enter cryptocurrency symbol (e.g., btc, eth, sol):",
515
+ default: "btc",
516
+ },
517
+ ]);
518
+ // Prompt for timeframe
519
+ const obIntervalChoice = await (0, select_1.default)({
520
+ message: "Select timeframe for Order Block analysis:",
521
+ choices: [
522
+ { name: "4 Hours (Recommended for swing trades)", value: "4h" },
523
+ { name: "1 Hour (Intraday trades)", value: "1h" },
524
+ { name: "15 Minutes (Scalping)", value: "15m" },
525
+ { name: "1 Day (Position trades)", value: "1d" },
526
+ ],
527
+ });
528
+ await (0, crypto_1.runOrderBlockStrategy)(obSymbol, obIntervalChoice);
529
+ break;
530
+ }
531
+ case "ict": {
532
+ // Prompt for crypto symbol
533
+ const { ictSymbol } = await inquirer_1.default.prompt([
534
+ {
535
+ type: "input",
536
+ name: "ictSymbol",
537
+ message: "Enter cryptocurrency symbol (e.g., btc, eth, sol):",
538
+ default: "btc",
539
+ },
540
+ ]);
541
+ // Prompt for timeframe
542
+ const ictIntervalChoice = await (0, select_1.default)({
543
+ message: "Select timeframe for ICT analysis:",
544
+ choices: [
545
+ { name: "1 Hour (Recommended for ICT)", value: "1h" },
546
+ { name: "15 Minutes (Scalping with Silver Bullet)", value: "15m" },
547
+ { name: "4 Hours (Higher timeframe bias)", value: "4h" },
548
+ ],
549
+ });
550
+ await (0, crypto_1.runICTStrategy)(ictSymbol, ictIntervalChoice);
551
+ break;
552
+ }
421
553
  case "model": {
422
554
  // Fetch models from Groq API if not cached
423
555
  if (cachedModels.length === 0) {
@@ -5,12 +5,15 @@
5
5
  * Fetches OHLCV data from Binance public API (no API key required)
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.fetchAllSymbols = fetchAllSymbols;
9
+ exports.findSimilarSymbols = findSimilarSymbols;
8
10
  exports.normalizeSymbol = normalizeSymbol;
9
11
  exports.fetchOHLCV = fetchOHLCV;
10
12
  exports.fetch24hTicker = fetch24hTicker;
11
13
  exports.fetchCryptoData = fetchCryptoData;
12
14
  exports.getSupportedSymbols = getSupportedSymbols;
13
15
  exports.isValidSymbol = isValidSymbol;
16
+ exports.validateSymbol = validateSymbol;
14
17
  // Common crypto symbols mapping (user-friendly -> Binance format)
15
18
  const SYMBOL_MAP = {
16
19
  btc: "BTCUSDT",
@@ -57,6 +60,63 @@ const SYMBOL_MAP = {
57
60
  wif: "WIFUSDT",
58
61
  };
59
62
  const BINANCE_API_BASE = "https://api.binance.com/api/v3";
63
+ // Cache for valid Binance symbols
64
+ let cachedSymbols = null;
65
+ let cacheTimestamp = 0;
66
+ const CACHE_DURATION = 1000 * 60 * 60; // 1 hour cache
67
+ /**
68
+ * Fetch all valid USDT trading pairs from Binance
69
+ */
70
+ async function fetchAllSymbols() {
71
+ // Return cached symbols if still valid
72
+ if (cachedSymbols && Date.now() - cacheTimestamp < CACHE_DURATION) {
73
+ return cachedSymbols;
74
+ }
75
+ try {
76
+ const response = await fetch(`${BINANCE_API_BASE}/exchangeInfo`);
77
+ if (!response.ok) {
78
+ throw new Error("Failed to fetch exchange info");
79
+ }
80
+ const data = await response.json();
81
+ const symbols = new Set();
82
+ for (const symbol of data.symbols) {
83
+ // Only include USDT pairs that are trading
84
+ if (symbol.status === "TRADING" && symbol.quoteAsset === "USDT") {
85
+ symbols.add(symbol.symbol);
86
+ // Also add the base asset for easy lookup
87
+ symbols.add(symbol.baseAsset.toLowerCase());
88
+ }
89
+ }
90
+ cachedSymbols = symbols;
91
+ cacheTimestamp = Date.now();
92
+ return symbols;
93
+ }
94
+ catch (error) {
95
+ // Return empty set on error, will fall back to direct API check
96
+ return new Set();
97
+ }
98
+ }
99
+ /**
100
+ * Get similar symbols for suggestions
101
+ */
102
+ async function findSimilarSymbols(input, limit = 5) {
103
+ const symbols = await fetchAllSymbols();
104
+ const inputUpper = input.toUpperCase();
105
+ const similar = [];
106
+ for (const symbol of symbols) {
107
+ // Only show USDT pairs, not base assets
108
+ if (!symbol.endsWith("USDT"))
109
+ continue;
110
+ const baseAsset = symbol.replace("USDT", "");
111
+ // Check if base asset starts with or contains the input
112
+ if (baseAsset.startsWith(inputUpper) || baseAsset.includes(inputUpper)) {
113
+ similar.push(baseAsset);
114
+ if (similar.length >= limit)
115
+ break;
116
+ }
117
+ }
118
+ return similar;
119
+ }
60
120
  /**
61
121
  * Normalize symbol to Binance format
62
122
  */
@@ -156,6 +216,12 @@ function getSupportedSymbols() {
156
216
  async function isValidSymbol(symbol) {
157
217
  try {
158
218
  const normalizedSymbol = normalizeSymbol(symbol);
219
+ // First check cache
220
+ const symbols = await fetchAllSymbols();
221
+ if (symbols.has(normalizedSymbol)) {
222
+ return true;
223
+ }
224
+ // Fall back to direct API check
159
225
  const url = `${BINANCE_API_BASE}/ticker/price?symbol=${normalizedSymbol}`;
160
226
  const response = await fetch(url);
161
227
  return response.ok;
@@ -164,3 +230,23 @@ async function isValidSymbol(symbol) {
164
230
  return false;
165
231
  }
166
232
  }
233
+ /**
234
+ * Validate symbol and get suggestions if invalid
235
+ */
236
+ async function validateSymbol(symbol) {
237
+ const normalized = normalizeSymbol(symbol);
238
+ try {
239
+ const url = `${BINANCE_API_BASE}/ticker/price?symbol=${normalized}`;
240
+ const response = await fetch(url);
241
+ if (response.ok) {
242
+ return { valid: true, normalized, suggestions: [] };
243
+ }
244
+ // If invalid, find similar symbols
245
+ const suggestions = await findSimilarSymbols(symbol, 5);
246
+ return { valid: false, normalized, suggestions };
247
+ }
248
+ catch {
249
+ const suggestions = await findSimilarSymbols(symbol, 5);
250
+ return { valid: false, normalized, suggestions };
251
+ }
252
+ }