gofinance / ib

Pure Go interface to Interactive Brokers IB API
386 stars 120 forks source link

Noob question: No streaming data for instrument manager #39

Closed LuSaxy closed 4 years ago

LuSaxy commented 4 years ago

Hi,

I am trying to get a price stream of a contract, so any time the price changes i want it to be captures. i have trued: `

    engine,_:=ib.NewEngine(ib.EngineOptions{})
    rc := make(chan ib.Reply)

    mgr,_:=ib.NewInstrumentManager(engine, ib.Contract{
        Symbol:       "USD",
        SecurityType: "CASH",
        Exchange:     "IDEALPRO",
        Currency:     "ZAR",
    })
    s:=ib.RequestMarketDataType{
        MarketDataType: 1,
    }

    engine.Send(&s)
    engine.SubscribeAll(rc)

    for {
        select {
        case r := <-rc:
            //log.Printf("%s - RECEIVE %v",  reflect.TypeOf(r))
            fmt.Println(r)
            fmt.Println(mgr.Ask())
        }
    }

I get the values only once: &{100 1 18.53616 2000000 true} 18.54108 &{100 2 18.54108 1000000 true} 18.54108 2020/04/15 09:39:54 Waited 5 seconds for reply channel 0xc0000546c0 2020/04/15 09:39:59 Waited 5 seconds for reply channel 0xc0000546c0 2020/04/15 09:40:04 Waited 5 seconds for reply channel 0xc0000546c0

but then afterwards i just get waited 5 seconds.

Please help

Thanks Gareth

a8d7e8 commented 4 years ago

See if https://github.com/nothize/ib/issues/1 is related.

dsouzae commented 4 years ago

Hello Gareth,

Not sure if you have resolved this issue yet, hopefully the following is helpful.

The InstrumentManager is not documented how it works. I am not sure of the history of it, but it looks to be used for testing the code. It is used to get one result based on test code.

My guess is the channel inside mgr is no longer reading the reply channel.

manager.go has a full documentation about how managers are supposed to work. Depending on your goal, you might need to implement your own manager.

Or you can start will the following code (hopefully it works, my environment is not setup market data):

func main() {
    options := ib.EngineOptions{}
    engine, err := ib.NewEngine(options)
    if err != nil {
        log.Fatal(err)
    }

    rc := make(chan ib.Reply)

    req := &ib.RequestMarketData{}
    req.Contract = ib.Contract{
        Symbol:       "USD",
        SecurityType: "CASH",
        Exchange:     "IDEALPRO",
        Currency:     "ZAR"}

    req.SetID(engine.NextRequestID())

    engine.Send(req)

    for {
        select {
        case r := <-rc:
            fmt.Println(r)
            switch r.(type) {
            case *ib.TickPrice:
                tick := r.(*ib.TickPrice)
                switch tick.Type {
                case ib.TickLast:
                    fmt.Printf("%v: Last %v", tick.ID(), tick.Price)
                case ib.TickBid:
                    fmt.Printf("%v: Bid %v", tick.ID(), tick.Price)
                case ib.TickAsk:
                    fmt.Printf("%v: Ask %v", tick.ID(), tick.Price)
                }
            }
        }
    }
}
LuSaxy commented 4 years ago

Thank you so much for getting back to me. I ended up solving the issue.

the code opens up 2 responses from the IB workstation. 1 when on the engine. and then another when i created the instrument manager (which i thought would have gone to the engine one). then in my select case statement i was only doing the drain for the engine channel that is created and never drained the instrument manager channel <- if that makes sense :)

so in my code above if i add notify:=mgr.Refresh() and then just listen for notify:

 engine,_:=ib.NewEngine(ib.EngineOptions{})
rc := make(chan ib.Reply)

mgr,_:=ib.NewInstrumentManager(engine, ib.Contract{
    Symbol:       "USD",
    SecurityType: "CASH",
    Exchange:     "IDEALPRO",
    Currency:     "ZAR",
})
s:=ib.RequestMarketDataType{
    MarketDataType: 1,
}

    notify:=mgr.Refresh()
engine.Send(&s)
engine.SubscribeAll(rc)

for {
    select {
       case <-notify:
                fmt.Println(mgr.Ask())   
    case r := <-rc:
        //whatever you want to do with engine responses

    }
}
dsouzae commented 4 years ago

Your code with Refresh looks to be the correct solution over mine.