@gaberoo/kalshitools 1.0.3 → 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.
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Market scanning and opportunity detection utilities
3
+ */
4
+ /**
5
+ * Calculate total liquidity from an orderbook
6
+ */
7
+ export function calculateOrderbookLiquidity(orderbook) {
8
+ const yesTotal = orderbook.yes.reduce((sum, level) => sum + level.count * level.price, 0);
9
+ const noTotal = orderbook.no.reduce((sum, level) => sum + level.count * level.price, 0);
10
+ return {
11
+ noTotal,
12
+ total: yesTotal + noTotal,
13
+ yesTotal,
14
+ };
15
+ }
16
+ /**
17
+ * Calculate bid-ask spread from an orderbook
18
+ *
19
+ * In Kalshi orderbooks:
20
+ * - Lower prices in the yes array are bids (buyers)
21
+ * - Higher prices in the yes array are asks (sellers)
22
+ * - Spread = ask - bid
23
+ */
24
+ export function calculateSpread(orderbook) {
25
+ if (orderbook.yes.length === 0) {
26
+ return null;
27
+ }
28
+ const prices = orderbook.yes.map(level => level.price).sort((a, b) => a - b);
29
+ // Best bid is the lowest price (buyers)
30
+ const yesBid = prices[0];
31
+ // Best ask is the highest price (sellers)
32
+ const yesAsk = prices.at(-1);
33
+ if (!yesAsk || !yesBid) {
34
+ return null;
35
+ }
36
+ // If bid and ask are the same, there's no spread
37
+ const spreadCents = yesAsk - yesBid;
38
+ const midPrice = (yesBid + yesAsk) / 2;
39
+ const spreadPct = midPrice > 0 ? (spreadCents / midPrice) * 100 : 0;
40
+ return {
41
+ spreadCents,
42
+ spreadPct,
43
+ yesAsk,
44
+ yesBid,
45
+ };
46
+ }
47
+ const DEFAULT_WEIGHTS = {
48
+ liquidity: 40,
49
+ spread: 30,
50
+ volume: 30,
51
+ };
52
+ /**
53
+ * Score a market based on liquidity, spread, and volume
54
+ * Returns score from 0-100
55
+ */
56
+ export function scoreMarket(market, orderbook, weights = DEFAULT_WEIGHTS) {
57
+ let score = 0;
58
+ // Liquidity score (0-40 points)
59
+ const liquidity = calculateOrderbookLiquidity(orderbook);
60
+ const liquidityScore = Math.min(weights.liquidity, (liquidity.total / 5000) * weights.liquidity);
61
+ score += liquidityScore;
62
+ // Spread score (0-30 points) - wider spreads are better for market making
63
+ const spread = calculateSpread(orderbook);
64
+ if (spread) {
65
+ // Spread between 0.03 (3 cents) and 0.20 (20 cents) is ideal
66
+ const { spreadCents } = spread;
67
+ let spreadScore = 0;
68
+ if (spreadCents >= 0.03 && spreadCents <= 0.2) {
69
+ spreadScore = weights.spread;
70
+ }
71
+ else if (spreadCents > 0.2) {
72
+ // Too wide - gradually decrease score
73
+ spreadScore = Math.max(0, weights.spread * (1 - (spreadCents - 0.2) / 0.3));
74
+ }
75
+ else {
76
+ // Too narrow - gradually decrease score
77
+ spreadScore = (spreadCents / 0.03) * weights.spread;
78
+ }
79
+ score += spreadScore;
80
+ }
81
+ // Volume score (0-30 points)
82
+ const volume = market.volume_24h || market.volume || 0;
83
+ const volumeScore = Math.min(weights.volume, (volume / 10_000) * weights.volume);
84
+ score += volumeScore;
85
+ return Math.round(score);
86
+ }
87
+ /**
88
+ * Classify the type of opportunity a market presents
89
+ */
90
+ export function classifyOpportunity(spread, liquidity, volume) {
91
+ const hasWideSpread = spread >= 0.05;
92
+ const hasHighLiquidity = liquidity >= 2000;
93
+ const hasHighVolume = volume >= 5000;
94
+ // Check combinations
95
+ if (hasWideSpread && hasHighLiquidity && hasHighVolume) {
96
+ return 'balanced';
97
+ }
98
+ if (hasWideSpread) {
99
+ return 'wide_spread';
100
+ }
101
+ if (hasHighLiquidity) {
102
+ return 'high_liquidity';
103
+ }
104
+ if (hasHighVolume) {
105
+ return 'high_volume';
106
+ }
107
+ // Default to balanced if none of the above
108
+ return 'balanced';
109
+ }
110
+ /**
111
+ * Generate human-readable reason for opportunity
112
+ */
113
+ export function generateOpportunityReason(type, spread, liquidity, volume) {
114
+ const spreadCents = Math.round(spread * 100);
115
+ switch (type) {
116
+ case 'balanced': {
117
+ return `Balanced opportunity: ${spreadCents} cent spread, $${Math.round(liquidity)} liquidity, $${Math.round(volume)} volume`;
118
+ }
119
+ case 'high_liquidity': {
120
+ return `Strong liquidity ($${Math.round(liquidity).toLocaleString()})`;
121
+ }
122
+ case 'high_volume': {
123
+ return `High trading volume ($${Math.round(volume).toLocaleString()} 24h)`;
124
+ }
125
+ case 'wide_spread': {
126
+ return `High liquidity with ${spreadCents} cent spread`;
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Filter markets based on criteria
132
+ */
133
+ export function filterMarketsByCriteria(markets, criteria) {
134
+ return markets.filter(m => {
135
+ // Liquidity check
136
+ if (criteria.minLiquidity && m.liquidity < criteria.minLiquidity) {
137
+ return false;
138
+ }
139
+ // Spread checks
140
+ if (m.spread === null) {
141
+ // No spread data - exclude if spread filters are specified
142
+ if (criteria.minSpread || criteria.maxSpread) {
143
+ return false;
144
+ }
145
+ }
146
+ else {
147
+ if (criteria.minSpread && m.spread < criteria.minSpread) {
148
+ return false;
149
+ }
150
+ if (criteria.maxSpread && m.spread > criteria.maxSpread) {
151
+ return false;
152
+ }
153
+ }
154
+ // Volume check
155
+ if (criteria.minVolume && m.volume < criteria.minVolume) {
156
+ return false;
157
+ }
158
+ return true;
159
+ });
160
+ }
@@ -0,0 +1,538 @@
1
+ # Trading Strategies Guide for AI Agents
2
+
3
+ This guide demonstrates how to use kalshitools' advanced analytics and scanning features to implement automated trading strategies. All examples use JSON output for programmatic integration.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Portfolio Analytics](#portfolio-analytics)
8
+ - [Risk Management](#risk-management)
9
+ - [Market Discovery](#market-discovery)
10
+ - [Strategy Examples](#strategy-examples)
11
+ - [Best Practices](#best-practices)
12
+
13
+ ---
14
+
15
+ ## Portfolio Analytics
16
+
17
+ ### Understanding Performance Metrics
18
+
19
+ Get comprehensive portfolio analytics:
20
+
21
+ ```bash
22
+ kalshitools portfolio analytics --period 30 --json
23
+ ```
24
+
25
+ **Key Metrics:**
26
+
27
+ ```json
28
+ {
29
+ "success": true,
30
+ "data": {
31
+ "trades": {
32
+ "total": 45,
33
+ "winning": 28,
34
+ "losing": 17,
35
+ "win_rate": 0.622
36
+ },
37
+ "pnl": {
38
+ "total_pnl": 1250.50,
39
+ "realized_pnl": 980.30,
40
+ "unrealized_pnl": 270.20,
41
+ "avg_win": 85.20,
42
+ "avg_loss": -42.30,
43
+ "total_return_pct": 12.51
44
+ },
45
+ "portfolio": {
46
+ "current_value": 11250.50,
47
+ "exposure": 2750.50,
48
+ "exposure_ratio": 0.244
49
+ },
50
+ "risk": {
51
+ "largest_position_pct": 15.2
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### Strategy Evaluation
58
+
59
+ **Assessing Strategy Effectiveness:**
60
+
61
+ ```bash
62
+ # Get 7-day performance
63
+ kalshitools portfolio analytics --period 7 --json | jq '.data.trades.win_rate'
64
+
65
+ # Get 30-day performance
66
+ kalshitools portfolio analytics --period 30 --json | jq '.data.trades.win_rate'
67
+
68
+ # Compare to determine if strategy is improving
69
+ ```
70
+
71
+ **Key Questions to Answer:**
72
+
73
+ 1. **Is the win rate acceptable?** Target: > 55% for market-making, > 60% for directional
74
+ 2. **Is the average win > average loss?** Positive expectancy requires this
75
+ 3. **Is exposure ratio appropriate?** < 50% for conservative, < 80% for aggressive
76
+ 4. **Are fees eating into profits?** Monitor `fee_impact_pct`
77
+
78
+ ---
79
+
80
+ ## Risk Management
81
+
82
+ ### Real-Time Risk Assessment
83
+
84
+ Check portfolio risk before adding new positions:
85
+
86
+ ```bash
87
+ kalshitools portfolio risk --threshold 20 --json
88
+ ```
89
+
90
+ **Response:**
91
+
92
+ ```json
93
+ {
94
+ "success": true,
95
+ "data": {
96
+ "risk_score": 45,
97
+ "risk_level": "MEDIUM",
98
+ "total_exposure": 2750.50,
99
+ "exposure_ratio": 0.244,
100
+ "concentrations": {
101
+ "by_ticker": [
102
+ {
103
+ "ticker": "MARKET-A",
104
+ "exposure": 1710.00,
105
+ "pct_of_portfolio": 15.2,
106
+ "alert": false
107
+ }
108
+ ]
109
+ },
110
+ "alerts": [],
111
+ "recommendations": {
112
+ "max_new_position_size": 2250.00
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### Position Sizing Strategy
119
+
120
+ **Before Opening a Position:**
121
+
122
+ ```bash
123
+ # Check recommended max position size
124
+ MAX_SIZE=$(kalshitools portfolio risk --json | jq -r '.data.recommendations.max_new_position_size')
125
+
126
+ # Use this to size your order
127
+ kalshitools orders create \
128
+ --ticker MARKET-A \
129
+ --action buy \
130
+ --side yes \
131
+ --quantity $(echo "$MAX_SIZE / 0.50" | bc) \
132
+ --type limit \
133
+ --price 0.50
134
+ ```
135
+
136
+ ### Correlation Monitoring
137
+
138
+ Detect correlated positions (multiple positions in same event):
139
+
140
+ ```bash
141
+ kalshitools portfolio risk --group-by event --json | jq '.data.correlations'
142
+ ```
143
+
144
+ **Use Case:**
145
+ - Avoid over-exposure to single events
146
+ - Diversify across uncorrelated markets
147
+ - Reduce systematic risk
148
+
149
+ ---
150
+
151
+ ## Market Discovery
152
+
153
+ ### Finding Trading Opportunities
154
+
155
+ Scan markets for high-quality opportunities:
156
+
157
+ ```bash
158
+ kalshitools markets scan \
159
+ --min-liquidity 200 \
160
+ --min-spread 0.05 \
161
+ --max-spread 0.20 \
162
+ --min-volume 1000 \
163
+ --sort-by score \
164
+ --limit 20 \
165
+ --json
166
+ ```
167
+
168
+ **Response:**
169
+
170
+ ```json
171
+ {
172
+ "success": true,
173
+ "data": {
174
+ "markets": [
175
+ {
176
+ "ticker": "MARKET-A",
177
+ "score": 85.5,
178
+ "spread": {
179
+ "yes_bid": 0.62,
180
+ "yes_ask": 0.68,
181
+ "spread_cents": 0.06
182
+ },
183
+ "liquidity": {
184
+ "total": 2430.00
185
+ },
186
+ "volume": {
187
+ "volume_24h": 8500.00
188
+ },
189
+ "opportunity_type": "wide_spread"
190
+ }
191
+ ]
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### Market-Making Strategy
197
+
198
+ **Criteria for Market-Making:**
199
+ - Wide spreads (> 0.05): Room for profit
200
+ - High liquidity (> 200): Can enter/exit easily
201
+ - Active volume (> 1000): Market is moving
202
+
203
+ **Implementation:**
204
+
205
+ ```bash
206
+ # Find markets with wide spreads
207
+ MARKETS=$(kalshitools markets scan \
208
+ --min-spread 0.05 \
209
+ --min-liquidity 300 \
210
+ --sort-by spread \
211
+ --json | jq -r '.data.markets[].ticker')
212
+
213
+ # For each market, place limit orders on both sides
214
+ for TICKER in $MARKETS; do
215
+ # Get current orderbook
216
+ ORDERBOOK=$(kalshitools markets orderbook $TICKER --json)
217
+
218
+ # Calculate fair value and place orders
219
+ # (implementation depends on your pricing model)
220
+ done
221
+ ```
222
+
223
+ ### Arbitrage Scanner
224
+
225
+ Look for mispriced markets within the same event:
226
+
227
+ ```bash
228
+ # Get all markets in an event
229
+ EVENT_MARKETS=$(kalshitools markets list \
230
+ --event-ticker EVENT-2024 \
231
+ --status active \
232
+ --json)
233
+
234
+ # Scan for opportunities
235
+ kalshitools markets scan \
236
+ --event-ticker EVENT-2024 \
237
+ --min-liquidity 100 \
238
+ --json | jq '.data.markets[] | select(.spread.spread_cents > 0.10)'
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Strategy Examples
244
+
245
+ ### 1. Mean Reversion Strategy
246
+
247
+ **Goal:** Buy when price drops below historical average, sell when it rises above.
248
+
249
+ **Implementation:**
250
+
251
+ ```bash
252
+ # Step 1: Get historical performance for a ticker
253
+ HISTORY=$(kalshitools portfolio history \
254
+ --ticker MARKET-A \
255
+ --group-by day \
256
+ --json)
257
+
258
+ # Step 2: Calculate average price (pseudocode)
259
+ AVG_PRICE=$(echo "$HISTORY" | jq '[.data.time_series.daily[].avg_price] | add / length')
260
+
261
+ # Step 3: Get current price
262
+ CURRENT_PRICE=$(kalshitools markets show MARKET-A --json | jq '.data.yes_bid')
263
+
264
+ # Step 4: Trade if deviation > threshold
265
+ if (( $(echo "$CURRENT_PRICE < $AVG_PRICE * 0.9" | bc -l) )); then
266
+ # Price is 10% below average - buy
267
+ kalshitools orders create --ticker MARKET-A --action buy --side yes ...
268
+ fi
269
+ ```
270
+
271
+ ### 2. Momentum Strategy
272
+
273
+ **Goal:** Follow trends by trading in the direction of recent price movement.
274
+
275
+ **Implementation:**
276
+
277
+ ```bash
278
+ # Get recent trading activity
279
+ HISTORY=$(kalshitools portfolio history \
280
+ --ticker MARKET-A \
281
+ --group-by day \
282
+ --limit 10 \
283
+ --json)
284
+
285
+ # Calculate momentum indicators
286
+ # - Volume trend (increasing = strong momentum)
287
+ # - Price trend (rising = bullish, falling = bearish)
288
+
289
+ # Trade with the trend
290
+ # (implementation depends on your momentum calculation)
291
+ ```
292
+
293
+ ### 3. Portfolio Rebalancing
294
+
295
+ **Goal:** Maintain target exposure levels and concentration limits.
296
+
297
+ **Implementation:**
298
+
299
+ ```bash
300
+ # Step 1: Check current risk
301
+ RISK=$(kalshitools portfolio risk --threshold 15 --json)
302
+
303
+ # Step 2: Identify over-concentrated positions
304
+ OVER_LIMIT=$(echo "$RISK" | jq -r '.data.concentrations.by_ticker[] | select(.alert == true) | .name')
305
+
306
+ # Step 3: Reduce positions that exceed threshold
307
+ for TICKER in $OVER_LIMIT; do
308
+ # Get current position
309
+ POSITION=$(kalshitools portfolio positions --json | \
310
+ jq -r ".data[] | select(.ticker == \"$TICKER\") | .position")
311
+
312
+ # Calculate amount to sell to reach target (15%)
313
+ TARGET_SIZE=$(echo "$RISK" | jq -r '.data.recommendations.max_new_position_size')
314
+
315
+ # Place sell order to reduce position
316
+ kalshitools orders create \
317
+ --ticker $TICKER \
318
+ --action sell \
319
+ --side yes \
320
+ --quantity $REDUCE_BY \
321
+ --type market
322
+ done
323
+ ```
324
+
325
+ ### 4. Statistical Arbitrage
326
+
327
+ **Goal:** Exploit pricing inefficiencies between correlated markets.
328
+
329
+ **Implementation:**
330
+
331
+ ```bash
332
+ # Step 1: Find correlated markets in same event
333
+ kalshitools markets list --event-ticker EVENT-2024 --json
334
+
335
+ # Step 2: Compare prices and liquidity
336
+ kalshitools markets scan --event-ticker EVENT-2024 --json
337
+
338
+ # Step 3: Identify spread > expected
339
+ # If Market A + Market B should sum to 1.00, but sum to 1.10:
340
+ # - Sell the overpriced side
341
+ # - Buy the underpriced side
342
+ # - Profit from convergence
343
+ ```
344
+
345
+ ---
346
+
347
+ ## Best Practices
348
+
349
+ ### 1. Pre-Trade Risk Checks
350
+
351
+ **Always check risk before trading:**
352
+
353
+ ```bash
354
+ # Create a pre-trade checklist function
355
+ pre_trade_check() {
356
+ TICKER=$1
357
+ SIZE=$2
358
+
359
+ # Check 1: Portfolio risk
360
+ RISK_SCORE=$(kalshitools portfolio risk --json | jq -r '.data.risk_score')
361
+ if (( $(echo "$RISK_SCORE > 70" | bc -l) )); then
362
+ echo "ERROR: Portfolio risk too high ($RISK_SCORE/100)"
363
+ return 1
364
+ fi
365
+
366
+ # Check 2: Position size limit
367
+ MAX_SIZE=$(kalshitools portfolio risk --json | jq -r '.data.recommendations.max_new_position_size')
368
+ if (( $(echo "$SIZE > $MAX_SIZE" | bc -l) )); then
369
+ echo "ERROR: Position size exceeds limit ($SIZE > $MAX_SIZE)"
370
+ return 1
371
+ fi
372
+
373
+ # Check 3: Market liquidity
374
+ LIQUIDITY=$(kalshitools markets orderbook $TICKER --json | jq -r '.data.liquidity')
375
+ if (( $(echo "$LIQUIDITY < 100" | bc -l) )); then
376
+ echo "ERROR: Insufficient liquidity ($LIQUIDITY)"
377
+ return 1
378
+ fi
379
+
380
+ echo "Pre-trade checks passed"
381
+ return 0
382
+ }
383
+
384
+ # Use before every trade
385
+ if pre_trade_check "MARKET-A" 500; then
386
+ kalshitools orders create --ticker MARKET-A ...
387
+ fi
388
+ ```
389
+
390
+ ### 2. Performance Monitoring
391
+
392
+ **Regular strategy evaluation:**
393
+
394
+ ```bash
395
+ # Daily: Check win rate and P&L
396
+ kalshitools portfolio analytics --period 1 --json > daily_analytics.json
397
+
398
+ # Weekly: Compare to baseline
399
+ kalshitools portfolio analytics --period 7 --json > weekly_analytics.json
400
+
401
+ # Monthly: Full performance review
402
+ kalshitools portfolio analytics --period 30 --json > monthly_analytics.json
403
+
404
+ # Track metrics over time
405
+ echo "$(date),$(jq -r '.data.trades.win_rate' daily_analytics.json)" >> performance_log.csv
406
+ ```
407
+
408
+ ### 3. Diversification
409
+
410
+ **Spread risk across multiple markets:**
411
+
412
+ ```bash
413
+ # Target: No single position > 20% of portfolio
414
+ kalshitools portfolio risk --threshold 20 --json
415
+
416
+ # Target: Max 3 positions per event
417
+ kalshitools portfolio risk --group-by event --json | \
418
+ jq '.data.concentrations.by_event[] | select(.markets | length > 3)'
419
+
420
+ # Rebalance if limits exceeded
421
+ ```
422
+
423
+ ### 4. Fee Optimization
424
+
425
+ **Prefer maker orders to minimize fees:**
426
+
427
+ ```bash
428
+ # Check maker vs taker ratio
429
+ kalshitools portfolio history --json | jq '.data.maker_taker'
430
+
431
+ # Target: > 70% maker fills for optimal fee structure
432
+ # Maker fee: 0.5%, Taker fee: 1.5%
433
+ # Use limit orders instead of market orders when possible
434
+ ```
435
+
436
+ ### 5. Rate Limiting
437
+
438
+ **Respect API rate limits (20 req/sec for reads, 10 req/sec for writes):**
439
+
440
+ ```bash
441
+ # Use sleep between API calls
442
+ for TICKER in $TICKERS; do
443
+ kalshitools markets show $TICKER --json
444
+ sleep 0.1 # 100ms delay = max 10 req/sec
445
+ done
446
+
447
+ # Batch requests when possible
448
+ kalshitools markets list --tickers "TICKER1,TICKER2,TICKER3" --json
449
+ ```
450
+
451
+ ---
452
+
453
+ ## Integration with OpenClaw
454
+
455
+ kalshitools is designed for seamless integration with AI trading agents:
456
+
457
+ ```python
458
+ import subprocess
459
+ import json
460
+
461
+ class KalshiAgent:
462
+ def get_analytics(self, period=30):
463
+ """Get portfolio analytics"""
464
+ result = subprocess.run(
465
+ ['kalshitools', 'portfolio', 'analytics',
466
+ '--period', str(period), '--json'],
467
+ capture_output=True, text=True
468
+ )
469
+ return json.loads(result.stdout)
470
+
471
+ def check_risk(self, threshold=20):
472
+ """Check portfolio risk"""
473
+ result = subprocess.run(
474
+ ['kalshitools', 'portfolio', 'risk',
475
+ '--threshold', str(threshold), '--json'],
476
+ capture_output=True, text=True
477
+ )
478
+ return json.loads(result.stdout)
479
+
480
+ def scan_markets(self, min_liquidity=200, min_spread=0.05):
481
+ """Scan for opportunities"""
482
+ result = subprocess.run(
483
+ ['kalshitools', 'markets', 'scan',
484
+ '--min-liquidity', str(min_liquidity),
485
+ '--min-spread', str(min_spread),
486
+ '--json'],
487
+ capture_output=True, text=True
488
+ )
489
+ return json.loads(result.stdout)
490
+
491
+ def make_decision(self):
492
+ """Example trading decision logic"""
493
+ # Get current portfolio state
494
+ analytics = self.get_analytics(period=7)
495
+ risk = self.check_risk(threshold=20)
496
+
497
+ # Check if we should trade
498
+ if analytics['data']['trades']['win_rate'] < 0.5:
499
+ return "SKIP", "Win rate too low"
500
+
501
+ if risk['data']['risk_score'] > 70:
502
+ return "SKIP", "Portfolio risk too high"
503
+
504
+ # Find opportunities
505
+ opportunities = self.scan_markets()
506
+
507
+ if len(opportunities['data']['markets']) == 0:
508
+ return "SKIP", "No opportunities found"
509
+
510
+ # Take best opportunity
511
+ best = opportunities['data']['markets'][0]
512
+ max_size = risk['data']['recommendations']['max_new_position_size']
513
+
514
+ return "TRADE", {
515
+ 'ticker': best['ticker'],
516
+ 'size': max_size,
517
+ 'reason': best['reason']
518
+ }
519
+ ```
520
+
521
+ ---
522
+
523
+ ## Summary
524
+
525
+ kalshitools provides four key capabilities for automated trading:
526
+
527
+ 1. **Portfolio Analytics**: Measure strategy performance
528
+ 2. **Risk Management**: Control exposure and concentration
529
+ 3. **Historical Analysis**: Learn from past trades
530
+ 4. **Market Scanner**: Discover opportunities systematically
531
+
532
+ All commands output structured JSON for easy integration with AI agents and automated systems.
533
+
534
+ **Next Steps:**
535
+ - Start with manual exploration using the CLI
536
+ - Build analytics dashboards using the JSON output
537
+ - Implement automated strategies with proper risk controls
538
+ - Monitor performance and iterate on your approach