Esempio n. 1
0
// NewTestFeedContext provides a simple way of producing a FeedContext for tests.
func NewTestFeedContext(t *testing.T) *TestFeedContext {
	c := core.NewTestConfig(t)

	ctx, err := core.NewContext(c)
	if err != nil {
		t.Fatal(err)
	}

	engine, err := ib.NewEngine(ib.NewEngineOptions{Gateway: c.IbGws[0]})
	if err != nil {
		t.Fatal(err)
	}

	fc := &FeedContext{
		Errors: make(chan FeedError),
		DB:     ctx.DB,
		N:      ctx.N,
		Eng:    engine,
	}

	return &TestFeedContext{
		ctx: ctx,
		FC:  fc,
	}
}
Esempio n. 2
0
func (g *GatewayService) initGatewayService() {
	go func() {
		feeds := []*Feed{}
		esl := make(chan ib.EngineState)
		var err error

		g.ctx.Eng, err = ib.NewEngine(ib.NewEngineOptions{Gateway: g.ibGw, Client: int64(g.ibClientId)})
		if err == nil {
			defer g.ctx.Eng.Stop()

			g.ctx.Eng.SubscribeState(esl)
			defer g.ctx.Eng.UnsubscribeState(esl)

			for _, ff := range g.ffs {
				feeds = append(feeds, ff.NewFeed(g.ctx))
			}
		} else {
			g.errors <- GatewayError{err, g.ibGw}
		}

		for {
			select {
			case <-g.terminated:
				return
			case <-g.exit:
				errsink := make(chan struct{})
				go func() {
					select {
					case <-errsink:
						return
					case <-g.ctx.Errors:
					}
				}()
				for _, feed := range feeds {
					(*feed).Close()
				}
				close(errsink)
				close(g.terminated)
			case feederr := <-g.ctx.Errors:
				g.errors <- GatewayError{feederr.Error, g.ibGw}
			case es := <-esl:
				if es != ib.EngineReady {
					// Engine should never report this state (in normal shutdown we've unsubscribed, so we would never receive this state change)
					err = g.ctx.Eng.FatalError()
					if err == nil {
						err = fmt.Errorf("%s without reporting fatal error", es.String())
					}
					g.errors <- GatewayError{err, g.ibGw}
				}
			}
		}
	}()
}
Esempio n. 3
0
func main() {

	// Output TWS messages to a separate file and use a split screen terminal to show them.
	if false {
		f, err := os.OpenFile("stockcli.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			log.Fatalf("LOG ERROR: %v", err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	log.SetFlags(log.Ltime | log.Lmicroseconds)

	// load configuration from
	config, cerr := LoadConfigFromFile("config.js")
	if cerr != nil {
		log.Fatalf("ERROR loading initial config %v", cerr)
		return
	}

	acct := make([]*IBManager, 0)
	for _, a := range config.Accounts {
		log.Printf("SETUP: %s %v", a.Label, a.Paper)
		acct = append(acct, &IBManager{
			label: a.Label,
			paper: a.Paper,
			opts: ib.EngineOptions{
				Gateway: a.Gateway,
				Client:  a.Client,
			},
			elog:        make(map[string]*ExecutionInfo),
			realtimeMap: make(map[int64]string),
		})
	}

	for _, ac := range acct {
		var err error
		ac.engine, err = ib.NewEngine(ac.opts)
		if err != nil {
			log.Fatalf("error creating %s Engine %v ", ac.label, err)
		}
		defer ac.engine.Stop()
		if ac.engine.State() != ib.EngineReady {
			log.Fatalf("%s engine is not ready", ac.label)
		}
		go engineLoop(ac)
	}

	time.Sleep(1 * time.Second)

	acctselect := ""
	prompt := "> "

	// Loop until Readline returns nil (signalling EOF)
	lastresult := ""
L:
	for {
		result := readline.Readline(&prompt)
		if result == nil {
			fmt.Println()
			continue
		}

		// prevent duplicate calls
		if *result == lastresult {
			continue
		}

		lastresult = *result
		strs := strings.Fields(strings.TrimSpace(*result))

		if len(strs) == 0 {
			continue
		}

		if *result != "" {
			readline.AddHistory(*result)
		}

		command := strs[0]

		switch {
		case command == "exit":
			break L // exit loop
		case command == "quit":
			break L // exit loop

		case command == "summary":
			lastresult = ""
			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				reqAs := &ib.RequestAccountSummary{}
				reqAs.SetID(ac.engine.NextRequestID())
				reqAs.Group = "All"
				reqAs.Tags = "BuyingPower,NetLiquidation,GrossPositionValue,TotalCashValue,SettledCash,InitMarginReq,MaintMarginReq,AvailableFunds,TotalCashValue,UnrealizedPnL"
				ac.engine.Send(reqAs)
				shownewline = true
				return nil
			})

		case command == "open":
			lastresult = ""
			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				ac.engine.Send(&ib.RequestOpenOrders{})
				shownewline = true
				return nil
			})

		case command == "positions":
			lastresult = ""
			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				req := &ib.RequestPositions{}
				ac.engine.Send(req)
				shownewline = true
				return nil
			})

		case command == "updates":
			lastresult = ""
			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				req := &ib.RequestAccountUpdates{}
				req.Subscribe = true
				ac.engine.Send(req)
				shownewline = true
				return nil
			})

		case command == "noupdates":
			lastresult = ""
			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				req := &ib.RequestAccountUpdates{}
				req.Subscribe = false
				ac.engine.Send(req)
				return nil
			})

		case command == "elog":
			lastresult = ""
			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				ac.elog = make(map[string]*ExecutionInfo)
				ereq := ib.RequestExecutions{}
				ereq.SetID(ac.engine.NextRequestID())
				ac.engine.Send(&ereq)
				shownewline = true
				return nil
			})

		case command == "select":
			lastresult = ""
			if len(strs) != 2 {
				fmt.Printf("select <label|all>\n")
				continue
			}
			if strs[1] == "all" {
				acctselect = ""
				prompt = "> "
			} else {
				for _, ac := range acct {
					if ac.label == strs[1] {
						acctselect = ac.label
						prompt = acctselect + " > "
						break
					}
				}
			}

		case command == "sell-t":
			if len(strs) != 4 {
				fmt.Printf("sell-t <symbol> <quantity> <trailamount>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			trailamount, _ := strconv.ParseFloat(strs[3], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doSellTrail(ac, strs[1], quantity, trailamount)
				shownewline = true
				return nil
			})

		case command == "sell-tl":
			if len(strs) != 6 {
				fmt.Printf("sell-tl <symbol> <quantity> <stopprice> <trailamount> <limitoffset>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			stopprice, _ := strconv.ParseFloat(strs[3], 64)
			trailamount, _ := strconv.ParseFloat(strs[4], 64)
			limitoffset, _ := strconv.ParseFloat(strs[5], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doSellTrailLimit(ac, strs[1], quantity, trailamount, stopprice, limitoffset)
				shownewline = true
				return nil
			})

		case command == "sell-l":
			if len(strs) != 4 {
				fmt.Printf("sell-l <symbol> <quantity> <limitprice>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			limitprice, _ := strconv.ParseFloat(strs[3], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doSell(ac, strs[1], quantity, false, limitprice)
				shownewline = true
				return nil
			})

		case command == "sell-m":
			if len(strs) != 3 {
				fmt.Printf("sell-m <symbol> <quantity>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doSell(ac, strs[1], quantity, true, 0)
				shownewline = true
				return nil
			})

		case command == "buy-t":
			if len(strs) != 4 {
				fmt.Printf("buy-t <symbol> <quantity> <trailamount>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			trailamount, _ := strconv.ParseFloat(strs[3], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBuyTrail(ac, strs[1], quantity, trailamount)
				shownewline = true
				return nil
			})

		case command == "buy-if":
			if len(strs) != 4 {
				fmt.Printf("buy-if <symbol> <quantity> <trailamount>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			trailamount, _ := strconv.ParseFloat(strs[3], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBuyTrailMarketIfTouched(ac, strs[1], quantity, trailamount)
				shownewline = true
				return nil
			})

		case command == "buy-tl":
			if len(strs) != 6 {
				fmt.Printf("buy-tl <symbol> <quantity> <stopprice> <trailamount> <limitoffset>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			stopprice, _ := strconv.ParseFloat(strs[3], 64)
			trailamount, _ := strconv.ParseFloat(strs[4], 64)
			limitoffset, _ := strconv.ParseFloat(strs[5], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBuyTrailLimit(ac, strs[1], quantity, trailamount, stopprice, limitoffset)
				shownewline = true
				return nil
			})

		case command == "buy-l":
			if len(strs) != 4 {
				fmt.Printf("buy-l <symbol> <quantity> <limitprice>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			limitprice, _ := strconv.ParseFloat(strs[3], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBuy(ac, strs[1], quantity, false, limitprice)
				shownewline = true
				return nil
			})

		case command == "buy-m":
			if len(strs) != 3 {
				fmt.Printf("buy-m <symbol> <quantity>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBuy(ac, strs[1], quantity, true, 0)
				shownewline = true
				return nil
			})

		case command == "bracket":
			if len(strs) != 6 {
				fmt.Printf("bracket <symbol> <quantity> <buyprice> <sellprice> <stopprice>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			buyprice, _ := strconv.ParseFloat(strs[3], 64)
			sellprice, _ := strconv.ParseFloat(strs[4], 64)
			stopprice, _ := strconv.ParseFloat(strs[5], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBracket(ac, strs[1], quantity, buyprice, sellprice, stopprice)
				shownewline = true
				return nil
			})

		case command == "brka":
			if len(strs) != 6 {
				fmt.Printf("brka <symbol> <quantity> <buyprice> <selloff> <stopoff>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			buyprice, _ := strconv.ParseFloat(strs[3], 64)
			sellprice, _ := strconv.ParseFloat(strs[4], 64)
			stopprice, _ := strconv.ParseFloat(strs[5], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBracket(ac, strs[1], quantity, buyprice, buyprice+sellprice, buyprice-stopprice)
				shownewline = true
				return nil
			})

		case command == "brkp1":
			if len(strs) != 4 {
				fmt.Printf("brkp1 <symbol> <quantity> <buyprice> {sell = buy + 0.20, stp = buy - 0.05} \n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			buyprice, _ := strconv.ParseFloat(strs[3], 64)
			sellprice := buyprice + 0.20
			stopprice := buyprice - 0.05

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBracket(ac, strs[1], quantity, buyprice, sellprice, stopprice)
				shownewline = true
				return nil
			})

		case command == "brkp2":
			if len(strs) != 4 {
				fmt.Printf("brkp2 <symbol> <quantity> <buyprice> {sell = buy + 0.11, stp = buy - 0.05} \n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			buyprice, _ := strconv.ParseFloat(strs[3], 64)
			sellprice := buyprice + 0.11
			stopprice := buyprice - 0.05

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doBracket(ac, strs[1], quantity, buyprice, sellprice, stopprice)
				shownewline = true
				return nil
			})

		case command == "stop-m":
			if len(strs) != 4 {
				fmt.Printf("stop-m <symbol> <quantity> <stopprice>\n")
				continue
			}

			quantity, _ := strconv.ParseUint(strs[2], 10, 64)
			stopprice, _ := strconv.ParseFloat(strs[3], 64)

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doStopMarket(ac, strs[1], quantity, stopprice)
				shownewline = true
				return nil
			})

		case command == "override":
			if len(strs) != 2 {
				fmt.Printf("override status %v\n", gUpdateOverride)
				continue
			}

			if strs[1] == "on" {
				gUpdateOverride = true
			} else {
				gUpdateOverride = false
			}
			fmt.Printf("override %v\n", gUpdateOverride)
		case command == "rth":
			if len(strs) != 2 {
				fmt.Printf("rth status %v\n", gEnableRTH)
				continue
			}

			if strs[1] == "on" {
				gEnableRTH = true
			} else {
				gEnableRTH = false
			}
			fmt.Printf("rth status %v\n", gEnableRTH)

		case command == "gtc":
			if len(strs) != 2 {
				fmt.Printf("gtc status %v\n", gEnableGTC)
				continue
			}

			if strs[1] == "on" {
				gEnableGTC = true
			} else {
				gEnableGTC = false
			}
			fmt.Printf("gtc status %v\n", gEnableGTC)

		case command == "acct-cancel":
			if len(strs) != 2 {
				fmt.Printf("acct-cancel status %v\n", gCancel)
				continue
			}

			if strs[1] == "on" {
				gCancel = true
			} else {
				gCancel = false
			}
			fmt.Printf("acct-cancel status %v\n", gCancel)

		case command == "realtimebar":
			if len(strs) != 2 {
				fmt.Printf("realtimebar <symbol>\n")
				continue
			}

			applyFunc(false, acctselect, acct, func(ac *IBManager) error {
				doRequestRealTimeBars(ac, strs[1])
				return nil
			})

		case command == "cancel":
			lastresult = ""
			if len(strs) != 2 {
				fmt.Printf("cancel <orderid>\n")
				continue
			}
			orderid := int64(0)
			if strs[1] != "all" {
				orderid, _ = strconv.ParseInt(strs[1], 10, 64)
			}

			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				if strs[1] == "all" {
					ac.engine.Send(&ib.RequestGlobalCancel{})
				} else {
					request := ib.CancelOrder{}
					request.SetID(orderid)
					ac.engine.Send(&request)
					shownewline = true
				}
				return nil
			})

		case command == "cancelall":
			lastresult = ""

			applyFunc(true, acctselect, acct, func(ac *IBManager) error {
				ac.engine.Send(&ib.RequestGlobalCancel{})
				shownewline = true
				return nil
			})

		case command != "": // Ignore blank lines
			fmt.Println(*result)
		}
	}
}
Esempio n. 4
0
func main() {
	//deal with os.Args
	checkArgErrors(os.Args[1], os.Args[2], os.Args[3], os.Args[4], os.Args[5])
	theAction := os.Args[1]
	theAcct := acctNametoNumber(os.Args[2])
	useLeverage := os.Args[3] == "l"
	argShares := os.Args[4]
	outsideRTH, err := strconv.ParseBool(os.Args[5])
	if os.Args[5] == "outside" {
		outsideRTH = true
	} else {
		outsideRTH = false
	}

	myEngine, err := ib.NewEngine(ib.EngineOptions{})
	if err != nil {
		panic(err)
	}

	myAccountManager, err := ib.NewAdvisorAccountManager(myEngine)
	if err != nil {
		panic(err)
	}
	<-myAccountManager.Refresh()
	defer myAccountManager.Close()

	valueMap := myAccountManager.Values()
	stockFromYahoo, err := stocks.GetQuote(ticker)
	if err != nil {
		fmt.Println(err)
	}
	aQuote, err := stockFromYahoo.GetPrice()
	if err != nil {
		fmt.Println(err)
	}
	quoteSlipped := Round((aQuote+(aQuote*slippage))*100) / 100

	//check on shares based on leverage
	for aVk, aV := range valueMap {
		//availableFunds are either buyingPower or netliquadation
		correctAcct := (aVk.AccountCode == theAcct)
		correctForLever := (aVk.Key == "BuyingPower") && useLeverage
		correctForNoLever := (aVk.Key == "BuyingPower") && !useLeverage

		if correctAcct && correctForLever {
			shares = getShares(argShares, aV.Value, quoteSlipped)
			shares = shares - int64(float64(shares)*0.6)
		}
		if correctAcct && correctForNoLever {
			shares = getShares(argShares, aV.Value, quoteSlipped)
		}
	}
	//	fmt.Println("quote", aQuote, "slipped-", quoteSlipped, "shares", shares)
	mgr := IBManager{engine: myEngine}
	mgr.engine.SubscribeAll(rc)

	mgr.engine.Send(&ib.RequestIDs{})
	nextOrderID = getNextOrderID(mgr)
	//	fmt.Println("the next order ID is: ", nextOrderID)

	if theAction == "buy" {
		doBuy(&mgr,
			"AAPL",
			shares,       // number shares
			"LOC",        // mkt, moc, lmt
			quoteSlipped, // price
			theAcct,      // account
			"DAY",        // DAY OPG
			nextOrderID,
			outsideRTH) //out side regular trading hours
	} else if theAction == "sell" { //positions := ib.RequestPositions
		doSell(&mgr, "AAPL", shares, "MARKET", "OPG", nextOrderID)
	} else {
		fmt.Println("neither a buy nor a sell")
	}
	//	nextOrderID = getNextOrderID(mgr)
}