本文将继续探讨使用 Python 构建事件驱动回测系统。在上一篇文章中,我们讨论了投资组合类体系结构,它负责处理当前持仓、生成交易订单以及跟踪盈亏(PnL)。
在本文中,我们将研究这些订单的执行过程,通过创建一个类体系结构来模拟订单处理机制,并最终实现与券商或其它市场连接方式的对接。
此处描述的 ExecutionHandler(执行处理器)非常简单,它可以让订单按当前市价成交。这种设定虽然可能与实际情况相差甚远,但为后续的改进提供了一个很好的基准。
与之前创建抽象基类体系结构一样,我们需要从ABC库中导入必要的属性和decorators。此外,还需要导入FillEvent和OrderEvent:
# execution.pyimport datetimeimport Queuefrom abc import ABCMeta, abstractmethodfrom event import FillEvent, OrderEvent
# execution.pyclass ExecutionHandler(object):"""The ExecutionHandler abstract class handles the interactionbetween a set of order objects generated by a Portfolio andthe ultimate set of Fill objects that actually occur in themarket.The handlers can be used to subclass simulated brokeragesor live brokerages, with identical interfaces. This allowsstrategies to be backtested in a very similar manner to thelive trading engine."""__metaclass__ = ABCMeta@abstractmethoddef execute_order(self, event):"""Takes an Order event and executes it, producinga Fill event that gets placed onto the Events queue.Parameters:event - Contains an Event object with order information."""raise NotImplementedError("Should implement execute_order()")
为了对交易策略进行回测,我们需要模拟实际成交过程。最简单的实现方式是假设所有订单都能按当前市价全额成交,并且成交数量完全符合要求。这种设定看起来有点不切实际,而提升回测真实性的关键环节就在于设计更精细的滑点和市场冲击模型。
需注意的是,FillEvent中的成交价格字段fill_cost被设置为None(参见execute_order的倒数第二行),因为我们在前一篇文章介绍的NaivePortfolio对象中已经处理了成交成本。在实际应用中,我们会使用"实时"市场数据来获取真实的成交价格。
这里我直接采用ARCA作为交易所标识,但就回测目的而言这仅是个占位符号。在实盘交易环境中,交易场所的选择将具有更重要的意义:
# execution.pyclass SimulatedExecutionHandler(ExecutionHandler):"""The simulated execution handler simply converts all orderobjects into their equivalent fill objects automaticallywithout latency, slippage or fill-ratio issues.This allows a straightforward "first go" test of any strategy,before implementation with a more sophisticated executionhandler."""def __init__(self, events):"""Initialises the handler, setting the event queuesup internally.Parameters:events - The Queue of Event objects."""self.events = eventsdef execute_order(self, event):"""Simply converts Order objects into Fill objects naively,i.e. without any latency, slippage or fill ratio problems.Parameters:event - Contains an Event object with order information."""if event.type == 'ORDER':fill_event = FillEvent(datetime.datetime.utcnow(), event.symbol,'ARCA', event.quantity, event.direction, None)self.events.put(fill_event)
至此,构建事件驱动回测系统所需的类层次结构已全部完成。在下一篇文章中,我计划带着大家一起探讨如何为回测策略计算一组绩效评估指标。