Continuous running Docker container (sidecar) that automatically imports files from brokers & crypto exchanges. Program checks every hour for new transactions and inserts them in ghostfolio. Can also correct & remove transactions if changed or source file deleted.
Additionally, maintains symbols automatically (self-hosted only):
- Set trackinsight property of symbols
- Create manual symbols
- Delete symbols that are no longer used
For non-self-hosted instances (shared accounts), the sidekick runs in non-admin mode:
- No admin-only endpoints are called (platforms, symbol profiles, market data)
- Default targets self-hosted (
ALLOW_ADMIN_CALLS=true); setALLOW_ADMIN_CALLS=falsefor shared/non-self-hosted instances - Platforms cannot be created automatically; configure them in Ghostfolio first
- Symbol profile sync is skipped gracefully
When syncing to the official hosted Ghostfolio instance, you need to configure the sidekick for non-admin mode with appropriate throttling:
ghostfoliosidekick:
image: vibenl/ghostfoliosidekick:latest
container_name: Ghostfolio-Ghostfoliosidekick
hostname: ghostfoliosidekick
security_opt:
- no-new-privilege:true
environment:
- GHOSTFOLIO_URL=https://app.ghostfol.io
- GHOSTFOLIO_ACCESTOKEN=your-user-token
- FILEIMPORTER_PATH=/var/lib/data
- CONFIGURATIONFILE_PATH=/var/lib/data/config.json
- ALLOW_ADMIN_CALLS=false
- TROTTLE_WAITINSECONDS=60
restart: always
volumes:
- /volume1/docker/ghostfolio/sidekick:/var/lib/data:r
depends_on:
ghostfolio:
condition: service_startedRequired settings for official Ghostfolio:
| Setting | Value | Reason |
|---|---|---|
ALLOW_ADMIN_CALLS=false |
false |
Official Ghostfolio does not grant admin access; admin endpoints will be rejected |
TROTTLE_WAITINSECONDS=60 |
60 |
Respects Ghostfolio's rate limits to avoid being blocked |
Important notes:
- Runtime: With 60s throttle between API calls, each sync run is limited to a maximum of 1 hour. Activities are synced incrementally — partial syncs accumulate over multiple runs until everything is complete.
- Platform setup: Platforms cannot be created automatically. Create your platform (e.g., "Ghostfolio.com") in the Ghostfolio UI first, then reference it in your config file.
- Symbol maintenance: Symbol profile sync is skipped in non-admin mode. Symbols will be resolved via Ghostfolio's built-in market data.
- User token: Use your personal access token from Ghostfolio (Settings → API Access), not an admin key.
( more to come? Help is always welcome! )
- Create an account in ghostfolio using anonymous option save your KEY.
- Create the relevant accounts in ghostfolio.
FileImporterPath should point to a folder with the following structure:
- Account Name
- File1.csv
- Account Name 2
- File2.csv
- File3.csv
Assuming you configured an account with the name 'Trading 212' and an account with 'De Giro' in ghostfolio, the following structure should be used. For example:
- Trading 212
- Export2023.csv
- De Giro
- Export2022.csv
- Export2023.csv
A single json file that contains mapping to convert currencies and symbols to a symbol that can be found via ghostfolio. Also allows the following symbol settings
- Setting Trackinsight on symbols
- Adding / Updating Manual symbols
{
"settings" : {
"performance.primarycurrency": "USD",
"dataprovider.preference.order": "COINGECKO;YAHOO",
"delete.unused.symbols": false
},
"platforms":[
{ "name": "De Giro", "url":"https://www.degiro.nl/" }
],
"accounts":[
{ "name": "De Giro", "currency":"EUR", "platform":"De Giro", "sync-activities": true, "sync-balance": false }
],
"mappings":[
{ "type":"currency", "source":"GBX", "target":"GBp"},
{ "type":"symbol", "source":"USDC", "target":"usd-coin"},
{ "type":"symbol", "source":"BTC", "target":"bitcoin"}
],
"symbols":[
{ "symbol": "VDUC.L", "trackinsight": "VUSC" },
{ "symbol": "VFEM.L", "trackinsight": "VDEM" },
{ "symbol": "DE0001102333", "manualSymbolConfiguration": { "currency":"EUR", "isin":"DE0001102333","name":"Bond Germany Feb 2024","assetSubClass":"BOND","assetClass":"EQUITY" } },
{ "symbol": "PhysicalGoldEuroPerKilogram", "manualSymbolConfiguration": { "currency":"EUR", "isin":"PhysicalGoldEuroPerKilogram","name":"Physical Gold EUR/KG","assetSubClass":"PRECIOUS_METAL","assetClass":"COMMODITY" } }
],
"benchmarks":[
{ "symbol": "^AEX" },
{ "symbol": "^SPX" }
]
}Notes:
performance.primarycurrency: default is"EUR"dataprovider.preference.order: default is"YAHOO,COINGECKO"delete.unused.symbols: default istrue. Note generated symbols like INTEREST and FEE are always deleted since they can't be reused.sync-activitiesistrueby default;sync-balanceistrueby default.
This settings does control if a workaround is used for dust (very small amount that cannot be sold or due to rounding errors). The amount is the total value of the assets (thus quantity times unitprice). Unitprice is converted to the currency defined by use.dust.currency.
For crypto specifically, another setting will take presidence. See use.crypto.workaround.dust.threshold. This due to the likelyness of higher values for the dust of cryptocurrencies.
This settings does control if a workaround is used for dust (very small amount that cannot be sold or due to rounding errors). The amount is the total value of the assets (thus quantity times unitprice). Unitprice is converted to the currency defined by use.dust.currency.
This settings does control if a workaround is used for staking rewards. If set to true, the staking reward is added to the last buy activity.
Creates platforms and accounts if not yet created
Fields are identical to the UI
Add a symbol as a benchmark
Change an identifier from the imported files to be compatible with Ghostfolio (for example, certain symbols may not be found by Ghostfolio, so we can substitute the identifier with one that is recognized)
| Fieldname | Type | Description |
|---|---|---|
| type | one of: 'currency', 'symbol' | The type of mapping to be applied |
| source | any string | the name of the symbol as it appears in the csv files |
| target | any string | the name of the symbol to use within Ghostfolio |
Maintaining symbols in ghostfolio
| Fieldname | Type | Description |
|---|---|---|
| symbol | any string | The name of the symbol |
| trackinsight | any string | The trackinsight key to be set |
| manualSymbolConfiguration | ManualSymbolConfiguration | see ManualSymbolConfiguration. Will be created if it does not exists |
| Fieldname | Type | Description |
|---|---|---|
| currency | any string | The currency of the symbol |
| isin | any string | The ISIN to be set |
| name | any string | The name of the symbol |
| assetSubClass | one of: 'CRYPTOCURRENCY', 'ETF', 'STOCK', 'MUTUALFUND', 'BOND', 'COMMODITY', 'PRECIOUS_METAL', 'PRIVATE_EQUITY' | Same list as Ghostfolio |
| assetClass | one of: 'CASH', 'COMMODITY', 'EQUITY', 'FIXED_INCOME', 'REAL_ESTATE' | Same list as Ghostfolio |
| scraperConfiguration | object with url, selector and optional locale | The scraperconfiguration as used in Ghostfolio (NOTE: no support for headers yet) |
The goal is to support all platforms as best as possible. Due to the continuous growth of Ghostfolio, new features may be added when possible.
| Platform | Source of the files | Documentation |
|---|---|---|
| Bitvavo (Broker) | Export of transaction history | |
| Bunq (Bank) | Export CSV (Semicolon delimited) | |
| Centraal Beheer (Broker) | Export of transaction history (CSV, Semicolon delimited) | |
| Coinbase (Broker) | Export of transaction history | |
| De Giro | Export of account history (Language dependent, NL and PT supported currently) | Documentation |
| Generic importer | See below | |
| Gold Republic | Account Statement export (PDF) | |
| MacroTrends | Historical data CSV export | |
| Nexo (Broker) | Export of transaction history | |
| NIBC (Bank) | Export CSV (Semicolon delimited) | |
| Scalable Capital (Prime only) | The CSV files export via the transaction view | |
| Trade Republic | CSV transaction export (recommended) or monthly statements and individual invoices (PDF, legacy) | Documentation |
| Trading 212 | Export of transaction history | Documentation |
| Trine | Export of transaction history (CSV) |
Beside the supported exchanges and brokers there is also a generic format. This format is only usefull for stocks at the moment, not for cryptocurrency:
| Field | Value(s) |
|---|---|
| ActivityType | BUY ,SELL, DIVIDEND and INTEREST |
| Symbol | The symbol to search |
| Date | The date, yyyy-MM-dd |
| Currency | The currency of the unitprice and fee |
| Quantity | The amount of units |
| UnitPrice | The paid price per unit |
| Fee | The total fee paid for the transaction. Is optional |
| Tax | The total tax on the transaction, is used to adjust the unitprice. Is optional |
| Description | A description, not used in ghostfolio itself. Is optional |
| Id | The transaction id. Is optional |
For stock splits there is a seperate format
| Field | Value(s) |
|---|---|
| Symbol | The symbol to search |
| Date | The date, yyyy-MM-dd |
| StockSplitFrom | The number of stock in the old situation |
| StockSplitTo | The number of stock in the new situation |
File1: ActivityType,Symbol,Date,Currency,Quantity,UnitPrice,Fee BUY,US67066G1040,2023-08-07,USD,0.0267001000,453.33,0.02
File2: Symbol,Date,StockSplitFrom,StockSplitTo US67066G1040,2023-08-07,1,3
The docker image is named: vibenl/ghostfoliosidekick
Example docker-compose.yml:
ghostfoliosidekick:
image: vibenl/ghostfoliosidekick:latest
container_name: Ghostfolio-Ghostfoliosidekick
hostname: ghostfoliosidekick
security_opt:
- no-new-privileges:true
environment:
- GHOSTFOLIO_URL=url
- GHOSTFOLIO_ACCESTOKEN=abc
- FILEIMPORTER_PATH=/var/lib/data
- CONFIGURATIONFILE_PATH=/var/lib/data/config.json
restart: always
volumes:
- /volume1/docker/ghostfolio/sidekick:/var/lib/data:r
depends_on:
ghostfolio:
condition: service_started
| Envs | Description |
|---|---|
| GHOSTFOLIO_URL | The endpoint for your ghostfolio instance. |
| GHOSTFOLIO_ACCESTOKEN | The token as used to 'login' in the UI |
| FILEIMPORTER_PATH | The path to the files (see [Import Path]) |
| DATABASE_PATH | The path to the database file. If it is only a path the file will be named 'ghostfolio.db'. In case this variable is not specified, it will be placed in the FILEIMPORTER_PATH. |
| CONFIGURATIONFILE_PATH | (optional) The path to the config file, for example '/files/config/config.json' |
| TROTTLE_WAITINSECONDS | (optional) The time in seconds between calls to Ghostfolio. Defaults to no waittime. |
| ALLOW_ADMIN_CALLS | (optional) Set to false to run in non-admin mode (for shared/non-self-hosted Ghostfolio instances). Defaults to true. |
| DATABASE_QUERY_TIMEOUT_SECONDS | (optional) Database query timeout in seconds for complex queries. Defaults to 120. |
| ENABLE_DATABASE_PERFORMANCE_LOGGING | (optional) Enable detailed database performance logging. Defaults to false. |
| BACKUP_FOLDER_NAME | (optional) Folder name for database backups. Defaults to GHOSTFOLIOSIDEKICKBACKUPS. |
| MAX_BACKUP_COUNT | (optional) Maximum number of compressed backups to keep. Defaults to 5. |
| COINGECKO_CACHE_EXPIRY_DAYS | (optional) HTTP cache expiry in hours for CoinGecko API calls. Defaults to 24. |
| YAHOO_CACHE_EXPIRY_DAYS | (optional) HTTP cache expiry in hours for Yahoo Finance API calls. Defaults to 24. |
| DIVIDENDMAX_CACHE_EXPIRY_DAYS | (optional) HTTP cache expiry in hours for DividendMax API calls. Defaults to 168 (7 days). |
| GHOSTFOLIO_CACHE_EXPIRY_DAYS | (optional) HTTP cache expiry in hours for Ghostfolio API calls. Defaults to 168 (7 days). |
- Feel free to submit any issue or PR's you think necessary