sigma-terminal 3.3.1__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/__init__.py +5 -5
- sigma/app.py +442 -112
- sigma/charts.py +33 -8
- sigma/cli.py +11 -11
- sigma/config.py +172 -34
- sigma/llm.py +153 -6
- sigma/setup.py +15 -15
- sigma/tools.py +277 -3
- sigma_terminal-3.4.0.dist-info/METADATA +264 -0
- {sigma_terminal-3.3.1.dist-info → sigma_terminal-3.4.0.dist-info}/RECORD +13 -13
- sigma_terminal-3.3.1.dist-info/METADATA +0 -444
- {sigma_terminal-3.3.1.dist-info → sigma_terminal-3.4.0.dist-info}/WHEEL +0 -0
- {sigma_terminal-3.3.1.dist-info → sigma_terminal-3.4.0.dist-info}/entry_points.txt +0 -0
- {sigma_terminal-3.3.1.dist-info → sigma_terminal-3.4.0.dist-info}/licenses/LICENSE +0 -0
sigma/setup.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Sigma v3.
|
|
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.
|
|
28
|
+
__version__ = "3.4.0"
|
|
29
29
|
SIGMA = "σ"
|
|
30
30
|
console = Console()
|
|
31
31
|
|
|
32
|
-
# Clean banner - just SIGMA
|
|
32
|
+
# Clean banner - just SIGMA
|
|
33
33
|
BANNER = """
|
|
34
|
-
[bold
|
|
35
|
-
[bold
|
|
36
|
-
[bold
|
|
37
|
-
[bold
|
|
38
|
-
[bold
|
|
39
|
-
[bold
|
|
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.
|
|
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]
|
|
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]
|
|
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]
|
|
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]
|
|
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":
|
|
@@ -403,7 +403,7 @@ def quick_setup():
|
|
|
403
403
|
choice = Prompt.ask("Provider", choices=["1", "2", "3"], default="1")
|
|
404
404
|
|
|
405
405
|
providers = {
|
|
406
|
-
"1": ("google", "gemini-
|
|
406
|
+
"1": ("google", "gemini-3-flash-preview"),
|
|
407
407
|
"2": ("groq", "llama-3.3-70b-versatile"),
|
|
408
408
|
"3": ("ollama", "llama3.2"),
|
|
409
409
|
}
|
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
|
-
|
|
1043
|
-
|
|
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>
|