@gaberoo/kalshitools 1.0.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +249 -12
- package/dist/commands/markets/scan.d.ts +18 -0
- package/dist/commands/markets/scan.js +237 -0
- package/dist/commands/portfolio/analytics.d.ts +12 -0
- package/dist/commands/portfolio/analytics.js +192 -0
- package/dist/commands/portfolio/history.d.ts +14 -0
- package/dist/commands/portfolio/history.js +245 -0
- package/dist/commands/portfolio/risk.d.ts +11 -0
- package/dist/commands/portfolio/risk.js +206 -0
- package/dist/lib/analytics.d.ts +64 -0
- package/dist/lib/analytics.js +236 -0
- package/dist/lib/risk.d.ts +51 -0
- package/dist/lib/risk.js +153 -0
- package/dist/lib/scanner.d.ts +58 -0
- package/dist/lib/scanner.js +160 -0
- package/dist/lib/validation.js +4 -3
- package/docs/TRADING_STRATEGIES.md +538 -0
- package/oclif.manifest.json +299 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,10 @@ A powerful CLI tool for interacting with the Kalshi prediction markets API. Buil
|
|
|
16
16
|
- 🛡️ **Safety First**: Demo environment default, confirmations, and order limits
|
|
17
17
|
- 📈 **Order Book Analysis**: Real-time order depth and liquidity assessment
|
|
18
18
|
- 🔍 **Market Discovery**: Event/series filtering, nested markets, multi-ticker batch queries
|
|
19
|
+
- 📊 **Portfolio Analytics**: Comprehensive performance metrics, win rate, P&L analysis, fee tracking
|
|
20
|
+
- ⚠️ **Risk Management**: Real-time risk assessment, concentration analysis, correlation detection
|
|
21
|
+
- 📈 **Historical Analysis**: Time-series performance data, maker/taker statistics, trend analysis
|
|
22
|
+
- 🔎 **Market Scanner**: Automated opportunity discovery based on liquidity, spreads, and volume
|
|
19
23
|
|
|
20
24
|
## Quick Start
|
|
21
25
|
|
|
@@ -120,6 +124,86 @@ kalshitools orders create \
|
|
|
120
124
|
|
|
121
125
|
# View order history
|
|
122
126
|
kalshitools orders list
|
|
127
|
+
|
|
128
|
+
# Analyze portfolio performance
|
|
129
|
+
kalshitools portfolio analytics --period 30 --json
|
|
130
|
+
|
|
131
|
+
# Check portfolio risk
|
|
132
|
+
kalshitools portfolio risk --threshold 20
|
|
133
|
+
|
|
134
|
+
# View historical performance
|
|
135
|
+
kalshitools portfolio history --group-by week
|
|
136
|
+
|
|
137
|
+
# Scan markets for opportunities
|
|
138
|
+
kalshitools markets scan --min-liquidity 200 --min-spread 0.05
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Advanced Features for AI Trading Agents
|
|
142
|
+
|
|
143
|
+
kalshitools provides powerful analytics and scanning capabilities designed for automated trading systems:
|
|
144
|
+
|
|
145
|
+
### Portfolio Analytics
|
|
146
|
+
|
|
147
|
+
Get comprehensive performance metrics for strategy evaluation:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Full analytics for last 30 days
|
|
151
|
+
kalshitools portfolio analytics --period 30 --json
|
|
152
|
+
|
|
153
|
+
# Custom date range
|
|
154
|
+
kalshitools portfolio analytics \
|
|
155
|
+
--min-ts 2026-01-01T00:00:00Z \
|
|
156
|
+
--max-ts 2026-02-01T00:00:00Z \
|
|
157
|
+
--json
|
|
158
|
+
|
|
159
|
+
# Returns: win rate, avg P&L, total return, exposure ratio, concentration, fees
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Risk Management
|
|
163
|
+
|
|
164
|
+
Real-time risk assessment to prevent over-concentration:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# Check portfolio risk with 20% position limit
|
|
168
|
+
kalshitools portfolio risk --threshold 20 --json
|
|
169
|
+
|
|
170
|
+
# Analyze concentration by event
|
|
171
|
+
kalshitools portfolio risk --group-by event --json
|
|
172
|
+
|
|
173
|
+
# Returns: risk score, concentrations, correlations, alerts, recommendations
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Historical Performance
|
|
177
|
+
|
|
178
|
+
Deep dive into trading history with time-series analytics:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Daily performance breakdown
|
|
182
|
+
kalshitools portfolio history --group-by day --json
|
|
183
|
+
|
|
184
|
+
# Filter by specific market
|
|
185
|
+
kalshitools portfolio history --ticker MARKET-A --json
|
|
186
|
+
|
|
187
|
+
# Returns: time-series data, maker/taker stats, performance by ticker
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Market Opportunity Scanner
|
|
191
|
+
|
|
192
|
+
Discover high-quality trading opportunities:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Scan for markets with good liquidity and spreads
|
|
196
|
+
kalshitools markets scan \
|
|
197
|
+
--min-liquidity 200 \
|
|
198
|
+
--min-spread 0.05 \
|
|
199
|
+
--max-spread 0.20 \
|
|
200
|
+
--min-volume 1000 \
|
|
201
|
+
--json
|
|
202
|
+
|
|
203
|
+
# Filter to specific event
|
|
204
|
+
kalshitools markets scan --event-ticker EVENT-2024 --json
|
|
205
|
+
|
|
206
|
+
# Returns: scored opportunities with liquidity, spread, and volume data
|
|
123
207
|
```
|
|
124
208
|
|
|
125
209
|
## Configuration
|
|
@@ -171,6 +255,22 @@ export LOG_LEVEL=info
|
|
|
171
255
|
* [Place an order (with confirmation)](#place-an-order-with-confirmation)
|
|
172
256
|
* [Use --dry-run to simulate without placing order](#use---dry-run-to-simulate-without-placing-order)
|
|
173
257
|
* [View order history](#view-order-history)
|
|
258
|
+
* [Analyze portfolio performance](#analyze-portfolio-performance)
|
|
259
|
+
* [Check portfolio risk](#check-portfolio-risk)
|
|
260
|
+
* [View historical performance](#view-historical-performance)
|
|
261
|
+
* [Scan markets for opportunities](#scan-markets-for-opportunities)
|
|
262
|
+
* [Full analytics for last 30 days](#full-analytics-for-last-30-days)
|
|
263
|
+
* [Custom date range](#custom-date-range)
|
|
264
|
+
* [Returns: win rate, avg P&L, total return, exposure ratio, concentration, fees](#returns-win-rate-avg-pl-total-return-exposure-ratio-concentration-fees)
|
|
265
|
+
* [Check portfolio risk with 20% position limit](#check-portfolio-risk-with-20-position-limit)
|
|
266
|
+
* [Analyze concentration by event](#analyze-concentration-by-event)
|
|
267
|
+
* [Returns: risk score, concentrations, correlations, alerts, recommendations](#returns-risk-score-concentrations-correlations-alerts-recommendations)
|
|
268
|
+
* [Daily performance breakdown](#daily-performance-breakdown)
|
|
269
|
+
* [Filter by specific market](#filter-by-specific-market)
|
|
270
|
+
* [Returns: time-series data, maker/taker stats, performance by ticker](#returns-time-series-data-makertaker-stats-performance-by-ticker)
|
|
271
|
+
* [Scan for markets with good liquidity and spreads](#scan-for-markets-with-good-liquidity-and-spreads)
|
|
272
|
+
* [Filter to specific event](#filter-to-specific-event)
|
|
273
|
+
* [Returns: scored opportunities with liquidity, spread, and volume data](#returns-scored-opportunities-with-liquidity-spread-and-volume-data)
|
|
174
274
|
* [Usage](#usage)
|
|
175
275
|
* [Commands](#commands)
|
|
176
276
|
<!-- tocstop -->
|
|
@@ -181,7 +281,7 @@ $ npm install -g @gaberoo/kalshitools
|
|
|
181
281
|
$ kalshitools COMMAND
|
|
182
282
|
running command...
|
|
183
283
|
$ kalshitools (--version)
|
|
184
|
-
@gaberoo/kalshitools/1.
|
|
284
|
+
@gaberoo/kalshitools/1.1.1 darwin-arm64 node-v22.20.0
|
|
185
285
|
$ kalshitools --help [COMMAND]
|
|
186
286
|
USAGE
|
|
187
287
|
$ kalshitools COMMAND
|
|
@@ -195,6 +295,7 @@ USAGE
|
|
|
195
295
|
* [`kalshitools help [COMMAND]`](#kalshitools-help-command)
|
|
196
296
|
* [`kalshitools markets list`](#kalshitools-markets-list)
|
|
197
297
|
* [`kalshitools markets orderbook TICKER`](#kalshitools-markets-orderbook-ticker)
|
|
298
|
+
* [`kalshitools markets scan`](#kalshitools-markets-scan)
|
|
198
299
|
* [`kalshitools markets show TICKER`](#kalshitools-markets-show-ticker)
|
|
199
300
|
* [`kalshitools orders cancel ORDERID`](#kalshitools-orders-cancel-orderid)
|
|
200
301
|
* [`kalshitools orders create`](#kalshitools-orders-create)
|
|
@@ -209,9 +310,12 @@ USAGE
|
|
|
209
310
|
* [`kalshitools plugins uninstall [PLUGIN]`](#kalshitools-plugins-uninstall-plugin)
|
|
210
311
|
* [`kalshitools plugins unlink [PLUGIN]`](#kalshitools-plugins-unlink-plugin)
|
|
211
312
|
* [`kalshitools plugins update`](#kalshitools-plugins-update)
|
|
313
|
+
* [`kalshitools portfolio analytics`](#kalshitools-portfolio-analytics)
|
|
212
314
|
* [`kalshitools portfolio balance`](#kalshitools-portfolio-balance)
|
|
213
315
|
* [`kalshitools portfolio fills`](#kalshitools-portfolio-fills)
|
|
316
|
+
* [`kalshitools portfolio history`](#kalshitools-portfolio-history)
|
|
214
317
|
* [`kalshitools portfolio positions`](#kalshitools-portfolio-positions)
|
|
318
|
+
* [`kalshitools portfolio risk`](#kalshitools-portfolio-risk)
|
|
215
319
|
|
|
216
320
|
## `kalshitools config init`
|
|
217
321
|
|
|
@@ -237,7 +341,7 @@ EXAMPLES
|
|
|
237
341
|
$ kalshitools config init --env production
|
|
238
342
|
```
|
|
239
343
|
|
|
240
|
-
_See code: [src/commands/config/init.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
344
|
+
_See code: [src/commands/config/init.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/config/init.ts)_
|
|
241
345
|
|
|
242
346
|
## `kalshitools config show`
|
|
243
347
|
|
|
@@ -259,7 +363,7 @@ EXAMPLES
|
|
|
259
363
|
$ kalshitools config show --json
|
|
260
364
|
```
|
|
261
365
|
|
|
262
|
-
_See code: [src/commands/config/show.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
366
|
+
_See code: [src/commands/config/show.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/config/show.ts)_
|
|
263
367
|
|
|
264
368
|
## `kalshitools help [COMMAND]`
|
|
265
369
|
|
|
@@ -317,7 +421,7 @@ EXAMPLES
|
|
|
317
421
|
$ kalshitools markets list --json
|
|
318
422
|
```
|
|
319
423
|
|
|
320
|
-
_See code: [src/commands/markets/list.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
424
|
+
_See code: [src/commands/markets/list.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/markets/list.ts)_
|
|
321
425
|
|
|
322
426
|
## `kalshitools markets orderbook TICKER`
|
|
323
427
|
|
|
@@ -345,7 +449,47 @@ EXAMPLES
|
|
|
345
449
|
$ kalshitools markets orderbook TICKER --json
|
|
346
450
|
```
|
|
347
451
|
|
|
348
|
-
_See code: [src/commands/markets/orderbook.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
452
|
+
_See code: [src/commands/markets/orderbook.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/markets/orderbook.ts)_
|
|
453
|
+
|
|
454
|
+
## `kalshitools markets scan`
|
|
455
|
+
|
|
456
|
+
Scan markets for trading opportunities based on liquidity and spreads
|
|
457
|
+
|
|
458
|
+
```
|
|
459
|
+
USAGE
|
|
460
|
+
$ kalshitools markets scan [--json] [--depth <value>] [--event-ticker <value>] [--limit <value>] [--max-spread
|
|
461
|
+
<value>] [--min-liquidity <value>] [--min-spread <value>] [--min-volume <value>] [--series-ticker <value>]
|
|
462
|
+
[--sort-by liquidity|score|spread|volume]
|
|
463
|
+
|
|
464
|
+
FLAGS
|
|
465
|
+
--depth=<value> [default: 5] Orderbook depth to fetch for analysis
|
|
466
|
+
--event-ticker=<value> Filter to specific event
|
|
467
|
+
--json Output in JSON format
|
|
468
|
+
--limit=<value> [default: 50] Maximum markets to scan
|
|
469
|
+
--max-spread=<value> [default: 0.30] Maximum spread in cents (e.g., 0.30 = 30 cents)
|
|
470
|
+
--min-liquidity=<value> [default: 100] Minimum orderbook depth in dollars
|
|
471
|
+
--min-spread=<value> [default: 0.03] Minimum spread in cents (e.g., 0.03 = 3 cents)
|
|
472
|
+
--min-volume=<value> [default: 500] Minimum 24h volume in dollars
|
|
473
|
+
--series-ticker=<value> Filter to specific series
|
|
474
|
+
--sort-by=<option> [default: score] Ranking criteria
|
|
475
|
+
<options: liquidity|score|spread|volume>
|
|
476
|
+
|
|
477
|
+
DESCRIPTION
|
|
478
|
+
Scan markets for trading opportunities based on liquidity and spreads
|
|
479
|
+
|
|
480
|
+
EXAMPLES
|
|
481
|
+
$ kalshitools markets scan
|
|
482
|
+
|
|
483
|
+
$ kalshitools markets scan --min-liquidity 200 --min-spread 0.05
|
|
484
|
+
|
|
485
|
+
$ kalshitools markets scan --event-ticker EVENT-2024
|
|
486
|
+
|
|
487
|
+
$ kalshitools markets scan --sort-by liquidity --limit 20
|
|
488
|
+
|
|
489
|
+
$ kalshitools markets scan --json
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
_See code: [src/commands/markets/scan.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/markets/scan.ts)_
|
|
349
493
|
|
|
350
494
|
## `kalshitools markets show TICKER`
|
|
351
495
|
|
|
@@ -370,7 +514,7 @@ EXAMPLES
|
|
|
370
514
|
$ kalshitools markets show TICKER --json
|
|
371
515
|
```
|
|
372
516
|
|
|
373
|
-
_See code: [src/commands/markets/show.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
517
|
+
_See code: [src/commands/markets/show.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/markets/show.ts)_
|
|
374
518
|
|
|
375
519
|
## `kalshitools orders cancel ORDERID`
|
|
376
520
|
|
|
@@ -398,7 +542,7 @@ EXAMPLES
|
|
|
398
542
|
$ kalshitools orders cancel ORDER_ID --json
|
|
399
543
|
```
|
|
400
544
|
|
|
401
|
-
_See code: [src/commands/orders/cancel.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
545
|
+
_See code: [src/commands/orders/cancel.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/orders/cancel.ts)_
|
|
402
546
|
|
|
403
547
|
## `kalshitools orders create`
|
|
404
548
|
|
|
@@ -436,7 +580,7 @@ EXAMPLES
|
|
|
436
580
|
$ kalshitools orders create --ticker TICKER --action buy --side yes --quantity 100 --dry-run
|
|
437
581
|
```
|
|
438
582
|
|
|
439
|
-
_See code: [src/commands/orders/create.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
583
|
+
_See code: [src/commands/orders/create.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/orders/create.ts)_
|
|
440
584
|
|
|
441
585
|
## `kalshitools orders list`
|
|
442
586
|
|
|
@@ -467,7 +611,7 @@ EXAMPLES
|
|
|
467
611
|
$ kalshitools orders list --json
|
|
468
612
|
```
|
|
469
613
|
|
|
470
|
-
_See code: [src/commands/orders/list.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
614
|
+
_See code: [src/commands/orders/list.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/orders/list.ts)_
|
|
471
615
|
|
|
472
616
|
## `kalshitools plugins`
|
|
473
617
|
|
|
@@ -759,6 +903,35 @@ DESCRIPTION
|
|
|
759
903
|
|
|
760
904
|
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.56/src/commands/plugins/update.ts)_
|
|
761
905
|
|
|
906
|
+
## `kalshitools portfolio analytics`
|
|
907
|
+
|
|
908
|
+
Comprehensive portfolio performance analytics
|
|
909
|
+
|
|
910
|
+
```
|
|
911
|
+
USAGE
|
|
912
|
+
$ kalshitools portfolio analytics [--json] [--max-ts <value>] [--min-ts <value>] [--period <value>]
|
|
913
|
+
|
|
914
|
+
FLAGS
|
|
915
|
+
--json Output in JSON format
|
|
916
|
+
--max-ts=<value> End date for analysis (ISO-8601 format)
|
|
917
|
+
--min-ts=<value> Start date for analysis (ISO-8601 format)
|
|
918
|
+
--period=<value> Analysis period in days (overridden by min-ts/max-ts)
|
|
919
|
+
|
|
920
|
+
DESCRIPTION
|
|
921
|
+
Comprehensive portfolio performance analytics
|
|
922
|
+
|
|
923
|
+
EXAMPLES
|
|
924
|
+
$ kalshitools portfolio analytics
|
|
925
|
+
|
|
926
|
+
$ kalshitools portfolio analytics --period 7
|
|
927
|
+
|
|
928
|
+
$ kalshitools portfolio analytics --min-ts 2026-01-01T00:00:00Z
|
|
929
|
+
|
|
930
|
+
$ kalshitools portfolio analytics --json
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
_See code: [src/commands/portfolio/analytics.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/portfolio/analytics.ts)_
|
|
934
|
+
|
|
762
935
|
## `kalshitools portfolio balance`
|
|
763
936
|
|
|
764
937
|
View account balance
|
|
@@ -779,7 +952,7 @@ EXAMPLES
|
|
|
779
952
|
$ kalshitools portfolio balance --json
|
|
780
953
|
```
|
|
781
954
|
|
|
782
|
-
_See code: [src/commands/portfolio/balance.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
955
|
+
_See code: [src/commands/portfolio/balance.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/portfolio/balance.ts)_
|
|
783
956
|
|
|
784
957
|
## `kalshitools portfolio fills`
|
|
785
958
|
|
|
@@ -807,7 +980,42 @@ EXAMPLES
|
|
|
807
980
|
$ kalshitools portfolio fills --json
|
|
808
981
|
```
|
|
809
982
|
|
|
810
|
-
_See code: [src/commands/portfolio/fills.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
983
|
+
_See code: [src/commands/portfolio/fills.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/portfolio/fills.ts)_
|
|
984
|
+
|
|
985
|
+
## `kalshitools portfolio history`
|
|
986
|
+
|
|
987
|
+
Historical performance analysis with time-series data
|
|
988
|
+
|
|
989
|
+
```
|
|
990
|
+
USAGE
|
|
991
|
+
$ kalshitools portfolio history [--json] [--group-by day|week|month] [--limit <value>] [--max-ts <value>] [--min-ts
|
|
992
|
+
<value>] [--ticker <value>]
|
|
993
|
+
|
|
994
|
+
FLAGS
|
|
995
|
+
--group-by=<option> [default: day] Time aggregation level
|
|
996
|
+
<options: day|week|month>
|
|
997
|
+
--json Output in JSON format
|
|
998
|
+
--limit=<value> [default: 500] Maximum fills to fetch (handles pagination)
|
|
999
|
+
--max-ts=<value> End date (ISO-8601 format)
|
|
1000
|
+
--min-ts=<value> Start date (ISO-8601 format)
|
|
1001
|
+
--ticker=<value> Filter by specific market ticker
|
|
1002
|
+
|
|
1003
|
+
DESCRIPTION
|
|
1004
|
+
Historical performance analysis with time-series data
|
|
1005
|
+
|
|
1006
|
+
EXAMPLES
|
|
1007
|
+
$ kalshitools portfolio history
|
|
1008
|
+
|
|
1009
|
+
$ kalshitools portfolio history --ticker MARKET-A
|
|
1010
|
+
|
|
1011
|
+
$ kalshitools portfolio history --group-by week
|
|
1012
|
+
|
|
1013
|
+
$ kalshitools portfolio history --min-ts 2026-01-01T00:00:00Z --max-ts 2026-02-01T00:00:00Z
|
|
1014
|
+
|
|
1015
|
+
$ kalshitools portfolio history --json
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
_See code: [src/commands/portfolio/history.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/portfolio/history.ts)_
|
|
811
1019
|
|
|
812
1020
|
## `kalshitools portfolio positions`
|
|
813
1021
|
|
|
@@ -835,5 +1043,34 @@ EXAMPLES
|
|
|
835
1043
|
$ kalshitools portfolio positions --json
|
|
836
1044
|
```
|
|
837
1045
|
|
|
838
|
-
_See code: [src/commands/portfolio/positions.ts](https://github.com/kalshitools/kalshitools/blob/v1.
|
|
1046
|
+
_See code: [src/commands/portfolio/positions.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/portfolio/positions.ts)_
|
|
1047
|
+
|
|
1048
|
+
## `kalshitools portfolio risk`
|
|
1049
|
+
|
|
1050
|
+
Real-time portfolio risk analysis and warnings
|
|
1051
|
+
|
|
1052
|
+
```
|
|
1053
|
+
USAGE
|
|
1054
|
+
$ kalshitools portfolio risk [--json] [--group-by event|series|ticker] [--threshold <value>]
|
|
1055
|
+
|
|
1056
|
+
FLAGS
|
|
1057
|
+
--group-by=<option> [default: ticker] Grouping for concentration analysis
|
|
1058
|
+
<options: event|series|ticker>
|
|
1059
|
+
--json Output in JSON format
|
|
1060
|
+
--threshold=<value> [default: 20] Alert threshold for position concentration (%)
|
|
1061
|
+
|
|
1062
|
+
DESCRIPTION
|
|
1063
|
+
Real-time portfolio risk analysis and warnings
|
|
1064
|
+
|
|
1065
|
+
EXAMPLES
|
|
1066
|
+
$ kalshitools portfolio risk
|
|
1067
|
+
|
|
1068
|
+
$ kalshitools portfolio risk --threshold 15
|
|
1069
|
+
|
|
1070
|
+
$ kalshitools portfolio risk --group-by event
|
|
1071
|
+
|
|
1072
|
+
$ kalshitools portfolio risk --json
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
_See code: [src/commands/portfolio/risk.ts](https://github.com/kalshitools/kalshitools/blob/v1.1.1/src/commands/portfolio/risk.ts)_
|
|
839
1076
|
<!-- commandsstop -->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../../lib/base-command.js';
|
|
2
|
+
export default class MarketsScan extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
depth: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
'event-ticker': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'max-spread': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'min-liquidity': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'min-spread': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'min-volume': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'series-ticker': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'sort-by': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { BaseCommand } from '../../lib/base-command.js';
|
|
4
|
+
import { createClientFromConfig } from '../../lib/kalshi/index.js';
|
|
5
|
+
import { logger } from '../../lib/logger.js';
|
|
6
|
+
import { calculateOrderbookLiquidity, calculateSpread, classifyOpportunity, filterMarketsByCriteria, generateOpportunityReason, scoreMarket, } from '../../lib/scanner.js';
|
|
7
|
+
export default class MarketsScan extends BaseCommand {
|
|
8
|
+
static description = 'Scan markets for trading opportunities based on liquidity and spreads';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> <%= command.id %>',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> --min-liquidity 200 --min-spread 0.05',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --event-ticker EVENT-2024',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --sort-by liquidity --limit 20',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> --json',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
...BaseCommand.baseFlags,
|
|
18
|
+
'depth': Flags.integer({
|
|
19
|
+
default: 5,
|
|
20
|
+
description: 'Orderbook depth to fetch for analysis',
|
|
21
|
+
}),
|
|
22
|
+
'event-ticker': Flags.string({
|
|
23
|
+
description: 'Filter to specific event',
|
|
24
|
+
}),
|
|
25
|
+
'limit': Flags.integer({
|
|
26
|
+
default: 50,
|
|
27
|
+
description: 'Maximum markets to scan',
|
|
28
|
+
}),
|
|
29
|
+
'max-spread': Flags.string({
|
|
30
|
+
default: '0.30',
|
|
31
|
+
description: 'Maximum spread in cents (e.g., 0.30 = 30 cents)',
|
|
32
|
+
}),
|
|
33
|
+
'min-liquidity': Flags.string({
|
|
34
|
+
default: '100',
|
|
35
|
+
description: 'Minimum orderbook depth in dollars',
|
|
36
|
+
}),
|
|
37
|
+
'min-spread': Flags.string({
|
|
38
|
+
default: '0.03',
|
|
39
|
+
description: 'Minimum spread in cents (e.g., 0.03 = 3 cents)',
|
|
40
|
+
}),
|
|
41
|
+
'min-volume': Flags.string({
|
|
42
|
+
default: '500',
|
|
43
|
+
description: 'Minimum 24h volume in dollars',
|
|
44
|
+
}),
|
|
45
|
+
'series-ticker': Flags.string({
|
|
46
|
+
description: 'Filter to specific series',
|
|
47
|
+
}),
|
|
48
|
+
'sort-by': Flags.string({
|
|
49
|
+
default: 'score',
|
|
50
|
+
description: 'Ranking criteria',
|
|
51
|
+
options: ['liquidity', 'score', 'spread', 'volume'],
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
async run() {
|
|
55
|
+
const { flags } = await this.parse(MarketsScan);
|
|
56
|
+
try {
|
|
57
|
+
const client = createClientFromConfig();
|
|
58
|
+
// Parse numeric flags
|
|
59
|
+
const minLiquidity = Number.parseFloat(flags['min-liquidity']);
|
|
60
|
+
const minSpread = Number.parseFloat(flags['min-spread']);
|
|
61
|
+
const maxSpread = Number.parseFloat(flags['max-spread']);
|
|
62
|
+
const minVolume = Number.parseFloat(flags['min-volume']);
|
|
63
|
+
if (!this.formatter.isJSONMode()) {
|
|
64
|
+
this.log(chalk.cyan.bold('Scanning Markets for Opportunities...'));
|
|
65
|
+
this.log();
|
|
66
|
+
}
|
|
67
|
+
// Fetch active markets
|
|
68
|
+
const marketsResult = await client.getMarkets({
|
|
69
|
+
event_ticker: flags['event-ticker'],
|
|
70
|
+
limit: flags.limit,
|
|
71
|
+
series_ticker: flags['series-ticker'],
|
|
72
|
+
status: 'active',
|
|
73
|
+
});
|
|
74
|
+
const { markets } = marketsResult;
|
|
75
|
+
if (markets.length === 0) {
|
|
76
|
+
if (this.formatter.isJSONMode()) {
|
|
77
|
+
this.formatter.success({
|
|
78
|
+
markets: [],
|
|
79
|
+
opportunities: 0,
|
|
80
|
+
scanned: 0,
|
|
81
|
+
stats: {
|
|
82
|
+
avg_liquidity: 0,
|
|
83
|
+
avg_spread: 0,
|
|
84
|
+
avg_volume_24h: 0,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.log(chalk.yellow('No active markets found'));
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!this.formatter.isJSONMode()) {
|
|
94
|
+
this.log(`Found ${markets.length} active markets. Fetching orderbooks...`);
|
|
95
|
+
this.log(chalk.gray('(This may take a few seconds due to rate limiting)'));
|
|
96
|
+
this.log();
|
|
97
|
+
}
|
|
98
|
+
// Fetch orderbooks for all markets (rate limited automatically by client)
|
|
99
|
+
const marketData = [];
|
|
100
|
+
for (const market of markets) {
|
|
101
|
+
try {
|
|
102
|
+
const orderbook = await client.getOrderBook(market.ticker, flags.depth);
|
|
103
|
+
const liquidity = calculateOrderbookLiquidity(orderbook);
|
|
104
|
+
const spreadData = calculateSpread(orderbook);
|
|
105
|
+
const volume = market.volume_24h || market.volume || 0;
|
|
106
|
+
const score = scoreMarket(market, orderbook);
|
|
107
|
+
marketData.push({
|
|
108
|
+
liquidity: liquidity.total,
|
|
109
|
+
market,
|
|
110
|
+
orderbook,
|
|
111
|
+
score,
|
|
112
|
+
spread: spreadData ? spreadData.spreadCents : null,
|
|
113
|
+
volume,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
logger.debug({ error, ticker: market.ticker }, 'Failed to fetch orderbook');
|
|
118
|
+
// Skip markets with orderbook fetch errors
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Filter markets by criteria
|
|
123
|
+
const filtered = filterMarketsByCriteria(marketData, {
|
|
124
|
+
maxSpread,
|
|
125
|
+
minLiquidity,
|
|
126
|
+
minSpread,
|
|
127
|
+
minVolume,
|
|
128
|
+
});
|
|
129
|
+
// Sort markets
|
|
130
|
+
const sorted = [...filtered];
|
|
131
|
+
if (flags['sort-by'] === 'liquidity') {
|
|
132
|
+
sorted.sort((a, b) => b.liquidity - a.liquidity);
|
|
133
|
+
}
|
|
134
|
+
else if (flags['sort-by'] === 'spread') {
|
|
135
|
+
sorted.sort((a, b) => (b.spread || 0) - (a.spread || 0));
|
|
136
|
+
}
|
|
137
|
+
else if (flags['sort-by'] === 'volume') {
|
|
138
|
+
sorted.sort((a, b) => b.volume - a.volume);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Default to score
|
|
142
|
+
sorted.sort((a, b) => b.score - a.score);
|
|
143
|
+
}
|
|
144
|
+
// Calculate statistics
|
|
145
|
+
const avgLiquidity = filtered.length > 0
|
|
146
|
+
? filtered.reduce((sum, m) => sum + m.liquidity, 0) / filtered.length
|
|
147
|
+
: 0;
|
|
148
|
+
const avgSpread = filtered.length > 0
|
|
149
|
+
? filtered.filter(m => m.spread !== null).reduce((sum, m) => sum + (m.spread || 0), 0) / filtered.filter(m => m.spread !== null).length
|
|
150
|
+
: 0;
|
|
151
|
+
const avgVolume24h = filtered.length > 0
|
|
152
|
+
? filtered.reduce((sum, m) => sum + m.volume, 0) / filtered.length
|
|
153
|
+
: 0;
|
|
154
|
+
if (this.formatter.isJSONMode()) {
|
|
155
|
+
const opportunities = sorted.map(m => {
|
|
156
|
+
const spreadData = m.orderbook ? calculateSpread(m.orderbook) : null;
|
|
157
|
+
const liquidityData = m.orderbook ? calculateOrderbookLiquidity(m.orderbook) : { noTotal: 0, total: 0, yesTotal: 0 };
|
|
158
|
+
const opportunityType = classifyOpportunity(m.spread || 0, m.liquidity, m.volume);
|
|
159
|
+
return {
|
|
160
|
+
liquidity: {
|
|
161
|
+
no_total: liquidityData.noTotal,
|
|
162
|
+
total: liquidityData.total,
|
|
163
|
+
yes_total: liquidityData.yesTotal,
|
|
164
|
+
},
|
|
165
|
+
opportunity_type: opportunityType,
|
|
166
|
+
reason: generateOpportunityReason(opportunityType, m.spread || 0, m.liquidity, m.volume),
|
|
167
|
+
score: m.score,
|
|
168
|
+
spread: spreadData ? {
|
|
169
|
+
spread_cents: spreadData.spreadCents,
|
|
170
|
+
spread_pct: spreadData.spreadPct,
|
|
171
|
+
yes_ask: spreadData.yesAsk,
|
|
172
|
+
yes_bid: spreadData.yesBid,
|
|
173
|
+
} : null,
|
|
174
|
+
ticker: m.market.ticker,
|
|
175
|
+
title: m.market.title,
|
|
176
|
+
volume: {
|
|
177
|
+
volume_24h: m.volume,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
this.formatter.success({
|
|
182
|
+
markets: opportunities,
|
|
183
|
+
opportunities: filtered.length,
|
|
184
|
+
scanned: markets.length,
|
|
185
|
+
stats: {
|
|
186
|
+
avg_liquidity: avgLiquidity,
|
|
187
|
+
avg_spread: avgSpread,
|
|
188
|
+
avg_volume_24h: avgVolume24h,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Human-readable output
|
|
194
|
+
this.log(chalk.cyan.bold('Market Opportunities'));
|
|
195
|
+
this.log();
|
|
196
|
+
this.log(chalk.yellow('Summary:'));
|
|
197
|
+
this.log(` Markets Scanned: ${markets.length}`);
|
|
198
|
+
this.log(` Opportunities Found: ${filtered.length}`);
|
|
199
|
+
this.log(` Avg Liquidity: ${chalk.cyan('$' + avgLiquidity.toFixed(2))}`);
|
|
200
|
+
this.log(` Avg Spread: ${chalk.cyan(avgSpread.toFixed(3))} cents`);
|
|
201
|
+
this.log(` Avg 24h Volume: ${chalk.cyan('$' + avgVolume24h.toFixed(2))}`);
|
|
202
|
+
this.log();
|
|
203
|
+
if (sorted.length > 0) {
|
|
204
|
+
this.log(chalk.yellow('Top Opportunities:'));
|
|
205
|
+
const rows = sorted.slice(0, 20).map(m => {
|
|
206
|
+
const spreadData = m.orderbook ? calculateSpread(m.orderbook) : null;
|
|
207
|
+
return [
|
|
208
|
+
m.market.ticker,
|
|
209
|
+
m.score.toString(),
|
|
210
|
+
spreadData ? spreadData.spreadCents.toFixed(3) : 'N/A',
|
|
211
|
+
'$' + m.liquidity.toFixed(0),
|
|
212
|
+
'$' + m.volume.toFixed(0),
|
|
213
|
+
m.market.title.length > 40 ? m.market.title.slice(0, 37) + '...' : m.market.title,
|
|
214
|
+
];
|
|
215
|
+
});
|
|
216
|
+
this.formatter.outputTable(['Ticker', 'Score', 'Spread', 'Liquidity', '24h Vol', 'Title'], rows);
|
|
217
|
+
if (sorted.length > 20) {
|
|
218
|
+
this.log();
|
|
219
|
+
this.log(chalk.gray(` ... showing top 20 of ${sorted.length} opportunities`));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
this.log(chalk.yellow('No opportunities found matching criteria'));
|
|
224
|
+
}
|
|
225
|
+
this.log();
|
|
226
|
+
this.log(chalk.gray('Tip: Use --json for full data including orderbook details'));
|
|
227
|
+
}
|
|
228
|
+
logger.info({
|
|
229
|
+
filtered: filtered.length,
|
|
230
|
+
scanned: markets.length,
|
|
231
|
+
}, 'Market scan completed');
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../lib/base-command.js';
|
|
2
|
+
export default class PortfolioAnalytics extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
'max-ts': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
'min-ts': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
period: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|