zoukankan      html  css  js  c++  java
  • Backtrader中文笔记之Operating the platform(操作平台)。

    Line Iterators

    行 迭代器

    To engage into operations, the plaftorm uses the notion of line iterators. They have been loosely modeled after Python’s iterators but have actually nothing to do with them.

    为了进行操作,plaftorm使用了行迭代器的概念。它们松散地模仿了Python的迭代器,但实际上与它们没有任何关系。

    Strategies and Indicators are line iterators

    策略与指标都是线迭代器

    The line iterator concept tries to describe the following:

    对行迭代器尝试以下方式解释:

    A Line Iterator kicks slave line iterators telling them to iterate

    一个行迭代器踢了行迭代器成员,告诉它们进行迭代

    A Line Iterator then iterates over its own declared named lines setting values

    然后行迭代器迭代自己声明的命名行,并设置值

    The key to iteration, just like with regular Python iterators, is

    就像Python的迭代器一样,迭代的关键是:

    The next method

    next方法

    It will be called for each iteration. The datas array which the line iterator has and serve as basis for logic/calculations will have already been moved to the next index by the platform (barring data replay)

    每次迭代都会调用它。迭代器作为逻辑/计算基础,有能力移动数据数组的下一个索引(禁止数据重放)

    Called when the minimum period for the line iterator has been met. A bit more on this below.

    当满足行迭代器的最小周期时调用。下面还有一点。

    But because they are not regular iterators, two additional methods exist:

    但是因为它们不是常规的迭代器,所以存在两个额外的方法:

    prenext

    Called before the minimum period for the line iterator` has been met

    在满足行迭代器的最小周期之前调用。(理解为在next的过程中,不满足条件没有输出的,比如15日均线,前面没有输出的就在这里输出)

    nextstart

    Called exactly ONCE when the minimum period for the line iterator` has been met.

    当满足行迭代器的最小周期时,只调用一次。

    The default behavior is to forward the call to next, but can of course be overriden if needed.

    默认的行为是将调用转发到next,但是如果需要,当然可以被覆盖。

    Extra methods for Indicators

    策略的额外方法

    To speed up operations, Indicators support a batch operation mode which has been termed as runonce. It is not strictly needed (a next method suffices) but it greatly reduces time.

    为了加快操作速度,指标支持称为runonce的批处理操作模式。它不是严格需要的(next方法就足够了),但是它大大缩短了时间。

    The runonce methods rules void the get/set point with index 0 and relies on direct access to the underlying arrays holding the data and being passed the right indices for each state.

    runonce方法规定使用索引0来grt/set点,并依赖于对存储数据的底层数组的直接访问,并为每个状态传递正确的索引。

    The defined methods follow the naming of the next family:

    定义的方法遵循该规则的命名:

    • once(self, start, end)

      Called when the minimum period has been met. The internal array must be processed between start and end which are zero based from the start of the internal array

    • 当满足最小周期时调用。内部数组必须在开始和结束之间进行处理,从内部数组的开始到结束都是零
    • preonce(self, start, end)

      Called before the minimum period has been met.

    • 在满足最小期限之前调用。
    • oncestart(self, start, end)

    • Called exactly ONCE when the minimum period has been met.

      The default behavior is to forward the call to once, but can of course be overriden if needed.

    • 恰好在满足最小周期时调用一次。

      默认的行为是将调用转发到once,但是如果需要,当然可以被覆盖。

    Minimum Period

    最小周期

    A picture is worth a thousand words and in this case possibly an example too. A SimpleMovingAverage is capable of explaining it:

    一张图片胜过千言万语,在这种情况下,也可能是一个例子。一个 SimpleMovingAverage能够解释它:

    class SimpleMovingAverage(Indicator):
        lines = ('sma',)
        params = dict(period=20)
    
        def __init__(self):
            ...  # Not relevant for the explanation
    
        def prenext(self):
            print('prenext:: current period:', len(self))
    
        def nextstart(self):
            print('nextstart:: current period:', len(self))
            # emulate default behavior ... call next
            self.next()
    
        def next(self):
            print('next:: current period:', len(self))
    

      

    And the instantiation could look like:

    实例如下所示

     
    sma = btind.SimpleMovingAverage(self.data, period=25)
    

    Briefly explained:

    简略说明

    • Assuming the data passed to the moving average is a standard data feed its default period is 1 that is: the data feed produces a bar with no initial delay.

    • 假设传递给移动平均线的数据是一个标准数据馈送,它的默认周期是1,也就是说:数据馈送产生一个没有初始延迟的条。
    • Then the “period=25” instantiated moving average would have its methods called as follows:

    • 那么实例化的“period=25”移动平均线的方法调用如下:
      • prenext 24 times

      • prenext运行24次
      • nextstart 1 time (in turn calling next)

      • nextstart运行一次(转向next)
      • next n additional times until the data feed has been exhausted

      • next将运行n次,知道数据用完

    Let’s go for the killer indicator: a SimpleMovingAverage over another SimpleMovingAverage. The instantiation could look like:

     让我们来看看最致命的指标:一个简单的平均水平用与于另一个简单的平均水平。实例化看起来像:
    sma1 = btind.SimpleMovingAverage(self.data, period=25)
    
    sma2 = btind.SimpleMovingAverage(sma1, period=20)
    

    What now goes on:

    现在接着说:

    • The same as above for sma1

    • sma1与之前一样
    • sma2 is receiving a data feed which has a minimum period of 25 which is our sma1 and therefore

    • sma2接收的数据feed至少有25个周期,这是我们的sma1,因此
    • The sma2 methods are called as indicated:

    • 按照指示调用sma2方法
      • prenext the first 25 + 18 times for a total of 43 times

      • prenext前25 + 18次,共43次
      • 25 times to let sma1 produce its 1st sensible value

      • 25次的时候让sma1产生第一个合理价值
      • 18 times to accumulate extra sma1 values

      • 18次以积累额外的sma1值
      • For a total of 19 values (1 after 25 calls and then 18 more)

      • 总共19个值(1个在25次调用之后,18个以上)
      • nextstart then 1 time (in turn calling next)

      • nextstart然后1次(依次调用next)
      • next the n additional times until the data feed has been exhausted

      • 接下来的n次,直到数据提要被耗尽

    The platform is calling next when the system has already processed 44 bars.

    当系统已经处理了44个bar时,平台才调用next。

    The minimum period has been automatically adjusted to the incoming data.

    最小周期将根据传入数据自动调整。

    Strategies and Indicators adhere to this behavior:

    策略和指标坚持这一行为:

    • Only when the automatically calculated minimum period has been reached will next be called (barring the initial hook call to nextstart)
    • 只有当达到自动计算的最小周期时,才会下一次调用(除非对nextstart的初始钩子调用)nextstart方法比next提前执行

    Note

    The same rules apply to preonce, oncestart and once for the runonce batch operation mode

    同样的规则适用于preonce、oncestart和once的runonce批处理操作模式

    Note

    The minimum period behavior can be manipulated although it’s not recommended. Should it be wished used the setminperiod(minperiod) method in either Strategies or Indicators

    最小周期行为可以被操纵,尽管不推荐。取决与是否在策略或指标中使用setminperiod(minperiod)方法

    Up and Running

    启动与运行

    Getting up and running involves at least 3 Lines objects:

    启动与运行至少涉及三个Lines对象

    • A Data feed

    • A Strategy (actually a class derived from Strategy)

    • A Cerebro (brain in Spanish)

    Data Feeds

    数据饲料

    These objects, obviously, provide the data which will be backtested by applying calculations (direct and/or with Indicators)

    显然,这些对象提供了将通过应用计算(直接 和/或 指示符)进行回溯测试的数据

    The platform provides several data feeds:

    平台提供了几个数据饲料的样板

    • Several CSV Format and a Generic CSV reader

    • 通用CSV
    • Yahoo online fetcher

    • Yahoo在线提取
    • Support for receiving Pandas DataFrames and blaze objects

    • 用于接收Pandas数据格式以及blzae对象
    • Live Data Feeds with Interacive Brokers, Visual Chart and Oanda

    • 互动的数据

    The platform makes no assumption about the content of the data feed such as timeframe and compression. Those values, together with a name, can be supplied for informational purposes and advance operations like Data Feed Resampling (turning a for example a 5 minute Data Feed into a Daily Data Feed)

    平台对数据提供的内容比如时间框架和压缩不做任何假设。这些值和名称可以用于提供信息和推进操作。就像数据饲料的重采集(例如将5分钟的数据饲料转换为天的数据饲料)

    Example of setting up a Yahoo Finance Data Feed:

    import backtrader as bt
    import backtrader.feeds as btfeeds
    
    ...
    
    datapath = 'path/to/your/yahoo/data.csv'
    
    data = btfeeds.YahooFinanceCSVData(
        dataname=datapath,
        reversed=True)
    

    The optional reversed parameter for Yahoo is shown, because the CSV files directly downloaded from Yahoo start with the latest date, rather than with the oldest.

    显示了Yahoo的可选反向参数,因为直接从Yahoo下载的CSV文件以最新的日期开始,而不是最老的日期。

    If your data spans a large time range, the actual loaded data can be limited as follows:

    如果数据跨度较大,实际加载的数据可以限制如下:

    data = btfeeds.YahooFinanceCSVData(
        dataname=datapath,
        reversed=True
        fromdate=datetime.datetime(2014, 1, 1),
        todate=datetime.datetime(2014, 12, 31))
    

    Both the fromdate and the todate will be included if present in the data feed.

    fromdatetodate都将包含在数据饲料中

    As already mentioned timeframe, compression and name can be added:

    如前面所述,timeframe与compression可以被添加设置

    data = btfeeds.YahooFinanceCSVData(
        dataname=datapath,
        reversed=True
        fromdate=datetime.datetime(2014, 1, 1),
        todate=datetime.datetime(2014, 12, 31)
        timeframe=bt.TimeFrame.Days,
        compression=1,
        name='Yahoo'
       )
    

    If the data is plotted, those values will be used.

    如果数据被绘制,这些值将被使用。

    A Strategy (derived) class

    一个 策略(派生)类

    Note

    Before going on and for a more simplified approach, please check the Signals section of the documentation if subclassing a strategy is not wished.

    在使用更简化的方法之前,如果不希望对策略进行子类化,请检查文档的signal部分。

    The goal of anyone using the platform is backtesting the data and this is done inside a Strategy (derived class).

    任何使用该平台的人的目标都是返回测试数据,这是在策略(派生类)中完成的

    There are 2 methods which at least need customization:

    这里有两个方法必须定制

    • __init__

    • next

    During initialization indicators on data and other calculations are created prepared to later apply the logic.

    在初始化期间,将创建数据和其他计算的指示器,以便稍后应用逻辑。

    The next method is later called to apply the logic for each and every bar of the data.

    接下来的next方法为每一条数据添加逻辑

    Note

    If data feeds of different timeframes (and thus different bar counts) are passed the next method will be called for the master data (the 1st one passed to cerebro, see below) which must be the the data with the smaller timeframe

    如果传递了不同的时间框架(因此有不同的bar),则将调用next方法来获取主数据(第一个传递给cerebro的方法,见下文),他必须具有较小的时间框架的数据。

    Note

    If the Data Replay functionality is used, the next method will be called several time for the same bar as the development of the bar is replayed.

    如果使用了数据回放功能,在开发时next方法将被调用多次在同一个bar,bar将被重播

    A basic Strategy derived class:

    class MyStrategy(bt.Strategy):
    
        def __init__(self):
    
            self.sma = btind.SimpleMovingAverage(self.data, period=20)
    
        def next(self):
    
            if self.sma > self.data.close:
                self.buy()
    
            elif self.sma < self.data.close:
                self.sell()
    

    Strategies have other methods (or hook points) which can be overriden:

    策略有其他方法或(回勾点),可以重写

    class MyStrategy(bt.Strategy):
    
        def __init__(self):
    
            self.sma = btind.SimpleMovingAverage(self.data, period=20)
    
        def next(self):
    
            if self.sma > self.data.close:
                submitted_order = self.buy()
    
            elif self.sma < self.data.close:
                submitted_order = self.sell()
    
        def start(self):
            print('Backtesting is about to start')
    
        def stop(self):
            print('Backtesting is finished')
    
        def notify_order(self, order):
            print('An order new/changed/executed/canceled has been received')
    

    The start and stop methods should be self-explanatory. As expected and following the text in the print function, the notify_order method will be called when the strategy needs a notification. Use case:

     start和stop方法应该不用多解释了。正如预期的那样,在print函数后面,当策略需要通知的时候,将调用notify_order方法。用例:

        • A buy or sell is requested (as seen in next)

        • 一个买或者卖的请求,在next方法里面
        • buy/sell will return an order which is submitted to the broker. Keeping a reference to this submitted order is up to the caller.

        • 买入/卖出将返回一个提交给经纪人的订单。保持对这个提交订单的引用由调用者决定。
        • It can for example be used to ensure that no new orders are submitted if an order is still pending.

        • 例如,它可以用于确保在订单仍然挂起时不会提交新订单。
        • If the order is Accepted/Executed/Canceled/Changed the broker will notify the status change (and for example execution size) back to the strategy via the notify method

        • 如果订单被接受/执行/取消/更改,经济人将通过notify方法将状态变更(比如执行大小)告知策略

        The QuickStart guide has a complete and functional example of order management in the notify_order method.

      • 快速开始指南里面有notify_order方法的完整的、功能性的订单管理示例
      • More can be done with other Strategy classes:

      • 更多其他策略类
        • buy / sell / close

          Use the underlying broker and sizer to send the broker a buy/sell order

        • 使用基础经纪人和sizer向经纪人发送一个买入或卖出订单
        • The same could be done by manually creating an Order and passing it over to the broker. But the platform is about making it easy for those using it.

        • 通过手动创建订单并将其传递给经纪人,可以完成同样的操作。但这个平台为了让使用它的人更简单
        • close will get the current market position and close it immediately.

        • close将得到当前市场的位置和close当前的价格
        • getposition (or the property “position”)

          Returns the current market position

        • 返回市场的定位
        • setsizer/getsizer (or the property “sizer”)

          These allow setting/getting the underlying stake Sizer. The same logic can be checked against Sizers which provide different stakes for the same situation (fixed size, proportional to capital, exponential)

        • 这允许设置/获取底层的Sizer。同样的逻辑,可以针对不同的情况,设置不同的筹码。
        • There is plenty of literature but Van K. Tharp has excellent books on the subject.

        • 这方面的文献很多,但范·k·萨普有很多这方面的优秀著作。

        A Strategy is a Lines object and these support parameters, which are collected using the standard Python kwargs argument:

      • 策略是一个Lines对象和这些支持参数,使用标准Python kwargs参数收集:
      • class MyStrategy(bt.Strategy):
        
            params = (('period', 20),)
        
            def __init__(self):
        
                self.sma = btind.SimpleMovingAverage(self.data, period=self.params.period)
        
            ...
            ...
        

        Notice how the SimpleMovingAverage is no longer instantiated with a fixed value of 20, but rather with the parameter “period” which has been defined for the strategy.

      • 注意,SimpleMovingAverage不再使用固定值20实例化,而是使用为策略定义的参数“period”实例化。
      • A Cerebro

      • 大脑
      •  

        Once Data Feeds are available and the Strategy has been defined, a Cerebro instance is what brings everything together and execute the actions. Instantiating one is easy:

      • 一旦提供了数据feed并定义了策略,就可以使用一个Cerebro实例将所有内容组合在一起并执行操作。实例化一个很容易:
      • cerebro = bt.Cerebro()
        

        Defaults are taking care of if nothing special is wished.

      • 如果没什么特殊要求,默认的设置将被执行
        • A default broker is created

        • 一个默认的经济人被创建了
        • No commission for the operations

        • 交易没有任何佣金
        • Data Feeds will be preloaded

        • 数据传输被预装
        • The default execution mode will be runonce (batch operation) which is the faster

        • 默认的执行模式是runonce(批处理操作),速度更快
        • All indicators must support the runonce mode for full speed. The ones included in the platform do.

        • 所有指标必须支持runonce模式以实现全速运行。包括在平台中的那些。
        • Custom indicators do not need to implement the runonce functionality. Cerebro will simulate it, which means those non-runonce compatible indicators will run slower. But still most of the system will run in batch mode.

        • 自定义指标不需要实现runonce功能。Cerebro将模拟它,这意味着那些非运行一次兼容的指标将运行得更慢。但系统的大部分仍将以批处理模式运行。

        Since a Data feed is already available and a Strategy too (created earlier) the standard way to put it all together and get it up and running is:

      • 既然已经有了数据feed和策略(之前创建的),那么将它们组合在一起并启动和运行的标准方法是:
      • cerebro.adddata(data)
        cerebro.addstrategy(MyStrategy, period=25)
        cerebro.run()
        

        Notice the following:

        • The Data Feed “instance” is added

        • Data Feed实例被添加
        • The MyStrategy “class” is added along with parameters (kwargs) that will be passed to it.

        • 添加MyStrategy“类”以及将传递给它的参数(kwargs)。
        • The instantiation of MyStrategy will be done by cerebro in the background and any kwargs in “addstrategy” will be passed to it

        • MyStrategy的实例化将由cerebro在后台完成,“addstrategy”中的任何kwarg将被传递给它

        The user may add as many Strategies and Data Feeds as wished. How Strategies communicate with each other to achieve coordination (if wished be) is not enforced/restricted by the platform.

      • 用户可以添加任意多的策略和数据提要。策略之间如何沟通以实现协调(如果愿意的话)不受平台的执行/限制。
      • Of course a Cerebro offers additional possibilities:

      • 当然,Cerebro提供了更多的可能性:

        • Decide about preloading and operation mode:
          预装及操作方式的确定:

      • cerebro = bt.Cerebro(runonce=True, preload=True)
        

        There is a constraint here: runonce needs preloading (if not, a batch operation cannot be run) Of course preloading Data Feeds does not enforce runonce


      • 这里有一个约束:runonce需要预加载(如果不需要,就不能运行批处理操作)当然,预加载数据提要不会强制执行runonce
      • setbroker / getbroker (and the broker property)

        A custom broker can be set if wished. The actual broker instance can also be accesed

      • 如果愿意可以自己设置经纪人,还可以访问经纪人实例.
      • Plotting. In a regular case as easy as:

      • cerebro.run()
        cerebro.plot()
        

        plot takes some arguments for the customization

      • plot定制了一些参数
        • numfigs=1

          If the plot is too dense it may be broken down into several plots

        • 如果过于密集,可以分成多个块
        • plotter=None

          A customer plotter instance can be passed and cerebro will not instantiate a default one

        • 可以传递一个客户绘图仪实例,而cerebro不会实例化一个默认的实例
        • **kwargs - standard keyword arguments

          Which will get passed to the plotter.

        Please see the plotting section for more information.

      • 请参阅有关更多信息,绘制部分
      • Optimization of strategies.

      • 优化策略
      • As mentioned above, Cerebro gets a Strategy derived class (not an instance) and the keyword arguments that will be passed to it upon instantiation, which will happen when “run” is called.

      • 如上所述,Cerebro获得一个策略派生类(不是实例)和实例化时传递给它的关键字参数,实例化将在调用“run”时发生。
      • This is so to enable optimization. The same Strategy class will be instantiated as many times as needed with new parameters. If an instance had been passed to cerebro … this would not be possible

      • 这是为了实现优化。同一个策略类将根据需要用新参数实例化多次。如果一个实例被传递给cerebro…这将是不可能的。.

        Optimization is requested as follows:

      • 优化要求如下:
    cerebro.optstrategy(MyStrategy, period=xrange(10, 20))
    

    The method optstrategy has the same signature as addstrategy but does extra housekeeping to ensure optimization runs as expected. A strategy could be expecting a range as a normal parameter for a strategy and addstrategy will make no assumptions about the passed parameter.

    方法optstrategy具有与addstrategy相同的签名,但是进行了额外的内务处理以确保优化按预期运行。策略可以期望一个范围作为策略的常规参数,而addstrategy不会对传递的参数做任何假设。

    On the other hand, optstrategy will understand that an iterable is a set of values that has to be passed in sequence to each instantiation of the Strategy class.

    另一方面,optstrategy将理解可迭代是一组必须按顺序传递给Strategy类的每个实例化的值。

    Notice that instead of a single value a range of values is passed. In this simple case 10 values 10 -> 19 (20 is the upper limit) will be tried for this strategy.

    If a more complex strategy is developed with extra parameters they can all be passed to optstrategy.

    注意,传递的不是单个值,而是一系列的值。在这个简单的例子中,这个策略将尝试10个值10 -> 19(20是上限)。Parameters which must not undergo optimization can be passed directly without the end user having to create a dummy iterable of just one value. Example:

    不需要经过优化的参数可以直接传递,而终端用户不必创建一个只有一个值的伪迭代。例子:

    经过测试,多个range参数会形成笛卡尔积

    cerebro.optstrategy(MyStrategy, period=xrange(10, 20), factor=3.5)
    

    The optstrategy method sees factor and creates (a needed) dummy iterable in the background for factor which has a single element (in the example 3.5)

    optstrategy方法发现factor参数并在后台为factor创建(一个需要的)虚拟迭代,该factor只有一个元素(在示例3.5中)

    Note

    Interactive Python shells and some types of frozen executables under Windows have problems with the Python multiprocessing module

    交互式Python shell和Windows下的某些类型的可执行文件与Python的multiprocessing模块可能有问题

    Please read the Python documentation about multiprocessing.

    请阅读关于multiprocessing的Python文档。

  • 相关阅读:
    ActionMQ
    解决Session共享
    Linux中使用keepalived高可用工具解决宕机问题
    Linux安装Nginx
    Nginx基础
    多线程(1)
    单例模式1(3)
    创建型模式5种(2)
    7原则(1)
    反射使用案例(2)
  • 原文地址:https://www.cnblogs.com/sidianok/p/13453669.html
Copyright © 2011-2022 走看看