@@ -29,15 +29,22 @@ const configTemplate = `# The configuration file version.
2929#
3030# Required. The only current valid version is v1.
3131version: v1
32- # The data directory for ibctl to store downloaded and computed data .
32+ # The data directory for persistent trade data that accumulates over time .
3333#
34- # Required. A v1/ subdirectory will be created within this directory.
35- data_dir: ~/Documents/ibctl
34+ # Required. Only contains trades.json per account, which is incrementally
35+ # merged across downloads. Cannot be safely deleted without losing history
36+ # beyond the 365-day API window.
37+ data_dir: ~/Documents/ibkr/data
38+ # The cache directory for downloaded snapshots (positions, FX rates, etc.).
39+ #
40+ # Required. Safe to delete — fully re-populated on the next download.
41+ cache_dir: ~/Documents/ibkr/cache
3642# The Flex Query ID (visible next to your query name in the IBKR portal).
3743#
3844# Required. Create a Flex Query at https://www.interactivebrokers.com
3945# under Performance & Reports > Flex Queries. Include the Trades,
40- # Open Positions, and Cash Transactions sections with all fields enabled.
46+ # Open Positions, Cash Transactions, Cash Report, Transfers,
47+ # Trade Transfers, and Corporate Actions sections with all fields enabled.
4148#
4249# The Flex Web Service token must be set via the IBKR_FLEX_WEB_SERVICE_TOKEN environment variable.
4350flex_query_id: ""
@@ -60,7 +67,7 @@ activity_statements_dir: ~/Documents/ibkr-statements
6067# seed_dir: ~/Documents/ibkr/seed
6168# Symbol classification configuration.
6269#
63- # Optional. Adds category, type, and sector metadata to holdings output.
70+ # Optional. Adds category, type, sector, and geo metadata to holdings output.
6471# symbols:
6572# - name: NET
6673# category: EQUITY
@@ -73,8 +80,11 @@ activity_statements_dir: ~/Documents/ibkr-statements
7380type ExternalConfigV1 struct {
7481 // Version is the configuration file version (must be "v1").
7582 Version string `yaml:"version"`
76- // DataDir is the data directory for ibctl to store downloaded and computed data .
83+ // DataDir is the directory for persistent trade data that accumulates over time .
7784 DataDir string `yaml:"data_dir"`
85+ // CacheDir is the directory for downloaded snapshots (positions, FX rates, etc.).
86+ // Safe to delete — fully re-populated on the next download.
87+ CacheDir string `yaml:"cache_dir"`
7888 // FlexQueryID is the Flex Query ID.
7989 FlexQueryID string `yaml:"flex_query_id"`
8090 // ActivityStatementsDir is the directory containing IBKR Activity Statement CSVs.
@@ -105,19 +115,11 @@ type ExternalSymbolConfigV1 struct {
105115
106116// Config is the validated runtime configuration derived from the config file.
107117type Config struct {
108- // DataDirV1Path is the resolved versioned data directory path (data_dir/v1).
109- DataDirV1Path string
110- // AccountsDirPath is the directory for per-account cached data (data_dir/v1/accounts).
111- AccountsDirPath string
112- // FXDirPath is the directory for FX rate data per currency pair (data_dir/v1/fx).
113- FXDirPath string
118+ // DataDirPath is the resolved data directory path for persistent trade data.
119+ DataDirPath string
120+ // CacheDirPath is the resolved cache directory path for downloaded snapshots.
121+ CacheDirPath string
114122 // IBKRFlexQueryID is the Flex Query ID.
115- //
116- // To create a Flex Query, log in to IBKR Client Portal, navigate to
117- // Performance & Reports > Flex Queries, and create a new query with
118- // Trades, Open Positions, Cash Transactions, Transfers, Trade Transfers,
119- // and Corporate Actions sections enabled.
120- // The Query ID is displayed next to the query name in the list.
121123 IBKRFlexQueryID string
122124 // ActivityStatementsDirPath is the resolved path to the Activity Statements directory.
123125 ActivityStatementsDirPath string
@@ -152,6 +154,9 @@ func NewConfigV1(externalConfig ExternalConfigV1) (*Config, error) {
152154 if externalConfig .DataDir == "" {
153155 return nil , errors .New ("data_dir is required" )
154156 }
157+ if externalConfig .CacheDir == "" {
158+ return nil , errors .New ("cache_dir is required" )
159+ }
155160 if externalConfig .FlexQueryID == "" {
156161 return nil , errors .New ("flex_query_id is required" )
157162 }
@@ -177,12 +182,16 @@ func NewConfigV1(externalConfig ExternalConfigV1) (*Config, error) {
177182 accountAliases [alias ] = accountID
178183 accountIDToAlias [accountID ] = alias
179184 }
180- // Resolve the data directory path and compute the v1 subdirectory .
185+ // Resolve the data directory path.
181186 dataDirPath , err := xos .ExpandHome (externalConfig .DataDir )
182187 if err != nil {
183188 return nil , err
184189 }
185- dataDirV1Path := filepath .Join (dataDirPath , "v1" )
190+ // Resolve the cache directory path.
191+ cacheDirPath , err := xos .ExpandHome (externalConfig .CacheDir )
192+ if err != nil {
193+ return nil , err
194+ }
186195 // Resolve the activity statements directory path.
187196 activityStatementsDirPath , err := xos .ExpandHome (externalConfig .ActivityStatementsDir )
188197 if err != nil {
@@ -213,9 +222,8 @@ func NewConfigV1(externalConfig ExternalConfigV1) (*Config, error) {
213222 }
214223 }
215224 return & Config {
216- DataDirV1Path : dataDirV1Path ,
217- AccountsDirPath : filepath .Join (dataDirV1Path , "accounts" ),
218- FXDirPath : filepath .Join (dataDirV1Path , "fx" ),
225+ DataDirPath : dataDirPath ,
226+ CacheDirPath : cacheDirPath ,
219227 IBKRFlexQueryID : externalConfig .FlexQueryID ,
220228 ActivityStatementsDirPath : activityStatementsDirPath ,
221229 SeedDirPath : seedDirPath ,
0 commit comments