社区中的几个主题似乎以如何跟踪订单为导向,特别是当几个data feeds在起作用时,还包括当多个订单一起工作时,例如在括号订单的情况下
下面的文稿尝试通过允许用户以下操作来充当示例:
-
使用 3 个 data feeds
-
使用
- 当下单买入订单类型
Marketusebracket=False
或
- 支架顺序集 (
usebracket=True
在这种情况下,可以指定如何创建括号集
-
在以下情况下发出 3 个订单(1 个父级 + 2 个子项)
rawbracket=True -
拨打何时
buy_bracketrawbracket=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()