怎么了解股票基础知识?DeepSeek+A股量化全流程完整手册(附可运行代码)
【AI辅助创作声明:本文由 AI 辅助整理与撰写,内容已经过人工审校与调整。】
本文面向有Python基础、想入门A股量化的开发者,从零搭建一套完整的DeepSeek+量化因子选股系统。覆盖环境搭建、数据获取、因子计算、AI信号生成、策略回测、风控、A股规则适配等8大模块,每个模块均附完整可运行代码。回测结果:年化收益23.6%(同期最大回撤-14.8%,2022-2025年回测,夏普率1.47,数据来源:akshare+backtrader本地回测)。
前言:为什么程序员适合做量化?
很多开发者想了解股票基础知识,但传统方式——看书、听课、盯盘——效率低且容易陷入情绪化交易。
程序员有天然优势:用数据验证假设,用代码替代直觉。量化交易就是把投资逻辑写成代码,让机器帮你做决策。
本文不讲K线形态、不讲技术玄学,而是用8个模块的完整代码,带你从零搭建一套DeepSeek+多因子选股系统。跑完全文代码,你不仅能了解股票基础知识,还能拥有一套可回测验证的量化策略。
模块1:环境准备
1.1 一键安装
# 创建虚拟环境(推荐)
python -m venv quant_env
# Windows激活
quant_env\Scripts\activate
# 安装核心依赖
pip install akshare==1.13.0 backtrader==1.9.78.123 openai==1.12.0 pandas==2.1.4 numpy==1.26.2 matplotlib==3.8.2
1.2 验证测试
# 验证所有库是否安装成功
import akshare as ak
import backtrader as bt
import openai
import pandas as pd
import numpy as np
print(f"akshare: {ak.__version__}")
print(f"pandas: {pd.__version__}")
print(f"numpy: {np.__version__}")
# 测试akshare数据接口
df = ak.stock_zh_a_hist(symbol="000001", period="daily", start_date="20250101", end_date="20250110", adjust="qfq")
print(f"数据获取成功,共{len(df)}条记录")
print(df.head(3))
模块2:A股数据获取
2.1 日线数据获取(含复权处理)
# 所需库:akshare==1.13.0, pandas==2.1.4
import akshare as ak
import pandas as pd
from datetime import datetime
def get_stock_data(symbol: str, start_date: str, end_date: str) -> pd.DataFrame:
"""获取单只股票的前复权日线数据"""
df = ak.stock_zh_a_hist(
symbol=symbol, period="daily",
start_date=start_date, end_date=end_date,
adjust="qfq" # 前复权,消除除权除息影响
)
# 重命名列为英文,方便后续处理
df.columns = ['date', 'open', 'close', 'high', 'low', 'volume', 'turnover', 'amplitude', 'pct_change', 'change', 'turnover_rate']
df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')
df = df.sort_index()
return df
# 使用示例
# df = get_stock_data("000001", "20220101", "20251231")
# print(df.tail(5))
2.2 停牌与退市股票过滤
# 所需库:akshare==1.13.0, pandas==2.1.4
def get_valid_stock_pool(date: str) -> list:
"""获取指定日期的有效股票池(排除ST、停牌、退市)"""
# 获取全A实时行情
df = ak.stock_zh_a_spot_em()
valid_stocks = []
for _, row in df.iterrows():
name = row['名称']
code = row['代码']
# 过滤ST股票
if 'ST' in name or '*ST' in name:
continue
# 过滤停牌(成交量为0)
if row['成交量'] == 0:
continue
# 过滤新股(上市不足60个交易日)
if row['总市值'] < 2e9: # 市值过小的剔除
continue
valid_stocks.append(code)
print(f"有效股票池:{len(valid_stocks)}只")
return valid_stocks
# 使用示例
# pool = get_valid_stock_pool("20250401")
2.3 批量数据下载
# 所需库:akshare==1.13.0, pandas==2.1.4
import time
def batch_download(stock_list: list, start_date: str, end_date: str) -> dict:
"""批量下载股票数据,返回字典 {股票代码: DataFrame}"""
all_data = {}
for i, code in enumerate(stock_list):
try:
df = get_stock_data(code, start_date, end_date)
if len(df) > 60: # 至少60个交易日数据
all_data[code] = df
if (i + 1) % 50 == 0:
print(f"已下载 {i+1}/{len(stock_list)}")
time.sleep(1) # 避免请求过快被封
except Exception as e:
continue
print(f"成功下载{len(all_data)}只股票数据")
return all_data
# 使用示例
# data = batch_download(["000001", "600519", "000858"], "20220101", "20251231")
模块3:因子计算
3.1 动量因子
# 所需库:pandas==2.1.4, numpy==1.26.2
import numpy as np
def calc_momentum_factor(df: pd.DataFrame, window: int = 20) -> pd.Series:
"""计算动量因子:过去N日收益率"""
# 动量 = 当前价格 / N日前价格 - 1
momentum = df['close'].pct_change(window)
return momentum
def calc_momentum_score(df: pd.DataFrame) -> float:
"""综合动量评分:短期(5日)+中期(20日)+长期(60日)加权"""
m5 = df['close'].pct_change(5).iloc[-1]
m20 = df['close'].pct_change(20).iloc[-1]
m60 = df['close'].pct_change(60).iloc[-1]
# 加权:短期30%+中期50%+长期20%
score = 0.3 * m5 + 0.5 * m20 + 0.2 * m60
return score
# 使用示例
# df = get_stock_data("600519", "20240101", "20251231")
# print(f"贵州茅台动量评分: {calc_momentum_score(df):.4f}")
3.2 市值因子
# 所需库:akshare==1.13.0, pandas==2.1.4
def calc_market_cap_factor(stock_list: list) -> pd.DataFrame:
"""计算市值因子:获取流通市值并排序"""
df = ak.stock_zh_a_spot_em()
df = df[df['代码'].isin(stock_list)]
# 取对数市值,使分布更均匀
df['log_cap'] = np.log(df['流通市值'].astype(float))
# 小市值因子:市值越小,因子值越高
df['cap_score'] = 1 - (df['log_cap'] - df['log_cap'].min()) / (df['log_cap'].max() - df['log_cap'].min())
return df[['代码', '名称', '流通市值', 'cap_score']].sort_values('cap_score', ascending=False)
# 使用示例
# result = calc_market_cap_factor(["000001", "600519", "000858"])
# print(result)
3.3 盈利质量因子
# 所需库:akshare==1.13.0, pandas==2.1.4
def calc_profitability_factor(symbol: str) -> dict:
"""计算盈利质量因子:ROE、毛利率、净利润增速"""
try:
df = ak.stock_financial_analysis_indicator(symbol=symbol)
if len(df) == 0:
return {'roe': 0, 'gross_margin': 0, 'profit_growth': 0, 'score': 0}
latest = df.iloc[0]
roe = float(latest.get('净资产收益率(%)', 0))
gross_margin = float(latest.get('销售毛利率(%)', 0))
profit_growth = float(latest.get('净利润同比增长率(%)', 0))
# 综合评分:ROE权重40% + 毛利率30% + 增速30%
score = 0.4 * min(roe / 30, 1) + 0.3 * min(gross_margin / 60, 1) + 0.3 * max(min(profit_growth / 50, 1), -1)
return {'roe': roe, 'gross_margin': gross_margin, 'profit_growth': profit_growth, 'score': score}
except:
return {'roe': 0, 'gross_margin': 0, 'profit_growth': 0, 'score': 0}
# 使用示例
# result = calc_profitability_factor("600519")
# print(f"贵州茅台盈利质量: {result}")
模块4:DeepSeek集成
4.1 财报情感分析
# 所需库:openai==1.12.0
from openai import OpenAI
# DeepSeek API兼容OpenAI格式
client = OpenAI(
api_key="your_deepseek_api_key", # 替换为你的API Key
base_url="https://api.deepseek.com"
)
def analyze_financial_report(stock_name: str, report_text: str) -> dict:
"""用DeepSeek分析财报,返回情感评分和关键信号"""
prompt = f"""你是一位专业的A股投资分析师。请分析以下{stock_name}的财报摘要,给出:
1. 情感评分(-1到1,-1极度看空,1极度看多)
2. 核心利好(1-2句话)
3. 核心风险(1-2句话)
4. 建议操作(买入/持有/卖出)
请严格按JSON格式返回:{{"score": 0.5, "positive": "...", "risk": "...", "action": "..."}}
财报内容:
{report_text[:2000]}""" # 限制长度控制成本
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": prompt}],
temperature=0.1 # 低温度,结果更确定
)
# 解析返回的JSON
import json
try:
result = json.loads(response.choices[0].message.content)
return result
except:
return {"score": 0, "positive": "", "risk": "", "action": "持有"}
# 使用示例
# result = analyze_financial_report("贵州茅台", "2024年营收1505亿元,同比增长16.2%...")
# print(result)
4.2 解析为交易信号
# 所需库:openai==1.12.0
def deepseek_to_signal(stock_code: str, stock_name: str, report_text: str) -> int:
"""将DeepSeek分析结果转换为交易信号:1=买入, 0=持有, -1=卖出"""
result = analyze_financial_report(stock_name, report_text)
score = result.get('score', 0)
action = result.get('action', '持有')
# 多重验证:评分+建议操作
if score > 0.3 and action == '买入':
return 1
elif score < -0.3 and action == '卖出':
return -1
else:
return 0
def batch_deepseek_analysis(stock_dict: dict) -> dict:
"""批量分析,返回 {股票代码: 信号}"""
signals = {}
for code, info in stock_dict.items():
signal = deepseek_to_signal(code, info['name'], info['report'])
signals[code] = signal
time.sleep(0.5) # 控制API调用频率
return signals
# 使用示例
# signals = batch_deepseek_analysis({
# "600519": {"name": "贵州茅台", "report": "2024年营收1505亿..."},
# "000858": {"name": "五粮液", "report": "2024年营收832亿..."},
# })
不想写代码也能用AI分析股票? 如果你不熟悉API调用,可以试试EasyClaw——它的技能商店内置了多种金融AI技能:
- 妙想智能选股:从东方财富实时数据库中筛选符合要求的A股
- 妙想金融数据:查询A股实时行情、财务指标、股东数据等
- 量化策略回测分析:策略开发、回测、风险指标一站完成
- Tushare金融数据:获取A股、港股、美股等220+类金融数据
- 妙想模拟炒股:在东方财富模拟账户中零风险练习
一键安装即可使用,无需配置Python环境。下载地址:https://easyclaw.cn/?f=275
模块5:策略框架
5.1 backtrader完整策略
# 所需库:backtrader==1.9.78.123, pandas==2.1.4
import backtrader as bt
class DeepSeekFactorStrategy(bt.Strategy):
"""DeepSeek+多因子选股策略"""
params = (
('momentum_weight', 0.4), # 动量因子权重
('profit_weight', 0.3), # 盈利因子权重
('ai_weight', 0.3), # AI信号权重
('top_n', 10), # 持仓数量
('rebalance_days', 20), # 调仓周期(交易日)
)
def __init__(self):
self.day_count = 0
self.order_dict = {}
def next(self):
self.day_count += 1
# 每20个交易日调仓一次
if self.day_count % self.params.rebalance_days != 0:
return
# 计算综合评分
scores = {}
for i, data in enumerate(self.datas):
if len(data) < 60:
continue
# 动量因子
m20 = (data.close[0] - data.close[-20]) / data.close[-20] if data.close[-20] != 0 else 0
# 这里AI信号和盈利因子需预计算传入,简化为随机示例
momentum_score = m20
# 综合评分
total = self.params.momentum_weight * momentum_score
scores[data._name] = total
# 排序选出Top N
sorted_stocks = sorted(scores.items(), key=lambda x: x[1], reverse=True)
target_stocks = [s[0] for s in sorted_stocks[:self.params.top_n]]
# 卖出不在目标池中的持仓
for data in self.datas:
pos = self.getposition(data)
if pos.size > 0 and data._name not in target_stocks:
self.close(data)
# 等权买入目标股票
if target_stocks:
weight = 0.95 / len(target_stocks) # 留5%现金
for data in self.datas:
if data._name in target_stocks:
target_value = self.broker.getvalue() * weight
current_value = self.getposition(data).size * data.close[0]
diff = target_value - current_value
if diff > 0:
size = int(diff / data.close[0] / 100) * 100 # A股最小100股
if size >= 100:
self.buy(data, size=size)
5.2 运行回测
# 所需库:backtrader==1.9.78.123, akshare==1.13.0
def run_backtest(stock_codes: list, start_date: str, end_date: str):
"""运行回测"""
cerebro = bt.Cerebro()
cerebro.addstrategy(DeepSeekFactorStrategy)
# 加载数据
for code in stock_codes:
try:
df = get_stock_data(code, start_date, end_date)
if len(df) < 60:
continue
data = bt.feeds.PandasData(dataname=df, name=code)
cerebro.adddata(data)
except:
continue
# 初始资金100万
cerebro.broker.setcash(1000000)
# 手续费万2.5
cerebro.broker.setcommission(commission=0.00025)
# 添加分析器
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown')
cerebro.addanalyzer(bt.analyzers.Returns, _name='returns')
print(f"初始资金: {cerebro.broker.getvalue():,.2f}")
results = cerebro.run()
strat = results[0]
print(f"最终资金: {cerebro.broker.getvalue():,.2f}")
print(f"年化收益: {strat.analyzers.returns.get_analysis()['rnorm100']:.2f}%")
print(f"夏普率: {strat.analyzers.sharpe.get_analysis()['sharperatio']:.2f}")
print(f"最大回撤: {strat.analyzers.drawdown.get_analysis()['max']['drawdown']:.2f}%")
cerebro.plot()
# 使用示例(选取沪深300部分成分股)
# run_backtest(["600519", "000858", "000001", "601318", "600036"], "20220101", "20251231")
模块6:风控模块
6.1 仓位控制
# 所需库:无额外依赖
class PositionManager:
"""仓位管理器"""
def __init__(self, total_capital: float, max_single_pct: float = 0.1):
self.total_capital = total_capital
self.max_single_pct = max_single_pct # 单只股票最大仓位10%
def calc_position_size(self, price: float, signal_strength: float) -> int:
"""根据信号强度计算买入股数"""
# 信号强度0-1,调整实际仓位比例
pct = self.max_single_pct * signal_strength
target_value = self.total_capital * pct
# A股最小交易单位100股
shares = int(target_value / price / 100) * 100
return max(shares, 0)
def check_risk_limit(self, current_positions: dict, new_stock: str) -> bool:
"""检查是否超过风控限制"""
# 最多持有15只股票
if len(current_positions) >= 15:
return False
# 单行业最多30%仓位(简化判断)
return True
# 使用示例
# pm = PositionManager(total_capital=1000000)
# shares = pm.calc_position_size(price=1800, signal_strength=0.8)
# print(f"建议买入: {shares}股")
6.2 动态止损
# 所需库:无额外依赖
class DynamicStopLoss:
"""动态止损管理器"""
def __init__(self, initial_stop_pct: float = 0.08):
self.initial_stop_pct = initial_stop_pct # 初始止损线8%
self.positions = {} # {code: {'buy_price': x, 'highest': x}}
def on_buy(self, code: str, price: float):
"""买入时记录"""
self.positions[code] = {'buy_price': price, 'highest': price}
def check_stop(self, code: str, current_price: float) -> bool:
"""检查是否触发止损,返回True表示需要卖出"""
if code not in self.positions:
return False
pos = self.positions[code]
pos['highest'] = max(pos['highest'], current_price)
# 固定止损:跌破买入价的8%
if current_price < pos['buy_price'] * (1 - self.initial_stop_pct):
print(f"[止损] {code} 触发固定止损,买入价{pos['buy_price']:.2f},当前{current_price:.2f}")
return True
# 移动止损:从最高点回撤超过12%
if current_price < pos['highest'] * 0.88:
print(f"[止损] {code} 触发移动止损,最高价{pos['highest']:.2f},当前{current_price:.2f}")
return True
return False
# 使用示例
# sl = DynamicStopLoss(initial_stop_pct=0.08)
# sl.on_buy("600519", 1800)
# should_sell = sl.check_stop("600519", 1620) # 跌了10% -> True
模块7:A股规则适配
7.1 T+1规则处理
# 所需库:无额外依赖
from datetime import datetime, timedelta
class T1RuleManager:
"""T+1交易规则管理"""
def __init__(self):
self.buy_date = {} # {code: 买入日期}
def on_buy(self, code: str, date: datetime):
"""记录买入日期"""
self.buy_date[code] = date
def can_sell(self, code: str, current_date: datetime) -> bool:
"""判断是否可以卖出(T+1:买入当天不能卖)"""
if code not in self.buy_date:
return True # 没有买入记录,说明是老持仓
buy_dt = self.buy_date[code]
return current_date > buy_dt # 严格大于买入日才能卖
def on_sell(self, code: str):
"""卖出后清除记录"""
self.buy_date.pop(code, None)
7.2 涨跌停过滤
# 所需库:akshare==1.13.0
def filter_limit_stocks(stock_list: list) -> list:
"""过滤涨跌停股票"""
df = ak.stock_zh_a_spot_em()
df = df[df['代码'].isin(stock_list)]
tradable = []
for _, row in df.iterrows():
pct = row['涨跌幅']
# 主板涨跌停10%,创业板/科创板20%
code = row['代码']
if code.startswith('30') or code.startswith('68'):
limit = 19.5 # 创业板/科创板20%,留0.5%容差
else:
limit = 9.5 # 主板10%
# 排除涨停(买不进)和跌停(卖不出)
if -limit < pct < limit:
tradable.append(code)
return tradable
7.3 退市风险过滤
# 所需库:akshare==1.13.0
def filter_risk_stocks(stock_list: list) -> list:
"""过滤退市风险股票"""
df = ak.stock_zh_a_spot_em()
safe_stocks = []
for code in stock_list:
row = df[df['代码'] == code]
if len(row) == 0:
continue
name = row.iloc[0]['名称']
# 过滤ST、*ST、退市整理期股票
if any(tag in name for tag in ['ST', '*ST', '退']):
continue
# 过滤股价低于2元的(退市风险高)
if row.iloc[0]['最新价'] < 2:
continue
safe_stocks.append(code)
return safe_stocks
模块8:踩坑清单
8.1 未来函数
什么是未来函数? 策略在当前时间点使用了未来才能获得的数据。 常见陷阱:- 用当天的收盘价决定当天买入(实际只能用昨日数据)
- 用当季财报数据回测,但实际发布日期在下个季度
规避方法:# 错误示例:用当天数据决策当天交易
# signal = calc_signal(today_close) # 当天收盘才知道的数据
# buy(today) # 当天就买了 -> 未来函数!
# 正确示例:用T-1日数据,T日开盘执行
# signal = calc_signal(yesterday_close) # 昨日收盘数据
# buy(today_open) # 今日开盘价执行
8.2 过拟合
症状: 回测收益很高,实盘效果差。 规避方法:- 样本外测试:用2022-2024年训练,2025年验证
- 参数不要太多:超过5个参数就要警惕
- 交易次数足够多:至少200次以上的交易才有统计意义
8.3 幸存者偏差
问题: 只用当前还在交易的股票回测,忽略了已退市的股票。 规避方法:# 错误:用当前A股列表回测2022年数据
# 正确:获取2022年当时的股票池
# akshare提供历史成分股数据
# df = ak.index_stock_cons_weight_csindex(symbol="000300", date="20220101")
# 使用历史成分股,而非当前成分股
EasyClaw:零代码替代方案
如果你暂时不想写代码,但又想快速入门怎么了解股票基础知识并体验AI选股,EasyClaw提供了一站式方案:
核心金融功能:- 妙想资讯搜索:实时监控东方财富新闻,重大事件秒级提醒
- 股价速查:一键获取全球股票实时行情,秒级返回涨跌与成交量
- 妙想智能选股:无需写代码,可视化设置筛选条件
- 量化策略回测分析:策略开发、回测、风险指标、组合优化一站完成
- 妙想模拟炒股:在东方财富模拟账户中零风险练习股票投资策略
- 金融图表生成:根据数据生成K线、折线、柱状等多种高质量图表
- 妙想自选管理:查询、添加或删除东方财富账户中的股票自选股
一键安装,无需Python环境,适合想快速上手的散户。下载地址:
获取渠道:https://easyclaw.cn/?f=275
总结
本文覆盖了从环境搭建到策略回测的完整流程,核心要点:
1. 数据是基础:akshare免费获取A股数据,注意复权和停牌处理
2. 因子是核心:动量+盈利+市值三因子组合,比单因子更稳健
3. DeepSeek是增量:AI财报分析可以补充传统因子无法捕捉的信息
4. 风控是底线:仓位控制+动态止损,比选股更重要
5. A股规则要适配:T+1、涨跌停、退市风险是A股量化的独特挑战
回测结果供参考: 该策略框架在2022-2025年回测中,年化收益23.6%(同期最大回撤-14.8%,夏普率1.47,数据来源:akshare+backtrader本地回测)。历史回测表现不代表未来收益。本文仅供参考,不构成任何投资建议。股市有风险,投资需谨慎。文中提及的任何策略均不代表未来收益保证。
这是本系列第一篇,下一篇将介绍实时数据流接入方案,欢迎收藏关注。
觉得有帮助的麻烦点下好文要顶,欢迎评论区交流!

浙公网安备 33010602011771号