Backtrader 教程:佣金計劃 - 擴展

  |  

佣金和相關功能由單個類CommissionInfo管理,該類主要通過調用broker.setcommission進行實例化。

該概念僅限於具有保證金和每份合約固定佣金的期貨以及具有基於價格/規模百分比的佣金的股票。不是最靈活的計劃,即使它已經達到了目的。

GitHub #29上的增強請求導致了一些返工,以便:

  • 保持CommissionInfobroker.setcommission與原始行為兼容

  • 對代碼進行一些清理

  • 使委員會計劃靈活,以支持增強請求和進一步的可能性

拿到樣品前的實際工作

class CommInfoBase(with_metaclass(MetaParams)):
    COMM_PERC, COMM_FIXED = range(2)

    params = (
        ('commission', 0.0), ('mult', 1.0), ('margin', None),
        ('commtype', None),
        ('stocklike', False),
        ('percabs', False),
    )

引入了CommissionInfo的基類,它向組合中添加了新參數:

  • commtype (默認值: None

    這是兼容性的關鍵。如果值為None ,則CommissionInfo對象和broker.setcommission的行為將像以前一樣工作。就是這樣:

    • 如果設置了margin ,那麼佣金計劃適用於每份合約固定佣金的期貨

    • 如果未設置margin ,佣金計劃適用於基於百分比方法的股票

    如果值為COMM_PERCCOMM_FIXED (或任何其他派生類),這顯然決定了佣金是固定的還是基於百分比的

  • stocklike (默認值: False

    如上所述,舊的CommissionInfo對像中的實際行為由參數margin確定

    如上所述,如果commtype設置為None以外的其他值,則此值指示該資產是否為類似期貨的資產(將使用保證金並執行基於條形的現金調整 9 或者這是類似股票的資產

  • percabs (默認值: False

    如果為False ,則百分比必須以相對形式傳遞 (xx%)

    如果為True ,則百分比必須作為絕對值 (0.xx) 傳遞

    CommissionInfoCommInfoBase的子類,將此參數的默認值更改為True以保持兼容的行為

所有這些參數也可以在broker.setcommission中使用,現在看起來像這樣:

def setcommission(self,
                  commission=0.0, margin=None, mult=1.0,
                  commtype=None, percabs=True, stocklike=False,
                  name=None):

請注意以下事項:

  • percabsTrue以保持與上面提到的CommissionInfo對象的舊調用兼容的行為

測試commissions-schemes的舊樣本已經過重新設計,以支持命令參數和新行為。使用幫助:

$ ./commission-schemes.py --help
usage: commission-schemes.py [-h] [--data DATA] [--fromdate FROMDATE]
                             [--todate TODATE] [--stake STAKE]
                             [--period PERIOD] [--cash CASH] [--comm COMM]
                             [--mult MULT] [--margin MARGIN]
                             [--commtype {none,perc,fixed}] [--stocklike]
                             [--percrel] [--plot] [--numfigs NUMFIGS]

Commission schemes

optional arguments:
  -h, --help            show this help message and exit
  --data DATA, -d DATA  data to add to the system (default:
                        ../../datas/2006-day-001.txt)
  --fromdate FROMDATE, -f FROMDATE
                        Starting date in YYYY-MM-DD format (default:
                        2006-01-01)
  --todate TODATE, -t TODATE
                        Starting date in YYYY-MM-DD format (default:
                        2006-12-31)
  --stake STAKE         Stake to apply in each operation (default: 1)
  --period PERIOD       Period to apply to the Simple Moving Average (default:
                        30)
  --cash CASH           Starting Cash (default: 10000.0)
  --comm COMM           Commission factor for operation, either apercentage or
                        a per stake unit absolute value (default: 2.0)
  --mult MULT           Multiplier for operations calculation (default: 10)
  --margin MARGIN       Margin for futures-like operations (default: 2000.0)
  --commtype {none,perc,fixed}
                        Commission - choose none for the old CommissionInfo
                        behavior (default: none)
  --stocklike           If the operation is for stock-like assets orfuture-
                        like assets (default: False)
  --percrel             If perc is expressed in relative xx{'const': True,
                        'help': u'If perc is expressed in relative xx%
                        ratherthan absolute value 0.xx', 'option_strings': [u'
                        --percrel'], 'dest': u'percrel', 'required': False,
                        'nargs': 0, 'choices': None, 'default': False, 'prog':
                        'commission-schemes.py', 'container':
                        <argparse._ArgumentGroup object at
                        0x0000000007EC9828>, 'type': None, 'metavar':
                        None}atherthan absolute value 0.xx (default: False)
  --plot, -p            Plot the read data (default: False)
  --numfigs NUMFIGS, -n NUMFIGS
                        Plot using numfigs figures (default: 1)

讓我們運行一些程序來重新創建原始佣金計劃帖子的原始行為。

期貨佣金(固定和有保證金)

執行和圖表:

$ ./commission-schemes.py --comm 2.0 --margin 2000.0 --mult 10 --plot

輸出顯示固定佣金為 2.0 個貨幣單位(默認賭注為 1):

2006-03-09, BUY CREATE, 3757.59
2006-03-10, BUY EXECUTED, Price: 3754.13, Cost: 2000.00, Comm 2.00
2006-04-11, SELL CREATE, 3788.81
2006-04-12, SELL EXECUTED, Price: 3786.93, Cost: 2000.00, Comm 2.00
2006-04-12, TRADE PROFIT, GROSS 328.00, NET 324.00
...

股票佣金(perc 和無保證金)

執行和圖表:

$ ./commission-schemes.py --comm 0.005 --margin 0 --mult 1 --plot

為了提高可讀性,可以使用相對百分比值:

$ ./commission-schemes.py --percrel --comm 0.5 --margin 0 --mult 1 --plot

現在0.5直接表示0.5%

作為兩種情況下的輸出:

2006-03-09, BUY CREATE, 3757.59
2006-03-10, BUY EXECUTED, Price: 3754.13, Cost: 3754.13, Comm 18.77
2006-04-11, SELL CREATE, 3788.81
2006-04-12, SELL EXECUTED, Price: 3786.93, Cost: 3754.13, Comm 18.93
2006-04-12, TRADE PROFIT, GROSS 32.80, NET -4.91
...

期貨佣金(perc 和保證金)

使用新參數,基於 perc 的方案的期貨:

$ ./commission-schemes.py --commtype perc --percrel --comm 0.5 --margin 2000 --mult 10 --plot

毫不奇怪,通過改變委員會......最終結果已經改變

輸出顯示佣金現在是可變的:

2006-03-09, BUY CREATE, 3757.59
2006-03-10, BUY EXECUTED, Price: 3754.13, Cost: 2000.00, Comm 18.77
2006-04-11, SELL CREATE, 3788.81
2006-04-12, SELL EXECUTED, Price: 3786.93, Cost: 2000.00, Comm 18.93
2006-04-12, TRADE PROFIT, GROSS 328.00, NET 290.29
...

在上一次運行中設置 2.0 貨幣單位(默認賭注為 1)

另一篇文章將詳細介紹新課程和男士熟食佣金計劃的實施。

示例代碼

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

import argparse
import datetime

import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind


class SMACrossOver(bt.Strategy):
    params = (
        ('stake', 1),
        ('period', 30),
    )

    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 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 enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

    def notify_trade(self, trade):
        if trade.isclosed:
            self.log('TRADE PROFIT, GROSS %.2f, NET %.2f' %
                     (trade.pnl, trade.pnlcomm))

    def __init__(self):
        sma = btind.SMA(self.data, period=self.p.period)
        # > 0 crossing up / < 0 crossing down
        self.buysell_sig = btind.CrossOver(self.data, sma)

    def next(self):
        if self.buysell_sig > 0:
            self.log('BUY CREATE, %.2f' % self.data.close[0])
            self.buy(size=self.p.stake)  # keep order ref to avoid 2nd orders

        elif self.position and self.buysell_sig < 0:
            self.log('SELL CREATE, %.2f' % self.data.close[0])
            self.sell(size=self.p.stake)


def runstrategy():
    args = parse_args()

    # Create a cerebro
    cerebro = bt.Cerebro()

    # Get the dates from the args
    fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
    todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')

    # Create the 1st data
    data = btfeeds.BacktraderCSVData(
        dataname=args.data,
        fromdate=fromdate,
        todate=todate)

    # Add the 1st data to cerebro
    cerebro.adddata(data)

    # Add a strategy
    cerebro.addstrategy(SMACrossOver, period=args.period, stake=args.stake)

    # Add the commission - only stocks like a for each operation
    cerebro.broker.setcash(args.cash)

    commtypes = dict(
        none=None,
        perc=bt.CommInfoBase.COMM_PERC,
        fixed=bt.CommInfoBase.COMM_FIXED)

    # Add the commission - only stocks like a for each operation
    cerebro.broker.setcommission(commission=args.comm,
                                 mult=args.mult,
                                 margin=args.margin,
                                 percabs=not args.percrel,
                                 commtype=commtypes[args.commtype],
                                 stocklike=args.stocklike)

    # And run it
    cerebro.run()

    # Plot if requested
    if args.plot:
        cerebro.plot(numfigs=args.numfigs, volume=False)


def parse_args():
    parser = argparse.ArgumentParser(
        description='Commission schemes',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,)

    parser.add_argument('--data', '-d',
                        default='../../datas/2006-day-001.txt',
                        help='data to add to the system')

    parser.add_argument('--fromdate', '-f',
                        default='2006-01-01',
                        help='Starting date in YYYY-MM-DD format')

    parser.add_argument('--todate', '-t',
                        default='2006-12-31',
                        help='Starting date in YYYY-MM-DD format')

    parser.add_argument('--stake', default=1, type=int,
                        help='Stake to apply in each operation')

    parser.add_argument('--period', default=30, type=int,
                        help='Period to apply to the Simple Moving Average')

    parser.add_argument('--cash', default=10000.0, type=float,
                        help='Starting Cash')

    parser.add_argument('--comm', default=2.0, type=float,
                        help=('Commission factor for operation, either a'
                              'percentage or a per stake unit absolute value'))

    parser.add_argument('--mult', default=10, type=int,
                        help='Multiplier for operations calculation')

    parser.add_argument('--margin', default=2000.0, type=float,
                        help='Margin for futures-like operations')

    parser.add_argument('--commtype', required=False, default='none',
                        choices=['none', 'perc', 'fixed'],
                        help=('Commission - choose none for the old'
                              ' CommissionInfo behavior'))

    parser.add_argument('--stocklike', required=False, action='store_true',
                        help=('If the operation is for stock-like assets or'
                              'future-like assets'))

    parser.add_argument('--percrel', required=False, action='store_true',
                        help=('If perc is expressed in relative xx% rather'
                              'than absolute value 0.xx'))

    parser.add_argument('--plot', '-p', action='store_true',
                        help='Plot the read data')

    parser.add_argument('--numfigs', '-n', default=1,
                        help='Plot using numfigs figures')

    return parser.parse_args()


if __name__ == '__main__':
    runstrategy()

推薦閱讀

相關文章

Backtrader做空現金

從一開始,反向交易者就可以做空任何東西,包括類似股票和類似期貨的工具。當做空時,現金減少,被賣空資產的價值用於總淨清算價值。從一側移除並添加到另一側可以保持平衡。人們似乎更喜歡增加現金,這可能會增加支出。在1.9.7.105版本中,經紀人已將默認行為更改為添加現金和移除價值。

Backtrader教程:經紀人 - 體積灌裝 - 灌裝機

backtrader經紀商類比在使用volume執行訂單時具有預設策略: 忽略 volume 這是基於2個前提: 在市場中交易的流動性足以一次性完全吸收買入/賣出訂單 真正的 volume 匹配需要真正的狼 一個簡單的例子是Fill or Kill 訂單。

Backtrader觀察員和統計

在 backtrader 內部運行的策略主要處理數據 和 指標。 數據被添加到Cerebro 實例中,並最終成為策略輸入的一部分(解析並用作實例的屬性),而指標由策略本身聲明和管理。

Backtrader股票篩選

在尋找其他一些東西時,我在StackOverlow家族網站之一上遇到了一個問題:Quantitative Finance aka Quant StackExchange。問題: 它被標記為Python,因此值得一看的是 backtrader 是否能夠勝任這項任務。 分析儀本身 該問題似乎適合用於簡單的分析器。

Backtrader策略選擇

最初的策略選擇方法使用兩個策略,手動註冊和一個簡單的[0, 1]列表來決定哪個是策略的目標。因為 Python 為元類提供了許多自省的可能性,所以實際上可以自動化該方法。

Backtrader交叉回溯測試陷阱

在backtrader 社區中 ,傾向於重複的事情是,用戶解釋了複製在例如 TradingView 中獲得的回溯測試結果的意願,這些天非常流行,或者其他一些回溯測試平臺。

Backtrader 教程:交易

交易的定義:當工具中的頭寸從 0 變為大小 X 時,交易打開,對於多頭/空頭頭寸可能為正/負)當頭寸從 X 變為 0 時,交易平倉。以下兩個動作:正轉負負轉正實際上被視為:一筆交易已關閉(倉位從 X 變為 0)新交易已開立(倉位從 0 變為 Y)交易只是提供信息,沒有用戶可調用的方法。

Backtrader遞歸指標

backtrader的最初目標之一是:能夠快速製作指標原型以測試新想法它不一定是一個完美的指標,但能夠快速輕鬆地開發它們確實會有所幫助。為了確認設計是正確的,反向交易者標準庫中的第一個指標是指數移動平均線(又名 EMA),其定義為:遞歸。

Backtrader版本 1.2.1.88

將次要版本號從 1 更改為 2 需要一段時間,但舊的 DataResampler 和 DataReplayer 的棄用導致了這種情況。 readthedocs 的文件有 文件已更新為僅引用現代方法 resampling 和 replaying。

Backtrader 教程:數據饋送 - 開發 - 常規

筆記示例goog.fd中使用的二進製文件屬於 VisualChart,不能與backtrader一起分發。對直接使用二進製文件感興趣的人可以免費下載VisualChart 。 CSV數據饋送開發已經展示瞭如何添加新的基於 CSV 的數據饋送。