0%

devtoolset介绍

devtoolset是为 Scientific Linux CERN 5 和 6 平台上的开发人员提供的产品。使用 Software Collections 框架,根据 UNIX 文件系统层次结构标准的建议,将一组额外的工具安装到 /opt 目录中。这些工具由用户使用提供的 scl 实用程序按需启用。

devtoolset与gcc的版本对应关系

devtoolset-3对应gcc4.9.x版本
devtoolset-4对应gcc5.x.x版本
devtoolset-6对应gcc6.x.x版本
devtoolset-7对应gcc7.x.x版本
devtoolset-8对应gcc8.x.x版本
devtoolset-9对应gcc9.x.x版本

安装步骤

由于devtoolset-3版本太老官方仓库已经不再提供安装,所以从需要先从其他网站更新仓库地址,具体更新和安装步骤如下

cd /etc/yum.repos.d

wget https://copr.fedorainfracloud.org/coprs/rhscl/devtoolset-3-el7/repo/epel-7/rhscl-devtoolset-3-el7-epel-7.repo

yum install devtoolset-3-toolchain

scl enable devtoolset-3 bash

gcc -v

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-3/root/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/opt/rh/devtoolset-3/root/usr --mandir=/opt/rh/devtoolset-3/root/usr/share/man --infodir=/opt/rh/devtoolset-3/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,fortran,lto --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC)

参考

https://linux.web.cern.ch/devtoolset/

https://copr.fedorainfracloud.org/coprs/rhscl/devtoolset-3-el7/

https://blog.csdn.net/zzhongcy/article/details/89950976

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

下载Redis源码

git clone -b 6.2 https://github.com/redis/redis.git

CLion导入Redis

image-20211016003737364

启动IDE之后弹出如下弹窗点击OK

image-20211016003853027

等导入项目加载完成之后,在IDE中打开Makefileb并点击第三行的绿色箭头执行make操作

image-20211016003943812

运行完成之后会在src目录下出现编译好的.o文件,比如redis-cli.o和redis-server.o

运行redis-server debug 模式

image-20211016004602127

找到Edit Configurations后打开,在Target中选择reids-server,Executable中找到src/redis-server,设置启动参数指定redis.conf

image-20211016004551730

设置好之后运行,提示如下错误

image-20211016001810427

安装pkg-config

brew install pkg-config

再次运行redis-server的debug模式启动成功

image-20211016002810464

参考

https://www.modb.pro/db/73281

https://zhuanlan.zhihu.com/p/339812402

https://www.jianshu.com/p/904b44911ab9

https://github.com/LHRchina/redis

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

不可追踪的加密数字货币

门罗币(Monero)是一种分散的加密货币,意味着它是由用户网络操作的安全数字现金。事务通过分布式协商一致确认,然后在区块链上进行不可更改的记录。 第三方不需要被信任来保证你的门罗币(Monero)的安全。

如何使用电脑CPU如何挖矿

非常简单,就两步:

  1. 下载并创建门罗币钱包
  2. 下载并设置挖矿程序

步骤1:下载并创建门罗币钱包

在门罗币官网下载Windows钱包,地址是:https://downloads.getmonero.org/gui/win64

解压缩并运行monero-wallet-gui.exe,按照下图红框位置语言选择中文,然后根据提示进行下一步操作,模式选择简易模式

创建一个新的钱包,记录保管好助记种子,万一密码忘记了可以通过助记词找回账户密码

下一步输入密码之后就创建好了钱包,登录钱包看到钱包页面。

复制钱包地址,类似如下字符串:

43WufLh9YvQU8UoPxFcgK8gAxMcCigmnPWSBGf6jvTY6URjkhPUCuBKHx5nTQR7HZR7UCnug1zdkWL9dppqDfzgnF64zV1i

这样就完成了钱包的创建

步骤2:下载并设置挖矿程序

下载门罗币挖矿程序,这里使用的是比较流行的xmrig,官网地址:https://github.com/xmrig/xmrig/

挖矿程序下载地址:https://github.com/xmrig/xmrig/releases/download/v6.10.0/xmrig-6.10.0-msvc-win64.zip

找到并设置如下两项

            "url": "mine.c3pool.com:15555",
            "user": "43WufLh9YvQU8UoPxFcgK8gAxMcCigmnPWSBGf6jvTY6URjkhPUCuBKHx5nTQR7HZR7UCnug1zdkWL9dppqDfzgnF64zV1i",

第一个url是矿池地址,这里使用的c3pool,第二个user是门罗币钱包地址,请使用上一步自己创建的钱包地址替换。

设置好点击目录下的start.cmd文件就开启挖矿程序了。

查看挖矿进度

通过以下网址可以查看挖矿进度,https://c3pool.com/cn/

打开网址后在网页中输入自己的钱包地址,就可以看到类似如下界面

image-20210425233645274

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

通常我使用笔记本电脑编写程序代码,而数据采集是由一台服务器进行,为了方便开发调试,需要把程序部署到服务器上运行。这时候就用到了pycharm的远程部署调试功能。

1. 配置远程服务器

在pycharm中Perferences -> Build, Execution, Deployment -> Deployment菜单下添加远程服务器配置,Type选择SFTP这样可以通过ssh方式将代码传到服务器上

![image-20210306171219402](/Users/eryk/Library/Application Support/typora-user-images/image-20210306171219402.png)

填写服务器地址、端口(ssh服务端口默认是22)、用户名和密码,密码如果配置了免秘钥登录可以选择“OpenSSH config and authentication”方式,否则选择password输入密码就可以,设置好之后点Test Connection验证如果可以连通则会弹出如下截图:

![image-20210306171534805](/Users/eryk/Library/Application Support/typora-user-images/image-20210306171534805.png)

说明已经可以连上服务器了,默认部署在服务器登录用户的根目录下,如有需要部署在其他位置可以修改Root path参数。设置好之后点ok保存配置就完成了第一步。

2. 设置代码自动上传

![image-20210306172025658](/Users/eryk/Library/Application Support/typora-user-images/image-20210306172025658.png)

打开菜单栏中Tools -> Deployment,勾选“Automatic Upload(always)”,这样每次保存代码有更新都会上传到服务器上,始终保持服务器和本地代码一致。点击“Brown Remote Host” 可以在pycharm 右侧弹出标签栏中看到远程服务器上目录内容。

3. 配置远程Python Interpreter

在pycharm中Perferences -> Project: 项目名 -> Project Interpreter,在右侧点击添加,如下步骤1所示位置

![image-20210306173647677](/Users/eryk/Library/Application Support/typora-user-images/image-20210306173647677.png)

弹出“Add Python Interpreter” 对话框,在 “Existing server configuration” 中选择刚添加的服务器,如上图步骤2所示。然后点next,

接下来需要设置服务器上Python所在路径和程序自动同步的位置,这里建议和之前deploy保持一致。

点击Finish就可以看到已经添加好了Remote Python,如下图所示

4. 运行Python远程代码

编写测试代码,新建mian.py,代码内容是输出当前程序所在路径,测试一下程序是否在服务器上运行

import os

print(os.system('pwd'))

image-20210306180021381

image-20210306180103879

设置“Edit Configuration” ,将Python interpreter设置为刚添加的远程服务器的python,运行代码,输出如下说明已经在远程服务器上运行成功了。

image-20210306180258162

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

missingno提供了一个灵活且易于使用的丢失数据可视化工具和实用程序的小型工具集,使您可以快速直观地概述数据集的完整性(或缺乏完整性)。只需pip install missingno就可以开始使用了

missingno包含了4种类型图示:

  1. Metrix:msno.matrix无效矩阵是一种数据密集显示图,可以直观的看到各个column缺失数据分布情况,这种可视化图示最多可以容纳50个column,超过此范围的标签开始重叠或变得不可读。

  2. Bar:msno.bar是按列对无效性数据的简单可视化:

  3. Heatmap:数据列之前缺失相关性分析图,展示了一个变量的存在或不存在对另一个变量的存在有多强烈的影响

  4. Dendrogram:通过树状图,您可以更全面地关联变量完成,揭示比Heatmap中可见的成对趋势更深的趋势。与metrix图一样,在这种配置下最多只能显示50个带标签的列。但是,树状图只需翻转到水平配置即可更优雅地处理超大型数据集。

参考

https://github.com/ResidentMario/missingno

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

最近重读了这本经典的金融投资类书籍,把其中精华部分摘录的下来,除了摘录的部分,第三章内容介绍的交易日志介绍了如何给一笔交易打分也不错,作者让我们更多的关注一笔交易的好坏,而不仅仅是盯住账户盈亏,这样日积月累交易技术才会精进。以下是本书精华部分,介绍了多种卖出的目的与技术。

第二部分 如何卖出

卖出策略分为下列三种:

  1. 止盈卖出
  2. 保护性止损卖出
  3. 在止盈或止损之间卖出,因为市场状况变化了,我们接下来不再希望持有这只股票

第四章 止盈

  1. 你的止盈价是多少—这只股票可能会涨多少?
  2. 股票跌多少你才会相信你的买入决策是错误的,并止损。
  3. 这只股票的期望损益比是多少?潜在的收益和风险之间的关系是什么?

对波段交易者来说,使用移动平均线和通道组合是设置目标价的好方法。如果要设立长期交易的盈利目标,就需要查看长期的支撑和压力在哪里。

移动平均线卖出

周线图中,在价值之下买入,把盈利目标设置在价值区,这个方法非常好用。三重过滤网系统要求在周K线做出战略决策,在日K线实施,日线是做战术性买入或卖出的时间框架。

使用通道技术卖出

如果使用通道技术给交易设定了盈利目标,但后来你觉得反弹高度会更高一些怎么办?你可能会持有多长时间?尽管价格有时候会反弹得很高,它容易让人放弃先前的决定而持有更长时间,但经验告诉我不要持有头寸时间过久。

如果价格比你设定的初始目标价低一些,你会获利了结吗?当这个问题摆在我面前的时候,我就等价格创新高失败的那天以收盘价卖出,或者在次日开盘后不久卖出。

压力位卖出

移动平均线卖出法适用于股票超卖后的反弹,通道卖出法适合短线交易者使用,这些方法可以用于短期波段交易。短期交易的波动幅度相对于长期交易者来说太小,我们曾把长线交易者称为投资者,但世界在变快,每个人又都是交易者。长线交易者的交易周期以月甚至年来衡量,这需要更大的盈利目标。猎鹿的人与猎兔子的人不同,猎鹿的人需要一杆大枪。

支撑和压力区的存在为长线交易者提供了盈利目标。我们把大量交易发生过的地方作为压力或支撑区,这样就很容易知道相对于压力或支撑,价格目前所处的位置。

每开始一次交易,你都应该有两个目标:赚钱和变成更好的交易者。你不一定每次都达到第一个目标,但必须达到第二个目标。如果没有从交易中学到什么,你就是在浪费时间和金钱。

第五章 止损

每次交易都应该设定止损。请务必遵循这个简单的规则:在确切地知道止损位置之前,不要交易。入场前你必须做出这个决策,当然你还应该确立一个盈利目标以计算损益比。没有目标的交易无异于赌博。

铁三角止损

设立止损的首要目的是避免情势不利时损失超过预期,第二个目的是保护浮盈,第三个目的毫无疑问是控制与资金管理有密切关系的总资金亏损。

风险控制工作的过程分三个步骤:

  1. 分析并设定止损位,通过入场价与止损价之间的距离计算每股风险损失值。

    假如准备以18美元/每股的价格买入股票,分析后发现如果股价跌破17美元就改变看多观点,所以你决定把保护性止损设在16.89美元。每股风险值是1.11美元,如果加上滑点的话每股风险值会更高一点,但是1.11美元已经是一个合理的估计值了。

  2. 运用资金管理规则确定单次交易的最大损失额度以及交易者所能承受的风险值。

    假设你的交易账户有5万美元,并遵循2%的资金管理规则。这意味着你每次交易的最大风险值是1000美元,这个风险值也比较适中,实际中不少人希望止损小于1%。

  3. 根据1和2中的数据计算可购入的最大股票数量。

    这样就可以计算得出单次交易所能购入的最大股票数量。如果单次交易最大风险值是1000美元,每股允许的风险值是1.11美元,最大的交易股数应该小于900股;另外这1000美元中必须包括交易佣金和滑点。还有一点,没有人规定你必须交易最大可购入的股数,如果你觉得风险仍然太大,可以交易比这个数量更少的股票。如果你对这只18美元的股票抱有很大期望,就应该把止损空间设得大一些,比如在15.89美元,然后每股允许的风险值将会是2.11美元;单次交易的最大损失值不变,因此你最多可购入的股票数量就只有470股了。

市价止损和限价止损

市价指令可以保证执行,但不能保证价格;限价指令保证价格但不能保证一定会执行。

硬止损和软止损

硬止损是下到市场中的止损指令,软止损是交易者牢记的止损价格,只要市场价格达到止损价格,就立即下单。

糟糕的止损位

关于止损的最糟糕的认识是,只要价格低于最近的最低价就立即止损

止损设在前低上:减少滑点

把止损点设在前期低点上而不是低于前期低点一个Tick的地方。看了很多图表后我发现,很少有股票在价格跌到前低的时候停下脚步,它们往往跌破前低。正常情况下,价格不是到不了前低就是跌破前低,这表明把止损设在低于前低一个Tick的位置上对交易安全没有帮助,所以我开始把止损设在前低的位置上。

尼克止损法

寻找大多数人设置止损的价格,然后找出跌破该价格的K线,并把止损设在两个次低价中较低的那个价格之下。这种紧随的设置止损方法非常适合短期波段交易,试图抓住底部是很危险的,而这样一个紧随性止损却会很好地保护账户,这就像告诉市场,要么来打我止损(反正止损不大),要么就给我涨。

使用宽幅止损的时机

交易周期影响止损大小,较短时间框架内的交易止损必须小,而长周期框架的交易要求止损大一些。短期时间框架内的价格运动先于长期时间框架内的价格运动。

移动止损

  • 可以用K线组合的低点作为新的止损点,比如把止损移动到最近三根K线最低价的位置(但决不要和交易方向相反)。
  • 可以使用周期非常短的移动平均线,并把均线值作为追踪止损值。
  • 可以使用枝形灯止损法,市场每次创新高都从最高点起算,以特定的距离向上移动止损,这个距离的计算应基于ATR(真实波幅)。只要股价创新高,就把止损向上移一定距离,这种方式就像从天花板上挂一盏枝形灯(本方法已经在《走进我的交易室》中介绍过)。
  • 抛物线止损。
  • 安全区止损。
  • 回撤比例止损。
  • 时间止损,如果在一定时间内价格没有变化就止损。比如做一笔日内交易,如果股价在10~15分钟内明显没有按照你的预期变化,那么最好了结这次交易;如果做一笔波段交易并预计股价会持续好几个交易日,但是一周过去了股价仍在横盘整理。这表明价格没有确认你的判断,安全的做法是赶紧出局。

抛物线止损指标

今日SAR=前一日SAR+AF×(EP–前一日SAR)

其中,今日SAR=今日止损价;

EP=当前交易中到达过的极点,如果看多,EP就表示近期明显的低点;如果看空,EP就表示近期明显的高点;

AF=加速因子。

交易的第一天加速因子等于0.02,表示你必须把止损设在近期极值的2%处;只要价格创下新高或新低,加速因子就增加0.02,加速因子的最大值是0.2。

抛物线系统在趋势行情中运行很好,但在震荡行情中却频频失灵。另外,不要在计算机自动交易中使用这个系统。

安全区止损

安全区止损的理念来源于金融市场中的信号和噪音,如果趋势是信号,那么回调就是噪音。

我们可以用多种方法定义趋势,比较简单且直接的方法是用价格与22天EMA的相对位置来定义趋势。在涨势中我们把噪音定义为今日价格中低于前一天低点的部分,这部分与趋势相反;如果是跌势我们把噪音定义为今日价格中高于前一天高点的部分。交易者需要决定测量噪音的回测期的长度,回测期不能太长但必须对交易有实质意义,只需日线图中最近一个月左右的数据就可以了

如果在上涨趋势中把所有噪音部分标出来并汇总,除以噪音发生的总次数,就得出回测期的噪音均值,它反映了当前上升趋势中的平均噪音水平。把止损设得太近容易弄巧成拙,所以要把止损设在远离噪音均值的地方,用噪音均值乘以平均噪音系数(初始值为2,也可用大于2的数值),用昨天最低价减去上面的这个计算结果就得出了止损应该设置的地方。如果今天的最低值比昨天低就不移动止损,这种方法只允许将止损向上移动。

下跌趋势与上涨趋势的规则相反。当22日EMA均线显示目前处于下跌趋势,计算回测期噪音均值并乘以系数,用昨日最高价加上上述数值,就得出今日的止损设置位置。同样,止损只向下移动不向上移动。

波幅减少追踪止损法

如果市场即将疯狂并大幅移动,我自然愿意留在市场中。我使用通道设置价格目标,通道宽度的正常值是2.7倍标准差。如果我想在价格达到目标价以后使用追踪止损,我会把止损设在1.7倍标准差的地方,只要价格继续沿着正常通道运动我就一直持有,但只要收盘价在1.7倍标准差这个通道内我就离场。通道宽度可以用修改通道参数的方法来修改。

如何决定在价格达到盈利目标时是获利了结还是使用追踪止损?

如果价格到达盈利目标并且看到顶背离信号,我就不用追踪止损;只要看到不利的价格运动,比如长上影伴随巨大的成交量,我会在盈利目标位获利了结;如果市场运行良好,并且底部一次比一次高,我就使用追踪止损方法。在价格到达盈利目标后,只有看到足够积极的价格信号我才会使用追踪止损。

盈利目标转换为追踪止损的使用频率是多少?

我在2/3的交易中都使用这种方法,但用得不是很好。有时候刚刚设定了追踪止损,5分钟后就被扫出局。大约有一半时间追踪止损法给我带来比原先更多的利润,大的获益极少,主要来自大行情中。

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

关于MultiIndex的资料并不太多,官方文档链接请点这里查看。

最近在使用MultiIndex时遇到的一个问题,先描述一下数据格式。我使用MultiIndex DataFrame来存储股票未来N天的收益率,变量命名为returns,数据样例如下,columns 1d和5d分别表示未来1天和5天的股票收益率,index为MultiIndex,第一级索引为日期,第二级索引为股票代码。

                              1d        5d
2005-01-04 000001.XSHE -0.009202  0.010736
           000002.XSHE  0.036053  0.045541
           000004.XSHE  0.020896  0.068657
           000005.XSHE  0.023474  0.098592
           000006.XSHE  0.014286  0.178571
...                          ...       ...
2020-12-11 688600.XSHG       NaN       NaN
           688777.XSHG       NaN       NaN
           688788.XSHG       NaN       NaN
           688981.XSHG       NaN       NaN
           689009.XSHG       NaN       NaN

对returns用start=‘2020-01-01’、end='2020-12-11’起止时间做了截断处理,代码片段如下:

returns_index = returns.index.get_level_values(level=0)
returns = returns.loc[(returns_index > pd.to_datetime(start)) & (returns_index < pd.to_datetime(end))]

这样获取的数据是从2020年开始的,但是使用returns.index.levels[0]发现数据还是从2005年开始的

returns.index.levels[0]
DatetimeIndex(['2005-01-04', '2005-01-05', '2005-01-06', '2005-01-07',
               '2005-01-10', '2005-01-11', '2005-01-12', '2005-01-13',
               '2005-01-14', '2005-01-17',
               ...
               '2020-11-30', '2020-12-01', '2020-12-02', '2020-12-03',
               '2020-12-04', '2020-12-07', '2020-12-08', '2020-12-09',
               '2020-12-10', '2020-12-11'],
              dtype='datetime64[ns]', length=3875, freq=None)

想了想,应该是由于index索引不可变,这里需要重建MultiIndex DataFrame,需要用到pandas.MultiIndex.remove_unused_levels() 方法先删除掉index里多余的信息,然后再重新创建MultiIndex DataFrame,代码如下:

tmp = returns.index.remove_unused_levels()
tmp = returns.index.remove_unused_levels()
returns = pd.DataFrame(returns, tmp)
returns.index.levels[0]
DatetimeIndex(['2020-01-02', '2020-01-03', '2020-01-06', '2020-01-07',
               '2020-01-08', '2020-01-09', '2020-01-10', '2020-01-13',
               '2020-01-14', '2020-01-15',
               ...
               '2020-11-27', '2020-11-30', '2020-12-01', '2020-12-02',
               '2020-12-03', '2020-12-04', '2020-12-07', '2020-12-08',
               '2020-12-09', '2020-12-10'],
              dtype='datetime64[ns]', length=228, freq=None)

看输出结果已经获取到了正确的时间范围内的数据。

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

今天遇到一个Pandas索引生成的问题,需要根据股票日频数据生成1分钟间隔的index,想了3个方法来生成:

方法1: 如果有1分钟bar数据的话可以直接读取数据获取index值,可惜没有哈

方法2: pandas.date_range,这个方法可以生成一个时间序列,设置参数freq=‘1min’ ,但是这样生成的结果包含了非交易时间段的数据,运行试了下速度也比较慢。

方法3: 两个list循环,第一个list是日期数据,第二个list是交易时间段的1分钟间隔数据,这个办法虽然笨点但是运行速度还挺快的,具体方法如下:

import itertools

import tushare as ts
import pandas as pd

pro = ts.pro_api()
df = ts.pro_bar(ts_code='000001.SZ', adj='hfq', start_date='20200101', end_date='20201209')
df.index = pd.to_datetime(df['trade_date'])
df.sort_index(inplace=True)

times = [d.strftime('%H:%M:%S') for d in
         pd.date_range('09:30:00', '11:30:00', closed='right', freq=('{}min'.format(1)))] + [
            d.strftime('%H:%M:%S') if d.strftime('%H:%M:%S') != '13:00:00' else '11:30:00' for d in
            pd.date_range('13:00:00', '15:00:00', closed='right', freq=('{}min'.format(1)))]

tmp = [str(item[0])[:10] + ' ' + item[1] for item in itertools.product(list(df.index), times)]
min1_index = pd.to_datetime(tmp)
print(min1_index)

输出结果如下:

DatetimeIndex(['2020-01-02 09:31:00', '2020-01-02 09:32:00',
               '2020-01-02 09:33:00', '2020-01-02 09:34:00',
               '2020-01-02 09:35:00', '2020-01-02 09:36:00',
               '2020-01-02 09:37:00', '2020-01-02 09:38:00',
               '2020-01-02 09:39:00', '2020-01-02 09:40:00',
               ...
               '2020-12-09 14:51:00', '2020-12-09 14:52:00',
               '2020-12-09 14:53:00', '2020-12-09 14:54:00',
               '2020-12-09 14:55:00', '2020-12-09 14:56:00',
               '2020-12-09 14:57:00', '2020-12-09 14:58:00',
               '2020-12-09 14:59:00', '2020-12-09 15:00:00'],
              dtype='datetime64[ns]', length=54480, freq=None)
Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

介绍

pyfolio是由Quantopian开发的Python库,用于对金融投资组合进行绩效和风险分析。它与Zipline开源回溯测试库配合使用良好。
pyfolio的核心是所谓的“tear sheet ”,它由各种单独的图组成,这些图提供了交易算法性能的全面图像展示。

入门示例

这里以双均线策略来做演示,当20日均线上穿40日均线买入股票,当20日均线下穿40日均线则卖出股票,首先我们通过tushare获取股票历史数据

import pandas as pd
import numpy as np
import tushare as ts
import pyfolio as pf

pro = ts.pro_api()
df = ts.pro_bar(ts_code='000001.SZ', adj='hfq', start_date='20150101', end_date='20191231')
df.index = pd.to_datetime(df['trade_date'])
df.sort_index(inplace=True)

接下来生成策略信号

df['ma20'] = df['close'].rolling(20).mean()
df['ma40'] = df['close'].rolling(40).mean()
# 计算20日均线和40日均线的距离
df['diff'] = df['ma20'] - df['ma40']
# 当diff值大于0买入股票,当diff值小于0卖出股票
df['signal'] = np.where(df['diff'] > 0, 1, 0)
df['signal'] = np.where(df['diff'] < 0, 0, df['signal'])
# 计算策略每日收益,这里计算每日收益使用log函数,signal计算由于使用了当天的收盘价,所以需要shift 1天,否则会用到未来数据
df['strategy'] = np.log(df['close'] / df['close'].shift(1)) * df['signal'].shift(1)
# 计算资产收益率
df['equity'] = df['strategy'].cumsum() + 1

展示资产收益率曲线,这里对股价做了归一化处理以便数据展示,可以看到双均线策略不仅跑赢股价,并且资金曲线回撤相对较小。

df['close_norm'] = df['close'] / float(df['close'][0])
df[['close_norm','equity']].plot(figsize=(12,6))

上图看到的信息有限,接下来是使用pyfolio工具对投资回报进一步分析,代码如下:

pf.create_full_tear_sheet(df['strategy'], benchmark_rets=np.log(df['close'] / df['close'].shift(1)))

首先是返回汇总信息:

介绍常用的几个指标:

  • Annual return:年化回报率
  • Cumulative returns: 累计收益率,是策略从开始执行到结束的总资产收益率。
  • Annual volatility:年化波动率
  • Sharpe ratio:夏普比率,一种非常流行的风险指标。它表示每单位风险(通过标准差衡量)的超额收益(超过无风险利率)。
  • Sortino ratio: 索提诺比率,Sharpe比率的修改版本,其中标准偏差由下行偏差代替。下行偏差仅衡量该系列的负波动性,严格来说是在称为最低可接受收益的预定水平以下。
  • Maximum drawdown :最大跌幅—指示峰和谷之间的最大跌幅(以%表示)
  • Tail ratio:对daily return的分布选取95分位和5分位,然后相除取绝对值。本质的含义就是赚取的return比亏钱的大多少倍。
  • Daily value at risk(daily Value-at-Risk )
    每日风险价值-另一个非常流行的风险指标。在这种情况下,这表明在95%的情况下,将头寸(投资组合)再保留1天,损失不会超过2.3%。

下图从各个角度对资产回报进行更详细的图表展示

参考

https://quantopian.github.io/pyfolio/
https://zhuanlan.zhihu.com/p/118108419
https://towardsdatascience.com/the-easiest-way-to-evaluate-the-performance-of-trading-strategies-in-python-4959fd798bb3

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant

Quantopian是国外著名的量化交易平台,早期聚宽就是仿照这个网站开发的,算是这类平台的鼻祖了,可惜Quantopian最近刚宣布要停止运营了。Quantopian开发了许多优秀的开源项目,其中比较著名的有zipline、pyfolio和alphalens,zipline是事件驱动的回测引擎,Alphalens与Zipline开源回溯测试库以及Pyfolio配合使用,Pyfolio提供金融投资组合的绩效和风险分析。

Alphalens主要功能是alpha因子的相关性统计数据和图表展示,包括:

  • Returns Analysis
  • Information Coefficient Analysis
  • Turnover Analysis
  • Grouped Analysis

下面通过一个例子来了解下Alphalens的主要用法,最重要的函数有两个:

  • get_clean_factor_and_forward_returns:数据预处理,将因子数据,价格数据和组映射格式化为包含对齐的时间戳和资产代码的MultiIndex索引的DataFrame。返回的数据将被格式化为适合Alphalens函数的格式。因子数据格式是MultiIndex索引,level0是时间,level1是资产代码,数据值只有一列为因子值,数据格式如下图所示:

  • create_full_tear_sheet: 生成全面的单因子分析和评估数据。

通过tushare获取A股股票数据,并将结果处理成get_clean_factor_and_forward_returns参数要求的格式

import pandas as pd
import tushare as ts

pro = ts.pro_api()
# 此接口获取的数据为未复权数据,回测建议使用后复权数据,这里为批量获取股票数据做了简化
df = pro.daily(ts_code='000001.SZ,600000.SH', start_date='20200101', end_date='20201231')
df.index = pd.to_datetime(df['trade_date'])
df.index.name = None
df.sort_index(inplace=True)
# MultiIndex,level0为日期,level1为股票代码,assets为get_clean_factor_and_forward_returns所需的因子数据格式
assets = df.set_index([df.index, df['ts_code']], drop=True)
# column为股票代码,index为日期,值为股票收盘价
close = df.pivot_table(index='trade_date',columns='ts_code',values='close')
close.index = pd.to_datetime(close.index)

生成的assets格式入下图所示,红框为index:

生成的close格式如下图所示:

接下来使用alphalens工具对数据进行分析,这里我们使用股票涨跌幅(字段名为pct_chg)作为因子数据

from alphalens.utils import get_clean_factor_and_forward_returns
from alphalens.tears import create_full_tear_sheet
# 需要将pct_chg做shift处理,否则将使用未来数据
ret = get_clean_factor_and_forward_returns(assets[['pct_chg']].shift(2),close)
create_full_tear_sheet(ret, long_short=False)

使用默认参数的情况下,ret将包含未来1、5、10日收益率,factor因子值,这里对应pct_chg列,factor_quantile为因子分组结果,默认会将因子分成5组,ret结果如图所示:

调用create_full_tear_sheet会生成因子分析结果,包含分位数统计信息、收益率信息、分组平均收益率柱状图、所有收益率分布图、单信号组合构建收益率图等,截取部分数据图如下:

以上就是样例全部内容,可以看到alphalens功能非常丰富,还需要继续深入学习了解。

参考

http://quantopian.github.io/alphalens/

https://www.quantopian.com/posts/alphalens-a-new-tool-for-analyzing-alpha-factors

Python量化交易实战
欢迎您扫码订阅我的微信公众号: pyquant