策略说明: 基于动量系统, 通过交易量加权进行判断
系统要素:
用VWM上穿零轴判断多头趋势
入场条件:
价格高于VWM上穿零轴时价格通道,且在SetupLen的BAR数目内,做多
出场条件:
空头势多单出场
import DataAPI
import numpy as np
import pandas as pd
import talib as ta
from collections import deque
from itertools import product
class DataCenter():
keys = [u’openPrice’, u’highPrice’, u’lowPrice’, u’closePrice’, u’turnoverVol’]
def init(self, refresh_rate, pipe_length):
self.data = {key:deque([], maxlen=pipe_length) for key in (self.keys + [‘tradeTime’])}
self.refresh_rate = refresh_rate
self.pipe_length = pipe_length
def update_data(self, symbol):
if len(self.data['openPrice']) < self.pipe_length:
hist = history(symbol=symbol, attribute=self.keys, time_range=self.refresh_rate*self.pipe_length, freq='m', rtype='frame')[symbol]
else:
hist = history(symbol=symbol, attribute=self.keys, time_range=self.refresh_rate, freq='m', rtype='frame')[symbol]
# hist.index = range(len(hist))
current_data = {key:[] for key in (self.keys + ['tradeTime'])}
for i in range(len(hist)/self.refresh_rate):
current_bar = hist[self.refresh_rate*i:self.refresh_rate*(i+1)]
current_data['closePrice'].append(current_bar.ix[len(current_bar)-1, 'closePrice'])
current_data['openPrice'].append(current_bar.ix[0, 'openPrice'])
current_data['highPrice'].append(current_bar['highPrice'].max())
current_data['lowPrice'].append(current_bar['lowPrice'].min())
current_data['turnoverVol'].append(current_bar['turnoverVol'].sum())
current_data['tradeTime'].append(current_bar.index[len(current_bar)-1])
for i in self.keys:
for j in current_data[i]:
self.data[i].append(j)
return self.data
def crossover(a, b):
if a[-2] < b[-2] and a[-1] > b[-1]:
return True
else:
return False
def crossunder(a, b):
if a[-2] > b[-2] and a[-1] < b[-1]:
return True
else:
return False
universe = [‘RBM0’] # 策略期货合约
start = ‘2016-01-01’ # 回测开始时间
end = ‘2016-12-31’ # 回测结束时间
refresh_rate = 5 # 调仓周期
freq = ‘m’ # 调仓频率:m-> 分钟;d-> 日
momlen = 5 # VWM参数
avglen = 20 # VWM参数
atrlen = 5 # ATR参数
atrpcnt = 0.5 # 入场价格波动率参数
setuplen = 5 # 条件持续有效K线数
accounts = {
‘futures_account’: AccountConfig(account_type=’futures’, capital_base=1000000)
}
def initialize(context): # 初始化虚拟期货账户,一般用于设置计数器,回测辅助变量等。
global data_pool
data_pool = DataCenter(refresh_rate, avglen+momlen+1)
context.symbol = ‘RB1605’
context.current_bar = 0
context.lsetup = 0
context.leprice = np.NAN
def handle_data(context): # 回测调仓逻辑,每个调仓周期运行一次,可在此函数内实现信号生产,生成调仓指令。
futures_account = context.get_account(‘futures_account’)
symbol = context.symbol
long_position = futures_account.position.get(symbol, dict()).get(‘long_amount’, 0)
if context.get_symbol(universe[0]) != symbol:
if long_position != 0:
print futures_account.current_date, futures_account.current_time, ‘主力更换, 平仓’
print context.get_symbol(universe[0])
order(futures_account.symbol, -long_position, ‘close’)
futures_account.symbol = context.get_symbol(universe[0])
else:
data = data_pool.update_data(symbol)
high = np.array(data['highPrice'])
low = np.array(data['lowPrice'])
close = np.array(data['closePrice'])
open_ = np.array(data['openPrice'])
volume = np.array(data['turnoverVol'])
# 计算动量
vwm = ta.EMA(ta.MOM(close, momlen)*volume, avglen)
atr = ta.ATR(high, low, close, atrlen)[-1]
bullsetup = crossover(vwm, [0]*2)
bearsetup = crossunder(vwm, [0]*2)
if bullsetup:
context.lsetup = 0
context.leprice = close[-1]
else:
context.lsetup += 1
if context.current_bar > avglen and long_position == 0:
if high[-1] > context.leprice + atrpcnt*atr and context.lsetup <= setuplen and context.lsetup >= 1:#价格高于VWM上穿零轴时价格通道,且在SetupLen的BAR数目内,做多
futures_account.order(symbol, 10, 'open')
if long_position != 0:
if bearsetup == True: #空头势多单出场
futures_account.order(symbol, -long_position, 'close')
context.current_bar += 1