yuclaw 1.0.0__tar.gz

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 (77) hide show
  1. yuclaw-1.0.0/PKG-INFO +74 -0
  2. yuclaw-1.0.0/README.md +137 -0
  3. yuclaw-1.0.0/README_PACKAGE.md +48 -0
  4. yuclaw-1.0.0/pyproject.toml +33 -0
  5. yuclaw-1.0.0/setup.cfg +4 -0
  6. yuclaw-1.0.0/setup.py +35 -0
  7. yuclaw-1.0.0/yuclaw/__init__.py +0 -0
  8. yuclaw-1.0.0/yuclaw/agents/__init__.py +0 -0
  9. yuclaw-1.0.0/yuclaw/agents/agents.py +247 -0
  10. yuclaw-1.0.0/yuclaw/api/__init__.py +0 -0
  11. yuclaw-1.0.0/yuclaw/api/server.py +108 -0
  12. yuclaw-1.0.0/yuclaw/audit/__init__.py +0 -0
  13. yuclaw-1.0.0/yuclaw/audit/vault.py +81 -0
  14. yuclaw-1.0.0/yuclaw/brain/__init__.py +0 -0
  15. yuclaw-1.0.0/yuclaw/brain/evidence_graph_live.py +116 -0
  16. yuclaw-1.0.0/yuclaw/brain/financial_ner_live.py +59 -0
  17. yuclaw-1.0.0/yuclaw/cli.py +156 -0
  18. yuclaw-1.0.0/yuclaw/core/__init__.py +0 -0
  19. yuclaw-1.0.0/yuclaw/core/ontology/__init__.py +0 -0
  20. yuclaw-1.0.0/yuclaw/core/ontology/financial_ner.py +50 -0
  21. yuclaw-1.0.0/yuclaw/core/ontology/models.py +123 -0
  22. yuclaw-1.0.0/yuclaw/core/router.py +86 -0
  23. yuclaw-1.0.0/yuclaw/core/security/__init__.py +0 -0
  24. yuclaw-1.0.0/yuclaw/core/security/injection_shield.py +38 -0
  25. yuclaw-1.0.0/yuclaw/data/__init__.py +0 -0
  26. yuclaw-1.0.0/yuclaw/data/connectors.py +85 -0
  27. yuclaw-1.0.0/yuclaw/data/earnings_calendar.py +39 -0
  28. yuclaw-1.0.0/yuclaw/data/edgar_downloader.py +187 -0
  29. yuclaw-1.0.0/yuclaw/data/universe_200.py +52 -0
  30. yuclaw-1.0.0/yuclaw/edge/__init__.py +0 -0
  31. yuclaw-1.0.0/yuclaw/edge/fix/__init__.py +0 -0
  32. yuclaw-1.0.0/yuclaw/edge/fix/fix_gateway_real.py +121 -0
  33. yuclaw-1.0.0/yuclaw/engine.py +305 -0
  34. yuclaw-1.0.0/yuclaw/factors/__init__.py +1 -0
  35. yuclaw-1.0.0/yuclaw/factors/advanced_factors.py +99 -0
  36. yuclaw-1.0.0/yuclaw/factors/factor_library.py +109 -0
  37. yuclaw-1.0.0/yuclaw/memory/__init__.py +0 -0
  38. yuclaw-1.0.0/yuclaw/memory/daily_synthesis.py +70 -0
  39. yuclaw-1.0.0/yuclaw/memory/evidence_graph.py +93 -0
  40. yuclaw-1.0.0/yuclaw/memory/portfolio_memory.py +94 -0
  41. yuclaw-1.0.0/yuclaw/memory/portfolio_memory_live.py +94 -0
  42. yuclaw-1.0.0/yuclaw/memory/portfolio_memory_v2.py +77 -0
  43. yuclaw-1.0.0/yuclaw/memory/thesis_drift.py +136 -0
  44. yuclaw-1.0.0/yuclaw/memory/thesis_tracker.py +133 -0
  45. yuclaw-1.0.0/yuclaw/memory/track_record.py +125 -0
  46. yuclaw-1.0.0/yuclaw/memory/track_record_v2.py +68 -0
  47. yuclaw-1.0.0/yuclaw/modules/__init__.py +0 -0
  48. yuclaw-1.0.0/yuclaw/modules/competitive_intel.py +93 -0
  49. yuclaw-1.0.0/yuclaw/modules/earnings_war_room.py +194 -0
  50. yuclaw-1.0.0/yuclaw/modules/execution_simulator.py +269 -0
  51. yuclaw-1.0.0/yuclaw/modules/factor_lab.py +190 -0
  52. yuclaw-1.0.0/yuclaw/modules/macro_regime.py +52 -0
  53. yuclaw-1.0.0/yuclaw/modules/portfolio_optimizer.py +190 -0
  54. yuclaw-1.0.0/yuclaw/modules/portfolio_sentinel.py +129 -0
  55. yuclaw-1.0.0/yuclaw/modules/scenario_shock.py +121 -0
  56. yuclaw-1.0.0/yuclaw/modules/sector_rotation.py +53 -0
  57. yuclaw-1.0.0/yuclaw/modules/signal_aggregator.py +171 -0
  58. yuclaw-1.0.0/yuclaw/output/__init__.py +0 -0
  59. yuclaw-1.0.0/yuclaw/output/excel.py +174 -0
  60. yuclaw-1.0.0/yuclaw/plugins/__init__.py +27 -0
  61. yuclaw-1.0.0/yuclaw/plugins/builtin.py +38 -0
  62. yuclaw-1.0.0/yuclaw/risk/__init__.py +1 -0
  63. yuclaw-1.0.0/yuclaw/risk/risk_engine.py +115 -0
  64. yuclaw-1.0.0/yuclaw/trust/__init__.py +0 -0
  65. yuclaw-1.0.0/yuclaw/trust/zkp_onchain.py +100 -0
  66. yuclaw-1.0.0/yuclaw/trust/zkp_vault.py +37 -0
  67. yuclaw-1.0.0/yuclaw/universe.py +18 -0
  68. yuclaw-1.0.0/yuclaw/validation/__init__.py +0 -0
  69. yuclaw-1.0.0/yuclaw/validation/engine.py +298 -0
  70. yuclaw-1.0.0/yuclaw/validation/model_trust_engine.py +62 -0
  71. yuclaw-1.0.0/yuclaw/validation/real_backtest.py +203 -0
  72. yuclaw-1.0.0/yuclaw.egg-info/PKG-INFO +74 -0
  73. yuclaw-1.0.0/yuclaw.egg-info/SOURCES.txt +75 -0
  74. yuclaw-1.0.0/yuclaw.egg-info/dependency_links.txt +1 -0
  75. yuclaw-1.0.0/yuclaw.egg-info/entry_points.txt +2 -0
  76. yuclaw-1.0.0/yuclaw.egg-info/requires.txt +7 -0
  77. yuclaw-1.0.0/yuclaw.egg-info/top_level.txt +1 -0
yuclaw-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.4
2
+ Name: yuclaw
3
+ Version: 1.0.0
4
+ Summary: YUCLAW — Open Financial Intelligence Platform
5
+ Home-page: https://github.com/YuClawLab/yuclaw-brain
6
+ Author: YuClawLab
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/YuClawLab
9
+ Project-URL: Dashboard, https://yuclawlab.github.io/yuclaw-brain
10
+ Keywords: finance,trading,quant,zkp,backtesting,ai
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: yfinance>=0.2.0
17
+ Requires-Dist: pandas>=2.0.0
18
+ Requires-Dist: numpy>=1.24.0
19
+ Requires-Dist: requests>=2.28.0
20
+ Requires-Dist: fastapi>=0.100.0
21
+ Requires-Dist: uvicorn>=0.20.0
22
+ Requires-Dist: rich>=13.0.0
23
+ Dynamic: author
24
+ Dynamic: home-page
25
+ Dynamic: requires-python
26
+
27
+ # YUCLAW — Open Financial Intelligence Platform
28
+
29
+ The open-source financial intelligence OS. Real backtests. ZKP audit. Local AI.
30
+
31
+ ## Install in one command
32
+ ```bash
33
+ pip install yuclaw
34
+ yuclaw start
35
+ ```
36
+
37
+ ## What YUCLAW gives you
38
+
39
+ - **Real signals** — factor-scored buy/sell for 167+ tickers
40
+ - **Real backtests** — Calmar 3.055 from 15 years of actual prices
41
+ - **ZKP audit trail** — every decision on Ethereum blockchain
42
+ - **Local AI** — Nemotron 120B, zero cloud dependency
43
+ - **Market regime** — CRISIS/RISK_OFF/RISK_ON detection
44
+ - **30-day track record** — verifiable signal performance
45
+
46
+ ## Quick start
47
+ ```bash
48
+ pip install yuclaw
49
+ yuclaw start # Start all engines
50
+ yuclaw signals # Show current signals
51
+ yuclaw regime # Show market regime
52
+ yuclaw brief # Show institutional brief
53
+ yuclaw track # Show track record
54
+ yuclaw dashboard # Open live dashboard
55
+ ```
56
+
57
+ ## How it works
58
+ ```
59
+ Market Data -> Factor Library -> Signal Aggregator
60
+ | | |
61
+ SEC XBRL Macro Regime Risk Engine
62
+ | | |
63
+ Evidence Graph -> Nemotron 120B -> ZKP Proof
64
+ |
65
+ Institutional Brief -> Dashboard -> Track Record
66
+ ```
67
+
68
+ ## Community
69
+
70
+ - GitHub: https://github.com/YuClawLab
71
+ - Dashboard: https://yuclawlab.github.io/yuclaw-brain
72
+ - Paper: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6461418
73
+
74
+ MIT License — free for everyone.
yuclaw-1.0.0/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # YUCLAW — Open Financial Intelligence Platform
2
+
3
+ [![Stars](https://img.shields.io/github/stars/YuClawLab/yuclaw-brain?style=flat&color=ffd700)](https://github.com/YuClawLab/yuclaw-brain)
4
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
5
+ [![Python](https://img.shields.io/badge/python-3.10+-blue)](https://python.org)
6
+ [![Model](https://img.shields.io/badge/model-Nemotron%20120B-brightgreen)](https://nvidia.com)
7
+ [![Hardware](https://img.shields.io/badge/hardware-DGX%20Spark%20GB10-76b900)](https://nvidia.com)
8
+ [![ZKP](https://img.shields.io/badge/ZKP-Ethereum%20Sepolia-purple)](https://sepolia.etherscan.io)
9
+ [![SSRN](https://img.shields.io/badge/paper-SSRN%206461418-red)](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6461418)
10
+
11
+ > The open-source financial intelligence OS. Real backtests. ZKP audit trail. Local 120B AI. Like OpenClaw but built for finance.
12
+
13
+ ## Install in one command
14
+ ```bash
15
+ pip install yuclaw
16
+ yuclaw start
17
+ ```
18
+
19
+ ## Quick commands
20
+ ```bash
21
+ yuclaw signals # Show current buy/sell signals
22
+ yuclaw regime # Show market regime (CRISIS/RISK_OFF/RISK_ON)
23
+ yuclaw brief # Nemotron 120B institutional brief
24
+ yuclaw track # 30-day verifiable track record
25
+ yuclaw zkp # ZKP cryptographic proofs on-chain
26
+ yuclaw dashboard # Open live dashboard
27
+ ```
28
+
29
+ ## Live Dashboard
30
+
31
+ **[yuclawlab.github.io/yuclaw-brain](https://yuclawlab.github.io/yuclaw-brain)**
32
+
33
+ Updates every 30 minutes. Real signals. Real risk. Real model.
34
+
35
+ ## Why YUCLAW
36
+
37
+ | Feature | OpenClaw | Claude | YUCLAW |
38
+ |---|---|---|---|
39
+ | Real backtests | No | No | Calmar 3.055 |
40
+ | ZKP audit trail | No | No | On-chain |
41
+ | Real VaR/Kelly | No | No | Historical sim |
42
+ | Local 120B model | No | No | Nemotron DGX |
43
+ | Verified track record | No | No | 30-day building |
44
+ | Adversarial Red Team | No | No | Kills bad strategies |
45
+ | Academic paper | No | No | SSRN #6461418 |
46
+
47
+ ## Track Record (Day 3 of 30)
48
+
49
+ | Signal | Result | Change | ZKP Block |
50
+ |---|---|---|---|
51
+ | LUNR STRONG_BUY | CORRECT | +14.68% | 10515603 |
52
+ | ASTS STRONG_BUY | CORRECT | +10.44% | 10515603 |
53
+ | MRVL STRONG_BUY | CORRECT | +6.59% | 10515603 |
54
+ | DELL STRONG_BUY | CORRECT | +4.01% | 10515603 |
55
+
56
+ **Day 3 accuracy: 60% — every signal on Ethereum blockchain**
57
+
58
+ ## How it works
59
+
60
+ ```
61
+ Market Data (167+ tickers)
62
+ |
63
+ Factor Library (RSI, MACD, Bollinger, Momentum)
64
+ |
65
+ Signal Aggregator -> Adversarial Red Team
66
+ |
67
+ Nemotron 3 Super 120B (local, 18.9 tok/s)
68
+ |
69
+ ZKP Proof -> Ethereum Sepolia Blockchain
70
+ |
71
+ Institutional Brief -> Dashboard -> Track Record
72
+ ```
73
+
74
+ ## What runs 24/7 on DGX Spark GB10
75
+
76
+ - **Signal loop** — 167 tickers every 30 min
77
+ - **Factor engine** — RSI/MACD/Bollinger every 30 min
78
+ - **Risk engine** — VaR/CVaR/Kelly every 1 hr
79
+ - **Macro regime** — CRISIS detection every 1 hr
80
+ - **Nemotron brief** — Institutional analysis every 15 min
81
+ - **ZKP vault** — Cryptographic proofs every 1 hr
82
+ - **FIX gateway** — Paper trading every 30 min
83
+ - **Track record** — Verified performance every 1 hr
84
+
85
+ ## Architecture
86
+
87
+ ```
88
+ yuclaw/
89
+ modules/ Signal aggregator, macro regime
90
+ factors/ Factor library (RSI, MACD, Bollinger)
91
+ risk/ VaR, CVaR, Kelly criterion
92
+ finclaw/ Institutional brief, competitive intel
93
+ trust/ ZKP vault, on-chain proofs
94
+ edge/ FIX gateway, execution levels 0-4
95
+ memory/ Portfolio memory, track record
96
+ brain/ Evidence graph, financial NER
97
+ plugins/ Plugin system (like ClawHub)
98
+ api/ REST API for OpenClaw integration
99
+ ```
100
+
101
+ ## Plugin System
102
+ ```python
103
+ from yuclaw.plugins import register
104
+
105
+ @register('my_strategy', 'My custom strategy', 'quant')
106
+ class MyStrategy:
107
+ def run(self):
108
+ # Your financial intelligence here
109
+ pass
110
+ ```
111
+
112
+ ## Academic Paper
113
+
114
+ **CRT Lock-Free Concurrent Scheduler for Financial Systems**
115
+ SSRN Abstract #6461418 | DGX Spark GB10 | 1.37ms latency
116
+
117
+ [Read on SSRN](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6461418)
118
+
119
+ ## Community
120
+
121
+ - Dashboard: [yuclawlab.github.io/yuclaw-brain](https://yuclawlab.github.io/yuclaw-brain)
122
+ - Twitter: [@Vincenzhang2026](https://twitter.com/Vincenzhang2026)
123
+ - Paper: [SSRN #6461418](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6461418)
124
+ - GitHub: [YuClawLab](https://github.com/YuClawLab)
125
+
126
+ ## Contributing
127
+
128
+ YUCLAW improves every day — like OpenClaw but for finance.
129
+ PRs welcome. Build plugins. Add data sources. Improve factors.
130
+
131
+ ## License
132
+
133
+ MIT — free for everyone.
134
+
135
+ ---
136
+
137
+ *Built on NVIDIA DGX Spark GB10 | Nemotron 3 Super 120B | Zero cloud dependency*
@@ -0,0 +1,48 @@
1
+ # YUCLAW — Open Financial Intelligence Platform
2
+
3
+ The open-source financial intelligence OS. Real backtests. ZKP audit. Local AI.
4
+
5
+ ## Install in one command
6
+ ```bash
7
+ pip install yuclaw
8
+ yuclaw start
9
+ ```
10
+
11
+ ## What YUCLAW gives you
12
+
13
+ - **Real signals** — factor-scored buy/sell for 167+ tickers
14
+ - **Real backtests** — Calmar 3.055 from 15 years of actual prices
15
+ - **ZKP audit trail** — every decision on Ethereum blockchain
16
+ - **Local AI** — Nemotron 120B, zero cloud dependency
17
+ - **Market regime** — CRISIS/RISK_OFF/RISK_ON detection
18
+ - **30-day track record** — verifiable signal performance
19
+
20
+ ## Quick start
21
+ ```bash
22
+ pip install yuclaw
23
+ yuclaw start # Start all engines
24
+ yuclaw signals # Show current signals
25
+ yuclaw regime # Show market regime
26
+ yuclaw brief # Show institutional brief
27
+ yuclaw track # Show track record
28
+ yuclaw dashboard # Open live dashboard
29
+ ```
30
+
31
+ ## How it works
32
+ ```
33
+ Market Data -> Factor Library -> Signal Aggregator
34
+ | | |
35
+ SEC XBRL Macro Regime Risk Engine
36
+ | | |
37
+ Evidence Graph -> Nemotron 120B -> ZKP Proof
38
+ |
39
+ Institutional Brief -> Dashboard -> Track Record
40
+ ```
41
+
42
+ ## Community
43
+
44
+ - GitHub: https://github.com/YuClawLab
45
+ - Dashboard: https://yuclawlab.github.io/yuclaw-brain
46
+ - Paper: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6461418
47
+
48
+ MIT License — free for everyone.
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "yuclaw"
7
+ version = "1.0.0"
8
+ description = "YUCLAW — Open Financial Intelligence Platform"
9
+ readme = "README_PACKAGE.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ keywords = ["finance", "trading", "quant", "zkp", "backtesting", "ai"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Financial and Insurance Industry",
16
+ "License :: OSI Approved :: MIT License",
17
+ ]
18
+ dependencies = [
19
+ "yfinance>=0.2.0",
20
+ "pandas>=2.0.0",
21
+ "numpy>=1.24.0",
22
+ "requests>=2.28.0",
23
+ "fastapi>=0.100.0",
24
+ "uvicorn>=0.20.0",
25
+ "rich>=13.0.0",
26
+ ]
27
+
28
+ [project.scripts]
29
+ yuclaw = "yuclaw.cli:main"
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/YuClawLab"
33
+ Dashboard = "https://yuclawlab.github.io/yuclaw-brain"
yuclaw-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
yuclaw-1.0.0/setup.py ADDED
@@ -0,0 +1,35 @@
1
+ from setuptools import setup, find_packages
2
+ import os
3
+
4
+ setup(
5
+ name='yuclaw',
6
+ version='1.0.0',
7
+ description='YUCLAW — Open Financial Intelligence Platform. Real backtests. ZKP audit. Local AI.',
8
+ long_description=open('README_PACKAGE.md').read() if os.path.exists('README_PACKAGE.md') else '',
9
+ long_description_content_type='text/markdown',
10
+ author='YuClawLab',
11
+ url='https://github.com/YuClawLab/yuclaw-brain',
12
+ packages=find_packages(),
13
+ install_requires=[
14
+ 'yfinance>=0.2.0',
15
+ 'pandas>=2.0.0',
16
+ 'numpy>=1.24.0',
17
+ 'requests>=2.28.0',
18
+ 'fastapi>=0.100.0',
19
+ 'uvicorn>=0.20.0',
20
+ 'rich>=13.0.0',
21
+ ],
22
+ entry_points={
23
+ 'console_scripts': [
24
+ 'yuclaw=yuclaw.cli:main',
25
+ ],
26
+ },
27
+ classifiers=[
28
+ 'Development Status :: 4 - Beta',
29
+ 'Intended Audience :: Financial and Insurance Industry',
30
+ 'Topic :: Office/Business :: Financial :: Investment',
31
+ 'License :: OSI Approved :: MIT License',
32
+ 'Programming Language :: Python :: 3.10',
33
+ ],
34
+ python_requires='>=3.10',
35
+ )
File without changes
File without changes
@@ -0,0 +1,247 @@
1
+ """yuclaw/agents/agents.py — All YUCLAW agents."""
2
+ from __future__ import annotations
3
+ import json
4
+ from datetime import datetime, timezone
5
+ from dataclasses import dataclass, field
6
+ from ..core.router import get_router
7
+ from ..core.ontology.models import EvidenceNode, ValidationStatus
8
+ from ..memory.evidence_graph import EvidenceGraph
9
+ from ..memory.portfolio_memory import PortfolioMemory
10
+
11
+
12
+ # ─────────────────────────────────────────────────────────
13
+ # CIO AGENT
14
+ # ─────────────────────────────────────────────────────────
15
+
16
+ CIO_SYSTEM = """You are the CIO Agent of YUCLAW financial intelligence system.
17
+ Decompose the research request into ordered tasks for specialist agents.
18
+ Output JSON array only. Each task: {"task_id":str, "agent":str, "instruction":str, "priority":"high|medium|low"}
19
+ agent options: research | macro | quant | risk | compliance
20
+ No preamble. JSON only."""
21
+
22
+
23
+ @dataclass
24
+ class Task:
25
+ task_id: str
26
+ agent: str
27
+ instruction: str
28
+ priority: str = "medium"
29
+ result: str | None = None
30
+
31
+
32
+ @dataclass
33
+ class WorkPlan:
34
+ request: str
35
+ tasks: list[Task]
36
+ capital_limit_usd: float = 0.0 # Always 0 until Execution Agent activated
37
+
38
+
39
+ class CIOAgent:
40
+ def __init__(self):
41
+ self._router = get_router()
42
+
43
+ async def decompose(self, request: str) -> WorkPlan:
44
+ response = await self._router.complete(
45
+ prompt=f"Research request: {request}",
46
+ system=CIO_SYSTEM,
47
+ fast=True
48
+ )
49
+ try:
50
+ tasks = [Task(**t) for t in json.loads(response)]
51
+ except Exception:
52
+ tasks = [Task(task_id="t1", agent="research",
53
+ instruction=request, priority="high")]
54
+ return WorkPlan(request=request, tasks=tasks, capital_limit_usd=0.0)
55
+
56
+
57
+ # ─────────────────────────────────────────────────────────
58
+ # RESEARCH AGENT
59
+ # ─────────────────────────────────────────────────────────
60
+
61
+ RESEARCH_SYSTEM = """You are the YUCLAW Research Agent. Analyze financial documents.
62
+ CRITICAL: Every factual claim MUST include a citation: [DOC:<id>|PAGE:<n>]
63
+ Output JSON only:
64
+ {
65
+ "summary": "comprehensive investment analysis",
66
+ "key_metrics": [{"name":str, "value":str, "page":int, "significance":str}],
67
+ "thesis": {"bull":str, "base":str, "bear":str},
68
+ "key_assumptions": [str],
69
+ "catalysts": [str],
70
+ "risks": [str],
71
+ "claims": [{"claim":str, "page":int, "confidence":float, "ontology_tags":[str]}]
72
+ }
73
+ JSON only. No preamble."""
74
+
75
+
76
+ class ResearchAgent:
77
+ def __init__(self, evidence_graph: EvidenceGraph, portfolio_memory: PortfolioMemory):
78
+ self._router = get_router()
79
+ self._graph = evidence_graph
80
+ self._memory = portfolio_memory
81
+ # Wire in real PDF parser for grounding with actual financial data
82
+ try:
83
+ from ..data.parsers.real_pdf_parser import RealPDFParser
84
+ self._real_parser = RealPDFParser()
85
+ except ImportError:
86
+ self._real_parser = None
87
+
88
+ async def analyze(self, doc_text: str, doc_id: str, ticker: str, query: str) -> dict:
89
+ # Pull prior thesis from memory
90
+ history = await self._memory.get_history(ticker)
91
+ history_context = ""
92
+ if history:
93
+ history_context = (
94
+ f"\n\nPRIOR THESIS HISTORY FOR {ticker} ({len(history)} records):\n"
95
+ + "\n".join(f"- [{h.created_at[:10]}] {h.thesis[:120]}" for h in history[:3])
96
+ + "\n\nCompare current analysis against prior thesis.\n"
97
+ )
98
+
99
+ # Ground with REAL financial data from yfinance
100
+ grounding_context = ""
101
+ if self._real_parser:
102
+ try:
103
+ parsed = self._real_parser.parse_yfinance(ticker)
104
+ if parsed.facts:
105
+ grounding_context = "\n\n" + parsed.to_grounding_context() + "\n"
106
+ except Exception:
107
+ pass
108
+
109
+ prompt = (
110
+ f"DOCUMENT ID: {doc_id}\nTICKER: {ticker}\n"
111
+ f"{grounding_context}"
112
+ f"{history_context}"
113
+ f"\nDOCUMENT TEXT:\n{doc_text[:50000]}\n\n"
114
+ f"QUERY: {query}"
115
+ )
116
+
117
+ response = await self._router.complete(
118
+ prompt=prompt, system=RESEARCH_SYSTEM, max_tokens=8192
119
+ )
120
+
121
+ try:
122
+ result = json.loads(response)
123
+ except Exception:
124
+ result = {"summary": response, "claims": [], "key_metrics": [],
125
+ "thesis": {}, "key_assumptions": [], "catalysts": [], "risks": []}
126
+
127
+ # Build Evidence Graph nodes
128
+ now = datetime.now(timezone.utc).isoformat()
129
+ node_ids = []
130
+ for i, c in enumerate(result.get("claims", [])):
131
+ if not c.get("claim"):
132
+ continue
133
+ node = EvidenceNode(
134
+ claim=c["claim"],
135
+ source_doc_id=doc_id,
136
+ page_number=max(int(c.get("page") or 1), 1),
137
+ paragraph_hash=f"{doc_id}_claim_{i}",
138
+ extraction_timestamp=now,
139
+ model_version="nemotron-3-super",
140
+ confidence=float(c.get("confidence") or 0.8),
141
+ ontology_tags=c.get("ontology_tags", [])
142
+ )
143
+ nid = await self._graph.add_node(node)
144
+ node_ids.append(nid)
145
+
146
+ result["evidence_node_ids"] = node_ids
147
+ result["ticker"] = ticker
148
+ result["doc_id"] = doc_id
149
+ result["status"] = ValidationStatus.EVIDENCE_EXTRACTED.value
150
+ result["prior_thesis_count"] = len(history)
151
+
152
+ # Thesis Tracker: compare against history
153
+ try:
154
+ from ..memory.thesis_tracker import ThesisTracker
155
+ tracker = ThesisTracker(self._memory)
156
+ current_thesis = result.get("thesis", {}).get("base", result.get("summary", ""))
157
+ current_assumptions = result.get("key_assumptions", [])
158
+ comparison = await tracker.compare_against_history(ticker, current_thesis, current_assumptions)
159
+ result["thesis_change"] = {
160
+ "prior_count": comparison.prior_count,
161
+ "drift_detected": comparison.drift_detected,
162
+ "drift_description": comparison.drift_description,
163
+ "conviction_trend": comparison.conviction_trend,
164
+ "assumptions_changed": comparison.assumptions_changed,
165
+ "status": "FALSIFIED" if comparison.drift_detected and comparison.conviction_trend == "decreasing"
166
+ else "WEAKENED" if comparison.conviction_trend == "decreasing"
167
+ else "STRENGTHENED" if comparison.conviction_trend == "increasing"
168
+ else "NEW" if comparison.prior_count == 0
169
+ else "UNCHANGED",
170
+ }
171
+ except Exception:
172
+ result["thesis_change"] = {"status": "NEW", "prior_count": 0}
173
+
174
+ return result
175
+
176
+
177
+ # ─────────────────────────────────────────────────────────
178
+ # MACRO AGENT
179
+ # ─────────────────────────────────────────────────────────
180
+
181
+ MACRO_SYSTEM = """You are the YUCLAW Macro Agent. Analyze macro events and their market impact.
182
+ Output JSON only:
183
+ {
184
+ "event": str,
185
+ "severity": "low|medium|high|critical",
186
+ "first_order_impacts": [
187
+ {"asset_class":str, "direction":"positive|negative|neutral", "magnitude":"small|medium|large", "reasoning":str}
188
+ ],
189
+ "second_order_impacts": [{"asset_class":str, "mechanism":str}],
190
+ "sectors": {"beneficiaries":[str], "casualties":[str]},
191
+ "portfolio_actions": [str],
192
+ "time_horizon": {"days_1_5":str, "weeks_1_4":str, "months_1_3":str}
193
+ }
194
+ JSON only. No preamble."""
195
+
196
+
197
+ class MacroAgent:
198
+ def __init__(self):
199
+ self._router = get_router()
200
+
201
+ async def analyze_event(self, event: str) -> dict:
202
+ response = await self._router.complete(
203
+ prompt=f"Macro event to analyze: {event}",
204
+ system=MACRO_SYSTEM,
205
+ max_tokens=4096
206
+ )
207
+ try:
208
+ return json.loads(response)
209
+ except Exception:
210
+ return {"event": event, "raw_analysis": response, "error": "parse_failed"}
211
+
212
+
213
+ # ─────────────────────────────────────────────────────────
214
+ # QUANT AGENT
215
+ # ─────────────────────────────────────────────────────────
216
+
217
+ QUANT_SYSTEM = """You are the YUCLAW Quant Agent. Generate quantitative strategy specifications.
218
+ Output JSON only:
219
+ {
220
+ "strategy_name": str,
221
+ "strategy_description": str,
222
+ "universe": str,
223
+ "signal_logic": str,
224
+ "holding_period": str,
225
+ "rebalance_frequency": str,
226
+ "risk_controls": [str],
227
+ "expected_calmar_ratio": float,
228
+ "python_pseudocode": str,
229
+ "known_failure_conditions": [str]
230
+ }
231
+ JSON only. No preamble."""
232
+
233
+
234
+ class QuantAgent:
235
+ def __init__(self):
236
+ self._router = get_router()
237
+
238
+ async def generate_strategy(self, instruction: str) -> dict:
239
+ response = await self._router.complete(
240
+ prompt=f"Generate a quantitative strategy for: {instruction}",
241
+ system=QUANT_SYSTEM,
242
+ max_tokens=4096
243
+ )
244
+ try:
245
+ return json.loads(response)
246
+ except Exception:
247
+ return {"strategy_description": response, "error": "parse_failed"}
File without changes