前两天看到一篇论文《基于EMV指标的量化交易策略在我国A股市场的研究》,想想看我们学习talib中居然没有这个指标,至少目前还没碰见。作者通过EMV指标实现了年化20%的收益。对于一个本着学习目的的我来说,学一学EMV指标确实挺好。想想看要是自己也能开发这样一套系统的话,想想都觉得美滋滋。但毕竟咋不是专业的,野路子就要咋不断的动手了,希望黄天不负有心人吧!

1.EMV到底是什么?

简易波动指标(EMV),是为数不多的考虑价量关系的技术指标。它是根据成交量和人气的变化,构成一个完整的股价系统循环。该指标指示投资者在人气聚集且成交热络的时候买进股票,并且在成交量逐渐展现无力时,卖出股票。具体来说,当股价下跌时,由于买方萎靡退缩,致使成交量逐渐的减少,EMV数值也因而尾随下降,直到股价下跌至某一个合理支撑区,捡便宜货的买单促使成交量再度活跃,EMV 数值于是作相对反应向上攀升。所以EMV 指标的上升下降意味着市场的强弱变化,可以以此作为择时的判断依据。

2.EMV的计算公式

EM=((high[i]+low[i])/2-(high[i-1]+low[i-1])/2)*(high[i]-low[i])/volum[i]
#EMV表示EM的n日平均值
EMV=talib.SMA(EM,n)
#MAEMV表示m日的EMV的均值
MAEMV=talib.SMA(EMV,m)

3.使用python实现上述公式并作图

def TEMV(data,fasttimeperiod,lasttimeperiod):temp=datatemp['sub']=2emFront=talib.DIV(talib.ADD(temp['high'],temp['low']),temp['sub'])emFrontSub=talib.DIV(talib.ADD(temp['high'].shift(1),temp['low'].shift(1)),temp['sub'])emEnd=talib.DIV(talib.SUB(temp['high'],temp['low']),temp['volume'])em= talib.SUB(emFront,emFrontSub)*emEndEMV=talib.SMA(em,fasttimeperiod)MAEMV=talib.SMA(EMV,lasttimeperiod)return EMV,MAEMV

小结:通过上述简易的Demo,我们发现emv指标确实能够捕捉到一些信号。至少会比我盲听别人的观点强的多。作为一个专业搞软件的同学,我觉得咋就搭建一个系统然后做一个EMV策略。因为咋也没做过投资,那就按一般的常识做。当emv和maemv指数均大于0,并且emv指数上穿maemv我们就买入,当emv下穿maven咋就卖出。并设定投资金额是5000元人名币,每次笔交易的服务费是0.2%

策略运行结果如下:

分析一下:emv的周期我设置的是5,maemv的周期设置的是10,当emv和maemv指数均大于0,并且emv指数上穿maemv我们就买入,当emv下穿maven咋就卖出。每次买入信号来的时候买100股,每次卖出信号来的时候全部卖出。总之在年末我的账面资金是:

这里贴一下耗了一下午的策略。算是学了python吧

import talib
import matplotlib.pyplot as plt
from matplotlib.pylab import date2num
import matplotlib.ticker as ticker  # 用于日期刻度定制
import baostock as bs
import pandas as pd
import datetime
from matplotlib import colors as mcolors  # 用于颜色转换成渲染时顶点需要的颜色格式
from matplotlib.collections import LineCollection, PolyCollection  # 用于绘制直线集合和多边形集合
from matplotlib.widgets import Cursor  # 处理鼠标totalRmb=10000
handTotal=0
buysell=[]
myRmb=[]
def date_to_num(dates):num_time = []for date in dates:date_time = datetime.datetime.strptime(date,'%Y-%m-%d')num_date = date2num(date_time)num_time.append(num_date)return num_time# 绘制蜡烛图
def format_date(x, pos=None):# 日期格式化函数,根据天数索引取出日期值return '' if x < 0 or x > len(date_tickers) - 1 else date_tickers[int(x)]#EMV技术计算
def TEMV(data,fasttimeperiod,lasttimeperiod):temp=datatemp['sub']=2emFront=talib.DIV(talib.ADD(temp['high'],temp['low']),temp['sub'])emFrontSub=talib.DIV(talib.ADD(temp['high'].shift(1),temp['low'].shift(1)),temp['sub'])emEnd=talib.DIV(talib.SUB(temp['high'],temp['low']),temp['volume'])em= talib.SUB(emFront,emFrontSub)*emEndEMV=talib.SMA(em,fasttimeperiod)MAEMV=talib.SMA(EMV,lasttimeperiod)SubEmv=talib.SUB(EMV,MAEMV)return EMV,MAEMV,SubEmv#策略
def BuySallForEmv(Emv,MaEmv):BuyIndex=[]SallIndex=[]temp=pd.DataFrame({ 'emv' :Emv, 'maemv' :MaEmv})for index, row in temp.iterrows():if row['emv'] is None:continueif row['emv'] > 0 and row['maemv']>0 and row['emv']>row['maemv']:BuyIndex.append(index)elif row['emv']>=0 and row['maemv']>=0 and row['emv']<row['maemv']:SallIndex.append(index)return BuyIndex,SallIndex#买股票
def Dobuy(index,price):global totalRmb, handTotalglobal buysell, myRmbcurrentRmb=price*100*1.002if totalRmb-currentRmb>0:totalRmb=totalRmb-currentRmbhandTotal=handTotal+1buysell.append(index-start)myRmb.append(totalRmb+handTotal*100*price)print("总金额:" + str(totalRmb) + "   总手数" + str(handTotal)+"   账户总金额:"+str(totalRmb+handTotal*100*price))else:print("资金不足")#卖股票
def Dosell(index,price):global buysell, myRmbglobal totalRmb, handTotalif handTotal>0:currentRmb=handTotal*100*price*0.998totalRmb=totalRmb+currentRmbbuysell.append(index-start)myRmb.append(totalRmb)handTotal=0print("总金额:"+str(totalRmb)+"   总手数"+str(handTotal)+"   账户总金额:"+str(totalRmb))else:print("不用再往出卖了")#历史回测
def calculateHistory(doBuy,doSell):bySort=doBuy.indexbySell=doSell.indexdoBuy['could']=1doBuy['sort']=bySortdoSell['could']=-1doSell['sort']=bySelltemp=pd.concat([doBuy,doSell])wang=temp.sort_values(by="sort", ascending=True)for index, row in wang.iterrows():print(str(index)+"  "+str(row['could'])+"  "+str(row['sort'])+"   "+str(row['low']))if row['could']==1:Dobuy(index,float(row['close']))elif row['could']==-1:price=float(row['close'])Dosell(index,price)lg = bs.login()
rs = bs.query_history_k_data_plus("sh.600567","date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST",start_date='1999-07-01', end_date='2020-10-24',frequency="d", adjustflag="3")#### 打印结果集 ####
data_list = []
while (rs.error_code == '0') & rs.next():data_list.append(rs.get_row_data())
result = pd.DataFrame(data_list, columns=rs.fields)
window=360
start=len(result)-window
#二维数组
result=result.loc[:,['date','open','high','low','close','volume'] ]
result=result[-window:]date_tickers=result.date.values
result.date = range(0, len(result))  # 日期改变成序号
matix = result.values  # 转换成绘制蜡烛图需要的数据格式(date, open, close, high, low, volume)
xdates = matix[:,0] # X轴数据(这里用的天数索引)
#总投资金额为5000元,买入信号出现时每次买一手。如果有卖出信号则全部卖出t3Price = talib.T3(result['close'], timeperiod=10, vfactor=0)
Adxprice = talib.ADX(result['high'],result['low'],result['close'], timeperiod=5)
Adxrprice = talib.ADXR(result['high'],result['low'],result['close'], timeperiod=5)
emv,maemv,subemv=TEMV(result,5,10)buy,sell=BuySallForEmv(emv,maemv)
realBuy=result.index.isin(buy)
doBuy=result[realBuy]
realSell=result.index.isin(sell)
doSell=result[realSell]upperband, middleband, lowerband = talib.BBANDS(result['close'], timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
# 设置外观效果
plt.rc('font', family='Microsoft YaHei')  # 用中文字体,防止中文显示不出来
plt.rc('figure', fc='k')  # 绘图对象背景图
plt.rc('text', c='#800000')  # 文本颜色
plt.rc('axes', axisbelow=True, xmargin=0, fc='k', ec='#800000', lw=1.5, labelcolor='#800000',unicode_minus=False)  # 坐标轴属性(置底,左边无空隙,背景色,边框色,线宽,文本颜色,中文负号修正)
plt.rc('xtick', c='#d43221')  # x轴刻度文字颜色
plt.rc('ytick', c='#d43221')  # y轴刻度文字颜色
plt.rc('grid', c='#800000', alpha=0.9, ls=':', lw=0.8)  # 网格属性(颜色,透明值,线条样式,线宽)
plt.rc('lines', lw=0.8)  # 全局线宽# 创建绘图对象和4个坐标轴
fig = plt.figure(figsize=(16, 8))
left, width = 0.05, 0.9
ax1 = fig.add_axes([left, 0.6, width, 0.4])  # left, bottom, width, height
ax2 = fig.add_axes([left, 0.5, width, 0.15], sharex=ax1)  # 共享ax1轴
ax3 = fig.add_axes([left, 0.35, width, 0.15], sharex=ax1)  # 共享ax1轴
ax4 = fig.add_axes([left, 0.2, width, 0.15], sharex=ax1)  # 共享ax1轴
ax5 = fig.add_axes([left, 0.05, width, 0.15], sharex=ax1)  # 共享ax1轴
plt.setp(ax1.get_xticklabels(), visible=False)  # 使x轴刻度文本不可见,因为共享,不需要显示
plt.setp(ax2.get_xticklabels(), visible=False)  # 使x轴刻度文本不可见,因为共享,不需要显示
plt.setp(ax3.get_xticklabels(), visible=False)  # 使x轴刻度文本不可见,因为共享,不需要显示ax1.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))  # 设置自定义x轴格式化日期函数
ax1.xaxis.set_major_locator(ticker.MultipleLocator(max(int(len(result) / 15), 5)))  # 横向最多排15个左右的日期,最少5个,防止日期太拥挤
# # 下面这一段代码,替换了上面注释的这个函数,因为上面的这个函数达不到同花顺的效果
opens, closes, highs, lows = matix[:, 1], matix[:, 4], matix[:, 2], matix[:, 3]  # 取出ochl值
avg_dist_between_points = (xdates[-1] - xdates[0]) / float(len(xdates))  # 计算每个日期之间的距离
delta = avg_dist_between_points / 4.0  # 用于K线实体(矩形)的偏移坐标计算
barVerts = [((date - delta, open), (date - delta, close), (date + delta, close), (date + delta, open)) for date, open, close in zip(xdates, opens, closes)]  # 生成K线实体(矩形)的4个顶点坐标
rangeSegLow = [((date, low), (date, min(open, close))) for date, low, open, close in  zip(xdates, lows, opens, closes)]  # 生成下影线顶点列表
rangeSegHigh = [((date, high), (date, max(open, close))) for date, high, open, close in zip(xdates, highs, opens, closes)]  # 生成上影线顶点列表
rangeSegments = rangeSegLow + rangeSegHigh  # 上下影线顶点列表
print(rangeSegments)
cmap = {True: mcolors.to_rgba('#000000', 1.0),False: mcolors.to_rgba('#54fcfc', 1.0)}  # K线实体(矩形)中间的背景色(True是上涨颜色,False是下跌颜色)
inner_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)]  # K线实体(矩形)中间的背景色列表
cmap = {True: mcolors.to_rgba('#ff3232', 1.0),False: mcolors.to_rgba('#54fcfc', 1.0)}  # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用)
updown_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)]  # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用)列表
#
ax1.add_collection(LineCollection(rangeSegments, colors=updown_colors, linewidths=0.5,antialiaseds=False))
# 生成上下影线的顶点数据(颜色,线宽,反锯齿,反锯齿关闭好像没效果)
ax1.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=False,linewidths=0.5))
# 生成多边形(矩形)顶点数据(背景填充色,边框色,反锯齿,线宽)# 绘制均线
mav_colors = ['#ffffff', '#d4ff07', '#ff80ff', '#00e600', '#02e2f4', '#ffffb9', '#2a6848']  # 均线循环颜色
mav_period = [5, 10, 20, 30, 60, 120, 180]  # 定义要绘制的均线周期,可增减
# mav_period = [5]  # 定义要绘制的均线周期,可增减
n = len(result)
for i in range(len(mav_period)):if n >= mav_period[i]:mav_vals = result['close'].rolling(mav_period[i]).mean().valuesax1.plot(xdates, mav_vals, c=mav_colors[i % len(mav_colors)], label='MA' + str(mav_period[i]))
for index, row in doBuy.iterrows():ax1.scatter(index-start, float(row['close']), color="Y", marker="*")
for index, row in doSell.iterrows():ax1.scatter(index-start, float(row['close']), color="b", marker="^")calculateHistory(doBuy,doSell)
ax1.plot(xdates,t3Price,label='t3price')
ax1.set_title('sz.002918')  # 标题
ax1.grid(True)  # 画网格
ax1.legend(loc='upper left')  # 图例放置于右上角
ax1.xaxis_date()  # 好像要不要效果一样?barVerts = [((date - delta, 0), (date - delta, vol), (date + delta, vol), (date + delta, 0)) for date, vol in zip(xdates, matix[:, 5])]
# 生成K线实体(矩形)的4个顶点坐标
ax2.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=False,linewidths=0.5))
# 生成多边形(矩形)顶点数据(背景填充色,边框色,反锯齿,线宽)
if n >= 5:  # 5日均线,作法类似前面的均线vol5 = result['volume'].rolling(5).mean().valuesax2.plot(xdates, vol5, c='y', label='VOL5')
if n >= 10:  # 10日均线,作法类似前面的均线vol10 = result['volume'].rolling(10).mean().valuesax2.plot(xdates, vol10, c='w', label='VOL10')
ax2.yaxis.set_ticks_position('right')  # y轴显示在右边
ax2.legend(loc='upper left')  # 图例放置于右上角
ax2.grid(True)  # 画网格ax3.plot(xdates, Adxprice, c='w', label='Adxprice')
ax3.plot(xdates, Adxrprice, c='b', label='Adxrprice')
ax3.legend(loc='upper left')  # 图例放置于右上角
ax3.grid(True)  # 画网格ax4.plot(xdates,emv,c='r',label='EMV')
ax4.plot(xdates,maemv,c='g',label='MAEMV')
ax4.axhline(0, ls='-', c='w', lw=0.5)  # 水平线
ax4.legend(loc='upper left')  # 图例放置于右上角
ax4.grid(True)  # 画网格ax5.axhline(10000, ls='-', c='w', lw=0.5)  # 水平线
ax5.plot(buysell, myRmb, c='g', label='割韭菜')
ax5.legend(loc='upper left')  # 图例放置于右上角
ax5.grid(True)  # 画网格cursor = Cursor(ax1, useblit=True, color='w', linewidth=0.5, linestyle='--')
cursor1 = Cursor(ax3, useblit=True, color='w', linewidth=0.5, linestyle='--')
cursor2 = Cursor(ax4, useblit=True, color='w', linewidth=0.5, linestyle='--')# 登出系统
bs.logout()plt.show()
‍

用talib实现基于emv的简易量化投资策略相关推荐

  1. matlab统计所有股票分析,MATLAB金融算法分析实战:基于机器学习的股票量化分析...

    MATLAB金融算法分析实战:基于机器学习的股票量化分析 作者:吴婷;余胜威 编著 出版日期:2017年07月 文件大小:32.24M 支持设备: ¥50.00在线试读 适用客户端: 言商书局 iPa ...

  2. python量化交易书籍推荐知乎_GitHub - XingkaiLiang/vnpy: 基于python的开源量化交易平台开发框架...

    vn.py - By Traders, For Traders. 简介 vn.py是基于Python的开源量化交易程序开发框架,起源于国内私募的自主量化交易系统.2015年初项目启动时只是单纯的交易A ...

  3. python 股票交易接口 github_GitHub - xiongyixiaoyang/vnpy: 基于python的开源量化交易平台开发框架...

    By Traders, For Traders. 简介 vn.py是基于Python的开源量化交易程序开发框架,起源于国内私募的自主量化交易系统.2015年初项目启动时只是单纯的交易API接口的Pyt ...

  4. socketserver模块用法,多道技术、 基于UDP的简易版QQ

    复习 1.OSI七层2.以太网协议3.ip协议(arp协议)4.TCP5.UDP OSI七层 应表会 # 应用层 (HTTP协议, FTP协议)传输层 # 端口协议 在此层发挥作用网络层 # IP协议 ...

  5. python量化投资必背代码-基于python的开源量化交易,量化投资架构

    原标题:基于python的开源量化交易,量化投资架构 github地址:https://github.com/bbfamily/abu abu能够帮助用户自动完善策略,主动分析策略产生的交易行为,智能 ...

  6. [原创][连载].基于SOPC的简易数码相框 - Nios II SBTE部分(软件部分) - 从SD卡内读取图片文件,然后显示在TFT-LCD上...

    实在很抱歉,时间紧张,我只讲怎样从SD卡内读取bin文件(二进制文件),然后现在TFT-LCD上. 准备工具 1. Image2Lcd.zip 操作步骤 步骤1 寻找或制作240x320的图片 简单起 ...

  7. 简单计算器的设计java_(基于java的简易计算器的设计.doc

    (基于java的简易计算器的设计 基于java的简易计算器的设计 摘要 自从java语言诞生以来,java语言就以不可抵挡的趋势很快成为国际上广泛流行的面向对象编程语言,它既具有高级语言的特点,又少了 ...

  8. 基于stm32简易计算机电路图,基于STM32的简易电子计算器设计与实现(DOC).doc

    嵌入式系统设计实验综合设计报告 PAGE 四川师范大学成都学院通信工程学院 基于STM32的简易电子计算器设计与实现 实验综合设计报告 学生姓名 陶龑 学 号 2016301033 所在学院 通信工程 ...

  9. linux 轻量化图形界面,YOXIOS 入门教程--基于Linux的 轻量化GUI图形系统和硬件平台(41页)-原创力文档...

    YOXIOS --基于 Linux 的轻量化 GUI图形系统和硬件平台 YOXIOS 入门教程 基于 Linux 的 轻量化 GUI图形系统和硬件平台 (V1.0 2020-05) 提示:阅读此文档需 ...

  10. python实现简易聊天需要登录博客园zip下载_Python基于Socket实现简易多人聊天室的示例代码...

    前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...

最新文章

  1. 如何利用python的newspaper包快速爬取网页数据
  2. RequisitePro SQL SERVER数据库的配置
  3. 单细胞一站式分析网站CeDR Atlas使用指南
  4. 09_分类算法--k近邻算法(KNN)、案例、欧氏距离、k-近邻算法API、KNeighborsClassifier、及其里面的案例(网络资料+学习资料整理笔记)
  5. python单元测试框架unittest介绍和使用_Python+Selenium框架设计篇之-简单介绍unittest单元测试框架...
  6. Python中添加中文注释报错SyntaxError: Non-UTF-8 code starting with '\xc1'
  7. 最简单的flex bison例子
  8. [文摘20070930]每个人都需要掌握的18个人情世故
  9. 唯有创新不可辜负!混合集成成就云时代创新
  10. 无类域间路由CIDR
  11. Flutter Image图片显示
  12. gtx1050ti最稳定的驱动_GTX1050ti显卡驱动下载_NVIDIA GeForce GTX1050ti显卡驱动Win7Win10版下载 - 系统之家...
  13. android-腾讯街景已经百度街景对比
  14. 5W2H在IC设计中的应用
  15. 用java怎么开发图片标注工具,图片标注工具选型
  16. windows批量部署
  17. 如何系统的学习 Elasticsearch ?
  18. 裁剪左上角x左上角y填什么_在“context.moveTo(x,y);”中,x、y 是相对于【 】的左上角。...
  19. 【考研英语】阅读理解词汇注释
  20. Java8 Zip 压缩与解压缩

热门文章

  1. Error Client wants topic A to have B, but our version has C. Dropping connection.
  2. android7.1索尼,Xperia 1
  3. Bash玩转脚本3之几个指令有趣的筛选京东评价
  4. 使用iMazing给苹果手机设置专属来电铃声
  5. 翻译: 人工智能的时代的教育将比上一代富豪的孩子更受益 慕课大规模开放在线课程(MOOC)
  6. 村长选举c语言程序,菜鸡学C语言之摸鱼村村长
  7. 如何启动android模拟器,如何从命令行启动Android模拟器?
  8. redis为什么这么快
  9. Markdown 4 印象笔记之马克飞象
  10. PTA-数据库作业题(二)