Python量化交易系统实战--设计交易策略:选股策略
作者:麦克煎蛋 出处:https://www.cnblogs.com/mazhiyong/ 转载请保留这段声明,谢谢!
这一节主要是了解基于“动量因子”的选股策略。
动量因子指的是股票在一段周期内的涨跌幅度 ,其本质是追涨杀跌。而选股策略,指的是基于这个因子的表现进行股票筛选,以及买入、卖出的操作。
该文章的策略和方法非常简单。仅适用于入门了解。
一、筛选股票池
考虑到成交活跃以及买入卖出的顺畅,这里选择的是沪深300持有个股。
def get_index_list(index_symbol='000300.XSHG'): """ 获取指数成分股,指数代码查询:https://www.joinquant.com/indexData :param index_symbol: 指数的代码,默认沪深300 :return: list,成分股代码 """ stocks = get_index_stocks(index_symbol, '2023-01-09') return stocks
def get_data(start_date, end_date, use_cols, index_symbol='000300.XSHG'): """ 获取股票收盘价数据,并拼接为一个df :param start_date: str :param end_date: str :param use_cols: list :param index_symbol: str :return data_concat: df,拼接后的数据表 """ # 获取股票列表代码:沪深300持有个股、创业板、上证 stocks = st.get_index_list(index_symbol) # 拼接收盘价数据 data_concat = pd.DataFrame() # 获取股票数据,这里为了测试方便取前10条 for code in stocks[0:10]: data = st.get_csv_price(code, start_date, end_date, use_cols) return data
二、计算动量因子
1、计算策略
① 确定交易对象:股票池、考虑流动性(沪深300、创业板) ② 选定业绩评价周期:过去1~12个月 ③ 计算形成期收益率:过去N个月的收益率 ---> 生成交易信号 ④ 对收益率进行排序:最佳~赢家组合、最差~输家组合 ⑤ 确定持仓/换仓周期: 1个月、可自定义测算 ⑥ 连续或间隔一-段时期 ,不断重复②- -⑤行为 ⑦ 计算动量/反向策略各持有期的回报率 ⑧ 计算t/p统计值,判断是否存在动量效应
2、数据源
拼接股票池的数据为一张大表:
def get_data(start_date, end_date, use_cols, index_symbol='000300.XSHG'): """ 获取股票收盘价数据,并拼接为一个df :param start_date: str :param end_date: str :param use_cols: list :param index_symbol: str :return data_concat: df,拼接后的数据表 """ # 获取股票列表代码:沪深300持有个股、创业板、上证 stocks = st.get_index_list(index_symbol) # 拼接收盘价数据 data_concat = pd.DataFrame() # 获取股票数据,这里为了测试方便取前10条 for code in stocks[0:10]: data = st.get_csv_price(code, start_date, end_date, use_cols) # 拼接多个股票的收盘价:日期 股票A收盘价 股票B收盘价 ... data.columns = [code] data_concat = pd.concat([data_concat, data], axis=1) # 预览股票数据 # print(data_concat.tail()) return data_concat
3、具体计算过程
- 按月计算收益率。
- 根据收益率生成交易信号(这里的策略简化为买入排名靠前的,卖出排名靠后的)。
- 根据交易信号计算投资组合收益率。
- 评估策略结果。
def momentum(data_concat, shift_n=1, top_n=4): """ :param data_concat: df :param shift_n: int,表示业绩统计周期(单位:月) :return: """ # 转换时间频率:日->月 data_concat.index = pd.to_datetime(data_concat.index) data_month = data_concat.resample('ME').last() # 计算过去N个月的收益率 = 期末值/期初值 - 1 =(期末-期初)/ 期初 shift_return = data_month / data_month.shift(shift_n) - 1 # print(shift_return.head()) # print(shift_return.shift(-1)) # 生成交易信号:收益率排前n的>赢家组合>买入1,排最后n个>输家>卖出-1 buy_signal = get_top_stocks(shift_return, top_n) sell_signal = get_top_stocks(-1 * shift_return, top_n) signal = buy_signal - sell_signal # print(signal.head()) # 计算投资组合收益率 returns = base.caculate_portfolio_return(shift_return, signal, top_n * 2) print(returns.head()) # 评估策略效果:总收益率、年化收益率、最大回撤、夏普比 returns = base.evaluate_strategy(returns) # 数据预览 # print(data_month.head()) return returns
关键函数:
def caculate_portfolio_return(data, signal, n): """ 计算组合收益率 :param data: dataframe :param signal: dataframe :param n: int :return returns: dataframe """ returns = data.copy() # 投组收益率(等权重)= 收益率之和 / 股票个数 # 信号发出的指令是针对的下一个月的指令,所以数据要后移 returns['profit_pct'] = (signal * returns.shift(-1)).T.sum() / n returns = calculate_cum_prof(returns) return returns.shift(1) # 匹配对应的交易月份
策略评估函数:
def evaluate_strategy(data): """ 评估策略收益表现 :param data: dataframe, 包含单次收益率数据 :return results: dict, 评估指标数据 """ # 评估策略效果:总收益率、年化收益率、最大回撤、夏普比 data = calculate_cum_prof(data) # 获取总收益率 total_return = data['cum_profit'].iloc[-1] # 计算年化收益率(每月开仓) annual_return = data['profit_pct'].mean() * 12 # 计算近一年最大回撤 data = caculate_max_drawdown(data, window=12) # print(data) # 获取近一年最大回撤 max_drawdown = data['max_dd'].iloc[-1] # 计算夏普比率 sharpe, annual_sharpe = calculate_sharpe(data) # 放到dict中 results = {'总收益率': total_return, '年化收益率': annual_return, '最大回撤': max_drawdown, '夏普比率': annual_sharpe} # 打印评估指标 for key, value in results.items(): print(key, value) return data