什么是动量效益?
这种类似惯性方向运动的价格变化现象被称作动量效应。比较专业地说:动量效应是由Jegadeesh和Titman(1993)提出的,是指股票的收益率有延续原来的运动方向的趋势,即过去一段时间收益率较高的股票在未来获得的收益率仍会高于过去收益率较低的股票。
为什么会产生动量?
今天我们主要介绍时间序列动量的最原始验证和捕捉方法。但是在此之前,根据其他参考文章的介绍,动量效应之所以存在是因为投资者在股票市场和期货市场的心理认知偏差,比如:
(1)过度自信
人们在决策中总是倾向于过高估计自己的判断力和决策力,进而容易忽视情况变化造成决策失误。通常人们认为对某事抱有90%的把握时,事实证明成功的概率大约只有70%。
(2)后悔厌恶
后悔厌恶指当人们做出错误的决策时,对自己的行为感到痛苦。为了避免痛苦,人们常常做出许多看起来是非理性的行为。
3)损失厌恶
损失厌恶是指人们面对同样数量的收益和损失时,感到损失比收益更加令他们难以忍受。
(4)锚定效应
锚定效应是指人们在对某人某事做出决策时,易受第一印象或者第一信息支配,人们在接受决策时,会不自觉地给予最初信息过多的关注。
(5)从众心理
当人们发现自己与多数人的判断不一致时,感受到一定的压力,从而改变原来自己正确的判断。
价格动量策略原理
价格动量的计算公式
AR = [N天所有(High-Open)的和/ N天所有(Open—Low)的和] * 100
这其中:
- N: 日时间周期的统计窗口,默认一般为7天
- High: 单日的最高价
- Open: 单日的开盘价
- Low: 单日的最低价
# 编写价格动量函数AR,以前N-1日K线计算价格动量ar
def AR(kline1):
spread_ho = sum(kline1.high[:-1] - kline1.open[:-1])
spread_oc = sum(kline1.open[:-1] - kline1.low[:-1])
# spread_oc 为0时,设置为最小价格跳动值
if spread_oc == 0:
spread_oc = quote.price_tick
ar = (spread_ho/spread_oc)*100
return ar
价格动量在一段时间内,反应了开盘价在最高价和最低价之间的位子,这个位置就是我们判断双方力量拉锯的依据。
- 我们假设这个值为100左右,超过100,则多头力量开始增加,小于100,则空头力量开始聚集。
- AR值升高时表示行情活跃,人气旺盛,多头一路高歌猛进,但是过高则表示价格进入超买区域,应选择时机平仓。AR值的高度没有具体标准,一般情况下,AR值上升至150左右时,价格很有可能会回调下挫。
- AR值下降时表示行情衰退,空头气势正盛,需要多头努力,过低则暗示价格可能已经跌入超卖区域,可考虑伺机做多或平仓。一般AR值跌至50以下时,价格随时止跌反涨。
策略思路
开仓思路
当价格动量ar值大于110小于150时开多仓
当ar值小于90大于50时开空仓
if api.is_changing(quote,"last_price"):
# 开仓策略
if position.pos_long == 0 and position.pos_short == 0:
# 如果ar大于110并且小于150,开多仓
if 110 < ar < 150:
print("价值动量超过110,小于150,做多")
target_pos.set_target_volume(100)
# 如果ar大于50,小于90,开空仓
elif 50 < ar < 90:
print("价值动量大于50,小于90,做空")
target_pos.set_target_volume(-100)
止损思路
持多头时,当ar值小于90则止损
持空头时,当ar值大于110则止损
# 止损策略,多头下当前ar值小于90则平仓止损,空头下当前ar值大于110则平仓止损
elif (position.pos_long > 0 and ar < 90) or (position.pos_short > 0 and ar > 110):
print("止损平仓")
target_pos.set_target_volume(0)
回测
初始账户资金:1000万
回测日期:2019.07.19-2019.08.29
多、空头开仓手数:100手
合约: SHFE.au1912
| 价格动量策略回测结果 | |||||
| 合约代码 | 合约品种 | 收益率 | 风险度 | 最大回撤 | 年化夏普率 |
| SHFE.au1912 | 沪金 | 37.47% | 14.27% | 7.21% | 4.6819 |
注意:以上参数皆是默认数值,并不严谨。在真正交易的过程中,我们要根据对应合约品种和行情的变化,调试这个区间以适应当下的行情状态。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Ringo"
from tqsdk import TqAccount, TqApi, TargetPosTask
# 设置指定合约,获取N条K线计算价格动量
SYMBOL ="SHFE.au1912"
N = 15
api = TqApi()
klines = api.get_kline_serial(SYMBOL,60*60*24,N)
quote = api.get_quote(SYMBOL)
target_pos = TargetPosTask(api, SYMBOL)
position = api.get_position(SYMBOL)
# 编写价格动量函数AR,以前N-1日K线计算价格动量ar
def AR(kline1):
spread_ho = sum(kline1.high[:-1] - kline1.open[:-1])
spread_oc = sum(kline1.open[:-1] - kline1.low[:-1])
# spread_oc 为0时,设置为最小价格跳动值
if spread_oc == 0:
spread_oc = quote.price_tick
ar = (spread_ho/spread_oc)*100
return ar
ar = AR(klines)
print("策略开始启动")
while True:
api.wait_update()
# 生成新K线时,重新计算价格动量值ar
if api.is_changing(klines.iloc[-1],"datetime"):
ar = AR(klines)
print("价格动量是:", ar)
# 每次最新价发生变动时,重新进行判断
if api.is_changing(quote,"last_price"):
# 开仓策略
if position.pos_long == 0 and position.pos_short == 0:
# 如果ar大于110并且小于150,开多仓
if 110 < ar < 150:
print("价值动量超过110,小于150,做多")
target_pos.set_target_volume(100)
# 如果ar大于50,小于90,开空仓
elif 50 < ar < 90:
print("价值动量大于50,小于90,做空")
target_pos.set_target_volume(-100)
# 止损策略,多头下当前ar值小于90则平仓止损,空头下当前ar值大于110则平仓止损
elif (position.pos_long > 0 and ar < 90) or (position.pos_short > 0 and ar > 110):
print("止损平仓")
target_pos.set_target_volume(0)
参考:https://blog.csdn.net/Quant_/article/details/85100502
