易经量化交易系统1

易经量化交易系统是一个完整的量化交易平台,提供基于深度元强化学习的交易策略,并且具有一整套回测平台,可以用于策略研发和实盘操作。
量化交易平台中,回测系统是一个关键的功能,易经量化交易系统的回测系统是基于BackTrader的回测系统,为量化交易研发中的性能评估,提供了一个易用回测系统,做量化交易研发,首先需要选择一个好的回测系统,所以我们先来向大家介绍这个回测系统。

环境配置

首先下载易经量化系统源码:

git clone https://github.com/yt7589/iching.git

在易经量化交易系统中,已经在源码层级整合了BackTrader系统,所以无需单独安装,即可使用回测系统。
在源码的apps/fmml目录,创建bt_app.py:

class BtApp(object):
    def __init__(self):
        self.name = 'apps.fmml.BtApp'

    def startup(self):
        print('回测系统示例程序 v0.0.1')

在apps/fmml/fmml_app.py中,启动这个应用:

from apps.fmml.bt_app import BtApp

class FmmlApp(object):    
    def startup(self):
        app = BtApp()
        app.startup()

回测平台基本概念

首先是线的概念,线就是标量值的时间序列,我们以股票市场的日K数据为例,通常包括:日期, 开盘价, 最高价, 最低价, 收盘价, 成交量等信息,这里就有日期线、开盘价线、最高价线、最低价线、收盘价线、成交量线,我们以开盘价线为例:

日期 7.31 8.1 8.2 8.3 8.4 8.5 8.6
形盘价 1.1 1.02 1.3 1.12 0.98 1.13 1.25

我们假设今天是8.2日,所以open_price[0]的值为1.3,而open_price[-1]代表的是8月1日的价格,值为1.02,以此类推,7月31日的价格为open_price[-2]=1.1。因为我们是回测过程,拿到的所有历史数据,所以我们有当天回测日期的明天的数据open_price[1],后天的数据为open_price[2],以此类推。

Hello World例程

接下来我们来看一个最简单的回测程序,在这里我们什么也不做,只是启动回测系统:

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import backtrader as bt

class BtApp(object):
    def startup(self):
        print('回测系统示例程序 v0.0.2')
        cerebro = bt.Cerebro()
        cerebro.broker.setcash(100000.0) # 设置初始资金
        print('期初净值: %.2f' % cerebro.broker.getvalue())
        cerebro.run()
        print('期末净值: %.2f' % cerebro.broker.getvalue())

在这里,我们只是简单的初始化一个回测引擎,设置初始资金,然后运行这个回测引擎,最后输出结束时的净值。由于我们在这里什么都没做,所以我们净值没有发生变化,而且眨眼间就执行结束了。

加入行情数据

我们的量化交易系统,就是用来根据行情来做交易的。下面我们获取A股日K线数据,并将其加入到回测引擎中来。

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import backtrader as bt
import akshare as ak

class BtApp(object):
    def startup(self, code='sh601318', start_cash=100000.0):
        print('回测系统示例程序 v0.0.2')
        cerebro = bt.Cerebro()
        stock_zh_a_daily_df = ak.stock_zh_a_daily(
            symbol=code, adjust="hfq"
        )  # 通过 AkShare 获取需要的数据
        data = bt.feeds.PandasData(dataname=stock_zh_a_daily_df)  # 规范化数据格式
        cerebro.adddata(data)  # 将数据加载至回测系统
        cerebro.broker.setcash(start_cash) # 设置初始资金
        print('期初净值: %.2f' % cerebro.broker.getvalue())
        cerebro.run()
        print('期末净值: %.2f' % cerebro.broker.getvalue())

我们通过akshare来获取A股日K线数据,获取的股票代码为sh601318,即中国平安的股票。

简单策略

下面我们来开发一个最简单的策略,就是连涨三天则买入,而连接持有5个交易日则卖出:

class TestStrategy(bt.Strategy):
    def __init__(self):
        self.dataclose = self.datas[0].close # 收盘价线
        self.order = None

    def notify_order(self, order):
        # 如果订单状态为提交和接受则直接返回
        if order.status in [order.Submitted, order.Accepted]:
            return
        # 如果订单为完成
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log('执行买入:{0:.2f}'.format(order.executed.price))
            elif order.issell():
                self.log('执行卖出:{0:.2f}'.format(order.executed.price))
            self.bar_executed = len(self) # 订单执行时间点
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('订单被取消或拒绝!')
        self.order = None

    def next(self):
        self.log('收盘价:{:.2f}'.format(self.dataclose[0]))
        if self.order:
            return
        if not self.position:
            if self.dataclose[0] < self.dataclose[-1]:
                    if self.dataclose[-1] < self.dataclose[-2]:
                        self.log('生成买入订单:{0:.2f}'.format(self.dataclose[0]))
                        self.order = self.buy()
        else:
            if len(self) >= (self.bar_executed + 5):
                self.log('生成卖出订单:{0:.2f}'.format(self.dataclose[0]))
                self.order = self.sell()

    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print('{0}, {1}'.format(dt.isoformat(), txt))

由于只有策略类需要修改,这里只列出了策略类的实现。

  • 第6行:我们增加了订单状态监听方法,在订单执行时打印日志信息;
  • 第25行:判断我们是否持有该股票,如果没持有该支股票,这时才能买入该支股票;
  • 第26~29行:如果连涨3天则买入;
  • 第31~33行:连续持有5个时间点则卖出,需要注意的是,这里是日K线,所以是连续持有5个交易日,但是如果是分钟线,这里就会变为持有5分钟;

至此,我们就完成了一个最简的回测系统,运行程序,输出如下所示:

2020-07-07, 收盘价:203.81
2020-07-08, 收盘价:209.86
2020-07-09, 收盘价:210.43
2020-07-10, 收盘价:201.66
2020-07-13, 收盘价:201.71
2020-07-14, 收盘价:199.11
2020-07-15, 收盘价:196.47
2020-07-15, 生成买入订单:196.47
2020-07-16, 执行买入:199.11
2020-07-16, 收盘价:191.57
2020-07-17, 收盘价:191.08
2020-07-20, 收盘价:202.79
2020-07-21, 收盘价:197.79
2020-07-22, 收盘价:195.76
2020-07-23, 收盘价:193.48
2020-07-23, 生成卖出订单:193.48
2020-07-24, 执行卖出:193.19
2020-07-24, 收盘价:188.58
2020-07-24, 生成买入订单:188.58
2020-07-27, 执行买入:189.27
2020-07-27, 收盘价:187.19
2020-07-28, 收盘价:187.06
2020-07-29, 收盘价:189.32
2020-07-30, 收盘价:186.21
2020-07-31, 收盘价:185.89
2020-08-03, 收盘价:187.21
2020-08-03, 生成卖出订单:187.21
期末净值: 100049.63

其实中国平安自上市以来,股价翻了很多倍,所以我们如果用最简单的策略,上市之初就买入,期间一直持有,最终的净值一定比我们的这个策略的结果好的多,因此我们的策略需要大力改造。
在这里还有一个问题,我们在这里交易是没有成本的,但是在实际股市中,交易需要交佣金、印花税、过户费等税费,所以为了使我们的回测系统更接近于真实系统,我们需要加入交易成本项。关于这部分内容,我们将在下一篇博文中介绍。

你可能感兴趣的:(量化交易)