Skip to content

Commit 2192476

Browse files
committed
deploy: c65ef92
1 parent 4e54490 commit 2192476

File tree

11 files changed

+712
-170
lines changed

11 files changed

+712
-170
lines changed

README.md

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Modern Flask-based web application with:
102102
### 1. Create and Activate Conda Environment
103103

104104
```bash
105-
conda create -n quantagents python=3.10
105+
conda create -n quantagents python=3.11
106106
conda activate quantagents
107107
```
108108

@@ -121,13 +121,22 @@ conda install -c conda-forge ta-lib
121121

122122
Or visit the [TA-Lib Python repository](https://github.com/ta-lib/ta-lib-python) for detailed installation instructions.
123123

124-
### 3. Set Up OpenAI API Key
124+
### 3. Set Up LLM API Key
125125
You can set it in our Web InterFace Later,
126+
126127
![alt text](assets/apibox.png)
127128

128129
Or set it as an environment variable:
129130
```bash
130-
export OPENAI_API_KEY="your_api_key_here"
131+
# For OpenAI
132+
export OPENAI_API_KEY="your_openai_api_key_here"
133+
134+
# For Anthropic (Claude)
135+
export ANTHROPIC_API_KEY="your_anthropic_api_key_here"
136+
137+
# For Qwen (DashScope, based in Singapore — delays may occur)
138+
export DASHSCOPE_API_KEY="your_dashscope_api_key_here"
139+
131140
```
132141

133142

@@ -191,24 +200,30 @@ print(final_state.get("pattern_report"))
191200
print(final_state.get("trend_report"))
192201
```
193202

194-
You can also adjust the default configuration to set your own choice of LLMs, analysis parameters, etc.
203+
You can also adjust the default configuration to set your own choice of LLMs or analysis parameters in web_interface.py.
195204

196205
```python
197-
from trading_graph import TradingGraph
198-
from default_config import DEFAULT_CONFIG
199-
200-
# Create a custom config
201-
config = DEFAULT_CONFIG.copy()
202-
config["agent_llm_model"] = "gpt-4o-mini" # Use a different model for agents
203-
config["graph_llm_model"] = "gpt-4o" # Use a different model for graph logic
204-
config["agent_llm_temperature"] = 0.2 # Adjust creativity level for agents
205-
config["graph_llm_temperature"] = 0.1 # Adjust creativity level for graph logic
206-
207-
# Initialize with custom config
208-
trading_graph = TradingGraph(config=config)
209-
210-
# Run analysis with custom configuration
211-
final_state = trading_graph.graph.invoke(initial_state)
206+
if provider == "anthropic":
207+
# Set default Claude models if not already set to Anthropic models
208+
if not analyzer.config["agent_llm_model"].startswith("claude"):
209+
analyzer.config["agent_llm_model"] = "claude-haiku-4-5-20251001"
210+
if not analyzer.config["graph_llm_model"].startswith("claude"):
211+
analyzer.config["graph_llm_model"] = "claude-haiku-4-5-20251001"
212+
213+
elif provider == "qwen":
214+
# Set default Qwen models if not already set to Qwen models
215+
if not analyzer.config["agent_llm_model"].startswith("qwen"):
216+
analyzer.config["agent_llm_model"] = "qwen3-max"
217+
if not analyzer.config["graph_llm_model"].startswith("qwen"):
218+
analyzer.config["graph_llm_model"] = "qwen3-vl-plus"
219+
220+
else:
221+
# Set default OpenAI models if not already set to OpenAI models
222+
if analyzer.config["agent_llm_model"].startswith(("claude", "qwen")):
223+
analyzer.config["agent_llm_model"] = "gpt-4o-mini"
224+
if analyzer.config["graph_llm_model"].startswith(("claude", "qwen")):
225+
analyzer.config["graph_llm_model"] = "gpt-4o"
226+
212227
```
213228

214229
For live data, we recommend using the web interface as it provides access to real-time market data through yfinance. The system automatically fetches the most recent 30 candlesticks for optimal LLM analysis accuracy.
@@ -251,8 +266,16 @@ This project is licensed under the MIT License - see the LICENSE file for detail
251266

252267
## 🙏 Acknowledgements
253268

254-
This repository was built off of [**LangGraph**](https://github.com/langchain-ai/langgraph), [**OpenAI**](https://github.com/openai/openai-python), [**yfinance**](https://github.com/ranaroussi/yfinance), [**Flask**](https://github.com/pallets/flask), [**TechnicalAnalysisAutomation**](https://github.com/neurotrader888/TechnicalAnalysisAutomation/tree/main) and [**tvdatafeed**](https://github.com/rongardF/tvdatafeed).
269+
This repository was built with the help of the following libraries and frameworks:
255270

271+
- [**LangGraph**](https://github.com/langchain-ai/langgraph)
272+
- [**OpenAI**](https://github.com/openai/openai-python)
273+
- [**Anthropic (Claude)**](https://github.com/anthropics/anthropic-sdk-python)
274+
- [**Qwen**](https://github.com/QwenLM/Qwen)
275+
- [**yfinance**](https://github.com/ranaroussi/yfinance)
276+
- [**Flask**](https://github.com/pallets/flask)
277+
- [**TechnicalAnalysisAutomation**](https://github.com/neurotrader888/TechnicalAnalysisAutomation/tree/main)
278+
- [**tvdatafeed**](https://github.com/rongardF/tvdatafeed)
256279
## ⚠️ Disclaimer
257280

258281
This software is for educational and research purposes only. It is not intended to provide financial advice. Always do your own research and consider consulting with a financial advisor before making investment decisions.
@@ -263,7 +286,7 @@ This software is for educational and research purposes only. It is not intended
263286

264287
1. **TA-Lib Installation**: If you encounter TA-Lib installation issues, refer to the [official repository](https://github.com/ta-lib/ta-lib-python) for platform-specific instructions.
265288

266-
2. **OpenAI API Key**: Ensure your API key is properly set in the environment or through the web interface.
289+
2. **LLM API Key**: Ensure your API key is properly set in the environment or through the web interface.
267290

268291
3. **Data Fetching**: The system uses Yahoo Finance for data. Some symbols might not be available or have limited historical data.
269292

@@ -272,10 +295,12 @@ This software is for educational and research purposes only. It is not intended
272295
### Support
273296

274297
If you encounter any issues, please:
298+
299+
0. Try refresh and re-enter LLM API key
275300
1. Check the troubleshooting section above
276301
2. Review the error messages in the console
277302
3. Ensure all dependencies are properly installed
278-
4. Verify your OpenAI API key is valid and has sufficient credits
303+
4. Verify your API key is valid and has sufficient credits
279304

280305
## 📧 Contact
281306

README_CN.md

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
### 1. 创建并激活 Conda 环境
100100

101101
```bash
102-
conda create -n quantagents python=3.10
102+
conda create -n quantagents python=3.11
103103
conda activate quantagents
104104
```
105105

@@ -117,19 +117,26 @@ conda install -c conda-forge ta-lib
117117

118118
或访问 [TA-Lib Python 仓库](https://github.com/ta-lib/ta-lib-python) 获取详细的安装说明。
119119

120-
### 3. 设置 OpenAI API 密钥
120+
### 3. 设置 LLM API 密钥
121121
您可以在我们的网络界面中稍后设置它,
122-
![API 密钥设置](assets/apibox.png)
122+
123+
![alt text](assets/apibox.png)
123124

124125
或将其设置为环境变量:
125126
```bash
126-
export OPENAI_API_KEY="your_api_key_here"
127+
# For OpenAI
128+
export OPENAI_API_KEY="your_openai_api_key_here"
129+
130+
# For Anthropic (Claude)
131+
export ANTHROPIC_API_KEY="your_anthropic_api_key_here"
132+
133+
# For Qwen (DashScope, based in Singapore — delays may occur)
134+
export DASHSCOPE_API_KEY="your_dashscope_api_key_here"
135+
127136
```
128137

129138
## 🔧 实现细节
130139

131-
我们使用 LangGraph 构建 QuantAgents 以确保灵活性和模块化。我们使用 gpt-4o 和 gpt-4o-mini 作为我们的深度思考和快速思考 LLM 进行实验。但是,出于测试目的,我们建议您使用 gpt-4o-mini 来节省成本,因为我们的框架会进行大量 API 调用。
132-
133140
**重要说明**:我们的模型需要一个可以接受图像输入的 LLM,因为我们的智能体会生成和分析视觉图表以进行模式识别和趋势分析。
134141

135142
### Python 使用
@@ -161,24 +168,30 @@ print(final_state.get("pattern_report"))
161168
print(final_state.get("trend_report"))
162169
```
163170

164-
您还可以调整默认配置以设置您自己的 LLM 选择、分析参数等
171+
您还可以调整默认配置以在 web_interface.py 中设置您自己的 LLM 选择或分析参数
165172

166173
```python
167-
from trading_graph import TradingGraph
168-
from default_config import DEFAULT_CONFIG
169-
170-
# 创建自定义配置
171-
config = DEFAULT_CONFIG.copy()
172-
config["agent_llm_model"] = "gpt-4o-mini" # 为智能体使用不同的模型
173-
config["graph_llm_model"] = "gpt-4o" # 为图逻辑使用不同的模型
174-
config["agent_llm_temperature"] = 0.2 # 调整智能体的创造力水平
175-
config["graph_llm_temperature"] = 0.1 # 调整图逻辑的创造力水平
176-
177-
# 使用自定义配置初始化
178-
trading_graph = TradingGraph(config=config)
179-
180-
# 使用自定义配置运行分析
181-
final_state = trading_graph.graph.invoke(initial_state)
174+
if provider == "anthropic":
175+
# Set default Claude models if not already set to Anthropic models
176+
if not analyzer.config["agent_llm_model"].startswith("claude"):
177+
analyzer.config["agent_llm_model"] = "claude-haiku-4-5-20251001"
178+
if not analyzer.config["graph_llm_model"].startswith("claude"):
179+
analyzer.config["graph_llm_model"] = "claude-haiku-4-5-20251001"
180+
181+
elif provider == "qwen":
182+
# Set default Qwen models if not already set to Qwen models
183+
if not analyzer.config["agent_llm_model"].startswith("qwen"):
184+
analyzer.config["agent_llm_model"] = "qwen3-max"
185+
if not analyzer.config["graph_llm_model"].startswith("qwen"):
186+
analyzer.config["graph_llm_model"] = "qwen3-vl-plus"
187+
188+
else:
189+
# Set default OpenAI models if not already set to OpenAI models
190+
if analyzer.config["agent_llm_model"].startswith(("claude", "qwen")):
191+
analyzer.config["agent_llm_model"] = "gpt-4o-mini"
192+
if analyzer.config["graph_llm_model"].startswith(("claude", "qwen")):
193+
analyzer.config["graph_llm_model"] = "gpt-4o"
194+
182195
```
183196

184197
对于实时数据,我们建议使用网络界面,因为它通过 yfinance 提供对实时市场数据的访问。系统会自动获取最近 30 个蜡烛图以获得最佳的 LLM 分析准确性。
@@ -213,7 +226,7 @@ python web_interface.py
213226
2. **时间框架选择**:分析从 1 分钟到每日间隔的数据
214227
3. **日期范围**:为分析选择自定义日期范围
215228
4. **实时分析**:获得带有可视化的全面技术分析
216-
5. **API 密钥管理**:通过界面更新您的 OpenAI API 密钥
229+
5. **API 密钥管理**:通过界面更新您的 LLM API 密钥
217230

218231
## 📺 演示
219232

@@ -244,7 +257,16 @@ python web_interface.py
244257

245258
## 🙏 致谢
246259

247-
此仓库基于 [**LangGraph**](https://github.com/langchain-ai/langgraph)[**OpenAI**](https://github.com/openai/openai-python)[**yfinance**](https://github.com/ranaroussi/yfinance)[**Flask**](https://github.com/pallets/flask)[**TechnicalAnalysisAutomation**](https://github.com/neurotrader888/TechnicalAnalysisAutomation/tree/main)[**tvdatafeed**](https://github.com/rongardF/tvdatafeed) 构建。
260+
此仓库基于以下库和框架构建:
261+
262+
- [**LangGraph**](https://github.com/langchain-ai/langgraph)
263+
- [**OpenAI**](https://github.com/openai/openai-python)
264+
- [**Anthropic (Claude)**](https://github.com/anthropics/anthropic-sdk-python)
265+
- [**Qwen**](https://github.com/QwenLM/Qwen)
266+
- [**yfinance**](https://github.com/ranaroussi/yfinance)
267+
- [**Flask**](https://github.com/pallets/flask)
268+
- [**TechnicalAnalysisAutomation**](https://github.com/neurotrader888/TechnicalAnalysisAutomation/tree/main)
269+
- [**tvdatafeed**](https://github.com/rongardF/tvdatafeed)
248270

249271
## ⚠️ 免责声明
250272

@@ -256,7 +278,7 @@ python web_interface.py
256278

257279
1. **TA-Lib 安装**:如果您遇到 TA-Lib 安装问题,请参考[官方仓库](https://github.com/ta-lib/ta-lib-python)获取平台特定的说明。
258280

259-
2. **OpenAI API 密钥**:确保您的 API 密钥在环境中或通过网络界面正确设置。
281+
2. **LLM API 密钥**:确保您的 API 密钥在环境中或通过网络界面正确设置。
260282

261283
3. **数据获取**:系统使用雅虎财经获取数据。某些符号可能不可用或历史数据有限。
262284

@@ -265,16 +287,18 @@ python web_interface.py
265287
### 支持
266288

267289
如果您遇到任何问题,请:
290+
291+
0. 尝试刷新页面,重新通过页面输入LLM API 密钥
268292
1. 检查上面的故障排除部分
269293
2. 查看控制台中的错误消息
270294
3. 确保所有依赖项都正确安装
271-
4. 验证您的 OpenAI API 密钥有效且有足够的积分
295+
4. 验证您的 LLM API 密钥有效且有足够的积分
272296

273297
## 📧 联系
274298

275299
如有问题、反馈或合作机会,请联系:
276300

277-
**邮箱**[[email protected]](mailto:[email protected])
301+
278302

279303
## Star History
280304

assets/apibox.png

-49.2 KB
Loading

default_config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
DEFAULT_CONFIG = {
22
"agent_llm_model": "gpt-4o-mini",
33
"graph_llm_model": "gpt-4o",
4+
"agent_llm_provider": "openai", # "openai", "anthropic", or "qwen"
5+
"graph_llm_provider": "openai", # "openai", "anthropic", or "qwen"
46
"agent_llm_temperature": 0.1,
57
"graph_llm_temperature": 0.1,
6-
"api_key": "",
8+
"api_key": "sk-", # OpenAI API key
9+
"anthropic_api_key": "sk-", # Anthropic API key (optional, can also use ANTHROPIC_API_KEY env var)
10+
"qwen_api_key": "sk-", # Qwen API key (optional, can also use DASHSCOPE_API_KEY env var)
711
}

indicator_agent.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import copy
77
import json
88

9-
from langchain_core.messages import ToolMessage
9+
from langchain_core.messages import ToolMessage, HumanMessage
1010
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
1111

1212

@@ -44,14 +44,18 @@ def indicator_agent_node(state):
4444
).partial(kline_data=json.dumps(state["kline_data"], indent=2))
4545

4646
chain = prompt | llm.bind_tools(tools)
47-
messages = state["messages"]
47+
# messages = state["messages"]
48+
messages = state.get("messages", [])
49+
if not messages:
50+
messages = [HumanMessage(content="Begin indicator analysis.")]
51+
4852

4953
# --- Step 1: Ask for tool calls ---
5054
ai_response = chain.invoke(messages)
5155
messages.append(ai_response)
52-
56+
5357
# --- Step 2: Collect tool results ---
54-
if hasattr(ai_response, "tool_calls"):
58+
if hasattr(ai_response, "tool_calls") and ai_response.tool_calls:
5559
for call in ai_response.tool_calls:
5660
tool_name = call["name"]
5761
tool_args = call["args"]
@@ -68,11 +72,52 @@ def indicator_agent_node(state):
6872
)
6973

7074
# --- Step 3: Re-run the chain with tool results ---
71-
final_response = chain.invoke(messages)
75+
# Keep invoking until we get a text response (not another tool call)
76+
# This is important for Claude which may make multiple tool calls
77+
max_iterations = 5 # Prevent infinite loops
78+
iteration = 0
79+
final_response = None
80+
81+
while iteration < max_iterations:
82+
iteration += 1
83+
final_response = chain.invoke(messages)
84+
messages.append(final_response)
85+
86+
# If there are no tool calls, we have the final answer
87+
if not hasattr(final_response, "tool_calls") or not final_response.tool_calls:
88+
break
89+
90+
# If there are more tool calls, execute them
91+
for call in final_response.tool_calls:
92+
tool_name = call["name"]
93+
tool_args = call["args"]
94+
tool_args["kline_data"] = copy.deepcopy(state["kline_data"])
95+
tool_fn = next(t for t in tools if t.name == tool_name)
96+
tool_result = tool_fn.invoke(tool_args)
97+
messages.append(
98+
ToolMessage(
99+
tool_call_id=call["id"], content=json.dumps(tool_result)
100+
)
101+
)
102+
103+
# Extract content - handle both string and empty content cases
104+
if final_response:
105+
report_content = final_response.content
106+
# If content is empty or None, try to get text from recent messages
107+
if not report_content or (isinstance(report_content, str) and not report_content.strip()):
108+
# Check if there's any text content in the messages (skip tool calls)
109+
for msg in reversed(messages):
110+
if (hasattr(msg, 'content') and msg.content and
111+
isinstance(msg.content, str) and msg.content.strip() and
112+
not hasattr(msg, 'tool_calls')):
113+
report_content = msg.content
114+
break
115+
else:
116+
report_content = "Indicator analysis completed, but no detailed report was generated."
72117

73118
return {
74-
"messages": messages + [final_response],
75-
"indicator_report": final_response.content,
119+
"messages": messages,
120+
"indicator_report": report_content if report_content else "Indicator analysis completed.",
76121
}
77122

78123
return indicator_agent_node

0 commit comments

Comments
 (0)