Steven Polley
47e460a9dc
All checks were successful
continuous-integration/drone/push Build is passing
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package questrade
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
)
|
|
|
|
// Account represents an account associated with the user on behalf
|
|
// of which the API client is authorized.
|
|
//
|
|
// Ref: http://www.questrade.com/api/documentation/rest-operations/account-calls/accounts
|
|
type account struct {
|
|
// Type of the account (e.g., "Cash", "Margin").
|
|
Type string `json:"type"`
|
|
|
|
// Eight-digit account number (e.g., "26598145")
|
|
// Stored as a string, it's used for making account-related API calls
|
|
Number string `json:"number"`
|
|
|
|
// Status of the account (e.g., Active).
|
|
Status string `json:"status"`
|
|
|
|
// Whether this is a primary account for the holder.
|
|
IsPrimary bool `json:"isPrimary"`
|
|
|
|
// Whether this account is one that gets billed for various expenses such as inactivity fees, market data, etc.
|
|
IsBilling bool `json:"isBilling"`
|
|
|
|
// Type of client holding the account (e.g., "Individual").
|
|
ClientAccountType string `json:"clientAccountType"`
|
|
}
|
|
|
|
// Balance belonging to an Account
|
|
//
|
|
// Ref: http://www.questrade.com/api/documentation/rest-operations/account-calls/accounts-id-balances
|
|
type balance struct {
|
|
|
|
// Currency of the balance figure(e.g., "USD" or "CAD").
|
|
Currency string `json:"currency"`
|
|
|
|
// Balance amount.
|
|
Cash float32 `json:"cash"`
|
|
|
|
// Market value of all securities in the account in a given currency.
|
|
MarketValue float32 `json:"marketValue"`
|
|
|
|
// Equity as a difference between cash and marketValue properties.
|
|
TotalEquity float32 `json:"totalEquity"`
|
|
|
|
// Buying power for that particular currency side of the account.
|
|
BuyingPower float32 `json:"buyingPower"`
|
|
|
|
// Maintenance excess for that particular side of the account.
|
|
MaintenanceExcess float32 `json:"maintenanceExcess"`
|
|
|
|
// Whether real-time data was used to calculate the above values.
|
|
IsRealTime bool `json:"isRealTime"`
|
|
}
|
|
|
|
// AccountBalances represents per-currency and combined balances for a specified account.
|
|
//
|
|
// Ref: http://www.questrade.com/api/documentation/rest-operations/account-calls/accounts-id-balances
|
|
type accountBalances struct {
|
|
PerCurrencyBalances []balance `json:"perCurrencyBalances"`
|
|
CombinedBalances []balance `json:"combinedBalances"`
|
|
SODPerCurrencyBalances []balance `json:"sodPerCurrencyBalances"`
|
|
SODCombinedBalances []balance `json:"sodCombinedBalances"`
|
|
}
|
|
|
|
// GetAccounts returns the logged-in User ID, and a list of accounts
|
|
// belonging to that user.
|
|
func (c *client) GetAccounts() (int, []account, error) {
|
|
list := struct {
|
|
UserID int `json:"userId"`
|
|
Accounts []account `json:"accounts"`
|
|
}{}
|
|
|
|
err := c.get("v1/accounts", &list, url.Values{})
|
|
if err != nil {
|
|
return 0, []account{}, err
|
|
}
|
|
return list.UserID, list.Accounts, nil
|
|
}
|
|
|
|
// GetBalances returns the balances for the account with the specified account number
|
|
func (c *client) GetBalances(number string) (accountBalances, error) {
|
|
bal := accountBalances{}
|
|
|
|
err := c.get("v1/accounts/"+number+"/balances", &bal, url.Values{})
|
|
if err != nil {
|
|
return accountBalances{}, err
|
|
}
|
|
return bal, nil
|
|
}
|
|
|
|
func (c *client) GetQuestradeAccountBalance(accountID int) (int, error) {
|
|
balances, err := c.GetBalances(strconv.Itoa(accountID))
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to get balances for account ID '%d': %v", accountID, err)
|
|
}
|
|
|
|
for _, balance := range balances.CombinedBalances {
|
|
if balance.Currency != "CAD" {
|
|
continue
|
|
}
|
|
|
|
return int(balance.TotalEquity) * 1000, nil
|
|
}
|
|
return 0, fmt.Errorf("could not find a CAD balance for this account in questade response")
|
|
}
|