我们借鉴唐奇安通道的思想,把它应用到期货日内的交易中。在当日交易中,我们会构建一个回溯周期60个bar的通道,每一个bar都是一分钟的蜡烛tick。当下一根bar收盘价高于这个通道的上限,则做多; 当下一根bar收盘价低于这个通道的下限,则做空。为避免交易次数过多,我们每天最多交易三次。并且我们会在当日晚盘快结束时,了结当日仓位。
import talib as ta
# 1. 策略基本参数
start_date = '2018-04-20 09:01:00'
end_date = '2018-05-20 15:15:00'
benchmark = instruments = 'RB1901.SHF'
TRADING_UNIT = 5
DAILY_TRADING_LIMITS = 2
LOOKBACK_WINDOW = 60
DAY_END_HOUR = 22
DAY_END_MINUTE = 50
EMPTY_POSITION = 0
# 2. 策略主体函数
# 初始化虚拟账户状态,只在第一个交易日运行
def initialize(context):
# 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
context.set_commission(futures_commission=PerContract(cost={'RB':(0.000045, 0.000045, 0.000045)}))
context.set_margin('RB', 0.07)
context.index = 1 #日期记录
context.position_counts = 0
# 策略交易逻辑,handle_data函数会每个周期(日/分)运行一次,可以把行情数据理解成K线,
# 然后handle_data函数会在每个K线上依次运行
def handle_data(context, data):
today = data.current_dt#.strftime('%Y-%m-%d-%H-%M')
instrument_symbol = context.future_symbol(context.instruments[0]) # 交易标的
curr_position = context.portfolio.positions[instrument_symbol].amount # 持仓数量
if context.index < LOOKBACK_WINDOW: # 日内数据超过窗口范围
context.index += 1
return
if today.hour >= DAY_END_HOUR and today.minute >= DAY_END_MINUTE:
context.index = 1 # 下标初始化
context.position_counts = 0
# 了结当日仓位
if curr_position != EMPTY_POSITION:
context.order_target(instrument_symbol, EMPTY_POSITION)
return
price = data.history(instrument_symbol, 'close', LOOKBACK_WINDOW, '1m')
# 如果当前没有仓位,且大于通道价格上限,long开仓
if curr_position <= 0 and price.iloc[-1] > price.iloc[(-1-LOOKBACK_WINDOW):-1].max() and context.position_counts < DAILY_TRADING_LIMITS:
context.position_counts += 1
context.order_target(instrument_symbol, TRADING_UNIT)
elif curr_position >= 0 and price.iloc[-1] < price.iloc[(-1-LOOKBACK_WINDOW):-1].min() and context.position_counts < DAILY_TRADING_LIMITS:
context.position_counts += 1
context.order_target(instrument_symbol, -TRADING_UNIT)
# 3. 启动回测
m = M.trade.v4(
instruments=instruments,
start_date=start_date,
end_date=end_date,
initialize=initialize,
handle_data=handle_data,
# 股票买入的时候,假设以次日开盘价成交
order_price_field_buy='open',
# 股票卖出的时候,假设以次日开盘价成交
order_price_field_sell='open',
capital_base=50000,
benchmark=benchmark,
volume_limit=0,
data_frequency='minute',
product_type='future',
m_deps=np.random.rand()
)