1. 项目背景与核心功能
在股票量化交易领域,移动平均线(MA)交叉策略是最基础也最经典的技术分析方法之一。其中5日均线上穿10日均线(简称金叉)常被视为短期买入信号,而5日均线下穿10日均线(死叉)则被视为卖出信号。这个Python项目实现了一个实时监控A股市场所有股票MA5/MA10金叉情况的自动化工具。
核心功能架构分为四个模块:
- 数据获取层:通过Tushare金融数据接口获取实时股票行情
- 指标计算层:计算每只股票的5日和10日移动平均线
- 信号检测层:识别MA5上穿MA10的技术形态
- 输出展示层:将符合条件的股票及其关键指标输出展示
注意:实际交易中不应单独依赖MA交叉信号,建议结合成交量、MACD等其他指标综合判断。本程序仅作技术演示用途。
2. 环境配置与依赖安装
2.1 基础环境要求
- Python 3.7+(建议3.8+以获得更好性能)
- Tushare Pro账号(免费版即可满足基础需求)
- 稳定的网络连接(需实时获取行情数据)
2.2 依赖库安装
bash复制pip install tushare pandas numpy schedule
各库作用说明:
tushare:获取A股行情数据的核心库pandas:数据处理与分析numpy:数值计算支持schedule:定时任务调度
2.3 Tushare Token配置
- 注册Tushare Pro账号(官网)
- 获取API Token
- 在代码中配置:
python复制import tushare as ts
ts.set_token('你的Token') # 替换为实际Token
pro = ts.pro_api()
3. 核心代码实现解析
3.1 数据获取模块
python复制def get_stock_list():
"""获取全量A股列表"""
df = pro.stock_basic(exchange='', list_status='L')
return df[df['ts_code'].str.endswith(('.SH', '.SZ'))]['ts_code'].tolist()
def get_hourly_kline(ts_code, hours=240):
"""获取个股60分钟K线数据"""
try:
df = ts.pro_bar(
ts_code=ts_code,
freq='60min',
adj='qfq',
limit=hours
)
return df.sort_values('trade_time')
except Exception as e:
print(f"获取{ts_code}数据失败: {str(e)}")
return None
关键参数说明:
freq='60min':指定60分钟级别K线adj='qfq':前复权处理limit=240:获取最近240根K线(约10个交易日)
3.2 指标计算模块
python复制def calculate_ma(df):
"""计算移动平均线"""
if df is None or len(df) < 20: # 至少需要20根K线
return None
df['MA5'] = df['close'].rolling(5).mean()
df['MA10'] = df['close'].rolling(10).mean()
df = df.dropna() # 去除前9个无MA10的数据点
# 计算金叉信号
df['signal'] = 0
df.loc[(df['MA5'] > df['MA10']) &
(df['MA5'].shift(1) <= df['MA10'].shift(1)), 'signal'] = 1
return df
技术要点:
- 使用pandas的
rolling().mean()计算移动平均 - 金叉判定条件:当日MA5>MA10且前一日MA5≤MA10
- 需要足够的历史数据(至少20根K线)才能计算可靠指标
3.3 信号扫描模块
python复制def scan_cross_signal(stock_list, scan_all=False):
"""扫描金叉信号"""
results = []
for code in stock_list:
data = get_hourly_kline(code)
if data is None:
continue
df = calculate_ma(data)
if df is None:
continue
last_signal = df.iloc[-1]['signal']
if last_signal == 1 or scan_all:
results.append({
'ts_code': code,
'name': get_stock_name(code),
'price': df.iloc[-1]['close'],
'MA5': round(df.iloc[-1]['MA5'], 2),
'MA10': round(df.iloc[-1]['MA10'], 2),
'time': df.iloc[-1]['trade_time']
})
return pd.DataFrame(results)
优化点:
- 增加
scan_all参数控制是否输出全部股票数据 - 只处理有有效数据的股票
- 返回包含关键信息的结构化数据
4. 定时任务与主程序
4.1 定时扫描实现
python复制import schedule
import time as tm
def job():
print(f"\n{datetime.now().strftime('%Y-%m-%d %H:%M')} 开始扫描...")
stocks = get_stock_list()
results = scan_cross_signal(stocks)
if not results.empty:
print("\n发现金叉信号股票:")
print(results[['ts_code', 'name', 'price', 'MA5', 'MA10']])
else:
print("当前未发现金叉信号")
# 每4小时运行一次
schedule.every(4).hours.do(job)
while True:
schedule.run_pending()
tm.sleep(1)
4.2 程序启动方式
- 直接运行模式:
bash复制python ma_cross.py
- 带参数运行(示例):
bash复制python ma_cross.py --interval 2 --output result.csv
5. 实战优化与注意事项
5.1 性能优化建议
- 缓存股票列表:避免每次扫描都获取全量股票列表
python复制stock_cache = None
def get_cached_stocks():
global stock_cache
if stock_cache is None:
stock_cache = get_stock_list()
return stock_cache
- 并行处理:使用多线程加速扫描
python复制from concurrent.futures import ThreadPoolExecutor
def parallel_scan(stock_list):
with ThreadPoolExecutor(max_workers=8) as executor:
results = list(executor.map(process_stock, stock_list))
return [r for r in results if r is not None]
5.2 常见问题排查
-
数据获取失败:
- 检查Token是否有效
- 确认网络连接正常
- 查看Tushare官网状态
-
指标计算异常:
- 确保K线数据足够(≥20根)
- 检查是否有NaN值
- 验证复权方式是否正确
-
信号误判:
- 检查金叉判定逻辑
- 确认时间序列排序正确
- 增加信号确认机制(如连续2根K线确认)
5.3 生产环境建议
- 增加日志记录
python复制import logging
logging.basicConfig(
filename='ma_cross.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
- 添加邮件/钉钉通知
python复制def send_alert(results):
# 实现邮件或IM通知
pass
- 结合其他指标过滤信号
python复制def filter_signal(df):
# 增加成交量验证
vol_condition = df['vol'] > df['vol'].rolling(5).mean().iloc[-1]
# 增加MACD验证
# ...
return df[df['signal'] == 1 & vol_condition]
6. 策略扩展方向
-
多周期验证:
- 同时检查日线、60分钟线的MA交叉情况
- 增加周线级别的趋势判断
-
动态参数优化:
- 根据市场波动率自动调整MA周期
- 实现网格参数搜索
-
回测框架集成:
- 接入Backtrader等回测框架
- 计算历史胜率和盈亏比
-
风险控制模块:
- 添加止损逻辑
- 实现仓位动态调整
这个MA交叉监测系统虽然逻辑简单,但构成了量化交易系统的基础框架。在实际使用中,建议先进行充分的历史回测,再结合其他技术指标和基本面因素构建完整的交易策略。