小指标大用处-巧用MACD指标做ETF择时:实现年化28+\%收益
为了感谢管理员通过我的专栏申请,再分享一个实盘策略。
这次的策略,我曾经在ptrade上实盘过1年多,由于标的盘口原因,上不了规模,但确实是盈亏比非常合适的策略,在这里分享给大家。
回顾下策略核心,它是利用经典的 MACD 指标进行交易决策,选定了512670、512480、513050三个ETF作为操作标的。每天开盘前 9:00 准备就绪,记录当天日期;开盘时段按 5 分钟间隔检查股票 MACD 指标,依据 DIFF 线与 0 轴的交叉情况,结合持仓状态决定买卖操作;收盘后记录当天交易结束时间,方便复盘。
注意:这个策略在不同的标的上,表现差异较大,所以,需要挑选合适的标的。
看看回测数据呈现出的策略表现:
-
收益对比:策略收益达到了惊人的 172.9%,而同期基准收益却是 -5.49%,这一正一负的鲜明对比,直观展现出策略在盈利能力上远超基准。
-
年化收益率:策略年化收益率为 28.53%,意味着长期下来每年有这样可观的增值速度,反观基准年化收益仅 -1.4%,进一步凸显策略优势。
-
风险评估指标:
-
Alpha 值为 0.28,说明策略相对基准有一定的超额收益获取能力。
-
Beta 值 0.46,显示策略与市场的相关性程度,相对较低的数值表明策略受市场整体波动影响较小。
-
Sharpe 比率达到 1.56,这可是衡量风险调整后收益的关键指标,越高说明在同等风险下收益越好,咱这策略表现相当亮眼。
-
Sortino 比率 2.47,着重考量下行风险下的收益,数值越高,在面对不利行情时策略的表现越佳。
-
其他关键指标:
-
Information Ratio 为 1.42,反映策略主动管理风险获取超额收益的能力。
-
Volatility 即波动率为 0.17,体现收益的波动幅度较小,收益稳定性较好。
-
最大回撤 10.76%,表示策略在最不利阶段的净值下跌幅度,处于相对可控范围。
-
Tracking Error 为 0.18,说明策略与基准的偏离程度,一定程度反映策略的独立性。
-
Downside Risk 为 0.11,再次强调下行风险状况。
-
胜率 45.8%,意味着交易成功次数占比近半,而次胜率 38.55% 也为策略表现提供了更多细节支撑。
下面是回测的截图:
接下来是源代码,欢迎交流。因为ptrade账号注销,ptrade的代码没有保留。这份代码是基于其他量化平台的,修改部分函数名后,可以在ptrade平台上直接运行。如果需要交流代码,也可以私信我。
# 股票策略模版
# 引入talib库
import talib
def init(context):
# 设置基准收益:沪深300指数
set_benchmark('512100.SH')
# 打印日志
log.info('策略开始运行,初始化函数全局只运行一次')
# 设置股票每笔交易的手续费为万分之一点五(手续费在买卖成交后扣除,不包括税费,税费在卖出成交后扣除)
set_commission(PerShare(type='stock',cost=0.00015))
# 设置股票交易滑点0.05%,表示买入价为实际价格乘1.0005,卖出价为实际价格乘0.9995
set_slippage(PriceSlippage(0.000))
# 设置日级最大成交比例25%,分钟级最大成交比例50%
# 日频运行时,下单数量超过当天真实成交量25%,则全部不成交
# 分钟频运行时,下单数量超过当前分钟真实成交量50%,则全部不成交
set_volume_limit(0.25,0.5)
# 设置要操作的股票:
g.security = ['512670.SH','512480.SH','513050.SH'] #输入股票代码,'513050.SH'
#设置MACD模型参数
g.Short = 12 #短周期平滑均线参数
g.Long = 26 #长周期平滑均线参数
g.M = 9 #DIFF的平滑均线参数
g.day_Short = 12 #短周期平滑均线参数
g.day_Long = 26 #长周期平滑均线参数
g.day_M = 9 #DIFF的平滑均线参数
#每日开盘前9:00被调用一次,用于储存自定义参数、全局变量,执行盘前选股等
def before_trading(context):
# 获取日期
date = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
# 打印日期
log.info('{} 盘前运行'.format(date))
## 开盘时运行函数
def handle_bar(context, bar_dict):
if is_multiple_of_5_minutes(get_datetime()):
for stock_code in g.security:
diff,dea,macd = get_macd(stock_code)
if diff[-1]>0 and diff[-2]<0 and context.portfolio.stock_account.positions[stock_code].amount == 0:
log.info("======================触发买入信号",stock_code)
av_cash = context.portfolio.stock_account.available_cash
target_postion = context.portfolio.total_value/len(g.security)
target_val = min(av_cash,target_postion)
order_id = order_value(stock_code,target_val)
try:
log.info(order_id)
avg_price =get_order(order_id).avg_price
log.info("买入 %s" % (stock_code),"价格 %F" % (avg_price))
except:
log.info("买入 %s" % (stock_code))
if diff[-1]<0 and context.portfolio.stock_account.positions[stock_code].available_amount > 0:
log.info("======================触发卖出信号",stock_code)
try:
order_id = order_target(stock_code,0)
log.info(order_id)
avg_price =get_order(order_id).avg_price
log.info("卖出 %s" % (stock_code),"价格 %F" % (avg_price))
except:
log.info("卖出 %s" % (stock_code))
## 获取macd指标
def get_macd(stock):
price = history(stock, ['close'], 100, '5m', True, 'pre', is_panel=1)['close']
DIFF, DEA, MACD = talib.MACD(price.values,
fastperiod = g.Short, slowperiod = g.Long, signalperiod = g.M)
return DIFF,DEA,MACD
## 获取macd指标
def get_day_macd(stock):
price = history(stock, ['close'], 500, '30m', True, 'pre', is_panel=1)['close']
DIFF, DEA, MACD = talib.MACD(price.values,
fastperiod = g.day_Short, slowperiod = g.day_Long, signalperiod = g.M)
return DIFF,DEA,MACD
## 判断是否是5分钟
def is_multiple_of_5_minutes(dt):
minutes = dt.minute
return minutes % 5 == 0
## 收盘后运行函数,用于储存自定义参数、全局变量,执行盘后选股等
def after_trading(context):
# 获取时间
time = get_datetime().strftime('%Y-%m-%d %H:%M:%S')
# 打印时间
log.info('{} 盘后运行'.format(time))
log.info('一天结束')
北京炒家的打首板模式很火,近期在研究如何通过ptrade进行自动监控首板并第一时间参与扫板。
目前已经完成了简单的交易框架代码,有兴趣的朋友也欢迎一起交流。
2025-02-10 21:48
2025-01-17 17:48
2025-01-17 17:47
2025-01-16 15:59
2025-01-15 18:05
2025-01-14 21:24
2025-01-14 21:12