opencandle 0.1.1 → 0.3.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.
Files changed (278) hide show
  1. package/README.md +111 -79
  2. package/dist/analysts/contracts.d.ts +31 -0
  3. package/dist/analysts/contracts.js +158 -0
  4. package/dist/analysts/contracts.js.map +1 -0
  5. package/dist/analysts/orchestrator.d.ts +11 -2
  6. package/dist/analysts/orchestrator.js +156 -9
  7. package/dist/analysts/orchestrator.js.map +1 -1
  8. package/dist/cli.js +26 -10
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.d.ts +29 -5
  11. package/dist/config.js +18 -8
  12. package/dist/config.js.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/infra/cache.d.ts +34 -0
  17. package/dist/infra/cache.js +44 -3
  18. package/dist/infra/cache.js.map +1 -1
  19. package/dist/infra/index.d.ts +1 -1
  20. package/dist/infra/index.js +1 -1
  21. package/dist/infra/index.js.map +1 -1
  22. package/dist/infra/opencandle-paths.d.ts +1 -0
  23. package/dist/infra/opencandle-paths.js +3 -0
  24. package/dist/infra/opencandle-paths.js.map +1 -1
  25. package/dist/infra/rate-limiter.js +7 -0
  26. package/dist/infra/rate-limiter.js.map +1 -1
  27. package/dist/memory/index.d.ts +3 -0
  28. package/dist/memory/index.js +2 -0
  29. package/dist/memory/index.js.map +1 -1
  30. package/dist/memory/manager.d.ts +19 -0
  31. package/dist/memory/manager.js +132 -0
  32. package/dist/memory/manager.js.map +1 -0
  33. package/dist/memory/sqlite.js +12 -1
  34. package/dist/memory/sqlite.js.map +1 -1
  35. package/dist/memory/types.d.ts +21 -0
  36. package/dist/memory/types.js +47 -0
  37. package/dist/memory/types.js.map +1 -0
  38. package/dist/onboarding/connect.d.ts +23 -0
  39. package/dist/onboarding/connect.js +107 -0
  40. package/dist/onboarding/connect.js.map +1 -0
  41. package/dist/onboarding/credential-interceptor.d.ts +44 -0
  42. package/dist/onboarding/credential-interceptor.js +72 -0
  43. package/dist/onboarding/credential-interceptor.js.map +1 -0
  44. package/dist/onboarding/degradation-accumulator.d.ts +21 -0
  45. package/dist/onboarding/degradation-accumulator.js +55 -0
  46. package/dist/onboarding/degradation-accumulator.js.map +1 -0
  47. package/dist/onboarding/prompt-user.d.ts +23 -0
  48. package/dist/onboarding/prompt-user.js +61 -0
  49. package/dist/onboarding/prompt-user.js.map +1 -0
  50. package/dist/onboarding/providers.d.ts +109 -0
  51. package/dist/onboarding/providers.js +236 -0
  52. package/dist/onboarding/providers.js.map +1 -0
  53. package/dist/onboarding/state.d.ts +31 -2
  54. package/dist/onboarding/state.js +141 -13
  55. package/dist/onboarding/state.js.map +1 -1
  56. package/dist/onboarding/tool-helpers.d.ts +34 -0
  57. package/dist/onboarding/tool-helpers.js +80 -0
  58. package/dist/onboarding/tool-helpers.js.map +1 -0
  59. package/dist/onboarding/tool-tags.d.ts +37 -0
  60. package/dist/onboarding/tool-tags.js +149 -0
  61. package/dist/onboarding/tool-tags.js.map +1 -0
  62. package/dist/onboarding/validation.d.ts +19 -0
  63. package/dist/onboarding/validation.js +117 -0
  64. package/dist/onboarding/validation.js.map +1 -0
  65. package/dist/pi/opencandle-extension.d.ts +5 -1
  66. package/dist/pi/opencandle-extension.js +345 -143
  67. package/dist/pi/opencandle-extension.js.map +1 -1
  68. package/dist/pi/session.d.ts +2 -0
  69. package/dist/pi/session.js +1 -1
  70. package/dist/pi/session.js.map +1 -1
  71. package/dist/pi/setup.d.ts +0 -1
  72. package/dist/pi/setup.js +66 -119
  73. package/dist/pi/setup.js.map +1 -1
  74. package/dist/prompts/context-builder.d.ts +26 -0
  75. package/dist/prompts/context-builder.js +127 -0
  76. package/dist/prompts/context-builder.js.map +1 -0
  77. package/dist/prompts/sections.d.ts +13 -0
  78. package/dist/prompts/sections.js +35 -0
  79. package/dist/prompts/sections.js.map +1 -0
  80. package/dist/providers/alpha-vantage.d.ts +3 -0
  81. package/dist/providers/alpha-vantage.js +204 -77
  82. package/dist/providers/alpha-vantage.js.map +1 -1
  83. package/dist/providers/coingecko.js +53 -37
  84. package/dist/providers/coingecko.js.map +1 -1
  85. package/dist/providers/exa-search.d.ts +39 -0
  86. package/dist/providers/exa-search.js +276 -0
  87. package/dist/providers/exa-search.js.map +1 -0
  88. package/dist/providers/fear-greed.js +23 -15
  89. package/dist/providers/fear-greed.js.map +1 -1
  90. package/dist/providers/finnhub.d.ts +17 -0
  91. package/dist/providers/finnhub.js +94 -0
  92. package/dist/providers/finnhub.js.map +1 -0
  93. package/dist/providers/fred.js +48 -28
  94. package/dist/providers/fred.js.map +1 -1
  95. package/dist/providers/index.d.ts +2 -0
  96. package/dist/providers/index.js +1 -0
  97. package/dist/providers/index.js.map +1 -1
  98. package/dist/providers/provider-credential-error.d.ts +8 -0
  99. package/dist/providers/provider-credential-error.js +22 -0
  100. package/dist/providers/provider-credential-error.js.map +1 -0
  101. package/dist/providers/reddit.d.ts +8 -0
  102. package/dist/providers/reddit.js +78 -43
  103. package/dist/providers/reddit.js.map +1 -1
  104. package/dist/providers/twitter.d.ts +20 -0
  105. package/dist/providers/twitter.js +137 -0
  106. package/dist/providers/twitter.js.map +1 -0
  107. package/dist/providers/web-search.d.ts +17 -0
  108. package/dist/providers/web-search.js +224 -0
  109. package/dist/providers/web-search.js.map +1 -0
  110. package/dist/providers/with-fallback.d.ts +15 -0
  111. package/dist/providers/with-fallback.js +32 -0
  112. package/dist/providers/with-fallback.js.map +1 -0
  113. package/dist/providers/wrap-provider.d.ts +20 -0
  114. package/dist/providers/wrap-provider.js +58 -0
  115. package/dist/providers/wrap-provider.js.map +1 -0
  116. package/dist/providers/yahoo-finance.js +77 -57
  117. package/dist/providers/yahoo-finance.js.map +1 -1
  118. package/dist/routing/classify-intent.js +22 -0
  119. package/dist/routing/classify-intent.js.map +1 -1
  120. package/dist/runtime/evidence.d.ts +35 -0
  121. package/dist/runtime/evidence.js +29 -0
  122. package/dist/runtime/evidence.js.map +1 -0
  123. package/dist/runtime/index.d.ts +16 -0
  124. package/dist/runtime/index.js +10 -0
  125. package/dist/runtime/index.js.map +1 -0
  126. package/dist/runtime/prompt-step.d.ts +41 -0
  127. package/dist/runtime/prompt-step.js +42 -0
  128. package/dist/runtime/prompt-step.js.map +1 -0
  129. package/dist/runtime/provider-ids.d.ts +14 -0
  130. package/dist/runtime/provider-ids.js +14 -0
  131. package/dist/runtime/provider-ids.js.map +1 -0
  132. package/dist/runtime/provider-tracker.d.ts +20 -0
  133. package/dist/runtime/provider-tracker.js +36 -0
  134. package/dist/runtime/provider-tracker.js.map +1 -0
  135. package/dist/runtime/run-context.d.ts +11 -0
  136. package/dist/runtime/run-context.js +14 -0
  137. package/dist/runtime/run-context.js.map +1 -0
  138. package/dist/runtime/session-coordinator.d.ts +47 -0
  139. package/dist/runtime/session-coordinator.js +171 -0
  140. package/dist/runtime/session-coordinator.js.map +1 -0
  141. package/dist/runtime/validation.d.ts +44 -0
  142. package/dist/runtime/validation.js +157 -0
  143. package/dist/runtime/validation.js.map +1 -0
  144. package/dist/runtime/workflow-events.d.ts +21 -0
  145. package/dist/runtime/workflow-events.js +31 -0
  146. package/dist/runtime/workflow-events.js.map +1 -0
  147. package/dist/runtime/workflow-runner.d.ts +36 -0
  148. package/dist/runtime/workflow-runner.js +129 -0
  149. package/dist/runtime/workflow-runner.js.map +1 -0
  150. package/dist/runtime/workflow-types.d.ts +60 -0
  151. package/dist/runtime/workflow-types.js +32 -0
  152. package/dist/runtime/workflow-types.js.map +1 -0
  153. package/dist/sentiment/adapters/finnhub.d.ts +7 -0
  154. package/dist/sentiment/adapters/finnhub.js +39 -0
  155. package/dist/sentiment/adapters/finnhub.js.map +1 -0
  156. package/dist/sentiment/adapters/reddit.d.ts +11 -0
  157. package/dist/sentiment/adapters/reddit.js +54 -0
  158. package/dist/sentiment/adapters/reddit.js.map +1 -0
  159. package/dist/sentiment/adapters/twitter.d.ts +9 -0
  160. package/dist/sentiment/adapters/twitter.js +32 -0
  161. package/dist/sentiment/adapters/twitter.js.map +1 -0
  162. package/dist/sentiment/adapters/web.d.ts +9 -0
  163. package/dist/sentiment/adapters/web.js +40 -0
  164. package/dist/sentiment/adapters/web.js.map +1 -0
  165. package/dist/sentiment/index.d.ts +16 -0
  166. package/dist/sentiment/index.js +44 -0
  167. package/dist/sentiment/index.js.map +1 -0
  168. package/dist/sentiment/keywords.d.ts +2 -0
  169. package/dist/sentiment/keywords.js +9 -0
  170. package/dist/sentiment/keywords.js.map +1 -0
  171. package/dist/sentiment/pipeline.d.ts +9 -0
  172. package/dist/sentiment/pipeline.js +57 -0
  173. package/dist/sentiment/pipeline.js.map +1 -0
  174. package/dist/sentiment/scorer.d.ts +9 -0
  175. package/dist/sentiment/scorer.js +64 -0
  176. package/dist/sentiment/scorer.js.map +1 -0
  177. package/dist/sentiment/store.d.ts +24 -0
  178. package/dist/sentiment/store.js +177 -0
  179. package/dist/sentiment/store.js.map +1 -0
  180. package/dist/sentiment/trends.d.ts +13 -0
  181. package/dist/sentiment/trends.js +73 -0
  182. package/dist/sentiment/trends.js.map +1 -0
  183. package/dist/sentiment/types.d.ts +66 -0
  184. package/dist/sentiment/types.js +54 -0
  185. package/dist/sentiment/types.js.map +1 -0
  186. package/dist/system-prompt.js +60 -2
  187. package/dist/system-prompt.js.map +1 -1
  188. package/dist/tool-kit.d.ts +9 -5
  189. package/dist/tool-kit.js +29 -6
  190. package/dist/tool-kit.js.map +1 -1
  191. package/dist/tools/fundamentals/company-overview.d.ts +3 -1
  192. package/dist/tools/fundamentals/company-overview.js +28 -17
  193. package/dist/tools/fundamentals/company-overview.js.map +1 -1
  194. package/dist/tools/fundamentals/comps.js +47 -39
  195. package/dist/tools/fundamentals/comps.js.map +1 -1
  196. package/dist/tools/fundamentals/dcf.js +83 -65
  197. package/dist/tools/fundamentals/dcf.js.map +1 -1
  198. package/dist/tools/fundamentals/earnings.d.ts +3 -1
  199. package/dist/tools/fundamentals/earnings.js +26 -18
  200. package/dist/tools/fundamentals/earnings.js.map +1 -1
  201. package/dist/tools/fundamentals/financials.d.ts +3 -1
  202. package/dist/tools/fundamentals/financials.js +24 -16
  203. package/dist/tools/fundamentals/financials.js.map +1 -1
  204. package/dist/tools/fundamentals/sec-filings.js +9 -1
  205. package/dist/tools/fundamentals/sec-filings.js.map +1 -1
  206. package/dist/tools/index.js +10 -2
  207. package/dist/tools/index.js.map +1 -1
  208. package/dist/tools/interaction/ask-user.d.ts +3 -0
  209. package/dist/tools/interaction/ask-user.js +51 -0
  210. package/dist/tools/interaction/ask-user.js.map +1 -0
  211. package/dist/tools/interaction/twitter-login.d.ts +8 -0
  212. package/dist/tools/interaction/twitter-login.js +77 -0
  213. package/dist/tools/interaction/twitter-login.js.map +1 -0
  214. package/dist/tools/macro/fear-greed.js +9 -1
  215. package/dist/tools/macro/fear-greed.js.map +1 -1
  216. package/dist/tools/macro/fred-data.d.ts +3 -1
  217. package/dist/tools/macro/fred-data.js +27 -16
  218. package/dist/tools/macro/fred-data.js.map +1 -1
  219. package/dist/tools/market/crypto-history.js +9 -1
  220. package/dist/tools/market/crypto-history.js.map +1 -1
  221. package/dist/tools/market/crypto-price.js +9 -1
  222. package/dist/tools/market/crypto-price.js.map +1 -1
  223. package/dist/tools/market/stock-history.js +28 -1
  224. package/dist/tools/market/stock-history.js.map +1 -1
  225. package/dist/tools/market/stock-quote.js +29 -4
  226. package/dist/tools/market/stock-quote.js.map +1 -1
  227. package/dist/tools/options/option-chain.js +9 -1
  228. package/dist/tools/options/option-chain.js.map +1 -1
  229. package/dist/tools/portfolio/correlation.js +15 -3
  230. package/dist/tools/portfolio/correlation.js.map +1 -1
  231. package/dist/tools/portfolio/predictions.js +6 -5
  232. package/dist/tools/portfolio/predictions.js.map +1 -1
  233. package/dist/tools/portfolio/risk-analysis.js +9 -1
  234. package/dist/tools/portfolio/risk-analysis.js.map +1 -1
  235. package/dist/tools/portfolio/tracker.js +6 -3
  236. package/dist/tools/portfolio/tracker.js.map +1 -1
  237. package/dist/tools/portfolio/watchlist.js +6 -1
  238. package/dist/tools/portfolio/watchlist.js.map +1 -1
  239. package/dist/tools/sentiment/reddit-sentiment.d.ts +3 -1
  240. package/dist/tools/sentiment/reddit-sentiment.js +112 -19
  241. package/dist/tools/sentiment/reddit-sentiment.js.map +1 -1
  242. package/dist/tools/sentiment/sentiment-summary.d.ts +7 -0
  243. package/dist/tools/sentiment/sentiment-summary.js +230 -0
  244. package/dist/tools/sentiment/sentiment-summary.js.map +1 -0
  245. package/dist/tools/sentiment/sentiment-trend.d.ts +22 -0
  246. package/dist/tools/sentiment/sentiment-trend.js +39 -0
  247. package/dist/tools/sentiment/sentiment-trend.js.map +1 -0
  248. package/dist/tools/sentiment/twitter-sentiment.d.ts +9 -0
  249. package/dist/tools/sentiment/twitter-sentiment.js +75 -0
  250. package/dist/tools/sentiment/twitter-sentiment.js.map +1 -0
  251. package/dist/tools/sentiment/web-search.d.ts +11 -0
  252. package/dist/tools/sentiment/web-search.js +115 -0
  253. package/dist/tools/sentiment/web-search.js.map +1 -0
  254. package/dist/tools/sentiment/web-sentiment.d.ts +8 -0
  255. package/dist/tools/sentiment/web-sentiment.js +66 -0
  256. package/dist/tools/sentiment/web-sentiment.js.map +1 -0
  257. package/dist/tools/technical/backtest.js +9 -1
  258. package/dist/tools/technical/backtest.js.map +1 -1
  259. package/dist/tools/technical/indicators.js +9 -1
  260. package/dist/tools/technical/indicators.js.map +1 -1
  261. package/dist/types/index.d.ts +16 -1
  262. package/dist/types/sentiment.d.ts +41 -0
  263. package/dist/workflows/compare-assets.d.ts +3 -0
  264. package/dist/workflows/compare-assets.js +21 -5
  265. package/dist/workflows/compare-assets.js.map +1 -1
  266. package/dist/workflows/index.d.ts +3 -3
  267. package/dist/workflows/index.js +3 -3
  268. package/dist/workflows/index.js.map +1 -1
  269. package/dist/workflows/options-screener.d.ts +3 -0
  270. package/dist/workflows/options-screener.js +24 -7
  271. package/dist/workflows/options-screener.js.map +1 -1
  272. package/dist/workflows/portfolio-builder.d.ts +3 -0
  273. package/dist/workflows/portfolio-builder.js +30 -9
  274. package/dist/workflows/portfolio-builder.js.map +1 -1
  275. package/package.json +27 -7
  276. package/dist/tools/sentiment/news-sentiment.d.ts +0 -7
  277. package/dist/tools/sentiment/news-sentiment.js +0 -57
  278. package/dist/tools/sentiment/news-sentiment.js.map +0 -1
package/README.md CHANGED
@@ -1,55 +1,65 @@
1
1
  # OpenCandle
2
2
 
3
- A financial agent that talks to markets. Ask it for stock prices, options chains with Greeks, macro data, sentiment it fetches real data, computes analytics locally, and gives you actionable answers.
3
+ OpenCandle is a terminal-first financial data agent built with TypeScript and Pi. It fetches market, macro, options, fundamentals, sentiment, and portfolio data from real providers, then lets the model synthesize that data into an answer.
4
4
 
5
- ## What This Does
5
+ This repository is useful in two ways:
6
6
 
7
- OpenCandle is an AI-powered terminal agent for investors and traders. Instead of switching between Yahoo Finance, FRED, Reddit, and a spreadsheet, you ask one agent and it chains the right tools together. It computes technical indicators and options Greeks locally (Black-Scholes), so there's no API dependency for math.
7
+ - Run `opencandle` as an interactive CLI for market research
8
+ - Extend OpenCandle with new tools, providers, or Pi-compatible add-on packages
8
9
 
9
- Type `analyze TSLA` and it runs a full 5-analyst breakdown — fundamentals, technicals, options positioning, sentiment, risk — then synthesizes a verdict.
10
+ ## What You Can Use It For
10
11
 
11
- [Pi](https://pi.dev/) powers the runtime, TUI, auth, and model selection. OpenCandle keeps its own user data in `~/.opencandle/`.
12
+ - Quote and history lookups for stocks and crypto
13
+ - Options chains with locally computed Greeks
14
+ - Company fundamentals, earnings, and SEC filings
15
+ - FRED macro series and Fear & Greed data
16
+ - Reddit-based sentiment and discussion lookups
17
+ - Portfolio tracking, watchlists, correlation, and risk analysis
18
+ - Multi-step workflows such as `/analyze NVDA`
12
19
 
13
- ## Getting Started
20
+ OpenCandle is designed to fetch and format data. The model handles synthesis. Tool code should not invent financial conclusions or hardcode market numbers.
14
21
 
15
- ### Standalone CLI
22
+ ## Install And Run
23
+
24
+ Requires Node.js 20+.
25
+
26
+ ### CLI
16
27
 
17
28
  ```bash
18
29
  npm install -g opencandle
19
30
  opencandle
20
31
 
21
- # or run without installing globally
32
+ # or without installing globally
22
33
  npx opencandle@latest
23
34
  ```
24
35
 
25
- On first run, OpenCandle guides you through AI model setup before chat starts. If you want to rerun that flow later, use `/setup`.
26
-
27
36
  ### From Source
28
37
 
29
38
  ```bash
30
39
  npm install
31
40
  cp .env.example .env
32
- # Add any LLM env vars you want to use locally (for example GEMINI_API_KEY)
33
41
  npm start
34
42
  ```
35
43
 
36
- ### API Keys
44
+ On first run, OpenCandle walks you through model setup. You can rerun that flow later with `/setup`.
37
45
 
38
- | Key | Required | Free Tier | What It Unlocks |
39
- |-----|----------|-----------|-----------------|
40
- | `GEMINI_API_KEY` | No | Yes | Google Gemini via Pi auth/model registry |
41
- | `OPENAI_API_KEY` | No | Paid | OpenAI models via Pi auth/model registry |
42
- | `ANTHROPIC_API_KEY` | No | Paid | Anthropic models via Pi auth/model registry |
43
- | `ALPHA_VANTAGE_API_KEY` | No | 25 req/day | Company fundamentals, earnings, financials |
44
- | `FRED_API_KEY` | No | Generous | Fed rates, CPI, GDP, unemployment, yield curve |
46
+ ## Configuration
45
47
 
46
- Yahoo Finance, CoinGecko, Reddit, and Fear & Greed Index need no keys.
47
- Pi also supports OAuth-backed and custom providers through `~/.pi/agent/auth.json`, `/login`, `/model`, and `~/.pi/agent/models.json`.
48
+ Model access comes from Pi. Market data providers are optional and additive.
48
49
 
49
- ### State and Config
50
+ | Key | Required | Used For |
51
+ | --- | --- | --- |
52
+ | `GEMINI_API_KEY` | No | Google models through Pi |
53
+ | `OPENAI_API_KEY` | No | OpenAI models through Pi |
54
+ | `ANTHROPIC_API_KEY` | No | Anthropic models through Pi |
55
+ | `ALPHA_VANTAGE_API_KEY` | No | Fundamentals, earnings, financial statements |
56
+ | `FRED_API_KEY` | No | Macro series such as rates, CPI, GDP, unemployment |
50
57
 
51
- - Pi runtime config and optional project overrides live in `.pi/` and `~/.pi/agent/...`.
52
- - OpenCandle finance-provider config lives in `~/.opencandle/config.json`:
58
+ Yahoo Finance, CoinGecko, Reddit, SEC EDGAR, and Fear & Greed data do not require keys.
59
+
60
+ OpenCandle stores its own user state in `~/.opencandle/` by default. Pi configuration stays in `.pi/` and `~/.pi/agent/`. The CLI should not depend on repo-local `.pi/extensions/`.
61
+
62
+ Provider keys can also be stored in `~/.opencandle/config.json`:
53
63
 
54
64
  ```json
55
65
  {
@@ -64,87 +74,109 @@ Pi also supports OAuth-backed and custom providers through `~/.pi/agent/auth.jso
64
74
  }
65
75
  ```
66
76
 
67
- - Environment variables still work and override `~/.opencandle/config.json`.
68
- - OpenCandle user data lives in `~/.opencandle/`:
69
- - `~/.opencandle/watchlist.json`
70
- - `~/.opencandle/portfolio.json`
71
- - `~/.opencandle/predictions.json`
72
- - `~/.opencandle/state.db`
73
- - `~/.opencandle/logs/...`
74
- - The published CLI should work from any directory without depending on a repo-local `.pi/extensions/...` file. Project `.pi/` remains optional for user overrides.
77
+ Environment variables override values from `~/.opencandle/config.json`. Set `OPENCANDLE_HOME` if you want OpenCandle state somewhere other than `~/.opencandle/`.
78
+
79
+ ## Basic Usage
75
80
 
76
- ## Usage
81
+ OpenCandle runs inside Pi's interactive terminal UI.
77
82
 
78
- OpenCandle now runs inside Pi's interactive TUI. Useful controls:
83
+ Useful commands:
79
84
 
80
85
  ```text
81
- /model Switch provider/model
82
- /login Authenticate an OAuth-backed provider
83
- /setup Rerun OpenCandle setup
84
- /analyze NVDA Run the multi-analyst workflow
86
+ /setup
87
+ /login
88
+ /model
89
+ /analyze AAPL
85
90
  ```
86
91
 
87
- Natural-language prompts still work:
92
+ Example prompts:
88
93
 
89
94
  ```text
90
- What's the price of AAPL?
95
+ What is AAPL trading at?
91
96
  Get the options chain for TSLA expiring April 24
92
97
  Show me MSFT puts with Greeks
93
- What's the Fear and Greed index?
94
98
  Get the fed funds rate from FRED
95
99
  Add 100 shares of NVDA at 120 to my portfolio, then show my portfolio
96
100
  Run risk analysis on SPY
97
- analyze AAPL
98
101
  ```
99
102
 
100
- ## Tools (23)
103
+ ## Data Sources And Tool Coverage
101
104
 
102
- | Category | Tools | Data Source |
103
- |----------|-------|------------|
104
- | **Market Data** | `search_ticker`, `get_stock_quote`, `get_stock_history`, `get_crypto_price`, `get_crypto_history` | Yahoo Finance, CoinGecko |
105
- | **Options** | `get_option_chain` — strikes, bids/asks, volume, OI, IV, computed Greeks | Yahoo Finance + Black-Scholes |
106
- | **Fundamentals** | `get_company_overview`, `get_financials`, `get_earnings`, `compute_dcf`, `compare_companies`, `get_sec_filings` | Alpha Vantage, SEC EDGAR |
107
- | **Technical** | `get_technical_indicators`, `backtest_strategy` — SMA, EMA, RSI, MACD, Bollinger Bands, backtesting | Computed locally from OHLCV |
108
- | **Macro** | `get_economic_data`, `get_fear_greed` | FRED, alternative.me |
109
- | **Sentiment** | `get_reddit_sentiment`, `get_reddit_discussions` | Reddit JSON API |
110
- | **Portfolio** | `track_portfolio`, `analyze_risk`, `manage_watchlist`, `analyze_correlation`, `track_prediction` | Yahoo Finance + local math |
105
+ | Area | Examples | Source |
106
+ | --- | --- | --- |
107
+ | Market data | quotes, history, ticker search, crypto price/history | Yahoo Finance, CoinGecko |
108
+ | Options | chains, open interest, IV, Greeks | Yahoo Finance plus local calculations |
109
+ | Fundamentals | overview, financials, earnings, DCF, company comparison | Alpha Vantage |
110
+ | Macro | economic series, Fear & Greed | FRED, alternative.me |
111
+ | Sentiment | Reddit, Twitter/X, and web sentiment with cross-source pipeline | Reddit JSON API, Twitter/X, DuckDuckGo, Brave |
112
+ | Filings | SEC filing search | SEC EDGAR |
113
+ | Portfolio | watchlist, prediction tracking, correlation, risk | Local state plus market data |
111
114
 
112
- ## How It Works
115
+ ## Engineering Notes
113
116
 
114
- Built on [Pi-mono](https://github.com/badlogic/pi-mono)'s `pi-coding-agent` SDK and TUI, with OpenCandle loaded as a bundled finance-only Pi extension. Tools are defined with [TypeBox](https://github.com/sinclairzx81/typebox) schemas and registered through Pi's extension system.
117
+ ### Project Shape
115
118
 
119
+ ```text
120
+ src/
121
+ ├── providers/ API clients
122
+ ├── tools/ Tool implementations by domain
123
+ ├── infra/ Cache, rate limiter, HTTP, browser, paths
124
+ ├── routing/ Intent classification and slot resolution
125
+ ├── workflows/ Multi-step workflow builders
126
+ ├── memory/ SQLite-backed state and retrieval
127
+ ├── analysts/ Multi-analyst orchestration
128
+ ├── pi/ Pi integration and session wiring
129
+ └── index.ts Public exports
116
130
  ```
117
- User prompt -> Pi session -> selected provider/model -> tool calls -> execute in parallel -> response
118
- ^ |
119
- |____________________ Pi session + model registry _________________|
131
+
132
+ ### Development Commands
133
+
134
+ ```bash
135
+ npm start
136
+ npm test
137
+ npm run test:watch
138
+ npm run test:e2e
139
+ npm run test:e2e:cli
140
+ npm run test:e2e:providers
120
141
  ```
121
142
 
122
- Key architectural choices:
123
- - **Local computation** over API calls for math (indicators, Greeks, risk metrics)
124
- - **Stealth browser fallback** via [Camoufox](https://github.com/daijro/camoufox) when Yahoo rate-limits Node.js `fetch`
125
- - **TTL caching + token bucket rate limiting** per provider
126
- - **Pi-native auth/model flow** via `/model`, `/login`, `auth.json`, and `models.json`
127
- - **Global OpenCandle state** under `~/.opencandle/`, separate from Pi config
128
- - **Multi-analyst orchestration** via Pi extension commands and follow-up message hooks
143
+ `npm test` is the required baseline check after changes.
129
144
 
130
- ## Test
145
+ ### Repository Rules That Matter
146
+
147
+ - TDD is mandatory for behavior changes
148
+ - Unit tests mock `globalThis.fetch` and use JSON fixtures
149
+ - Use `cache` and `rateLimiter` for external calls
150
+ - Tools fetch and format data; analysts and prompts synthesize
151
+ - Keep typing strict and use `.js` extensions on relative imports
152
+
153
+ ### Public Package Exports
154
+
155
+ Besides the CLI, the package exposes pieces for engineers building on top of OpenCandle:
156
+
157
+ - `opencandle`
158
+ - `opencandle/tool-kit`
159
+ - `opencandle/infra`
160
+ - `opencandle/types`
161
+ - `opencandle/providers`
162
+
163
+ If you want to add a new tool or publish an add-on package, start with [docs/build-a-tool.md](./docs/build-a-tool.md).
164
+
165
+ ## Testing The Agent
166
+
167
+ For end-to-end agent driving with file-based IPC:
131
168
 
132
169
  ```bash
133
- npm test # 208 unit tests
134
- npm run test:watch # watch mode
170
+ npx tsx tests/harness/manual-run.ts /tmp/opencandle-ipc "What is AAPL trading at?"
135
171
  ```
136
172
 
137
- ## Project Docs
173
+ The harness writes status and trace files into the IPC directory. See [tests/harness/README.md](./tests/harness/README.md) for the full flow.
138
174
 
139
- - OSS launch and npm release plan: [docs/production-plan.md](https://github.com/Kahtaf/OpenCandle/blob/main/docs/production-plan.md)
140
- - Contributor guide: [CONTRIBUTING.md](https://github.com/Kahtaf/OpenCandle/blob/main/CONTRIBUTING.md)
141
- - Security policy: [SECURITY.md](https://github.com/Kahtaf/OpenCandle/blob/main/SECURITY.md)
142
- - Release history: [CHANGELOG.md](https://github.com/Kahtaf/OpenCandle/blob/main/CHANGELOG.md)
143
-
144
- ## Tech Stack
175
+ ## Project Docs
145
176
 
146
- - **Runtime**: TypeScript, Node.js
147
- - **LLM**: Pi model registry with Gemini, OpenAI, Anthropic, and custom providers
148
- - **Browser**: Camoufox (anti-detection Firefox for scraping fallback)
149
- - **Testing**: Vitest with fixture-mocked `fetch`
150
- - **No frameworks**: Raw providers, no LangChain/LlamaIndex
177
+ - [CONTRIBUTING.md](./CONTRIBUTING.md)
178
+ - [docs/build-a-tool.md](./docs/build-a-tool.md)
179
+ - [tests/harness/README.md](./tests/harness/README.md)
180
+ - [CHANGELOG.md](./CHANGELOG.md)
181
+ - [SECURITY.md](./SECURITY.md)
182
+ - [LICENSE](./LICENSE)
@@ -0,0 +1,31 @@
1
+ import type { AnalystOutput, AnalystSignal, DebateSide, DebateOutput } from "../runtime/workflow-types.js";
2
+ import type { EvidenceRecord } from "../runtime/evidence.js";
3
+ /** All analyst roles. */
4
+ export type AnalystRole = "valuation" | "momentum" | "options" | "contrarian" | "risk";
5
+ /** Evidence fields expected per analyst role. */
6
+ export declare const ROLE_EXPECTED_EVIDENCE: Record<AnalystRole, string[]>;
7
+ /**
8
+ * Parse an LLM response into a structured AnalystOutput.
9
+ * Falls back to raw text if parsing fails.
10
+ */
11
+ export declare function parseAnalystOutput(role: string, responseText: string): AnalystOutput;
12
+ /** Build a structured vote tally from analyst outputs. */
13
+ export declare function tallyVotes(outputs: AnalystOutput[]): {
14
+ buy: number;
15
+ hold: number;
16
+ sell: number;
17
+ weightedConviction: number;
18
+ verdict: AnalystSignal;
19
+ };
20
+ /**
21
+ * Parse an LLM debate response into a structured DebateOutput.
22
+ * Eval/test helper only — not used in the live workflow path.
23
+ */
24
+ export declare function parseDebateOutput(side: DebateSide, responseText: string): DebateOutput;
25
+ /**
26
+ * Check whether analysts produced a BUY+SELL split.
27
+ * Eval/test helper only — not used in the live workflow path.
28
+ */
29
+ export declare function isAnalystSplit(outputs: AnalystOutput[]): boolean;
30
+ /** Collect all evidence from analyst outputs. */
31
+ export declare function collectEvidence(outputs: AnalystOutput[]): EvidenceRecord[];
@@ -0,0 +1,158 @@
1
+ /** Evidence fields expected per analyst role. */
2
+ export const ROLE_EXPECTED_EVIDENCE = {
3
+ valuation: ["P/E Ratio", "Forward P/E", "EPS", "Intrinsic Value", "Revenue Growth"],
4
+ momentum: ["RSI", "MACD", "SMA 50", "SMA 200", "Volume Trend"],
5
+ options: ["Put/Call Ratio", "IV Level", "Unusual Volume", "Max Pain"],
6
+ contrarian: ["Fear & Greed Index", "Reddit Sentiment", "Sentiment Score"],
7
+ risk: ["Annualized Volatility", "Sharpe Ratio", "Max Drawdown", "VaR 95%", "Position Size"],
8
+ };
9
+ /**
10
+ * Parse an LLM response into a structured AnalystOutput.
11
+ * Falls back to raw text if parsing fails.
12
+ */
13
+ export function parseAnalystOutput(role, responseText) {
14
+ const signal = extractSignal(responseText);
15
+ const conviction = extractConviction(responseText);
16
+ const thesis = extractThesis(responseText);
17
+ return {
18
+ role,
19
+ signal: signal ?? "HOLD",
20
+ conviction: conviction ?? 5,
21
+ thesis: thesis ?? "",
22
+ evidence: [],
23
+ rawText: responseText,
24
+ };
25
+ }
26
+ function extractSignal(text) {
27
+ const match = text.match(/SIGNAL:\s*(BUY|HOLD|SELL)/i);
28
+ if (match)
29
+ return match[1].toUpperCase();
30
+ return null;
31
+ }
32
+ function extractConviction(text) {
33
+ const match = text.match(/CONVICTION:\s*(\d+)/i);
34
+ if (match) {
35
+ const value = parseInt(match[1], 10);
36
+ if (value >= 1 && value <= 10)
37
+ return value;
38
+ }
39
+ return null;
40
+ }
41
+ function extractThesis(text) {
42
+ const match = text.match(/THESIS:\s*(.+)/i);
43
+ return match ? match[1].trim() : null;
44
+ }
45
+ /** Build a structured vote tally from analyst outputs. */
46
+ export function tallyVotes(outputs) {
47
+ let buy = 0;
48
+ let hold = 0;
49
+ let sell = 0;
50
+ let totalWeight = 0;
51
+ let weightedSum = 0;
52
+ for (const output of outputs) {
53
+ switch (output.signal) {
54
+ case "BUY":
55
+ buy++;
56
+ break;
57
+ case "HOLD":
58
+ hold++;
59
+ break;
60
+ case "SELL":
61
+ sell++;
62
+ break;
63
+ }
64
+ totalWeight += output.conviction;
65
+ const signalValue = output.signal === "BUY" ? 1 : output.signal === "SELL" ? -1 : 0;
66
+ weightedSum += signalValue * output.conviction;
67
+ }
68
+ const weightedConviction = totalWeight > 0
69
+ ? Math.round((totalWeight / outputs.length) * 10) / 10
70
+ : 0;
71
+ let verdict;
72
+ if (weightedSum > 0)
73
+ verdict = "BUY";
74
+ else if (weightedSum < 0)
75
+ verdict = "SELL";
76
+ else
77
+ verdict = "HOLD";
78
+ return { buy, hold, sell, weightedConviction, verdict };
79
+ }
80
+ /**
81
+ * Parse an LLM debate response into a structured DebateOutput.
82
+ * Eval/test helper only — not used in the live workflow path.
83
+ */
84
+ export function parseDebateOutput(side, responseText) {
85
+ // Detect skipped rebuttal
86
+ if (/^rebuttal skipped/i.test(responseText.trim())) {
87
+ return {
88
+ side,
89
+ thesis: "",
90
+ keyRisk: "",
91
+ concessions: [],
92
+ remainingConviction: 0,
93
+ evidence: [],
94
+ rawText: responseText,
95
+ };
96
+ }
97
+ const thesis = extractDebateThesis(side, responseText);
98
+ const keyRisk = extractKeyRisk(side, responseText);
99
+ const concessions = extractConcessions(responseText);
100
+ const remainingConviction = extractRemainingConviction(responseText);
101
+ return {
102
+ side,
103
+ thesis,
104
+ keyRisk,
105
+ concessions,
106
+ remainingConviction,
107
+ evidence: [],
108
+ rawText: responseText,
109
+ };
110
+ }
111
+ function extractDebateThesis(side, text) {
112
+ const label = side === "bull" ? "BULL THESIS" : "BEAR THESIS";
113
+ const match = text.match(new RegExp(`${label}:\\s*(.+)`, "i"));
114
+ return match ? match[1].trim() : "";
115
+ }
116
+ function extractKeyRisk(side, text) {
117
+ if (side === "bear") {
118
+ const match = text.match(/WHAT WOULD CHANGE MY MIND:\s*(.+)/i);
119
+ return match ? match[1].trim() : "";
120
+ }
121
+ const match = text.match(/KEY RISK(?:\s+TO THIS THESIS)?:\s*(.+)/i);
122
+ return match ? match[1].trim() : "";
123
+ }
124
+ function extractConcessions(text) {
125
+ const match = text.match(/CONCESSIONS:\s*([\s\S]*?)(?=REMAINING CONVICTION:|$)/i);
126
+ if (!match)
127
+ return [];
128
+ return match[1]
129
+ .split("\n")
130
+ .map((line) => line.replace(/^[-*•]\s*/, "").trim())
131
+ .filter(Boolean);
132
+ }
133
+ function extractRemainingConviction(text) {
134
+ const match = text.match(/REMAINING CONVICTION:\s*(\d+)/i);
135
+ if (match) {
136
+ const value = parseInt(match[1], 10);
137
+ if (value >= 1 && value <= 10)
138
+ return value;
139
+ }
140
+ return 0;
141
+ }
142
+ /**
143
+ * Check whether analysts produced a BUY+SELL split.
144
+ * Eval/test helper only — not used in the live workflow path.
145
+ */
146
+ export function isAnalystSplit(outputs) {
147
+ const votes = tallyVotes(outputs);
148
+ return votes.buy > 0 && votes.sell > 0;
149
+ }
150
+ /** Collect all evidence from analyst outputs. */
151
+ export function collectEvidence(outputs) {
152
+ const evidence = [];
153
+ for (const output of outputs) {
154
+ evidence.push(...output.evidence);
155
+ }
156
+ return evidence;
157
+ }
158
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/analysts/contracts.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,16 @@
1
1
  export type AnalystRole = "valuation" | "momentum" | "options" | "contrarian" | "risk";
2
+ export declare function buildBullPrompt(symbol: string): string;
3
+ export declare function buildBearPrompt(symbol: string): string;
4
+ export declare function buildRebuttalPrompt(symbol: string): string;
5
+ export declare function buildSynthesisPrompt(symbol: string): string;
2
6
  export declare function getInitialAnalysisPrompt(symbol: string): string;
3
- export declare function getComprehensiveAnalysisPrompts(symbol: string): string[];
4
- export declare function runComprehensiveAnalysis(enqueueFollowUp: (prompt: string) => void, symbol: string): void;
7
+ export interface ComprehensiveAnalysisOptions {
8
+ debate?: boolean;
9
+ }
10
+ export declare function getComprehensiveAnalysisPrompts(symbol: string, options?: ComprehensiveAnalysisOptions): string[];
11
+ import type { WorkflowDefinition } from "../runtime/prompt-step.js";
12
+ export declare function buildComprehensiveAnalysisDefinition(symbol: string, options?: ComprehensiveAnalysisOptions): WorkflowDefinition;
13
+ export declare function runComprehensiveAnalysis(enqueueFollowUp: (prompt: string) => void, symbol: string, options?: ComprehensiveAnalysisOptions): void;
5
14
  export declare function isAnalysisRequest(input: string): {
6
15
  match: boolean;
7
16
  symbol?: string;