考虑到长度和主要变化,添加另一个答案。鉴于我正在编写一些代码,我用它回答了另一个问题,并且经过小的修改也可以用于投资组合。
代码:
from __future__ import (absolute_import, division, print_function,)
# unicode_literals)
import collections
import sys
if sys.version_info.major == 2:
import Queue as queue
import itertools
map = itertools.imap
else: # >= 3
import queue
import ib.opt
import ib.ext.Contract
class IbManager(object):
def __init__(self, timeout=20, **kwargs):
self.q = queue.Queue()
self.timeout = 20
self.con = ib.opt.ibConnection(**kwargs)
self.con.registerAll(self.watcher)
self.msgs = {
ib.opt.message.error: self.errors,
ib.opt.message.updatePortfolio: self.acct_update,
ib.opt.message.accountDownloadEnd: self.acct_update,
}
# Skip the registered ones plus noisy ones from acctUpdate
self.skipmsgs = tuple(self.msgs.keys()) + (
ib.opt.message.updateAccountValue,
ib.opt.message.updateAccountTime)
for msgtype, handler in self.msgs.items():
self.con.register(handler, msgtype)
self.con.connect()
def watcher(self, msg):
if isinstance(msg, ib.opt.message.error):
if msg.errorCode > 2000: # informative message
print('-' * 10, msg)
elif not isinstance(msg, self.skipmsgs):
print('-' * 10, msg)
def errors(self, msg):
if msg.id is None: # something is very wrong in the connection to tws
self.q.put((True, -1, 'Lost Connection to TWS'))
elif msg.errorCode < 1000:
self.q.put((True, msg.errorCode, msg.errorMsg))
def acct_update(self, msg):
self.q.put((False, -1, msg))
def get_account_update(self):
self.con.reqAccountUpdates(True, 'D999999')
portfolio = list()
while True:
try:
err, mid, msg = self.q.get(block=True, timeout=self.timeout)
except queue.Empty:
err, mid, msg = True, -1, "Timeout receiving information"
break
if isinstance(msg, ib.opt.message.accountDownloadEnd):
break
if isinstance(msg, ib.opt.message.updatePortfolio):
c = msg.contract
ticker = '%s-%s-%s' % (c.m_symbol, c.m_secType, c.m_exchange)
entry = collections.OrderedDict(msg.items())
# Don't do this if contract object needs to be referenced later
entry['contract'] = ticker # replace object with the ticker
portfolio.append(entry)
# return list of contract details, followed by:
# last return code (False means no error / True Error)
# last error code or None if no error
# last error message or None if no error
# last error message
return portfolio, err, mid, msg
ibm = IbManager(clientId=5001)
portfolio, err, errid, errmsg = ibm.get_account_update()
if portfolio:
print(','.join(portfolio[0].keys()))
for p in portfolio:
print(','.join(map(str, p.values())))
sys.exit(0) # Ensure ib thread is terminated
结果
Server Version: 76
TWS Time at connection:20160113 00:15:29 CET
---------- <managedAccounts accountsList=D999999>
---------- <nextValidId orderId=1>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfuture>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:eufarm>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:cashfarm>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfarm.us>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ushmds.us>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ilhmds>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:cashhmds>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ethmds>
contract,position,marketPrice,marketValue,averageCost,unrealizedPNL,realizedPNL,accountName
IBM-STK-,10,25.0,250.0,210.0,40.0,0.0,D999999
最后两行可以直接导入(例如)Excel。或者假设它是一个字典列表(打印出来的内容),它可以在脚本中进一步操作。