我们的量化历程-Python算法简易实例

(于北京疫情期间)

量化之所以做为投资的手段,早应该有共识了。下围棋象棋的人知道, 人脑不可能战胜有智能的程序,它的计算能力太强太快,加上严格的程序化执行。我们人在做交易的时候,受情绪身体状况影响,感知的偏差,消息的不对称,往往会经常性的犯错。

我们的量化历程也是发展的很不顺利,从最初C++Fix协议注重高频交易,C#算法编程。到如今终于归入正道,发现Python才是一统江山的金融量化的工具,而我们现在用的Backtrader更可以称为国之重器!为什么呢? 首先它有强大丰富的支持库,简单易用且成熟。 具体对我们来说就是金融数据分析应用方面引用库numpy,pandas和matplotlib。可以非常快速部署,性能稳定高效。

又为什么说它一统江山呢?外汇,加密货币和金融股指期货可以一并用它作为量化工具了:

  • FX-外汇有 IB, OANDA可以支持用(策略难度最高)
  • 加密货币的大部分交易所;我们现在用OKex,Binance (难度适中)
  • 国内的股指商品期货极星量化交易可以用 (相对简单)

通用的解决方案是Python封装API接口。这大大简化了各个平台策略开发。相信国内外宽客的同行团队越来越多的会像我们一样,转向Python-BT。也许很快就发展成为新的行业标准。

下面是BT应用的一个简单实例,只需要几分钟就安装好了,在你的Python的 IDE环境运行一下,看你是否认同它的强大简单和高效!?

首先安装BACKTRADER

pip install backtrader
pip install backtrader[plotting]

下面我们运行一个简单的策略,将symbol orcl一年的数据导入策略运行,结果显示导入数据和价格曲线以图形方式绘制出来。设定起始资金,用这次导入价格数据运行后显示交易记录和资金状况。

下面是数据文件的链接,浏览打开另存到本地文件夹,程序中默认路径为当前程序目录。请根据需要修改。

https://nabidex.com/usercontent/orcl-1995-2014.txt

数据文件存好后, 复制下面的程序就可以运行了,结果看后面的截图。

#this source code is provided by Backtrader Team!
from __future__ import (absolute_import,division,print_function,unicode_literals)
import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])
# Import the backtrader platform
import backtrader as bt
# Create a Stratey
class TestStrategy(bt.Strategy):
    params = (
        ('maperiod', 15),
    )
    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))
    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close
        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        # Add a MovingAverageSimple indicator
        self.sma = bt.indicators.SimpleMovingAverage(
            self.datas[0], period=self.params.maperiod)
        # Indicators for the plotting show
        bt.indicators.ExponentialMovingAverage(self.datas[0],period=25)
        bt.indicators.WeightedMovingAverage(self.datas[0],period=25,subplot=True)
        bt.indicators.StochasticSlow(self.datas[0])
        bt.indicators.MACDHisto(self.datas[0])
        rsi = bt.indicators.RSI(self.datas[0])
        bt.indicators.SmoothedMovingAverage(rsi,period=10)
        bt.indicators.ATR(self.datas[0],plot=False)
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return
        # Check if an order has been completed
        # Attention: broker could reject order if not enough cash
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))
            self.bar_executed = len(self)
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
        # Write down: no pending order
        self.order = None
    def notify_trade(self, trade):
        if not trade.isclosed:
            return
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return
        # Check if we are in the market
        if not self.position:
            # Not yet ... we MIGHT BUY if ...
            if self.dataclose[0] > self.sma[0]:
                # BUY, BUY, BUY!!! (with all possible default parameters)
                self.log('BUY CREATE, %.2f' % self.dataclose[0])
                # Keep track of the created order to avoid a 2nd order
                self.order = self.buy()
        else:
            if self.dataclose[0] < self.sma[0]:
                # SELL, SELL, SELL!!! (with all possible default parameters)
                self.log('SELL CREATE, %.2f' % self.dataclose[0])
                # Keep track of the created order to avoid a 2nd order
                self.order = self.sell()
if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()
    # Add a strategy
    cerebro.addstrategy(TestStrategy)
    # Datas are in a subfolder of the samples. Need to find where the script is
    # because it could have been called from anywhere
    modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    datapath = os.path.join(modpath, 'orcl-1995-2014.txt')
    # Create a Data Feed
    data = bt.feeds.YahooFinanceCSVData(
        dataname=datapath,
        # Do not pass values before this date
        fromdate=datetime.datetime(2000, 1, 1),
        # Do not pass values before this date
        todate=datetime.datetime(2000, 12, 31),
        # Do not pass values after this date
        reverse=False)
    # Add the Data Feed to Cerebro
    cerebro.adddata(data)
    # Set our desired cash start
    cerebro.broker.setcash(1000.0)
    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=10)
    # Set the commission
    cerebro.broker.setcommission(commission=0.0)
    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    # Run over everything
    cerebro.run()
    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    # Plot the result
    cerebro.plot()
最后是运行后的截图:

欢迎同行加入我们的群组交流讨论!

发表评论

电子邮件地址不会被公开。 必填项已用*标注