first commit

This commit is contained in:
lzybetter
2026-08-06 20:44:18 +08:00
commit cb5a2df89f
12 changed files with 238 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
.env
.venv/
+5
View File
@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
+12
View File
@@ -0,0 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyStubPackagesAdvertiser" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<list>
<option value="pandas" />
</list>
</option>
</inspection_tool>
</profile>
</component>
+6
View File
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="~/files/code/python/stock_agent/.venv" project-jdk-type="Python SDK" />
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/stock_agent.iml" filepath="$PROJECT_DIR$/.idea/stock_agent.iml" />
</modules>
</component>
</project>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="~/files/code/python/stock_agent/.venv" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PackageRequirementsSettings" />
<component name="PyDocumentationSettings" />
<component name="ReSTService" />
<component name="TestRunnerService" />
</module>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
View File
Binary file not shown.
+70
View File
@@ -0,0 +1,70 @@
from adata import stock
import pandas as pd
# 显示所有列
pd.set_option('display.max_columns', None)
# 显示所有行
pd.set_option('display.max_rows', None)
# 显示单元格完整内容(不截断长文本)
pd.set_option('display.max_colwidth', None)
# 不自动折行
pd.set_option('display.expand_frame_repr', False)
def get_fina_info(stock_code="600699"):
df = stock.finance.get_core_index(stock_code=stock_code)
data = df[['report_date', 'report_type', 'total_rev', 'total_rev_yoy_gr','net_profit_attr_sh', 'net_profit_yoy_gr',
'non_gaap_net_profit', 'non_gaap_net_profit_yoy_gr', 'roe_wtd', 'gross_margin', 'net_margin', 'quick_ratio',
'inv_turn_rate', 'acct_recv_turn_rate']]
last_type = data['report_type'].to_list()[0]
recent_df = data[data.report_type == last_type].iloc[:2,:].reset_index(drop=True)
recent_df.rename(columns={"report_date": "报告日期",
"report_type": "报告类型",
"total_rev":"营业总收入",
"total_rev_yoy_gr":"营业总收入同比增长率",
"net_profit_attr_sh":"归母净利润",
"net_profit_yoy_gr":"归母净利润同比增长率",
"non_gaap_net_profit":"扣非净利润",
"non_gaap_net_profit_yoy_gr":"扣非净利润同比增长率",
"roe_wtd":"加权净资产收益率",
"gross_margin":"销售毛利率",
"net_margin":"销售净利率",
"quick_ratio":"速动比率",
"inv_turn_rate":"存货周转率",
"acct_recv_turn_rate":"应收账款周转率"
}, inplace=True)
formatted_lines = []
for _, row in recent_df.iterrows():
line_items = []
for col, val in zip(recent_df.columns, row):
# 判断是否为数字类型
if isinstance(val, (int, float)):
# 如果列名包含"率",则格式化为保留两位小数并加上 %
if "" in col:
formatted_val = f"{val:.2f}%"
else:
# 其他数字:格式化为带千分位、保留两位小数
formatted_val = f"{val:,.2f}"
else:
# 非数字类型(如日期、文本)直接转为字符串
formatted_val = str(val)
line_items.append(f"{col}{formatted_val}")
# 将这一期的所有字段用换行符拼接
formatted_lines.append("\n".join(line_items))
# 3. 组装最终报告文本
final_report = f"近两期{last_type}主要财务数据如下:\n" + "\n\n".join(formatted_lines)
return final_report
if __name__ == "__main__":
print(get_fina_info(stock_code="600105"))
+111
View File
@@ -0,0 +1,111 @@
import os
from langchain_classic.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
from adata import stock
from langchain_core.tools import tool
from telegram import Update
from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters
load_dotenv()
# ================= 你的原有逻辑(完全保留) =================
@tool
def get_fina_info(stock_code: str) -> str:
"""获取指定股票代码的财务数据。当需要获取财务数据的时使用此工具"""
df = stock.finance.get_core_index(stock_code=stock_code)
data = df[['report_date', 'report_type', 'total_rev', 'total_rev_yoy_gr', 'net_profit_attr_sh', 'net_profit_yoy_gr',
'non_gaap_net_profit', 'non_gaap_net_profit_yoy_gr', 'roe_wtd', 'gross_margin', 'net_margin',
'quick_ratio',
'inv_turn_rate', 'acct_recv_turn_rate']]
last_type = data['report_type'].to_list()[0]
recent_df = data[data.report_type == last_type].iloc[:2, :].reset_index(drop=True)
recent_df.rename(columns={"report_date": "报告日期", "report_type": "报告类型", "total_rev": "营业总收入",
"total_rev_yoy_gr": "营业总收入同比增长率", "net_profit_attr_sh": "归母净利润",
"net_profit_yoy_gr": "归母净利润同比增长率", "non_gaap_net_profit": "扣非净利润",
"non_gaap_net_profit_yoy_gr": "扣非净利润同比增长率", "roe_wtd": "加权净资产收益率",
"gross_margin": "销售毛利率", "net_margin": "销售净利率", "quick_ratio": "速动比率",
"inv_turn_rate": "存货周转率", "acct_recv_turn_rate": "应收账款周转率"
}, inplace=True)
formatted_lines = []
for _, row in recent_df.iterrows():
line_items = []
for col, val in zip(recent_df.columns, row):
if isinstance(val, (int, float)):
if "" in col:
formatted_val = f"{val:.2f}%"
else:
formatted_val = f"{val:,.2f}"
else:
formatted_val = str(val)
line_items.append(f"{col}{formatted_val}")
formatted_lines.append("\n".join(line_items))
final_report = f"近两期{last_type}主要财务数据如下:\n" + "\n\n".join(formatted_lines)
return final_report
class MyOutputParser(StrOutputParser):
def parse(self, text) -> str:
return text.strip()
llm = ChatOpenAI(model="deepseek-v4-flash")
tools = [get_fina_info]
template = """
你是一个专业的股票分析助手。用户会输入一个股票代码,你可以使用工具来获取其财务数据,之后根据获取到的财务数据来分析这家公司的基本面情况。
"""
chat_prompt = ChatPromptTemplate.from_messages([
("system", template),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
agent = create_tool_calling_agent(llm, tools, chat_prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# ================= 新增:Telegram 机器人交互逻辑 =================
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理 /start 命令"""
await update.message.reply_text("你好!我是你的股票分析助手,请直接发送类似“分析一下600699的基本面”的消息。")
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理普通文本消息,调用你的 Agent"""
user_input = update.message.text
# 提示用户正在处理,因为 Agent 调用工具可能需要几秒钟
await update.message.reply_text("🤔 正在分析,请稍候...")
try:
# 调用你原有的 Agent 逻辑
res = agent_executor.invoke({"input": user_input})
output = res["output"]
except Exception as e:
output = f"分析出错:{str(e)}"
await update.message.reply_text(output)
if __name__ == "__main__":
# 从环境变量读取 Token
token = os.getenv("TELEGRAM_BOT_TOKEN")
if not token:
raise ValueError("未在 .env 文件中找到 TELEGRAM_BOT_TOKEN")
proxy_url = "http://127.0.0.1:8889"
# 启动机器人
application = ApplicationBuilder().token(token).proxy(proxy_url).get_updates_proxy(proxy_url).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
print("Telegram Bot 正在运行...")
application.run_polling()