sigma-terminal 3.3.2__py3-none-any.whl → 3.4.0__py3-none-any.whl

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.
sigma/setup.py CHANGED
@@ -1,4 +1,4 @@
1
- """Sigma v3.3.1 - Setup Wizard."""
1
+ """Sigma v3.4.0 - Setup Wizard."""
2
2
 
3
3
  import os
4
4
  import sys
@@ -25,20 +25,20 @@ from .config import (
25
25
  )
26
26
 
27
27
 
28
- __version__ = "3.3.1"
28
+ __version__ = "3.4.0"
29
29
  SIGMA = "σ"
30
30
  console = Console()
31
31
 
32
- # Clean banner - just SIGMA, no SETU
32
+ # Clean banner - just SIGMA
33
33
  BANNER = """
34
- [bold blue]███████╗██╗ ██████╗ ███╗ ███╗ █████╗ [/bold blue]
35
- [bold blue]██╔════╝██║██╔════╝ ████╗ ████║██╔══██╗[/bold blue]
36
- [bold blue]███████╗██║██║ ███╗██╔████╔██║███████║[/bold blue]
37
- [bold blue]╚════██║██║██║ ██║██║╚██╔╝██║██╔══██║[/bold blue]
38
- [bold blue]███████║██║╚██████╔╝██║ ╚═╝ ██║██║ ██║[/bold blue]
39
- [bold blue]╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝[/bold blue]
34
+ [bold #3b82f6]███████╗██╗ ██████╗ ███╗ ███╗ █████╗ [/bold #3b82f6]
35
+ [bold #60a5fa]██╔════╝██║██╔════╝ ████╗ ████║██╔══██╗[/bold #60a5fa]
36
+ [bold #93c5fd]███████╗██║██║ ███╗██╔████╔██║███████║[/bold #93c5fd]
37
+ [bold #60a5fa]╚════██║██║██║ ██║██║╚██╔╝██║██╔══██║[/bold #60a5fa]
38
+ [bold #3b82f6]███████║██║╚██████╔╝██║ ╚═╝ ██║██║ ██║[/bold #3b82f6]
39
+ [bold #1d4ed8]╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝[/bold #1d4ed8]
40
40
 
41
- [bold cyan]σ Finance Research Agent[/bold cyan] [dim]- Setup Wizard v3.3.1[/dim]
41
+ [bold cyan]σ Finance Research Agent[/bold cyan] [dim]- Setup Wizard v3.4.0[/dim]
42
42
  """
43
43
 
44
44
 
@@ -265,7 +265,7 @@ class SetupWizard:
265
265
  if self.settings.default_provider != LLMProvider.OLLAMA:
266
266
  ollama_running, ollama_host = detect_ollama()
267
267
  if ollama_running and ollama_host:
268
- console.print(f"[green][/green] Ollama detected at {ollama_host}")
268
+ console.print(f"[green][ok][/green] Ollama detected at {ollama_host}")
269
269
  if Confirm.ask("Enable Ollama as local fallback?", default=True):
270
270
  save_setting("ollama_host", ollama_host)
271
271
  console.print(f"[cyan]{SIGMA}[/cyan] Ollama enabled")
@@ -280,7 +280,7 @@ class SetupWizard:
280
280
  lean_installed, lean_cli, lean_dir = detect_lean_installation()
281
281
 
282
282
  if lean_installed:
283
- console.print(f"[green][/green] LEAN/QuantConnect detected!")
283
+ console.print(f"[green][ok][/green] LEAN/QuantConnect detected!")
284
284
  if lean_cli:
285
285
  console.print(f" [dim]CLI: {lean_cli}[/dim]")
286
286
  if lean_dir:
@@ -316,7 +316,7 @@ class SetupWizard:
316
316
  success, message = install_lean_cli_sync()
317
317
 
318
318
  if success:
319
- console.print(f"[green][/green] {message}")
319
+ console.print(f"[green][ok][/green] {message}")
320
320
  save_setting("lean_enabled", "true")
321
321
  save_setting("lean_cli_path", "lean")
322
322
 
@@ -325,7 +325,7 @@ class SetupWizard:
325
325
  if lean_cli:
326
326
  console.print(f"[cyan]{SIGMA}[/cyan] LEAN CLI ready: {lean_cli}")
327
327
  else:
328
- console.print(f"[red][/red] {message}")
328
+ console.print(f"[red][x][/red] {message}")
329
329
  console.print("[dim]You can install manually later: pip install lean[/dim]")
330
330
 
331
331
  elif lean_choice == "manual":
sigma/tools.py CHANGED
@@ -583,6 +583,211 @@ def get_market_news(tickers: str = "", topics: str = "") -> dict:
583
583
  return {"error": str(e)}
584
584
 
585
585
 
586
+ # ============================================================================
587
+ # POLYGON.IO TOOLS (Real-time & Historical Market Data)
588
+ # ============================================================================
589
+
590
+ def _get_polygon_key() -> Optional[str]:
591
+ """Get Polygon.io API key from config."""
592
+ try:
593
+ from .config import get_settings
594
+ return get_settings().polygon_api_key
595
+ except:
596
+ return None
597
+
598
+
599
+ def polygon_get_quote(symbol: str) -> dict:
600
+ """Get real-time quote from Polygon.io with additional data."""
601
+ api_key = _get_polygon_key()
602
+ if not api_key:
603
+ return {"error": "Polygon API key not configured. Use /setkey polygon <key>", "fallback": True}
604
+
605
+ import requests
606
+
607
+ try:
608
+ symbol = symbol.upper()
609
+
610
+ # Get previous day's data
611
+ prev_url = f"https://api.polygon.io/v2/aggs/ticker/{symbol}/prev?adjusted=true&apiKey={api_key}"
612
+ prev_response = requests.get(prev_url, timeout=10)
613
+
614
+ if prev_response.status_code == 403:
615
+ return {"error": "Polygon API key is invalid or expired", "error_code": 1101}
616
+ elif prev_response.status_code == 429:
617
+ return {"error": "Polygon rate limit exceeded", "error_code": 1303}
618
+ elif prev_response.status_code != 200:
619
+ return {"error": f"Polygon API error: {prev_response.status_code}"}
620
+
621
+ prev_data = prev_response.json()
622
+
623
+ if prev_data.get("resultsCount", 0) == 0:
624
+ return {"error": f"No data found for {symbol}", "error_code": 1300}
625
+
626
+ result = prev_data["results"][0]
627
+
628
+ # Get ticker details
629
+ details_url = f"https://api.polygon.io/v3/reference/tickers/{symbol}?apiKey={api_key}"
630
+ details_response = requests.get(details_url, timeout=10)
631
+ details = {}
632
+ if details_response.status_code == 200:
633
+ details_data = details_response.json()
634
+ if details_data.get("results"):
635
+ details = details_data["results"]
636
+
637
+ return {
638
+ "symbol": symbol,
639
+ "name": details.get("name", symbol),
640
+ "open": result.get("o", 0),
641
+ "high": result.get("h", 0),
642
+ "low": result.get("l", 0),
643
+ "close": result.get("c", 0),
644
+ "volume": result.get("v", 0),
645
+ "vwap": result.get("vw", 0),
646
+ "timestamp": result.get("t"),
647
+ "transactions": result.get("n", 0),
648
+ "market_cap": details.get("market_cap"),
649
+ "primary_exchange": details.get("primary_exchange"),
650
+ "type": details.get("type"),
651
+ "source": "polygon.io"
652
+ }
653
+ except requests.exceptions.Timeout:
654
+ return {"error": "Request timed out", "error_code": 1002}
655
+ except requests.exceptions.ConnectionError:
656
+ return {"error": "Connection error", "error_code": 1400}
657
+ except Exception as e:
658
+ return {"error": str(e), "error_code": 1000}
659
+
660
+
661
+ def polygon_get_aggregates(symbol: str, timespan: str = "day", multiplier: int = 1,
662
+ from_date: str = "", to_date: str = "", limit: int = 120) -> dict:
663
+ """Get historical aggregated bars from Polygon.io."""
664
+ api_key = _get_polygon_key()
665
+ if not api_key:
666
+ return {"error": "Polygon API key not configured. Use /setkey polygon <key>"}
667
+
668
+ import requests
669
+
670
+ try:
671
+ symbol = symbol.upper()
672
+
673
+ # Default date range: last 6 months
674
+ if not to_date:
675
+ to_date = datetime.now().strftime("%Y-%m-%d")
676
+ if not from_date:
677
+ from_date = (datetime.now() - timedelta(days=180)).strftime("%Y-%m-%d")
678
+
679
+ url = (f"https://api.polygon.io/v2/aggs/ticker/{symbol}/range/"
680
+ f"{multiplier}/{timespan}/{from_date}/{to_date}"
681
+ f"?adjusted=true&sort=desc&limit={limit}&apiKey={api_key}")
682
+
683
+ response = requests.get(url, timeout=15)
684
+
685
+ if response.status_code != 200:
686
+ return {"error": f"Polygon API error: {response.status_code}"}
687
+
688
+ data = response.json()
689
+
690
+ if data.get("resultsCount", 0) == 0:
691
+ return {"error": f"No data found for {symbol}"}
692
+
693
+ results = data["results"]
694
+
695
+ # Calculate statistics
696
+ closes = [r["c"] for r in results]
697
+ highs = [r["h"] for r in results]
698
+ lows = [r["l"] for r in results]
699
+ volumes = [r["v"] for r in results]
700
+
701
+ latest = results[0]
702
+ oldest = results[-1]
703
+
704
+ return {
705
+ "symbol": symbol,
706
+ "timespan": timespan,
707
+ "from": from_date,
708
+ "to": to_date,
709
+ "data_points": len(results),
710
+ "latest_close": latest["c"],
711
+ "oldest_close": oldest["c"],
712
+ "period_return": round((latest["c"] / oldest["c"] - 1) * 100, 2),
713
+ "high": max(highs),
714
+ "low": min(lows),
715
+ "avg_volume": int(sum(volumes) / len(volumes)),
716
+ "total_volume": sum(volumes),
717
+ "source": "polygon.io"
718
+ }
719
+ except Exception as e:
720
+ return {"error": str(e)}
721
+
722
+
723
+ def polygon_get_ticker_news(symbol: str, limit: int = 10) -> dict:
724
+ """Get news articles for a ticker from Polygon.io."""
725
+ api_key = _get_polygon_key()
726
+ if not api_key:
727
+ return {"error": "Polygon API key not configured. Use /setkey polygon <key>"}
728
+
729
+ import requests
730
+
731
+ try:
732
+ symbol = symbol.upper()
733
+ url = f"https://api.polygon.io/v2/reference/news?ticker={symbol}&limit={limit}&apiKey={api_key}"
734
+
735
+ response = requests.get(url, timeout=10)
736
+
737
+ if response.status_code != 200:
738
+ return {"error": f"Polygon API error: {response.status_code}"}
739
+
740
+ data = response.json()
741
+ articles = []
742
+
743
+ for item in data.get("results", []):
744
+ articles.append({
745
+ "title": item.get("title", ""),
746
+ "author": item.get("author", ""),
747
+ "published": item.get("published_utc", ""),
748
+ "article_url": item.get("article_url", ""),
749
+ "tickers": item.get("tickers", []),
750
+ "description": item.get("description", "")[:300] + "..." if item.get("description") else "",
751
+ "keywords": item.get("keywords", [])[:5]
752
+ })
753
+
754
+ return {
755
+ "symbol": symbol,
756
+ "articles": articles,
757
+ "source": "polygon.io"
758
+ }
759
+ except Exception as e:
760
+ return {"error": str(e)}
761
+
762
+
763
+ def polygon_market_status() -> dict:
764
+ """Get current market status from Polygon.io."""
765
+ api_key = _get_polygon_key()
766
+ if not api_key:
767
+ return {"error": "Polygon API key not configured. Use /setkey polygon <key>"}
768
+
769
+ import requests
770
+
771
+ try:
772
+ url = f"https://api.polygon.io/v1/marketstatus/now?apiKey={api_key}"
773
+ response = requests.get(url, timeout=10)
774
+
775
+ if response.status_code != 200:
776
+ return {"error": f"Polygon API error: {response.status_code}"}
777
+
778
+ data = response.json()
779
+
780
+ return {
781
+ "market": data.get("market", "unknown"),
782
+ "server_time": data.get("serverTime"),
783
+ "exchanges": data.get("exchanges", {}),
784
+ "currencies": data.get("currencies", {}),
785
+ "source": "polygon.io"
786
+ }
787
+ except Exception as e:
788
+ return {"error": str(e)}
789
+
790
+
586
791
  # ============================================================================
587
792
  # EXA SEARCH TOOLS (Financial News, SEC Filings)
588
793
  # ============================================================================
@@ -1008,6 +1213,67 @@ TOOLS = [
1008
1213
  }
1009
1214
  }
1010
1215
  },
1216
+ # Polygon.io tools (enhanced market data)
1217
+ {
1218
+ "type": "function",
1219
+ "function": {
1220
+ "name": "polygon_get_quote",
1221
+ "description": "Get real-time stock quote with extended data from Polygon.io (requires API key)",
1222
+ "parameters": {
1223
+ "type": "object",
1224
+ "properties": {
1225
+ "symbol": {"type": "string", "description": "Stock ticker symbol (e.g., AAPL, MSFT)"}
1226
+ },
1227
+ "required": ["symbol"]
1228
+ }
1229
+ }
1230
+ },
1231
+ {
1232
+ "type": "function",
1233
+ "function": {
1234
+ "name": "polygon_get_aggregates",
1235
+ "description": "Get historical price aggregates/bars from Polygon.io with custom timespan",
1236
+ "parameters": {
1237
+ "type": "object",
1238
+ "properties": {
1239
+ "symbol": {"type": "string", "description": "Stock ticker symbol"},
1240
+ "timespan": {"type": "string", "enum": ["minute", "hour", "day", "week", "month"], "description": "Size of time window", "default": "day"},
1241
+ "multiplier": {"type": "integer", "description": "Size multiplier for timespan", "default": 1},
1242
+ "from_date": {"type": "string", "description": "Start date (YYYY-MM-DD)", "default": ""},
1243
+ "to_date": {"type": "string", "description": "End date (YYYY-MM-DD)", "default": ""},
1244
+ "limit": {"type": "integer", "description": "Number of results", "default": 120}
1245
+ },
1246
+ "required": ["symbol"]
1247
+ }
1248
+ }
1249
+ },
1250
+ {
1251
+ "type": "function",
1252
+ "function": {
1253
+ "name": "polygon_get_ticker_news",
1254
+ "description": "Get recent news articles for a stock from Polygon.io",
1255
+ "parameters": {
1256
+ "type": "object",
1257
+ "properties": {
1258
+ "symbol": {"type": "string", "description": "Stock ticker symbol"},
1259
+ "limit": {"type": "integer", "description": "Number of articles", "default": 10}
1260
+ },
1261
+ "required": ["symbol"]
1262
+ }
1263
+ }
1264
+ },
1265
+ {
1266
+ "type": "function",
1267
+ "function": {
1268
+ "name": "polygon_market_status",
1269
+ "description": "Get current market status (open/closed) from Polygon.io",
1270
+ "parameters": {
1271
+ "type": "object",
1272
+ "properties": {},
1273
+ "required": []
1274
+ }
1275
+ }
1276
+ },
1011
1277
  ]
1012
1278
 
1013
1279
 
@@ -1032,12 +1298,20 @@ TOOL_FUNCTIONS = {
1032
1298
  "search_financial_news": search_financial_news,
1033
1299
  "search_sec_filings": search_sec_filings,
1034
1300
  "search_earnings_transcripts": search_earnings_transcripts,
1301
+ # Polygon.io
1302
+ "polygon_get_quote": polygon_get_quote,
1303
+ "polygon_get_aggregates": polygon_get_aggregates,
1304
+ "polygon_get_ticker_news": polygon_get_ticker_news,
1305
+ "polygon_market_status": polygon_market_status,
1035
1306
  }
1036
1307
 
1037
1308
 
1038
1309
  def execute_tool(name: str, args: dict) -> Any:
1039
- """Execute a tool by name."""
1310
+ """Execute a tool by name with error handling."""
1040
1311
  func = TOOL_FUNCTIONS.get(name)
1041
1312
  if func:
1042
- return func(**args)
1043
- return {"error": f"Unknown tool: {name}"}
1313
+ try:
1314
+ return func(**args)
1315
+ except Exception as e:
1316
+ return {"error": f"Tool execution failed: {str(e)}", "error_code": 1000}
1317
+ return {"error": f"Unknown tool: {name}", "error_code": 1001}
@@ -0,0 +1,264 @@
1
+ Metadata-Version: 2.4
2
+ Name: sigma-terminal
3
+ Version: 3.4.0
4
+ Summary: Sigma - Finance Research Agent
5
+ Project-URL: Homepage, https://github.com/desenyon/sigma
6
+ Project-URL: Documentation, https://github.com/desenyon/sigma/wiki
7
+ Project-URL: Repository, https://github.com/desenyon/sigma
8
+ Author: Sigma Team
9
+ License: Proprietary
10
+ License-File: LICENSE
11
+ Keywords: ai,analytics,backtesting,finance,investment,portfolio,quantitative,research,stocks,terminal,trading
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Financial and Insurance Industry
15
+ Classifier: License :: Other/Proprietary License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Office/Business :: Financial :: Investment
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: aiohttp>=3.9.0
22
+ Requires-Dist: anthropic>=0.18.0
23
+ Requires-Dist: google-genai>=1.0.0
24
+ Requires-Dist: groq>=0.4.0
25
+ Requires-Dist: httpx>=0.26.0
26
+ Requires-Dist: kaleido>=0.2.1
27
+ Requires-Dist: numpy>=1.26.0
28
+ Requires-Dist: openai>=1.12.0
29
+ Requires-Dist: pandas>=2.2.0
30
+ Requires-Dist: pillow>=10.2.0
31
+ Requires-Dist: plotext>=5.2.8
32
+ Requires-Dist: plotly>=5.18.0
33
+ Requires-Dist: pydantic-settings>=2.1.0
34
+ Requires-Dist: pydantic>=2.6.0
35
+ Requires-Dist: pyobjc-framework-cocoa>=10.0; sys_platform == 'darwin'
36
+ Requires-Dist: python-dotenv>=1.0.0
37
+ Requires-Dist: requests>=2.31.0
38
+ Requires-Dist: rich>=13.7.0
39
+ Requires-Dist: scipy>=1.12.0
40
+ Requires-Dist: textual>=0.47.0
41
+ Requires-Dist: yfinance>=0.2.36
42
+ Provides-Extra: all
43
+ Requires-Dist: black>=24.0.0; extra == 'all'
44
+ Requires-Dist: lean>=1.0.0; extra == 'all'
45
+ Requires-Dist: mypy>=1.8.0; extra == 'all'
46
+ Requires-Dist: py2app>=0.28.0; extra == 'all'
47
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
48
+ Requires-Dist: pytest>=8.0.0; extra == 'all'
49
+ Requires-Dist: ruff>=0.2.0; extra == 'all'
50
+ Provides-Extra: dev
51
+ Requires-Dist: black>=24.0.0; extra == 'dev'
52
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
53
+ Requires-Dist: py2app>=0.28.0; extra == 'dev'
54
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
55
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
56
+ Requires-Dist: ruff>=0.2.0; extra == 'dev'
57
+ Provides-Extra: lean
58
+ Requires-Dist: lean>=1.0.0; extra == 'lean'
59
+ Description-Content-Type: text/markdown
60
+
61
+ <h1 align="center">
62
+ <code>σ</code> SIGMA
63
+ </h1>
64
+
65
+ <p align="center">
66
+ <strong>The AI-Powered Finance Research Agent</strong>
67
+ </p>
68
+
69
+ <p align="center">
70
+ <a href="#quick-start">Quick Start</a> •
71
+ <a href="#features">Features</a> •
72
+ <a href="#commands">Commands</a> •
73
+ <a href="#architecture">Architecture</a> •
74
+ <a href="#roadmap">Roadmap</a>
75
+ </p>
76
+
77
+ <p align="center">
78
+ <img src="https://img.shields.io/badge/version-3.4.0-blue.svg" alt="Version 3.4.0"/>
79
+ <img src="https://img.shields.io/badge/python-3.11+-green.svg" alt="Python 3.11+"/>
80
+ <img src="https://img.shields.io/badge/platform-cross--platform-lightgrey.svg" alt="Cross Platform"/>
81
+ <img src="https://img.shields.io/badge/AI-Multi--Provider-purple.svg" alt="Multi-Provider AI"/>
82
+ <img src="https://img.shields.io/badge/license-Proprietary-red.svg" alt="License"/>
83
+ </p>
84
+
85
+ ---
86
+
87
+ ## What is Sigma?
88
+
89
+ **Sigma isn't just another finance app.** It's a conversational AI agent that thinks like a quant, analyzes like a hedge fund, and speaks like your smartest friend who happens to be a CFA.
90
+
91
+ ## Quick Start
92
+
93
+ ### One Command Install
94
+
95
+ \`\`\`bash
96
+ pip install sigma-terminal
97
+ \`\`\`
98
+
99
+ ### Launch Sigma
100
+
101
+ \`\`\`bash
102
+ sigma
103
+ \`\`\`
104
+
105
+ Or alternatively: `python -m sigma`
106
+
107
+ ### First Launch = Automatic Setup
108
+
109
+ **That's it.** Sigma detects it's your first time and walks you through:
110
+
111
+ 1. **Choose AI Provider** — Google Gemini, OpenAI, Anthropic, Groq, xAI, or Ollama
112
+ 2. **Enter API Key** — Or use local Ollama (completely free, no key needed!)
113
+ 3. **Auto-detect Integrations** — Finds Ollama, LEAN, and more
114
+ 4. **Launch Directly** — Straight into the beautiful terminal UI
115
+
116
+ Your config persists at \`~/.sigma/\` — **setup never asks again**.
117
+
118
+ ---
119
+
120
+ ## Features
121
+
122
+ ### Multi-Provider AI Engine
123
+
124
+ Switch between providers on the fly. Use free tiers or bring your own keys.
125
+
126
+ | Provider | Models | Speed | Cost | Tool Calls |
127
+ | ----------------------- | ---------------------------- | --------- | -------------- | ---------- |
128
+ | **Google Gemini** | gemini-2.5-flash, 2.5-pro | Fast | Free tier | Native |
129
+ | **OpenAI** | gpt-4o, gpt-4o-mini, o3-mini | Fast | Paid | Native |
130
+ | **Anthropic** | claude-sonnet-4, 3.5-sonnet | Fast | Paid | Native |
131
+ | **Groq** | llama-3.3-70b | Very Fast | Free tier | Native |
132
+ | **xAI** | grok-2, grok-2-mini | Fast | Paid | Native |
133
+ | **Ollama** | llama3.2, mistral, phi3 | Local | **FREE** | Native |
134
+
135
+ **Built-in Rate Limiting** — No more API flooding or timeouts.
136
+
137
+ **Error Codes** — Clear error codes (E1100-E1400) help you quickly diagnose issues.
138
+
139
+ ### Real-Time Market Intelligence
140
+
141
+ | Tool | What It Does |
142
+ | ------------------------------- | --------------------------------------------- |
143
+ | \`get_stock_quote\` | Live price, change, volume, market cap |
144
+ | \`technical_analysis\` | RSI, MACD, Bollinger, MAs, Support/Resistance |
145
+ | \`get_financial_statements\` | Income, balance sheet, cash flow |
146
+ | \`get_analyst_recommendations\` | Price targets, ratings, consensus |
147
+ | \`get_insider_trades\` | Who's buying, who's selling |
148
+ | \`get_institutional_holders\` | Track the smart money |
149
+ | \`compare_stocks\` | Multi-stock comparison with metrics |
150
+ | \`get_market_overview\` | Major indices at a glance |
151
+ | \`get_sector_performance\` | Sector rotation analysis |
152
+
153
+ ### Data APIs
154
+
155
+ | Tool | Source | What It Does |
156
+ | --------------------------- | ------------- | ------------------------------------ |
157
+ | \`get_economic_indicators\` | Alpha Vantage | GDP, inflation, unemployment, CPI |
158
+ | \`get_intraday_data\` | Alpha Vantage | 1min to 60min candles |
159
+ | \`get_market_news\` | Alpha Vantage | News with sentiment analysis |
160
+ | \`polygon_get_quote\` | Polygon.io | Real-time quotes with extended data |
161
+ | \`polygon_get_aggregates\` | Polygon.io | Historical bars with custom timespan |
162
+ | \`polygon_get_ticker_news\` | Polygon.io | News articles for specific tickers |
163
+ | \`search_financial_news\` | Exa | Search Bloomberg, Reuters, WSJ |
164
+ | \`search_sec_filings\` | Exa | 10-K, 10-Q, 8-K filings |
165
+
166
+ ### Backtesting Engine
167
+
168
+ | Strategy | Description | Use Case |
169
+ | ----------------- | ----------------------- | ------------------ |
170
+ | \`sma_crossover\` | 20/50 MA crossover | Trend following |
171
+ | \`rsi\` | RSI oversold/overbought | Mean reversion |
172
+ | \`macd\` | MACD signal crossovers | Momentum |
173
+ | \`bollinger\` | Band breakout/bounce | Volatility |
174
+ | \`momentum\` | Price momentum | Trend continuation |
175
+ | \`breakout\` | S/R level breaks | Breakout trading |
176
+
177
+ ---
178
+
179
+ ## Commands
180
+
181
+ ### In-App Commands
182
+
183
+ | Command | Description |
184
+ | --------------------------- | -------------------------------- |
185
+ | \`/help\` | Comprehensive help with examples |
186
+ | \`/clear\` | Clear chat history |
187
+ | \`/keys\` | Configure API keys (improved!) |
188
+ | \`/models\` | Show available models |
189
+ | \`/status\` | Current configuration |
190
+ | \`/provider `<name>`\` | Switch AI provider |
191
+ | \`/model `<name>`\` | Switch model |
192
+ | \`/setkey `<p>` `<k>`\` | Set API key for provider |
193
+ | \`/backtest\` | Show backtesting strategies |
194
+
195
+ ### Keyboard Shortcuts
196
+
197
+ | Shortcut | Action |
198
+ | ---------- | ----------------------- |
199
+ | \`Tab\` | Autocomplete suggestion |
200
+ | \`Ctrl+L\` | Clear chat |
201
+ | \`Ctrl+M\` | Show models |
202
+ | \`Ctrl+H\` | Toggle quick help |
203
+ | \`Esc\` | Cancel operation |
204
+
205
+ ---
206
+
207
+ ## Configuration
208
+
209
+ ### Config Location
210
+
211
+ \`\`\`
212
+ ~/.sigma/
213
+ |-- config.env # API keys and settings
214
+ └── .first_run_complete # First-run marker
215
+ \`\`\`
216
+
217
+ ### Error Codes
218
+
219
+ | Code Range | Category | Example |
220
+ | ---------- | -------- | ----------------------- |
221
+ | E1000-1099 | General | E1002: Timeout |
222
+ | E1100-1199 | API Keys | E1101: Invalid API key |
223
+ | E1200-1299 | Provider | E1202: Model not found |
224
+ | E1300-1399 | Data | E1300: Symbol not found |
225
+ | E1400-1499 | Network | E1400: Connection error |
226
+
227
+ ---
228
+
229
+ ## Changelog
230
+
231
+ ### v3.4.0 (Current)
232
+
233
+ - [X] **Improved API Key Management** — Beautiful \`/keys\` interface with URLs
234
+ - [X] **Polygon.io Integration** — Real-time quotes, aggregates, news
235
+ - [X] **xAI Grok Support** — Full support for Grok-2 and Grok-2-mini
236
+ - [X] **Error Codes** — Structured error codes (E1000-E1499)
237
+ - [X] **Updated Models** — Removed deprecated, added latest versions
238
+ - [X] **Enhanced AI** — Maximum helpfulness with proactive insights
239
+ - [X] **Modern UI** — Gradient blues, improved styling
240
+ - [X] **Cross-Platform** — Works on macOS, Linux, Windows
241
+
242
+ ### v3.3.x
243
+
244
+ - [X] Auto-setup on first launch
245
+ - [X] LEAN auto-detection
246
+ - [X] API rate limiting
247
+ - [X] Ollama native tool calls
248
+ - [X] Alpha Vantage & Exa integration
249
+
250
+ ---
251
+
252
+ ## Acknowledgments
253
+
254
+ Built with [Textual](https://textual.textualize.io/), [Rich](https://rich.readthedocs.io/), [yfinance](https://github.com/ranaroussi/yfinance), [Plotly](https://plotly.com/python/), LEAN
255
+
256
+ AI: [Google Gemini](https://ai.google.dev/) • [OpenAI](https://openai.com/) • [Anthropic](https://anthropic.com/) • [Groq](https://groq.com/) • [xAI](https://x.ai/) • [Ollama](https://ollama.ai/)
257
+
258
+ Data: [Polygon.io](https://polygon.io/) • [Alpha Vantage](https://www.alphavantage.co/) • [Exa](https://exa.ai/)
259
+
260
+ ---
261
+
262
+ <p align="center">
263
+ <code>σ</code> — Finance Research AI Agent
264
+ </p>