Skip to content

Commit e3b3691

Browse files
authored
Merge pull request #2 from intellispectrum/feature/add-ai-hedge-fund-subtree
Introduce AI Hedge Fund subtree and corresponding agent executor and adapter
2 parents 1fde795 + 34928d3 commit e3b3691

File tree

227 files changed

+47651
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

227 files changed

+47651
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# For getting financial data to power the hedge fund
2+
# Get your Financial Datasets API key from https://financialdatasets.ai/
3+
FINANCIAL_DATASETS_API_KEY=your-financial-datasets-api-key
4+
5+
# For running LLMs hosted by openai (GPT 5, etc.)
6+
# Get your OpenAI API key from https://platform.openai.com/
7+
OPENAI_API_KEY=your-openai-api-key
8+
9+
# For running LLMs hosted by anthropic (claude-4-sonnet, claude-4.1-opus, etc.)
10+
# Get your Anthropic API key from https://anthropic.com/
11+
ANTHROPIC_API_KEY=your-anthropic-api-key
12+
13+
# For running LLMs hosted by deepseek (deepseek-chat, deepseek-reasoner, etc.)
14+
# Get your DeepSeek API key from https://deepseek.com/
15+
DEEPSEEK_API_KEY=your-deepseek-api-key
16+
17+
# For running LLMs hosted by groq (deepseek, llama3, etc.)
18+
# Get your Groq API key from https://groq.com/
19+
GROQ_API_KEY=your-groq-api-key
20+
21+
# For running LLMs hosted by gemini (gemini-2.5-flash, gemini-2.5-pro)
22+
# Get your Google API key from https://ai.dev/
23+
GOOGLE_API_KEY=your-google-api-key
24+
25+
# For running LLMs hosted by xAI (Grok 4, etc.)
26+
XAI_API_KEY=your-xai-api-key
27+
28+
# For running LLM GigaChat
29+
GIGACHAT_API_KEY=your-gigachat-api-key
30+
31+
# For running LLMs hosted by OpenRouter
32+
OPENROUTER_API_KEY=your-openrouter-api-key
33+
34+
# For running LLMs hosted by Microsoft Azure OpenAI (gpt-4o, gpt-4o-mini, etc.)
35+
# Get your Azure OpenAI API settings from https://oai.azure.com/
36+
AZURE_OPENAI_API_KEY=your-azure-openai-api-key
37+
AZURE_OPENAI_ENDPOINT=your-azure-openai-endpoint
38+
AZURE_OPENAI_DEPLOYMENT_NAME=your-azure-openai-deployment-name
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**Screenshot**
14+
Add a screenshot of the bug to help explain your problem.
15+
16+
**Additional context**
17+
Add any other context about the problem here.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: enhancement
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the feature you'd like**
11+
A clear and concise description of what you want to happen.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
env/
8+
build/
9+
develop-eggs/
10+
dist/
11+
downloads/
12+
eggs/
13+
.eggs/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual Environment
24+
venv/
25+
ENV/
26+
27+
# Environment Variables
28+
.env
29+
30+
# IDE
31+
.idea/
32+
.vscode/
33+
*.swp
34+
*.swo
35+
.cursorrules
36+
.cursorignore
37+
.cursorindexingignore
38+
39+
# OS
40+
.DS_Store
41+
Thumbs.db
42+
43+
# graph
44+
*.png
45+
46+
# Txt files
47+
*.txt
48+
49+
# PDF files
50+
*.pdf
51+
52+
# Frontend
53+
node_modules
54+
55+
# Outputs
56+
outputs/
57+
58+
# Database files (users will have their own local databases)
59+
*.db
60+
*.db-journal
61+
*.db-wal
62+
*.db-shm
63+
*.sqlite
64+
*.sqlite3
65+
66+
# Alembic (keep migration files, but ignore generated/cache files)
67+
app/backend/alembic/versions/__pycache__/
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# AI Hedge Fund
2+
3+
This is a proof of concept for an AI-powered hedge fund. The goal of this project is to explore the use of AI to make trading decisions. This project is for **educational** purposes only and is not intended for real trading or investment.
4+
5+
This system employs several agents working together:
6+
7+
1. Aswath Damodaran Agent - The Dean of Valuation, focuses on story, numbers, and disciplined valuation
8+
2. Ben Graham Agent - The godfather of value investing, only buys hidden gems with a margin of safety
9+
3. Bill Ackman Agent - An activist investor, takes bold positions and pushes for change
10+
4. Cathie Wood Agent - The queen of growth investing, believes in the power of innovation and disruption
11+
5. Charlie Munger Agent - Warren Buffett's partner, only buys wonderful businesses at fair prices
12+
6. Michael Burry Agent - The Big Short contrarian who hunts for deep value
13+
7. Mohnish Pabrai Agent - The Dhandho investor, who looks for doubles at low risk
14+
8. Peter Lynch Agent - Practical investor who seeks "ten-baggers" in everyday businesses
15+
9. Phil Fisher Agent - Meticulous growth investor who uses deep "scuttlebutt" research
16+
10. Rakesh Jhunjhunwala Agent - The Big Bull of India
17+
11. Stanley Druckenmiller Agent - Macro legend who hunts for asymmetric opportunities with growth potential
18+
12. Warren Buffett Agent - The oracle of Omaha, seeks wonderful companies at a fair price
19+
13. Valuation Agent - Calculates the intrinsic value of a stock and generates trading signals
20+
14. Sentiment Agent - Analyzes market sentiment and generates trading signals
21+
15. Fundamentals Agent - Analyzes fundamental data and generates trading signals
22+
16. Technicals Agent - Analyzes technical indicators and generates trading signals
23+
17. Risk Manager - Calculates risk metrics and sets position limits
24+
18. Portfolio Manager - Makes final trading decisions and generates orders
25+
26+
<img width="1042" alt="Screenshot 2025-03-22 at 6 19 07 PM" src="https://github.com/user-attachments/assets/cbae3dcf-b571-490d-b0ad-3f0f035ac0d4" />
27+
28+
Note: the system does not actually make any trades.
29+
30+
[![Twitter Follow](https://img.shields.io/twitter/follow/virattt?style=social)](https://twitter.com/virattt)
31+
32+
## Disclaimer
33+
34+
This project is for **educational and research purposes only**.
35+
36+
- Not intended for real trading or investment
37+
- No investment advice or guarantees provided
38+
- Creator assumes no liability for financial losses
39+
- Consult a financial advisor for investment decisions
40+
- Past performance does not indicate future results
41+
42+
By using this software, you agree to use it solely for learning purposes.
43+
44+
## Table of Contents
45+
- [How to Install](#how-to-install)
46+
- [How to Run](#how-to-run)
47+
- [⌨️ Command Line Interface](#️-command-line-interface)
48+
- [🖥️ Web Application](#️-web-application)
49+
- [How to Contribute](#how-to-contribute)
50+
- [Feature Requests](#feature-requests)
51+
- [License](#license)
52+
53+
## How to Install
54+
55+
Before you can run the AI Hedge Fund, you'll need to install it and set up your API keys. These steps are common to both the full-stack web application and command line interface.
56+
57+
### 1. Clone the Repository
58+
59+
```bash
60+
git clone https://github.com/virattt/ai-hedge-fund.git
61+
cd ai-hedge-fund
62+
```
63+
64+
### 2. Set up API keys
65+
66+
Create a `.env` file for your API keys:
67+
```bash
68+
# Create .env file for your API keys (in the root directory)
69+
cp .env.example .env
70+
```
71+
72+
Open and edit the `.env` file to add your API keys:
73+
```bash
74+
# For running LLMs hosted by openai (gpt-4o, gpt-4o-mini, etc.)
75+
OPENAI_API_KEY=your-openai-api-key
76+
77+
# For getting financial data to power the hedge fund
78+
FINANCIAL_DATASETS_API_KEY=your-financial-datasets-api-key
79+
```
80+
81+
**Important**: You must set at least one LLM API key (e.g. `OPENAI_API_KEY`, `GROQ_API_KEY`, `ANTHROPIC_API_KEY`, or `DEEPSEEK_API_KEY`) for the hedge fund to work.
82+
83+
**Financial Data**: Data for AAPL, GOOGL, MSFT, NVDA, and TSLA is free and does not require an API key. For any other ticker, you will need to set the `FINANCIAL_DATASETS_API_KEY` in the .env file.
84+
85+
## How to Run
86+
87+
### ⌨️ Command Line Interface
88+
89+
You can run the AI Hedge Fund directly via terminal. This approach offers more granular control and is useful for automation, scripting, and integration purposes.
90+
91+
<img width="992" alt="Screenshot 2025-01-06 at 5 50 17 PM" src="https://github.com/user-attachments/assets/e8ca04bf-9989-4a7d-a8b4-34e04666663b" />
92+
93+
#### Quick Start
94+
95+
1. Install Poetry (if not already installed):
96+
```bash
97+
curl -sSL https://install.python-poetry.org | python3 -
98+
```
99+
100+
2. Install dependencies:
101+
```bash
102+
poetry install
103+
```
104+
105+
#### Run the AI Hedge Fund
106+
```bash
107+
poetry run python src/main.py --ticker AAPL,MSFT,NVDA
108+
```
109+
110+
You can also specify a `--ollama` flag to run the AI hedge fund using local LLMs.
111+
112+
```bash
113+
poetry run python src/main.py --ticker AAPL,MSFT,NVDA --ollama
114+
```
115+
116+
You can optionally specify the start and end dates to make decisions over a specific time period.
117+
118+
```bash
119+
poetry run python src/main.py --ticker AAPL,MSFT,NVDA --start-date 2024-01-01 --end-date 2024-03-01
120+
```
121+
122+
#### Run the Backtester
123+
```bash
124+
poetry run python src/backtester.py --ticker AAPL,MSFT,NVDA
125+
```
126+
127+
**Example Output:**
128+
<img width="941" alt="Screenshot 2025-01-06 at 5 47 52 PM" src="https://github.com/user-attachments/assets/00e794ea-8628-44e6-9a84-8f8a31ad3b47" />
129+
130+
131+
Note: The `--ollama`, `--start-date`, and `--end-date` flags work for the backtester, as well!
132+
133+
### 🖥️ Web Application
134+
135+
The new way to run the AI Hedge Fund is through our web application that provides a user-friendly interface. This is recommended for users who prefer visual interfaces over command line tools.
136+
137+
Please see detailed instructions on how to install and run the web application [here](https://github.com/virattt/ai-hedge-fund/tree/main/app).
138+
139+
<img width="1721" alt="Screenshot 2025-06-28 at 6 41 03 PM" src="https://github.com/user-attachments/assets/b95ab696-c9f4-416c-9ad1-51feb1f5374b" />
140+
141+
142+
## How to Contribute
143+
144+
1. Fork the repository
145+
2. Create a feature branch
146+
3. Commit your changes
147+
4. Push to the branch
148+
5. Create a Pull Request
149+
150+
**Important**: Please keep your pull requests small and focused. This will make it easier to review and merge.
151+
152+
## Feature Requests
153+
154+
If you have a feature request, please open an [issue](https://github.com/virattt/ai-hedge-fund/issues) and make sure it is tagged with `enhancement`.
155+
156+
## License
157+
158+
This project is licensed under the MIT License - see the LICENSE file for details.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import json
2+
import logging
3+
import sys
4+
from pathlib import Path
5+
6+
import click
7+
import httpx
8+
import uvicorn
9+
from a2a.server.apps import A2AStarletteApplication
10+
from a2a.server.request_handlers import DefaultRequestHandler
11+
from a2a.server.tasks import (
12+
BasePushNotificationSender,
13+
InMemoryPushNotificationConfigStore,
14+
InMemoryTaskStore,
15+
)
16+
from a2a.types import AgentCard
17+
from adapter.agent_executor import VanillaAgentExecutor
18+
19+
logger = logging.getLogger(__name__)
20+
21+
22+
@click.command()
23+
@click.option('--host', 'host', default='localhost')
24+
@click.option('--port', 'port', default=10001)
25+
@click.option('--agent-card', 'agent_card_file')
26+
def main(host, port, agent_card_file):
27+
"""Starts an Agent server."""
28+
try:
29+
if not agent_card_file:
30+
raise ValueError('Agent card is required')
31+
with Path.open(agent_card_file) as file:
32+
data = json.load(file)
33+
agent_card = AgentCard(**data)
34+
35+
client = httpx.AsyncClient()
36+
push_notification_config_store = InMemoryPushNotificationConfigStore()
37+
push_notification_sender = BasePushNotificationSender(
38+
client, config_store=push_notification_config_store
39+
)
40+
41+
request_handler = DefaultRequestHandler(
42+
agent_executor=VanillaAgentExecutor(),
43+
task_store=InMemoryTaskStore(),
44+
push_config_store=push_notification_config_store,
45+
push_sender=push_notification_sender,
46+
)
47+
48+
server = A2AStarletteApplication(
49+
agent_card=agent_card, http_handler=request_handler
50+
)
51+
52+
logger.info(f'Starting server on {host}:{port}')
53+
54+
uvicorn.run(server.build(), host=host, port=port)
55+
except FileNotFoundError:
56+
logger.error(f"Error: File '{agent_card_file}' not found.")
57+
sys.exit(1)
58+
except json.JSONDecodeError:
59+
logger.error(f"Error: File '{agent_card_file}' contains invalid JSON.")
60+
sys.exit(1)
61+
except Exception as e:
62+
logger.error(f'An error occurred during server startup: {e}')
63+
sys.exit(1)
64+
65+
66+
if __name__ == '__main__':
67+
main()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import json
2+
3+
from a2a.server.agent_execution import AgentExecutor, RequestContext
4+
from a2a.server.events import EventQueue
5+
from a2a.types import Task, UnsupportedOperationError
6+
from a2a.utils import new_agent_text_message
7+
from a2a.utils.errors import ServerError
8+
from src.main import run_hedge_fund
9+
10+
11+
class VanillaAgent:
12+
async def invoke(self, message: dict) -> str:
13+
result = run_hedge_fund(**message)
14+
return json.dumps(result)
15+
16+
17+
class VanillaAgentExecutor(AgentExecutor):
18+
def __init__(self):
19+
self.agent = VanillaAgent()
20+
21+
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
22+
result = await self.agent.invoke(json.loads(context.get_user_input()))
23+
await event_queue.enqueue_event(new_agent_text_message(result))
24+
25+
async def cancel(
26+
self, request: RequestContext, event_queue: EventQueue
27+
) -> Task | None:
28+
raise ServerError(error=UnsupportedOperationError())

0 commit comments

Comments
 (0)