python实现MACD均线择时策略
本文采用了聚宽平台接口进行量化策略设置:
1 确定策略内容
在之前的教程中,我们学习了如何通过财务指标等对股票进行筛选等操作。今天我们将以MACD为例,探究如何利用技术指标进行策略的构建与实现。
> MACD的组成
MACD(Moving Average Convergence and Divergence)即指数平滑移动平均线,由Geral Appel 于1970年提出,属于大势趋势类指标,它由***长期慢速均线DEA,短期快线的DIF,红色能量柱(多头),绿色能量柱(空头)、0轴(多空分界线)***五部分组成,即“两线两柱一轴”组合起来形成。
在图中表示出来则为:
图中水平线为零轴,又称多空分水岭,顾名思义上方为多头势力较强,下方则为空头势力较强。
当短期快线DIF值和长期慢线DEA值上穿零轴,同时零轴之上出现红色柱状体,表示股价趋势当时属于多头市场,投资者可以考虑持股待涨。
DIF值和DEA值下穿零轴,同时零轴之下出现绿色柱状体,则表示股价趋势当时属于空头市场,投资者应当空仓持币,规避风险。
> MACD思想————均线位置与买卖时机判断
MACD是从双指数移动平均线发展而来的,由快的指数移动平均线(EMA12)减去慢的指数移动平均线(EMA26)得到快线DIF,再用2×(快线DIF-DEA)得到MACD柱。MACD的意义和双移动平均线相似,即由快、慢均线的离散、聚合来显示当前的多空状态和股价可能的发展变化趋势并对买进、卖出时机作出研判,但MACD阅读起来更方便。
总体而言:
当MACD从负数转向正数,即买入信号
当MACD从正数转向负数,即卖出信号
当MACD以大角度变化,表示快的移动平均线和慢的移动平均线的差距非常迅速的拉开,代表了一个市场大趋势的转变
> DIF与DEA金叉的使用
当白线即短期快线DIF向上穿过黄色的长期慢线DEA时,即“快线高于慢线”,属于做多金叉信号。然而实际中需要进行**“金叉+零轴”**的综合考虑。
当零轴之下出现金叉时,股价属于弱势市场,金叉为弱势金叉,股价极有可能短期弱势反弹或暂时止跌后再度夭折,一般没有做多价值。
当零轴之上发生金叉时,股价属于强势市场,金叉为强势金叉,股价后市成功惯性上攻的概率较高。若零轴之上出现二次金叉信号时,又称零上二次红金叉,属于股价强势中的强势,此时跟进做多,股价往往容易出现加速上涨。属于短线极佳买点。
> DIF与DEA死叉的使用
当白线即短期快线DIF向下穿过黄色的长期慢线DEA时,即“快线低于慢线”,属于做空死叉信号。死叉同样需要结合零轴。
当零轴之上出现死叉时,一般认为是股价上升趋势途中的短暂回调,后市股价仍有再次走强的可能。
当零轴之下发生死叉时,一般认为是股价下跌趋势途中的继续回调,后市股价惯性下跌的概率较高,尤其是MACD零轴之下出现二次死叉时,股价更容易出现加速下跌行情,所以零轴之下,无论出现的是一次死叉或二次死叉,投资者都应当空仓观望,静观其变。
策略内容
了解了MACD的基本情况,我们就能够制定本次利用技术指标构建的策略内容。
基本思路:
- 筛选出符合:
10<市盈率(pe_ratio)<40, 市净率(pb_ratio)❤️, 净利润环比增长率(inc_net_profit_annual)>0.3,净资产收益率(roe)>15的股票,按照销售毛利率进行降序排列,选取前50只- 买入:DIF从下而上穿过DEA,即形成金叉
- 卖出:DIF从上往下穿过DEA,即形成死叉
- 十天一次调仓
翻译成计算机语言即:
1.运用get_fundalmentals
函数查询相关财务数据并筛选出符合条件的股票
2.运用talib
读取MACD相关指标数值
3.利用if
条件语句以及and
、or
逻辑语句进行买入卖出条件设置
2 基本框架构建
在之前的教程中,我们基本上已经整理出交易之前策略构成的基本框架。下面我们对这一内容再次进行细化:
首先是initialize()
函数的设置。这里我们沿用之前的做法,将其分为多个自定义函数的形式:
def initialize(context):set_params() #设置相关参数set_backtest() #设置回测基本数据run_daily(trade, 'every_bar')def set_params():g.days=0 #起始日期为0g.refresh_rate=10 #调仓周期设置为10日def set_backtest():set_benchmark('000905.XSHG') #将基准设置为中证500set_option('use_real_price', True) #开启动态复权log.set_level('order', 'error') #设定报错等级
以及对滑点、手续费、过滤停牌、退市及ST股票的设置
#每天开盘前要做的事情
def before_trading_start(context):set_slip_fee(context)# 根据不同的时间段设置滑点与手续费
def set_slip_fee(context):set_slippage(FixedSlippage(0.02)) dt=context.current_dtif dt>datetime.datetime(2013,1, 1):set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')else:set_order_cost(OrderCost(open_tax=0, open_commission=0.003,close_commission=0.003, close_tax=0.001,min_commission=5), type='stock')# 过滤停牌、退市和ST股票
def paused_filter(security_list):current_data = get_current_data()security_list = [stock for stock in security_list if not current_data[stock].paused]return security_listdef delisted_filter(security_list):current_data = get_current_data()security_list = [stock for stock in security_list if not '退' in current_data[stock].name]return security_listdef st_filter(security_list):current_data = get_current_data()security_list = [stock for stock in security_list if not current_data[stock].is_st]return security_list
3 MACD数据读取
根据我们策略的内容,我们采用的思路是:筛选出股票池中质量较高的股票–>查询MACD指数–>买入卖出条件
再次复习我们熟悉的选股方法:财务指标。这里我们挑选出符合:
10<市净率(pe_ratio)<40,每股盈余(eps)>0.3,净资产收益率(roe)>15,净利润环比增长率>0.3,并按照市净率进行升序排列,取前五十只。
stock_to_choose = get_fundamentals(query(valuation.code, valuation.pe_ratio, valuation.pb_ratio,valuation.market_cap, indicator.eps, indicator.inc_net_profit_annual).filter(valuation.pe_ratio < 40,valuation.pe_ratio > 10,indicator.eps > 0.3,indicator.inc_net_profit_annual > 0.30,indicator.roe > 15).order_by(valuation.pb_ratio.asc()).limit(50), date=None)
将筛选后得到股票代码放置在stockpool的list列表中,以便之后对列表进行循环。
stockpool = list(stock_to_choose['code']) #将筛选出的股票代码存入list中stockpool = paused_filter(stockpool)stockpool = delisted_filter(stockpool)stockpool = st_filter(stockpool) #过滤停牌、退市及ST股票long_list = [] #买入列表short_list = [] #卖出列表hold = [] #持有列表
对于筛选出来的股票依次读取MACD数据。这里就需要用到talib
库中MACD
函数。TA-Lib中文全称为技术分析库,是一个广泛用在程序化交易中进行金融市场数据的技术分析的函数库。它提供了多种技术分析的函数,包含多种指标如ADX, MACD, RSI, 布林轨道等等,可以极大地方便我们量化投资中编程工作。
Talib中的MACD函数使用时格式为:
MACD(price, fastperiod=12, slowperiod=26, signalperiod=9)
传入函数的三个参数分别为短线周期、长线周期以及MACD的移动平滑周期。这里我们使用最常用的(12,26,9)组合。MACD()
函数返回值共有三个,分别为DIF,DEA和MACD
if g.days%g.refresh_rate == 0:for stock in stockpool:prices = attribute_history(stock,300, '1d',['close']) #取较长周期的数据,这里为300日price = array(prices['close']) #将price一列函数格式变为arraymacd_tmp = talib.MACD(price, fastperiod=12, slowperiod=26, signalperiod=20) #将参数传入MACD函数中DIF = macd_tmp[0] #返回的数据分别为短期慢线DIF、长期快线DEA及MACDDEA = macd_tmp[1]MACD = macd_tmp[2]
答疑与延伸:
-为什么要通过macd_tmp[0]来读取数据? 因为MACD返回的是一个包括三个元素的序列array,和从list中取元素类似,我们通过在其后加上0的方式分别取第一个元素和第二个元素。
-为什么要选取300日的历史数据? MACD存在一个问题,即若选取时间较短,则可能出现不收敛的状况,因此这里我们选取300日的数据。
4 买入卖出条件设置
策略中我们要判断长线和短线的位置问题。这里我们做一些简化,判断当日和三日前的MACD正负情况。
当日MACD为正且三日前MACD为负–>金叉形成 买入
当日MACD为负且三日前MACD为正–>死叉形成 卖出
将股票代码通过append()
函数放在相应的买卖列表当中。
if MACD[-1] > 0 and MACD[-4] < 0:long_list.append(stock) #将出现金叉的股票代码放入long_list中elif MACD[-1] < 0 and MACD[-4] > 0:short_list.append(stock) #将出现死叉的股票代码放入short_list中stockset = list(context.portfolio.positions.keys()) #获得当前持仓状况
当对筛选后保留的股票进行循环之后,符合条件的股票已经被放入买入或卖出列表中。下面查看当前所持有的股票,如果在卖出列表当中则全部卖出,不是则保留,并将股票代码放入hold[]列表中
for stock in stockset:if stock in short_list:order_target_value(stock, 0) #卖出在short_list中的股票else:hold.append(stock) #保留不在short_list中的股票并将代码放在hold[]中,表示可以继续持有
买入long_list中除去已持有的股票:
buy_list = [] #设定一个新的空的list代表需要买入的股票for stock in long_list:if stock not in hold:buy_list.append(stock) #把在long_list中目前未持有的股票放入buy_list中代表接下来需要买入的股票
将可用资金根据股票数量进行均分。为避免出现除数为0的状况在这里进行一个判断。
if len(buy_list)==0: #如果要买入列表股票数量为0Cash = context.portfolio.available_cashelse:Cash = context.portfolio.available_cash/len(buy_list)for stock in buy_list:order_target_value(stock, Cash) g.days = 1 else:g.days += 1 #天数+1进行调仓周期的循环
策略完成,进行回测
把买入卖出的代码写好,策略就写完了,完整代码如下:
import pandas as pd
import numpy as np
import talib ## 使用talib计算MACD的参数def initialize(context):set_params()set_backtest()run_daily(trade, 'every_bar')def set_params():g.days=0 g.refresh_rate=10 def set_backtest():set_benchmark('000905.XSHG') set_option('use_real_price', True) log.set_level('order', 'error')#每天开盘前要做的事情
def before_trading_start(context):set_slip_fee(context)# 根据不同的时间段设置滑点与手续费
def set_slip_fee(context):set_slippage(FixedSlippage(0.02)) dt=context.current_dtif dt>datetime.datetime(2013,1, 1):set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')else:set_order_cost(OrderCost(open_tax=0, open_commission=0.003,close_commission=0.003, close_tax=0.001,min_commission=5), type='stock')# 过滤停牌、退市、ST股票
def paused_filter(security_list):current_data = get_current_data()security_list = [stock for stock in security_list if not current_data[stock].paused]return security_listdef delisted_filter(security_list):current_data = get_current_data()security_list = [stock for stock in security_list if not '退' in current_data[stock].name]return security_listdef st_filter(security_list):current_data = get_current_data()security_list = [stock for stock in security_list if not current_data[stock].is_st]return security_list#######进行操作的过程#######
def trade(context):stock_to_choose = get_fundamentals(query(valuation.code, valuation.pe_ratio, valuation.pb_ratio,valuation.market_cap, indicator.eps, indicator.inc_net_profit_annual).filter(valuation.pe_ratio < 40,valuation.pe_ratio > 10,indicator.eps > 0.3,indicator.inc_net_profit_annual > 0.30,indicator.roe > 15).order_by(valuation.pb_ratio.asc()).limit(50), date=None)stockpool = list(stock_to_choose['code'])stockpool = paused_filter(stockpool)stockpool = delisted_filter(stockpool)stockpool = st_filter(stockpool)long_list = []short_list = []hold = []if g.days%g.refresh_rate == 0:for stock in stockpool:prices = attribute_history(stock,300, '1d',['close'])price = array(prices['close'])macd_tmp = talib.MACD(price, fastperiod=12, slowperiod=26, signalperiod=20)DIF = macd_tmp[0]DEA = macd_tmp[1]MACD = macd_tmp[2]# 判断MACD走向if MACD[-1] > 0 and MACD[-4] < 0:long_list.append(stock)elif MACD[-1] < 0 and MACD[-4] > 0:short_list.append(stock)stockset = list(context.portfolio.positions.keys())for stock in stockset:if stock in short_list:order_target_value(stock, 0) else:hold.append(stock)#如果不在卖出列表里则持有buy_list = []for stock in long_list:if stock not in hold:buy_list.append(stock)#新增的买入股票if len(buy_list)==0: Cash = context.portfolio.available_cashelse:Cash = context.portfolio.available_cash/len(buy_list)for stock in buy_list:order_target_value(stock, Cash) g.days = 1else:g.days += 1
python实现MACD均线择时策略相关推荐
- 【量化】基于聚宽实现MACD均线择时策略
MACD均线择时策略是十分基础的策略,适合咱们这种新手学习,这篇博客就分享一下基于聚宽实现MACD均线择时策略. 代码: 注:需要到聚宽的量化平台去运行. # MACD均线择时策略 ''' 筛选出符合 ...
- python量化交易--择时策略
1.在banban网爬取所有A股的股票名称和代码. 观察板板网站的股票,将在深圳上市和上海上市的A股信息爬取并保存到本地文件 2.传入股票代码,利用tushare api提取股票的所有历史数据,对股票 ...
- 择时策略1:一个金叉死叉(python)
学习目标:择时策略1:一个金叉买入死叉卖出策略 学习内容: 1:导入必要的库 import pandas as pd pd.set_option('expand_frame_repr', False) ...
- 搭建系统|别只盯MA、KDJ、MACD这些技术指标,择时策略也能叠加基本面指标!
前言 "搭建系统"专栏系列一直按以下的进程再不断地迭代开发工具: 我一直强调要搭建属于适合自己的股票量化交易系统,而不是照搬着拿别人的来用呢.也就是说我们要掌握搭建的方法,不断去调 ...
- 量化择时策略入门与实操-笔记(同花顺金融量化实验室python实现)
文字与代码来源:2022年第三届"大湾区杯"粤港澳金融数学建模竞赛在线讲座-6_哔哩哔哩_bilibili 目录 指数估值择时策略 指数轮动择时策略 基于风险平价模型的仓位管理策略 ...
- 【Python 量化交易】什么是择时策略
量化金融:什么是择时策略? 什么是市场择时? 市场择时概要 择时成本 损失机会的代价 交易成本的代价 真实例子 什么是市场择时? 市场择时,也可以叫做市场选时,是一种投资或者交易的策略.是一种基于某种 ...
- 添加布林带择时策略有多便捷!股票量化分析工具QTYX-V2.4.7
前言 布林带通道(Bollinger Bands)是非常经典的技术指标,常用于研判市场中长期运动趋势. 比如我们以[350, 2,2] 这组长线参数来绘制恒瑞医药.贵州茅台10年行情走势的布林带通道, ...
- 基于A股周内效应择时策略验证与思考(附代码)
基于A股周内效应择时策略验证与思考 本文思路来自于东吴证券研报<A股市场的周内效应>内容,对A股市场的日历效应在周内表现进行探索. 上述研报的核心内容简述: 1.A股市场在股票指数和个股上 ...
- 基于北向资金指数择时策略验证与思考
基于北向资金指数择时策略验证与思考 本文思路华泰金工研量化资产配置7月月报<北向资金走向预示市场短期或震荡>关于北上资金的择时思路,构建基于北向资金的股市择时策略,并进行历史回测.结果表明 ...
最新文章
- day 2 基本类型和函数
- 基于 Docker 的微服务架构实践
- Python基础 --- 使用 dict 和 set
- SpringBoot中整合freemarker时配置文件application.properties示例代码
- jmeter服务器测试项目,JMeter-项目测试
- 训练技巧 | 功守道:NLP中的对抗训练 + PyTorch实现
- php dns更新,php_mzdns: 站群,大量域名 通过 dns 服务商 api 批量添加 ip 工具。你懂的~ 基于 mzphp2 框架。...
- springCloud - 第1篇 - 服务的注册 Eureka
- 鸿蒙明年可以在手机上用吗,华为王成录:鸿蒙已满足在手机上使用,明年一二月份向部分用户开放...
- Java中@WebServlet的使用方法
- 中国天然蜂蜂蜜市场趋势报告、技术动态创新及市场预测
- 081 Search in Rotated Sorted Array II
- 区块链 Fisco bcos 智能合约(18)-FISCO BCOS的速度与激情:性能优化方案最全解密
- java连接mysql并在textarea输出_Java面试宝典Java IO篇
- 谈谈我对Ui设计师的一些观点
- mysql俩个表怎么创主外洁_单独招生面试题极其详细答案
- 如何成为名副其实的测试架构师?
- 删除文件后清空了回收站要怎么恢复
- ps顶级调色技术解密视频教程 终极大法
- jar 文件打不开解决的办法
热门文章
- 计算机毕业设计 ssm+vue毕设选题管理系统(源码+论文)
- JavaScript/Ajax/JQuery知识点(BOM/DOM/ScriptEngine/JS引擎),JSCore
- java 爱情程序_Java的爱情:巩固控制和循环语句
- 三星530换固态硬盘_华硕x550jx换固态硬盘或内存条等
- 电脑安全模式怎么进?3种方式教会你!
- 操作系统实验--30天自制操作系统第5天实验日志
- 公众号的变现方式-私域流量引流获客实战技能
- 三封信让你知道什么是政治
- 垂死病中惊坐起,好好锻炼来得及
- 电脑组成图解和组装步骤