prab-cli 1.2.1 → 1.2.4
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 +97 -2
- package/dist/lib/crypto/analyzer.js +275 -0
- package/dist/lib/crypto/chart-visual.js +548 -0
- package/dist/lib/crypto/data-fetcher.js +166 -0
- package/dist/lib/crypto/index.js +47 -0
- package/dist/lib/crypto/indicators.js +390 -0
- package/dist/lib/crypto/market-analyzer.js +497 -0
- package/dist/lib/crypto/signal-generator.js +559 -0
- package/dist/lib/crypto/smc-analyzer.js +418 -0
- package/dist/lib/crypto/smc-indicators.js +512 -0
- package/dist/lib/slash-commands.js +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Trading Signal Generator with AI Reasoning
|
|
4
|
+
* Combines technical analysis with AI-powered insights
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.generateTradingSignal = generateTradingSignal;
|
|
11
|
+
exports.displaySignal = displaySignal;
|
|
12
|
+
exports.quickSignal = quickSignal;
|
|
13
|
+
exports.fullSignal = fullSignal;
|
|
14
|
+
exports.displayComprehensiveAnalysis = displayComprehensiveAnalysis;
|
|
15
|
+
exports.comprehensiveAnalysis = comprehensiveAnalysis;
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const ora_1 = __importDefault(require("ora"));
|
|
18
|
+
const data_fetcher_1 = require("./data-fetcher");
|
|
19
|
+
const analyzer_1 = require("./analyzer");
|
|
20
|
+
const market_analyzer_1 = require("./market-analyzer");
|
|
21
|
+
const config_1 = require("../config");
|
|
22
|
+
const groq_provider_1 = require("../models/groq-provider");
|
|
23
|
+
/**
|
|
24
|
+
* Generate AI reasoning for the trading signal
|
|
25
|
+
*/
|
|
26
|
+
async function generateAIReasoning(symbol, signal, price, priceChange24h) {
|
|
27
|
+
const apiKey = (0, config_1.getApiKey)();
|
|
28
|
+
if (!apiKey) {
|
|
29
|
+
return "AI reasoning unavailable (no API key configured)";
|
|
30
|
+
}
|
|
31
|
+
const modelConfig = (0, config_1.getModelConfig)();
|
|
32
|
+
const provider = new groq_provider_1.GroqProvider(modelConfig.modelId, 0.7);
|
|
33
|
+
provider.initialize(apiKey, modelConfig.modelId);
|
|
34
|
+
const prompt = `You are a crypto trading analyst. Based on the following technical analysis, provide a brief (2-3 sentences) trading insight and recommendation.
|
|
35
|
+
|
|
36
|
+
Symbol: ${symbol}
|
|
37
|
+
Current Price: $${price.toLocaleString()}
|
|
38
|
+
24h Change: ${priceChange24h.toFixed(2)}%
|
|
39
|
+
|
|
40
|
+
Technical Analysis:
|
|
41
|
+
- Signal: ${signal.signal}
|
|
42
|
+
- Confidence: ${signal.confidence}%
|
|
43
|
+
- Trend: ${signal.indicators.trend}
|
|
44
|
+
- EMA Crossover: ${signal.indicators.emaCrossover}
|
|
45
|
+
- Price vs EMAs: ${signal.indicators.priceVsEMA}
|
|
46
|
+
- Suggested Stop-Loss: ${signal.stopLoss}%
|
|
47
|
+
- Suggested Take-Profit: ${signal.takeProfit}%
|
|
48
|
+
|
|
49
|
+
Key Observations:
|
|
50
|
+
${signal.reasoning.map((r) => `- ${r}`).join("\n")}
|
|
51
|
+
|
|
52
|
+
Provide a concise trading insight (2-3 sentences) explaining the signal and any cautions. Be direct and actionable.`;
|
|
53
|
+
try {
|
|
54
|
+
const stream = provider.streamChat([{ role: "user", content: prompt }], [] // No tools needed
|
|
55
|
+
);
|
|
56
|
+
let response = "";
|
|
57
|
+
for await (const chunk of stream) {
|
|
58
|
+
if (chunk.content && typeof chunk.content === "string") {
|
|
59
|
+
response += chunk.content;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return response.trim();
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return `AI reasoning unavailable: ${error.message}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Main function to generate trading signal with AI reasoning
|
|
70
|
+
*/
|
|
71
|
+
async function generateTradingSignal(symbol, interval = "1h", includeAI = true) {
|
|
72
|
+
const spinner = (0, ora_1.default)(`Fetching ${symbol.toUpperCase()} data...`).start();
|
|
73
|
+
try {
|
|
74
|
+
// Fetch crypto data
|
|
75
|
+
const data = await (0, data_fetcher_1.fetchCryptoData)(symbol, interval, 250); // Get 250 candles for EMA200
|
|
76
|
+
spinner.text = "Analyzing chart data...";
|
|
77
|
+
// Generate technical signal
|
|
78
|
+
const signal = (0, analyzer_1.generateSignal)(data);
|
|
79
|
+
spinner.text = "Generating trading signal...";
|
|
80
|
+
let aiReasoning;
|
|
81
|
+
// Generate AI reasoning if requested
|
|
82
|
+
if (includeAI) {
|
|
83
|
+
spinner.text = "Getting AI insights...";
|
|
84
|
+
aiReasoning = await generateAIReasoning(data.symbol, signal, data.currentPrice, data.priceChangePercent24h);
|
|
85
|
+
}
|
|
86
|
+
spinner.succeed(`Analysis complete for ${data.symbol}`);
|
|
87
|
+
return {
|
|
88
|
+
success: true,
|
|
89
|
+
symbol: data.symbol,
|
|
90
|
+
signal,
|
|
91
|
+
aiReasoning,
|
|
92
|
+
price: data.currentPrice,
|
|
93
|
+
priceChange24h: data.priceChangePercent24h,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
spinner.fail(`Failed to analyze ${symbol}`);
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
symbol: (0, data_fetcher_1.normalizeSymbol)(symbol),
|
|
101
|
+
error: error.message,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Display trading signal in terminal
|
|
107
|
+
*/
|
|
108
|
+
function displaySignal(result) {
|
|
109
|
+
if (!result.success || !result.signal) {
|
|
110
|
+
console.log(chalk_1.default.red(`\nError: ${result.error}`));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const { signal, symbol, price, priceChange24h, aiReasoning } = result;
|
|
114
|
+
// Signal colors
|
|
115
|
+
const signalColor = signal.signal === "BUY"
|
|
116
|
+
? chalk_1.default.green.bold
|
|
117
|
+
: signal.signal === "SELL"
|
|
118
|
+
? chalk_1.default.red.bold
|
|
119
|
+
: chalk_1.default.yellow.bold;
|
|
120
|
+
const signalIcon = signal.signal === "BUY" ? "\u{1F7E2}" : signal.signal === "SELL" ? "\u{1F534}" : "\u{1F7E1}";
|
|
121
|
+
const trendIcon = signal.indicators.trend === "bullish"
|
|
122
|
+
? chalk_1.default.green("\u{2191}")
|
|
123
|
+
: signal.indicators.trend === "bearish"
|
|
124
|
+
? chalk_1.default.red("\u{2193}")
|
|
125
|
+
: chalk_1.default.yellow("\u{2192}");
|
|
126
|
+
const changeColor = priceChange24h >= 0 ? chalk_1.default.green : chalk_1.default.red;
|
|
127
|
+
const changeSign = priceChange24h >= 0 ? "+" : "";
|
|
128
|
+
// Format price for display
|
|
129
|
+
const formattedPrice = price < 1
|
|
130
|
+
? `$${price.toFixed(4)}`
|
|
131
|
+
: price < 100
|
|
132
|
+
? `$${price.toFixed(2)}`
|
|
133
|
+
: `$${price.toLocaleString(undefined, { maximumFractionDigits: 2 })}`;
|
|
134
|
+
// Header with current price
|
|
135
|
+
console.log("");
|
|
136
|
+
console.log(chalk_1.default.cyan("\u{250C}" + "\u{2500}".repeat(45) + "\u{2510}"));
|
|
137
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
138
|
+
chalk_1.default.bold.white(` \u{1F4CA} ${symbol}`.padEnd(44)) +
|
|
139
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
140
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
141
|
+
chalk_1.default.bold.yellow(` Current Price: ${formattedPrice}`).padEnd(44) +
|
|
142
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
143
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
144
|
+
` 24h: ${changeColor(changeSign + priceChange24h.toFixed(2) + "%")}`.padEnd(52) +
|
|
145
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
146
|
+
console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
|
|
147
|
+
// Signal
|
|
148
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
149
|
+
` Signal: ${signalIcon} ${signalColor(signal.signal)}`.padEnd(53) +
|
|
150
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
151
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
152
|
+
` Confidence: ${chalk_1.default.white(signal.confidence + "%")}`.padEnd(53) +
|
|
153
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
154
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
155
|
+
` Stop-Loss: ${chalk_1.default.red("-" + signal.stopLoss + "%")}`.padEnd(53) +
|
|
156
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
157
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
158
|
+
` Take-Profit: ${chalk_1.default.green("+" + signal.takeProfit + "%")}`.padEnd(53) +
|
|
159
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
160
|
+
// Trend info
|
|
161
|
+
console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
|
|
162
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
163
|
+
` Trend: ${trendIcon} ${chalk_1.default.white(signal.indicators.trend)}`.padEnd(53) +
|
|
164
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
165
|
+
// EMA Values
|
|
166
|
+
console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
|
|
167
|
+
console.log(chalk_1.default.cyan("\u{2502}") + chalk_1.default.gray(" EMA Indicators:").padEnd(53) + chalk_1.default.cyan("\u{2502}"));
|
|
168
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
169
|
+
chalk_1.default.gray(` EMA9: $${signal.indicators.currentEMA9.toFixed(2)}`).padEnd(44) +
|
|
170
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
171
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
172
|
+
chalk_1.default.gray(` EMA21: $${signal.indicators.currentEMA21.toFixed(2)}`).padEnd(44) +
|
|
173
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
174
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
175
|
+
chalk_1.default.gray(` EMA50: $${signal.indicators.currentEMA50.toFixed(2)}`).padEnd(44) +
|
|
176
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
177
|
+
if (signal.indicators.currentEMA200 > 0) {
|
|
178
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
179
|
+
chalk_1.default.gray(` EMA200: $${signal.indicators.currentEMA200.toFixed(2)}`).padEnd(44) +
|
|
180
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
181
|
+
}
|
|
182
|
+
// Technical observations
|
|
183
|
+
console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
|
|
184
|
+
console.log(chalk_1.default.cyan("\u{2502}") + chalk_1.default.gray(" Technical Analysis:").padEnd(53) + chalk_1.default.cyan("\u{2502}"));
|
|
185
|
+
for (const reason of signal.reasoning.slice(0, 4)) {
|
|
186
|
+
const truncated = reason.length > 40 ? reason.substring(0, 37) + "..." : reason;
|
|
187
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
188
|
+
chalk_1.default.gray(` \u{2022} ${truncated}`).padEnd(44) +
|
|
189
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
190
|
+
}
|
|
191
|
+
// AI Reasoning
|
|
192
|
+
if (aiReasoning) {
|
|
193
|
+
console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
|
|
194
|
+
console.log(chalk_1.default.cyan("\u{2502}") +
|
|
195
|
+
chalk_1.default.magenta.bold(" \u{1F916} AI Insight:").padEnd(53) +
|
|
196
|
+
chalk_1.default.cyan("\u{2502}"));
|
|
197
|
+
// Word wrap AI reasoning
|
|
198
|
+
const words = aiReasoning.split(" ");
|
|
199
|
+
let line = " ";
|
|
200
|
+
for (const word of words) {
|
|
201
|
+
if (line.length + word.length > 40) {
|
|
202
|
+
console.log(chalk_1.default.cyan("\u{2502}") + chalk_1.default.white(line.padEnd(44)) + chalk_1.default.cyan("\u{2502}"));
|
|
203
|
+
line = " " + word + " ";
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
line += word + " ";
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (line.trim()) {
|
|
210
|
+
console.log(chalk_1.default.cyan("\u{2502}") + chalk_1.default.white(line.padEnd(44)) + chalk_1.default.cyan("\u{2502}"));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Footer
|
|
214
|
+
console.log(chalk_1.default.cyan("\u{2514}" + "\u{2500}".repeat(45) + "\u{2518}"));
|
|
215
|
+
// Disclaimer
|
|
216
|
+
console.log("");
|
|
217
|
+
console.log(chalk_1.default.gray.italic(" \u{26A0}\u{FE0F} This is not financial advice. Always do your own research."));
|
|
218
|
+
console.log("");
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Quick signal check (no AI)
|
|
222
|
+
*/
|
|
223
|
+
async function quickSignal(symbol) {
|
|
224
|
+
const result = await generateTradingSignal(symbol, "1h", false);
|
|
225
|
+
displaySignal(result);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Full signal with AI reasoning
|
|
229
|
+
*/
|
|
230
|
+
async function fullSignal(symbol, interval = "1h") {
|
|
231
|
+
const result = await generateTradingSignal(symbol, interval, true);
|
|
232
|
+
displaySignal(result);
|
|
233
|
+
}
|
|
234
|
+
// ============================================
|
|
235
|
+
// COMPREHENSIVE ANALYSIS
|
|
236
|
+
// ============================================
|
|
237
|
+
/**
|
|
238
|
+
* Generate AI analysis for comprehensive market data
|
|
239
|
+
*/
|
|
240
|
+
async function generateComprehensiveAIAnalysis(analysis) {
|
|
241
|
+
const apiKey = (0, config_1.getApiKey)();
|
|
242
|
+
if (!apiKey) {
|
|
243
|
+
return "AI analysis unavailable (no API key configured)";
|
|
244
|
+
}
|
|
245
|
+
const modelConfig = (0, config_1.getModelConfig)();
|
|
246
|
+
const provider = new groq_provider_1.GroqProvider(modelConfig.modelId, 0.7);
|
|
247
|
+
provider.initialize(apiKey, modelConfig.modelId);
|
|
248
|
+
const prompt = `You are an expert crypto trading analyst. Provide a detailed but concise analysis (4-6 sentences) based on the following comprehensive market data.
|
|
249
|
+
|
|
250
|
+
Symbol: ${analysis.symbol}
|
|
251
|
+
Current Price: $${analysis.currentPrice.toLocaleString()}
|
|
252
|
+
24h Change: ${analysis.priceChange24h.toFixed(2)}%
|
|
253
|
+
|
|
254
|
+
RECOMMENDATION: ${analysis.recommendation}
|
|
255
|
+
Confidence: ${analysis.confidence}%
|
|
256
|
+
Risk Level: ${analysis.riskLevel}
|
|
257
|
+
|
|
258
|
+
MULTI-TIMEFRAME ANALYSIS:
|
|
259
|
+
- 1H Trend: ${analysis.timeframes.short.signal} (${analysis.timeframes.short.trend.direction})
|
|
260
|
+
- 4H Trend: ${analysis.timeframes.medium.signal} (${analysis.timeframes.medium.trend.direction})
|
|
261
|
+
- 1D Trend: ${analysis.timeframes.long.signal} (${analysis.timeframes.long.trend.direction})
|
|
262
|
+
- Timeframe Alignment: ${analysis.timeframeAlignment}
|
|
263
|
+
|
|
264
|
+
INDICATORS:
|
|
265
|
+
- RSI(14): ${analysis.indicators.rsi.current.toFixed(1)} (${analysis.indicators.rsi.condition})
|
|
266
|
+
- MACD: ${analysis.indicators.macd.crossover} crossover, momentum ${analysis.indicators.macd.momentum}
|
|
267
|
+
- Bollinger: Price ${analysis.indicators.bollinger.pricePosition}, ${analysis.indicators.bollinger.squeeze ? "SQUEEZE detected" : "normal bandwidth"}
|
|
268
|
+
- Volume: ${analysis.indicators.volume.volumeRatio.toFixed(1)}x average, ${analysis.indicators.volume.trend} trend
|
|
269
|
+
- ATR Volatility: ${analysis.indicators.atr.volatility} (${analysis.indicators.atr.percentOfPrice.toFixed(1)}% of price)
|
|
270
|
+
|
|
271
|
+
KEY LEVELS:
|
|
272
|
+
- Support: $${analysis.indicators.supportResistance.nearestSupport.toFixed(2)} (${analysis.indicators.supportResistance.distanceToSupport.toFixed(1)}% away)
|
|
273
|
+
- Resistance: $${analysis.indicators.supportResistance.nearestResistance.toFixed(2)} (${analysis.indicators.supportResistance.distanceToResistance.toFixed(1)}% away)
|
|
274
|
+
|
|
275
|
+
TIMING:
|
|
276
|
+
- Action: ${analysis.timing.action}
|
|
277
|
+
- Entry Zone: $${analysis.timing.entryZone.low.toFixed(2)} - $${analysis.timing.entryZone.high.toFixed(2)}
|
|
278
|
+
|
|
279
|
+
TRADE SETUP:
|
|
280
|
+
- Entry: $${analysis.tradeSetup.entry.toFixed(2)}
|
|
281
|
+
- Stop Loss: $${analysis.tradeSetup.stopLoss.toFixed(2)}
|
|
282
|
+
- Target 1: $${analysis.tradeSetup.target1.toFixed(2)}
|
|
283
|
+
- Target 2: $${analysis.tradeSetup.target2.toFixed(2)}
|
|
284
|
+
- Risk/Reward: ${analysis.tradeSetup.riskRewardRatio}:1
|
|
285
|
+
|
|
286
|
+
MARKET CONDITION: ${analysis.marketCondition.type}
|
|
287
|
+
${analysis.marketCondition.description}
|
|
288
|
+
|
|
289
|
+
Bullish Factors:
|
|
290
|
+
${analysis.reasoning.bullishFactors
|
|
291
|
+
.slice(0, 3)
|
|
292
|
+
.map((f) => `- ${f}`)
|
|
293
|
+
.join("\n")}
|
|
294
|
+
|
|
295
|
+
Bearish Factors:
|
|
296
|
+
${analysis.reasoning.bearishFactors
|
|
297
|
+
.slice(0, 3)
|
|
298
|
+
.map((f) => `- ${f}`)
|
|
299
|
+
.join("\n")}
|
|
300
|
+
|
|
301
|
+
Warnings:
|
|
302
|
+
${analysis.reasoning.warnings.map((w) => `- ${w}`).join("\n")}
|
|
303
|
+
|
|
304
|
+
Provide a detailed trading analysis (4-6 sentences) that:
|
|
305
|
+
1. Explains the current market structure and why the recommendation makes sense
|
|
306
|
+
2. Specifies WHEN to enter (now, wait for pullback, wait for breakout, etc.)
|
|
307
|
+
3. Mentions specific price levels to watch
|
|
308
|
+
4. Highlights any risks or cautions
|
|
309
|
+
Be specific with prices and actionable advice.`;
|
|
310
|
+
try {
|
|
311
|
+
const stream = provider.streamChat([{ role: "user", content: prompt }], []);
|
|
312
|
+
let response = "";
|
|
313
|
+
for await (const chunk of stream) {
|
|
314
|
+
if (chunk.content && typeof chunk.content === "string") {
|
|
315
|
+
response += chunk.content;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return response.trim();
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
return `AI analysis unavailable: ${error.message}`;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Format price for display
|
|
326
|
+
*/
|
|
327
|
+
function formatPrice(price) {
|
|
328
|
+
if (price < 0.01)
|
|
329
|
+
return `$${price.toFixed(6)}`;
|
|
330
|
+
if (price < 1)
|
|
331
|
+
return `$${price.toFixed(4)}`;
|
|
332
|
+
if (price < 100)
|
|
333
|
+
return `$${price.toFixed(2)}`;
|
|
334
|
+
return `$${price.toLocaleString(undefined, { maximumFractionDigits: 2 })}`;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Word wrap text for terminal display
|
|
338
|
+
*/
|
|
339
|
+
function wordWrap(text, maxWidth) {
|
|
340
|
+
const words = text.split(" ");
|
|
341
|
+
const lines = [];
|
|
342
|
+
let currentLine = "";
|
|
343
|
+
for (const word of words) {
|
|
344
|
+
if (currentLine.length + word.length + 1 > maxWidth) {
|
|
345
|
+
lines.push(currentLine.trim());
|
|
346
|
+
currentLine = word + " ";
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
currentLine += word + " ";
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (currentLine.trim()) {
|
|
353
|
+
lines.push(currentLine.trim());
|
|
354
|
+
}
|
|
355
|
+
return lines;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Display comprehensive analysis in terminal
|
|
359
|
+
*/
|
|
360
|
+
function displayComprehensiveAnalysis(analysis, aiAnalysis) {
|
|
361
|
+
const boxWidth = 55;
|
|
362
|
+
const contentWidth = boxWidth - 4;
|
|
363
|
+
const border = {
|
|
364
|
+
top: chalk_1.default.cyan("\u{250C}" + "\u{2500}".repeat(boxWidth) + "\u{2510}"),
|
|
365
|
+
mid: chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(boxWidth) + "\u{2524}"),
|
|
366
|
+
bot: chalk_1.default.cyan("\u{2514}" + "\u{2500}".repeat(boxWidth) + "\u{2518}"),
|
|
367
|
+
left: chalk_1.default.cyan("\u{2502}"),
|
|
368
|
+
right: chalk_1.default.cyan("\u{2502}"),
|
|
369
|
+
};
|
|
370
|
+
const line = (content, padEnd = contentWidth) => {
|
|
371
|
+
console.log(border.left + " " + content.padEnd(padEnd) + " " + border.right);
|
|
372
|
+
};
|
|
373
|
+
// Recommendation colors and icons
|
|
374
|
+
const recColors = {
|
|
375
|
+
STRONG_BUY: chalk_1.default.green.bold,
|
|
376
|
+
BUY: chalk_1.default.green,
|
|
377
|
+
WAIT_TO_BUY: chalk_1.default.greenBright,
|
|
378
|
+
HOLD: chalk_1.default.yellow,
|
|
379
|
+
WAIT_TO_SELL: chalk_1.default.redBright,
|
|
380
|
+
SELL: chalk_1.default.red,
|
|
381
|
+
STRONG_SELL: chalk_1.default.red.bold,
|
|
382
|
+
};
|
|
383
|
+
const recIcons = {
|
|
384
|
+
STRONG_BUY: "\u{1F7E2}\u{1F7E2}",
|
|
385
|
+
BUY: "\u{1F7E2}",
|
|
386
|
+
WAIT_TO_BUY: "\u{1F7E1}\u{2197}",
|
|
387
|
+
HOLD: "\u{1F7E1}",
|
|
388
|
+
WAIT_TO_SELL: "\u{1F7E1}\u{2198}",
|
|
389
|
+
SELL: "\u{1F534}",
|
|
390
|
+
STRONG_SELL: "\u{1F534}\u{1F534}",
|
|
391
|
+
};
|
|
392
|
+
const changeColor = analysis.priceChange24h >= 0 ? chalk_1.default.green : chalk_1.default.red;
|
|
393
|
+
const changeSign = analysis.priceChange24h >= 0 ? "+" : "";
|
|
394
|
+
console.log("");
|
|
395
|
+
// Header
|
|
396
|
+
console.log(border.top);
|
|
397
|
+
line(chalk_1.default.bold.white(`\u{1F4CA} ${analysis.symbol} - Comprehensive Analysis`));
|
|
398
|
+
line(chalk_1.default.bold.yellow(`Current Price: ${formatPrice(analysis.currentPrice)}`) +
|
|
399
|
+
` ${changeColor(changeSign + analysis.priceChange24h.toFixed(2) + "%")}`);
|
|
400
|
+
console.log(border.mid);
|
|
401
|
+
// Main Recommendation
|
|
402
|
+
const recColor = recColors[analysis.recommendation] || chalk_1.default.white;
|
|
403
|
+
const recIcon = recIcons[analysis.recommendation] || "";
|
|
404
|
+
line(chalk_1.default.bold(`\u{1F3AF} RECOMMENDATION: ${recIcon} ${recColor(analysis.recommendation)}`));
|
|
405
|
+
line(` Confidence: ${chalk_1.default.white(analysis.confidence + "%")} | Risk: ${analysis.riskLevel === "low"
|
|
406
|
+
? chalk_1.default.green(analysis.riskLevel)
|
|
407
|
+
: analysis.riskLevel === "medium"
|
|
408
|
+
? chalk_1.default.yellow(analysis.riskLevel)
|
|
409
|
+
: chalk_1.default.red(analysis.riskLevel)}`);
|
|
410
|
+
// Timing
|
|
411
|
+
console.log(border.mid);
|
|
412
|
+
line(chalk_1.default.bold("\u{23F0} TIMING"));
|
|
413
|
+
const timingAction = analysis.timing.action.replace(/_/g, " ").toUpperCase();
|
|
414
|
+
line(` ${chalk_1.default.cyan(timingAction)}`);
|
|
415
|
+
line(` Entry Zone: ${chalk_1.default.white(formatPrice(analysis.timing.entryZone.low))} - ${chalk_1.default.white(formatPrice(analysis.timing.entryZone.high))}`);
|
|
416
|
+
const timingLines = wordWrap(analysis.timing.reason, contentWidth - 3);
|
|
417
|
+
timingLines.forEach((l) => line(chalk_1.default.gray(` ${l}`)));
|
|
418
|
+
// Trade Setup
|
|
419
|
+
console.log(border.mid);
|
|
420
|
+
line(chalk_1.default.bold("\u{1F4B0} TRADE SETUP"));
|
|
421
|
+
line(` Entry: ${chalk_1.default.white(formatPrice(analysis.tradeSetup.entry))}`);
|
|
422
|
+
line(` Stop Loss: ${chalk_1.default.red(formatPrice(analysis.tradeSetup.stopLoss))} (${chalk_1.default.red("-" +
|
|
423
|
+
(((analysis.tradeSetup.entry - analysis.tradeSetup.stopLoss) / analysis.tradeSetup.entry) *
|
|
424
|
+
100).toFixed(1) +
|
|
425
|
+
"%")})`);
|
|
426
|
+
line(` Target 1: ${chalk_1.default.green(formatPrice(analysis.tradeSetup.target1))} (${chalk_1.default.green("+" +
|
|
427
|
+
(((analysis.tradeSetup.target1 - analysis.tradeSetup.entry) / analysis.tradeSetup.entry) *
|
|
428
|
+
100).toFixed(1) +
|
|
429
|
+
"%")})`);
|
|
430
|
+
line(` Target 2: ${chalk_1.default.green(formatPrice(analysis.tradeSetup.target2))} (${chalk_1.default.green("+" +
|
|
431
|
+
(((analysis.tradeSetup.target2 - analysis.tradeSetup.entry) / analysis.tradeSetup.entry) *
|
|
432
|
+
100).toFixed(1) +
|
|
433
|
+
"%")})`);
|
|
434
|
+
line(` R/R Ratio: ${chalk_1.default.cyan(analysis.tradeSetup.riskRewardRatio + ":1")}`);
|
|
435
|
+
// Multi-Timeframe
|
|
436
|
+
console.log(border.mid);
|
|
437
|
+
line(chalk_1.default.bold("\u{1F4C8} MULTI-TIMEFRAME ANALYSIS"));
|
|
438
|
+
const tfIcon = (signal) => signal === "bullish"
|
|
439
|
+
? chalk_1.default.green("\u{2191}")
|
|
440
|
+
: signal === "bearish"
|
|
441
|
+
? chalk_1.default.red("\u{2193}")
|
|
442
|
+
: chalk_1.default.yellow("\u{2192}");
|
|
443
|
+
line(` 1H: ${tfIcon(analysis.timeframes.short.signal)} ${analysis.timeframes.short.signal.padEnd(8)} | RSI: ${analysis.timeframes.short.rsi.current.toFixed(0)}`);
|
|
444
|
+
line(` 4H: ${tfIcon(analysis.timeframes.medium.signal)} ${analysis.timeframes.medium.signal.padEnd(8)} | RSI: ${analysis.timeframes.medium.rsi.current.toFixed(0)}`);
|
|
445
|
+
line(` 1D: ${tfIcon(analysis.timeframes.long.signal)} ${analysis.timeframes.long.signal.padEnd(8)} | RSI: ${analysis.timeframes.long.rsi.current.toFixed(0)}`);
|
|
446
|
+
const alignmentColor = analysis.timeframeAlignment === "aligned_bullish"
|
|
447
|
+
? chalk_1.default.green
|
|
448
|
+
: analysis.timeframeAlignment === "aligned_bearish"
|
|
449
|
+
? chalk_1.default.red
|
|
450
|
+
: chalk_1.default.yellow;
|
|
451
|
+
line(` Alignment: ${alignmentColor(analysis.timeframeAlignment.replace(/_/g, " "))}`);
|
|
452
|
+
// Indicators
|
|
453
|
+
console.log(border.mid);
|
|
454
|
+
line(chalk_1.default.bold("\u{1F4CA} INDICATORS"));
|
|
455
|
+
// RSI
|
|
456
|
+
const rsiColor = analysis.indicators.rsi.condition === "overbought"
|
|
457
|
+
? chalk_1.default.red
|
|
458
|
+
: analysis.indicators.rsi.condition === "oversold"
|
|
459
|
+
? chalk_1.default.green
|
|
460
|
+
: chalk_1.default.white;
|
|
461
|
+
line(` RSI(14): ${rsiColor(analysis.indicators.rsi.current.toFixed(1))} (${analysis.indicators.rsi.condition})${analysis.indicators.rsi.divergence !== "none"
|
|
462
|
+
? chalk_1.default.magenta(` - ${analysis.indicators.rsi.divergence} div`)
|
|
463
|
+
: ""}`);
|
|
464
|
+
// MACD
|
|
465
|
+
const macdColor = analysis.indicators.macd.crossover === "bullish"
|
|
466
|
+
? chalk_1.default.green
|
|
467
|
+
: analysis.indicators.macd.crossover === "bearish"
|
|
468
|
+
? chalk_1.default.red
|
|
469
|
+
: chalk_1.default.gray;
|
|
470
|
+
line(` MACD: ${macdColor(analysis.indicators.macd.crossover)} | momentum ${analysis.indicators.macd.momentum}`);
|
|
471
|
+
// Bollinger
|
|
472
|
+
const bbPosition = analysis.indicators.bollinger.pricePosition.replace(/_/g, " ");
|
|
473
|
+
line(` Bollinger: ${bbPosition}${analysis.indicators.bollinger.squeeze ? chalk_1.default.yellow(" [SQUEEZE]") : ""}`);
|
|
474
|
+
// Volume
|
|
475
|
+
const volColor = analysis.indicators.volume.volumeRatio > 1.2
|
|
476
|
+
? chalk_1.default.green
|
|
477
|
+
: analysis.indicators.volume.volumeRatio < 0.8
|
|
478
|
+
? chalk_1.default.red
|
|
479
|
+
: chalk_1.default.white;
|
|
480
|
+
line(` Volume: ${volColor(analysis.indicators.volume.volumeRatio.toFixed(1) + "x")} avg | ${analysis.indicators.volume.trend}`);
|
|
481
|
+
// ATR
|
|
482
|
+
const atrColor = analysis.indicators.atr.volatility === "high"
|
|
483
|
+
? chalk_1.default.red
|
|
484
|
+
: analysis.indicators.atr.volatility === "low"
|
|
485
|
+
? chalk_1.default.green
|
|
486
|
+
: chalk_1.default.yellow;
|
|
487
|
+
line(` Volatility: ${atrColor(analysis.indicators.atr.volatility)} (ATR: ${analysis.indicators.atr.percentOfPrice.toFixed(1)}%)`);
|
|
488
|
+
// Key Levels
|
|
489
|
+
console.log(border.mid);
|
|
490
|
+
line(chalk_1.default.bold("\u{1F511} KEY LEVELS"));
|
|
491
|
+
line(` Support: ${chalk_1.default.green(formatPrice(analysis.indicators.supportResistance.nearestSupport))} (${analysis.indicators.supportResistance.distanceToSupport.toFixed(1)}% away)`);
|
|
492
|
+
line(` Resistance: ${chalk_1.default.red(formatPrice(analysis.indicators.supportResistance.nearestResistance))} (${analysis.indicators.supportResistance.distanceToResistance.toFixed(1)}% away)`);
|
|
493
|
+
line(` EMA21: ${chalk_1.default.gray(formatPrice(analysis.timeframes.medium.ema.ema21))}`);
|
|
494
|
+
line(` EMA50: ${chalk_1.default.gray(formatPrice(analysis.timeframes.medium.ema.ema50))}`);
|
|
495
|
+
line(` EMA200: ${chalk_1.default.gray(formatPrice(analysis.timeframes.medium.ema.ema200))}`);
|
|
496
|
+
// Market Condition
|
|
497
|
+
console.log(border.mid);
|
|
498
|
+
line(chalk_1.default.bold(`\u{1F30A} MARKET: ${analysis.marketCondition.type.toUpperCase()}`));
|
|
499
|
+
const conditionLines = wordWrap(analysis.marketCondition.tradingAdvice, contentWidth - 3);
|
|
500
|
+
conditionLines.forEach((l) => line(chalk_1.default.gray(` ${l}`)));
|
|
501
|
+
// Bullish/Bearish Factors
|
|
502
|
+
if (analysis.reasoning.bullishFactors.length > 0 ||
|
|
503
|
+
analysis.reasoning.bearishFactors.length > 0) {
|
|
504
|
+
console.log(border.mid);
|
|
505
|
+
if (analysis.reasoning.bullishFactors.length > 0) {
|
|
506
|
+
line(chalk_1.default.green.bold("\u{2705} BULLISH FACTORS"));
|
|
507
|
+
analysis.reasoning.bullishFactors.slice(0, 3).forEach((f) => {
|
|
508
|
+
const lines = wordWrap(f, contentWidth - 5);
|
|
509
|
+
lines.forEach((l, i) => line(chalk_1.default.green(` ${i === 0 ? "\u{2022}" : " "} ${l}`)));
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
if (analysis.reasoning.bearishFactors.length > 0) {
|
|
513
|
+
line(chalk_1.default.red.bold("\u{274C} BEARISH FACTORS"));
|
|
514
|
+
analysis.reasoning.bearishFactors.slice(0, 3).forEach((f) => {
|
|
515
|
+
const lines = wordWrap(f, contentWidth - 5);
|
|
516
|
+
lines.forEach((l, i) => line(chalk_1.default.red(` ${i === 0 ? "\u{2022}" : " "} ${l}`)));
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
// Warnings
|
|
521
|
+
if (analysis.reasoning.warnings.length > 0) {
|
|
522
|
+
console.log(border.mid);
|
|
523
|
+
line(chalk_1.default.yellow.bold("\u{26A0}\u{FE0F} WARNINGS"));
|
|
524
|
+
analysis.reasoning.warnings.forEach((w) => {
|
|
525
|
+
const lines = wordWrap(w, contentWidth - 5);
|
|
526
|
+
lines.forEach((l, i) => line(chalk_1.default.yellow(` ${i === 0 ? "\u{2022}" : " "} ${l}`)));
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
// AI Analysis
|
|
530
|
+
if (aiAnalysis) {
|
|
531
|
+
console.log(border.mid);
|
|
532
|
+
line(chalk_1.default.magenta.bold("\u{1F916} AI ANALYSIS"));
|
|
533
|
+
const aiLines = wordWrap(aiAnalysis, contentWidth - 3);
|
|
534
|
+
aiLines.forEach((l) => line(chalk_1.default.white(` ${l}`)));
|
|
535
|
+
}
|
|
536
|
+
// Footer
|
|
537
|
+
console.log(border.bot);
|
|
538
|
+
console.log("");
|
|
539
|
+
console.log(chalk_1.default.gray.italic(" \u{26A0}\u{FE0F} This is not financial advice. Always do your own research."));
|
|
540
|
+
console.log("");
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Perform and display comprehensive market analysis
|
|
544
|
+
*/
|
|
545
|
+
async function comprehensiveAnalysis(symbol) {
|
|
546
|
+
const spinner = (0, ora_1.default)(`Analyzing ${symbol.toUpperCase()} across multiple timeframes...`).start();
|
|
547
|
+
try {
|
|
548
|
+
spinner.text = "Fetching 1H, 4H, and 1D data...";
|
|
549
|
+
const analysis = await (0, market_analyzer_1.analyzeMarket)(symbol);
|
|
550
|
+
spinner.text = "Generating AI insights...";
|
|
551
|
+
const aiAnalysis = await generateComprehensiveAIAnalysis(analysis);
|
|
552
|
+
spinner.succeed(`Comprehensive analysis complete for ${analysis.symbol}`);
|
|
553
|
+
displayComprehensiveAnalysis(analysis, aiAnalysis);
|
|
554
|
+
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
spinner.fail(`Failed to analyze ${symbol}`);
|
|
557
|
+
console.log(chalk_1.default.red(`\nError: ${error.message}`));
|
|
558
|
+
}
|
|
559
|
+
}
|