ticker-cli 1.0.0

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,152 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService, createIndicatorService } from "../services";
3
+ import { createFormatter, isValidPeriod } from "../utils";
4
+ import type { PeriodPreset } from "../types";
5
+
6
+ const AVAILABLE_INDICATORS = ["sma", "ema", "rsi", "macd", "bb"] as const;
7
+
8
+ /**
9
+ * Create the indicator command
10
+ */
11
+ export function createIndicatorCommand(): Command {
12
+ const command = new Command("indicator");
13
+
14
+ command
15
+ .description(
16
+ `Calculate technical indicators. Available: ${AVAILABLE_INDICATORS.join(", ")}`,
17
+ )
18
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
19
+ .argument(
20
+ "<indicator>",
21
+ `Indicator type: ${AVAILABLE_INDICATORS.join(", ")}`,
22
+ )
23
+ .option(
24
+ "-p, --period <period>",
25
+ "Preset period for historical data: 1d, 5d, 1wk, 1mo, 3mo, 6mo, 1y, 2y, 5y",
26
+ "3mo",
27
+ )
28
+ .option("-s, --start <date>", "Start date (YYYY-MM-DD)")
29
+ .option("-e, --end <date>", "End date (YYYY-MM-DD)")
30
+ .option(
31
+ "--length <number>",
32
+ "Period length for SMA/EMA/RSI/BB (default: 20 for SMA/EMA/BB, 14 for RSI)",
33
+ )
34
+ .option("--short <number>", "Short period for MACD (default: 12)")
35
+ .option("--long <number>", "Long period for MACD (default: 26)")
36
+ .option("--signal <number>", "Signal period for MACD (default: 9)")
37
+ .option("--table", "Output as table instead of JSON")
38
+ .option("--pretty", "Pretty print JSON output", true)
39
+ .action(
40
+ async (
41
+ symbol: string,
42
+ indicator: string,
43
+ options: {
44
+ period?: string;
45
+ start?: string;
46
+ end?: string;
47
+ length?: string;
48
+ short?: string;
49
+ long?: string;
50
+ signal?: string;
51
+ table?: boolean;
52
+ pretty?: boolean;
53
+ },
54
+ ) => {
55
+ const yahooService = createYahooService();
56
+ const indicatorService = createIndicatorService();
57
+ const formatter = createFormatter(options);
58
+
59
+ // Validate indicator
60
+ const normalizedIndicator = indicator.toLowerCase();
61
+ if (
62
+ !AVAILABLE_INDICATORS.includes(
63
+ normalizedIndicator as (typeof AVAILABLE_INDICATORS)[number],
64
+ )
65
+ ) {
66
+ console.error(
67
+ `Invalid indicator: ${indicator}. Available: ${AVAILABLE_INDICATORS.join(", ")}`,
68
+ );
69
+ process.exit(1);
70
+ }
71
+
72
+ // Validate period
73
+ let period: PeriodPreset | undefined;
74
+ if (options.period) {
75
+ if (!isValidPeriod(options.period)) {
76
+ console.error(
77
+ `Invalid period: ${options.period}. Valid options: 1d, 5d, 1wk, 1mo, 3mo, 6mo, 1y, 2y, 5y`,
78
+ );
79
+ process.exit(1);
80
+ }
81
+ period = options.period as PeriodPreset;
82
+ }
83
+
84
+ // Parse numeric options
85
+ const config: {
86
+ length?: number;
87
+ short?: number;
88
+ long?: number;
89
+ signal?: number;
90
+ } = {};
91
+
92
+ if (options.length) {
93
+ config.length = parseInt(options.length, 10);
94
+ if (isNaN(config.length)) {
95
+ console.error("Invalid length value");
96
+ process.exit(1);
97
+ }
98
+ }
99
+ if (options.short) {
100
+ config.short = parseInt(options.short, 10);
101
+ if (isNaN(config.short)) {
102
+ console.error("Invalid short value");
103
+ process.exit(1);
104
+ }
105
+ }
106
+ if (options.long) {
107
+ config.long = parseInt(options.long, 10);
108
+ if (isNaN(config.long)) {
109
+ console.error("Invalid long value");
110
+ process.exit(1);
111
+ }
112
+ }
113
+ if (options.signal) {
114
+ config.signal = parseInt(options.signal, 10);
115
+ if (isNaN(config.signal)) {
116
+ console.error("Invalid signal value");
117
+ process.exit(1);
118
+ }
119
+ }
120
+
121
+ try {
122
+ // Fetch chart data
123
+ const chartData = await yahooService.getChart(symbol, {
124
+ period,
125
+ start: options.start,
126
+ end: options.end,
127
+ });
128
+
129
+ // Calculate indicator
130
+ const indicatorResult = indicatorService.calculate(
131
+ normalizedIndicator,
132
+ chartData.quotes,
133
+ config,
134
+ );
135
+
136
+ // Add symbol to result
137
+ indicatorResult.symbol = symbol;
138
+
139
+ const output = formatter.format(indicatorResult);
140
+ console.log(output);
141
+ } catch (error) {
142
+ console.error(
143
+ "Error calculating indicator:",
144
+ error instanceof Error ? error.message : String(error),
145
+ );
146
+ process.exit(1);
147
+ }
148
+ },
149
+ );
150
+
151
+ return command;
152
+ }
@@ -0,0 +1,42 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+
5
+ /**
6
+ * Create the insights command
7
+ */
8
+ export function createInsightsCommand(): Command {
9
+ const command = new Command("insights");
10
+
11
+ command
12
+ .description("Get insights for a symbol")
13
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
14
+ .option("--table", "Output as table instead of JSON")
15
+ .option("--pretty", "Pretty print JSON output", true)
16
+ .action(
17
+ async (
18
+ symbol: string,
19
+ options: {
20
+ table?: boolean;
21
+ pretty?: boolean;
22
+ },
23
+ ) => {
24
+ const yahooService = createYahooService();
25
+ const formatter = createFormatter(options);
26
+
27
+ try {
28
+ const insights = await yahooService.getInsights(symbol);
29
+ const output = formatter.format(insights);
30
+ console.log(output);
31
+ } catch (error) {
32
+ console.error(
33
+ "Error fetching insights:",
34
+ error instanceof Error ? error.message : String(error),
35
+ );
36
+ process.exit(1);
37
+ }
38
+ },
39
+ );
40
+
41
+ return command;
42
+ }
@@ -0,0 +1,46 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+
5
+ /**
6
+ * Create the news command
7
+ */
8
+ export function createNewsCommand(): Command {
9
+ const command = new Command("news");
10
+
11
+ command
12
+ .description("Get news for a symbol")
13
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
14
+ .option("-l, --limit <number>", "Number of news articles", "10")
15
+ .option("--table", "Output as table instead of JSON")
16
+ .option("--pretty", "Pretty print JSON output", true)
17
+ .action(
18
+ async (
19
+ symbol: string,
20
+ options: {
21
+ limit?: string;
22
+ table?: boolean;
23
+ pretty?: boolean;
24
+ },
25
+ ) => {
26
+ const yahooService = createYahooService();
27
+ const formatter = createFormatter(options);
28
+
29
+ const limit = options.limit ? parseInt(options.limit, 10) : 10;
30
+
31
+ try {
32
+ const news = await yahooService.getNews(symbol, limit);
33
+ const output = formatter.format(news);
34
+ console.log(output);
35
+ } catch (error) {
36
+ console.error(
37
+ "Error fetching news:",
38
+ error instanceof Error ? error.message : String(error),
39
+ );
40
+ process.exit(1);
41
+ }
42
+ },
43
+ );
44
+
45
+ return command;
46
+ }
@@ -0,0 +1,69 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+
5
+ /**
6
+ * Create the options command
7
+ */
8
+ export function createOptionsCommand(): Command {
9
+ const command = new Command("options");
10
+
11
+ command
12
+ .description("Get options chain for a symbol")
13
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
14
+ .option("-d, --date <date>", "Expiration date (YYYY-MM-DD)")
15
+ .option("--calls", "Show only calls")
16
+ .option("--puts", "Show only puts")
17
+ .option("--table", "Output as table instead of JSON")
18
+ .option("--pretty", "Pretty print JSON output", true)
19
+ .action(
20
+ async (
21
+ symbol: string,
22
+ options: {
23
+ date?: string;
24
+ calls?: boolean;
25
+ puts?: boolean;
26
+ table?: boolean;
27
+ pretty?: boolean;
28
+ },
29
+ ) => {
30
+ const yahooService = createYahooService();
31
+ const formatter = createFormatter(options);
32
+
33
+ try {
34
+ const optionsData = await yahooService.getOptions(
35
+ symbol,
36
+ options.date,
37
+ );
38
+
39
+ // Filter calls/puts if requested
40
+ if (options.calls && !options.puts) {
41
+ const output = formatter.format({
42
+ symbol: optionsData.symbol,
43
+ expirationDate: optionsData.expirationDate,
44
+ calls: optionsData.calls,
45
+ });
46
+ console.log(output);
47
+ } else if (options.puts && !options.calls) {
48
+ const output = formatter.format({
49
+ symbol: optionsData.symbol,
50
+ expirationDate: optionsData.expirationDate,
51
+ puts: optionsData.puts,
52
+ });
53
+ console.log(output);
54
+ } else {
55
+ const output = formatter.format(optionsData);
56
+ console.log(output);
57
+ }
58
+ } catch (error) {
59
+ console.error(
60
+ "Error fetching options:",
61
+ error instanceof Error ? error.message : String(error),
62
+ );
63
+ process.exit(1);
64
+ }
65
+ },
66
+ );
67
+
68
+ return command;
69
+ }
@@ -0,0 +1,34 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+
5
+ /**
6
+ * Create the quote command
7
+ */
8
+ export function createQuoteCommand(): Command {
9
+ const command = new Command("quote");
10
+
11
+ command
12
+ .description("Get stock quotes for one or more symbols")
13
+ .argument("<symbols...>", "Stock symbols (e.g., AAPL MSFT GOOGL)")
14
+ .option("--table", "Output as table instead of JSON")
15
+ .option("--pretty", "Pretty print JSON output", true)
16
+ .action(async (symbols: string[], options: { table?: boolean; pretty?: boolean }) => {
17
+ const yahooService = createYahooService();
18
+ const formatter = createFormatter(options);
19
+
20
+ try {
21
+ const quotes = await yahooService.getQuotes(symbols);
22
+ const output = formatter.format({ quotes });
23
+ console.log(output);
24
+ } catch (error) {
25
+ console.error(
26
+ "Error fetching quotes:",
27
+ error instanceof Error ? error.message : String(error)
28
+ );
29
+ process.exit(1);
30
+ }
31
+ });
32
+
33
+ return command;
34
+ }
@@ -0,0 +1,42 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+
5
+ /**
6
+ * Create the recommendations command
7
+ */
8
+ export function createRecommendationsCommand(): Command {
9
+ const command = new Command("recommendations");
10
+
11
+ command
12
+ .description("Get analyst recommendations for a symbol")
13
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
14
+ .option("--table", "Output as table instead of JSON")
15
+ .option("--pretty", "Pretty print JSON output", true)
16
+ .action(
17
+ async (
18
+ symbol: string,
19
+ options: {
20
+ table?: boolean;
21
+ pretty?: boolean;
22
+ },
23
+ ) => {
24
+ const yahooService = createYahooService();
25
+ const formatter = createFormatter(options);
26
+
27
+ try {
28
+ const recommendations = await yahooService.getRecommendations(symbol);
29
+ const output = formatter.format(recommendations);
30
+ console.log(output);
31
+ } catch (error) {
32
+ console.error(
33
+ "Error fetching recommendations:",
34
+ error instanceof Error ? error.message : String(error),
35
+ );
36
+ process.exit(1);
37
+ }
38
+ },
39
+ );
40
+
41
+ return command;
42
+ }
@@ -0,0 +1,58 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+ import type { PredefinedScreenerModules } from "yahoo-finance2/modules/screener";
5
+
6
+ const PREDEFINED_QUERIES: PredefinedScreenerModules[] = [
7
+ "most_actives",
8
+ "day_gainers",
9
+ "day_losers",
10
+ "undervalued_growth_stocks",
11
+ "undervalued_large_caps",
12
+ "growth_technology_stocks",
13
+ "top_mutual_funds",
14
+ ];
15
+
16
+ /**
17
+ * Create the screener command
18
+ */
19
+ export function createScreenerCommand(): Command {
20
+ const command = new Command("screener");
21
+
22
+ command
23
+ .description("Screen stocks using predefined queries")
24
+ .option(
25
+ "-q, --query <query>",
26
+ `Predefined query: ${PREDEFINED_QUERIES.join(", ")}`,
27
+ "most_actives",
28
+ )
29
+ .option("--table", "Output as table instead of JSON")
30
+ .option("--pretty", "Pretty print JSON output", true)
31
+ .action(
32
+ async (options: {
33
+ query?: string;
34
+ table?: boolean;
35
+ pretty?: boolean;
36
+ }) => {
37
+ const yahooService = createYahooService();
38
+ const formatter = createFormatter(options);
39
+
40
+ const query = (options.query ??
41
+ "most_actives") as PredefinedScreenerModules;
42
+
43
+ try {
44
+ const screenerData = await yahooService.getScreener(query);
45
+ const output = formatter.format(screenerData);
46
+ console.log(output);
47
+ } catch (error) {
48
+ console.error(
49
+ "Error fetching screener data:",
50
+ error instanceof Error ? error.message : String(error),
51
+ );
52
+ process.exit(1);
53
+ }
54
+ },
55
+ );
56
+
57
+ return command;
58
+ }
@@ -0,0 +1,49 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+
5
+ /**
6
+ * Create the search command
7
+ */
8
+ export function createSearchCommand(): Command {
9
+ const command = new Command("search");
10
+
11
+ command
12
+ .description("Search for stock symbols")
13
+ .argument("<query>", "Search query (e.g., apple)")
14
+ .option("--quotes", "Include quotes in results")
15
+ .option("--news", "Include news in results")
16
+ .option("--table", "Output as table instead of JSON")
17
+ .option("--pretty", "Pretty print JSON output", true)
18
+ .action(
19
+ async (
20
+ query: string,
21
+ options: {
22
+ quotes?: boolean;
23
+ news?: boolean;
24
+ table?: boolean;
25
+ pretty?: boolean;
26
+ },
27
+ ) => {
28
+ const yahooService = createYahooService();
29
+ const formatter = createFormatter(options);
30
+
31
+ try {
32
+ const result = await yahooService.search(query, {
33
+ includeQuotes: options.quotes,
34
+ includeNews: options.news,
35
+ });
36
+ const output = formatter.format(result);
37
+ console.log(output);
38
+ } catch (error) {
39
+ console.error(
40
+ "Error searching symbols:",
41
+ error instanceof Error ? error.message : String(error),
42
+ );
43
+ process.exit(1);
44
+ }
45
+ },
46
+ );
47
+
48
+ return command;
49
+ }
@@ -0,0 +1,50 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter } from "../utils";
4
+ import type { QuoteSummaryModules } from "yahoo-finance2/modules/quoteSummary";
5
+
6
+ /**
7
+ * Create the summary command
8
+ */
9
+ export function createSummaryCommand(): Command {
10
+ const command = new Command("summary");
11
+
12
+ command
13
+ .description("Get quote summary for a symbol")
14
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
15
+ .option(
16
+ "-m, --modules <modules>",
17
+ "Comma-separated modules to include (e.g., summaryProfile,summaryDetail)",
18
+ )
19
+ .option("--table", "Output as table instead of JSON")
20
+ .option("--pretty", "Pretty print JSON output", true)
21
+ .action(
22
+ async (
23
+ symbol: string,
24
+ options: {
25
+ modules?: string;
26
+ table?: boolean;
27
+ pretty?: boolean;
28
+ },
29
+ ) => {
30
+ const yahooService = createYahooService();
31
+ const formatter = createFormatter(options);
32
+
33
+ const modules = options.modules?.split(",").map((m) => m.trim() as QuoteSummaryModules);
34
+
35
+ try {
36
+ const summary = await yahooService.getSummary(symbol, modules);
37
+ const output = formatter.format(summary);
38
+ console.log(output);
39
+ } catch (error) {
40
+ console.error(
41
+ "Error fetching summary:",
42
+ error instanceof Error ? error.message : String(error),
43
+ );
44
+ process.exit(1);
45
+ }
46
+ },
47
+ );
48
+
49
+ return command;
50
+ }
@@ -0,0 +1,3 @@
1
+ export { YahooService, createYahooService } from "./yahoo";
2
+ export { IndicatorService, createIndicatorService } from "./indicators";
3
+ export type { IndicatorConfig } from "./indicators";