WeQuant交易策略—EMV
EMV指标策略
简介
EMV(Ease of Movement Value, 简易波动指标),它是由RichardW.ArmJr.根据等量图和压缩图的原理设计而成, 目的是将价格与成交量的变化结合成一个波动指标来反映股价或指数的变动状况。 旨在先于其他投资者买入/卖出。
计算方法(以日为单位举例)
(1) A = (当日最高价 + 当日最低价)/ 2
B = (前日最高价 + 前日最低价)/ 2
C = 当日最高价 – 当日最低价
(2) 当日EM = (A – B ) * C / 当日成交额
(3) EMV = N日内EM的总和
使用方法
当EMV值从下向上穿过零轴时,全仓买入;EMV值从上向下穿过零轴时,全仓卖出。
如果较少的成交量便能推动股价上涨,则EMV数值会升高,相反的,股价下跌时也仅伴随较少的成交量,则EMV数值将降低。另一方面,倘若价格不涨不跌,或者价格的上涨和下跌,都伴随着较大的成交量时,则EMV的数值会趋近于零。
EMV指标曲线大部份集中在0轴下方,这个特征是EMV指标的主要特色,由于股价下跌一般成交量较少,EMV自然位于0轴下方,当成交量放大时,EMV又趋近于零,这可以说明EMV的理论精髓中,无法接受股价在涨升的过程,不断的出现高成交量消耗力气,反而认同徐缓成交的上涨,能够保存一定的元气,促使涨势能走得更远更长。从另外一个角度说,EMV重视移动长久且能产生足够利润的行情。关于EMV和EMV的平均线,两线的交叉并无意义,而是选择以EMV指标平均线跨越0轴为讯号,所产生的交易成果将更令人满意。
优点
EMV的用法十分简单,只要看EMV线穿越零轴这一点即可。而且,较好地运用波动指标EMA不仅可以避免在市场中盲目追涨杀跌,而且还能够发现较好得操作时机。
缺点
EMV指标反应的是价格运行全过程中成交量的动态变化情况。因此,指标对价格的中长期走势更具有警示性。须长期使用EMV指标,才能获得较好的投资效果。想要短期高频操作的同学,最好不要使用EMV作为买卖指标。
代码
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# 策略代码总共分为三大部分,1)PARAMS变量 2)initialize函数 3)handle_data函数
# 请根据指示阅读。或者直接点击运行回测按钮,进行测试,查看策略效果。
# 策略名称:EMV指标策略
# 策略详细介绍:https://wequant.io/study/strategy.emv.html
# 关键词:成交量、捕捉趋势。
# 方法:
# 1)通过价格变化以及成交量来捕捉趋势;
# 2)在上升趋势买入,在下跌趋势卖出。
# 阅读1,首次阅读可跳过:
# PARAMS用于设定程序参数,回测的起始时间、结束时间、滑点误差、初始资金和持仓。
# 可以仿照格式修改,基本都能运行。如果想了解详情请参考新手学堂的API文档。
PARAMS = {
"start_time": "2017-02-01 00:00:00", # 回测起始时间
"end_time": "2017-08-01 00:00:00", # 回测结束时间
"slippage": 0.003, # 此处“slippage"包含佣金(千二)+交易滑点(千一)
"account_initial": {"huobi_cny_cash": 100000,
"huobi_cny_btc": 0}, # 设置账户初始状态
}
# 阅读2,遇到不明白的变量可以跳过,需要的时候回来查阅:
# initialize函数是两大核心函数之一(另一个是handle_data),用于初始化策略变量。
# 策略变量包含:必填变量,以及非必填(用户自己方便使用)的变量
def initialize(context):
# 设置回测频率, 可选:"1m", "5m", "15m", "30m", "60m", "4h", "1d", "1w"
context.frequency = "4h"
# 设置回测基准, 比特币:"huobi_cny_btc", 莱特币:"huobi_cny_ltc", 以太坊:"huobi_cny_eth"
context.benchmark = "huobi_cny_btc"
# 设置回测标的, 比特币:"huobi_cny_btc", 莱特币:"huobi_cny_ltc", 以太坊:"huobi_cny_eth"
context.security = "huobi_cny_btc"
# 设置EMV回看累积时间段
context.user_data.emv_period = 14
# 阅读3,策略核心逻辑:
# handle_data函数定义了策略的执行逻辑,按照frequency生成的bar依次读取并执行策略逻辑,直至程序结束。
# handle_data和bar的详细说明,请参考新手学堂的解释文档。
def handle_data(context):
# 获取历史数据
hist = context.data.get_price(context.security, count=context.user_data.emv_period + 2, frequency=context.frequency)
if len(hist.index) < (context.user_data.emv_period + 2):
context.log.warn("bar的数量不足, 等待下一根bar...")
return
# 每根bar的最高价
high = hist["high"]
# 每根bar的最低价
low = hist["low"]
# 每根bar的成交量(数量)
vol = hist["volume"]
close = hist["close"]
# 计算EMV
a = (high + low) / 2
b = a.shift(1)
c = high - low
em = (a - b) * c / vol
emv = em.rolling(window=context.user_data.emv_period).sum()
# 当前bar的EMV值
emv_current = emv[len(emv)-1]
# 前一根bar的EMV值
emv_prev = emv[len(emv)-2]
context.log.info("当前 EMV = %s; 前一根bar EMV = %s" % (emv_current, emv_prev))
# EMV从下向上穿过零轴,买入信号
if emv_prev <= 0 < emv_current:
context.log.info("EMV由下向上穿过0轴,产生买入信号")
if context.account.huobi_cny_cash >= HUOBI_CNY_BTC_MIN_ORDER_CASH_AMOUNT:
# 有买入信号,且持有现金,则市价单全仓买入
context.log.info("正在买入 %s" % context.security)
context.log.info("下单金额为 %s 元" % context.account.huobi_cny_cash)
context.order.buy_limit(context.security, quantity=str(context.account.huobi_cny_cash/close[-1]*0.98), price=str(close[-1]*1.02))
else:
context.log.info("现金不足,无法下单")
# EMV从上向下穿过零轴,卖出信号
elif emv_prev >= 0 > emv_current:
context.log.info("EMV由上向下穿过0轴,产生卖出信号")
if context.account.huobi_cny_btc >= HUOBI_CNY_BTC_MIN_ORDER_QUANTITY:
# 有卖出信号,且持有仓位,则市价单全仓卖出
context.log.info("正在卖出 %s" % context.security)
context.log.info("卖出数量为 %s" % context.account.huobi_cny_btc)
context.order.sell_limit(context.security, quantity=str(context.account.huobi_cny_btc), price=str(close[-1]*0.98))
else:
context.log.info("仓位不足,无法卖出")
else:
context.log.info("无交易信号,进入下一根bar")
回测
- 参数设置如下:
| 时间段 | 2017-02-01至2017-08-01 |
| 回测频率(context.frequency) | 4h |
| EMV回看时间窗口 | 5(天) |
股票市场常用的回看时间窗口一般是14天。但是由于数字货币市场自身容易暴涨暴跌的特性,回看时间太长会很难及时对市场的变化做出反应,过于滞后。因此,需要将回看窗口适当调小。大家也可以尝试一下别的时间窗口,看看效果如何。
- 回测结果:

从回测结果中,我们看出EMV指标在捕捉行情上非常有效。几次大幅上涨都有抓住,而在下跌的时候也能比较及时的逃出,锁定收益。
现在,将回看时间调到传统的14天,我们来看一下回测结果:

现在的表现大不如前,几次暴跌都没能反映过来,将大部分收益回吐。所以,在设置指标的参数时,要区分不同产品不同行情,不能无脑照搬。
总结
EMV指标引入了成交量数据,与其他单纯通过价格来计算出的指标,能更有效的反应出一些价格背后所隐藏的东西。在数字货币市场中,EMV指标的回看时间不宜过长,防止在暴涨暴跌中不能及时应对。
WeQuant交易策略—EMV的更多相关文章
- WeQuant交易策略—网格交易
网格交易策略(Grid Trading) 策略介绍 网格策略本质上是一种低吸高抛的策略.标的物价格越低,吸纳的头寸越多:标的物价格越高,卖出的头寸越多.网格策略巧妙地借鉴了日常生活中渔翁撒网扑鱼的思路 ...
- WeQuant交易策略—Dual Thrust
Dual Thrust策略 策略介绍 Dual Thrust是一个趋势跟踪系统,由Michael Chalek在20世纪80年代开发,曾被Future Thruth杂志评为最赚钱的策略之一. Dual ...
- WeQuant交易策略—ATR
ATR(真实波幅均值)策略 策略介绍 ATR(average true range,真实波幅均值),是用来衡量一段时间内价格的真实的平均波动范围,ATR不是一个领先指标,但是它测量最重要的市场参数之一 ...
- WeQuant交易策略—RSI
RSI指标策略 策略介绍 RSI(相对强弱指标),是通过一段时期内的平均收盘上涨和下跌数,计算价格上涨所产生的波动占整个波动的百分比,来分析市场买卖盘的意向和实力. 计算公式(以日为单位举例) RSI ...
- WeQuant交易策略—BOLL
BOLL(布林线指标)策略 简介 BOLL(布林线)指标是技术分析的常用工具之一,由美国股市分析家约翰•布林根据统计学中的标准差原理设计出来的一种非常简单实用的技术分析指标.一般而言,价格的运动总是围 ...
- WeQuant交易策略—KDJ
KDJ随机指标策略策略介绍KDJ指标又叫随机指标,是一种相当新颖.实用的技术分析指标,它起先用于期货市场的分析,后被广泛用于股市的中短期趋势分析,是期货和股票市场上最常用的技术分析工具.随机指标KDJ ...
- WeQuant交易策略—MACD
MACD(指数平滑异同平均线)策略简介MACD指标应该是大家最常见的技术指标,在很多股票.比特币的软件中都是默认显示的.MACD是从双指数移动平均线发展而来的.意义和双移动平均线基本相同,即由快.慢均 ...
- WeQuant交易策略—简单均线
简单双均线策略(Simple Moving Average) 策略介绍简单双均线策略,通过一短一长(一快一慢)两个回看时间窗口收盘价的简单移动平均绘制两条均线,利用均线的交叉来跟踪价格的趋势.这里说的 ...
- WeQuant交易策略—Chaikin A/D
策略名称:AD指标策略 多空双方力量浮标- AD(Chaikin A/D线)策略关键词:ChaikinA/D线.多空对比.AD指标是一种非常流行的平横交易量指标, 用于估定一段时间内该证券累积的资金流 ...
随机推荐
- js 内置对象常用方法
1 内容概述 js包含一些内置对象,如Array,Function,String等,这些是基本的,常用的js类,所以了解它们十分重要:把他们的方法,用例子和文字简要的记录下来,方便今后参看. 2 Ar ...
- 文件操作之格式化IO
其实在我使用最多的文件操作中,还是喜欢格式化IO控制的方式,简单方便易理解. #include <stdio.h> #include<stdlib.h> int main() ...
- iOS开发 支持https请求以及ssl证书配置(转)
原文地址:http://blog.5ibc.net/p/100221.html 众所周知,苹果有言,从2017年开始,将屏蔽http的资源,强推https 楼主正好近日将http转为https,给还没 ...
- Linux 新增一个用户命令 adduser
这几天新增用户老是会用 useradd , 这条命令比较复杂,记录 adduser 这条超级简单的命令. Full name 最后和用户差不多,不然登录的时候不好辨别 附: 新增用户无法 sudo 请 ...
- CSS——伪元素
CSS伪元素 伪元素的语法: selector:pseudo-element {property:value;} 作 用 添加特殊样式 :first-line 伪元素 "first-l ...
- Android基础总结(五)网络通信2
HttpClient 发送get请求 创建一个客户端对象 HttpClient client = new DefaultHttpClient(); 创建一个get请求对象 HttpGet hg = n ...
- C++ 类的继承四(类继承中的重名成员)
//类继承中的重名成员 #include<iostream> using namespace std; /* 自己猜想: 对于子类中的与父类重名的成员,c++编译器会单独为子类的这个成员变 ...
- 遍历一个Set的方法只有一个:迭代器(interator)
Set-HashSet实现类: 遍历一个Set的方法只有一个:迭代器(interator). HashSet中元素是无序的(这个无序指的是数据的添加顺序和后来的排列顺序不同),而且元素不可重复. 在O ...
- 【BZOJ】1674: [Usaco2005]Part Acquisition(spfa)
http://www.lydsy.com/JudgeOnline/problem.php?id=1674 想法很简单...将每一种看做一个点,如果i可以换成j,那么连边到j.. 费用都为1.. 然后拥 ...
- Android笔记——Activity中的回传数据案例(装备选择)
1.创建程序: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns: ...