stoqey / ib

Interactive Brokers TWS/IB Gateway API client library for Node.js (TS)
https://stoqey.github.io/ib-doc/
MIT License
212 stars 48 forks source link

Properly disconnecting from IB Gateway #221

Open kfiroo opened 3 months ago

kfiroo commented 3 months ago

Hey! First of all, thanks for all the effort! it is much appreciated ❤️

I am working with the new IBApiNext and I am wondering on what is the best way to disconnect a client.

I am connecting using a random clientId and doing my best to call disconnect when my work is done but in my IB Gateway app I see that the API Client is still connected.

This didn't happen to me when I used the python module ib_insync and I am wondering if there is something that I am doing wrong or is it the expected behavior?

Sample code:

const clientId = getRandonId()

const apiNext = new IBApiNext({
  port: configuration.IB_PORT,
})

// Subject for connected - I guess this is not really needed as you do it internally right?
const connected$ = apiNext.connectionState.pipe(
  filter((state) => state === ConnectionState.Connected),
  first(),
)

try {
  apiNext.connect(clientId)

  await firstValueFrom(connected$)

  await doSomethingWithIBApi(apiNext)
} catch (error) {
  logger.error(error)
  throw error
} finally {
  // not this this actually disconnects me :(
  apiNext.disconnect()
}

Thanks in advance 🙏🏼

rylorin commented 1 week ago

Hello,

I tested your code fragment with:

import { filter, first, firstValueFrom } from "rxjs";
import { ConnectionState, IBApiNext } from "..";

const getRandonId = () => 12;

const sleep = (secs: number) => new Promise((r) => setTimeout(r, secs * 1000));

const doSomethingWithIBApi = async (..._args) => {
  await sleep(10);
};

async function main() {
  const clientId = getRandonId();

  const apiNext = new IBApiNext();

  // Subject for connected - I guess this is not really needed as you do it internally right?
  const connected$ = apiNext.connectionState.pipe(
    filter((state) => state === ConnectionState.Connected),
    first(),
  );

  try {
    apiNext.connect(clientId);

    await firstValueFrom(connected$);
    console.log("connected");

    await doSomethingWithIBApi(apiNext);
  } catch (error) {
    console.error(error);
    throw error;
  } finally {
    // not this this actually disconnects me :(
    apiNext.disconnect();
    console.log("disconnected");
    await sleep(10);
  }
}

main();

I connect, then disconnect after 10 secs, and I've been able to seen that the client properly disconnected from the API. Your issue is maybe related to some other problem.