目录
一、量化交易概述
1、量化交易(投资方法)
2、算法交易(自动交易、黑盒交易或机器交易)
3、量化策略
4、量化选股
5、股票回测
二、股票数据
三、股票数据分析
1、导入股票时间序列数据
2、绘制股票成交量的时间序列图
3、绘制股票收盘价和成交量的时间序列图
3、绘制K线图(蜡烛图)
(1)K线图理论
(2)K线图绘制
4、股票指标相关性分析
(1)相关关系分析
(2)相关系数(Correlation coefficient)分析
5、移动平均线
以先进的数学模型替代人为的主观判断,利用计算机技术从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略,极大地减少了投资者情绪波动的影响,避免在市场极度狂热或悲观的情况下作出非理性的投资决策。
量化交易一般会经过海量数据仿真测试和模拟操作等手段进行检验,并依据一定的风险管理算法进行仓位和资金配置,实现风险最小化和收益最大化,但往往也会存在一定的潜在风险。
通过设计算法,利用计算机程序发出交易指令的方法。在交易中,程序可以决定的范围包括交易时间的选择、交易的价格,甚至包括最后需要成交的资产数量。
使用计算机作为工具,通过一套固定的逻辑来分析、判断和决策。量化策略既可以自动执行,也可以人工执行。
一个完整的策略需要包含输入、策略处理逻辑、输出;策略处理逻辑需要考虑选股、择时、仓位管理和止盈止损等因素。
用量化的方法选择确定的投资组合,期望这样的投资组合可以获得超越大盘的投资收益。
常用的量化选股模型:多因子选股模型、行业轮动选股、风格轮动模型、资金流模型、动量反转模型、一致预期模型、趋势跟踪选股等。
将交易策略在历史数据中进行合理验证的过程。
股票回测的意义:策略筛选、策略优化、策略验证。
部分股票数据如下:
该支股票数据包含了开盘价、最高价、最低价、收盘价、成交量、市值、换手率、pe和pb这9种指标。
股票指标名称 |
指标含义 |
开盘价(open) |
每个交易日开市后的第一笔每股买卖成交价格 |
最高价(high) 最低价(low) |
最高价是好的卖出价格,最低价是好的买进价格,可根据价格极差判断股价的波动程度和是否超出常态范围 |
收盘价(close) |
最后一笔交易前一分钟所有交易的成交量加权平均价,无论当天股价如何振荡,最终将定格在收盘价上 |
成交量(volume) |
指一个时间单位内对某项交易成交的数量,可根据成交量的增加幅度或减少幅度来判断股票趋势,预测市场供求关系和活跃程度 |
市值(market value) |
市场价格总值,可以市值的增加幅度或减少幅度来衡量该种股票发行公司的经营状况 |
换手率(turnover) |
“换手率”也称“周转率”,指在一定时间内市场中股票转手买卖的频率,是反映股票流通性强弱的指标之一 |
pe |
市盈率, 股票价格除以每股盈利的比率,评估股价水平是否合理的指标之一,反应企业近期表现,可根据其大小判断投资回收期的长短和投资风险大小 |
pb |
市净率,股价除以账面价值,可衡量该种股票的投资价值和投资风险 |
from pandas import read_excel
## 读取excel文件,并将‘日期’列解析为日期时间格式,并设为索引
stock_data=read_excel('stock_data/600000.SH.xlsx',parse_dates=['日期'],index_col='日期')
stock_data.drop('交易日期', axis=1, inplace=True) #删除第二列’交易日期‘
stock_data.index.name='日期' #日期为索引列
#将数据按日期这一列排序(保证后续计算收益率的正确性)
stock_data=stock_data.sort_values(by='日期')
# 打印数据的前5行
print(stock_data.head())
要得到数据的更多信息,可以使用.info()
方法。它告诉我们该数据一共有1481行,索引是时间格式,日期从2013年1月4日到2019年3月14日。总共有9列,并列出了每一列的名称和数据格式,并且没有缺失值,其中pb为1434行,即末尾是缺失值。
print(stock_data.info())
绘制股票在2013年到2019年的日成交量的时间序列图。
以时间为横坐标,每日的成交量为纵坐标,做折线图,可以观察股票成交量随时间的变化情况。这里直接用DataFrame数据自带的作图工具(该工具能够快速做图,并自动优化图形输出形式)
import matplotlib.pyplot as plt
stock_data['成交量'].plot(grid=True,color='red',label='600000.SH')
plt.title('2013-2019 volume', fontsize='9')
plt.ylabel('volume', fontsize='8')
plt.xlabel('date', fontsize='8')
plt.legend(loc='best',fontsize='small')
plt.show()
结果为:
绘制股票在2016年3月份—2017年12月份的日收盘价和日成交量的时间序列图,因为它们的数值差异很大,所以采用两套纵坐标系来做图。
stock_data.index.name='date' #日期为索引列
#对股票数据的列名重新命名
stock_data.columns=['open','high','low','close','volume','market_value','turnover','pe','pb']
data=stock_data.loc['2016-02-15':'2017-12-29'] #获取某个时间段内的时间序列数据
data[['close','volume']].plot(secondary_y='volume',grid=True)
plt.title('2016-2017 close and volume', fontsize='9')
plt.show()
结果为:
绘制方法:首先我们找到该日或某一周期的最高和最低价,垂直地连成一条直线;然后再找出当日或某一周期的开市和收市价,把这二个价位连接成一条狭长的长方柱体。假如当日或某一周期的收市价较开市价为高(即低开高收),我们便以红色来表示,或是在柱体上留白,这种柱体就称之为"阳线"。如果当日或某一周期的收市价较开市价为低(即高开低收),我们则以绿色表示,又或是在住柱上涂黑色,这柱体就是"阴线"了。
表示意义:能够全面透彻地观察到市场的真正变化。我们从K线图中,既可看到股价(或大市)的趋势,也同时可以了解到每日市况的波动情形。
首先,安装 mpl_finance 模块(pip install mpl_finance)
使用mpl_finance 模块中的candlestick_ohlc() 函数绘制K线图。
下面定义了pandas_candlestick_ohlc()
函数来绘制适用于本文数据的K线图,其中大部分代码都是在设置坐标轴的格式。
绘制股票在2013年3月份每日的开盘价,最高价,最低价,收盘价的K线图。
import numpy as np
from mpl_finance import candlestick_ohlc
from matplotlib.dates import DateFormatter, WeekdayLocator, DayLocator, MONDAY,date2num
#定义绘制K线图的函数
def pandas_candlestick_ohlc(stock_data, otherseries=None):
# 设置绘图参数,主要是坐标轴
mondays = WeekdayLocator(MONDAY)
alldays = DayLocator()
dayFormatter = DateFormatter('%d')
fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2)
if stock_data.index[-1] - stock_data.index[0] < pd.Timedelta('730 days'):
weekFormatter = DateFormatter('%b %d')
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
else:
weekFormatter = DateFormatter('%b %d, %Y')
ax.xaxis.set_major_formatter(weekFormatter)
ax.grid(True)
# 创建K线图
stock_array = np.array(stock_data.reset_index()[['date','open','high','low','close']])
stock_array[:,0] = date2num(stock_array[:,0])
candlestick_ohlc(ax, stock_array, colorup = "red", colordown="green", width=0.6)
# 可同时绘制其他折线图
if otherseries is not None:
for each in otherseries:
plt.plot(stock_data[each], label=each)
plt.legend()
ax.xaxis_date()
ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
plt.show()
stock_data.index.name='date' #日期为索引列
#对股票数据的列名重新命名
stock_data.columns=['open','high','low','close','volume','market_value','turnover','pe','pb']
data=stock_data.loc['2016-02-15':'2016-03-31'] #获取某个时间段内的时间序列数据
pandas_candlestick_ohlc(data)
结果为:
该图红色代表上涨,绿色代表下跌。
下面挑选了部分代表性的指标,并使用pandas.scatter_matrix()
函数,将各项指标数据两两关联做散点图,对角线是每个指标数据的直方图。指标包括:成交量、市值、换手率、pe、pb。
from pandas.plotting import scatter_matrix
#换手率字符串类型转换为浮点型函数
def str_to_float(s):
s=s[:-1]
s_float=float(s)
return s_float
stock_data['换手率']=stock_data['换手率'].apply(str_to_float)#换手率字符串类型转换为浮点型
#对股票数据的列名重新命名
stock_data.columns=['open','high','low','close','volume','market_value','turnover','pe','pb']
data=stock_data.loc['2018-01-02':'2018-12-28'] #获取某个时间段内的时间序列数据
scatter_matrix(data[['volume','market_value','turnover','pe','pb']])
plt.show()
从图中可以明显发现成交量(volume)和换手率(turnover)有非常明显的线性关系;pe和pb有非常明显的线性关系;市值(marker_value)分别和pe、pb有非常明显的线性关系。所以我们可以将换手率、市值、pe这三个指标去除,这里使用了相关性关系来实现数据降维。
注意:相关表和相关图可反映两个变量之间的相互关系及其相关方向,但无法确切地表明两个变量之间相关的程度。
相关系数是用以反映变量之间相关关系密切程度的统计指标。
我们可以使用numpy.corrcof()
来直接计算各指标数据间的相关系数。
#换手率字符串类型转换为浮点型函数
def str_to_float(s):
s=s[:-1]
s_float=float(s)
return s_float
stock_data['换手率']=stock_data['换手率'].apply(str_to_float)#换手率字符串类型转换为浮点型
#对股票数据的列名重新命名
stock_data.columns=['open','high','low','close','volume','market_value','turnover','pe','pb']
data=stock_data.loc['2018-01-02':'2018-12-28'] #获取某个时间段内的时间序列数据
cov=np.corrcoef(data[['volume','market_value','turnover','pe','pb']].T)
print(cov)
结果为:
看数字还是不够方便,所以继续将上述相关系数矩阵转换成图形,使用matplotlib.pyplot.matshow() 将矩阵可视化。如下图所示,其中用颜色来代表相关系数。
cov=np.corrcoef(data[['volume','market_value','turnover','pe','pb']].T)
img=plt.matshow(cov)
plt.colorbar(img,ticks=[-1,0,1])
plt.show()
从图中可以看出,0和2的相关系数非常大,即成交量(volume)和转手率(turnover)强烈正相关,查看相关系数矩阵,数值为1;1、3和4相关系数非常大,即市值,pe和pe强烈正相关,查看相关系数矩阵,其数值为1。
相关性分析总结:用矩阵图表的方式分析多个指标或观察指标间的相关系数矩阵可以迅速找到了强相关的指标。
移动平均线(Moving Average,MA)是用统计分析的方法,将一定时期内的证券价格(指数)加以平均,并把不同时间的平均值连接起来,形成一根MA,用以观察证券价格变动趋势的一种技术指标。
使用股票数据中每日的收盘价,算出5日均价和20日均价,并将均价的折线图(也称移动平均线)与K线图画在一起。
选取该股票2013-03-11日——2016-05-31的数据进行模拟。
stock_data['close_mean5']=np.round(stock_data['close'].rolling(window=5,center=False).mean(),2)
stock_data['close_mean20']=np.round(stock_data['close'].rolling(window=20,center=False).mean(),2)
data=stock_data.loc['2016-03-11':'2016-05-31'] #获取某个时间段内的时间序列数据
pandas_candlestick_ohlc(data,['close_mean5','close_mean20'])
移动平均线具有抹平短期波动的作用,更能反映长期的走势。观察上图,比较5日均线和20日均线,特别是关注它们的交叉点,这些是交易的时机。移动平均线策略,最简单的方式就是:当5日均线从下方超越20日均线时,买入股票,当5日均线从上方越到20日均线之下时,卖出股票。
为了找出交易的时机,我们计算5日均价和20日均价的差值,并取其正负号,作于下图。当图中水平线出现跳跃的时候就是交易时机。
stock_data['close_m5-20']=stock_data['close_mean5']-stock_data['close_mean20']
stock_data['diff']=np.sign(stock_data['close_m5-20'])
data=stock_data.loc['2016-03-11':'2016-05-31'] #获取某个时间段内的时间序列数据
data['diff'].plot(ylim=(-2,2)).axhline(y=0,color='black',lw=2)
plt.show()
为了更方便观察,上述计算得到的均价差值,再取其相邻日期的差值,得到信号指标。当信号为1时,表示买入股票;当信号为-1时,表示卖出股票;当信号为0时,不进行任何操作。
data['signal'] = np.sign(data['diff'] - data['diff'].shift(1))
data['signal'].plot(ylim=(-2,2))
plt.show()
从上图中看出,一共有三轮买进和卖出的时机。
看一下下这三轮交易详情:
trade = pd.concat([ pd.DataFrame({"price": data.loc[data["signal"] == 1, "close"],"operation": "Buy"}),
pd.DataFrame({"price": data.loc[data["signal"] == -1, "close"],"operation": "Sell"}) ])
trade.sort_index(inplace=True)
print(trade)
上述表格列出了交易日期、操作和当天的价格。但是发现这三轮交易的卖出价都小于买入价,实际上按上述方法交易是亏本了!
这里的分析只是演示移动平均线策略的思想,而并非真正的投资建议。
如果考虑更长的时间跨度,比如2年、5年,并考虑更长的均线,比如将20日均线和50日均线比较;虽然过程中也有亏损的时候,但赢的概率更大。
参考:
1、基于移动平均的交易策略
2、数据分析实践之路