量化交易实践篇(2)—— Quantopian策略实现初体验

这篇带大家按照官方入门指南来体验下Quantopian的魅力,文章中会涉及到一些平台中常用的API,大家可以先有个初步印象,用的时候再去查文档即可。文章最后会实现一个简单的均值回归的策略,好了,宽客动手不动口,开始我们的旅程!

量化交易实践篇(2)—— Quantopian策略实现初体验_第1张图片
Quantopian

交易算法框架

在Quantopian中,交易算法是一段Python脚本,其中包含了几个关键的函数

  1. initialize()
    程序启动时调用的函数,用于处理启动时需要的一次性逻辑,需要context(上下文对象)作为输入。
    context是一个增强的Python字典,用于存储回测或交易中的一些状态与有效数据,它作为算法中的共享区域,在各个函数中均可访问其内容(使用context.键值的方式)。
  2. handle_data()
    按照自定义的周期,定时调用,一般在其中处理当前周期中需要处理的订单,context与data是函数的两个参数。
    data是用于存放一些API方法的对象。
  3. before_trading_start()
    每交易日开盘前调用的函数,通常用于选定当天待交易的股票,入参与handle_data一样,也为context与data两个对象。

一个最基础的算法框架如下:

def initialize(context):
    # 启动后需要处理的一次性逻辑
def handle_data(context, data):
    # 定时执行,处理当前周期中待处理订单
def before_trading_start(context, data):
    # 开盘前执行,选定当天待交易股票

整体框架基本可以模拟了我们平日里的交易操作,很容易理解。对于框架有初步了解后,我们再继续前进一小步,如何获购买一只股票呢?首先我们要获取到这只股票

获取证券信息

平台提供了sid()函数,这个函数会根据输入返回一只股票在平台中的唯一ID,且是始终不变的。
比如你想获取到苹果公司的股票,只需要在代码区域调用sid函数,并在入参里输入股票简称AAPL,编辑器就会智能地给出相应提示。


量化交易实践篇(2)—— Quantopian策略实现初体验_第2张图片
获取代码

获取之后一般都会存放到context对象中,供之后的逻辑使用

def initialize(context):
    context.aapl = sid(24)
def handle_data(context, data):
    print context.aapl

下单

下单平台提供了几种不同的函数,这个点后续再展开详述,这篇文章我们以order_target_percent()这个为例进行说明,order_target_percent函数需要两个参数,sid(证券ID)与target_percent(投资比例,分母为可用头寸)
**注:
可用头寸=现金账户+敞口头寸(open position)
敞口头寸应该为当日买卖差价
**
如果用可用头寸的50%去做多苹果,代码如下

order_target_percent(sid(24), 0.50)

而如果用可用头寸的50%去做空,代码如下

order_target_percent(sid(24), -0.50)

获取证券信息

在下单前,策略可能需要根据历史及当前该证券的信息进行分析,data对象提供了几个快捷的函数供使用。

  1. data.current() 获取当前信息
    需要两个参数,第一个参数为证券sid或一个证券sid列表,第二个参数为你需要的信息字段,目前支持的有价格(price)、开盘价(open)、收盘价(close)、最高价(high)、最低价(low)与交易量(volume)。
    例如:
data.current(sid(24), 'price') #获取苹果的当前价格
data.current([sid(24), sid(46631)], 'price') 获取苹果与谷歌的当前股价
data.current([sid(24), sid(46631)], ['low', 'high'])获取苹果与谷歌截止当前的最高最低价
  1. data.can_trade() 该证券能否交易
    需要传入证券sid或证券sid列表
  2. data.history() 获取历史信息
    在current参数的基础上增加了回看窗口大小(lookback window length)及回看频率(lookback frequency)的参数
hist = data.history(sid(24), 'price', 10, '1d')#获取苹果过去十天的价格,频率为每天
mean_price = hist.mean()
#注:获取历史价格的时候,会先返回当前的价格,及前9天的日中收盘价,所以如果你希望获取前十天的均价,先取11天,然后丢弃掉最新的一条。
data.history(sid(8554), 'price', 11, '1d')[:-1].mean()

注: data.current()与data.history()返回的均为pandas的DataFrame结构,pandas这个python科学库后续会专门一系列说明

自定义调度

可以根据自己需要的周期,灵活地定义自己需要的定时处理逻辑函数,参数中包含自定义函数名、日期规则与实践规则,

#在每周第一天开盘后一小时,已目前可用的10%买入苹果股票。
def initialize(context):
    context.aapl = sid(24)
    schedule_function(func=open_positions, 
    data_rules=date_rules.week_start(), 
    time_rules=time_rules.market_open(hours=1)

def open_positions(context, data):
    order_target_percent(context.aapl, 0.10)

查询当前持仓

Quantopian在context中内置了portfolio对象,持仓存储在context.portfolio.positions中,positions可以看做sid为键,Postion对象为值的一个字典。我们可以使用for...in语法进行循环处理:

#清盘所有持仓
for security in context.portfolio.positions:
  order_target_percent(security, 0)

绘制变量

平台提供了record()方法帮助你将自己关注的变量绘制成时间序列图,可以方便的监控关心的变量。

def initialize(context):
    context.aapl = sid(24)
    schedule_function(record_vars, date_rules.every_day(), time_rules.market_close())

def record_vars(context, data):
    long_count = 0
    short_count = 0
    for position in context.portfolio.positions.itervalues():
        if position.amount > 0:
            long_count += 1
        if position.amount < 0:
            short_count += 1
    # 绘制图表
    record(num_long=long_count, num_short=short_count)

重新编译算法后,可直观地展现每日收盘空头/多头的时间序列图。


量化交易实践篇(2)—— Quantopian策略实现初体验_第3张图片
绘制

滑点与佣金

滑点与佣金都属于交易成本的范畴,对于算法的实际表现影响很大

  1. 滑点
    滑点表示由于下单(尤其是大单)对于股价潜在的影响,会导致实际成交比预期差的情况,平台中集成了多种滑点的策略,下面为默认的策略:
# 假设过去几分钟内交易量为1000时,限制每次只能下1000*0.025=25的单,系统会根据这个值进行拆单
set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))
  1. 佣金
    可以根据真实经纪商的情况设置佣金费率及最小费用。
set_commission(commission.PerShare(cost=0.0075, min_trade_cost=1))

订单管理

因为订单基本都不是即刻成交的,而且当前未成交订单对于后续的策略执行也有很大的指导意义,所以订单管理的功能也是至关重要的。
get_open_orders()函数帮助我们获取当前已下但尚未成交的订单

 open_orders = get_open_orders()
 if context.xtl not in open_orders and data.can_trade(context.xtl):
        order_target_percent(context.xtl, 1.0)

动手均值回归策略

好了,把之前所有的内容整合起来,我们很容易就能实现一个简单的均值回归策略。均值回归策略可以简单的理解为短期的均值会有一定波动,但随时间一定会逐步与长期均值趋同。
我们就来实现这样一个策略:
如果一个股票10天移动平均高于了其30天移动平均值,我们则认为股价一定会下跌,反之亦然。

def initialize(context):
    #初始化证券池
    context.security_list = [sid(5061), sid(7792), sid(1941), sid(24556), sid(1746)]

    # 自定义调度:每周第一交易日开盘时重新计算并执行组合重新配置
    schedule_function(rebalance,
                      date_rules.week_start(days_offset=0),
                      time_rules.market_open())

def compute_weights(context, data):
    #计算10日与30日均值
    hist = data.history(context.security_list, 'price', 30, '1d')
    prices_10 = hist[-10:]
    prices_30 = hist
    sma_10 = prices_10.mean()
    sma_30 = prices_30.mean()
    # 加权计算
    raw_weights = (sma_30 - sma_10) / sma_30
    normalized_weights = raw_weights / raw_weights.abs().sum()
    return normalized_weights

def rebalance(context, data):
    # 重置权重
    weights = compute_weights(context, data)
    # 组合重新分配
    for security in context.security_list:
        if data.can_trade(security):
            order_target_percent(security, weights[security])

这一篇到这里就结束了,是不是觉得很容易上手呢?建议大家去官方教程里克隆策略,自己上手跑一跑,对于量化交易会更有体会。

你可能感兴趣的:(量化交易实践篇(2)—— Quantopian策略实现初体验)