实时数据/实时交易
原文: https://www.backtrader.com/blog/posts/2016-06-21-livedata-feed/live-data-feed/
从发布版本1.5.0开始,backtrader 支持实时数据馈送和实时交易。第一个综合实体是:
- 互动经纪人
自平台作为一个小想法诞生以来,这一直是人们追求的目标。设计思想已经证明足够灵活,可以适应所需的更改。同时保持相同的接口,即:回测一次,交易多次。相同的代码/api/原语/通知用于回溯测试和实时数据馈送/交易。
将平台命名为back
+trader
是有意为之,尽管很可能它仍然是一个纯粹的测试人员。但现在不是了。
新变化:
-
存储概念为互动经纪等实体提供一次过提供数据和经纪设施的集成概念
-
从存储和/或数据源向策略和/或大脑发送新通知
-
时间管理支持…因为人们可以在任何其他地方交易纽约 baed 产品,时间必须保持一致
-
重新采样/重放以尽快交付酒吧,如果市场不交易,则不会太迟(没有人希望在 30 秒后收到 5 秒重采样酒吧,因为没有中间滴答声)
-
当然,内部有很多小变化
集成过程中进行了大量测试,一个名为ibtest
的大型样本集成在源代码中,但在 1st版本中,仍然可能存在一些优势。如果您决定试一试,请对互动经纪人提供的纸面交易账户执行 1st(通常在7497
端口而不是7496
端口运行)
笔记
确保对与数据断开相关的固有风险、软件中存在的缺陷(TWS和backtrader)以及您自己的软件中的缺陷感到满意,并监控您的活动。
backtrader
不能对交易者可能遭受的任何损失承担任何责任或承担任何责任(它也不会接受任何赢款)
互动经纪人支持的内容:
-
指数(显然不用于交易)、股票、期货、期权、期货期权和外汇
-
在连接开始和重新连接后回填
-
从现场更改为回填和替代的通知 a
-
反向交易者:
Market
、Limit
、StopLimit
和Close
中已经存在的订单类型(也称为收盘市场*)
平台无意重新发明轮子,因此使用互动经纪设施需要/可选以下内容:
-
必需:
IbPy
与互动经纪人 TW接口IB的文档说明了如何安装它,如果它还不是您的武器库的一部分
-
可选:
pytz
自动设置产品的时区。最终用户可以直接向数据源提供其他与
tzinfo
兼容的实例(来自pytz
或家常菜),作为参数,而不依赖于自动确定。参见文件中的时间管理和文件中的IB具体部分。
!!! 笔记
If no `pytz` is detected and no `tzinfo` compatible instance is
supplied to the *data feed*, the time delivered by the platform will be
`UTC`
已尽可能多地记录在案,并可通过通常的文档链接获得:
从样本ibtest
到TWS 演示的几次运行
第一个:TWTR
重采样至 5 秒:
$ ./ibtest.py --port 7497 --data0 TWTR --resample --timeframe Seconds --compression 5
输出:
Server Version: 76
TWS Time at connection:20160620 22:37:37 CET
--------------------------------------------------
Strategy Created
--------------------------------------------------
Timezone from ContractDetails: EST5EDT
Datetime, Open, High, Low, Close, Volume, OpenInterest, SMA
***** STORE NOTIF: <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:ibdemo>
***** STORE NOTIF: <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:demohmds>
***** DATA NOTIF: CONNECTED
0001, 2016-06-20T14:37:35.000000, 15.96, 15.97, 15.96, 15.96, 0.0, 0, nan
***** DATA NOTIF: DELAYED
0002, 2016-06-20T14:37:40.000000, 15.96, 15.97, 15.96, 15.96, 0.0, 0, nan
0003, 2016-06-20T14:37:45.000000, 15.96, 15.97, 15.96, 15.97, 0.0, 0, nan
0004, 2016-06-20T14:37:50.000000, 15.96, 15.98, 15.94, 15.94, 0.0, 0, nan
0005, 2016-06-20T14:37:55.000000, 15.97, 15.97, 15.96, 15.97, 0.0, 0, 15.96
...
1441, 2016-06-20T16:37:35.000000, 16.03, 16.03, 16.02, 16.03, 0.0, 0, 16.026
1442, 2016-06-20T16:37:40.000000, 16.11, 16.11, 16.11, 16.11, 2.0, 0, 16.044
***** DATA NOTIF: LIVE
1443, 2016-06-20T16:37:45.000000, 16.1, 16.11, 16.1, 16.11, 5.0, 0, 16.06
1444, 2016-06-20T16:37:50.000000, 16.11, 16.11, 16.1, 16.1, 14.0, 0, 16.076
...
笔记
已安装执行环境pytz
可以观察到以下情况:
-
1st行(来自
IbPy
本身)显示与服务器的连接已成功,数据馈送已找到资产的工作时区:EST5EDT
(又名EST
又名US/Eastern
)请注意TWS在开始时如何报告本地时间(时区
CET
又称Europe/Berlin
,但资产延迟了6
小时。在交易地点的时间报告资产。如果你真的想改变这一点以及这种行为的原因,请查看文档。
-
来自存储的一些通知,在本例中TWS表示到不同数据场的连接正常。这是通过策略中覆盖的方法打印出来的
-
数据通知类
-
CONNECTED
:告知TWS的策略连接可用 -
DELAYED
:接收的数据不是实时数据。正在进行回填(历史数据)。由于重采样参数为秒/5秒,因此在单个请求中下载的最大 5 秒棒拟合数约为 1440。
-
LIVE
:一旦平台赶上回填,队列减少为实时数据,通知会告知策略。从棒 1443 开始,数据为实时数据。
笔记
因为正在进行重采样,所以该数据不是勾号数据,而是在 5 秒周期结束时发送的。请检查
IBData
中qcheck
参数 docs 的文档,了解如果平台没有发送新的勾号,重采样条延迟的速度有多快(因为没有新的勾号,平台无法理解当前重采样条是否已经结束)
-
让我们执行相同的操作,但强制断开连接(网络接口被禁用 20 秒):
$ ./ibtest.py --port 7497 --data0 TWTR --resample --timeframe Seconds --compression 5
输出(跳过初始已知零件):
...
1440, 2016-06-20T18:16:20.000000, 16.05, 16.05, 16.04, 16.04, 0.0, 0, 16.048
1441, 2016-06-20T18:16:25.000000, 16.05, 16.05, 16.05, 16.05, 0.0, 0, 16.05
***** DATA NOTIF: LIVE
1442, 2016-06-20T18:16:30.000000, 15.9, 15.9, 15.89, 15.9, 11.0, 0, 16.02
***** STORE NOTIF: <error id=-1, errorCode=1100, errorMsg=Connectivity between IB and TWS has been lost.>
***** STORE NOTIF: <error id=-1, errorCode=2105, errorMsg=HMDS data farm connection is broken:demohmds>
***** STORE NOTIF: <error id=-1, errorCode=2103, errorMsg=Market data farm connection is broken:ibdemo>
1443, 2016-06-20T18:16:35.000000, 15.9, 15.9, 15.89, 15.9, 28.0, 0, 15.988
***** STORE NOTIF: <error id=-1, errorCode=1102, errorMsg=Connectivity between IB and TWS has been restored - data maintained.>
***** STORE NOTIF: <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:demohmds>
***** STORE NOTIF: <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:ibdemo>
***** DATA NOTIF: DELAYED
1444, 2016-06-20T18:16:40.000000, 16.04, 16.04, 16.03, 16.04, 0.0, 0, 15.986
1445, 2016-06-20T18:16:45.000000, 16.03, 16.04, 16.03, 16.04, 0.0, 0, 15.986
1446, 2016-06-20T18:16:50.000000, 16.04, 16.04, 16.03, 16.03, 0.0, 0, 15.982
1447, 2016-06-20T18:16:55.000000, 16.04, 16.04, 16.03, 16.04, 0.0, 0, 16.01
1448, 2016-06-20T18:17:00.000000, 16.03, 16.04, 16.03, 16.04, 0.0, 0, 16.038
1449, 2016-06-20T18:17:05.000000, 16.03, 16.04, 16.02, 16.03, 0.0, 0, 16.036
1450, 2016-06-20T18:17:10.000000, 15.9, 15.91, 15.9, 15.91, 3.0, 0, 16.01
***** DATA NOTIF: LIVE
1451, 2016-06-20T18:17:15.000000, 15.92, 15.92, 15.9, 15.92, 9.0, 0, 15.988
1452, 2016-06-20T18:17:20.000000, 15.91, 15.91, 15.89, 15.89, 18.0, 0, 15.958
1453, 2016-06-20T18:17:25.000000, 15.89, 15.92, 15.89, 15.89, 24.0, 0, 15.928
...
叙述:
-
在 bar 1442 之后,WLAN 接口已被禁用
-
TWS 通知到达,指示情况
-
由于平台在
18:16:30.000000
和18:16:35.000000
之间有一些滴答声,所以棒 1443 是从重采样器发出的 -
连接在
18:17:15
左右恢复,但此数据不会立即发送 -
已识别情况,并尝试在
18:16:35
和18:17:15
之间进行回填。这可以通过通知
DELAYED
看到。数据不再是LIVE
-
1444 至 1450 条(包括这两条)提供了缺失的时间
-
接收到通知
LIVE
,bar 1451 包含一个实时数据包
笔记
有些情况是backtrader
无法克服的,因为TWS不符合要求。如果 TCP/IP 数据包以某种方式丢失,并且IB服务器反应缓慢,则TWS需要很长时间才能做出反应并通知连接丢失。
TWS甚至会以当前时间戳(通过突然的数据包突发来识别)发送明显延迟从服务器接收的数据包
最后是一些交易,用一个Market
订单购买TWTR
的20K股,然后以两个10K的订单出售。
执行:
./ibtest.py --port 7497 --data0 TWTR --resample --timeframe Seconds --compression 5 --broker --trade --stake 20000
输出相当详细,显示了订单执行的所有部分。总结一下:
...
***** DATA NOTIF: LIVE
1442, 2016-06-20T18:28:05.000000, 15.92, 15.93, 15.92, 15.93, 1748.0, 0, 16.03
-------------------------------------------------- ORDER BEGIN 2016-06-20 23:28:11.343000
Ref: 1
OrdType: 0
OrdType: Buy
Status: 1
Status: Submitted
Size: 20000
Price: 14.34
Price Limit: None
ExecType: 0
ExecType: Market
CommInfo: <backtrader.brokers.ibbroker.IBCommInfo object at 0x00000000040B9278>
End of Session: 736136.166655
Info: AutoOrderedDict()
Broker: <backtrader.brokers.ibbroker.IBBroker object at 0x0000000003E23470>
Alive: True
Ref: 1
orderId: 1
Action: BUY
Size (ib): 20000
Lmt Price: 0.0
Aux Price: 0.0
OrderType: MKT
Tif (Time in Force): GTC
GoodTillDate:
-------------------------------------------------- ORDER END
...
1443, 2016-06-20T18:28:10.000000, 15.93, 15.93, 15.92, 15.92, 10.0, 0, 16.004
-------------------------------------------------- ORDER BEGIN 2016-06-20 23:28:15.924000
Ref: 1
OrdType: 0
OrdType: Buy
Status: 3
Status: Partial
Size: 20000
Price: 14.34
Price Limit: None
ExecType: 0
ExecType: Market
CommInfo: <backtrader.brokers.ibbroker.IBCommInfo object at 0x00000000040B9278>
End of Session: 736136.166655
Info: AutoOrderedDict()
Broker: <backtrader.brokers.ibbroker.IBBroker object at 0x0000000003E23470>
Alive: True
Ref: 1
orderId: 1
Action: BUY
Size (ib): 20000
Lmt Price: 0.0
Aux Price: 0.0
OrderType: MKT
Tif (Time in Force): GTC
GoodTillDate:
-------------------------------------------------- ORDER END
...
-------------------------------------------------- ORDER BEGIN 2016-06-20 23:28:20.972000
Ref: 1
OrdType: 0
OrdType: Buy
Status: 4
Status: Completed
Size: 20000
Price: 14.34
Price Limit: None
ExecType: 0
ExecType: Market
CommInfo: <backtrader.brokers.ibbroker.IBCommInfo object at 0x00000000040B9278>
End of Session: 736136.166655
Info: AutoOrderedDict()
Broker: <backtrader.brokers.ibbroker.IBBroker object at 0x0000000003E23470>
Alive: False
Ref: 1
orderId: 1
Action: BUY
Size (ib): 20000
Lmt Price: 0.0
Aux Price: 0.0
OrderType: MKT
Tif (Time in Force): GTC
GoodTillDate:
-------------------------------------------------- ORDER END
1445, 2016-06-20T18:28:20.000000, 15.92, 15.93, 15.92, 15.93, 21.0, 0, 15.954
...
发生以下情况:
-
数据正常接收
-
针对执行类型为
Market
的20K
发出BUY
-
收到
Submitted
和Accepted
通知(以上仅显示Submitted
) -
连续执行
Partial
次(仅显示 1 次),直到收到Completed
。
未显示实际执行情况,但在
order.executed
下接收的order
实例中可用 -
-
虽然未显示,但会发出 2 个
Market``SELL
命令来撤消该操作屏幕截图显示了TWS在一个晚上两次不同的跑步后的日志
该样品可以做更多的工作,旨在对设施进行彻底测试,如果可能的话,可以发现任何粗糙的边缘。
用法:
$ ./ibtest.py --help
usage: ibtest.py [-h] [--exactbars EXACTBARS] [--plot] [--stopafter STOPAFTER]
[--usestore] [--notifyall] [--debug] [--host HOST]
[--qcheck QCHECK] [--port PORT] [--clientId CLIENTID]
[--no-timeoffset] [--reconnect RECONNECT] [--timeout TIMEOUT]
--data0 DATA0 [--data1 DATA1] [--timezone TIMEZONE]
[--what WHAT] [--no-backfill_start] [--latethrough]
[--no-backfill] [--rtbar] [--historical]
[--fromdate FROMDATE] [--smaperiod SMAPERIOD]
[--replay | --resample]
[--timeframe {Ticks,MicroSeconds,Seconds,Minutes,Days,Weeks,Months,Years}]
[--compression COMPRESSION] [--no-takelate] [--no-bar2edge]
[--no-adjbartime] [--no-rightedge] [--broker] [--trade]
[--donotsell]
[--exectype {Market,Close,Limit,Stop,StopLimit}]
[--stake STAKE] [--valid VALID] [--cancel CANCEL]
Test Interactive Brokers integration
optional arguments:
-h, --help show this help message and exit
--exactbars EXACTBARS
exactbars level, use 0/-1/-2 to enable plotting
(default: 1)
--plot Plot if possible (default: False)
--stopafter STOPAFTER
Stop after x lines of LIVE data (default: 0)
--usestore Use the store pattern (default: False)
--notifyall Notify all messages to strategy as store notifs
(default: False)
--debug Display all info received form IB (default: False)
--host HOST Host for the Interactive Brokers TWS Connection
(default: 127.0.0.1)
--qcheck QCHECK Timeout for periodic notification/resampling/replaying
check (default: 0.5)
--port PORT Port for the Interactive Brokers TWS Connection
(default: 7496)
--clientId CLIENTID Client Id to connect to TWS (default: random)
(default: None)
--no-timeoffset Do not Use TWS/System time offset for non timestamped
prices and to align resampling (default: False)
--reconnect RECONNECT
Number of recconnection attempts to TWS (default: 3)
--timeout TIMEOUT Timeout between reconnection attempts to TWS (default:
3.0)
--data0 DATA0 data 0 into the system (default: None)
--data1 DATA1 data 1 into the system (default: None)
--timezone TIMEZONE timezone to get time output into (pytz names)
(default: None)
--what WHAT specific price type for historical requests (default:
None)
--no-backfill_start Disable backfilling at the start (default: False)
--latethrough if resampling replaying, adjusting time and disabling
time offset, let late samples through (default: False)
--no-backfill Disable backfilling after a disconnection (default:
False)
--rtbar Use 5 seconds real time bar updates if possible
(default: False)
--historical do only historical download (default: False)
--fromdate FROMDATE Starting date for historical download with format:
YYYY-MM-DD[THH:MM:SS] (default: None)
--smaperiod SMAPERIOD
Period to apply to the Simple Moving Average (default:
5)
--replay replay to chosen timeframe (default: False)
--resample resample to chosen timeframe (default: False)
--timeframe {Ticks,MicroSeconds,Seconds,Minutes,Days,Weeks,Months,Years}
TimeFrame for Resample/Replay (default: Ticks)
--compression COMPRESSION
Compression for Resample/Replay (default: 1)
--no-takelate resample/replay, do not accept late samples in new bar
if the data source let them through (latethrough)
(default: False)
--no-bar2edge no bar2edge for resample/replay (default: False)
--no-adjbartime no adjbartime for resample/replay (default: False)
--no-rightedge no rightedge for resample/replay (default: False)
--broker Use IB as broker (default: False)
--trade Do Sample Buy/Sell operations (default: False)
--donotsell Do not sell after a buy (default: False)
--exectype {Market,Close,Limit,Stop,StopLimit}
Execution to Use when opening position (default:
Market)
--stake STAKE Stake to use in buy operations (default: 10)
--valid VALID Seconds to keep the order alive (0 means DAY)
(default: None)
--cancel CANCEL Cancel a buy order after n bars in operation, to be
combined with orders like Limit (default: 0)
守则:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import argparse
import datetime
# The above could be sent to an independent module
import backtrader as bt
from backtrader.utils import flushfile # win32 quick stdout flushing
class TestStrategy(bt.Strategy):
params = dict(
smaperiod=5,
trade=False,
stake=10,
exectype=bt.Order.Market,
stopafter=0,
valid=None,
cancel=0,
donotsell=False,
)
def __init__(self):
# To control operation entries
self.orderid = list()
self.order = None
self.counttostop = 0
self.datastatus = 0
# Create SMA on 2nd data
self.sma = bt.indicators.MovAv.SMA(self.data, period=self.p.smaperiod)
print('--------------------------------------------------')
print('Strategy Created')
print('--------------------------------------------------')
def notify_data(self, data, status, *args, **kwargs):
print('*' * 5, 'DATA NOTIF:', data._getstatusname(status), *args)
if status == data.LIVE:
self.counttostop = self.p.stopafter
self.datastatus = 1
def notify_store(self, msg, *args, **kwargs):
print('*' * 5, 'STORE NOTIF:', msg)
def notify_order(self, order):
if order.status in [order.Completed, order.Cancelled, order.Rejected]:
self.order = None
print('-' * 50, 'ORDER BEGIN', datetime.datetime.now())
print(order)
print('-' * 50, 'ORDER END')
def notify_trade(self, trade):
print('-' * 50, 'TRADE BEGIN', datetime.datetime.now())
print(trade)
print('-' * 50, 'TRADE END')
def prenext(self):
self.next(frompre=True)
def next(self, frompre=False):
txt = list()
txt.append('%04d' % len(self))
dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
txt.append('%s' % self.data.datetime.datetime(0).strftime(dtfmt))
txt.append('{}'.format(self.data.open[0]))
txt.append('{}'.format(self.data.high[0]))
txt.append('{}'.format(self.data.low[0]))
txt.append('{}'.format(self.data.close[0]))
txt.append('{}'.format(self.data.volume[0]))
txt.append('{}'.format(self.data.openinterest[0]))
txt.append('{}'.format(self.sma[0]))
print(', '.join(txt))
if len(self.datas) > 1:
txt = list()
txt.append('%04d' % len(self))
dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
txt.append('%s' % self.data1.datetime.datetime(0).strftime(dtfmt))
txt.append('{}'.format(self.data1.open[0]))
txt.append('{}'.format(self.data1.high[0]))
txt.append('{}'.format(self.data1.low[0]))
txt.append('{}'.format(self.data1.close[0]))
txt.append('{}'.format(self.data1.volume[0]))
txt.append('{}'.format(self.data1.openinterest[0]))
txt.append('{}'.format(float('NaN')))
print(', '.join(txt))
if self.counttostop: # stop after x live lines
self.counttostop -= 1
if not self.counttostop:
self.env.runstop()
return
if not self.p.trade:
return
if self.datastatus and not self.position and len(self.orderid) < 1:
self.order = self.buy(size=self.p.stake,
exectype=self.p.exectype,
price=round(self.data0.close[0] * 0.90, 2),
valid=self.p.valid)
self.orderid.append(self.order)
elif self.position.size > 0 and not self.p.donotsell:
if self.order is None:
self.order = self.sell(size=self.p.stake // 2,
exectype=bt.Order.Market,
price=self.data0.close[0])
elif self.order is not None and self.p.cancel:
if self.datastatus > self.p.cancel:
self.cancel(self.order)
if self.datastatus:
self.datastatus += 1
def start(self):
if self.data0.contractdetails is not None:
print('Timezone from ContractDetails: {}'.format(
self.data0.contractdetails.m_timeZoneId))
header = ['Datetime', 'Open', 'High', 'Low', 'Close', 'Volume',
'OpenInterest', 'SMA']
print(', '.join(header))
self.done = False
def runstrategy():
args = parse_args()
# Create a cerebro
cerebro = bt.Cerebro()
storekwargs = dict(
host=args.host, port=args.port,
clientId=args.clientId, timeoffset=not args.no_timeoffset,
reconnect=args.reconnect, timeout=args.timeout,
notifyall=args.notifyall, _debug=args.debug
)
if args.usestore:
ibstore = bt.stores.IBStore(**storekwargs)
if args.broker:
if args.usestore:
broker = ibstore.getbroker()
else:
broker = bt.brokers.IBBroker(**storekwargs)
cerebro.setbroker(broker)
timeframe = bt.TimeFrame.TFrame(args.timeframe)
if args.resample or args.replay:
datatf = bt.TimeFrame.Ticks
datacomp = 1
else:
datatf = timeframe
datacomp = args.compression
fromdate = None
if args.fromdate:
dtformat = '%Y-%m-%d' + ('T%H:%M:%S' * ('T' in args.fromdate))
fromdate = datetime.datetime.strptime(args.fromdate, dtformat)
IBDataFactory = ibstore.getdata if args.usestore else bt.feeds.IBData
datakwargs = dict(
timeframe=datatf, compression=datacomp,
historical=args.historical, fromdate=fromdate,
rtbar=args.rtbar,
qcheck=args.qcheck,
what=args.what,
backfill_start=not args.no_backfill_start,
backfill=not args.no_backfill,
latethrough=args.latethrough,
tz=args.timezone
)
if not args.usestore and not args.broker: # neither store nor broker
datakwargs.update(storekwargs) # pass the store args over the data
data0 = IBDataFactory(dataname=args.data0, **datakwargs)
data1 = None
if args.data1 is not None:
data1 = IBDataFactory(dataname=args.data1, **datakwargs)
rekwargs = dict(
timeframe=timeframe, compression=args.compression,
bar2edge=not args.no_bar2edge,
adjbartime=not args.no_adjbartime,
rightedge=not args.no_rightedge,
takelate=not args.no_takelate,
)
if args.replay:
cerebro.replaydata(dataname=data0, **rekwargs)
if data1 is not None:
cerebro.replaydata(dataname=data1, **rekwargs)
elif args.resample:
cerebro.resampledata(dataname=data0, **rekwargs)
if data1 is not None:
cerebro.resampledata(dataname=data1, **rekwargs)
else:
cerebro.adddata(data0)
if data1 is not None:
cerebro.adddata(data1)
if args.valid is None:
valid = None
else:
datetime.timedelta(seconds=args.valid)
# Add the strategy
cerebro.addstrategy(TestStrategy,
smaperiod=args.smaperiod,
trade=args.trade,
exectype=bt.Order.ExecType(args.exectype),
stake=args.stake,
stopafter=args.stopafter,
valid=valid,
cancel=args.cancel,
donotsell=args.donotsell)
# Live data ... avoid long data accumulation by switching to "exactbars"
cerebro.run(exactbars=args.exactbars)
if args.plot and args.exactbars < 1: # plot if possible
cerebro.plot()
def parse_args():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description='Test Interactive Brokers integration')
parser.add_argument('--exactbars', default=1, type=int,
required=False, action='store',
help='exactbars level, use 0/-1/-2 to enable plotting')
parser.add_argument('--plot',
required=False, action='store_true',
help='Plot if possible')
parser.add_argument('--stopafter', default=0, type=int,
required=False, action='store',
help='Stop after x lines of LIVE data')
parser.add_argument('--usestore',
required=False, action='store_true',
help='Use the store pattern')
parser.add_argument('--notifyall',
required=False, action='store_true',
help='Notify all messages to strategy as store notifs')
parser.add_argument('--debug',
required=False, action='store_true',
help='Display all info received form IB')
parser.add_argument('--host', default='127.0.0.1',
required=False, action='store',
help='Host for the Interactive Brokers TWS Connection')
parser.add_argument('--qcheck', default=0.5, type=float,
required=False, action='store',
help=('Timeout for periodic '
'notification/resampling/replaying check'))
parser.add_argument('--port', default=7496, type=int,
required=False, action='store',
help='Port for the Interactive Brokers TWS Connection')
parser.add_argument('--clientId', default=None, type=int,
required=False, action='store',
help='Client Id to connect to TWS (default: random)')
parser.add_argument('--no-timeoffset',
required=False, action='store_true',
help=('Do not Use TWS/System time offset for non '
'timestamped prices and to align resampling'))
parser.add_argument('--reconnect', default=3, type=int,
required=False, action='store',
help='Number of recconnection attempts to TWS')
parser.add_argument('--timeout', default=3.0, type=float,
required=False, action='store',
help='Timeout between reconnection attempts to TWS')
parser.add_argument('--data0', default=None,
required=True, action='store',
help='data 0 into the system')
parser.add_argument('--data1', default=None,
required=False, action='store',
help='data 1 into the system')
parser.add_argument('--timezone', default=None,
required=False, action='store',
help='timezone to get time output into (pytz names)')
parser.add_argument('--what', default=None,
required=False, action='store',
help='specific price type for historical requests')
parser.add_argument('--no-backfill_start',
required=False, action='store_true',
help='Disable backfilling at the start')
parser.add_argument('--latethrough',
required=False, action='store_true',
help=('if resampling replaying, adjusting time '
'and disabling time offset, let late samples '
'through'))
parser.add_argument('--no-backfill',
required=False, action='store_true',
help='Disable backfilling after a disconnection')
parser.add_argument('--rtbar', default=False,
required=False, action='store_true',
help='Use 5 seconds real time bar updates if possible')
parser.add_argument('--historical',
required=False, action='store_true',
help='do only historical download')
parser.add_argument('--fromdate',
required=False, action='store',
help=('Starting date for historical download '
'with format: YYYY-MM-DD[THH:MM:SS]'))
parser.add_argument('--smaperiod', default=5, type=int,
required=False, action='store',
help='Period to apply to the Simple Moving Average')
pgroup = parser.add_mutually_exclusive_group(required=False)
pgroup.add_argument('--replay',
required=False, action='store_true',
help='replay to chosen timeframe')
pgroup.add_argument('--resample',
required=False, action='store_true',
help='resample to chosen timeframe')
parser.add_argument('--timeframe', default=bt.TimeFrame.Names[0],
choices=bt.TimeFrame.Names,
required=False, action='store',
help='TimeFrame for Resample/Replay')
parser.add_argument('--compression', default=1, type=int,
required=False, action='store',
help='Compression for Resample/Replay')
parser.add_argument('--no-takelate',
required=False, action='store_true',
help=('resample/replay, do not accept late samples '
'in new bar if the data source let them through '
'(latethrough)'))
parser.add_argument('--no-bar2edge',
required=False, action='store_true',
help='no bar2edge for resample/replay')
parser.add_argument('--no-adjbartime',
required=False, action='store_true',
help='no adjbartime for resample/replay')
parser.add_argument('--no-rightedge',
required=False, action='store_true',
help='no rightedge for resample/replay')
parser.add_argument('--broker',
required=False, action='store_true',
help='Use IB as broker')
parser.add_argument('--trade',
required=False, action='store_true',
help='Do Sample Buy/Sell operations')
parser.add_argument('--donotsell',
required=False, action='store_true',
help='Do not sell after a buy')
parser.add_argument('--exectype', default=bt.Order.ExecTypes[0],
choices=bt.Order.ExecTypes,
required=False, action='store',
help='Execution to Use when opening position')
parser.add_argument('--stake', default=10, type=int,
required=False, action='store',
help='Stake to use in buy operations')
parser.add_argument('--valid', default=None, type=int,
required=False, action='store',
help='Seconds to keep the order alive (0 means DAY)')
parser.add_argument('--cancel', default=0, type=int,
required=False, action='store',
help=('Cancel a buy order after n bars in operation,'
' to be combined with orders like Limit'))
return parser.parse_args()
if __name__ == '__main__':
runstrategy()