Reputation: 23
I would like to get the price of a future that I actually bought. I am getting crazy trying to make it work. I would like to know too how to get PnL in real time. When I am trying to do that It takes almost 5 minutes to change the value. Here is some code I am using from over here, it does works but I am not able to get the execution details.
import time
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
import time
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_positions = pd.DataFrame([], columns=['Account', 'Symbol', 'Quantity', 'Average Cost', 'Sec Type'])
def error(self, reqId: TickerId, errorCode: int, errorString: str):
if reqId > -1:
print("Error. Id: ", reqId, " Code: ", errorCode, " Msg: ", errorString)
def position(self, account, contract, pos, avgCost):
index = str(account) + str(contract.symbol)
self.all_positions.loc[index] = account, contract.symbol, pos, avgCost, contract.secType
def positionEnd(self):
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 10)
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
import time
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_accounts = pd.DataFrame([], columns=['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 accountSummary(self, reqId, account, tag, value, currency):
#if tag == 'NetLiquidationByCurrency':
index = str(account)
self.all_accounts.loc[index] = reqId, account, tag, value, currency
def accountSummaryEnd(self, reqId: int):
self.disconnect()
def execDetails(self, reqId, contract, execution):
print('Order Executed: ', reqId, contract.symbol, contract.secType, contract.currency, execution.execId,
execution.orderId, execution.shares, execution.lastLiquidity)
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 10)
ib_api.reqAccountSummary(9001, "All", "$LEDGER")
current_nav = ib_api.all_accounts
ib_api.run()
return current_nav
while True: time.sleep(0.1); print(read_positions())
Upvotes: 1
Views: 2377
Reputation: 10979
I remembered the was a new function reqPnLSingle so I wrote this to test.
There is some weird data but the value seems right and it updates continuously.
I put comments in code to explain.
import ibapi
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import *
from ibapi.contract import *
import pandas as pd
import collections
import time
class TestApp(EClient, EWrapper):
accts = []
orderId = 0
posns = collections.defaultdict(list)
start = time.time()
def __init__(self):
EClient.__init__(self, self)
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if (reqId > -1):
# ignore many 2150 Invalid position trade derived value
if (errorCode == 2150): return
print("Error:", reqId, errorCode, errorString)
else :
print("Info: ", errorCode, errorString)
def managedAccounts(self, accountsList: str):
# the accounts are sent when a connection is made
# only needed to reqPosns for sub acct
self.accts = accountsList.split(",")# probably just 1
print("accts", self.accts)
def nextValidId(self, orderId:int):
# this is called when a connection is made
self.orderId = orderId
# to make sure the version is >= min 9.73.06, server > ~127?
print(ibapi.VERSION, self.serverVersion())
#use this as a signal to start making requests
self.reqPositions()
def position(self, account: str, contract: Contract, position: float, avgCost: float):
self.posns["account"].append(account)
self.posns["conId"].append(contract.conId)
self.posns["symbol"].append(contract.localSymbol)
self.posns["avgCost"].append(avgCost)
self.posns["posn"].append(position)
def positionEnd(self):
self.df = pd.DataFrame.from_dict(self.posns) #will make an automatic int index
if (self.df.empty):
self.disconnect()
return
# make req for each posn, use index for reqId
for index, row in self.df.iterrows():
self.reqPnLSingle(index, row.account, "", row.conId)
def pnlSingle(self, reqId: int, pos: int, dailyPnL: float, unrealizedPnL: float, realizedPnL: float, value: float):
row = self.df.iloc[reqId]
# all PnL's are maxint for me at night so I calc the right amount
print(row.symbol, "PnL", unrealizedPnL, "calc", value - row.avgCost * row.posn)
#just run for ~10 secs
if (time.time() - self.start > 10):
print(self.df)
self.disconnect()
def main():
app = TestApp()
app.connect("127.0.0.1", 7497, 123)
app.run()
if __name__ == "__main__":
main()
Upvotes: 1