prab-cli 1.2.6 → 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.
@@ -13,6 +13,8 @@ exports.quickSignal = quickSignal;
13
13
  exports.fullSignal = fullSignal;
14
14
  exports.displayComprehensiveAnalysis = displayComprehensiveAnalysis;
15
15
  exports.comprehensiveAnalysis = comprehensiveAnalysis;
16
+ exports.displayStrategyResult = displayStrategyResult;
17
+ exports.runSmartStrategy = runSmartStrategy;
16
18
  const chalk_1 = __importDefault(require("chalk"));
17
19
  const ora_1 = __importDefault(require("ora"));
18
20
  const data_fetcher_1 = require("./data-fetcher");
@@ -221,14 +223,31 @@ async function displaySignal(result) {
221
223
  console.log(chalk_1.default.cyan("\u{2502}") +
222
224
  ` Trend: ${trendIcon} ${chalk_1.default.white(signal.indicators.trend)}`.padEnd(53) +
223
225
  chalk_1.default.cyan("\u{2502}"));
224
- // EMA Values
226
+ // EMA Values with Tilt
225
227
  console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
226
228
  console.log(chalk_1.default.cyan("\u{2502}") + chalk_1.default.gray(" EMA Indicators:").padEnd(53) + chalk_1.default.cyan("\u{2502}"));
229
+ // EMA10 with tilt indicator
230
+ const ema10TiltIcon = signal.indicators.ema10Tilt.direction === "bullish"
231
+ ? chalk_1.default.green("\u{2191}")
232
+ : signal.indicators.ema10Tilt.direction === "bearish"
233
+ ? chalk_1.default.red("\u{2193}")
234
+ : chalk_1.default.gray("\u{2194}");
235
+ const ema10TiltColor = signal.indicators.ema10Tilt.strength === "HIGH"
236
+ ? chalk_1.default.green
237
+ : signal.indicators.ema10Tilt.strength === "MEDIUM"
238
+ ? chalk_1.default.yellow
239
+ : chalk_1.default.gray;
227
240
  console.log(chalk_1.default.cyan("\u{2502}") +
228
- chalk_1.default.gray(` EMA9: $${signal.indicators.currentEMA9.toFixed(2)}`).padEnd(44) +
241
+ ` EMA10: $${signal.indicators.currentEMA10.toFixed(2)} ${ema10TiltIcon} ${ema10TiltColor(signal.indicators.ema10Tilt.strength)}`.padEnd(52) +
229
242
  chalk_1.default.cyan("\u{2502}"));
243
+ // EMA20 with tilt
244
+ const ema20TiltIcon = signal.indicators.ema20Tilt.direction === "bullish"
245
+ ? chalk_1.default.green("\u{2191}")
246
+ : signal.indicators.ema20Tilt.direction === "bearish"
247
+ ? chalk_1.default.red("\u{2193}")
248
+ : chalk_1.default.gray("\u{2194}");
230
249
  console.log(chalk_1.default.cyan("\u{2502}") +
231
- chalk_1.default.gray(` EMA21: $${signal.indicators.currentEMA21.toFixed(2)}`).padEnd(44) +
250
+ ` EMA20: $${signal.indicators.currentEMA20.toFixed(2)} ${ema20TiltIcon}`.padEnd(52) +
232
251
  chalk_1.default.cyan("\u{2502}"));
233
252
  console.log(chalk_1.default.cyan("\u{2502}") +
234
253
  chalk_1.default.gray(` EMA50: $${signal.indicators.currentEMA50.toFixed(2)}`).padEnd(44) +
@@ -238,6 +257,50 @@ async function displaySignal(result) {
238
257
  chalk_1.default.gray(` EMA200: $${signal.indicators.currentEMA200.toFixed(2)}`).padEnd(44) +
239
258
  chalk_1.default.cyan("\u{2502}"));
240
259
  }
260
+ // Probability indicator
261
+ const probColor = signal.indicators.probability === "HIGH"
262
+ ? chalk_1.default.green
263
+ : signal.indicators.probability === "MEDIUM"
264
+ ? chalk_1.default.yellow
265
+ : chalk_1.default.gray;
266
+ console.log(chalk_1.default.cyan("\u{2502}") +
267
+ ` Probability: ${probColor(signal.indicators.probability)}`.padEnd(52) +
268
+ chalk_1.default.cyan("\u{2502}"));
269
+ // Market Condition indicator
270
+ const marketCondition = signal.indicators.marketCondition;
271
+ if (marketCondition) {
272
+ const conditionColor = marketCondition.shouldTrade ? chalk_1.default.green : chalk_1.default.red;
273
+ const conditionIcon = marketCondition.shouldTrade ? "\u{2705}" : "\u{26A0}";
274
+ console.log(chalk_1.default.cyan("\u{2502}") +
275
+ ` Market: ${conditionIcon} ${conditionColor(marketCondition.shouldTrade ? "TRADEABLE" : "AVOID")}`.padEnd(52) +
276
+ chalk_1.default.cyan("\u{2502}"));
277
+ // Show EMA separation
278
+ const separationColor = marketCondition.emaSeparationPercent > 0.3
279
+ ? chalk_1.default.green
280
+ : marketCondition.emaSeparationPercent > 0.15
281
+ ? chalk_1.default.yellow
282
+ : chalk_1.default.red;
283
+ console.log(chalk_1.default.cyan("\u{2502}") +
284
+ chalk_1.default
285
+ .gray(` EMA Sep: ${separationColor(marketCondition.emaSeparationPercent.toFixed(2) + "%")}`)
286
+ .padEnd(44) +
287
+ chalk_1.default.cyan("\u{2502}"));
288
+ // Show warning if not tradeable
289
+ if (!marketCondition.shouldTrade) {
290
+ const reasonTrunc = marketCondition.reason.length > 35
291
+ ? marketCondition.reason.substring(0, 32) + "..."
292
+ : marketCondition.reason;
293
+ console.log(chalk_1.default.cyan("\u{2502}") +
294
+ chalk_1.default.yellow(` ${reasonTrunc}`).padEnd(44) +
295
+ chalk_1.default.cyan("\u{2502}"));
296
+ }
297
+ }
298
+ // Alert trigger
299
+ if (signal.indicators.alertTrigger) {
300
+ console.log(chalk_1.default.cyan("\u{2502}") +
301
+ chalk_1.default.yellow.bold(" \u{26A1} HIGH PROBABILITY SETUP!").padEnd(52) +
302
+ chalk_1.default.cyan("\u{2502}"));
303
+ }
241
304
  // Technical observations
242
305
  console.log(chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(45) + "\u{2524}"));
243
306
  console.log(chalk_1.default.cyan("\u{2502}") + chalk_1.default.gray(" Technical Analysis:").padEnd(53) + chalk_1.default.cyan("\u{2502}"));
@@ -684,3 +747,215 @@ async function comprehensiveAnalysis(symbol) {
684
747
  console.log("");
685
748
  }
686
749
  }
750
+ // ============================================
751
+ // SMART TREND CONFLUENCE STRATEGY
752
+ // ============================================
753
+ const strategy_1 = require("./strategy");
754
+ /**
755
+ * Display strategy result in terminal
756
+ */
757
+ function displayStrategyResult(result, symbol) {
758
+ const boxWidth = 60;
759
+ const contentWidth = boxWidth - 4;
760
+ const border = {
761
+ top: chalk_1.default.cyan("\u{250C}" + "\u{2500}".repeat(boxWidth) + "\u{2510}"),
762
+ mid: chalk_1.default.cyan("\u{251C}" + "\u{2500}".repeat(boxWidth) + "\u{2524}"),
763
+ bot: chalk_1.default.cyan("\u{2514}" + "\u{2500}".repeat(boxWidth) + "\u{2518}"),
764
+ left: chalk_1.default.cyan("\u{2502}"),
765
+ right: chalk_1.default.cyan("\u{2502}"),
766
+ };
767
+ const line = (content, padEnd = contentWidth) => {
768
+ console.log(border.left + " " + content.padEnd(padEnd) + " " + border.right);
769
+ };
770
+ // Signal colors
771
+ const signalColors = {
772
+ STRONG_BUY: chalk_1.default.green.bold,
773
+ BUY: chalk_1.default.green,
774
+ WAIT: chalk_1.default.yellow,
775
+ SELL: chalk_1.default.red,
776
+ STRONG_SELL: chalk_1.default.red.bold,
777
+ NO_TRADE: chalk_1.default.gray,
778
+ };
779
+ const signalIcons = {
780
+ STRONG_BUY: "\u{1F7E2}\u{1F7E2}",
781
+ BUY: "\u{1F7E2}",
782
+ WAIT: "\u{1F7E1}",
783
+ SELL: "\u{1F534}",
784
+ STRONG_SELL: "\u{1F534}\u{1F534}",
785
+ NO_TRADE: "\u{26AA}",
786
+ };
787
+ const signalColor = signalColors[result.signal];
788
+ const signalIcon = signalIcons[result.signal];
789
+ console.log("");
790
+ console.log(border.top);
791
+ // Header
792
+ line(chalk_1.default.bold.white(`\u{1F3AF} SMART TREND CONFLUENCE - ${symbol.toUpperCase()}`));
793
+ line(chalk_1.default.gray(`Higher TF: ${result.higherTimeframe.interval} | Lower TF: ${result.lowerTimeframe.interval}`));
794
+ // Main Signal
795
+ console.log(border.mid);
796
+ line(chalk_1.default.bold(`SIGNAL: ${signalIcon} ${signalColor(result.signal)}`));
797
+ line(`Direction: ${result.direction === "long"
798
+ ? chalk_1.default.green("LONG \u{2191}")
799
+ : result.direction === "short"
800
+ ? chalk_1.default.red("SHORT \u{2193}")
801
+ : chalk_1.default.gray("NONE")}`);
802
+ // Confluence Score
803
+ console.log(border.mid);
804
+ const scoreColor = result.score.total >= 85
805
+ ? chalk_1.default.green
806
+ : result.score.total >= 70
807
+ ? chalk_1.default.cyan
808
+ : result.score.total >= 50
809
+ ? chalk_1.default.yellow
810
+ : chalk_1.default.red;
811
+ line(chalk_1.default.bold(`\u{1F4CA} CONFLUENCE SCORE: ${scoreColor(result.score.total + "/100")}`));
812
+ line(result.score.meetsMinimum
813
+ ? chalk_1.default.green(" \u{2705} Meets minimum threshold (70)")
814
+ : chalk_1.default.red(" \u{274C} Below minimum threshold (70)"));
815
+ // Score Breakdown
816
+ console.log(border.mid);
817
+ line(chalk_1.default.gray("Score Breakdown:"));
818
+ const breakdown = result.score.breakdown;
819
+ const barWidth = 20;
820
+ const drawBar = (label, score, max) => {
821
+ const filled = Math.round((score / max) * barWidth);
822
+ const empty = barWidth - filled;
823
+ const bar = chalk_1.default.green("\u{2588}".repeat(filled)) + chalk_1.default.gray("\u{2591}".repeat(empty));
824
+ const scoreStr = `${score}/${max}`;
825
+ line(` ${label.padEnd(12)} ${bar} ${scoreStr}`);
826
+ };
827
+ drawBar("Trend", breakdown.trendAlignment, 30);
828
+ drawBar("Pullback", breakdown.pullbackQuality, 25);
829
+ drawBar("Key Level", breakdown.keyLevel, 20);
830
+ drawBar("Volume", breakdown.volume, 15);
831
+ drawBar("RSI", breakdown.rsiRange, 10);
832
+ // Trade Setup
833
+ if (result.signal !== "NO_TRADE" && result.signal !== "WAIT") {
834
+ console.log(border.mid);
835
+ line(chalk_1.default.bold("\u{1F4B0} TRADE SETUP"));
836
+ line(` Entry: ${chalk_1.default.white("$" + result.entry.toFixed(4))}`);
837
+ line(` Stop Loss: ${chalk_1.default.red("$" + result.stopLoss.toFixed(4))}`);
838
+ line(` Target 1: ${chalk_1.default.green("$" + result.takeProfit1.toFixed(4))} (1.5R)`);
839
+ line(` Target 2: ${chalk_1.default.green("$" + result.takeProfit2.toFixed(4))} (2.5R)`);
840
+ line(` Risk/Reward: ${chalk_1.default.cyan(result.riskRewardRatio + ":1")}`);
841
+ }
842
+ // Timeframe Analysis
843
+ console.log(border.mid);
844
+ line(chalk_1.default.bold("\u{1F4C8} TIMEFRAME ANALYSIS"));
845
+ const trendIcon = (trend) => trend === "bullish"
846
+ ? chalk_1.default.green("\u{2191}")
847
+ : trend === "bearish"
848
+ ? chalk_1.default.red("\u{2193}")
849
+ : chalk_1.default.gray("\u{2192}");
850
+ line(` ${result.higherTimeframe.interval.toUpperCase()}: ${trendIcon(result.higherTimeframe.trend)} ${result.higherTimeframe.trend.padEnd(8)} | RSI: ${result.higherTimeframe.rsi.toFixed(0)}`);
851
+ line(` ${result.lowerTimeframe.interval.toUpperCase()}: ${trendIcon(result.lowerTimeframe.trend)} ${result.lowerTimeframe.trend.padEnd(8)} | RSI: ${result.lowerTimeframe.rsi.toFixed(0)}`);
852
+ // EMA Values
853
+ console.log(border.mid);
854
+ line(chalk_1.default.bold("\u{1F4C9} EMA VALUES (Lower TF)"));
855
+ line(chalk_1.default.gray(` EMA10: $${result.lowerTimeframe.ema10.toFixed(4)}`));
856
+ line(chalk_1.default.gray(` EMA20: $${result.lowerTimeframe.ema20.toFixed(4)}`));
857
+ line(chalk_1.default.gray(` EMA50: $${result.lowerTimeframe.ema50.toFixed(4)}`));
858
+ if (result.lowerTimeframe.ema200 > 0) {
859
+ line(chalk_1.default.gray(` EMA200: $${result.lowerTimeframe.ema200.toFixed(4)}`));
860
+ }
861
+ // Pullback Status
862
+ console.log(border.mid);
863
+ line(chalk_1.default.bold("\u{1F504} PULLBACK STATUS"));
864
+ const pullbackColor = result.pullback.quality === "optimal"
865
+ ? chalk_1.default.green
866
+ : result.pullback.quality === "acceptable"
867
+ ? chalk_1.default.yellow
868
+ : chalk_1.default.red;
869
+ line(` Quality: ${pullbackColor(result.pullback.quality.toUpperCase())}`);
870
+ line(` In EMA Zone: ${result.pullback.inEMAZone ? chalk_1.default.green("Yes") : chalk_1.default.red("No")}`);
871
+ line(chalk_1.default.gray(` Distance to EMA10: ${result.pullback.distanceToEMA10.toFixed(2)}%`));
872
+ line(chalk_1.default.gray(` Distance to EMA20: ${result.pullback.distanceToEMA20.toFixed(2)}%`));
873
+ // Candle Pattern
874
+ if (result.candlePattern.type !== "none") {
875
+ console.log(border.mid);
876
+ line(chalk_1.default.bold("\u{1F56F} CANDLE PATTERN"));
877
+ line(` ${chalk_1.default.cyan(result.candlePattern.type.replace(/_/g, " ").toUpperCase())}`);
878
+ line(chalk_1.default.gray(` ${result.candlePattern.description}`));
879
+ line(chalk_1.default.gray(` Strength: ${result.candlePattern.strength}/100`));
880
+ }
881
+ // Key Levels
882
+ if (result.keyLevels.length > 0) {
883
+ console.log(border.mid);
884
+ line(chalk_1.default.bold("\u{1F511} KEY LEVELS"));
885
+ result.keyLevels.slice(0, 4).forEach((level) => {
886
+ const levelColor = level.type.includes("support") || level.type.includes("bullish") ? chalk_1.default.green : chalk_1.default.red;
887
+ const typeStr = level.type.replace(/_/g, " ");
888
+ line(` ${levelColor(typeStr.padEnd(18))} $${level.price.toFixed(4)} (${level.distance.toFixed(1)}%)`);
889
+ });
890
+ }
891
+ // Volume
892
+ console.log(border.mid);
893
+ line(chalk_1.default.bold("\u{1F4CA} VOLUME"));
894
+ const volColor = result.volume.volumeRatio > 1.2
895
+ ? chalk_1.default.green
896
+ : result.volume.volumeRatio > 0.8
897
+ ? chalk_1.default.yellow
898
+ : chalk_1.default.red;
899
+ line(` Ratio: ${volColor(result.volume.volumeRatio.toFixed(2) + "x")} average`);
900
+ line(` Trend: ${result.volume.trend}`);
901
+ // Confluence Factors
902
+ console.log(border.mid);
903
+ line(chalk_1.default.bold("\u{2705} CONFLUENCE FACTORS"));
904
+ result.score.factors.slice(0, 8).forEach((factor) => {
905
+ const color = factor.startsWith("\u{2713}") || factor.startsWith("✓")
906
+ ? chalk_1.default.green
907
+ : factor.startsWith("\u{2717}") || factor.startsWith("✗")
908
+ ? chalk_1.default.red
909
+ : chalk_1.default.yellow;
910
+ const truncated = factor.length > contentWidth - 3 ? factor.substring(0, contentWidth - 6) + "..." : factor;
911
+ line(color(` ${truncated}`));
912
+ });
913
+ // Reasoning
914
+ if (result.reasoning.length > 0) {
915
+ console.log(border.mid);
916
+ line(chalk_1.default.bold("\u{1F4DD} REASONING"));
917
+ result.reasoning.forEach((r) => {
918
+ const truncated = r.length > contentWidth - 5 ? r.substring(0, contentWidth - 8) + "..." : r;
919
+ line(chalk_1.default.gray(` • ${truncated}`));
920
+ });
921
+ }
922
+ // Warnings
923
+ if (result.warnings.length > 0) {
924
+ console.log(border.mid);
925
+ line(chalk_1.default.yellow.bold("\u{26A0}\u{FE0F} WARNINGS"));
926
+ result.warnings.forEach((w) => {
927
+ const truncated = w.length > contentWidth - 5 ? w.substring(0, contentWidth - 8) + "..." : w;
928
+ line(chalk_1.default.yellow(` • ${truncated}`));
929
+ });
930
+ }
931
+ // Footer
932
+ console.log(border.bot);
933
+ console.log("");
934
+ console.log(chalk_1.default.gray.italic(" \u{26A0}\u{FE0F} This is not financial advice. Always do your own research."));
935
+ console.log(chalk_1.default.gray.italic(" \u{1F4A1} Minimum score of 70 required. Only trade with proper risk management."));
936
+ console.log("");
937
+ }
938
+ /**
939
+ * Run the Smart Trend Confluence Strategy
940
+ */
941
+ async function runSmartStrategy(symbol, htfInterval = "4h", ltfInterval = "1h") {
942
+ const spinner = (0, ora_1.default)(`Running Smart Trend Confluence on ${symbol.toUpperCase()}...`).start();
943
+ try {
944
+ spinner.text = `Fetching ${htfInterval} and ${ltfInterval} data...`;
945
+ const result = await (0, strategy_1.generateStrategySignal)(symbol, htfInterval, ltfInterval);
946
+ spinner.succeed(`Strategy analysis complete for ${symbol.toUpperCase()}`);
947
+ displayStrategyResult(result, symbol);
948
+ }
949
+ catch (error) {
950
+ spinner.fail(`Failed to run strategy on ${symbol}`);
951
+ console.log("");
952
+ console.log(chalk_1.default.red(` Error: ${error.message || "Unknown error"}`));
953
+ if (error.message?.includes("Invalid symbol") || error.message?.includes("Failed to fetch")) {
954
+ const suggestions = await (0, data_fetcher_1.findSimilarSymbols)(symbol, 5);
955
+ if (suggestions.length > 0) {
956
+ console.log(chalk_1.default.gray("\n Did you mean: ") + chalk_1.default.cyan(suggestions.join(", ")));
957
+ }
958
+ }
959
+ console.log("");
960
+ }
961
+ }