量化交易-MACD策略學習

MACD的基本概念,可以參考 ofollow,noindex">https://www.joinquant.com/post/7095?f=18newyearjx ,感謝 Quant中找米吃的阿鼠 和 聚寬小祕書 Thanks♪(・ω・)ノ
我認為MACD不適合採用輪動策略,經過回測,我將策略改成以下模式::laughing:
- 選出基本面較好的股票
- 剔除ST、停牌、退市的股票
- 在DIF和DEA在0軸上形成金叉時買入
- 在DIF他DEA的0軸下形成死叉時賣出
- 加入止損:這次的止損買有根據股票的盈虧來判斷,而是:
- 記錄持倉股票的每天的盈利,如果當天盈利比之前的盈利小,則不記錄
- 如果當天判斷的盈利已經比記錄的最大盈利小20%,則止損賣出
下面:point_down:是回測結果和原始碼

import numpy as np import pandas as pd # 匯入技術分析庫 import talib as tb def initialize(context): """初始化函式""" # 記錄股票的收益率 g.retio = {} # 設定中證500為參考基準 set_benchmark('000905.XSHG') # 使用真實價格交易 set_option('use_real_price', True) # 設定日誌級別 log.set_level('order', 'error') # 指定週期性交易函式 run_daily(trade, 'every_bar') def before_trading_start(context): """開盤前設定交易費用""" # 設定所有型別的交易品種的交易滑點為0.02 set_slippage(FixedSlippage(0.02)) # 設定2013年前與2013年後的交易費用 dt = context.current_dt if 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') def trade(context): """交易函式""" # g.days += 1 # if g.days % g.refresh_rate != 1: #return '''一、挑選出高質量的股票''' stocks_choose = get_fundamentals( query( valuation.code ).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) # 將股票程式碼集轉成ndarray,因為它比列表的計算速度更快 stocks_pool = stocks_choose['code'].values '''二、剔除st、停牌、退市的股票''' current_data = get_current_data() # 剔除停牌 stocks_pool = [stock for stock in stocks_pool if not current_data[stock].paused] # 剔除st stocks_pool = [stock for stock in stocks_pool if not current_data[stock].is_st] # 剔除退市 stocks_pool = [stock for stock in stocks_pool if not '退' in current_data[stock].name] '''三、股票交易條件判斷''' # 買入列表 stocks_long = [] # 賣出列表 stocks_short = [] # 繼續持有列表 stocks_hold = [] #MACD判斷 for stock in stocks_pool: # 獲得之前300天的收盤價 prices = attribute_history(stock, 300, '1d', ['close']) # 將價格值轉換成ndarray price = np.array(prices['close']) # 計算MACD值 DIF, DEA, MACD = tb.MACD( price, fastperiod=12, slowperiod=26, signalperiod=20) # 在0軸上金叉買入 if DIF[-1] > 0 and DEA[-1] > 0: if (DIF[-2] <= DEA[-2]) and (DIF[-1] > DEA[-1]): stocks_long.append(stock) # 在0軸之下死叉賣出 elif DIF[-1] < 0 and DEA[-1] < 0: if (DIF[-2] >= DEA[-2]) and (DIF[-1] < DEA[-1]): stocks_long.append(stock) '''四、賣出持倉中符合賣出條件的股票''' # 持倉 hold_list = list(context.portfolio.positions.keys()) # 判斷 for stock in hold_list: # 計算持倉股票的收益率 cost = context.portfolio.positions[stock].avg_cost price = context.portfolio.positions[stock].price ret = (price/cost) - 1 # 記錄收益率,如果當前收益率比之前大,替換之前的記錄 # 如果當前收益率比記錄的最大收益率小20%,止損,賣出 if stock in g.retio.keys(): if ret > g.retio[stock]: g.retio[stock] = ret elif (ret - g.retio[stock]) < -0.2: order_target_value(stock, 0) del g.retio[stock] else: g.retio[stock] = ret # 將在賣出列表中的股票賣出 if stock in stocks_short: order_target_value(stock, 0) # 繼續持倉的股票 else: stocks_hold.append(stock) '''五、買入符合條件的股票''' # 買入列表,已經持倉的不再重複買入 buy_list = list(set(stocks_long) - set(stocks_hold)) # 買入 if len(buy_list) > 0: Cash = context.portfolio.available_cash / len(buy_list) for stock in buy_list: order_value(stock, Cash)