示例,获取贵州茅台数据
核心思想与Python源码实现指南
在量化交易领域,威廉·欧奈儿(William J. O'Neil)的CAN SLIM投资体系因其“基本面+技术面”双轮驱动的独特逻辑,成为无数投资者追寻的“圣杯”,而将这套体系转化为可量化的交易指标,则是将其从理论落地的关键一步,本文将深入解析欧奈儿核心量化指标的设计思想,并基于Python提供源码实现,帮助交易者理解、复现并应用于实际策略。
欧奈儿量化指标的核心逻辑:从CAN SLIM到数字信号
欧奈儿的CAN SLIM体系包含7个核心维度:当季每股收益增长(C)、年度每股收益增长(A)、新产品、新管理层、新 highs(N)、供给与需求(S)、市场整体走向(I),最容易被量化且直接关联交易时机的,是“新高突破”与“相对强度”两大技术指标,这也是欧奈儿“在正确的时机买入强势股”思想的集中体现。
新高突破(New High, NH)
欧奈儿认为,股价创近期新高(如52周新高)是股票进入强势阶段的信号,意味着市场对其价值的认可,量化时需结合“成交量确认”——突破新高当日成交量需显著放大(如超过过去50日均量的1.5倍),避免“无量假突破”。
相对强度(Relative Strength, RS)
相对强度衡量个股相对于大盘(如沪深300、标普500)的走势强弱,欧奈儿常用“RS评级”(1-100分,越高越强),核心是计算一段时间内个股涨幅与指数涨幅的比值,通常要求RS评级≥80,即股票表现强于80%以上的其他股票。
Python源码实现:构建欧奈儿量化指标
基于上述逻辑,我们用Python实现“新高突破”和“相对强度”两大核心指标,并给出综合信号示例。
环境准备
import pandas as pd import numpy as np import akshare as ak # 用于获取股票数据(也可用tushare、yfinance等)
数据获取
以A股为例,获取某股票过去一年的日线数据及对应指数数据:
def get_stock_data(stock_code, index_code="000300.SH", period="daily"): """获取股票及指数数据""" # 获取股票数据(示例:贵州茅台,股票代码600519) stock_df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", start_date="20230101", end_date="20231231", adjust="qfq") stock_df = stock_df[['日期', '开盘', '收盘', '最高', '最低', '成交量']] stock_df.columns = ['date', 'open', 'close', 'high', 'low', 'volume'] stock_df['date'] = pd.to_datetime(stock_df['date']) stock_df = stock_df.sort_values('date').reset_index(drop=True) # 获取指数数据(沪深300) index_df = ak.stock_zh_index_hist(symbol=index_code, period="daily", start_date="20230101", end_date="20231231") index_df = index_df[['日期', '收盘']] index_df.columns = ['date', 'index_close'] index_df['date'] = pd.to_datetime(index_df['date']) # 合并数据 df = pd.merge(stock_df, index_df, on='date', how='left') return df stock_code = "600519" # 贵州茅台 df = get_stock_data(stock_code)
新高突破指标实现
def new_high_breakout(df, window=252, volume_ratio=1.5):
"""
计算新高突破信号
:param df: 包含股价数据的DataFrame
:param window: 新高周期(默认252个交易日≈1年)
:param volume_ratio: 成交量放大倍数阈值
:return: 包含新高信号的DataFrame
"""
# 计算52周最高价
df['high_window_max'] = df['high'].rolling(window=window, min_periods=1).max()
# 标记新高日(当日最高价=窗口内最高价)
df['is_new_high'] = (df['high'] == df['high_window_max']).astype(int)
# 计算日均成交量
df['avg_volume'] = df['volume'].rolling(window=50, min_periods=1).mean()
# 突破条件:当日最高价创52周新高 + 成交量放大1.5倍
df['breakout_signal'] = (df['is_new_high'] == 1) & (df['volume'] > volume_ratio * df['avg_volume'])
return df
df = new_high_breakout(df)
相对强度指标实现
def relative_strength(df, period=12):
"""
计算相对强度(RS)及RS评级
:param df: 包含股价及指数数据的DataFrame
:param period: 相对强度计算周期(默认12个月≈250个交易日,这里简化用12周≈60个交易日)
:return: 包含RS及RS评级的DataFrame
"""
# 计算个股及指数的周期涨跌幅
df['stock_return'] = df['close'].pct_change(periods=period*5) # 12周≈60个交易日
df['index_return'] = df['index_close'].pct_change(periods=period*5)
# 相对强度 = 个股涨跌幅 / 指数涨跌幅(避免除以0)
df['rs'] = np.where(df['index_return'] != 0, df['stock_return'] / df['index_return'], 1)
# 计算RS评级(将RS值映射到1-100分,取滚动分位数)
df['rs_percentile'] = df['rs'].rolling(window=252, min_periods=60).rank(pct=True) * 100
df['rs_rating'] = df['rs_percentile'].round(0).astype(int)
return df
df = relative_strength(df)
综合信号生成
欧奈儿理想的买入信号是:新高突破 + RS评级≥80 + 成交量确认。
def generate_oney_signals(df):
"""生成欧奈儿综合买入信号"""
df['oneil_signal'] = (df['breakout_signal'] == 1) & (df['rs_rating'] >= 80)
return df
df = generate_oney_signals(df)
# 输出信号日期
signal_dates = df[df['oneil_signal'] == 1]['date'].tolist()
print(f"欧奈儿买入信号触发日期:{signal_dates}")
指标应用与注意事项
指标应用场景
- 选股:通过扫描全市场股票,筛选出“新高突破+高RS评级”的标的,缩小观察范围。
- 择时:结合成交量确认的突破信号,作为买入触发点,避免追高。
- 止损:欧奈儿强调“亏损7%立即止损”,可在指标中设置止损线(如买入价下跌7%时卖出)。
关键注意事项
- 参数优化:
window(新高周期)、volume_ratio(成交量阈值)、period(RS计算周期)需根据市场风格调整,例如牛市可缩短周期,熊市需放大成交量确认。 - 市场环境适配:欧奈儿体系适用于趋势明显的市场,震荡市中“新高突破”易出现假信号,需结合大盘走势(I维度)过滤。
- 数据质量:高频数据(如分钟级)可能放大噪声,日线数据更符合欧奈儿原周期设计。
欧奈儿量化交易指标的精髓,是将“强者恒强”的市场哲学转化为可量化的数字信号,通过Python实现新高突破与相对强度指标,交易者不仅能理解其底层逻辑,还能根据自身需求优化参数,但需注意:没有“万能指标”,量化工具的核心是辅助决策,最终的成功仍需结合风险管理和持续的市场观察。
对于进阶用户,可进一步将上述指标嵌入策略回测框架(如backtrader、vn.py),或结合基本面数据(如当季收益增长)构建“CAN SLIM全维度量化模型”,让欧奈儿的投资智慧在数字时代焕发新生。
