# ynab-portfolio-monitor [![Build Status](https://drone.deadbeef.codes/api/badges/steven/ynab-portfolio-monitor/status.svg)](https://drone.deadbeef.codes/steven/ynab-portfolio-monitor) Track your securities in YNAB for account types and update your balance automatically. For each configured account, it will update the balance from your broker in YNAB every 6 hours by creating / editing a transaction named "Capital Gains or Losses". On days that exchanges are closed, it will not do anything. The end result is that there will be transaction each day with payee "Capital Gains or Losses" in YNAB for each account you configure, which allows tracking your account balance over time. It syncs your balance like magic! ![alt text][logo] [logo]: https://deadbeef.codes/steven/ynab-portfolio-monitor/raw/branch/main/example-image.png "It syncs your balance like magic!" ### Architecture No bloat, uses only the standard library, separate all integrations into their own package. #### Main Package Each account provider / integration is defined in its own package and adheres to the interface specified in accountProviders.go. When the program starts, init() inside main.go attempts to configure all providers, and uses providers where configuration succeeds and ignores providers if configuration fails (eg: missing environment variable or config file). init() will run again if SIGHUP is received to reload configuration. The main() program loop refreshes data every 6 hours by looping through each configured provider and calling AccountProvider.GetBalances(). This returns a slice of balances, and a slice of YNAB account IDs. The index position of the balance slice maps with the index of the YNAB account ID slice. This allows a single provider to provide multiple balances for different YNAB accounts depending on the provider's configuration (eg: if you have multiple accounts at your broker). We loop through the balance slice and update each YNAB account balance with the value. Finally, sleep for 6 hours before doing it again. #### Provider Packages Provider packages are used for any integration and are found in their own sub directories. Providers must adhere to the interface speficied in accountProviders.go. ```golang // AccountProvider is the base set of requirements to be implemented for any integration type AccountProvider interface { Name() string // Returns the name of the provider Configure() error // Configures the provider for first use - if an error is returned the provider is not used GetBalances() ([]int, []string, error) // A slice of balances, and an index mapped slice of ynab account IDs this provider handles is returned } ``` By convention, these methods are implemented in a file called providerImpl.go in each of the provider packages. The following providers are currently available: * bitcoin * questrade * staticjsonFinnhub * staticjsonYahooFinance #### YNAB Package This is a special package used for messaging to and from YNAB, instead of adhering to the AccountProvider interface, it exposes multiple public methods for use in the Main package's business logic. ### Example docker-compose.yml The values below are examples only, and show how to configure the Questrade and Bitcoin providers. With these providers, you can configure as many account pairings as you want using environment variables in a continuous series starting from 0 as shown below. Two example Questrade accounts are configured ending in _0 and _1 but a third can be added by adding account numbers/ID with _2. See the respective README.md files inside the provider directories for more details. ```yaml version: '3.8' services: ynab-portfolio-monitor: image: registry.deadbeef.codes/ynab-portfolio-monitor:latest restart: always environment: - TZ=America/Edmonton - questrade_refresh_token=4dsO6652dS3cxtcctscd3ds4Df2E0 - questrade_account_0=51000001 # TFSA - questrade_account_1=51000002 # RRSP - questrade_ynab_account_0=731af51e-cb40-4d4a-8094-8654e59e11fc # TFSA - questrade_ynab_account_1=78e76e45-2fbe-4ab1-84e9-64ba0996d015 # RRSP - ynab_budget_id=76566452-67ff-4642-99d1-47d752216fb3 - ynab_secret=98Q_J655F_TAyGnhCCDS4uqRe4R5654DT2d-ZXdssZ - bitcoin_address_0=bc1qg0edu4tr7pza8qsxf576r0eulr2ygt3mhldswg - bitcoin_address_1=bc1qeh0dkdqvjyt646657lge0nxqj67z5xa8zxl8q3 - bitcoin_address_2=bc1qsfsdqvj4443t64dfssfgexsaqj67z44dsjkfkj - bitcoin_ynab_account=1f5bec0d-f852-2fbe-bbee-02fa98ded566 # Bitcoin addresses map to single YNAB account volumes: - /data/ynab-portfolio-monitor-data:/data ``` ### Static JSON Providers If your broker doesn't have a provider available, or if you don't want to connect this application to your brokerage account, there is an offline solution available where you can configure your holdings in local static JSON files - and these only need to be updated if your holdings change such as after a trade has been made, or a stock split. For more details, see the README.md files located in the provider directories prefixed with "staticjson".