@gaberoo/kalshitools 1.0.2 → 1.1.0

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.
Files changed (61) hide show
  1. package/README.md +328 -27
  2. package/dist/commands/config/init.js +4 -4
  3. package/dist/commands/config/show.js +5 -5
  4. package/dist/commands/markets/list.d.ts +5 -1
  5. package/dist/commands/markets/list.js +28 -8
  6. package/dist/commands/markets/orderbook.d.ts +13 -0
  7. package/dist/commands/markets/orderbook.js +83 -0
  8. package/dist/commands/markets/scan.d.ts +18 -0
  9. package/dist/commands/markets/scan.js +237 -0
  10. package/dist/commands/markets/show.d.ts +3 -3
  11. package/dist/commands/markets/show.js +7 -7
  12. package/dist/commands/orders/cancel.d.ts +3 -3
  13. package/dist/commands/orders/cancel.js +7 -7
  14. package/dist/commands/orders/create.d.ts +5 -5
  15. package/dist/commands/orders/create.js +33 -33
  16. package/dist/commands/orders/list.d.ts +1 -1
  17. package/dist/commands/orders/list.js +9 -9
  18. package/dist/commands/portfolio/analytics.d.ts +12 -0
  19. package/dist/commands/portfolio/analytics.js +192 -0
  20. package/dist/commands/portfolio/fills.d.ts +1 -1
  21. package/dist/commands/portfolio/fills.js +7 -7
  22. package/dist/commands/portfolio/history.d.ts +14 -0
  23. package/dist/commands/portfolio/history.js +245 -0
  24. package/dist/commands/portfolio/positions.d.ts +1 -0
  25. package/dist/commands/portfolio/positions.js +11 -2
  26. package/dist/commands/portfolio/risk.d.ts +11 -0
  27. package/dist/commands/portfolio/risk.js +206 -0
  28. package/dist/lib/analytics.d.ts +64 -0
  29. package/dist/lib/analytics.js +236 -0
  30. package/dist/lib/base-command.d.ts +2 -2
  31. package/dist/lib/base-command.js +8 -8
  32. package/dist/lib/config/manager.d.ts +25 -25
  33. package/dist/lib/config/manager.js +51 -51
  34. package/dist/lib/config/schema.d.ts +11 -11
  35. package/dist/lib/config/schema.js +6 -6
  36. package/dist/lib/errors/base.d.ts +10 -10
  37. package/dist/lib/errors/base.js +7 -7
  38. package/dist/lib/kalshi/auth.d.ts +4 -4
  39. package/dist/lib/kalshi/auth.js +24 -24
  40. package/dist/lib/kalshi/client.d.ts +35 -35
  41. package/dist/lib/kalshi/client.js +93 -91
  42. package/dist/lib/kalshi/index.d.ts +1 -1
  43. package/dist/lib/kalshi/index.js +1 -1
  44. package/dist/lib/kalshi/types.d.ts +53 -53
  45. package/dist/lib/logger.js +3 -3
  46. package/dist/lib/output/formatter.d.ts +20 -20
  47. package/dist/lib/output/formatter.js +55 -55
  48. package/dist/lib/retry.d.ts +2 -2
  49. package/dist/lib/retry.js +8 -10
  50. package/dist/lib/risk.d.ts +51 -0
  51. package/dist/lib/risk.js +153 -0
  52. package/dist/lib/sanitize.js +9 -9
  53. package/dist/lib/scanner.d.ts +58 -0
  54. package/dist/lib/scanner.js +160 -0
  55. package/dist/lib/shutdown.d.ts +4 -4
  56. package/dist/lib/shutdown.js +7 -7
  57. package/dist/lib/validation.d.ts +5 -5
  58. package/dist/lib/validation.js +14 -20
  59. package/docs/TRADING_STRATEGIES.md +538 -0
  60. package/oclif.manifest.json +559 -170
  61. package/package.json +1 -1
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../lib/base-command.js';
2
+ export default class MarketsOrderbook extends BaseCommand {
3
+ static args: {
4
+ ticker: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ depth: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,83 @@
1
+ import { Args, 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
+ export default class MarketsOrderbook extends BaseCommand {
7
+ static args = {
8
+ ticker: Args.string({
9
+ description: 'Market ticker symbol',
10
+ required: true,
11
+ }),
12
+ };
13
+ static description = 'Show order book for a market';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %> TICKER',
16
+ '<%= config.bin %> <%= command.id %> TICKER --depth 5',
17
+ '<%= config.bin %> <%= command.id %> TICKER --json',
18
+ ];
19
+ static flags = {
20
+ ...BaseCommand.baseFlags,
21
+ depth: Flags.integer({
22
+ default: 10,
23
+ description: 'Number of price levels to show',
24
+ }),
25
+ };
26
+ async run() {
27
+ const { args, flags } = await this.parse(MarketsOrderbook);
28
+ try {
29
+ // Create API client from configuration
30
+ const client = createClientFromConfig();
31
+ // Fetch order book
32
+ const orderbook = await client.getOrderBook(args.ticker, flags.depth);
33
+ if (this.formatter.isJSONMode()) {
34
+ this.formatter.success(orderbook);
35
+ }
36
+ else {
37
+ // Human-readable output
38
+ this.log(chalk.cyan.bold(`Order Book: ${orderbook.ticker}`));
39
+ this.log();
40
+ // YES Side (Buy)
41
+ this.log(chalk.green.bold('YES Side (Buy)'));
42
+ if (orderbook.yes.length === 0) {
43
+ this.log(chalk.gray(' No orders'));
44
+ }
45
+ else {
46
+ const yesRows = orderbook.yes.map((level) => [
47
+ level.price.toFixed(2),
48
+ level.count.toString(),
49
+ (level.price * level.count).toFixed(2),
50
+ ]);
51
+ this.formatter.outputTable(['Price', 'Quantity', 'Total'], yesRows);
52
+ }
53
+ this.log();
54
+ // NO Side (Sell)
55
+ this.log(chalk.red.bold('NO Side (Sell)'));
56
+ if (orderbook.no.length === 0) {
57
+ this.log(chalk.gray(' No orders'));
58
+ }
59
+ else {
60
+ const noRows = orderbook.no.map((level) => [
61
+ level.price.toFixed(2),
62
+ level.count.toString(),
63
+ (level.price * level.count).toFixed(2),
64
+ ]);
65
+ this.formatter.outputTable(['Price', 'Quantity', 'Total'], noRows);
66
+ }
67
+ // Calculate and display spread if both sides have orders
68
+ if (orderbook.yes.length > 0 && orderbook.no.length > 0) {
69
+ const bestYes = orderbook.yes[0].price;
70
+ const bestNo = orderbook.no[0].price;
71
+ const spread = Math.abs(bestYes - bestNo);
72
+ const spreadPct = ((spread / ((bestYes + bestNo) / 2)) * 100).toFixed(1);
73
+ this.log();
74
+ this.log(`${chalk.cyan('Spread:')} ${spread.toFixed(2)} (${spreadPct}%)`);
75
+ }
76
+ }
77
+ logger.info({ depth: flags.depth, ticker: args.ticker }, 'Order book fetched successfully');
78
+ }
79
+ catch (error) {
80
+ throw error;
81
+ }
82
+ }
83
+ }
@@ -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
+ }
@@ -1,13 +1,13 @@
1
1
  import { BaseCommand } from '../../lib/base-command.js';
2
2
  export default class MarketsShow extends BaseCommand {
3
+ static args: {
4
+ ticker: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
3
6
  static description: string;
4
7
  static examples: string[];
5
8
  static flags: {
6
9
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
10
  };
8
- static args: {
9
- ticker: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
10
- };
11
11
  run(): Promise<void>;
12
12
  private formatStatus;
13
13
  }
@@ -4,6 +4,12 @@ import { BaseCommand } from '../../lib/base-command.js';
4
4
  import { createClientFromConfig } from '../../lib/kalshi/index.js';
5
5
  import { logger } from '../../lib/logger.js';
6
6
  export default class MarketsShow extends BaseCommand {
7
+ static args = {
8
+ ticker: Args.string({
9
+ description: 'Market ticker symbol',
10
+ required: true,
11
+ }),
12
+ };
7
13
  static description = 'Show market details';
8
14
  static examples = [
9
15
  '<%= config.bin %> <%= command.id %> TICKER',
@@ -12,12 +18,6 @@ export default class MarketsShow extends BaseCommand {
12
18
  static flags = {
13
19
  ...BaseCommand.baseFlags,
14
20
  };
15
- static args = {
16
- ticker: Args.string({
17
- description: 'Market ticker symbol',
18
- required: true,
19
- }),
20
- };
21
21
  async run() {
22
22
  const { args } = await this.parse(MarketsShow);
23
23
  try {
@@ -70,8 +70,8 @@ export default class MarketsShow extends BaseCommand {
70
70
  const colors = {
71
71
  active: chalk.green,
72
72
  closed: chalk.yellow,
73
- settled: chalk.blue,
74
73
  finalized: chalk.gray,
74
+ settled: chalk.blue,
75
75
  };
76
76
  const colorFn = colors[status] || chalk.white;
77
77
  return colorFn(status);
@@ -1,14 +1,14 @@
1
1
  import { BaseCommand } from '../../lib/base-command.js';
2
2
  export default class OrdersCancel extends BaseCommand {
3
+ static args: {
4
+ orderId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
3
6
  static description: string;
4
7
  static examples: string[];
5
8
  static flags: {
6
9
  yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
10
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
11
  };
9
- static args: {
10
- orderId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
11
- };
12
12
  run(): Promise<void>;
13
13
  private confirm;
14
14
  }
@@ -5,6 +5,12 @@ import { getConfig } from '../../lib/config/manager.js';
5
5
  import { createClientFromConfig } from '../../lib/kalshi/index.js';
6
6
  import { logger } from '../../lib/logger.js';
7
7
  export default class OrdersCancel extends BaseCommand {
8
+ static args = {
9
+ orderId: Args.string({
10
+ description: 'Order ID to cancel',
11
+ required: true,
12
+ }),
13
+ };
8
14
  static description = 'Cancel an order';
9
15
  static examples = [
10
16
  '<%= config.bin %> <%= command.id %> ORDER_ID',
@@ -15,14 +21,8 @@ export default class OrdersCancel extends BaseCommand {
15
21
  ...BaseCommand.baseFlags,
16
22
  yes: Flags.boolean({
17
23
  char: 'y',
18
- description: 'Skip confirmation prompt',
19
24
  default: false,
20
- }),
21
- };
22
- static args = {
23
- orderId: Args.string({
24
- description: 'Order ID to cancel',
25
- required: true,
25
+ description: 'Skip confirmation prompt',
26
26
  }),
27
27
  };
28
28
  async run() {
@@ -3,17 +3,17 @@ export default class OrdersCreate extends BaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
- ticker: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
6
  action: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
- side: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ price: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
9
  quantity: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ side: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ ticker: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
12
  type: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
- price: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
13
  yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
- 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
14
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
15
  };
16
16
  run(): Promise<void>;
17
- private formatStatus;
18
17
  private confirm;
18
+ private formatStatus;
19
19
  }
@@ -16,45 +16,45 @@ export default class OrdersCreate extends BaseCommand {
16
16
  ];
17
17
  static flags = {
18
18
  ...BaseCommand.baseFlags,
19
- ticker: Flags.string({
20
- char: 't',
21
- description: 'Market ticker symbol',
22
- required: true,
23
- }),
24
19
  action: Flags.string({
25
20
  char: 'a',
26
21
  description: 'Order action (buy or sell)',
27
22
  options: ['buy', 'sell'],
28
23
  required: true,
29
24
  }),
25
+ 'dry-run': Flags.boolean({
26
+ default: false,
27
+ description: 'Simulate the order without actually placing it',
28
+ }),
29
+ price: Flags.string({
30
+ char: 'p',
31
+ description: 'Limit price (required for limit orders, 0.01-0.99)',
32
+ }),
33
+ quantity: Flags.integer({
34
+ char: 'q',
35
+ description: 'Number of contracts',
36
+ required: true,
37
+ }),
30
38
  side: Flags.string({
31
39
  char: 's',
32
40
  description: 'Contract side (yes or no)',
33
41
  options: ['yes', 'no'],
34
42
  required: true,
35
43
  }),
36
- quantity: Flags.integer({
37
- char: 'q',
38
- description: 'Number of contracts',
44
+ ticker: Flags.string({
45
+ char: 't',
46
+ description: 'Market ticker symbol',
39
47
  required: true,
40
48
  }),
41
49
  type: Flags.string({
50
+ default: 'market',
42
51
  description: 'Order type (market or limit)',
43
52
  options: ['market', 'limit'],
44
- default: 'market',
45
- }),
46
- price: Flags.string({
47
- char: 'p',
48
- description: 'Limit price (required for limit orders, 0.01-0.99)',
49
53
  }),
50
54
  yes: Flags.boolean({
51
55
  char: 'y',
52
- description: 'Skip confirmation prompt',
53
- default: false,
54
- }),
55
- 'dry-run': Flags.boolean({
56
- description: 'Simulate the order without actually placing it',
57
56
  default: false,
57
+ description: 'Skip confirmation prompt',
58
58
  }),
59
59
  };
60
60
  async run() {
@@ -84,10 +84,10 @@ export default class OrdersCreate extends BaseCommand {
84
84
  const costEstimate = estimateOrderCost(side, action, flags.quantity, price);
85
85
  // Build order request
86
86
  const orderRequest = {
87
- ticker: flags.ticker,
88
- side,
89
87
  action,
90
88
  count: flags.quantity,
89
+ side,
90
+ ticker: flags.ticker,
91
91
  type: orderType,
92
92
  };
93
93
  if (orderType === 'limit' && price) {
@@ -132,16 +132,16 @@ export default class OrdersCreate extends BaseCommand {
132
132
  if (flags['dry-run']) {
133
133
  if (this.formatter.isJSONMode()) {
134
134
  this.formatter.success({
135
+ costEstimate,
135
136
  dryRun: true,
136
137
  order: orderRequest,
137
- costEstimate,
138
138
  });
139
139
  }
140
140
  else {
141
141
  this.log(chalk.yellow('DRY RUN - Order not placed'));
142
142
  this.log(chalk.gray('Order would be submitted with the parameters above'));
143
143
  }
144
- logger.info({ orderRequest, dryRun: true }, 'Dry run order');
144
+ logger.info({ dryRun: true, orderRequest }, 'Dry run order');
145
145
  return;
146
146
  }
147
147
  // Confirmation prompt (unless --yes flag or JSON mode)
@@ -187,17 +187,6 @@ export default class OrdersCreate extends BaseCommand {
187
187
  throw error;
188
188
  }
189
189
  }
190
- formatStatus(status) {
191
- const colors = {
192
- executed: chalk.green,
193
- pending: chalk.yellow,
194
- resting: chalk.cyan,
195
- canceled: chalk.gray,
196
- expired: chalk.red,
197
- };
198
- const colorFn = colors[status] || chalk.white;
199
- return colorFn(status);
200
- }
201
190
  async confirm(message) {
202
191
  const readline = await import('node:readline/promises');
203
192
  const rl = readline.createInterface({
@@ -208,4 +197,15 @@ export default class OrdersCreate extends BaseCommand {
208
197
  rl.close();
209
198
  return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
210
199
  }
200
+ formatStatus(status) {
201
+ const colors = {
202
+ canceled: chalk.gray,
203
+ executed: chalk.green,
204
+ expired: chalk.red,
205
+ pending: chalk.yellow,
206
+ resting: chalk.cyan,
207
+ };
208
+ const colorFn = colors[status] || chalk.white;
209
+ return colorFn(status);
210
+ }
211
211
  }
@@ -3,9 +3,9 @@ export default class OrdersList extends BaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
6
7
  status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
8
  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
9
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
10
  };
11
11
  run(): Promise<void>;
@@ -13,6 +13,10 @@ export default class OrdersList extends BaseCommand {
13
13
  ];
14
14
  static flags = {
15
15
  ...BaseCommand.baseFlags,
16
+ limit: Flags.integer({
17
+ default: 50,
18
+ description: 'Maximum number of orders to return',
19
+ }),
16
20
  status: Flags.string({
17
21
  description: 'Filter by order status',
18
22
  options: ['pending', 'resting', 'canceled', 'executed', 'expired'],
@@ -20,10 +24,6 @@ export default class OrdersList extends BaseCommand {
20
24
  ticker: Flags.string({
21
25
  description: 'Filter by ticker',
22
26
  }),
23
- limit: Flags.integer({
24
- description: 'Maximum number of orders to return',
25
- default: 50,
26
- }),
27
27
  };
28
28
  async run() {
29
29
  const { flags } = await this.parse(OrdersList);
@@ -32,13 +32,13 @@ export default class OrdersList extends BaseCommand {
32
32
  const client = createClientFromConfig();
33
33
  // Fetch orders
34
34
  const result = await client.getOrders({
35
+ limit: flags.limit,
35
36
  status: flags.status,
36
37
  ticker: flags.ticker,
37
- limit: flags.limit,
38
38
  });
39
- const orders = result.orders;
39
+ const { orders } = result;
40
40
  if (this.formatter.isJSONMode()) {
41
- this.formatter.success({ orders, cursor: result.cursor });
41
+ this.formatter.success({ cursor: result.cursor, orders });
42
42
  }
43
43
  else {
44
44
  if (orders.length === 0) {
@@ -80,11 +80,11 @@ export default class OrdersList extends BaseCommand {
80
80
  }
81
81
  formatStatus(status) {
82
82
  const colors = {
83
+ canceled: chalk.gray,
83
84
  executed: chalk.green,
85
+ expired: chalk.red,
84
86
  pending: chalk.yellow,
85
87
  resting: chalk.cyan,
86
- canceled: chalk.gray,
87
- expired: chalk.red,
88
88
  };
89
89
  const colorFn = colors[status] || chalk.white;
90
90
  return colorFn(status);