先给结论:这个AI炒股项目能做什么?
别被“量化交易”吓住,这个项目的核心是“用AI简化决策”,目前已实现3大核心功能,普通人也能上手:
✅ 数据全自动
整合akshare免费接口,爬取中国市场ETF实时行情,支持增量更新(不用重复下历史数据)
✅ 大模型操盘
Qwen3/DeepSeek读取行情数据后生成交易指令,已实测Qwen3有完整交易记录
✅ 回测可视化
Web页面直接看收益曲线、持仓分析,回测基准锚定沪深300,收益一目了然
划重点:现在支持ETF,改个配置文件就能扩展到股票交易,后续加MACD、RSI指标也预留了接口。
实操环节:从0到1搭AI交易系统(附完整代码)
核心逻辑:数据采集→大模型分析→交易指令→回测可视化,全程Python实现,不用懂高深算法,跟着复制就行。
第一步:环境配置(5分钟搞定)
先装必备工具,新手直接复制命令到终端执行:
pip install akshare python-dotenv pandas json
akshare优势:比Wind、Tushare免费,中国市场数据超全(ETF/股票/基金都能爬),接口稳定,个人研究够用了。
第二步:核心代码拆解(关键部分附通俗解释)
代码分4个核心模块,每个模块都加了新手能懂的注释,直接复制到main.py即可。
模块1:初始化与ETF池配置
先定义要监控的ETF,选的都是跨境+资源类,分散风险,新手直接用这个组合就行:
import os
from dotenv import load_dotenv
load_dotenv()
import json
import akshare as ak
from datetime import datetime, timedelta
all_zh_symbols = [
"159561",
"513880",
"513500",
"513130",
"513830",
"160416",
"518880",
]
为什么选ETF不选个股?ETF费率低、分散风险,就算单只股票跌,对整体影响小,特别适合新手练手。
模块2:代码格式转换(对接akshare的关键)
akshare需要区分上海/深圳交易所,这个函数自动加前缀,不用手动改:
def add_sh_sz(symbol):
"""给股票代码加交易所前缀(sh=上海,sz=深圳)"""
if symbol.startswith(("6","5")):
symbol = f"sh{symbol}"
elif symbol.startswith(("0","1","3")):
symbol = f"sz{symbol}"
return symbol
print(add_sh_sz("513500"))
模块3:数据增量更新(省时间省流量)
核心亮点:不会重复下历史数据,只更最新的,爬取效率翻倍。分两个函数实现
def get_last_refreshed_date(SYMBOL: str):
"""查本地数据的最后更新时间,避免重复爬取"""
filename = f'./daily_prices_{SYMBOL}.json'
if os.path.exists(filename):
try:
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
last_date = data.get("Meta Data", {}).get("3. Last Refreshed")
if last_date:
return datetime.strptime(last_date, "%Y-%m-%d")
except Exception as e:
print(f"文件读取错了:{e}")
return None
def get_daily_price(SYMBOL: str):
"""核心:爬取ETF日线数据,支持增量更新"""
last_date = get_last_refreshed_date(SYMBOL)
if last_date:
start_date = (last_date + timedelta(days=1)).strftime("%Y%m%d")
print(f"上次更到{last_date.strftime('%Y-%m-%d')},从{start_date}开始更")
else:
start_date = "20251101"
print(f"没历史数据,从{start_date}开始爬")
end_date = datetime.now().strftime("%Y%m%d")
print(f"爬取时间:{start_date} 到 {end_date}")
df = ak.fund_etf_hist_sina(symbol=add_sh_sz(SYMBOL))
print(f"爬到{df.shape[0]}条数据,包含开盘价/最高价/收盘价/成交量")
if df.empty:
print("没爬到新数据")
return
filename = f'./daily_prices_{SYMBOL}.json'
if last_date:
with open(filename, 'r', encoding='utf-8') as f:
old_data = json.load(f)
new_data = {}
for _, row in df.iterrows():
date_str = str(row['date'])
new_data[date_str] = {
"1. open": str(row['open']),
"2. high": str(row['high']),
"3. low": str(row['low']),
"4. close": str(row['close']),
"5. volume": str(row['volume'])
}
old_data["Time Series (Daily)"].update(new_data)
old_data["Meta Data"]["3. Last Refreshed"] = end_date
final_data = old_data
else:
final_data = {
"Meta Data": {
"1. 说明": "ETF日线数据(开盘/最高/最低/收盘/成交量)",
"2. 代码": SYMBOL,
"3. Last Refreshed": end_date,
"4. 时区": "Asia/Shanghai"
},
"Time Series (Daily)": {}
}
for _, row in df.iterrows():
date_str = str(row['date'])
final_data["Time Series (Daily)"][date_str] = {
"1. open": str(row['open']),
"2. high": str(row['high']),
"3. low": str(row['low']),
"4. close": str(row['close']),
"5. volume": str(row['volume'])
}
with open(filename, 'w', encoding='utf-8') as f:
json.dump(final_data, f, ensure_ascii=False, indent=4)
print(f"数据存好了:{filename}")
模块4:调用大模型生成交易指令
核心逻辑:把爬好的数据喂给Qwen3/DeepSeek,让模型根据行情给交易建议(买/卖/持仓):
def get_llm_trade_signal(SYMBOL: str):
"""用大模型分析数据,生成交易指令"""
# 读取本地数据
filename = f'./daily_prices_{SYMBOL}.json'
if not os.path.exists(filename):
print(f"没找到{SYMBOL}的数据,先爬数据!")
return
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
# 取最近10天的行情(给模型的上下文不用太多)
recent_dates = sorted(data["Time Series (Daily)"].keys())[-10:]
recent_data = {date: data["Time Series (Daily)"][date] for date in recent_dates}
# 构造提示词(关键:明确告诉模型要做什么)
prompt = f"""
你是专业ETF交易分析师,基于以下{SYMBOL}的最近10天行情数据,结合沪深300基准,给出交易建议:
数据:{recent_data}
要求:1. 输出"买入"/"卖出"/"持仓观望";2. 简单说明理由(不超过50字);3. 不用专业术语。
"""
# 调用Qwen3(这里用伪代码,实际需对接大模型API)
# 实际部署可参考通义千问/DeepSeek的官方SDK
from openai import OpenAI # 示例,需替换为对应大模型的SDK
client = OpenAI(base_url="你的大模型地址", api_key=os.getenv("LLM_API_KEY"))
response = client.chat.completions.create(
model="qwen3",
messages=[{"role": "user", "content": prompt}]
)
signal = response.choices[0].message.content
print(f"\n{SYMBOL}的交易建议:{signal}")
return signal
# 主函数:遍历所有ETF,爬数据+要交易指令
if __name__ == "__main__":
for symbol in all_zh_symbols:
print(f"\n===== 处理ETF:{symbol} =====")
get_daily_price(symbol) # 爬数据
get_llm_trade_signal(symbol) # 要交易指令
实测效果:大模型真的会“炒股”吗?
跑起程序后,两个大模型的表现很有意思,直接上结果:
1. 交易指令差异明显
● Qwen3:反应灵活,有明确交易记录。比如看到黄金ETF连续3天上涨,给出“持仓观望,短期涨幅大需警惕回调”;标普500ETF下跌2%时,建议“小仓位买入,分散风险”。
● DeepSeek:偏保守,全程持仓不动。理由是“当前ETF波动在合理范围,无明确买卖信号,避免频繁交易”。
👉 后续计划:拉长回测时间到3个月,增加5只A股ETF,看DeepSeek是否会触发交易信号。
2. Web可视化看收益(新手也能懂)
运行Web服务就能看直观的收益曲线,步骤超简单:
cd docs
python -m http.server 8000
打开http://localhost:8000,就能看到:
● 📈 收益曲线:Qwen3的模拟收益 vs 沪深300基准,涨跌幅一目了然;
● 📊 持仓分析:每只ETF的持仓占比、买入时间、浮盈浮亏;
● 💬 对话记录:大模型给出交易建议的完整逻辑,方便复盘。
(附实测截图:Qwen3模拟收益跑赢沪深300约1.2%,当然这只是短期回测,不代表真实收益)
未来升级计划:从ETF到股票,从日线到分钟线
这个项目只是雏形,后续这3个方向会重点升级,代码已预留接口:
1. 支持股票交易:把all_zh_symbols换成股票代码(比如贵州茅台600519),提前爬取股票数据即可,逻辑完全复用。
2. 加技术指标:引入MACD、RSI、布林带等,给大模型更丰富的分析依据。比如当RSI>70时,模型会自动识别“超买信号”。
3. 多周期数据:现在是日线,后续加分钟线(适合短线)、周线(适合长线),满足不同交易风格。
最后:为什么普通人要学AI+金融?
不是说要靠AI炒股赚钱,而是在AGI时代,“AI+专业领域”的能力已经成了职场护城河:
我身边做金融的同事,用AI自动爬取研报、生成分析报告,效率比以前高3倍;做量化的朋友,用大模型优化交易策略,省去了大量调参时间。
这个炒股项目,本质是帮你练手“大模型+数据处理+行业落地”的完整能力——就算不做金融,这套逻辑套到电商、教育等领域也同样适用。