Quantopian自学笔记02

LESSON 4 : Strategy Analysis.

      在学会了如果导入数据并 manipulate 操纵数据后,我们就要试着为我们的 long-short equity strategy 构建一个数据pipeline(到目前为止,似乎 pipeline 就是在处理数据)。简单地说,long-short equity strategy 包含了首先对资产之间的相对价值进行了建模,模型化;然后在我们有信心将会涨得最多和跌得做多的资产组合上投资(具体怎么投资呢?我预测它将会上涨,肯定是买入持有,但是对于预计或者是说期望下跌地资产呢?做空还是买入持有呢?查了一下,美国股市是支持做空操作的,但不是我国之前那种裸卖空,但我觉得这里应该指的是一并持有,为了更安全起见)。

       当上涨的资产和下跌的资产之间的差价越大我们这个策略的获利也就越高。我们这个模型的质量,完全取决于我们所运行得那个资产排序模型。本章的教程就将会用到一个是用于我们模型的简单排序模式。

策略定义:我们认定有一个高的3日平均情绪分的资产为高价值资产,低的3日平均情绪分的资产为低价值资产。

       那么怎么来进行策略分析呢?我们可以先用 SimpleMovingAverage 和 stockwits 模块中的 bull_minus_bear 指标来定义我们的策略,就像上一章中我们创建 pipeline 一样。

#Pipeline import
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.psychsignal import stockwits
from quantopian.pipeline.factor import SimpleMovingAverage
from quantopian.pipeline.experimental import QTradabelStocksUS

#Pipeline definition
def  make_pipeline():

    base_universe = QTradableStocksUS()

    sentiment_score = SimpleMovingAverage(
        inputs=[stocktwits.bull_minus_bear],
        window_length=3,
    )

    return Pipeline(
        columns={
            'sentiment_score': sentiment_score,
        },
        screen=base_universe
    )

        为了简单一点好理解,我们只分析由 sentiment_score 排序得到的前350和后350只股票。我们可以用 sentiment_score 的输出所拥有的 top 和 bottom 方法来创建一个 pipeline 的过滤器 filter,来处理我们得到的数据,然后用一个操作符 ' | '来得到 top 和 bottom 的合并。接下来我们用 ' & ' 来得到过滤器得到的数据和交易空间的相交部分,并将其它部分移除出我们的交易空间(?)。不过实际上交易空间还是那个空间,并没有改变,我们改变的是传给创建 pipeline 实例时的对象,同时也可以看出,原来 QTradabelStocksUS() 返回的很可能是一个 DataFrame。

# Pipeline imports
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.psychsignal import stocktwits
from quantopian.pipeline.factors import SimpleMovingAverage
from quantopian.pipeline.experimental import QTradableStocksUS

# Pipeline definition
def  make_pipeline():

    base_universe = QTradableStocksUS()

    sentiment_score = SimpleMovingAverage(
        inputs=[stocktwits.bull_minus_bear],
        window_length=3,
    )

    # Create filter for top 350 and bottom 350
    # assets based on their sentiment scores
    top_bottom_scores = (
        sentiment_score.top(350) | sentiment_score.bottom(350)
    )

    return Pipeline(
        columns={
            'sentiment_score': sentiment_score,
        },
        # Set screen as the intersection between our filter
        # and trading universe
        screen=(
            base_universe
            & top_bottom_scores
        )
    )

        接下来,在时长为三年的长度上运行我们的 pipeline,将会得到一个我们可以用来做分析的输出。使用从 pipeline 导入的函数 run_pipeline,返回一个DataFrame格式的数据。

# Import run_pipeline method
from quantopian.research import run_pipeline

# Specify a time range to evaluate
period_start = '2013-01-01'
period_end = '2016-01-01'

# Execute pipeline over evaluation period
pipeline_output = run_pipeline(
    make_pipeline(),
    start_date=period_start,
    end_date=period_end
)

     到这里先稍作停顿,想一下上面都做了什么。我们定义了一个三日 bull_minus_bear 牛熊指标的均线,用的是SimpleMovingAverage ,得到了一个名为 sentiment_score 的对象,里面是一个完整的表,索引为股票名和日期。暂时我所理解中的 DataFrame,也是一个表,但更高意义上,它也可以理解成若干相互之间有联系个表,可以通过一定的索引,来找到我们想要的数据或者构造出我们想要的视图(有点像数据库,不过很大可能是我瞎掰的,如果以后发现错了,我再回来修改!)。sentiment_score 这个对象就传递给 make_pipeline(),而 make_pipeline() 本身只是负责接受它获得的那个 'columns',以及暂时知道的受到 screen 所表示的选中股票,这两个参数的影响,并没有在时间跨度上做出限制,所以在 run_pipeline() 中就补充两个参数 start_date,end_date。目前,得到的 pipeline_output,输出的即是一个 DataFrame 数据。

       在有了指标数据之后,我们还需要所有的股票在这段时间上的价格。这个不难,我们可以轻松地从我们 pipeline 地输出中获得我们那些选定的资产/股票的编号,然后把得到的 list 传入另外一个函数 prices 中,就可以得到我们想要的价格数据。注意,我们这里的价格是日线的价格,也就是每天的平均价(我觉得严谨的算,应该是总成交额除以总交易量),但这个价格实际上并没有什么参考意义,不过我们现在也是入门嘛,先明白概念就好。

#Import prices function
from quantopian.research import prices

#Get list of unique assets from the pipeline output
asset_list = pipeline_output.index.level[1].unique()

#Query pricing data for all assets persent during evaluation period
asset_prices = prices(
    asset_list,
    start = period_start,
    end = period_end
)

       那么下一步,我们用 quantopian 开源的指标分析工具 Alphalens,来检测我们这个选股策略。首先,把我们的指标和价格数据用 get_clean_factors_and_forward_returns 结合在一起;这个函数把我们的指标按类别分好类,在这里我们只是给出 quantile = 2,然后函数就自动帮我们分类了,应该是简单的根据数值的高低,排序之后分类了的。然后对每个资产按各种持有时间长度计算后续利润。我们把我们的指标数据分成两类,top 和 bottom,然后持有周期定义为1天,5天和10天。

#Import Alphalens
import alphalens as al

#Get asset forward returns and quantile classification based on sentiment score
factor_data = al.utils.get_clean_factor_and_forward_returns(下·
    factor = pipeline_output['sentiment_score'],
    prices = asset_prices,
    quantile = 2,
    periods = (1,5,10),
) 

#Display first 5 rows
factor_data.head(5)

得到的结果如下,这个是我把文档中的内容 copy 到 Quantopian 一个叫做 research 的功能之中打开,因为在 start coding 中是显示无法执行 research 的相关功能的。我理解的是,start coding 更多专注在回测和策略的建立上,research 是前期我们熟悉那些数据结构用的。Quantopian自学笔记02_第1张图片

      可以看到,' Dropped 4.8% entries from factor data: 4.8% in forward returns computation and 0.0% in binning phase (set max_loss to see potentially suppressed Exceptions). ' 意思就是说,我们所使用的那个函数,get_clean_factor_and_forward_returns,使用了我们 factor data 指标数据集里面才4.8%的数据,为什么用了这么少呢?原因应该是我们有一定持有期,在持有期内不考虑换手,所以不用去使用那段时间内的数据,这也是在提醒我们开发的人合理的切片数据,以免浪费内存的情况出现;另外还默认有一个 max_loss 的数值设置为了35%,也就是说如果我们某一笔(还是某一天?应该是某一笔吧,一天的话如果一次性亏损35%,那也不太可能)持有会导致超过35%的损失,就卖出,即止损。我们可以通过设置max_loss 的数值为0,看到那些潜在的,被禁止的交易。

       仔细看表格,有两个索引:日期,股票编号。后面是不同持有时间的一个利润情况,然后还有在当天,该资产的 sentiment_score,也就是 factor,情绪指标的数值,以及它是被分成了 high/2,还是被成进了low/1。然后那些1D,5D,11D这些,我的理解就是我们每天都会参考那个情绪指标,每天都会买进排行前350和后350的股票,但依照方法不同,例如我们是只持有一天的,第二天就会清仓,然后重新买入一批;如果是持有五天的,那么第二天照样还是会买进,但是第一天买入的股票将会一直持有到第五天才卖出,以此类推。不过算出来一共有17W条数据,如果每个交易日700条,那么算下来三年才有240左右个交易日,240接近的是一年的交易日数,这个就不太对了......这个问题有点复杂,想查文档但是找不到这个函数,哎,要不先跳过,大概的意义了解了先,等后面有机会,或者说有别的函数更好用可以替代。

       那么现在我们有了如上格式的数据了,就可以将其加载在 Alphalens 的加工和绘图工具上。我们从整个考虑的时间区间上,来看分成两类的平均利润的情况。因为我们的目标是建立一个 long_short strategy,所以我们希望看到低的指标 quantile(1)有负的回报然后高的指标 quantile(2) 有正的回报。从这里我们可以完整地理解我们的策略了,我们对于低的指标的资产组合,因为我们的指标是情绪指标,低的,也是说明群众们并不看好,所以预期也是下跌的,那么做空也是比较合理的了;同理,高指标,也就是大家一致看好的,也就是上涨的可能性更大,故选择做多。

#Calculate mean returns by factor quantile
mean_return_by_q, std_error_by_q = al.performance.mean_return_by_quantile(factor_data)

#Plot mean returns by quantile and holding period over evaluation time range
al.plotting.plot_quantile_returns_bar(
    mean_returns_by_q.apply(
        al.utils.rate_of_return,
        axis = 0,
        args = ('1D',)
    )
);

Quantopian自学笔记02_第2张图片

      得到了一个如上的图像,可以看出两个类别不同持有时间的平均利润情况。al.performance.mean_return_by_quantile 这个函数,接受了我们之前计算并分好类的 factor_data 数据,然后返回了两个对象,mean_return_by_q 和 std_error_by_q,这里似乎不是返回的数值,而是一个类之类的东西,需要之后使用一些方法 method 来执行。看起来在后面调用了方法 apply,传入了参数 al.utils.rate_of_return 表示计算的是回报率,而不是 factor_data 中的各股的利润。

      我们也可以绘制出,以指标为依据,持有期为5天的 long-short portfolio 策略的累积收益情况,使用如下的代码: 

#Calculate factor-weighted long short portfolio returns
ls_factor_returns = al.performance.factor_return(factor_data)

#Plotting cumulative returns for 5 day holding period
al.plotting.plot_cumulative_returns(ls_factor_returns['5D'],'5D')

可以看到第一个函数 al.performance.factor_return(factor_data) 的作用是把 factor_data 这个打包好的数据,计算出按持时长不同而整个策略的各个利润率随时间的变化情况。然后 plot_cumulative_returns 就是绘制连续的利润率折线图,ls_factor_returns['5D'] 我猜可能是键对应的值,也就是一个数组,是计算好的结果,后面的 '5D' 可能是改变图像标题中的内容的。

       从图中可以看到有一个较长的有着最大回撤率的期间,而我们的分析没有考虑账户交易成本和市场冲击的情况。这不是一个很有前途的策略,从这个方面上讲,我们应该使用 Alphalens 构建一个更具深度的分析策略,并让其在我们的策略里面迭代运行。但出于我们教程的初衷,我们维持现在的程度即可。

       分析并测试了一个策略之后,我们一起来使用它并测试一个 long-short equity 算法策略。教程的剩余部分将讲述 Algorithm 的一些函数接口 API,并且在 IDE 中来调试我们的策略。

 

 

 

 

 

 

 

你可能感兴趣的:(quantopian)