From c3b17e0629768e4bf3573b85a52e6a535e043fec Mon Sep 17 00:00:00 2001 From: rdyzakya Date: Thu, 25 Dec 2025 22:57:32 +0800 Subject: [PATCH 1/5] add telegram functionality --- tradingagents/dataflows/interface.py | 2 ++ tradingagents/dataflows/telegram.py | 49 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tradingagents/dataflows/telegram.py diff --git a/tradingagents/dataflows/interface.py b/tradingagents/dataflows/interface.py index 4cd5ddef..b5057d19 100644 --- a/tradingagents/dataflows/interface.py +++ b/tradingagents/dataflows/interface.py @@ -16,6 +16,7 @@ from .alpha_vantage import ( get_news as get_alpha_vantage_news ) from .alpha_vantage_common import AlphaVantageRateLimitError +from .telegram import get_crypto_news_telegram # Configuration and routing logic from .config import get_config @@ -100,6 +101,7 @@ VENDOR_METHODS = { "alpha_vantage": get_alpha_vantage_news, "openai": get_stock_news_openai, "google": get_google_news, + "telegram": get_crypto_news_telegram, "local": [get_finnhub_news, get_reddit_company_news, get_google_news], }, "get_global_news": { diff --git a/tradingagents/dataflows/telegram.py b/tradingagents/dataflows/telegram.py new file mode 100644 index 00000000..7d277e5e --- /dev/null +++ b/tradingagents/dataflows/telegram.py @@ -0,0 +1,49 @@ +import asyncio +from telethon import TelegramClient +from datetime import datetime, timedelta, timezone +import os + +def get_api_credentials(): + api_id = int(os.getenv("TELEGRAM_API_ID", "")) + api_hash = os.getenv("TELEGRAM_API_HASH", "") + session_name = os.getenv("TELEGRAM_SESSION_NAME", "") + return api_id, api_hash, session_name + +async def _get_channel_history_async(start_date_str, end_date_str): + """ + The internal async logic that does the actual work. + """ + + username = "WatcherGuru" + + api_id, api_hash, session_name = get_api_credentials() + + # 1. Start the client using 'async with' + # This automatically handles connecting AND disconnecting (releasing the DB lock) + async with TelegramClient(session_name, api_id, api_hash) as client: + + # Date parsing logic + start_date = datetime.strptime(start_date_str, '%Y-%m-%d').replace(tzinfo=timezone.utc) + end_date_obj = datetime.strptime(end_date_str, '%Y-%m-%d').replace(tzinfo=timezone.utc) + end_date = end_date_obj + timedelta(days=1) - timedelta(seconds=1) + + formatted_log = "" + + # Fetching messages + n_records = 0 + async for message in client.iter_messages(username, offset_date=end_date, reverse=False): + if message.date < start_date: + break + + if message.text: + date_str = message.date.strftime('%Y-%m-%d') + clean_text = message.text.replace('\n', ' ') + formatted_log += f"[{date_str}] {clean_text}\n" + n_records += 1 + + intro = f"# News data from Telegram channel @{username} from {start_date_str} to {end_date_str}:\n# Total records: {n_records}\n# Data retrieved on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n" + + return intro + formatted_log + +def get_crypto_news_telegram(symbol, start_date, end_date): + return asyncio.run(_get_channel_history_async(start_date, end_date)) \ No newline at end of file From 31a67d2125fe1267ed4810885ed4364b7dfbec84 Mon Sep 17 00:00:00 2001 From: rdyzakya Date: Thu, 25 Dec 2025 23:19:58 +0800 Subject: [PATCH 2/5] update news prompt, change telegram to global news --- tradingagents/dataflows/interface.py | 10 ++++----- tradingagents/dataflows/openai.py | 33 ++++++++++++++++++++++++++++ tradingagents/dataflows/telegram.py | 5 ++++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tradingagents/dataflows/interface.py b/tradingagents/dataflows/interface.py index b5057d19..5941a629 100644 --- a/tradingagents/dataflows/interface.py +++ b/tradingagents/dataflows/interface.py @@ -4,7 +4,7 @@ from typing import Annotated from .local import get_YFin_data, get_finnhub_news, get_finnhub_company_insider_sentiment, get_finnhub_company_insider_transactions, get_simfin_balance_sheet, get_simfin_cashflow, get_simfin_income_statements, get_reddit_global_news, get_reddit_company_news from .y_finance import get_YFin_data_online, get_stock_stats_indicators_window, get_balance_sheet as get_yfinance_balance_sheet, get_cashflow as get_yfinance_cashflow, get_income_statement as get_yfinance_income_statement, get_insider_transactions as get_yfinance_insider_transactions from .google import get_google_news -from .openai import get_stock_news_openai, get_global_news_openai, get_fundamentals_openai +from .openai import get_crypto_news_openai, get_global_news_openai, get_fundamentals_openai from .alpha_vantage import ( get_stock as get_alpha_vantage_stock, get_indicator as get_alpha_vantage_indicator, @@ -99,14 +99,14 @@ VENDOR_METHODS = { # news_data "get_news": { "alpha_vantage": get_alpha_vantage_news, - "openai": get_stock_news_openai, + "openai": get_crypto_news_openai, "google": get_google_news, - "telegram": get_crypto_news_telegram, - "local": [get_finnhub_news, get_reddit_company_news, get_google_news], + # "local": [get_finnhub_news, get_reddit_company_news, get_google_news], }, "get_global_news": { "openai": get_global_news_openai, - "local": get_reddit_global_news + "telegram": get_crypto_news_telegram, + # "local": get_reddit_global_news }, "get_insider_sentiment": { "local": get_finnhub_company_insider_sentiment diff --git a/tradingagents/dataflows/openai.py b/tradingagents/dataflows/openai.py index 91a2258b..7b543f90 100644 --- a/tradingagents/dataflows/openai.py +++ b/tradingagents/dataflows/openai.py @@ -36,6 +36,39 @@ def get_stock_news_openai(query, start_date, end_date): return response.output[1].content[0].text +def get_crypto_news_openai(query, start_date, end_date): + config = get_config() + client = OpenAI(base_url=config["backend_url"]) + + response = client.responses.create( + model=config["quick_think_llm"], + input=[ + { + "role": "system", + "content": [ + { + "type": "input_text", + "text": f"Can you search News for {query} from {start_date} to {end_date}? Make sure you only get the data posted during that period.", + } + ], + } + ], + text={"format": {"type": "text"}}, + reasoning={}, + tools=[ + { + "type": "web_search_preview", + "user_location": {"type": "approximate"}, + "search_context_size": "low", + } + ], + temperature=1, + max_output_tokens=4096, + top_p=1, + store=True, + ) + + return response.output[1].content[0].text def get_global_news_openai(curr_date, look_back_days=7, limit=5): config = get_config() diff --git a/tradingagents/dataflows/telegram.py b/tradingagents/dataflows/telegram.py index 7d277e5e..a669a843 100644 --- a/tradingagents/dataflows/telegram.py +++ b/tradingagents/dataflows/telegram.py @@ -45,5 +45,8 @@ async def _get_channel_history_async(start_date_str, end_date_str): return intro + formatted_log -def get_crypto_news_telegram(symbol, start_date, end_date): +def get_crypto_news_telegram(curr_date, look_back_days=7, limit=100): + # ignore limit for now + start_date = curr_date - timedelta(days=look_back_days) + end_date = curr_date return asyncio.run(_get_channel_history_async(start_date, end_date)) \ No newline at end of file From 6e206d3a4d43a360e2dd5c4939a8c53413c589ed Mon Sep 17 00:00:00 2001 From: rdyzakya Date: Thu, 25 Dec 2025 23:21:14 +0800 Subject: [PATCH 3/5] update news prompt, change telegram to global news --- tradingagents/agents/analysts/news_analyst.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tradingagents/agents/analysts/news_analyst.py b/tradingagents/agents/analysts/news_analyst.py index 03b4fae4..f7b9250e 100644 --- a/tradingagents/agents/analysts/news_analyst.py +++ b/tradingagents/agents/analysts/news_analyst.py @@ -16,7 +16,7 @@ def create_news_analyst(llm): ] 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. Use the available tools: get_news(query, start_date, end_date) for company-specific or targeted news searches, and get_global_news(curr_date, look_back_days, limit) for broader macroeconomic news. 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. Use the available tools: get_news(query, start_date, end_date) for crypto-specific or targeted news searches, and get_global_news(curr_date, look_back_days, limit) for broader macroeconomic news. 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.""" ) From 2a95a81a4ee338ac9cf240d11c10f6f16bf65590 Mon Sep 17 00:00:00 2001 From: rdyzakya Date: Thu, 25 Dec 2025 23:25:52 +0800 Subject: [PATCH 4/5] fix bug datetime in curr_date --- tradingagents/dataflows/telegram.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tradingagents/dataflows/telegram.py b/tradingagents/dataflows/telegram.py index a669a843..494d2c21 100644 --- a/tradingagents/dataflows/telegram.py +++ b/tradingagents/dataflows/telegram.py @@ -25,6 +25,7 @@ async def _get_channel_history_async(start_date_str, end_date_str): # Date parsing logic start_date = datetime.strptime(start_date_str, '%Y-%m-%d').replace(tzinfo=timezone.utc) end_date_obj = datetime.strptime(end_date_str, '%Y-%m-%d').replace(tzinfo=timezone.utc) + lookback_days = (end_date_obj - start_date).days end_date = end_date_obj + timedelta(days=1) - timedelta(seconds=1) formatted_log = "" @@ -41,12 +42,17 @@ async def _get_channel_history_async(start_date_str, end_date_str): formatted_log += f"[{date_str}] {clean_text}\n" n_records += 1 - intro = f"# News data from Telegram channel @{username} from {start_date_str} to {end_date_str}:\n# Total records: {n_records}\n# Data retrieved on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n" + intro = f"# News data from Telegram channel @{username} from {start_date_str} to {end_date_str} ({lookback_days} days):\n# Total records: {n_records}\n# Data retrieved on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n" return intro + formatted_log def get_crypto_news_telegram(curr_date, look_back_days=7, limit=100): # ignore limit for now + # convert curr_date from yyyy-mm-dd to datetime + curr_date = datetime.strptime(curr_date, '%Y-%m-%d') start_date = curr_date - timedelta(days=look_back_days) end_date = curr_date - return asyncio.run(_get_channel_history_async(start_date, end_date)) \ No newline at end of file + + start_date_str = start_date.strftime('%Y-%m-%d') + end_date_str = end_date.strftime('%Y-%m-%d') + return asyncio.run(_get_channel_history_async(start_date_str, end_date_str)) \ No newline at end of file From 5294324f976c6a2b8d9201609c4d5aa40e46cb51 Mon Sep 17 00:00:00 2001 From: rdyzakya Date: Thu, 25 Dec 2025 23:29:32 +0800 Subject: [PATCH 5/5] update env example for telegram --- .env.example | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 1e257c3c..ca3762c6 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,5 @@ ALPHA_VANTAGE_API_KEY=alpha_vantage_api_key_placeholder -OPENAI_API_KEY=openai_api_key_placeholder \ No newline at end of file +OPENAI_API_KEY=openai_api_key_placeholder +TELEGRAM_API_ID=telegram_api_placeholder +TELEGRAM_API_HASH=telegram_api_hash_placeholder +TELEGRAM_SESSION_NAME=telegram_session_name_placeholder \ No newline at end of file