社區中的幾個主題似乎以如何跟蹤訂單為導向,特別是當幾個data feeds在起作用時,還包括當多個訂單一起工作時,例如在括號訂單的情況下
下面的文稿嘗試透過允許使用者以下操作來充當示例:
-
使用 3 個 data feeds
-
使用
- 當下單買入訂單類型
Market
usebracket=False
或
- 支架順序集 (
usebracket=True
在這種情況下,可以指定如何創建括號集
-
在以下情況下發出 3 個訂單(1 個父級 + 2 個子項)
rawbracket=True
-
撥打何時
buy_bracket
rawbracket=False
主括號訂單在幾天後
valid
有一個到期日(預設值為10
) - 當下單買入訂單類型
-
當與為每個data feed定義的值匹配
enter
時,weekday
將輸入(或至少嘗試輸入)一個位置,該值預設為[1, 3, 4]
-
將退出 open 倉位
- 在一段時間後有一個
holding
常規close
。週期是為每個data feeds單獨定義的,其參數hold
預設為[7, 10, 15]
這將觸發取消任何括號訂單的
stop
一側(如果存在)(這將自動取消另一側)- 或者,如果使用括弧,當
stop
(限價虧損)或limit
(止盈)一方被執行時(系統將自動取消另一方)
- 在一段時間後有一個
-
訂單保留在
-
dict
它使用 作為data
鍵 -
包含
list
每個data
條目,其中包含每個條目 open 的訂單data
一旦下達了訂單,管理就完成了
notify_order
-
此外:
-
使用 A
TestSizer
,它將返回不同的值buy
和sell
訂單作為測試由於僅啟動長操作,因此將僅
buy
返回大小調整,並且輸出日誌將不包含大小調整的sell
痕跡。
創建了大量的操作,頭寸和訂單管理日誌,以幫助瞭解正在發生的事情。
讓我們看一個預設值為usebracket=True
and rawbracket=True
的範例執行(為了簡化繪圖,將刪除 volume ):
$ ./mult-values.py --plot volume=False 2001-01-02 d0 Position 0 2001-01-02 Data d0 OType buy Sizing to 1 2001-01-02 d0 Main 1 Stp 2 Lmt 3 2001-01-02 d1 Position 0 2001-01-02 d2 Position 0 2001-01-03 d0 Order 1 Status Accepted 2001-01-03 d0 Order 2 Status Accepted 2001-01-03 d0 Order 3 Status Accepted 2001-01-03 d0 Order 1 Status Completed -- No longer alive main Ref 2001-01-03 d0 Position 1 2001-01-03 d1 Position 0 2001-01-03 d2 Position 0 2001-01-04 d0 Order 3 Status Completed -- No longer alive limit Ref 2001-01-04 d0 Order 2 Status Canceled -- No longer alive stop Ref ... ... ... 2006-12-27 d0 Order 2036 Status Accepted 2006-12-27 d0 Order 2037 Status Accepted 2006-12-27 d0 Order 2038 Status Accepted 2006-12-27 d0 Position 0 2006-12-27 d1 Position 0 2006-12-27 d2 Position 0 2006-12-28 d0 Position 0 2006-12-28 d1 Position 0 2006-12-28 d2 Position 0 2006-12-29 d0 Position 0 2006-12-29 d1 Position 0 2006-12-29 d2 Position 0
第 2個 執行集 rawbracket=False
$ ./mult-values.py --plot volume=False --strat rawbracket=False
它輸出完全相同的結果,這次已經使用了buy_bracket
。
最後禁用括弧用法:
./mult-values.py --strat usebracket=False --plot volume=False
結論
這應該作為訂單管理的一個很好的例子,具有多個 data feeds 和訂單集。
示例用法
$ ./mult-values.py --help usage: mult-values.py [-h] [--data0 DATA0] [--data1 DATA1] [--data2 DATA2] [--fromdate FROMDATE] [--todate TODATE] [--cerebro kwargs] [--broker kwargs] [--sizer kwargs] [--strat kwargs] [--plot [kwargs]] Multiple Values and Brackets optional arguments: -h, --help show this help message and exit --data0 DATA0 Data0 to read in (default: ../../datas/nvda-1999-2014.txt) --data1 DATA1 Data1 to read in (default: ../../datas/yhoo-1996-2014.txt) --data2 DATA2 Data1 to read in (default: ../../datas/orcl-1995-2014.txt) --fromdate FROMDATE Date[time] in YYYY-MM-DD[THH:MM:SS] format (default: 2001-01-01) --todate TODATE Date[time] in YYYY-MM-DD[THH:MM:SS] format (default: 2007-01-01) --cerebro kwargs kwargs in key=value format (default: ) --broker kwargs kwargs in key=value format (default: ) --sizer kwargs kwargs in key=value format (default: ) --strat kwargs kwargs in key=value format (default: ) --plot [kwargs] kwargs in key=value format (default: )
示例代碼
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import datetime import backtrader as bt class TestSizer(bt.Sizer): params = dict(stake=1) def _getsizing(self, comminfo, cash, data, isbuy): dt, i = self.strategy.datetime.date(), data._id s = self.p.stake * (1 + (not isbuy)) print('{} Data {} OType {} Sizing to {}'.format( dt, data._name, ('buy' * isbuy) or 'sell', s)) return s class St(bt.Strategy): params = dict( enter=[1, 3, 4], # data ids are 1 based hold=[7, 10, 15], # data ids are 1 based usebracket=True, rawbracket=True, pentry=0.015, plimits=0.03, valid=10, ) def notify_order(self, order): if order.status == order.Submitted: return dt, dn = self.datetime.date(), order.data._name print('{} {} Order {} Status {}'.format( dt, dn, order.ref, order.getstatusname()) ) whichord = ['main', 'stop', 'limit', 'close'] if not order.alive(): # not alive - nullify dorders = self.o[order.data] idx = dorders.index(order) dorders[idx] = None print('-- No longer alive {} Ref'.format(whichord[idx])) if all(x is None for x in dorders): dorders[:] = [] # empty list - New orders allowed def __init__(self): self.o = dict() # orders per data (main, stop, limit, manual-close) self.holding = dict() # holding periods per data def next(self): for i, d in enumerate(self.datas): dt, dn = self.datetime.date(), d._name pos = self.getposition(d).size print('{} {} Position {}'.format(dt, dn, pos)) if not pos and not self.o.get(d, None): # no market / no orders if dt.weekday() == self.p.enter[i]: if not self.p.usebracket: self.o[d] = [self.buy(data=d)] print('{} {} Buy {}'.format(dt, dn, self.o[d][0].ref)) else: p = d.close[0] * (1.0 - self.p.pentry) pstp = p * (1.0 - self.p.plimits) plmt = p * (1.0 + self.p.plimits) valid = datetime.timedelta(self.p.valid) if self.p.rawbracket: o1 = self.buy(data=d, exectype=bt.Order.Limit, price=p, valid=valid, transmit=False) o2 = self.sell(data=d, exectype=bt.Order.Stop, price=pstp, size=o1.size, transmit=False, parent=o1) o3 = self.sell(data=d, exectype=bt.Order.Limit, price=plmt, size=o1.size, transmit=True, parent=o1) self.o[d] = [o1, o2, o3] else: self.o[d] = self.buy_bracket( data=d, price=p, stopprice=pstp, limitprice=plmt, oargs=dict(valid=valid)) print('{} {} Main {} Stp {} Lmt {}'.format( dt, dn, *(x.ref for x in self.o[d]))) self.holding[d] = 0 elif pos: # exiting can also happen after a number of days self.holding[d] += 1 if self.holding[d] >= self.p.hold[i]: o = self.close(data=d) self.o[d].append(o) # manual order to list of orders print('{} {} Manual Close {}'.format(dt, dn, o.ref)) if self.p.usebracket: self.cancel(self.o[d][1]) # cancel stop side print('{} {} Cancel {}'.format(dt, dn, self.o[d][1])) def runstrat(args=None): args = parse_args(args) cerebro = bt.Cerebro() # Data feed kwargs kwargs = dict() # Parse from/to-date dtfmt, tmfmt = '%Y-%m-%d', 'T%H:%M:%S' for a, d in ((getattr(args, x), x) for x in ['fromdate', 'todate']): if a: strpfmt = dtfmt + tmfmt * ('T' in a) kwargs[d] = datetime.datetime.strptime(a, strpfmt) # Data feed data0 = bt.feeds.YahooFinanceCSVData(dataname=args.data0, **kwargs) cerebro.adddata(data0, name='d0') data1 = bt.feeds.YahooFinanceCSVData(dataname=args.data1, **kwargs) data1.plotinfo.plotmaster = data0 cerebro.adddata(data1, name='d1') data2 = bt.feeds.YahooFinanceCSVData(dataname=args.data2, **kwargs) data2.plotinfo.plotmaster = data0 cerebro.adddata(data2, name='d2') # Broker cerebro.broker = bt.brokers.BackBroker(**eval('dict(' + args.broker + ')')) cerebro.broker.setcommission(commission=0.001) # Sizer # cerebro.addsizer(bt.sizers.FixedSize, **eval('dict(' + args.sizer + ')')) cerebro.addsizer(TestSizer, **eval('dict(' + args.sizer + ')')) # Strategy cerebro.addstrategy(St, **eval('dict(' + args.strat + ')')) # Execute cerebro.run(**eval('dict(' + args.cerebro + ')')) if args.plot: # Plot if requested to cerebro.plot(**eval('dict(' + args.plot + ')')) def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description=( 'Multiple Values and Brackets' ) ) parser.add_argument('--data0', default='../../datas/nvda-1999-2014.txt', required=False, help='Data0 to read in') parser.add_argument('--data1', default='../../datas/yhoo-1996-2014.txt', required=False, help='Data1 to read in') parser.add_argument('--data2', default='../../datas/orcl-1995-2014.txt', required=False, help='Data1 to read in') # Defaults for dates parser.add_argument('--fromdate', required=False, default='2001-01-01', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--todate', required=False, default='2007-01-01', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--cerebro', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--broker', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--sizer', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--strat', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--plot', required=False, default='', nargs='?', const='{}', metavar='kwargs', help='kwargs in key=value format') return parser.parse_args(pargs) if __name__ == '__main__': runstrat()