![](/img/trans.png)
[英]Getting portfolio names and existing orders using Interactive Brokers IBPy
[英]ibpy Getting portfolio information: Interactive Broker, Python
我已经成功编写了代码,使用代码从TWS演示版中提取有关我的职位的信息:
tws_conn = conn.Connection.create(port=7497, clientId=100)
tws_conn.register( acct_update, msg.updateAccountValue,
msg.updateAccountTime, msg.updatePortfolio)
tws_conn.connect()
tws_conn.reqPositions()
tws_conn.reqAccountUpdates(True,'DU15181')
但是,它将信息转储为:
<updatePortfolio contract=<Packages.IbPy.ib.ext.Contract.Contract object at 0x06B0FE30>, position=-10, marketPrice=3.4000001, marketValue=-3400.0, averageCost=334.345, unrealizedPNL=-56.55, realizedPNL=0.0, accountName=DU15181>
我想知道如何将上述信息存储到一个数组中,该数组中包含合同或股票行情记录,投资组合中的数量和购买价格的不同列
给定长度和主要更改,添加另一个答案。 鉴于我正在编写某些代码,因此我用它回答了另一个问题,并且稍作改动也可以用于产品组合。
码:
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。 或者给定字典列表(要打印的内容),可以在脚本中对其进行进一步操作。
如果列表中的每个条目都是列表本身(并且子列表中的每个索引位置始终包含相同的字段),则鉴于列表已经满足该要求,因此“列”的要求有些模糊
您收到的消息将发送到您在tws中注册的回调。 每个“转储”字段都可以使用“点”符号或类似dict的方法(例如“键”,“值”和“项目”)进行访问
主要挑战是合同:IB允许访问大量交易所和不同的交易资产。 “合同”对象(以及IB后端中的信息)似乎反映了对所有内容的统一/统一访问的努力,同时表明他们必须在现有基础架构上构建。
您提到“股票行情自动收录器”,所以我想您可能会对以下内容感到满意:具有“ ib”行业标准符号的IBM-STK-SMART(第2字段表示是股票,第3字段表示IB将使用SMART路由用于订单和价格更新)
让我们去看一个列表列表:
def acct_update(self, msg):
# Assume the function is a method in a class with access to a member
# 'portfolio' which is a list
if isinstance(msg, ib.opt.message.updatePortfolio):
c = msg.contract
ticker = '%s-%s-%s' % (contract.m_symbol, c.m_secType, c.m_exchange)
entry = [ticker]
entry.extend(msg.values)
self.portfolio.append(entry)
不幸的是, ibpy
消息中的“ keys”方法不是classmethod
,但是名称实际上是__slots__
。 在持有acct_update
方法的类中,您可以执行以下操作:
class MyClass(object):
portfields = ['ticker'] + ib.opt.message.updatePortfolio.__slots__
如果您更喜欢ibpy已经提供的字段名称,而不是按索引访问列表中的字段,则还可以对dict
def __init__(self, ...)
self.portfolio = collections.OrderedDict()
def acct_update(self, msg):
# Assume the function is a method in a class with access to a member
# 'portfolio' which is a list
if isinstance(msg, ib.opt.message.updatePortfolio):
c = msg.contract
ticker = '%s-%s-%s' % (contract.m_symbol, c.m_secType, c.m_exchange)
self.portfolio[ticker] = collections.OrderedDict(msg.items())
这样您就可以按名称获取最新的股票行情资讯,并按名称访问字段。
如果您需要保留每个股票行情记录
def __init__(self, ...)
self.portfolio = collections.defaultdict(list)
def acct_update(self, msg):
# Assume the function is a method in a class with access to a member
# 'portfolio' which is a list
if isinstance(msg, ib.opt.message.updatePortfolio):
c = msg.contract
ticker = '%s-%s-%s' % (contract.m_symbol, c.m_secType, c.m_exchange)
self.portfolio[ticker].extend(msg.values())
您可以存储“项目”而不是值,然后在需要时访问元组。
除了使用ibpy,我还将导入IBWrapper,可以从Github下载该文件: https : //github.com/anthonyng2/ib
import pandas as pd
import numpy as np
import time
from IBWrapper import IBWrapper, contract
from ib.ext.EClientSocket import EClientSocket
accountName = "Your Account ID"
callback = IBWrapper() # Instantiate IBWrapper. callback
tws = EClientSocket(callback) # Instantiate EClientSocket and return data to callback
host = ""
port = 4002 # It is for default port no. in demo account
clientId = 25
tws.eConnect(host, port, clientId) # connect to TWS
create = contract() # Instantiate contract class
callback.initiate_variables()
tws.reqAccountUpdates(1, accountName)
time.sleep(2)
它们是您更新后的帐户价值和投资组合摘要:
accvalue = pd.DataFrame(callback.update_AccountValue, columns = ['key', 'value', 'currency', 'accountName']) #[:199]
portfolio = pd.DataFrame(callback.update_Portfolio, columns=['Contract ID','Currency', 'Expiry','Include Expired','Local Symbol','Multiplier','Primary Exchange','Right',
'Security Type','Strike','Symbol','Trading Class','Position','Market Price','Market Value',
'Average Cost', 'Unrealised PnL', 'Realised PnL', 'Account Name'])
callback.update_AccountTime
print("AccountValue: \n" + str(accvalue))
print("portfolio: \n" + str(portfolio))
这是您更新的职位摘要:
# Position Summary
tws.reqPositions()
time.sleep(2)
dat = pd.DataFrame(callback.update_Position,
columns=['Account','Contract ID','Currency','Exchange','Expiry',
'Include Expired','Local Symbol','Multiplier','Right',
'Security Type','Strike','Symbol','Trading Class',
'Position','Average Cost'])
dat[dat["Account"] == accountName]
print("Position Summary: \n" + str(dat))
我编写了以下代码,使我可以直接从Interactive Brokers API中读取头寸和资产净值。
# Interactive Brokers functions to import data
def read_positions(): #read all accounts positions and return DataFrame with information
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId
import pandas as pd
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_positions = pd.DataFrame([], columns = ['Account','Symbol', 'Quantity', 'Average Cost'])
def position(self, account, contract, pos, avgCost):
index = str(account)+str(contract.symbol)
self.all_positions.loc[index]=account,contract.symbol,pos,avgCost
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def positionEnd(self):
super().positionEnd()
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 0)
ib_api.reqPositions()
current_positions = ib_api.all_positions
ib_api.run()
return(current_positions)
def read_navs(): #read all accounts NAVs
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId
import pandas as pd
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_accounts = pd.DataFrame([], columns = ['reqId','Account', 'Tag', 'Value' , 'Currency'])
def accountSummary(self, reqId, account, tag, value, currency):
if tag == 'NetLiquidationByCurrency':
index = str(account)
self.all_accounts.loc[index]=reqId, account, tag, value, currency
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def accountSummaryEnd(self, reqId:int):
super().accountSummaryEnd(reqId)
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 0)
ib_api.reqAccountSummary(9001,"All","$LEDGER")
current_nav = ib_api.all_accounts
ib_api.run()
return(current_nav)
为了测试代码,我将其保存在名为IB_API的.py文件中,然后运行以下命令:
import IB_API
print("Testing IB's API as an imported library:")
all_positions = IB_API.read_positions()
all_navs = IB_API.read_navs()
print("Test ended")
我仍在尝试避免显示错误“ [WinError 10038]”,该错误为“试图对非套接字的对象进行操作”-请参阅关于此主题的问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.