基础API
策略程序接口
备注
用户编写的策略文件需实现以下部分策略程序接口函数,才能被QFF框架识别并正确执行。
initialize - 策略初始化
- initialize(context)
初始化函数 - 在回测和实时模拟交易只会在启动的时候触发一次,用于初始一些全局变量。作为策略文件的入口,本方法必须实现。
在初始化函数中,除了初始化全局变量,用户可以设置基准、交易费率、固定滑点等参数。 另外通过调用
run_daily(),还可以配置定时运行的策略函数,用以替代其他的框架函数。- 参数
context (
Context对象) – 策略上下文,存放有当前的账户/股票持仓信息- Example
def initialize(context): # 设置指数基准 set_benchmark(security="000300") # 定义一个全局变量, 保存要操作的股票 g.security = ['000001', '000002'] # 定义运行函数 run_daily(market_open, run_time='09:50') log.info("initialize : 初始化运行")
handle_data - 盘中策略运行函数(可选)
- handle_data(context, data)
盘中策略运行函数 - 该函数每个单位时间会调用一次, 如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次。 如果在initialize()函数中run_daily设置了盘中策略函数,则本函数可以不实现。
该函数运行的时间是股票的交易时间,即 9:30 - 15:00。
该函数在回测中的非交易日是不会触发的(如回测结束日期为2021年1月5日,则程序在2022年1月1日-3日时,handle_data不会运行,4日继续运行)。
对于使用日级回测或模拟, 策略内获取到逻辑时间(context.current_dt)是 9:30。
- 参数
context (
Context对象) – 策略上下文, 存放有当前的账户/股票持仓信息data (Dict[
SecurityUnitData]) – 一个字典(dict), key是股票代码, value是当时的SecurityUnitData对象,存放当前时间的股票数据,与使用get_current_data()功能相同。注意: 为了加速, data 里面的数据是按需获取的, 每次 handle_data 被调用时, data 是空的 dict, 当你使用data[security]时该 security 的数据才会被获取.
- Example
def handle_data(context, data): for code in g.security: # 获取当前时间点的股票数据 last_price = data[code].last_price average_price = data[code].mavg(20, 'close') # 获取账户剩余资金 cash = context.portfolio.available_cash if last_price > average_price: # 下单买入指定金额的股票 order_value(code, cash) elif last_price < average_price: # 卖出指定股票 order_target(code, 0) # 在交易时间段内的策略函数中,使用 :func:`get_current_data` 来获取当前时间点的数据,此数据只在这一个时间点有效,请不要存起来到下一个 handle_data 再用。 # :class:`.Context` 为全局变量,在策略函数中可以访问,但不能对context对象属性进行修改和赋值。
before_trading_start - 开盘前运行策略(可选)
- before_trading_start(context)
开盘前运行函数 - 该函数会在每天开始交易前被调用一次, 您可以在这里添加一些每天都要初始化的东西。比如根据历史量价数据或基本面数据, 选择符合策略条件的股票加入股票池,再根据当日开盘后的表现,进行买入或卖出。需要注意,不能在这个函数中发送订单。
该函数依据的时间是股票的交易时间,即该函数启动时间为’09:00’。
- 参数
context (
Context对象) – 策略上下文,存放有当前的账户/股票持仓信息- Example
def before_trading_start(context): log.info(context.current_dt)
after_trading_end - 收盘后运行策略(可选)
on_strategy_end - 策略运行结束时调用函数(可选)
process_initialize - 策略恢复启动时运行函数(可选)
策略执行函数
run_file - 执行指定的策略文件
- qff.frame.api.run_file(strategy_file, run_type='bt', resume=False, freq='day', cash=1000000, start=None, end=None, name=None, output_dir=None, log_level='info', trace=False)[源代码]
运行策略文件,并初始化环境参数。
- 参数
strategy_file (
str) – 待运行策略文件路径run_type (
str) – 指定策略运行方式。bt-回测; sim-实盘模拟, 默认值为btresume (
bool) – 是否执行恢复运行, True-恢复以前的策略执行,False-重新开始执行策略,默认False.freq (
str) – 策略执行频率,有效值为 ‘day’,’min’,’tick’,默认值为 ‘day’cash (
int) – 账户初始资金,默认值1000000start (
Optional[str]) – 回测开始日期,默认为结束日期前60个交易日end (
Optional[str]) – 回测结束日期, 默认为上一个交易日name (
Optional[str]) – 策略名称output_dir (
Optional[str]) – 指定结果数据输出目录log_level (
str) – 控制台日志输出的级别, 有效值为 ‘debug’, ‘info’, ‘warning’, ‘error’,默认值为‘info’trace (
bool) – 策略运行过程中是否进行交互,模拟交易时自动有效
- 返回
None
- Example
使用方法:一般在策略文件中的尾部加入以下代码
if __name__ == '__main__': run_file(__file__, 0, start='2022-06-01', end='2022-08-31')
策略设置函数
run_daily - 定时运行策略设置函数(可选)
- qff.frame.api.run_daily(func, run_time='every_bar', append=True)[源代码]
设置定时运行的策略函数。回测环境/模拟专用API
指定每天要运行的函数, 可以在具体交易日的某一分钟执行。
- 参数
func (
Callable) – 一个自定义的函数,此函数必须接受context参数。例如自定义函数名market_open(context)。run_time (
str) –具体执行时间,一个字符串格式的时间:
交易时间内的任意时间点,上午“09:30-11:30”, 下午“13:01-15:00”,例如”10:00”, “14:00”;
every_bar,运行时间和您设置的运行频率一致,按天会在交易日的开盘时调用一次,按分钟会在交易时间每分钟运行。执行后将替代handle_data()策略框架函数.
before_open,设置func在开盘前运行,执行后将替代before_trading_start()策略框架函数.
after_close,设置func在收盘后运行,执行后将替代after_trading_end()策略框架函数.
append (
bool) – 如果run_time已注册运行函数,新函数是在原函数前面运行还是后面运行。append=True: 则新函数是在原函数后面运行。
备注
一个策略中尽量不要同时使用run_daily和handle_data,更不能使用run_daily(handle_data, “xx:xx”) run_daily中的函数只能有一个参数context,具体示例如下:
- Example
def initialize(context): run_daily(func, run_time='10:00') def func(context): print(context.current_dt) print('-'*50) # 参数 func 必须是一个全局的函数, 不能是类的成员函数, 并且func是可重入函数,即可重复调用。
- 返回类型
None
set_benchmark - 设置指数基准
set_order_cost - 设置交易税费
- qff.frame.api.set_order_cost(open_tax=0, close_tax=0.001, open_commission=0.0002, close_commission=0.0002, min_commission=5)[源代码]
设置佣金和印花税率。
指定每笔交易要收取的手续费, 系统会根据用户指定的费率计算每笔交易的手续费
- 参数
open_tax (
float) – 买入时印花税,默认值为0close_tax (
float) – 卖出时印花税,默认值为千分之一open_commission (
float) – 买入时佣金,默认值为万分之二close_commission (
float) – 卖出时佣金,默认值为万分之二min_commission (
float) – 最低佣金,不包含印花税,默认值为5
- 返回类型
None
set_slippage - 设置固定滑点
set_universe - 定股票值(history函数专用)
pass_today - 跳过当日(回测专用)
股票交易函数
order - 按股票数量下单
- qff.frame.order.order(security, amount=100, price=None, callback=None)[源代码]
按股票数量下单
调用成功后, 您将可以调用
get_open_orders()取得所有未完成的交易, 也可以调用order_cancel()取消交易- 参数
security (
str) – 标的代码amount (
int) – 交易数量, 正数表示买入, 负数表示卖出price (
Optional[float]) – 下单价格,下单价格为空,则认为是市价单,按当前最新价格挂单,否则认为是限价单callback (
Optional[Callable]) – 回调函数,订单成交/取消后调用执行, callback(status)
- 返回类型
Optional[str]- 返回
成功返回order对象id,失败返回None
订单撮合规则:
为简化操作,撮合时不考虑成交量,一个订单一次成交记录
市价单买入时按当前价格+滑点价格,转成限价单。如果当前价格为涨停价格,则订单取消。
市价单卖出时按当前价格-滑点价格,转成限价单。如果当前价格为跌停价格,则订单取消。
如果运行频率为天,则下单后立即撮合,读取剩余的分钟数据曲线,判断最高价是否大于委托价,是则成交。
如果运行频率为分钟,则下单后,每分钟都判断该订单是否符合成交条件。
对未成交的订单,在本交易日结束后撤销。
order_value - 按股票价值下单
- qff.frame.order.order_value(security, value, price=None, callback=None)[源代码]
按股票价值下单
- 参数
security (
str) – 股票代码value (
float) – 股票价值,value = 最新价 * 手数 * 乘数(股票为100)price (
Optional[float]) – 下单价格,市价单可不填价格,按当前最新价格挂单callback (
Optional[Callable]) – 回调函数,订单成交/取消后调用执行, callback(status)
- 返回类型
Optional[str]- 返回
Order对象id或者None, 如果创建委托成功, 则返回Order对象id, 失败则返回None
- Example
# 卖出价值为10000元的平安银行股票 order_value('000001', -10000)
order_target - 按股票目标数量下单
- qff.frame.order.order_target(security, amount, price=None, callback=None)[源代码]
按股票目标数量下单
使最终标的的数量达到指定的amount。 注意使用此接口下单时若指定的标的有未完成的订单,则先前未完成的订单将会被取消
- 参数
security (
str) – 股票代码amount (
int) – 期望的标的最终持有的股票数量price (
Optional[float]) – 下单价格,市价单可不填价格,按当前最新价格挂单callback (
Optional[Callable]) – 回调函数,订单成交/取消后调用执行, callback(status)
- 返回类型
Optional[str]- 返回
Order对象id或者None, 如果创建委托成功, 则返回Order对象id, 失败则返回None
order_target_value - 按股票目标价值下单
- qff.frame.order.order_target_value(security, value, price=None, callback=None)[源代码]
按股票目标价值下单
调整标的仓位到value价值, 注意使用此接口下单时若指定的标的有未完成的订单,则先前未完成的订单将会被取消
- 参数
security (
str) – 股票代码value (
float) – 期望的标的最终价值,value = 最新价 * 手数 * 乘数(股票为100)price (
Optional[float]) – 下单价格,市价单可不填价格,按当前最新价格挂单callback (
Optional[Callable]) – 回调函数,订单成交/取消后调用执行, callback(status)
- 返回类型
Optional[str]- 返回
Order对象id或者None, 如果创建委托成功, 则返回Order对象id, 失败则返回None
- Example
# 卖出价值为10000元的平安银行股票 order_value('000001', -10000) #卖出平安银行所有股票 order_target_value('000001', 0) #调整平安银行股票仓位到10000元价值 order_target_value('000001', 10000)
order_cancel - 撤回已下的订单
get_orders - 获取当天的所有订单
- qff.frame.order.get_orders(order_id=None, security=None, status=None)[源代码]
获取当天的所有订单
- 参数
order_id (
Optional[str]) – 订单 idsecurity (
Optional[str]) – 标的代码,可以用来查询指定标的的所有订单status (
Optional[ORDER_TYPE]) – 查询特定订单状态的所有订单
- 返回类型
Dict[str,Order]- 返回
返回一个dict, key是order_id, value是
Order对象
get_open_orders - 获得当天的所有未完成的订单
实盘操作函数
trader_connect - 连接交易软件客户端
trader_balance - 获取当前账户资金股票信息
trader_position - 获取当前账户股票持仓信息
trader_today_entrusts - 获取当日委托记录
trader_today_deal - 获取当日成交记录
trader_order - 实盘交易股票
trader_cancel - 撤销当日委托
策略分析函数
stats_report - 策略运行结果分析
- class qff.frame.stats.stats_report(ctx=None, file_name=None)[源代码]
分析策略运行结果,并输出分析报告。QFF回测运行完成后会自动调用,模拟交易中每天收盘后也会自动调用。
- 参数
ctx (
Optional[str]) – 策略运行的上下文环境,默认为当前运行的策略。也可以通过 pickle.dump 函数读取以前策略的pkl文件获取context.file_name (
Optional[str]) – 策略分析报告输出路径,默认为 .qff/output/backtest/<策略名称>策略分析报告.html
- 返回类型
None- 返回
None
strategy_eval - 择时策略评价
- class qff.frame.evaluation.strategy_eval(get_signal_fun, name=None, desc=None, hold_gaps=None, start='2010-01-04', end='2022-05-06', security=None, csv=None)[源代码]
策略评价函数, 对每个股票的历史曲线数据进行择时,分析策略运行效果,并生成策略评价报告word文件。
- 参数
get_signal_fun (
Callable) – 择时函数,获取买点信号,输入参数为(code,kline数据), 返回值List[date_str]name (
Optional[str]) – 策略名称desc (
Optional[str]) – 策略描述hold_gaps (
Optional[List[str]]) – 持仓周期,评估策略在不同持仓周期下的表现,默认[1, 3, 5, 10, 20]start (
str) – 评价测试开始日期end (
str) – 评价测试结束日期security (
Optional[List[str]]) – 评价测试使用的股票集合,为None表示当前所有上市股票csv (
Optional[str]) – 保存pnl的数据文件,如果存在该文件,则直接使用该文件数据,否则运行策略函数,并将运行结果保存至csv文件中。
- 返回类型
None- 返回
None
日期时间函数
get_real_trade_date - 获取真实的交易日期
is_trade_day - 判断是否交易日期
get_date_gap - 获取向前或向后间隔天数的交易日日期
get_next_trade_day - 获取下一个交易日的日期
get_pre_trade_day - 获取前几个交易周期的日期
get_trade_days - 获取指定范围交易日
get_trade_gap - 获取两个交易日之间的交易天数
run_time - 计算函数运行时间的装饰函数
其他函数
log - 日志log信息
- class qff.tools.logs.Log[源代码]
分级别输出日志,跟python的logging模块一致print输出的结果等同于log.info
log.error(content) 输出错误日志
log.warn(content) 输出报警日志
log.info(content) 输出信息日志
log.debug(content) 输出调试日志
- class qff.tools.logs.Log.set_level(self, level)
设置不同种类的log的级别, 低于这个级别的log不会输出. 所有log的默认级别是info
- 参数
level – 字符串, 必须是’debug’, ‘info’, ‘warning’, ‘error’中的一个, 级别: debug < info < warning < error
- 返回
None
kshow - 生成网页版K线图
send_message - 发送消息提醒
- class qff.tools.email.send_message(message)[源代码]
给用户自己发送消息提醒, 暂时只支持邮件通知.
- 参数
message – 消息内容. 字符串.
- 返回
True/False, 表示是否发送成功. 当发送失败时, 会在日志中显示错误信息.
此功能只能在 实时运行模拟交易 中使用, 回测中使用会直接忽略, 无任何提示;
要使用模拟交易发送消息提醒功能, 必须在使用前正确设置邮箱配置参数;
参数文件 ~/.qff/setting/config.ini 按以下格式配置参数:
[EMAIL] from_email = your_email@example.com from_email_password = 授权密码 smtp_server = smtp.example.com smtp_port = 587 to_email = to_receive_email@example.com
其中授权密码可通过访问 https://www.jiuanweb.com/jz/show-165933770.html 获取生成方法。
类和对象
g - 全局变量对象
- class qff.frame.context.GlobalVar[源代码]
全局对象 g,用来存储用户的各类可被pickle.dumps函数序列化的全局数据
在模拟盘中,如果中途进程中断,我们会使用[pickle.dumps]序列化所有的g下面的变量内容, 保存到磁盘中,再启动的时候模拟盘就不会 有任何数据影响。如果没有用g声明,会出现模拟盘重启后,变量数据丢失的问题。
如果不想 g 中的某个变量被序列化, 可以让变量以 ‘__’ 开头, 这样, 这个变量在序列化时就会被忽略
示例:
def initialize(context): g.security = "000001" g.count = 1 g.flag = 0 def process_initialize(context): # 保存不能被序列化的对象, 进程每次重启都初始化, 更多信息, 请看 [process_initialize] g.__q = ["000001", "000002"] def handle_data(context, data): log.info(g.security) log.info(g.count) log.info(g.flag)
context - 策略上下文全局对象
- class qff.frame.context.Context[源代码]
策略上下文
系统全局变量context保存策略运行信息,包含账户、策略、时间、运行参数等。用户可以直接读取context相关属性,但 注意不能直接修改
属性
类型
说明
strategy_name
str
策略名称
run_type
当前框架运行模式,回测还是模拟
status
策略当前运行状态
run_freq
str
策略运行频率 包括”day” ,”tick”和 “min”
start_date
str
回测开始日期
end_date
str
回测结束日期
current_dt
str
策略执行的当前时间 “yyyy-mm-dd HH:MM:SS”
previous_date
str
策略执行的当前时间的前一天”yyyy-mm-dd”
benchmark
str
基准指数代码
portfolio
交易账户对象
order_list
Dict
当日的所有订单列表,key为order_id, value为
Orderorder_hists
List
历史订单列表,以List保存
Order对象的message属性positions_hists
List
历史仓位列表,以List保存
Position对象的message属性asset_hists
List
历史账户资产列表,以List保存
Portfolio对象的message属性strategy_file
str
策略文件名称及路径
log_file
str
日志文件名称及路径
run_start
str
回测开始时间,格式”yyyy-mm-dd HH:MM:SS”
run_end
str
回测运行结束时间(用于计算回测耗时)
output_dir
str
策略运行结果文件输出路径
Portfolio - 股票账户
- class qff.frame.portfolio.Portfolio(starting_cash)[源代码]
股票账户
账户当前的资金,标的信息,即所有标的操作仓位的信息汇总。
属性
类型
说明
starting_cash
float
初始资金
available_cash
float
可用资金, 可用来购买证券的资金
locked_cash
float
冻结资金, 挂单锁住资金
total_assets
float
账户总资产, 包括现金, 仓位(股票)的总价值, 可用来计算收益
positions_assets
float
持仓资产价值
benchmark_assets
float
基准市值
income
float
账户累计收益
returns
float
账户收益率
day_income
float
当日盈亏金额
day_returns
float
当日涨幅
positions
Dict
当前仓位,key值为股票代码,value是
Position对象benchmark_returns
float
基准收益率
Position - 持仓
- class qff.frame.position.Position(security, security_name, init_time, amount, avg_cost)[源代码]
持仓标的信息
持有的某个标的的信息
属性
类型
说明
security
str
股票代码
security_name
str
股票名称
init_time
str
建仓时间
avg_cost
float
当前持仓成本,只有在开仓/加仓时会更新
acc_avg_cost
float
累计的持仓成本,在清仓/减仓时也会更新,该持仓累积的收益都会用于计算成本
transact_time
str
最后交易时间
locked_amount
int
挂单冻结仓位
closeable_amount
int
可卖出的仓位,不包括挂单冻结仓位,建仓当天不能卖出
today_open_amount
int
今天开仓的仓位
today_open_price
float
今日开仓价格
total_amount
int
总仓位, 等于locked_amount+closeable_amount+today_open_amount)
latest_price
float
最新行情价格
valuation
float
标的市值,计算方法是: price * total_amount
income
float
浮动盈亏
income_rate
float
浮动盈亏比率
today_income
float
当日盈亏
today_income_rate
float
当日盈亏比率
hold_days
int
持仓天数
Order - 订单对象
- class qff.frame.order.Order(security, amount, price=None, style=ORDER_TYPE.MARKET, callback=None)[源代码]
订单对象
属性
类型
说明
id
str
订单编号
security
str
股票代码
is_buy
boolean
买入还是卖出, True-买入, False-卖出
amount
int
委托数量
status
订单状态
add_time
str
订单委托时间
deal_time
str
订单成交时间
cancel_time
str
订单取消时间
style
订单类型,市价单还是限价单
order_price
float
委托价格,当订单为限价单时
trade_amount
int
成交数量
trade_money
float
成交金额(含交易费用)
trade_price
float
成交均价,等于成交金额除以成交数量,包含了交易费用分摊
commission
float
交易费用(佣金、税费等)
gain
float
订单收益 股票卖出时计算该值
SecurityUnitData - 当前数据对象
- class qff.price.cache.SecurityUnitData(code, market='stock')[源代码]
当前时刻标的数据快照对象
通过get_current_data()函数获取,只能在回测或模拟交易中使用
属性
类型
说明
code
str
标的代码
name
str
标的名称
last_price
float
当前股票价格
day_open
float
当日开盘价
high_all_day
float
当日之前时间段最高价
low_all_day
float
当日之前时间段最低价
pre_close
float
昨日收盘价
high_limit
float
当日涨停价
low_limit
float
当日跌停价
last_high
float
当前Bar最高价
last_low
float
当前Bar最低价
paused
bool
当日是否停牌
min_data_before
DataFrame
今日当前时刻之前的分钟曲线
min_data_freq
str
当日缓存分钟曲线的频率(‘1min’, ‘5min’, ‘15min’, ‘30min’, ‘60min’)
high_limit_time
int
当天涨停时间长度
block
list
股票所属板块
ticks
dict
当前时刻Tick值,实盘专用
Tick - tick对象
- class qff.Tick
一个 tick 所包含的信息。 tick 中的信息是在 tick 事件发生时, 盘面的一个快照。
字段名
含义
price
当前价格
last_close
昨日收盘价
open
当日开盘价
high
截至到当前时刻的日内最高价
low
截至到当前时刻的日内最低价
vol
截至到当前时刻的日内总手数
cur_vol
当前tick成交笔数
amount
截至到当前时刻的日内总成交额
s_vol
内盘
b_vol
外盘
bid1~bid5
买一到买五价格
ask1~ask5
卖一到卖五价格
bid_vol1~bid_vol5
买一到买五挂单手数
ask_vol1~ask_vol5
卖一到卖五挂单手数