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.
- yuclaw-1.0.0/PKG-INFO +74 -0
- yuclaw-1.0.0/README.md +137 -0
- yuclaw-1.0.0/README_PACKAGE.md +48 -0
- yuclaw-1.0.0/pyproject.toml +33 -0
- yuclaw-1.0.0/setup.cfg +4 -0
- yuclaw-1.0.0/setup.py +35 -0
- yuclaw-1.0.0/yuclaw/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/agents/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/agents/agents.py +247 -0
- yuclaw-1.0.0/yuclaw/api/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/api/server.py +108 -0
- yuclaw-1.0.0/yuclaw/audit/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/audit/vault.py +81 -0
- yuclaw-1.0.0/yuclaw/brain/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/brain/evidence_graph_live.py +116 -0
- yuclaw-1.0.0/yuclaw/brain/financial_ner_live.py +59 -0
- yuclaw-1.0.0/yuclaw/cli.py +156 -0
- yuclaw-1.0.0/yuclaw/core/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/core/ontology/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/core/ontology/financial_ner.py +50 -0
- yuclaw-1.0.0/yuclaw/core/ontology/models.py +123 -0
- yuclaw-1.0.0/yuclaw/core/router.py +86 -0
- yuclaw-1.0.0/yuclaw/core/security/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/core/security/injection_shield.py +38 -0
- yuclaw-1.0.0/yuclaw/data/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/data/connectors.py +85 -0
- yuclaw-1.0.0/yuclaw/data/earnings_calendar.py +39 -0
- yuclaw-1.0.0/yuclaw/data/edgar_downloader.py +187 -0
- yuclaw-1.0.0/yuclaw/data/universe_200.py +52 -0
- yuclaw-1.0.0/yuclaw/edge/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/edge/fix/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/edge/fix/fix_gateway_real.py +121 -0
- yuclaw-1.0.0/yuclaw/engine.py +305 -0
- yuclaw-1.0.0/yuclaw/factors/__init__.py +1 -0
- yuclaw-1.0.0/yuclaw/factors/advanced_factors.py +99 -0
- yuclaw-1.0.0/yuclaw/factors/factor_library.py +109 -0
- yuclaw-1.0.0/yuclaw/memory/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/memory/daily_synthesis.py +70 -0
- yuclaw-1.0.0/yuclaw/memory/evidence_graph.py +93 -0
- yuclaw-1.0.0/yuclaw/memory/portfolio_memory.py +94 -0
- yuclaw-1.0.0/yuclaw/memory/portfolio_memory_live.py +94 -0
- yuclaw-1.0.0/yuclaw/memory/portfolio_memory_v2.py +77 -0
- yuclaw-1.0.0/yuclaw/memory/thesis_drift.py +136 -0
- yuclaw-1.0.0/yuclaw/memory/thesis_tracker.py +133 -0
- yuclaw-1.0.0/yuclaw/memory/track_record.py +125 -0
- yuclaw-1.0.0/yuclaw/memory/track_record_v2.py +68 -0
- yuclaw-1.0.0/yuclaw/modules/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/modules/competitive_intel.py +93 -0
- yuclaw-1.0.0/yuclaw/modules/earnings_war_room.py +194 -0
- yuclaw-1.0.0/yuclaw/modules/execution_simulator.py +269 -0
- yuclaw-1.0.0/yuclaw/modules/factor_lab.py +190 -0
- yuclaw-1.0.0/yuclaw/modules/macro_regime.py +52 -0
- yuclaw-1.0.0/yuclaw/modules/portfolio_optimizer.py +190 -0
- yuclaw-1.0.0/yuclaw/modules/portfolio_sentinel.py +129 -0
- yuclaw-1.0.0/yuclaw/modules/scenario_shock.py +121 -0
- yuclaw-1.0.0/yuclaw/modules/sector_rotation.py +53 -0
- yuclaw-1.0.0/yuclaw/modules/signal_aggregator.py +171 -0
- yuclaw-1.0.0/yuclaw/output/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/output/excel.py +174 -0
- yuclaw-1.0.0/yuclaw/plugins/__init__.py +27 -0
- yuclaw-1.0.0/yuclaw/plugins/builtin.py +38 -0
- yuclaw-1.0.0/yuclaw/risk/__init__.py +1 -0
- yuclaw-1.0.0/yuclaw/risk/risk_engine.py +115 -0
- yuclaw-1.0.0/yuclaw/trust/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/trust/zkp_onchain.py +100 -0
- yuclaw-1.0.0/yuclaw/trust/zkp_vault.py +37 -0
- yuclaw-1.0.0/yuclaw/universe.py +18 -0
- yuclaw-1.0.0/yuclaw/validation/__init__.py +0 -0
- yuclaw-1.0.0/yuclaw/validation/engine.py +298 -0
- yuclaw-1.0.0/yuclaw/validation/model_trust_engine.py +62 -0
- yuclaw-1.0.0/yuclaw/validation/real_backtest.py +203 -0
- yuclaw-1.0.0/yuclaw.egg-info/PKG-INFO +74 -0
- yuclaw-1.0.0/yuclaw.egg-info/SOURCES.txt +75 -0
- yuclaw-1.0.0/yuclaw.egg-info/dependency_links.txt +1 -0
- yuclaw-1.0.0/yuclaw.egg-info/entry_points.txt +2 -0
- yuclaw-1.0.0/yuclaw.egg-info/requires.txt +7 -0
- 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
|
+
[](https://github.com/YuClawLab/yuclaw-brain)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://python.org)
|
|
6
|
+
[](https://nvidia.com)
|
|
7
|
+
[](https://nvidia.com)
|
|
8
|
+
[](https://sepolia.etherscan.io)
|
|
9
|
+
[](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
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
|