BackTrader 中文文档(一)(2)

简介: BackTrader 中文文档(一)

BackTrader 中文文档(一)(1)https://developer.aliyun.com/article/1489208

Python 2.x/3.x 兼容

开发工作在 Python 2.7 下进行,有时也在 3.4 下进行。本地同时运行两个版本的测试。

在 Travis 下,使用连续集成检查与 3.2 / 3.3 / 3.5 以及 pypy/pyp3 的兼容性

从 pypi 安装

例如使用 pip:

pip install backtrader

使用相同语法也可以应用 easy_install

从 pypi 安装(包括 matplotlib

若需要绘图功能,请使用此选项:

pip install backtrader[plotting]

这会引入 matplotlib,它将进一步引入其他依赖项。

你可能更喜欢(或只能使用…)easy_install

从源码安装

首先从 github 网站下载一个发布版或最新的压缩包:

解压后运行以下命令:

python setup.py install

从源码在你的项目中运行

从 github 网站下载一个发布版或最新的压缩包:

然后将 backtrader 包目录复制到你自己的项目中。例如,在类 Unix 操作系统下:

tar xzf backtrader.tgz
cd backtrader
cp -r backtrader project_directory

请记住,你随后需要手动安装 matplotlib 以进行绘图。

快速开始

原文:www.backtrader.com/docu/quickstart/quickstart/

注意

快速入门指南中使用的数据文件会不时更新,这意味着调整后的收盘价会变化,以及收盘价(以及其他组件)。这意味着实际输出可能与撰写文档时的情况不同。

使用平台

让我们通过一系列的例子运行一遍(从几乎空白到完全成熟的策略),但在粗略解释backtrader的两个基本概念之前。

  1. 线数据源、指标和策略都有线。一条线是一系列的点,当它们连接在一起时形成这条线。当谈到市场时,一个数据源通常每天有以下一组点:
  • 开盘价、最高价、最低价、收盘价、成交量、持仓量
  1. 一系列“开盘价”随时间的变化是一条线。因此,一个数据源通常有 6 条线。
    如果我们还考虑“DateTime”(这是单个点的实际参考),我们可以计算出 7 条线。
  2. 第 0 个指数方法
    当访问线中的值时,当前值通过索引访问:0
    通过*-1访问“最后”输出值。这符合 Python 对可迭代对象的惯例(一条线可以被迭代,因此是可迭代的),其中索引-1*用于访问可迭代/数组的“最后”项。
    在我们的情况下,访问的是最后的输出值。
    因此,作为* -1 之后的索引 0 *,它用于访问当前行。

考虑到这一点,如果我们想象一个在初始化过程中创建的简单移动平均策略:

self.sma = SimpleMovingAverage(.....)

访问当前移动平均线的最简单和最简单的方法:

av = self.sma[0]

无需知道已处理了多少个条/分钟/天/月,因为“0”唯一标识当前时刻。

按照 Python 的传统,通过*-1*来访问“最后”输出值:

previous_value = self.sma[-1]

当然,早期的输出值可以用-2、-3 等来访问

从 0 到 100:样本

基本设置

让我们开始吧。

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import backtrader as bt
if __name__ == '__main__':
    cerebro = bt.Cerebro()
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

执行后输出为:

Starting Portfolio Value: 10000.00
Final Portfolio Value: 10000.00

在这个例子中:

  • backtrader 被导入
  • Cerebro 引擎被实例化
  • 创建的cerebro实例被告知运行(循环遍历数据)
  • 结果输出并打印出来

虽然看起来不起眼,但让我们明确指出一些事情:

  • Cerebro 引擎在后台创建了一个broker实例
  • 实例已经有一些现金可以开始了

在幕后经纪人实例化是该平台的一个固定特征,以简化用户的生活。如果用户未设置经纪人,则会放置一个默认的经纪人。

10000 个货币单位是一些经纪人开始使用的常见值。

设置现金

在金融世界中,确实只有“失败者”才从 10k 开始。让我们改变现金并再次运行示例。

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import backtrader as bt
if __name__ == '__main__':
    cerebro = bt.Cerebro()
    cerebro.broker.setcash(100000.0)
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

执行后输出为:

Starting Portfolio Value: 1000000.00
Final Portfolio Value: 1000000.00

任务完成。让我们转向风云变幻的水域。

添加一个 Data Feed

拥有现金很有趣,但所有这一切背后的目的是让一个自动化策略通过对我们视为 Data Feed 的资产进行操作而无需动手指就能增加现金。

因此… 没有 Data Feed -> 没趣。让我们给这个不断增长的示例添加一个。

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
if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()
    # 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, '../../datas/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 after this date
        todate=datetime.datetime(2000, 12, 31),
        reverse=False)
    # Add the Data Feed to Cerebro
    cerebro.adddata(data)
    # Set our desired cash start
    cerebro.broker.setcash(100000.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())

执行后的输出为:

Starting Portfolio Value: 1000000.00
Final Portfolio Value: 1000000.00

模板代码的数量略有增加,因为我们添加了:

  • 找出我们示例脚本所在的位置,以便能够定位示例 Data Feed 文件
  • datetime 对象用于过滤我们将要操作的 Data Feed 中的数据。

除此之外,Data Feed 被创建并添加到 cerebro 中。

输出没有变化,如果有变化将是个奇迹。

注意

Yahoo Online 以日期降序发送 CSV 数据,这不是标准约定。reversed=True 参数考虑到 CSV 文件中的数据已经被 反转,并具有标准预期的日期升序。

我们的第一个策略

现金在 broker 中,而 Data Feed 在那里。看起来,危险的生意就在拐角处。

让我们将一个策略引入到等式中,并打印每天(每个 bar)的“Close”价格。

DataSeriesData Feeds 中的基础类)对象具有访问已知 OHLC(开盘价 最高价 最低价 收盘价)日常值的别名。这应该能够简化我们的打印逻辑的创建。

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):
    def log(self, txt, dt=None):
  ''' Logging function for 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
    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
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, '../../datas/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(100000.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())

执行后的输出为:

Starting Portfolio Value: 100000.00
2000-01-03T00:00:00, Close, 27.85
2000-01-04T00:00:00, Close, 25.39
2000-01-05T00:00:00, Close, 24.05
...
...
...
2000-12-26T00:00:00, Close, 29.17
2000-12-27T00:00:00, Close, 28.94
2000-12-28T00:00:00, Close, 29.29
2000-12-29T00:00:00, Close, 27.41
Final Portfolio Value: 100000.00

有人说股票市场是危险的生意,但似乎并不是这样。

让我们解释一些魔法:

  • 在调用 init 后,策略已经拥有了平台上存在的数据列表。
    这是一个标准的 Python list,可以按插入顺序访问数据。
    列表中的第一个数据 self.datas[0] 是默认用于交易操作的数据,并且用于保持所有策略元素同步(它是系统时钟)。
  • self.dataclose = self.datas[0].close 保持对 close 线 的引用。稍后只需要一级间接引用就能访问 close 值。
  • 策略的 next 方法将在系统时钟的每个 bar 上调用(self.datas[0])。直到其他因素开始起作用,如 指标,它们需要一些 bar 才能开始产生输出。稍后会详细介绍。

在策略中添加一些逻辑

让我们通过查看一些图表来尝试一些疯狂的想法。

  • 如果价格连续下跌 3 个交易会话… 买买买!!!
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):
    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
    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
        if self.dataclose[0] < self.dataclose[-1]:
            # current close less than previous close
            if self.dataclose[-1] < self.dataclose[-2]:
                # previous close less than the previous close
                # BUY, BUY, BUY!!! (with all possible default parameters)
                self.log('BUY CREATE, %.2f' % self.dataclose[0])
                self.buy()
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, '../../datas/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(100000.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())

执行后的输出为:

Starting Portfolio Value: 100000.00
2000-01-03, Close, 27.85
2000-01-04, Close, 25.39
2000-01-05, Close, 24.05
2000-01-05, BUY CREATE, 24.05
2000-01-06, Close, 22.63
2000-01-06, BUY CREATE, 22.63
2000-01-07, Close, 24.37
...
...
...
2000-12-20, BUY CREATE, 26.88
2000-12-21, Close, 27.82
2000-12-22, Close, 30.06
2000-12-26, Close, 29.17
2000-12-27, Close, 28.94
2000-12-27, BUY CREATE, 28.94
2000-12-28, Close, 29.29
2000-12-29, Close, 27.41
Final Portfolio Value: 99725.08

发出了多个“BUY”创建订单,我们的投资组合价值减少了。显然有几个重要的事情缺失了。

  • 订单已创建,但不清楚是否已执行,何时执行以及以什么价格执行。
    下一个示例将在此基础上建立,通过监听订单状态通知。

好奇的读者可能会问买了多少股票,购买了什么资产以及订单是如何执行的。在可能的情况下(在这种情况下是可能的),平台会填补这些空白:

  • self.datas[0](主数据,也称为系统时钟)是目标资产,如果没有指定其他资产
  • 股份是由position sizer在后台提供的,它使用固定的股份,“1”是默认值。稍后将进行修改。
  • 订单是“市价”执行的。经纪人(在前面的示例中显示)使用下一根 bar 的开盘价执行此操作,因为那是当前检查的 bar 之后的第一个 tick。
  • 到目前为止,订单已经执行了,没有任何佣金(稍后会详细介绍)

不仅买……还卖

在了解如何进入市场(做多)之后,需要一个“退出概念”,并且还要了解策略是否处于市场中。

  • 幸运的是,Strategy 对象为默认的data feed提供了对position属性的访问权限
  • buysell方法返回创建的(尚未执行)订单
  • 订单状态的更改将通过notify方法通知策略

*“退出概念”*将是一个简单的概念:

  • 在过了 5 个 bar(第 6 个 bar)之后退出,无论好坏都要退出
    请注意,没有暗示“时间”或“时间框架”:bar 的数量。bar 可以表示 1 分钟、1 小时、1 天、1 周或任何其他时间段。
    尽管我们知道数据源是每日的,但策略不对此做任何假设。

此外,为了简化:

  • 只有在市场中还没有持仓时才允许买入订单

注意

next方法没有传递“bar index”,因此似乎不清楚如何理解 5 个 bar 是否已经过去,但这已经以 Pythonic 的方式进行了建模:在对象上调用len,它将告诉您它的lines长度。只需记录(保存在变量中)操作发生的长度,然后查看当前长度是否相差 5 个 bar。

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):
    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
        self.order = None
    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, %.2f' % order.executed.price)
            elif order.issell():
                self.log('SELL EXECUTED, %.2f' % order.executed.price)
            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 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.dataclose[-1]:
                    # current close less than previous close
                    if self.dataclose[-1] < self.dataclose[-2]:
                        # previous close less than the previous close
                        # BUY, BUY, BUY!!! (with 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:
            # Already in the market ... we might sell
            if len(self) >= (self.bar_executed + 5):
                # 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, '../../datas/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(100000.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())

执行后的输出如下:

Starting Portfolio Value: 100000.00
2000-01-03T00:00:00, Close, 27.85
2000-01-04T00:00:00, Close, 25.39
2000-01-05T00:00:00, Close, 24.05
2000-01-05T00:00:00, BUY CREATE, 24.05
2000-01-06T00:00:00, BUY EXECUTED, 23.61
2000-01-06T00:00:00, Close, 22.63
2000-01-07T00:00:00, Close, 24.37
2000-01-10T00:00:00, Close, 27.29
2000-01-11T00:00:00, Close, 26.49
2000-01-12T00:00:00, Close, 24.90
2000-01-13T00:00:00, Close, 24.77
2000-01-13T00:00:00, SELL CREATE, 24.77
2000-01-14T00:00:00, SELL EXECUTED, 25.70
2000-01-14T00:00:00, Close, 25.18
...
...
...
2000-12-15T00:00:00, SELL CREATE, 26.93
2000-12-18T00:00:00, SELL EXECUTED, 28.29
2000-12-18T00:00:00, Close, 30.18
2000-12-19T00:00:00, Close, 28.88
2000-12-20T00:00:00, Close, 26.88
2000-12-20T00:00:00, BUY CREATE, 26.88
2000-12-21T00:00:00, BUY EXECUTED, 26.23
2000-12-21T00:00:00, Close, 27.82
2000-12-22T00:00:00, Close, 30.06
2000-12-26T00:00:00, Close, 29.17
2000-12-27T00:00:00, Close, 28.94
2000-12-28T00:00:00, Close, 29.29
2000-12-29T00:00:00, Close, 27.41
2000-12-29T00:00:00, SELL CREATE, 27.41
Final Portfolio Value: 100018.53

烈焰般的船舱!!! 系统赚了钱……一定有问题。

经纪人说:给我看看钱!

钱被称为“佣金”。

让我们为每次操作(买入和卖出……是的,经纪人很贪婪……)添加合理的*0.1%*佣金率。

一条线足矣:

# 0.1% ... divide by 100 to remove the %
cerebro.broker.setcommission(commission=0.001)

由于对该平台有经验,我们想要在买入/卖出周期之后看到利润或损失,有无佣金都行。

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):
    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
    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')
        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.dataclose[-1]:
                    # current close less than previous close
                    if self.dataclose[-1] < self.dataclose[-2]:
                        # previous close less than the previous close
                        # BUY, BUY, BUY!!! (with 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:
            # Already in the market ... we might sell
            if len(self) >= (self.bar_executed + 5):
                # 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, '../../datas/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(100000.0)
    # Set the commission - 0.1% ... divide by 100 to remove the %
    cerebro.broker.setcommission(commission=0.001)
    # 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())

BackTrader 中文文档(一)(3)https://developer.aliyun.com/article/1489211

相关文章
|
5月前
|
索引
BackTrader 中文文档(六)(2)
BackTrader 中文文档(六)
79 0
|
5月前
|
存储 编解码 API
BackTrader 中文文档(四)(1)
BackTrader 中文文档(四)
64 1
|
5月前
|
存储 数据库连接 数据库
BackTrader 中文文档(三)(2)
BackTrader 中文文档(三)
78 0
|
5月前
|
索引
BackTrader 中文文档(三)(4)
BackTrader 中文文档(三)
57 0
|
5月前
|
Python
BackTrader 中文文档(一)(3)
BackTrader 中文文档(一)
54 0
|
5月前
|
存储
BackTrader 中文文档(四)(4)
BackTrader 中文文档(四)
42 0
|
5月前
|
Python
BackTrader 中文文档(六)(4)
BackTrader 中文文档(六)
81 0
|
5月前
|
存储 安全 Unix
BackTrader 中文文档(四)(2)
BackTrader 中文文档(四)
55 0
|
5月前
|
存储 DataX Python
BackTrader 中文文档(五)(1)
BackTrader 中文文档(五)
91 0
|
5月前
BackTrader 中文文档(五)(2)
BackTrader 中文文档(五)
72 0