feat: get news from Blockbeats and CoinDesk

This commit is contained in:
Tomortec 2025-06-26 17:54:16 +08:00
parent e62672768d
commit 3e83389092
8 changed files with 158 additions and 3 deletions

View File

@ -48,6 +48,41 @@ class Toolkit:
if config:
self.update_config(config)
@staticmethod
@tool
def get_blockbeats_news(
count: Annotated[int, "Number of news articles to retrieve, no more than 50"] = 10,
) -> str:
"""
Retrieve the latest news from BlockBeats, especially useful for Cryptos.
Args:
count (int): Number of news articles to retrieve, no more than 50
Returns:
str: A formatted string containing the latest news from BlockBeats.
"""
blockbeats_news_result = interface.get_blockbeats_news(count)
return blockbeats_news_result
@staticmethod
@tool
def get_coindesk_news(
tickers: Annotated[
List[str],
"List of tickers to get news for, e.g. ['BTC', 'ETH']",
] = [],
count: Annotated[int, "Number of news articles to retrieve, default is 10"] = 10,
) -> str:
"""
Retrieve the latest news from Coindesk for a given list of tickers.
Args:
tickers (List[str]): List of tickers to get news for, e.g. ['BTC', 'ETH']
count (int): Number of news articles to retrieve, default is 10
Returns:
str: A formatted string containing the latest news from Coindesk for the specified tickers.
"""
coindesk_news_result = interface.get_coindesk_news(tickers, count)
return coindesk_news_result
@staticmethod
@tool
def get_reddit_news(

View File

@ -0,0 +1,16 @@
# Dataflows
### To add a new data source
1. create a file with filename `[sth]_utils.py` and fetch data in it
2. go to [interface.py](./interface.py) and wrap your utility in a function returning a `str`
3. go to [\_\_init\_\_.py](./__init__.py) and expose your function in `interface.py`
4. go to [agent_utils.py](../agents/utils/agent_utils.py) and wrap your function in class `Toolkit` with the following template:
``` py
@staticmethod
@tool
def get_sth(params: Annotated[type, "comments"]):
"""docs"""
return interface.your_func(params)
```
5. modify `_create_tool_nodes` in [trading_graph.py](../graph/trading_graph.py) and `news_analyst_node` in each analyst creation file in `tradingagents/agents/analysts/[sth]_analyst.py`
6. (OPTIONAL) modify prompts to tell models when to use the utility

View File

@ -1,3 +1,5 @@
from .blockbeats_utils import get_blockbeats_news
from .coindesk_utils import get_coindesk_news
from .finnhub_utils import get_data_in_range
from .googlenews_utils import getNewsData
from .yfin_utils import YFinanceUtils
@ -7,6 +9,8 @@ from .yfin_utils import YFinanceUtils
from .interface import (
# News and sentiment functions
get_blockbeats_news,
get_coindesk_news,
get_finnhub_news,
get_finnhub_company_insider_sentiment,
get_finnhub_company_insider_transactions,
@ -27,6 +31,8 @@ from .interface import (
__all__ = [
# News and sentiment functions
"get_blockbeats_news",
"get_coindesk_news",
"get_finnhub_news",
"get_finnhub_company_insider_sentiment",
"get_finnhub_company_insider_transactions",

View File

@ -0,0 +1,16 @@
import requests
def get_blockbeats_news(count = 10):
url = f"https://api.theblockbeats.news/v1/open-api/open-flash?page=1&size={count}&type=push&lang=cn"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
if "data" in data and "data" in data["data"] and isinstance(data["data"]["data"], list):
return data["data"]["data"]
else:
print("No 'data' key found in the response.")
return []
else:
print(f"Error: {response.status_code} - {response.text}")
return []

View File

@ -0,0 +1,34 @@
import os
import requests
def get_coindesk_news(tickers=[], count=10) -> list[dict[str, str]]:
"""
Fetches the latest news from Coindesk for a given ticker.
Args:
tickers (list): The ticker symbols for which to fetch news.
count (int): The number of news articles to fetch. Default is 10.
Returns:
list: A list of news articles, each represented as a dictionary.
"""
api_key = os.getenv('COINDESK_API_KEY')
if not api_key:
raise ValueError("COINDESK_API_KEY environment variable is not set.")
url = f"https://data-api.coindesk.com/news/v1/article/list?lang=EN&limit={count}&categories={','.join(tickers)}&api_key={api_key}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
if "Data" in data and isinstance(data["Data"], list):
return list(map(lambda item: {
"title": item.get("TITLE", ""),
"categories": item.get("KEYWORDS", []),
"body": item.get("BODY", ""),
}, data["Data"]))
return []
else:
print(f"Error: {response.status_code} - {response.text}")
return []

View File

@ -1,4 +1,6 @@
from typing import Annotated, Dict
from .blockbeats_utils import get_blockbeats_news
from .coindesk_utils import get_coindesk_news
from .reddit_utils import fetch_top_from_category
from .yfin_utils import *
from .stockstats_utils import *
@ -15,6 +17,52 @@ import yfinance as yf
from openai import OpenAI
from .config import get_config, set_config, DATA_DIR
def get_blockbeats_news(count: Annotated[int, "news' count, no more than 50"] = 10):
"""
Retrieve the latest top Blockbeats news
Args:
count (int): number of news to retrieve, no more than 50
Returns:
str: A formatted string containing the latest news articles and meta information
"""
if count > 50:
raise ValueError("Count should not be more than 50")
news = get_blockbeats_news(count)
if len(news) == 0:
return ""
news_str = ""
for entry in news:
news_str += f"### {entry['title']} ({entry['create_time']})\n\n{entry['content']}\n\n"
return f"## Blockbeats News:\n\n{news_str}"
def get_coindesk_news(
tickers: Annotated[list[str], "List of ticker symbols to fetch news for"] = [],
count: Annotated[int, "Number of news articles to fetch, default is 10"] = 10,
) -> str:
"""
Retrieve the latest top Coindesk news for given tickers.
Args:
tickers (list): List of ticker symbols to fetch news for.
count (int): Number of news articles to fetch, default is 10.
Returns:
str: A formatted string containing the latest news articles and meta information.
"""
news = get_coindesk_news(tickers, count)
if len(news) == 0:
return ""
news_str = ""
for entry in news:
news_str += f"### {entry['title']} ({', '.join(entry['categories'])})\n\n{entry['body']}\n\n"
return f"## Coindesk News:\n\n{news_str}"
def get_finnhub_news(
ticker: Annotated[

View File

@ -14,7 +14,7 @@ PROMPTS = {
#region Fundamentals Analyst
"fundamentals_analyst": {
"system_message": (
"You are a researcher tasked with analyzing fundamental information over the past week about a company. Please write a comprehensive report of the company's fundamental information such as financial documents, company profile, basic company financials, company financial history, insider sentiment and insider transactions to gain a full view of the company's fundamental information to inform traders. Make sure to include as much detail as possible. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." +
"You are a researcher tasked with analyzing fundamental information over the past week about an asset. Please write a comprehensive report of the asset's fundamental information such as financial documents, company profile, basic company financials, company financial history, insider sentiment and insider transactions to gain a full view of the company's fundamental information to inform traders. Make sure to include as much detail as possible. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." +
" Make sure to append a Markdown table at the end of the report to organize key points in the report, organized and easy to read."
)
},
@ -56,7 +56,7 @@ Volume-Based Indicators:
#region News Analyst
"news_analyst": {
"system_message": (
"You are a news researcher tasked with analyzing recent news and trends over the past week. Please write a comprehensive report of the current state of the world that is relevant for trading and macroeconomics. Look at news from EODHD, and finnhub to be comprehensive. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." +
"You are a news researcher tasked with analyzing recent news and trends over the past week. Please write a comprehensive report of the current state of the world that is relevant for trading and macroeconomics. Look at news from Blockbeats, and CoinDesk to be comprehensive. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions." +
" Make sure to append a Makrdown table at the end of the report to organize key points in the report, organized and easy to read."
)
},

View File

@ -52,7 +52,7 @@ Volume-Based Indicators:
#region News Analyst
"news_analyst": {
"system_message": (
"你是一名新闻研究员,负责分析过去一周内影响交易与宏观经济的重要新闻与趋势。请撰写一份全面的分析报告,整合来自 EODHD 与 finnhub 的新闻数据。避免使用模糊措辞如“走势复杂”,应深入剖析市场动态与潜在影响,提供有助于交易判断的洞察。" +
"你是一名新闻研究员,负责分析过去一周内影响交易与宏观经济的重要新闻与趋势。请撰写一份全面的分析报告,整合来自 Blockbeats 与 CoinDesk 的新闻数据。避免使用模糊措辞如“走势复杂”,应深入剖析市场动态与潜在影响,提供有助于交易判断的洞察。" +
" 最后请附上一张 Markdown 表格,总结并清晰地整理报告中的关键要点,便于阅读和参考。"
)
},