def get_emv(security, start_date=None, end_date=None, n=10):
trade_date = get_trade_days(start_date=start_date, end_date=end_date)
HS_data=get_price(security,start_date=start_date,end_date=end_date,frequency='daily',fields=None,skip_paused=False,fq='pre')
HS_data['Low_1'] = HS_data['low'].shift(1)
HS_data['High_1'] = HS_data['high'].shift(1)
Volume = HS_data['volume'].rolling(14).mean()
Volume = Volume / HS_data['volume']
Mid = 100* (HS_data['high'] HS_data['low'] - HS_data['High_1'] - HS_data['Low_1']) / (HS_data['high'] HS_data['low'])
Temp = Mid * Volume * (HS_data['high'] - HS_data['low'])
EMV = HS_data['high'] - HS_data['low']
EMV = EMV.rolling(14).mean()
EMV = (Temp / EMV).rolling(14).mean()
MAEMV = EMV.rolling(9).mean().dropna()
EMV = EMV.dropna()[8:]
return EMV, MAEMV
def show_ema(EMA):
plt.figure(figsize=(16, 3))
plt.plot(EMV)
plt.plot(MAEMV)
plt.show()
简易波动指标(EMV),它是根据成交量和人气的变化,构成一个完整的股价系统循环。指示投资者在人气聚集且成交热络的时候买进股票,并且在成交量逐渐展现无力,而狂热的投资者尚未察觉能量即将用尽时,卖出股票。
用相对成交量除以相对振幅,作为衡量股价中间价波动百分比的基数,来得到股价中间价的相对波动范围。
1、从百度、财经博客以及财经解析中获取的公式如下:
2、同花顺计算公式如下:
寻找最优参数N与M
"""导入常用模块"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import talib
from jqdata import *
from jqlib.technical_analysis import *
from environment import * # 导入大树工作室开发的回测模块
上图图例容易分辨出进出场位置,以零轴为中心的,但是我们后期可以加入金叉与死叉来辅助交易,它有特殊之处,其代表的是量价直接的关系,EMV线上升能显现出成交量与人气的增长,下降能显现出成交量与人气的枯竭。MAEMV则使得EMV更加平滑,具有转折的参考意义。改指标从其内在就能明白,不适合短线,而且急涨急跌行情也不适合,因为EMV的创造者认为,上升量是循序渐进的,而不是爆量增长。
深入了解该指标的时候,总让人有奇思妙想,单条指标线会如何呢,双条指标线会如何呢,多条呢。虽然自己在软件上去多次调整了EMV与MAEMV,看着效果一般,而且金死叉的搭配也不错,但是还需要数据来证明,所以大家就按照[魏稀饭]给大家喂稀饭的方式去了解该指标的部分情况吧。
本次研究的脉络为:
单EMV指标,简单为一,不含糊,稀饭里面不加柴米油盐酱醋茶,至始至终皆为:量(水),价(米),比较清淡,吃起来总会感觉缺少了些什么,但是最基础的也是单一的稀饭(EMV)。咱们就来试试看这碗稀饭的水米搭配为多少最佳。
"""初始化以下内容"""
context = Context() # 账户对象
order = Order(context) # 下单对象
trade = Trade(context, order) # 回测对旬
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
"""策略主体"""
def handle(context, order):
stock = context.universe[0]
Ma_count = 50
n = 14
m = 9
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= Ma_count)
EM_list = []
for i in range(Ma_count):
if i > (n-1):
high_today = HS_da['high'][i]
low_today = HS_da['low'][i]
volume_today = HS_da['volume'][i]
high_yesterday = HS_da['high'][i-1]
low_yesterday = HS_da['low'][i-1]
tmpVolume = talib.SMA(np.array(HS_da['volume'][(i-n 1):(i 1)]), n)[-1]/volume_today
Mid = 100*(high_today low_today - high_yesterday - low_yesterday)/(high_today low_today)
temp = Mid * tmpVolume * (high_today-low_today)
high = talib.SMA(np.array(HS_da['high'][(i-n 1):(i 1)]), n)[-1]
low = talib.SMA(np.array(HS_da['low'][(i-n 1):(i 1)]), n)[-1]
EM = (temp/(high-low))
else:
EM = 0
EM_list.append(EM)
HS_da['EM'] = EM_list
HS_da['EMV'] = talib.SMA(np.array(HS_da['EM']), n)
HS_da['MAEMV'] = talib.SMA(np.array(HS_da['EMV']), m)
today_Emv = HS_da['EMV'][-1]
yesterday_Emv = HS_da['EMV'][-2]
today_MaEMV = HS_da['MAEMV'][-1]
yesterday_Maemv = HS_da['MAEMV'][-2]
if today_Emv > 0 and yesterday_Emv < 0:
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif today_Emv < 0 and yesterday_Emv > 0:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
"""执行策略"""
trade.trade(handle)
单回测数据来看,数据不是很符合心理要求,稀饭的味道明显有点烧焦味,我们需要调整看看,多方面的比例来找出最优的的参数。
已经吃完一汤勺的,给自己几拳,吐一吐,准备吃下一碗。
trade_list = []
EMV_list = [5, 10, 15, 25, 30, 35, 40, 45, 50]
for _EMV in EMV_list:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
def handle(context, order):
stock = context.universe[0]
Ma_count = 60
n = _EMV
m = 9
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= Ma_count)
EM_list = []
for i in range(Ma_count):
if i > (n-1):
high_today = HS_da['high'][i]
low_today = HS_da['low'][i]
volume_today = HS_da['volume'][i]
high_yesterday = HS_da['high'][i-1]
low_yesterday = HS_da['low'][i-1]
tmpVolume = talib.SMA(np.array(HS_da['volume'][(i-n 1):(i 1)]), n)[-1]/volume_today
Mid = 100*(high_today low_today - high_yesterday - low_yesterday)/(high_today low_today)
temp = Mid * tmpVolume * (high_today-low_today)
high = talib.SMA(np.array(HS_da['high'][(i-n 1):(i 1)]), n)[-1]
low = talib.SMA(np.array(HS_da['low'][(i-n 1):(i 1)]), n)[-1]
EM = (temp/(high-low))
else:
EM = 0
EM_list.append(EM)
HS_da['EM'] = EM_list
HS_da['EMV'] = talib.SMA(np.array(HS_da['EM']), n)
HS_da['MAEMV'] = talib.SMA(np.array(HS_da['EMV']), m)
today_Emv = HS_da['EMV'][-1]
yesterday_Emv = HS_da['EMV'][-2]
today_MaEMV = HS_da['MAEMV'][-1]
yesterday_Maemv = HS_da['MAEMV'][-2]
if today_Emv > 0 and yesterday_Emv < 0:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif today_Emv < 0 and yesterday_Emv > 0:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_ratio_compare('EMV', EMV_list, trade_list, 3, 3)
由上图数据表对比分析,符合沪深300指数的EMV值为45,果然第一次一口闷的喂稀饭方式是不正确的。从这个比例看,于熊市时候,策略收益图下跌的斜率明显低于其他EMV数值的策略,于牛市时候,策略收益图上涨的斜率会高于其他EMV数值的策略,而且对比其他指标,最大回撤、胜率、策略收益、年化收益排名同列于第一,说明EMV值45是有效的最优参数,这个道理告诉我们:稀饭,一口一口吃,心急吃不了热豆腐,这块好的热豆腐温度45°。
好稀饭的水与米比例,我们基本是以及确定了,但是上小菜也是必不可少的,现在我们上MAEMV这道菜,看是否符合市场味道。然后我们,下菜的方式有零轴判断、交叉判断、综合判断。
trade_list = []
EMV_list = [(5, 4),(10, 6),(15, 8), (25, 10), (30, 12), (35, 14), (40, 16), (45, 18), (50, 20)]
for _EMV in EMV_list:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
def handle(context, order):
stock = context.universe[0]
Ma_count = 60
n = _EMV[0]
m = _EMV[1]
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= Ma_count)
EM_list = []
for i in range(Ma_count):
if i > (n-1):
high_today = HS_da['high'][i]
low_today = HS_da['low'][i]
volume_today = HS_da['volume'][i]
high_yesterday = HS_da['high'][i-1]
low_yesterday = HS_da['low'][i-1]
tmpVolume = talib.SMA(np.array(HS_da['volume'][(i-n 1):(i 1)]), n)[-1]/volume_today
Mid = 100*(high_today low_today - high_yesterday - low_yesterday)/(high_today low_today)
temp = Mid * tmpVolume * (high_today-low_today)
high = talib.SMA(np.array(HS_da['high'][(i-n 1):(i 1)]), n)[-1]
low = talib.SMA(np.array(HS_da['low'][(i-n 1):(i 1)]), n)[-1]
EM = (temp/(high-low))
else:
EM = 0
EM_list.append(EM)
HS_da['EM'] = EM_list
HS_da['EMV'] = talib.SMA(np.array(HS_da['EM']), n)
HS_da['MAEMV'] = talib.SMA(np.array(HS_da['EMV']), m)
today_Emv = HS_da['EMV'][-1]
yesterday_Emv = HS_da['EMV'][-2]
today_MaEMV = HS_da['MAEMV'][-1]
yesterday_Maemv = HS_da['MAEMV'][-2]
if today_Emv > 0 and yesterday_Emv < 0 and today_MaEMV < today_Emv:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif today_Emv < 0 and yesterday_Emv > 0:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_ratio_compare('EMV', EMV_list, trade_list, 3, 3)
首先解释一下该进场点,必须是EMV站于MAEMV,并且突破0轴。从口味来看,貌似还适中,但是仔细品尝,感觉还是有点杂味,现在的图例给我们最好的配比是(40,15),但是回撤已经超过了心理的承受能力了,就算你能吃,不过汤匙你拿得稳吗?这个问题很尖锐啊。数据中,也发现问题,n,m数值越大,标的信号几乎没有,因为数据几乎被磨平了,适当的比值被突显出关键。我们就全面对比数据试试看。
观察了这数据,[魏稀饭]觉得自己连碗可能也端得不是很稳了,因为回撤问题依旧。不过,我们依旧可以从中知道点知识,在EMV取值在40,MAEMV取值在15-20范围内,是最优的佐料比值。数据中有比较稳健的比值,比如(10,10)配比,回撤几乎是最小,碗拿得稳,汤匙也不抖了,但是收益率将近银行理财。
trade_list = []
EMV_list = [(5, 4),(10, 6),(15, 8), (25, 10), (30, 12), (35, 14), (40, 16), (45, 18), (50, 20)]
for _EMV in EMV_list:
# 策略结构
context = Context()
order = Order(context)
trade = Trade(context, order)
context.start_date = '2010-01-01'
context.end_date = '2018-12-31'
context.universe = ['000300.XSHG']
context.base = '000300.XSHG'
def handle(context, order):
stock = context.universe[0]
Ma_count = 60
n = _EMV[0]
m = _EMV[1]
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= Ma_count)
EM_list = []
for i in range(Ma_count):
if i > (n-1):
high_today = HS_da['high'][i]
low_today = HS_da['low'][i]
volume_today = HS_da['volume'][i]
high_yesterday = HS_da['high'][i-1]
low_yesterday = HS_da['low'][i-1]
tmpVolume = talib.SMA(np.array(HS_da['volume'][(i-n 1):(i 1)]), n)[-1]/volume_today
Mid = 100*(high_today low_today - high_yesterday - low_yesterday)/(high_today low_today)
temp = Mid * tmpVolume * (high_today-low_today)
high = talib.SMA(np.array(HS_da['high'][(i-n 1):(i 1)]), n)[-1]
low = talib.SMA(np.array(HS_da['low'][(i-n 1):(i 1)]), n)[-1]
EM = (temp/(high-low))
else:
EM = 0
EM_list.append(EM)
HS_da['EM'] = EM_list
HS_da['EMV'] = talib.SMA(np.array(HS_da['EM']), n)
HS_da['MAEMV'] = talib.SMA(np.array(HS_da['EMV']), m)
today_Emv = HS_da['EMV'][-1]
yesterday_Emv = HS_da['EMV'][-2]
today_MaEMV = HS_da['MAEMV'][-1]
yesterday_Maemv = HS_da['MAEMV'][-2]
if today_Emv > today_MaEMV and yesterday_Emv < yesterday_Maemv:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif today_Emv < today_MaEMV and yesterday_Emv > yesterday_Maemv:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
# 展示
Trade.show_ratio_compare('EMV', EMV_list, trade_list, 3, 3)
交叉判断顾名思义,加的佐料是金枪鱼,当EMV与MAEMV出现金叉,立马咬。数据的展示,依旧在给我们说:来啊,快活呀!回撤辣么大,想吃金枪鱼,就得陪鲨鱼。再仔细分析数据,最优参数是(40,16),有点老味道的气息,但是这次是有陷阱,收益仅有40.2%,悲伤更大了,可以摔碗筷了,舍不得碗筷就去喝摔碗酒吧。
以[魏稀饭]性格,分析这组数据,需要谨慎思考,因为数据的回撤与收益是反比的关系,单一EMV回测数据,本身在风控范围内是不够全面,但是双EMV却加重的情况。可以给我们一个警示,简单的菜的虽然好,但是部分的菜在不合时宜的时候吃,容易拉肚子。
def handle(context, order):
stock = context.universe[0]
Ma_count = 60
n = _EMV[0]
m = _EMV[1]
HS_da = get_price(security=stock,
end_date= context.current_dt,
frequency= 'daily',
fields= None,
skip_paused= False,
fq='pre',
count= Ma_count)
EM_list = []
for i in range(Ma_count):
if i > (n-1):
high_today = HS_da['high'][i]
low_today = HS_da['low'][i]
volume_today = HS_da['volume'][i]
high_yesterday = HS_da['high'][i-1]
low_yesterday = HS_da['low'][i-1]
tmpVolume = talib.SMA(np.array(HS_da['volume'][(i-n 1):(i 1)]), n)[-1]/volume_today
Mid = 100*(high_today low_today - high_yesterday - low_yesterday)/(high_today low_today)
temp = Mid * tmpVolume * (high_today-low_today)
high = talib.SMA(np.array(HS_da['high'][(i-n 1):(i 1)]), n)[-1]
low = talib.SMA(np.array(HS_da['low'][(i-n 1):(i 1)]), n)[-1]
EM = (temp/(high-low))
else:
EM = 0
EM_list.append(EM)
HS_da['EM'] = EM_list
HS_da['EMV'] = talib.SMA(np.array(HS_da['EM']), n)
HS_da['MAEMV'] = talib.SMA(np.array(HS_da['EMV']), m)
today_Emv = HS_da['EMV'][-1]
yesterday_Emv = HS_da['EMV'][-2]
today_MaEMV = HS_da['MAEMV'][-1]
yesterday_Maemv = HS_da['MAEMV'][-2]
if today_Emv > 0 and yesterday_Emv < 0 and today_MaEMV < today_Emv:
if today_Emv > today_MaEMV and yesterday_Emv < yesterday_Maemv:
if stock in context.position.keys():
return
order.buy(stock, HS_da['close'][-1], context.cash // HS_da['close'][-1])
elif today_Emv < today_MaEMV and yesterday_Emv > yesterday_Maemv:
if stock not in context.position.keys():
return
order.sell(stock, HS_da['close'][-1], context.position[stock]['count'])
trade.trade(handle, False)
trade_list.append(trade)
Trade.show_ratio_compare('EMV', EMV_list, trade_list, 3, 3)
```
零轴 金叉等于是双拼,就好比吃稀饭,点油条又加馒头,可能会吃太饱。由上面数据,发现回撤开始缩小,这是好兆头,虽然大部分收益不乐观,还是有独角兽的,如参数(40,16),收益与回撤的改善是正比的。既然有好效果,我们就继续回测多数据看看。
数据列表,给了信心。EMV参数基本为40,MAEMV参数取值区间:12-20,从整个分析研究中,40基本比较突出,而且双拼配效果也优秀,因为回撤控制了,收益率也提升,更为突出的是盈亏比。看来着喂稀饭的方式还是算可以的,没白喂。
EMV指标从回测数据观察可以得知,于短线操作是不利的,因为入场与出场资金的瞬间放大容易造成误差,参数设置过于敏感也同样受上述情况影响。EMV指标之所以加入MAEMV是为使得整个趋势更加明显,确定出一定的走势,过滤掉大涨大跌情况,贴合市场真正的情绪。数据的最优参数和最优方案都有给出:双拼 (40,[12-20]).但是实际的运用上可能存在误差,因为就算是厨师,也无法百分百确定盐的比例是最标准的。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程