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.
package/CLAUDE.md ADDED
@@ -0,0 +1,111 @@
1
+ ---
2
+ description: Use Bun instead of Node.js, npm, pnpm, or vite.
3
+ globs: "*.ts, *.tsx, *.html, *.css, *.js, *.jsx, package.json"
4
+ alwaysApply: false
5
+ ---
6
+
7
+ Default to using Bun instead of Node.js.
8
+
9
+ - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
10
+ - Use `bun test` instead of `jest` or `vitest`
11
+ - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
12
+ - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
13
+ - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
14
+ - Use `bunx <package> <command>` instead of `npx <package> <command>`
15
+ - Bun automatically loads .env, so don't use dotenv.
16
+
17
+ ## APIs
18
+
19
+ - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
20
+ - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
21
+ - `Bun.redis` for Redis. Don't use `ioredis`.
22
+ - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
23
+ - `WebSocket` is built-in. Don't use `ws`.
24
+ - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
25
+ - Bun.$`ls` instead of execa.
26
+
27
+ ## Testing
28
+
29
+ Use `bun test` to run tests.
30
+
31
+ ```ts#index.test.ts
32
+ import { test, expect } from "bun:test";
33
+
34
+ test("hello world", () => {
35
+ expect(1).toBe(1);
36
+ });
37
+ ```
38
+
39
+ ## Frontend
40
+
41
+ Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
42
+
43
+ Server:
44
+
45
+ ```ts#index.ts
46
+ import index from "./index.html"
47
+
48
+ Bun.serve({
49
+ routes: {
50
+ "/": index,
51
+ "/api/users/:id": {
52
+ GET: (req) => {
53
+ return new Response(JSON.stringify({ id: req.params.id }));
54
+ },
55
+ },
56
+ },
57
+ // optional websocket support
58
+ websocket: {
59
+ open: (ws) => {
60
+ ws.send("Hello, world!");
61
+ },
62
+ message: (ws, message) => {
63
+ ws.send(message);
64
+ },
65
+ close: (ws) => {
66
+ // handle close
67
+ }
68
+ },
69
+ development: {
70
+ hmr: true,
71
+ console: true,
72
+ }
73
+ })
74
+ ```
75
+
76
+ HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
77
+
78
+ ```html#index.html
79
+ <html>
80
+ <body>
81
+ <h1>Hello, world!</h1>
82
+ <script type="module" src="./frontend.tsx"></script>
83
+ </body>
84
+ </html>
85
+ ```
86
+
87
+ With the following `frontend.tsx`:
88
+
89
+ ```tsx#frontend.tsx
90
+ import React from "react";
91
+ import { createRoot } from "react-dom/client";
92
+
93
+ // import .css files directly and it works
94
+ import './index.css';
95
+
96
+ const root = createRoot(document.body);
97
+
98
+ export default function Frontend() {
99
+ return <h1>Hello, world!</h1>;
100
+ }
101
+
102
+ root.render(<Frontend />);
103
+ ```
104
+
105
+ Then, run index.ts
106
+
107
+ ```sh
108
+ bun --hot ./index.ts
109
+ ```
110
+
111
+ For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # ticker-cli
2
+
3
+ A powerful command-line interface for trading analysis that provides stock quotes, charts, technical indicators, news, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun install
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ bun run index.ts <command> [options]
15
+ ```
16
+
17
+ Or create an alias:
18
+
19
+ ```bash
20
+ alias ticker="bun run /path/to/ticker-cli/index.ts"
21
+ ticker quote AAPL
22
+ ```
23
+
24
+ ## Commands
25
+
26
+ ### quote - Get stock quotes
27
+
28
+ ```bash
29
+ ticker quote <symbols...>
30
+
31
+ # Examples:
32
+ ticker quote AAPL # Single quote
33
+ ticker quote AAPL MSFT GOOGL # Multiple quotes
34
+ ```
35
+
36
+ ### chart - Get chart/historical data
37
+
38
+ ```bash
39
+ ticker chart <symbol> [options]
40
+
41
+ Options:
42
+ -p, --period <period> Preset period: 1d, 5d, 1wk, 1mo, 3mo, 6mo, 1y, 2y, 5y
43
+ -s, --start <date> Start date (YYYY-MM-DD)
44
+ -e, --end <date> End date (YYYY-MM-DD)
45
+ -i, --interval <interval> Interval: 1m, 5m, 15m, 30m, 1h, 1d, 1wk, 1mo
46
+
47
+ # Examples:
48
+ ticker chart AAPL -p 1mo
49
+ ticker chart AAPL --start 2025-01-01 --end 2025-12-31
50
+ ticker chart AAPL -p 1y --interval 1wk
51
+ ```
52
+
53
+ ### indicator - Calculate technical indicators
54
+
55
+ ```bash
56
+ ticker indicator <symbol> <indicator> [options]
57
+
58
+ Indicators:
59
+ sma Simple Moving Average
60
+ ema Exponential Moving Average
61
+ rsi Relative Strength Index
62
+ macd Moving Average Convergence Divergence
63
+ bb Bollinger Bands
64
+
65
+ Options:
66
+ -p, --period <period> Period for historical data
67
+ -s, --start <date> Start date
68
+ -e, --end <date> End date
69
+ --length <number> Period length (default: 20 for SMA/EMA/BB, 14 for RSI)
70
+ --short <number> Short period for MACD (default: 12)
71
+ --long <number> Long period for MACD (default: 26)
72
+ --signal <number> Signal period for MACD (default: 9)
73
+
74
+ # Examples:
75
+ ticker indicator AAPL sma -p 3mo
76
+ ticker indicator AAPL ema --length 50 -p 6mo
77
+ ticker indicator AAPL rsi -p 3mo
78
+ ticker indicator AAPL macd -p 6mo
79
+ ticker indicator AAPL bb -p 3mo
80
+ ```
81
+
82
+ ### search - Search for symbols
83
+
84
+ ```bash
85
+ ticker search <query>
86
+
87
+ # Examples:
88
+ ticker search apple
89
+ ticker search "micro soft"
90
+ ```
91
+
92
+ ### summary - Get quote summary
93
+
94
+ ```bash
95
+ ticker summary <symbol> [options]
96
+
97
+ Options:
98
+ -m, --modules <modules> Comma-separated modules
99
+
100
+ # Examples:
101
+ ticker summary AAPL
102
+ ticker summary AAPL -m summaryProfile,summaryDetail
103
+ ```
104
+
105
+ ### news - Get stock news
106
+
107
+ ```bash
108
+ ticker news <symbol> [options]
109
+
110
+ Options:
111
+ -l, --limit <number> Number of articles (default: 10)
112
+
113
+ # Examples:
114
+ ticker news AAPL
115
+ ticker news AAPL --limit 20
116
+ ```
117
+
118
+ ### insights - Get stock insights
119
+
120
+ ```bash
121
+ ticker insights <symbol>
122
+
123
+ # Examples:
124
+ ticker insights AAPL
125
+ ```
126
+
127
+ ### options - Get options chain
128
+
129
+ ```bash
130
+ ticker options <symbol> [options]
131
+
132
+ Options:
133
+ -d, --date <date> Expiration date (YYYY-MM-DD)
134
+ --calls Show only calls
135
+ --puts Show only puts
136
+
137
+ # Examples:
138
+ ticker options AAPL
139
+ ticker options AAPL -d 2026-03-21
140
+ ticker options AAPL --calls
141
+ ```
142
+
143
+ ### recommendations - Get analyst recommendations
144
+
145
+ ```bash
146
+ ticker recommendations <symbol>
147
+
148
+ # Examples:
149
+ ticker recommendations AAPL
150
+ ```
151
+
152
+ ### screener - Screen stocks
153
+
154
+ ```bash
155
+ ticker screener [options]
156
+
157
+ Options:
158
+ -q, --query <query> Predefined query (default: most_actives)
159
+
160
+ Available Queries:
161
+ most_actives, day_gainers, day_losers,
162
+ undervalued_growth_stocks, undervalued_large_caps,
163
+ growth_technology_stocks, top_mutual_funds
164
+
165
+ # Examples:
166
+ ticker screener
167
+ ticker screener -q day_gainers
168
+ ticker screener -q undervalued_large_caps
169
+ ```
170
+
171
+ ## Global Options
172
+
173
+ ```
174
+ --pretty Pretty print JSON output (default: true)
175
+ ```
176
+
177
+ ## Output Format
178
+
179
+ ```bash
180
+ ticker quote AAPL
181
+ ```
182
+
183
+ ## Dependencies
184
+
185
+ - [commander.js](https://github.com/tj/commander.js) - CLI framework
186
+ - [yahoo-finance2](https://github.com/gadicc/yahoo-finance2) - Yahoo Finance API
187
+ - [indicatorts](https://github.com/cinar/indicatorts) - Technical indicators
188
+ - [Bun](https://bun.sh) - JavaScript runtime
189
+
190
+ ## License
191
+
192
+ MIT
package/bun.lock ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "ticker-cli",
7
+ "dependencies": {
8
+ "commander": "^14.0.3",
9
+ "indicatorts": "^2.2.2",
10
+ "yahoo-finance2": "^3.13.0",
11
+ },
12
+ "devDependencies": {
13
+ "@types/bun": "latest",
14
+ },
15
+ "peerDependencies": {
16
+ "typescript": "^5",
17
+ },
18
+ },
19
+ },
20
+ "packages": {
21
+ "@deno/shim-deno": ["@deno/shim-deno@0.18.2", "", { "dependencies": { "@deno/shim-deno-test": "^0.5.0", "which": "^4.0.0" } }, "sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA=="],
22
+
23
+ "@deno/shim-deno-test": ["@deno/shim-deno-test@0.5.0", "", {}, "sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w=="],
24
+
25
+ "@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
26
+
27
+ "@types/node": ["@types/node@25.2.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ=="],
28
+
29
+ "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
30
+
31
+ "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
32
+
33
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
34
+
35
+ "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
36
+
37
+ "fetch-mock-cache": ["fetch-mock-cache@2.3.1", "", { "dependencies": { "debug": "^4.3.4", "filenamify-url": "2.1.2" } }, "sha512-hDk+Nbt0Y8Aq7KTEU6ASQAcpB34UjhkpD3QjzD6yvEKP4xVElAqXrjQ7maL+LYMGafx51Zq6qUfDM57PNu/qMw=="],
38
+
39
+ "filename-reserved-regex": ["filename-reserved-regex@2.0.0", "", {}, "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ=="],
40
+
41
+ "filenamify": ["filenamify@4.3.0", "", { "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", "trim-repeated": "^1.0.0" } }, "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg=="],
42
+
43
+ "filenamify-url": ["filenamify-url@2.1.2", "", { "dependencies": { "filenamify": "^4.3.0", "humanize-url": "^2.1.1" } }, "sha512-3rMbAr7vDNMOGsj1aMniQFl749QjgM+lMJ/77ZRSPTIgxvolZwoQbn8dXLs7xfd+hAdli+oTnSWZNkJJLWQFEQ=="],
44
+
45
+ "humanize-url": ["humanize-url@2.1.1", "", { "dependencies": { "normalize-url": "^4.5.1" } }, "sha512-V4nxsPGNE7mPjr1qDp471YfW8nhBiTRWrG/4usZlpvFU8I7gsV7Jvrrzv/snbLm5dWO3dr1ennu2YqnhTWFmYA=="],
46
+
47
+ "indicatorts": ["indicatorts@2.2.2", "", {}, "sha512-oJRe83n2zj826Mlp2RKQVfurqbq5dEHzAWgZidiYkS0mrx3GCbXlNj59YtwZvekRmNwi/d4NdeHGHd8Nspl6Xg=="],
48
+
49
+ "isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
50
+
51
+ "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
52
+
53
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
54
+
55
+ "normalize-url": ["normalize-url@4.5.1", "", {}, "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA=="],
56
+
57
+ "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="],
58
+
59
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
60
+
61
+ "querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="],
62
+
63
+ "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
64
+
65
+ "strip-outer": ["strip-outer@1.0.1", "", { "dependencies": { "escape-string-regexp": "^1.0.2" } }, "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg=="],
66
+
67
+ "tldts": ["tldts@6.1.86", "", { "dependencies": { "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ=="],
68
+
69
+ "tldts-core": ["tldts-core@6.1.86", "", {}, "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA=="],
70
+
71
+ "tough-cookie": ["tough-cookie@5.1.2", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A=="],
72
+
73
+ "tough-cookie-file-store": ["tough-cookie-file-store@2.0.3", "", { "dependencies": { "tough-cookie": "^4.0.0" } }, "sha512-sMpZVcmFf6EYFHFFl+SYH4W1/OnXBYMGDsv2IlbQ2caHyFElW/UR/gpj/KYU1JwmP4dE9xqwv2+vWcmlXHojSw=="],
74
+
75
+ "trim-repeated": ["trim-repeated@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.2" } }, "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg=="],
76
+
77
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
78
+
79
+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
80
+
81
+ "universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
82
+
83
+ "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="],
84
+
85
+ "which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="],
86
+
87
+ "yahoo-finance2": ["yahoo-finance2@3.13.0", "", { "dependencies": { "@deno/shim-deno": "~0.18.0", "fetch-mock-cache": "npm:fetch-mock-cache@^2.1.3", "json-schema": "^0.4.0", "tough-cookie": "npm:tough-cookie@^5.1.1", "tough-cookie-file-store": "npm:tough-cookie-file-store@^2.0.3" }, "bin": { "yahoo-finance": "esm/bin/yahoo-finance.js" } }, "sha512-czBj2q/MD68YEsB7aXNnGhJvWxYZn01O5r/i7VYiQV2m2sWwhca6tKgjwf/LT7zHHEVxhKNiGLB46glLnmq9Ag=="],
88
+
89
+ "tough-cookie-file-store/tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="],
90
+ }
91
+ }
package/index.ts ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bun
2
+ import { Command } from "commander";
3
+ import {
4
+ createQuoteCommand,
5
+ createChartCommand,
6
+ createSearchCommand,
7
+ createSummaryCommand,
8
+ createNewsCommand,
9
+ createInsightsCommand,
10
+ createOptionsCommand,
11
+ createRecommendationsCommand,
12
+ createScreenerCommand,
13
+ createIndicatorCommand,
14
+ } from "./src/commands";
15
+
16
+ const program = new Command();
17
+
18
+ program
19
+ .name("ticker")
20
+ .description(
21
+ "Trading analysis CLI - stock quotes, charts, indicators, and more",
22
+ )
23
+ .version("1.0.0")
24
+ .option("--table", "Output as table instead of JSON (global option)")
25
+ .option("--pretty", "Pretty print JSON output", true);
26
+
27
+ // Add all commands
28
+ program.addCommand(createQuoteCommand());
29
+ program.addCommand(createChartCommand());
30
+ program.addCommand(createSearchCommand());
31
+ program.addCommand(createSummaryCommand());
32
+ program.addCommand(createNewsCommand());
33
+ program.addCommand(createInsightsCommand());
34
+ program.addCommand(createOptionsCommand());
35
+ program.addCommand(createRecommendationsCommand());
36
+ program.addCommand(createScreenerCommand());
37
+ program.addCommand(createIndicatorCommand());
38
+
39
+ // Parse arguments and run
40
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "ticker-cli",
3
+ "version": "1.0.0",
4
+ "module": "index.ts",
5
+ "type": "module",
6
+ "bin": {
7
+ "ticker": "./index.ts"
8
+ },
9
+ "scripts": {
10
+ "start": "bun run index.ts",
11
+ "ticker": "bun run index.ts"
12
+ },
13
+ "devDependencies": {
14
+ "@types/bun": "latest"
15
+ },
16
+ "peerDependencies": {
17
+ "typescript": "^5"
18
+ },
19
+ "dependencies": {
20
+ "commander": "^14.0.3",
21
+ "indicatorts": "^2.2.2",
22
+ "yahoo-finance2": "^3.13.0"
23
+ }
24
+ }
@@ -0,0 +1,100 @@
1
+ import { Command } from "commander";
2
+ import { createYahooService } from "../services";
3
+ import { createFormatter, isValidPeriod, isValidInterval } from "../utils";
4
+ import type { PeriodPreset, IntervalType } from "../types";
5
+
6
+ /**
7
+ * Create the chart command
8
+ */
9
+ export function createChartCommand(): Command {
10
+ const command = new Command("chart");
11
+
12
+ command
13
+ .description("Get chart/historical data for a symbol")
14
+ .argument("<symbol>", "Stock symbol (e.g., AAPL)")
15
+ .option(
16
+ "-p, --period <period>",
17
+ "Preset period: 1d, 5d, 1wk, 1mo, 3mo, 6mo, 1y, 2y, 5y",
18
+ )
19
+ .option("-s, --start <date>", "Start date (YYYY-MM-DD)")
20
+ .option("-e, --end <date>", "End date (YYYY-MM-DD)")
21
+ .option(
22
+ "-i, --interval <interval>",
23
+ "Interval: 1m, 5m, 15m, 30m, 1h, 1d, 1wk, 1mo",
24
+ )
25
+ .option("--table", "Output as table instead of JSON")
26
+ .option("--pretty", "Pretty print JSON output", true)
27
+ .action(
28
+ async (
29
+ symbol: string,
30
+ options: {
31
+ period?: string;
32
+ start?: string;
33
+ end?: string;
34
+ interval?: string;
35
+ table?: boolean;
36
+ pretty?: boolean;
37
+ },
38
+ ) => {
39
+ const yahooService = createYahooService();
40
+ const formatter = createFormatter(options);
41
+
42
+ // Validate period if provided
43
+ let period: PeriodPreset | undefined;
44
+ if (options.period) {
45
+ if (!isValidPeriod(options.period)) {
46
+ console.error(
47
+ `Invalid period: ${options.period}. Valid options: 1d, 5d, 1wk, 1mo, 3mo, 6mo, 1y, 2y, 5y`,
48
+ );
49
+ process.exit(1);
50
+ }
51
+ period = options.period as PeriodPreset;
52
+ }
53
+
54
+ // Validate interval if provided
55
+ let interval: IntervalType | undefined;
56
+ if (options.interval) {
57
+ if (!isValidInterval(options.interval)) {
58
+ console.error(
59
+ `Invalid interval: ${options.interval}. Valid options: 1m, 5m, 15m, 30m, 1h, 1d, 1wk, 1mo`,
60
+ );
61
+ process.exit(1);
62
+ }
63
+ interval = options.interval as IntervalType;
64
+ }
65
+
66
+ // Validate date range
67
+ if (options.start && options.end) {
68
+ const startDate = new Date(options.start);
69
+ const endDate = new Date(options.end);
70
+ if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
71
+ console.error("Invalid date format. Use YYYY-MM-DD");
72
+ process.exit(1);
73
+ }
74
+ if (startDate >= endDate) {
75
+ console.error("Start date must be before end date");
76
+ process.exit(1);
77
+ }
78
+ }
79
+
80
+ try {
81
+ const chartData = await yahooService.getChart(symbol, {
82
+ period,
83
+ start: options.start,
84
+ end: options.end,
85
+ interval,
86
+ });
87
+ const output = formatter.format(chartData);
88
+ console.log(output);
89
+ } catch (error) {
90
+ console.error(
91
+ "Error fetching chart data:",
92
+ error instanceof Error ? error.message : String(error),
93
+ );
94
+ process.exit(1);
95
+ }
96
+ },
97
+ );
98
+
99
+ return command;
100
+ }
@@ -0,0 +1,10 @@
1
+ export { createQuoteCommand } from "./quote";
2
+ export { createChartCommand } from "./chart";
3
+ export { createSearchCommand } from "./search";
4
+ export { createSummaryCommand } from "./summary";
5
+ export { createNewsCommand } from "./news";
6
+ export { createInsightsCommand } from "./insights";
7
+ export { createOptionsCommand } from "./options";
8
+ export { createRecommendationsCommand } from "./recommendations";
9
+ export { createScreenerCommand } from "./screener";
10
+ export { createIndicatorCommand } from "./indicator";