Ally Invest API Wrapper

Why an API Wrapper?

The work may not be very glorious, but I feel like an API wrapper is a great way to really get in touch with a language and to see what common patterns in that language look like. When writing an API wrapper, you tend to repeat certain lines of code over and over again. When repeating these lines of code, ways of abstracting out common patterns start to emerge and you learn to write more efficient code in the language as you go. This happened to me as I was coding up the first release of this project.

In addition, I chose the API wrapper because the broker I use to handle my investment portfolio, Ally, has a great API with great documentation. I don’t want to have to manage my investments by hand where I don’t have to, and I think that with an API wrapper, I’ve taken the first steps toward automating my portfolio and being able to backtest any new strategies I can come up with.

Also, I feel that an API wrapper is always welcome in the open source community. While there does exist a Python package that wraps the Ally Invest API, now a Go module exists as well. People can leverage the power and finesse that Go has to offer when managing their investments, and can deploy applications as a single binary that manage their portfolio!

Why Go?

As a professional software engineer, Go is my favorite language for every day work. It’s hard to narrow down why that is, but there are a few key reasons that come to mind. Go is very opinionated on formatting, there are very few syntactic constructs in Go, and Go compiles to a single binary.

Most Go programmers will run the go fmt tool that comes with the langauge any time they check in source code. With everyone using the same formatting tool, gone are the arguments where engineers claim that their way to write code is the best. Everyone has more time to focus on what matters, the code.

Go has very few ways to do things, and less variety in getting things done means more room for creativity in solutions. The less our brains as software engineers have to jump between feature implementation and wrestling with a programming language, the better. There is a much lower cognitive load with writing Go than other languages.

Finally, deploying a go application involves compiling the binary and then copying it to the server! It’s a paradise for those of us familiar with ops.

What Have I Learned?

There were two useful lessons that came out of this project for me in Go, and both have to do with the language itself.

Kinda Generics With the Interface Type

I have a ton of data structures in my project that represent the different types of responses that can come back from the Ally API. I opted to do this so that I could push the majority of the XML parsing onto the Golang standard XML package by just adding annotations to the structure. This has added benefits of also providing a very clean API to work with when using my Ally Invest Wrapper.

The below example outlines how to get quotes for all the symbols passed in.

var api AllyApi
api.Intialize() // Reads in config
res := api.MarketQuotes("FEYE", "IBM") // Returns an struct MarketQuotesResponse, with quotes inside
res.Quotes[0] // First Quote, FEYE

Since I opted to use structs that are used by encoding/xml to do the parsing, I was left with a ton of repeated code marshaling XML into my structures. Each function looked a little something like this

var resp MarketQuotesRepsonse
raw := api.Get("market/quotes?symbols=FEYE")
_ := xml.Unmarhsal(raw, &resp)

This drove me wild because this code was everywhere! Always an unmarshal with a pointer, and having to repeat it every time. Luckily, noticing that the pointer did not have to be any specific type, I looked into how I could pass any pointer to a function and have that pointer be accepted. It is kinda hacky, but to do this I used the interface type.

func unmarshalWithPtr(resp []byte, s interface{}){
    _ := xml.Unmarshal(resp, &s)

Technically, all pointer implement the interface type, so passing in my structure in that second argument (the structure that holds the API results) allows me to have a generic unmarshal method for all of my API calls!

What are the Next Steps With This Project?

I didn’t technically finish the whole API, but I did finish all the calls that I knew I wanted to have so I am leaving it there for now. If I need to, I will revisit this API wrapper and fill in other calls from the Ally Invest API so that I can utilize them in my programs.

With the API Wrapper, I will include it in other Golang projects that will actually pull data from Ally and save it, building a dataset so that I can begin automatically managing my stock portfolio! I can see the next project definitely being a module thats only job is to pull data I care about into some datastore. That module will more than likely also have a dashboard that I can use to configure what data I want to pull in and when I want to start that pulling process. It will essentially be my own personal stock ticker


comments powered by Disqus