社区中的几个主题似乎以如何跟踪订单为导向,特别是当几个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()