Skip to content

Commit 0b768d0

Browse files
committed
Add --exclude-symbol flag
1 parent 9fe7ffa commit 0b768d0

File tree

11 files changed

+110
-5
lines changed

11 files changed

+110
-5
lines changed

cmd/ibctl/internal/command/category/categorylist/categorylist.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ const (
2929
baseCurrencyFlagName = "base-currency"
3030
// realtimeFlagName is the flag name for fetching real-time quotes and FX rates.
3131
realtimeFlagName = "realtime"
32+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
33+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
3234
)
3335

3436
// NewCommand returns a new category list command.
@@ -70,6 +72,8 @@ type flags struct {
7072
BaseCurrency string
7173
// Realtime fetches real-time quotes and FX rates from Yahoo Finance.
7274
Realtime bool
75+
// ExcludeSymbols excludes these symbols from all computations and output.
76+
ExcludeSymbols []string
7377
}
7478

7579
func newFlags() *flags {
@@ -83,6 +87,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
8387
flagSet.StringVar(&f.Geo, geoFlagName, "", "Filter by geo (e.g., US, INTL)")
8488
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for value conversion (e.g., USD, CAD)")
8589
flagSet.BoolVar(&f.Realtime, realtimeFlagName, false, "Fetch real-time quotes and FX rates from Yahoo Finance")
90+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
8691
}
8792

8893
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -91,7 +96,7 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
9196
return appcmd.NewInvalidArgumentError(err.Error())
9297
}
9398
// Load data through the common pipeline (config, merge, FX, optional download/realtime).
94-
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency)
99+
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency, flags.ExcludeSymbols)
95100
if err != nil {
96101
return err
97102
}

cmd/ibctl/internal/command/coveredcall/coveredcalllist/coveredcalllist.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ type flags struct {
107107
Symbol string
108108
// Sort controls the sort order (yield, premium, otm, expiry).
109109
Sort string
110+
// ExcludeSymbols excludes these symbols from all computations and output.
111+
ExcludeSymbols []string
110112
}
111113

112114
func newFlags() *flags {
@@ -126,6 +128,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
126128
flagSet.Int64Var(&f.MinOpenInterest, "min-open-interest", 10, "Minimum open interest (liquidity filter)")
127129
flagSet.StringVar(&f.Symbol, "symbol", "", "Filter to a specific symbol")
128130
flagSet.StringVar(&f.Sort, "sort", "yield", "Sort by: yield, premium, otm, expiry")
131+
flagSet.StringSliceVar(&f.ExcludeSymbols, ibctlcmd.ExcludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
129132
}
130133

131134
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -185,6 +188,8 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
185188
if err != nil {
186189
return err
187190
}
191+
// Filter out excluded symbols before FIFO computation.
192+
ibctlcmd.FilterExcludedSymbols(mergedData, ibctlcmd.NormalizeExcludeSymbols(flags.ExcludeSymbols))
188193
// Load FX rates for base currency conversion.
189194
fxStore := ibctlfxrates.NewStore(ibctlpath.CacheFXDirPath(config.DirPath))
190195
// Override market prices and FX rates with real-time data from Yahoo Finance.

cmd/ibctl/internal/command/geo/geolist/geolist.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ const (
2929
baseCurrencyFlagName = "base-currency"
3030
// realtimeFlagName is the flag name for fetching real-time quotes and FX rates.
3131
realtimeFlagName = "realtime"
32+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
33+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
3234
)
3335

3436
// NewCommand returns a new geo list command.
@@ -71,6 +73,8 @@ type flags struct {
7173
BaseCurrency string
7274
// Realtime fetches real-time quotes and FX rates from Yahoo Finance.
7375
Realtime bool
76+
// ExcludeSymbols excludes these symbols from all computations and output.
77+
ExcludeSymbols []string
7478
}
7579

7680
func newFlags() *flags {
@@ -84,6 +88,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
8488
flagSet.StringVar(&f.Category, categoryFlagName, "", "Filter by category (e.g., EQUITY, FIXED_INCOME)")
8589
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for value conversion (e.g., USD, CAD)")
8690
flagSet.BoolVar(&f.Realtime, realtimeFlagName, false, "Fetch real-time quotes and FX rates from Yahoo Finance")
91+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
8792
}
8893

8994
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -92,7 +97,7 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
9297
return appcmd.NewInvalidArgumentError(err.Error())
9398
}
9499
// Load data through the common pipeline (config, merge, FX, optional download/realtime).
95-
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency)
100+
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency, flags.ExcludeSymbols)
96101
if err != nil {
97102
return err
98103
}

cmd/ibctl/internal/command/holding/holdinglist/holdinglist.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const (
2626
baseCurrencyFlagName = "base-currency"
2727
// realtimeFlagName is the flag name for fetching real-time quotes and FX rates.
2828
realtimeFlagName = "realtime"
29+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
30+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
2931
)
3032

3133
// NewCommand returns a new holdings overview command.
@@ -98,6 +100,8 @@ type flags struct {
98100
BaseCurrency string
99101
// Realtime fetches real-time quotes and FX rates from Yahoo Finance.
100102
Realtime bool
103+
// ExcludeSymbols excludes these symbols from all computations and output.
104+
ExcludeSymbols []string
101105
}
102106

103107
func newFlags() *flags {
@@ -110,6 +114,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
110114
flagSet.BoolVar(&f.Download, downloadFlagName, false, "Download fresh data before displaying")
111115
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for value conversion (e.g., USD, CAD)")
112116
flagSet.BoolVar(&f.Realtime, realtimeFlagName, false, "Fetch real-time quotes and FX rates from Yahoo Finance")
117+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
113118
}
114119

115120
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -118,7 +123,7 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
118123
return appcmd.NewInvalidArgumentError(err.Error())
119124
}
120125
// Load data through the common pipeline (config, merge, FX, optional download/realtime).
121-
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency)
126+
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency, flags.ExcludeSymbols)
122127
if err != nil {
123128
return err
124129
}

cmd/ibctl/internal/command/lot/lotlist/lotlist.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const (
3737
baseCurrencyFlagName = "base-currency"
3838
// realtimeFlagName is the flag name for fetching real-time quotes and FX rates.
3939
realtimeFlagName = "realtime"
40+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
41+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
4042
)
4143

4244
// NewCommand returns a new lot list command.
@@ -86,6 +88,8 @@ type flags struct {
8688
BaseCurrency string
8789
// Realtime fetches real-time quotes and FX rates from Yahoo Finance.
8890
Realtime bool
91+
// ExcludeSymbols excludes these symbols from all computations and output.
92+
ExcludeSymbols []string
8993
}
9094

9195
func newFlags() *flags {
@@ -99,6 +103,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
99103
flagSet.StringVar(&f.Symbol, symbolFlagName, "", "Filter by symbol (omit for all symbols)")
100104
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for value conversion (e.g., USD, CAD)")
101105
flagSet.BoolVar(&f.Realtime, realtimeFlagName, false, "Fetch real-time quotes and FX rates from Yahoo Finance")
106+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
102107
}
103108

104109
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -143,6 +148,8 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
143148
if err != nil {
144149
return err
145150
}
151+
// Filter out excluded symbols before FIFO computation.
152+
ibctlcmd.FilterExcludedSymbols(mergedData, ibctlcmd.NormalizeExcludeSymbols(flags.ExcludeSymbols))
146153
// Load FX rates for base currency conversion.
147154
fxStore := ibctlfxrates.NewStore(ibctlpath.CacheFXDirPath(config.DirPath))
148155
// Override market prices and FX rates with real-time data from Yahoo Finance.

cmd/ibctl/internal/command/overview/holdingoverview.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const (
3030
baseCurrencyFlagName = "base-currency"
3131
// realtimeFlagName is the flag name for fetching real-time quotes and FX rates.
3232
realtimeFlagName = "realtime"
33+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
34+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
3335
)
3436

3537
// NewCommand returns a new holding overview command.
@@ -63,6 +65,8 @@ type flags struct {
6365
BaseCurrency string
6466
// Realtime fetches real-time quotes and FX rates from Yahoo Finance.
6567
Realtime bool
68+
// ExcludeSymbols excludes these symbols from all computations and output.
69+
ExcludeSymbols []string
6670
}
6771

6872
func newFlags() *flags {
@@ -75,6 +79,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
7579
flagSet.BoolVar(&f.Download, downloadFlagName, false, "Download fresh data before displaying")
7680
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for value conversion (e.g., USD, CAD)")
7781
flagSet.BoolVar(&f.Realtime, realtimeFlagName, false, "Fetch real-time quotes and FX rates from Yahoo Finance")
82+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
7883
}
7984

8085
// overviewJSON is the combined JSON output for the overview command.
@@ -153,7 +158,7 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
153158
return appcmd.NewInvalidArgumentError(err.Error())
154159
}
155160
// Load data through the common pipeline (config, merge, FX, optional download/realtime).
156-
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency)
161+
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency, flags.ExcludeSymbols)
157162
if err != nil {
158163
return err
159164
}

cmd/ibctl/internal/command/possiblesale/possiblesalelist/possiblesalelist.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const (
4646
safeExcludedFlagName = "safe-excluded"
4747
// unsafeFlagName is the flag name for showing only the unsafe section.
4848
unsafeFlagName = "unsafe"
49+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
50+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
4951
)
5052

5153
// safeSellWithCategory wraps PossibleSaleOverview to add a sale_category field for JSON output.
@@ -164,6 +166,8 @@ type flags struct {
164166
SafeExcluded bool
165167
// Unsafe shows only the unsafe section.
166168
Unsafe bool
169+
// ExcludeSymbols excludes these symbols from all computations and output.
170+
ExcludeSymbols []string
167171
}
168172

169173
func newFlags() *flags {
@@ -180,6 +184,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
180184
flagSet.BoolVar(&f.Safe, safeFlagName, false, "Show only the Safe section (losses and LTCG)")
181185
flagSet.BoolVar(&f.SafeExcluded, safeExcludedFlagName, false, "Show only the Safe Excluded section (excluded positions)")
182186
flagSet.BoolVar(&f.Unsafe, unsafeFlagName, false, "Show only the Unsafe section (short-term capital gains)")
187+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
183188
}
184189

185190
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -238,6 +243,8 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
238243
if err != nil {
239244
return err
240245
}
246+
// Filter out excluded symbols before FIFO computation.
247+
ibctlcmd.FilterExcludedSymbols(mergedData, ibctlcmd.NormalizeExcludeSymbols(flags.ExcludeSymbols))
241248
// Load FX rates for base currency conversion.
242249
fxStore := ibctlfxrates.NewStore(ibctlpath.CacheFXDirPath(config.DirPath))
243250
// Override market prices and FX rates with real-time data from Yahoo Finance.

cmd/ibctl/internal/command/realizedsale/realizedsalelist/salelist.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const (
3737
toFlagName = "to"
3838
// baseCurrencyFlagName is the flag name for the base currency for P&L conversion.
3939
baseCurrencyFlagName = "base-currency"
40+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
41+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
4042
)
4143

4244
// NewCommand returns a new trade list command.
@@ -195,6 +197,8 @@ type flags struct {
195197
To string
196198
// BaseCurrency is the target currency for P&L conversion (e.g., "USD", "CAD").
197199
BaseCurrency string
200+
// ExcludeSymbols excludes these symbols from all computations and output.
201+
ExcludeSymbols []string
198202
}
199203

200204
func newFlags() *flags {
@@ -208,6 +212,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
208212
flagSet.StringVar(&f.From, fromFlagName, "", "Filter on sale date (inclusive, format: YYYYMMDD)")
209213
flagSet.StringVar(&f.To, toFlagName, "", "Filter on sale date (inclusive, format: YYYYMMDD)")
210214
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for P&L conversion (e.g., USD, CAD)")
215+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
211216
}
212217

213218
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -261,6 +266,8 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
261266
if err != nil {
262267
return err
263268
}
269+
// Filter out excluded symbols before FIFO computation.
270+
ibctlcmd.FilterExcludedSymbols(mergedData, ibctlcmd.NormalizeExcludeSymbols(flags.ExcludeSymbols))
264271
// Load FX rates for base currency conversion.
265272
fxStore := ibctlfxrates.NewStore(ibctlpath.CacheFXDirPath(config.DirPath))
266273
// Compute realized trades via FIFO lot matching.

cmd/ibctl/internal/command/transaction/transactionlist/transactionlist.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const (
3737
toFlagName = "to"
3838
// baseCurrencyFlagName is the flag name for the base currency for conversion.
3939
baseCurrencyFlagName = "base-currency"
40+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
41+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
4042
)
4143

4244
// NewCommand returns a new transaction list command.
@@ -128,6 +130,8 @@ type flags struct {
128130
To string
129131
// BaseCurrency is the target currency for conversion (e.g., "USD", "CAD").
130132
BaseCurrency string
133+
// ExcludeSymbols excludes these symbols from all computations and output.
134+
ExcludeSymbols []string
131135
}
132136

133137
func newFlags() *flags {
@@ -141,6 +145,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
141145
flagSet.StringVar(&f.From, fromFlagName, "", "Filter on transaction date (inclusive, format: YYYYMMDD)")
142146
flagSet.StringVar(&f.To, toFlagName, "", "Filter on transaction date (inclusive, format: YYYYMMDD)")
143147
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for conversion (e.g., USD, CAD)")
148+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
144149
}
145150

146151
func run(ctx context.Context, container appext.Container, flags *flags) error {
@@ -194,6 +199,8 @@ func run(ctx context.Context, container appext.Container, flags *flags) error {
194199
if err != nil {
195200
return err
196201
}
202+
// Filter out excluded symbols before FIFO computation.
203+
ibctlcmd.FilterExcludedSymbols(mergedData, ibctlcmd.NormalizeExcludeSymbols(flags.ExcludeSymbols))
197204
// Load FX rates for base currency conversion.
198205
fxStore := ibctlfxrates.NewStore(ibctlpath.CacheFXDirPath(config.DirPath))
199206
// Compute the unified transaction list from all data sources.

cmd/ibctl/internal/command/value/holdingvalue.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const (
2424
baseCurrencyFlagName = "base-currency"
2525
// realtimeFlagName is the flag name for fetching real-time quotes and FX rates.
2626
realtimeFlagName = "realtime"
27+
// excludeSymbolFlagName is the shared flag name for excluding symbols from output.
28+
excludeSymbolFlagName = ibctlcmd.ExcludeSymbolFlagName
2729
)
2830

2931
// NewCommand returns a new holding value command.
@@ -68,6 +70,8 @@ type flags struct {
6870
BaseCurrency string
6971
// Realtime fetches real-time quotes and FX rates from Yahoo Finance.
7072
Realtime bool
73+
// ExcludeSymbols excludes these symbols from all computations and output.
74+
ExcludeSymbols []string
7175
}
7276

7377
func newFlags() *flags {
@@ -79,11 +83,12 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) {
7983
flagSet.BoolVar(&f.Download, downloadFlagName, false, "Download fresh data before displaying")
8084
flagSet.StringVar(&f.BaseCurrency, baseCurrencyFlagName, "USD", "Base currency for value conversion (e.g., USD, CAD)")
8185
flagSet.BoolVar(&f.Realtime, realtimeFlagName, false, "Fetch real-time quotes and FX rates from Yahoo Finance")
86+
flagSet.StringSliceVar(&f.ExcludeSymbols, excludeSymbolFlagName, nil, "Exclude symbol from all computations and output (repeatable)")
8287
}
8388

8489
func run(ctx context.Context, container appext.Container, flags *flags) error {
8590
// Load data through the common pipeline (config, merge, FX, optional download/realtime).
86-
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency)
91+
data, err := ibctlcmd.LoadHoldingsData(ctx, container, flags.Download, flags.Realtime, flags.BaseCurrency, flags.ExcludeSymbols)
8792
if err != nil {
8893
return err
8994
}

0 commit comments

Comments
 (0)