期货专用与定时任务
前面几章覆盖了股票主流程。本章讲两类进阶内容:一是期货的专用 API(开平仓、合约查询、保证金与手续费设置),二是定时任务和 tick 级处理(run_daily / run_interval / tick_data / set_parameters),它们是日内和套利策略的核心工具。
一、期货交易函数
A 股只能做多,期货天然双向。PTrade 用四个函数对应「开仓 / 平仓」×「多 / 空」:
| 函数 | 含义 | 方向 |
|---|---|---|
buy_open(contract, amount, limit_price=None) | 买入开仓 | 做多建仓 |
sell_close(contract, amount, limit_price=None, close_today=False) | 卖出平仓 | 平多头 |
sell_open(contract, amount, limit_price=None) | 卖出开仓 | 做空建仓 |
buy_close(contract, amount, limit_price=None, close_today=False) | 买入平仓 | 平空头 |
amount均为正数(手数)。close_today:仅上海期货交易所生效,True仅平今仓;其他交易所不要传True,否则会被强制转为False。- 不传
limit_price时以行情快照最新价(交易)或分钟最新价(回测)报单。
def handle_data(context, data):
# 开 1 手多仓
buy_open('IF2312.CCFX', 1)
# 平 1 手空仓
buy_close('IF2312.CCFX', 1)
# 做空 1 手
sell_open('IF2312.CCFX', 1)
# 平 1 手多仓(上期所可指定仅平今)
sell_close('CU2312.SHF', 1, close_today=True)
二、期货合约查询
| 函数 | 含义 |
|---|---|
get_instruments(contract) | 合约详情:乘数、交易单位、交割日、上市日、保证金、涨跌幅、最小变动价位 |
get_dominant_contract(contract, date=None) | 连续合约对应的主力合约代码 |
get_margin_rate(transaction_code) | 用户设置的保证金比例(仅回测) |
# 取 IF 当前主力合约
main = get_dominant_contract('IF888.CCFX')['IF888.CCFX']['corr_month_code']
log.info('IF 主力合约:%s' % main)
# 查合约详情
info = get_instruments('IF2312.CCFX')
log.info('乘数 %s,保证金 %s' % (info['contract_multiplier'], info['margin_rate']))
回测中建议用连续合约代码(如
IF888.CCFX)做信号,再用get_dominant_contract映射到具体月合约下单;实盘要换成当日上市的具体合约。合约详情 API 依赖期货资料数据权限,无权限返回空 dict。
三、期货回测设置
| 函数 | 含义 | 示例 |
|---|---|---|
set_margin_rate(code, rate) | 设置保证金比例 | set_margin_rate('IF', 0.08) |
set_future_commission(code, commission) | 设置手续费 | set_future_commission('IF', 0.00004) |
股指期货按成交额比例收(如 0.4/万 = 0.00004),国债期货按每手金额收(如 2 元/手 = 2)。两者都仅在回测可用,实盘按真实柜台费率。
四、期货双均线示例
import numpy as np
def initialize(context):
g.target = 'IF'
g.security = g.target + '888.CCFX' # 连续合约
g.amount = 1
if not is_trade():
set_limit_mode('UNLIMITED')
set_margin_rate(g.target, 0.15)
def before_trading_start(context, data):
h = get_history(20, '1d', 'close', g.security, fq='dypre',
include=False, is_dict=True)
g.close = h[g.security]['close']
def handle_data(context, data):
price = data[g.security].close
close = np.concatenate((g.close, [price]))
ma5, ma10 = close[-5:].mean(), close[-10:].mean()
pos = get_position(g.security)
if ma5 > ma10:
if pos.long_amount == 0:
buy_open(g.security, g.amount) # 开多
if pos.short_amount != 0:
buy_close(g.security, g.amount) # 平空
elif ma5 < ma10:
if pos.short_amount == 0:
sell_open(g.security, g.amount) # 开空
if pos.long_amount != 0:
sell_close(g.security, g.amount) # 平多
要点:期货持仓对象把多头和空头分开(long_amount / short_amount / long_enable_amount / short_enable_amount),判断时要分别看。
五、定时任务:run_daily
run_daily(context, func, time='9:31')
- 只能在
initialize中调用,可多次调用注册多个定时任务。 func须以context为唯一参数。- 分钟回测中
time须在 9:3111:30、13:0015:00;日回测无论设何值都在 15:00 执行;交易中范围 00:00~23:59。
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
run_daily(context, get_data, time='9:25') # 盘前取数据
run_daily(context, clear_pos, time='14:55') # 尾盘清仓
def get_data(context):
snap = get_snapshot(g.security)
log.info(snap)
def clear_pos(context):
if get_position(g.security).enable_amount > 0:
order_target(g.security, 0)
def handle_data(context, data):
pass
六、定时任务:run_interval
run_interval(context, func, seconds=10)
- 仅交易可用,在
initialize中注册。 - 非交易时段(9:30
11:30、13:0015:00 之外)不执行。 - 期货最小 1 秒,其他品种最小 3 秒。
run_daily+run_interval累计线程数上限 5,超过会堵塞丢任务。
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
run_interval(context, on_tick, seconds=3)
def on_tick(context):
snap = get_snapshot(g.security)
last = snap[g.security]['last_px']
log.info('最新价 %s' % last)
def handle_data(context, data):
pass
七、tick_data 事件
tick_data(context, data) 每 3 秒触发一次(9:30~14:59),data 是字典,含 tick / order(逐笔委托)/ transaction(逐笔成交)三项,后两项需开通 Level-2 行情。
import ast
def tick_data(context, data):
sec = g.security
bid1 = ast.literal_eval(data[sec]['tick']['bid_grp'][0])[1][0] # 买一价
if bid1 > 38.19:
order_tick(sec, 100, '1') # 以买一档下单
def handle_data(context, data):
pass
tick_data里的data与handle_data里的data结构不同,不要混用。
八、策略配置:set_parameters
set_parameters(not_restart_trade='1', server_restart_not_do_before='1', ...)
仅交易可用,用于控制引擎行为。关键参数:
| 参数 | 含义 |
|---|---|
not_restart_trade | 交易时段服务器重启时是否自动重拉交易,'1' 不重拉 |
server_restart_not_do_before | 重启重拉后是否跳过重复执行 before_trading_start,'1' 跳过 |
holiday_not_do_before | 节假日是否执行 before_trading_start,'1' 不执行 |
tick_data_no_l2 | tick_data 的 data 是否剔除 order/transaction,'1' 剔除 |
receive_other_response | 是否接收非本交易的主推,'1' 接收 |
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
set_parameters(not_restart_trade='1', server_restart_not_do_before='1')
取消设置:再次调用并传 '0'。
九、消息通知
| 函数 | 含义 |
|---|---|
set_email_info(email_address, smtp_code, email_subject) | 设置异常终止通知邮箱(仅 QQ 邮箱) |
send_email(send_email_info, get_email_info, smtp_code, info='', ...) | 主动发邮件 |
send_qywx(corp_id, secret, agent_id, info='', ...) | 发企业微信消息 |
策略出错终止时引擎可自动发邮件提醒,对无人值守的实盘很有用。
小结
- 期货四件套:
buy_open/sell_close/sell_open/buy_close,对应多空开平;用连续合约做信号、主力合约下单。 - 定时任务用
run_daily(固定时刻)和run_interval(固定间隔),线程上限 5;tick 级用tick_data事件。 - 用
set_parameters控制重启、节假日、主推等引擎行为,让策略在实盘更稳。至此 PTrade 手册从机制、框架、函数、两融、回测、示例到进阶形成闭环——左侧导航可随时回查。