ibpy获取投资组合信息:交互式代理、Python

2024-09-30 01:32:01 发布

您现在位置: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')

但是,它将信息转储为:

^{pr2}$

我想知道如何将上述信息存储到一个数组中,其中包含合同或股票代码的列、投资组合中的数量和购买价格的列


Tags: 代码register信息portcreateupdatemsgconnection
3条回答

如果列表中的每个条目都是一个列表本身(并且子列表中的每个索引位置总是包含同一个字段),那么“列”要求在某种程度上是模糊的

您收到的消息将发送到您在tws注册的回调。每个“转储”字段都可以用“点”表示法或通过dict类似的方法(如“keys”、“values”和“items”)访问

主要的挑战是合约:IB提供了大量交易所和不同交易资产的通道。“contract”对象(以及IB后端的信息)似乎反映了一种对所有事物提供统一/统一访问的努力,同时也表明它们必须建立在现有基础设施之上。在

你提到“股票行情”,所以我想你可能会喜欢这样的东西:IBM-STK-SMART带有“ib”行业标准符号(第二个字段表示它是股票,第三个字段表示ib将使用智能路由来更新订单和价格)

我们来看看列表:

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方法的类中,可以执行以下操作:

^{pr2}$

如果您不想通过索引访问列表中的字段,而是更喜欢ibpy已经提供的字段的名称,那么还可以对dict进行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())

您可以存储“items”而不是值,然后根据需要访问元组。在

除了使用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)

它们是您更新的账户价值和投资组合摘要:

^{pr2}$

更新您的职位:

# 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))

在篇幅和主要变化的情况下增加另一个答案。考虑到我正在编写一段代码,我用它回答了另一个问题,稍作修改也可以用于投资组合。在

代码:

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

结果

^{pr2}$

最后2行可以直接导入(例如)Excel。或者,如果它是一个字典列表(打印出来的内容),它可以在脚本中进一步操作。在

相关问题 更多 >

    热门问题