prab-cli 1.2.0 → 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 +175 -4
- package/dist/lib/config.js +60 -1
- 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 +24 -0
- package/dist/lib/ui.js +70 -8
- package/package.json +1 -1
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SMC (Smart Money Concepts) Analyzer
|
|
4
|
+
* Combines SMC with traditional analysis for comprehensive trading signals
|
|
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.displaySMCAnalysis = displaySMCAnalysis;
|
|
11
|
+
exports.runSMCAnalysis = runSMCAnalysis;
|
|
12
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
13
|
+
const ora_1 = __importDefault(require("ora"));
|
|
14
|
+
const data_fetcher_1 = require("./data-fetcher");
|
|
15
|
+
const smc_indicators_1 = require("./smc-indicators");
|
|
16
|
+
const config_1 = require("../config");
|
|
17
|
+
const groq_provider_1 = require("../models/groq-provider");
|
|
18
|
+
const chart_visual_1 = require("./chart-visual");
|
|
19
|
+
// ============================================
|
|
20
|
+
// TRADE SETUP GENERATION
|
|
21
|
+
// ============================================
|
|
22
|
+
function generateSMCTradeSetup(smc, currentPrice) {
|
|
23
|
+
const { marketStructure, orderBlocks, fairValueGaps, liquidity, premiumDiscount, bias } = smc;
|
|
24
|
+
const setup = {
|
|
25
|
+
bias: bias.direction === "bullish" ? "long" : bias.direction === "bearish" ? "short" : "neutral",
|
|
26
|
+
confidence: bias.confidence,
|
|
27
|
+
entry: {
|
|
28
|
+
type: "structure_break",
|
|
29
|
+
zone: { low: currentPrice * 0.99, high: currentPrice * 1.01 },
|
|
30
|
+
trigger: "Wait for confirmation",
|
|
31
|
+
},
|
|
32
|
+
stopLoss: currentPrice * (bias.direction === "bullish" ? 0.97 : 1.03),
|
|
33
|
+
targets: [],
|
|
34
|
+
riskReward: 0,
|
|
35
|
+
invalidation: "",
|
|
36
|
+
};
|
|
37
|
+
// Determine best entry based on SMC confluence
|
|
38
|
+
if (bias.direction === "bullish") {
|
|
39
|
+
// Look for bullish entry
|
|
40
|
+
if (orderBlocks.nearest?.type === "bullish" && !orderBlocks.nearest.mitigated) {
|
|
41
|
+
const ob = orderBlocks.nearest;
|
|
42
|
+
setup.entry = {
|
|
43
|
+
type: "order_block",
|
|
44
|
+
zone: { low: ob.bottom, high: ob.top },
|
|
45
|
+
trigger: `Enter on bullish reaction from OB zone`,
|
|
46
|
+
};
|
|
47
|
+
setup.stopLoss = ob.bottom * 0.99;
|
|
48
|
+
}
|
|
49
|
+
else if (fairValueGaps.unfilled.some((f) => f.type === "bullish")) {
|
|
50
|
+
const fvg = fairValueGaps.unfilled.find((f) => f.type === "bullish");
|
|
51
|
+
setup.entry = {
|
|
52
|
+
type: "fvg",
|
|
53
|
+
zone: { low: fvg.bottom, high: fvg.top },
|
|
54
|
+
trigger: `Enter on fill of bullish FVG`,
|
|
55
|
+
};
|
|
56
|
+
setup.stopLoss = fvg.bottom * 0.99;
|
|
57
|
+
}
|
|
58
|
+
else if (premiumDiscount.zone === "discount") {
|
|
59
|
+
setup.entry = {
|
|
60
|
+
type: "liquidity_sweep",
|
|
61
|
+
zone: { low: premiumDiscount.rangeLow, high: premiumDiscount.equilibrium },
|
|
62
|
+
trigger: `Enter in discount zone after sweep of lows`,
|
|
63
|
+
};
|
|
64
|
+
setup.stopLoss = premiumDiscount.rangeLow * 0.99;
|
|
65
|
+
}
|
|
66
|
+
// Set targets based on liquidity
|
|
67
|
+
if (liquidity.buySide.length > 0) {
|
|
68
|
+
setup.targets = liquidity.buySide.slice(0, 3).map((l) => l.level);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
setup.targets = [currentPrice * 1.02, currentPrice * 1.04, premiumDiscount.rangeHigh];
|
|
72
|
+
}
|
|
73
|
+
setup.invalidation = `Break below ${marketStructure.swingLows[marketStructure.swingLows.length - 1]?.price.toFixed(2) || "recent low"}`;
|
|
74
|
+
}
|
|
75
|
+
else if (bias.direction === "bearish") {
|
|
76
|
+
// Look for bearish entry
|
|
77
|
+
if (orderBlocks.nearest?.type === "bearish" && !orderBlocks.nearest.mitigated) {
|
|
78
|
+
const ob = orderBlocks.nearest;
|
|
79
|
+
setup.entry = {
|
|
80
|
+
type: "order_block",
|
|
81
|
+
zone: { low: ob.bottom, high: ob.top },
|
|
82
|
+
trigger: `Enter on bearish rejection from OB zone`,
|
|
83
|
+
};
|
|
84
|
+
setup.stopLoss = ob.top * 1.01;
|
|
85
|
+
}
|
|
86
|
+
else if (fairValueGaps.unfilled.some((f) => f.type === "bearish")) {
|
|
87
|
+
const fvg = fairValueGaps.unfilled.find((f) => f.type === "bearish");
|
|
88
|
+
setup.entry = {
|
|
89
|
+
type: "fvg",
|
|
90
|
+
zone: { low: fvg.bottom, high: fvg.top },
|
|
91
|
+
trigger: `Enter on fill of bearish FVG`,
|
|
92
|
+
};
|
|
93
|
+
setup.stopLoss = fvg.top * 1.01;
|
|
94
|
+
}
|
|
95
|
+
else if (premiumDiscount.zone === "premium") {
|
|
96
|
+
setup.entry = {
|
|
97
|
+
type: "liquidity_sweep",
|
|
98
|
+
zone: { low: premiumDiscount.equilibrium, high: premiumDiscount.rangeHigh },
|
|
99
|
+
trigger: `Enter in premium zone after sweep of highs`,
|
|
100
|
+
};
|
|
101
|
+
setup.stopLoss = premiumDiscount.rangeHigh * 1.01;
|
|
102
|
+
}
|
|
103
|
+
// Set targets based on liquidity
|
|
104
|
+
if (liquidity.sellSide.length > 0) {
|
|
105
|
+
setup.targets = liquidity.sellSide.slice(0, 3).map((l) => l.level);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
setup.targets = [currentPrice * 0.98, currentPrice * 0.96, premiumDiscount.rangeLow];
|
|
109
|
+
}
|
|
110
|
+
setup.invalidation = `Break above ${marketStructure.swingHighs[marketStructure.swingHighs.length - 1]?.price.toFixed(2) || "recent high"}`;
|
|
111
|
+
}
|
|
112
|
+
// Calculate R:R
|
|
113
|
+
const entryPrice = (setup.entry.zone.low + setup.entry.zone.high) / 2;
|
|
114
|
+
const risk = Math.abs(entryPrice - setup.stopLoss);
|
|
115
|
+
const reward = setup.targets.length > 1 ? Math.abs(setup.targets[1] - entryPrice) : risk * 2;
|
|
116
|
+
setup.riskReward = Math.round((reward / risk) * 10) / 10;
|
|
117
|
+
return setup;
|
|
118
|
+
}
|
|
119
|
+
// ============================================
|
|
120
|
+
// AI ANALYSIS
|
|
121
|
+
// ============================================
|
|
122
|
+
async function generateSMCAIAnalysis(analysis) {
|
|
123
|
+
const apiKey = (0, config_1.getApiKey)();
|
|
124
|
+
if (!apiKey)
|
|
125
|
+
return "AI analysis unavailable (no API key configured)";
|
|
126
|
+
const modelConfig = (0, config_1.getModelConfig)();
|
|
127
|
+
const provider = new groq_provider_1.GroqProvider(modelConfig.modelId, 0.7);
|
|
128
|
+
provider.initialize(apiKey, modelConfig.modelId);
|
|
129
|
+
const { smc, tradeSetup, currentPrice } = analysis;
|
|
130
|
+
const prompt = `You are an expert Smart Money Concepts (SMC) trader. Analyze this setup and provide actionable advice (4-5 sentences).
|
|
131
|
+
|
|
132
|
+
Symbol: ${analysis.symbol}
|
|
133
|
+
Current Price: $${currentPrice.toFixed(2)}
|
|
134
|
+
24h Change: ${analysis.priceChange24h.toFixed(2)}%
|
|
135
|
+
|
|
136
|
+
MARKET STRUCTURE:
|
|
137
|
+
- Trend: ${smc.marketStructure.trend}
|
|
138
|
+
- Last BOS: ${smc.marketStructure.lastBOS ? `${smc.marketStructure.lastBOS.direction} at $${smc.marketStructure.lastBOS.level.toFixed(2)}` : "None"}
|
|
139
|
+
- Last CHoCH: ${smc.marketStructure.lastCHoCH ? `${smc.marketStructure.lastCHoCH.direction} at $${smc.marketStructure.lastCHoCH.level.toFixed(2)}` : "None"}
|
|
140
|
+
|
|
141
|
+
ORDER BLOCKS:
|
|
142
|
+
- Bullish OBs: ${smc.orderBlocks.bullish.length} (Nearest: ${smc.orderBlocks.nearest?.type === "bullish" ? `$${smc.orderBlocks.nearest.bottom.toFixed(2)}-$${smc.orderBlocks.nearest.top.toFixed(2)}` : "N/A"})
|
|
143
|
+
- Bearish OBs: ${smc.orderBlocks.bearish.length} (Nearest: ${smc.orderBlocks.nearest?.type === "bearish" ? `$${smc.orderBlocks.nearest.bottom.toFixed(2)}-$${smc.orderBlocks.nearest.top.toFixed(2)}` : "N/A"})
|
|
144
|
+
|
|
145
|
+
FAIR VALUE GAPS:
|
|
146
|
+
- Unfilled: ${smc.fairValueGaps.unfilled.length}
|
|
147
|
+
- Bullish FVGs above: ${smc.fairValueGaps.bullish.filter((f) => !f.filled && f.bottom > currentPrice).length}
|
|
148
|
+
- Bearish FVGs below: ${smc.fairValueGaps.bearish.filter((f) => !f.filled && f.top < currentPrice).length}
|
|
149
|
+
|
|
150
|
+
LIQUIDITY:
|
|
151
|
+
- Buy-side (above): ${smc.liquidity.buySide.map((l) => `$${l.level.toFixed(2)}`).join(", ") || "None"}
|
|
152
|
+
- Sell-side (below): ${smc.liquidity.sellSide.map((l) => `$${l.level.toFixed(2)}`).join(", ") || "None"}
|
|
153
|
+
|
|
154
|
+
PREMIUM/DISCOUNT:
|
|
155
|
+
- Zone: ${smc.premiumDiscount.zone} (${smc.premiumDiscount.fibLevel.toFixed(0)}% of range)
|
|
156
|
+
- Range: $${smc.premiumDiscount.rangeLow.toFixed(2)} - $${smc.premiumDiscount.rangeHigh.toFixed(2)}
|
|
157
|
+
- Equilibrium: $${smc.premiumDiscount.equilibrium.toFixed(2)}
|
|
158
|
+
|
|
159
|
+
TRADE SETUP:
|
|
160
|
+
- Bias: ${tradeSetup.bias.toUpperCase()}
|
|
161
|
+
- Entry Type: ${tradeSetup.entry.type}
|
|
162
|
+
- Entry Zone: $${tradeSetup.entry.zone.low.toFixed(2)} - $${tradeSetup.entry.zone.high.toFixed(2)}
|
|
163
|
+
- Stop Loss: $${tradeSetup.stopLoss.toFixed(2)}
|
|
164
|
+
- Targets: ${tradeSetup.targets.map((t) => `$${t.toFixed(2)}`).join(", ")}
|
|
165
|
+
- R:R: ${tradeSetup.riskReward}:1
|
|
166
|
+
|
|
167
|
+
SMC BIAS REASONING:
|
|
168
|
+
${smc.bias.reasoning.map((r) => `- ${r}`).join("\n")}
|
|
169
|
+
|
|
170
|
+
Provide SMC-focused analysis explaining:
|
|
171
|
+
1. Current market structure and institutional order flow
|
|
172
|
+
2. Where smart money is likely positioned
|
|
173
|
+
3. Best entry strategy (order block, FVG, or liquidity sweep)
|
|
174
|
+
4. Key levels to watch and when to enter
|
|
175
|
+
Be specific with prices and SMC terminology.`;
|
|
176
|
+
try {
|
|
177
|
+
const stream = provider.streamChat([{ role: "user", content: prompt }], []);
|
|
178
|
+
let response = "";
|
|
179
|
+
for await (const chunk of stream) {
|
|
180
|
+
if (chunk.content && typeof chunk.content === "string") {
|
|
181
|
+
response += chunk.content;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return response.trim();
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return `AI analysis unavailable: ${error.message}`;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// ============================================
|
|
191
|
+
// DISPLAY
|
|
192
|
+
// ============================================
|
|
193
|
+
function formatPrice(price) {
|
|
194
|
+
if (price < 0.01)
|
|
195
|
+
return `$${price.toFixed(6)}`;
|
|
196
|
+
if (price < 1)
|
|
197
|
+
return `$${price.toFixed(4)}`;
|
|
198
|
+
if (price < 100)
|
|
199
|
+
return `$${price.toFixed(2)}`;
|
|
200
|
+
return `$${price.toLocaleString(undefined, { maximumFractionDigits: 2 })}`;
|
|
201
|
+
}
|
|
202
|
+
function wordWrap(text, maxWidth) {
|
|
203
|
+
const words = text.split(" ");
|
|
204
|
+
const lines = [];
|
|
205
|
+
let currentLine = "";
|
|
206
|
+
for (const word of words) {
|
|
207
|
+
if (currentLine.length + word.length + 1 > maxWidth) {
|
|
208
|
+
lines.push(currentLine.trim());
|
|
209
|
+
currentLine = word + " ";
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
currentLine += word + " ";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (currentLine.trim())
|
|
216
|
+
lines.push(currentLine.trim());
|
|
217
|
+
return lines;
|
|
218
|
+
}
|
|
219
|
+
function displaySMCAnalysis(analysis, aiAnalysis) {
|
|
220
|
+
const boxWidth = 58;
|
|
221
|
+
const contentWidth = boxWidth - 4;
|
|
222
|
+
const border = {
|
|
223
|
+
top: chalk_1.default.magenta("\u{250C}" + "\u{2500}".repeat(boxWidth) + "\u{2510}"),
|
|
224
|
+
mid: chalk_1.default.magenta("\u{251C}" + "\u{2500}".repeat(boxWidth) + "\u{2524}"),
|
|
225
|
+
bot: chalk_1.default.magenta("\u{2514}" + "\u{2500}".repeat(boxWidth) + "\u{2518}"),
|
|
226
|
+
left: chalk_1.default.magenta("\u{2502}"),
|
|
227
|
+
right: chalk_1.default.magenta("\u{2502}"),
|
|
228
|
+
};
|
|
229
|
+
const line = (content, pad = contentWidth) => {
|
|
230
|
+
console.log(border.left + " " + content.padEnd(pad) + " " + border.right);
|
|
231
|
+
};
|
|
232
|
+
const { smc, tradeSetup, currentPrice, priceChange24h } = analysis;
|
|
233
|
+
const changeColor = priceChange24h >= 0 ? chalk_1.default.green : chalk_1.default.red;
|
|
234
|
+
const changeSign = priceChange24h >= 0 ? "+" : "";
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log(border.top);
|
|
237
|
+
// Header
|
|
238
|
+
line(chalk_1.default.bold.white(`\u{1F3E6} ${analysis.symbol} - Smart Money Analysis`));
|
|
239
|
+
line(chalk_1.default.bold.yellow(`Price: ${formatPrice(currentPrice)}`) +
|
|
240
|
+
` ${changeColor(changeSign + priceChange24h.toFixed(2) + "%")}`);
|
|
241
|
+
// Market Structure
|
|
242
|
+
console.log(border.mid);
|
|
243
|
+
line(chalk_1.default.bold("\u{1F4CA} MARKET STRUCTURE"));
|
|
244
|
+
const trendColor = smc.marketStructure.trend === "bullish"
|
|
245
|
+
? chalk_1.default.green
|
|
246
|
+
: smc.marketStructure.trend === "bearish"
|
|
247
|
+
? chalk_1.default.red
|
|
248
|
+
: chalk_1.default.yellow;
|
|
249
|
+
line(` Trend: ${trendColor(smc.marketStructure.trend.toUpperCase())}`);
|
|
250
|
+
if (smc.marketStructure.lastBOS) {
|
|
251
|
+
const bosColor = smc.marketStructure.lastBOS.direction === "bullish" ? chalk_1.default.green : chalk_1.default.red;
|
|
252
|
+
line(` Last BOS: ${bosColor(smc.marketStructure.lastBOS.direction)} @ ${formatPrice(smc.marketStructure.lastBOS.level)}`);
|
|
253
|
+
}
|
|
254
|
+
if (smc.marketStructure.lastCHoCH) {
|
|
255
|
+
const chochColor = smc.marketStructure.lastCHoCH.direction === "bullish" ? chalk_1.default.green : chalk_1.default.red;
|
|
256
|
+
line(` Last CHoCH: ${chochColor(smc.marketStructure.lastCHoCH.direction)} @ ${formatPrice(smc.marketStructure.lastCHoCH.level)}`);
|
|
257
|
+
}
|
|
258
|
+
// Order Blocks
|
|
259
|
+
console.log(border.mid);
|
|
260
|
+
line(chalk_1.default.bold("\u{1F4E6} ORDER BLOCKS"));
|
|
261
|
+
line(` Bullish OBs: ${chalk_1.default.green(smc.orderBlocks.bullish.length.toString())}`);
|
|
262
|
+
line(` Bearish OBs: ${chalk_1.default.red(smc.orderBlocks.bearish.length.toString())}`);
|
|
263
|
+
if (smc.orderBlocks.nearest) {
|
|
264
|
+
const ob = smc.orderBlocks.nearest;
|
|
265
|
+
const obColor = ob.type === "bullish" ? chalk_1.default.green : chalk_1.default.red;
|
|
266
|
+
line(` Nearest: ${obColor(ob.type)} ${formatPrice(ob.bottom)} - ${formatPrice(ob.top)}`);
|
|
267
|
+
line(` Strength: ${ob.strength} | Mitigated: ${ob.mitigated ? "Yes" : "No"}`);
|
|
268
|
+
}
|
|
269
|
+
// Fair Value Gaps
|
|
270
|
+
console.log(border.mid);
|
|
271
|
+
line(chalk_1.default.bold("\u{26A1} FAIR VALUE GAPS"));
|
|
272
|
+
line(` Unfilled FVGs: ${chalk_1.default.yellow(smc.fairValueGaps.unfilled.length.toString())}`);
|
|
273
|
+
smc.fairValueGaps.unfilled.slice(0, 2).forEach((fvg) => {
|
|
274
|
+
const fvgColor = fvg.type === "bullish" ? chalk_1.default.green : chalk_1.default.red;
|
|
275
|
+
line(` ${fvgColor(fvg.type)}: ${formatPrice(fvg.bottom)} - ${formatPrice(fvg.top)}`);
|
|
276
|
+
});
|
|
277
|
+
// Liquidity
|
|
278
|
+
console.log(border.mid);
|
|
279
|
+
line(chalk_1.default.bold("\u{1F4B0} LIQUIDITY POOLS"));
|
|
280
|
+
if (smc.liquidity.buySide.length > 0) {
|
|
281
|
+
line(chalk_1.default.cyan(" Buy-side (stops above):"));
|
|
282
|
+
smc.liquidity.buySide.slice(0, 2).forEach((l) => {
|
|
283
|
+
line(` ${formatPrice(l.level)} (${l.strength} touch${l.strength > 1 ? "es" : ""})`);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
if (smc.liquidity.sellSide.length > 0) {
|
|
287
|
+
line(chalk_1.default.cyan(" Sell-side (stops below):"));
|
|
288
|
+
smc.liquidity.sellSide.slice(0, 2).forEach((l) => {
|
|
289
|
+
line(` ${formatPrice(l.level)} (${l.strength} touch${l.strength > 1 ? "es" : ""})`);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
// Premium/Discount
|
|
293
|
+
console.log(border.mid);
|
|
294
|
+
line(chalk_1.default.bold("\u{1F3AF} PREMIUM/DISCOUNT"));
|
|
295
|
+
const zoneColor = smc.premiumDiscount.zone === "discount"
|
|
296
|
+
? chalk_1.default.green
|
|
297
|
+
: smc.premiumDiscount.zone === "premium"
|
|
298
|
+
? chalk_1.default.red
|
|
299
|
+
: chalk_1.default.yellow;
|
|
300
|
+
line(` Zone: ${zoneColor(smc.premiumDiscount.zone.toUpperCase())} (${smc.premiumDiscount.fibLevel.toFixed(0)}%)`);
|
|
301
|
+
line(` Range: ${formatPrice(smc.premiumDiscount.rangeLow)} - ${formatPrice(smc.premiumDiscount.rangeHigh)}`);
|
|
302
|
+
line(` Equilibrium: ${formatPrice(smc.premiumDiscount.equilibrium)}`);
|
|
303
|
+
// Trade Setup
|
|
304
|
+
console.log(border.mid);
|
|
305
|
+
const biasColor = tradeSetup.bias === "long"
|
|
306
|
+
? chalk_1.default.green.bold
|
|
307
|
+
: tradeSetup.bias === "short"
|
|
308
|
+
? chalk_1.default.red.bold
|
|
309
|
+
: chalk_1.default.yellow.bold;
|
|
310
|
+
const biasIcon = tradeSetup.bias === "long"
|
|
311
|
+
? "\u{1F7E2}"
|
|
312
|
+
: tradeSetup.bias === "short"
|
|
313
|
+
? "\u{1F534}"
|
|
314
|
+
: "\u{1F7E1}";
|
|
315
|
+
line(chalk_1.default.bold(`\u{1F4DD} TRADE SETUP: ${biasIcon} ${biasColor(tradeSetup.bias.toUpperCase())}`));
|
|
316
|
+
line(` Confidence: ${chalk_1.default.white(tradeSetup.confidence + "%")}`);
|
|
317
|
+
line(` Entry Type: ${chalk_1.default.cyan(tradeSetup.entry.type.replace(/_/g, " "))}`);
|
|
318
|
+
line(` Entry Zone: ${chalk_1.default.white(formatPrice(tradeSetup.entry.zone.low))} - ${chalk_1.default.white(formatPrice(tradeSetup.entry.zone.high))}`);
|
|
319
|
+
line(` Stop Loss: ${chalk_1.default.red(formatPrice(tradeSetup.stopLoss))}`);
|
|
320
|
+
line(` Targets:`);
|
|
321
|
+
tradeSetup.targets.slice(0, 3).forEach((t, i) => {
|
|
322
|
+
const pct = ((t - currentPrice) / currentPrice) * 100;
|
|
323
|
+
const pctStr = pct >= 0 ? `+${pct.toFixed(1)}%` : `${pct.toFixed(1)}%`;
|
|
324
|
+
line(` T${i + 1}: ${chalk_1.default.green(formatPrice(t))} (${chalk_1.default.green(pctStr)})`);
|
|
325
|
+
});
|
|
326
|
+
line(` R:R Ratio: ${chalk_1.default.cyan(tradeSetup.riskReward + ":1")}`);
|
|
327
|
+
// SMC Bias Reasoning
|
|
328
|
+
console.log(border.mid);
|
|
329
|
+
line(chalk_1.default.bold("\u{1F9E0} SMC REASONING"));
|
|
330
|
+
smc.bias.reasoning.slice(0, 4).forEach((r) => {
|
|
331
|
+
const lines = wordWrap(r, contentWidth - 5);
|
|
332
|
+
lines.forEach((l, i) => line(chalk_1.default.gray(` ${i === 0 ? "\u{2022}" : " "} ${l}`)));
|
|
333
|
+
});
|
|
334
|
+
// AI Analysis
|
|
335
|
+
if (aiAnalysis) {
|
|
336
|
+
console.log(border.mid);
|
|
337
|
+
line(chalk_1.default.bold.magenta("\u{1F916} AI SMC ANALYSIS"));
|
|
338
|
+
const aiLines = wordWrap(aiAnalysis, contentWidth - 3);
|
|
339
|
+
aiLines.forEach((l) => line(chalk_1.default.white(` ${l}`)));
|
|
340
|
+
}
|
|
341
|
+
console.log(border.bot);
|
|
342
|
+
// ============================================
|
|
343
|
+
// VISUAL CHARTS SECTION
|
|
344
|
+
// ============================================
|
|
345
|
+
console.log("");
|
|
346
|
+
console.log(chalk_1.default.bold.cyan(" ═══════════════════════════════════════════════════════"));
|
|
347
|
+
console.log(chalk_1.default.bold.cyan(" 📊 VISUAL ANALYSIS "));
|
|
348
|
+
console.log(chalk_1.default.bold.cyan(" ═══════════════════════════════════════════════════════"));
|
|
349
|
+
// Market Structure Visual
|
|
350
|
+
(0, chart_visual_1.createMarketStructureVisual)(smc).forEach((l) => console.log(l));
|
|
351
|
+
// Price Candlestick Chart (if candles available)
|
|
352
|
+
if (analysis.candles && analysis.candles.length > 0) {
|
|
353
|
+
console.log(chalk_1.default.bold.white(" ┌─────────────────────────────────────────────┐"));
|
|
354
|
+
console.log(chalk_1.default.bold.white(" │") +
|
|
355
|
+
chalk_1.default.bold.yellow(" PRICE ACTION (Last 50 Candles) ") +
|
|
356
|
+
chalk_1.default.bold.white("│"));
|
|
357
|
+
console.log(chalk_1.default.bold.white(" └─────────────────────────────────────────────┘"));
|
|
358
|
+
console.log("");
|
|
359
|
+
const candleChart = (0, chart_visual_1.createCandlestickChart)(analysis.candles, 45, 12);
|
|
360
|
+
candleChart.forEach((l) => console.log(" " + l));
|
|
361
|
+
console.log(chalk_1.default.gray(" └" + "─".repeat(45) + "┘"));
|
|
362
|
+
console.log(chalk_1.default.gray(" " +
|
|
363
|
+
chalk_1.default.green("█ Bullish") +
|
|
364
|
+
" " +
|
|
365
|
+
chalk_1.default.red("░ Bearish") +
|
|
366
|
+
" " +
|
|
367
|
+
chalk_1.default.gray("│ Wick")));
|
|
368
|
+
console.log("");
|
|
369
|
+
}
|
|
370
|
+
// Order Block Visual
|
|
371
|
+
(0, chart_visual_1.createOrderBlockVisual)(smc.orderBlocks, currentPrice).forEach((l) => console.log(l));
|
|
372
|
+
// FVG Visual
|
|
373
|
+
(0, chart_visual_1.createFVGVisual)(smc.fairValueGaps, currentPrice).forEach((l) => console.log(l));
|
|
374
|
+
// Liquidity Visual
|
|
375
|
+
(0, chart_visual_1.createLiquidityVisual)(smc.liquidity, currentPrice).forEach((l) => console.log(l));
|
|
376
|
+
// Trade Setup Visual
|
|
377
|
+
const entryMid = (tradeSetup.entry.zone.low + tradeSetup.entry.zone.high) / 2;
|
|
378
|
+
(0, chart_visual_1.createTradeSetupVisual)(currentPrice, entryMid, tradeSetup.stopLoss, tradeSetup.targets, tradeSetup.bias).forEach((l) => console.log(l));
|
|
379
|
+
// SMC Price Level Chart
|
|
380
|
+
console.log("");
|
|
381
|
+
const smcChart = (0, chart_visual_1.createSMCVisualChart)(currentPrice, smc, tradeSetup);
|
|
382
|
+
smcChart.forEach((l) => console.log(l));
|
|
383
|
+
console.log("");
|
|
384
|
+
console.log(chalk_1.default.gray.italic(" \u{26A0}\u{FE0F} This is not financial advice. Always do your own research."));
|
|
385
|
+
console.log("");
|
|
386
|
+
}
|
|
387
|
+
// ============================================
|
|
388
|
+
// MAIN FUNCTION
|
|
389
|
+
// ============================================
|
|
390
|
+
async function runSMCAnalysis(symbol) {
|
|
391
|
+
const spinner = (0, ora_1.default)(`Analyzing ${symbol.toUpperCase()} with Smart Money Concepts...`).start();
|
|
392
|
+
try {
|
|
393
|
+
spinner.text = "Fetching market data...";
|
|
394
|
+
const data = await (0, data_fetcher_1.fetchCryptoData)(symbol, "4h", 200);
|
|
395
|
+
spinner.text = "Identifying order blocks & FVGs...";
|
|
396
|
+
const smc = (0, smc_indicators_1.analyzeSMC)(data.candles);
|
|
397
|
+
spinner.text = "Generating trade setup...";
|
|
398
|
+
const tradeSetup = generateSMCTradeSetup(smc, data.currentPrice);
|
|
399
|
+
const analysis = {
|
|
400
|
+
symbol: data.symbol,
|
|
401
|
+
currentPrice: data.currentPrice,
|
|
402
|
+
priceChange24h: data.priceChangePercent24h,
|
|
403
|
+
smc,
|
|
404
|
+
tradeSetup,
|
|
405
|
+
confluence: smc.bias.reasoning,
|
|
406
|
+
warnings: [],
|
|
407
|
+
candles: data.candles,
|
|
408
|
+
};
|
|
409
|
+
spinner.text = "Getting AI insights...";
|
|
410
|
+
const aiAnalysis = await generateSMCAIAnalysis(analysis);
|
|
411
|
+
spinner.succeed(`SMC analysis complete for ${data.symbol}`);
|
|
412
|
+
displaySMCAnalysis(analysis, aiAnalysis);
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
spinner.fail(`Failed to analyze ${symbol}`);
|
|
416
|
+
console.log(chalk_1.default.red(`\nError: ${error.message}`));
|
|
417
|
+
}
|
|
418
|
+
}
|