“趋势是你的朋友”这是每一个交易者都耳熟能详的箴言。但做过交易的朋友可能会有体会,趋势总是在毫无预警地开始并突然结束。那么在CTA策略中,如何抓住趋势并过滤震荡行情,是许多主观和量化交易者孜孜不倦的追求。在本节课程中,我们将以平均趋向指数(ADX)为滤网,分析在它量化交易中的应用。
# 回测配置 '''backtest start: 2015-02-22 00:00:00 end: 2019-10-17 00:00:00 period: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] ''' # 导入库 import talib import numpy as np mp = 0 # 定义一个全局变量,用于控制虚拟持仓 # 把K线数组转换成最高价、最低价、收盘价数组,用于转换为numpy.array类型数据 def get_data(bars): arr = [[], [], []] for i in bars: arr[0].append(i['High']) arr[1].append(i['Low']) arr[2].append(i['Close']) return arr # 判断两根两个数组是否金叉 def is_up_cross(arr1, arr2): if arr1[len(arr1) - 2] < arr2[len(arr2) - 2] and arr1[len(arr1) - 1] > arr2[len(arr2) - 1]: return True # 判断两根两个数组是否死叉 def is_down_cross(arr1, arr2): if arr1[len(arr1) - 2] > arr2[len(arr2) - 2] and arr1[len(arr1) - 1] < arr2[len(arr2) - 1]: return True # 程序主函数 def onTick(): exchange.SetContractType("rb000") # 订阅期货品种 bar_arr = exchange.GetRecords() # 获取K线数组 if len(bar_arr) < long + m + 1: # 如果K线数组长度太小,就不能计算MACD,所以直接返回跳过 return all_macd = TA.MACD(bar_arr, short, long, m) # 计算MACD值,返回的是一个二维数组 dif = all_macd[0] # 获取DIF的值,返回一个数组 dif.pop() # 删除DIF数组最后一个元素 dea = all_macd[1] # 获取DEA的值,返回一个数组 dea.pop() # 删除DEA数组最后一个元素 np_arr = np.array(get_data(bar_arr)) # 把列表转换为numpy.array类型数据,用于计算ADX的值 adx_arr = talib.ADX(np_arr[0], np_arr[1], np_arr[2], 14); # 计算ADX的值 adx1 = adx_arr[len(adx_arr) - 2] # 倒数第二根K线的ADX值 adx2 = adx_arr[len(adx_arr) - 3] # 倒数第三根K线的ADX值 last_close = bar_arr[len(bar_arr) - 1]['Close'] # 获取最新价格(卖价),用于开平仓 global mp # 全局变量,用于控制虚拟持仓 # 开多单 if mp == 0 and dif[len(dif) - 1] > 0 and adx1 > 45: exchange.SetDirection("buy") # 设置交易方向和类型 exchange.Buy(last_close, 1) # 开多单 mp = 1 # 设置虚拟持仓的值,即有多单 # 开空单 if mp == 0 and dif[len(dif) - 1] < 0 and adx1 > 45: exchange.SetDirection("sell") # 设置交易方向和类型 exchange.Sell(last_close - 1, 1) # 开空单 mp = -1 # 设置虚拟持仓的值,即有空单 # 平多单 if mp == 1 and (is_down_cross(dif, dea) or adx1 < adx2): exchange.SetDirection("closebuy") # 设置交易方向和类型 exchange.Sell(last_close - 1, 1) # 平多单 mp = 0 # 设置虚拟持仓的值,即空仓 # 平空单 if mp == -1 and (is_up_cross(dif, dea) or adx1 < adx2): exchange.SetDirection("closesell") # 设置交易方向和类型 exchange.Buy(last_close, 1) # 平空单 mp = 0 # 设置虚拟持仓的值,即空仓 def main(): while True: onTick() Sleep(1000)