claude-evolve 1.3.43 → 1.4.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.
@@ -26,11 +26,43 @@ get_model_for_generation() {
26
26
  gen_num=1 # Default for malformed input
27
27
  fi
28
28
 
29
- # Alternate between models by generation
30
- if (( gen_num % 2 == 1 )); then
31
- echo "opus" # Odd generations: use Opus for exploration
29
+ # Check which AI tools are available
30
+ local has_o3=false
31
+ local has_gemini=false
32
+
33
+ if command -v codex >/dev/null 2>&1; then
34
+ has_o3=true
35
+ fi
36
+
37
+ if command -v gemini >/dev/null 2>&1; then
38
+ has_gemini=true
39
+ fi
40
+
41
+ # Determine rotation based on what's available
42
+ if [[ "$has_o3" == "true" && "$has_gemini" == "true" ]]; then
43
+ # All three available: opus -> o3 -> gemini rotation
44
+ case $((gen_num % 3)) in
45
+ 1) echo "opus" ;; # 1, 4, 7, 10...
46
+ 2) echo "o3" ;; # 2, 5, 8, 11...
47
+ 0) echo "gemini" ;; # 3, 6, 9, 12...
48
+ esac
49
+ elif [[ "$has_o3" == "true" ]]; then
50
+ # Only opus and o3: alternate between them
51
+ if (( gen_num % 2 == 1 )); then
52
+ echo "opus" # Odd generations
53
+ else
54
+ echo "o3" # Even generations
55
+ fi
56
+ elif [[ "$has_gemini" == "true" ]]; then
57
+ # Only opus and gemini: alternate between them
58
+ if (( gen_num % 2 == 1 )); then
59
+ echo "opus" # Odd generations
60
+ else
61
+ echo "gemini" # Even generations
62
+ fi
32
63
  else
33
- echo "o3" # Even generations: use o3 for refinement
64
+ # Only opus available
65
+ echo "opus"
34
66
  fi
35
67
  }
36
68
 
@@ -55,10 +87,67 @@ call_ai_with_limit_check() {
55
87
  local ai_exit_code=$?
56
88
 
57
89
  if [[ $ai_exit_code -eq 0 ]]; then
58
- echo "$ai_output"
59
- return 0
90
+ # Clean o3 output - it may be JSON with the response in a field
91
+ local cleaned_output
92
+ # Try to extract content from JSON response if present
93
+ if echo "$ai_output" | grep -q '"content"'; then
94
+ # Attempt to extract content field from JSON
95
+ cleaned_output=$(echo "$ai_output" | python3 -c "
96
+ import sys
97
+ import json
98
+ try:
99
+ data = json.load(sys.stdin)
100
+ if 'content' in data:
101
+ print(data['content'])
102
+ elif 'response' in data:
103
+ print(data['response'])
104
+ elif 'text' in data:
105
+ print(data['text'])
106
+ else:
107
+ # If no known field, print the whole thing
108
+ print(json.dumps(data))
109
+ except:
110
+ # If not valid JSON, print as-is
111
+ print(sys.stdin.read())
112
+ " 2>/dev/null || echo "$ai_output")
113
+ else
114
+ cleaned_output="$ai_output"
115
+ fi
116
+
117
+ # Validate the output is not empty and doesn't contain error messages
118
+ if [[ -n "$cleaned_output" ]] && ! echo "$cleaned_output" | grep -q "error\|failed\|exception"; then
119
+ echo "$cleaned_output"
120
+ return 0
121
+ else
122
+ echo "[WARN] Codex o3 returned invalid output, falling back to Claude Opus" >&2
123
+ preferred_model="opus"
124
+ fi
125
+ else
126
+ echo "[WARN] Codex o3 failed with exit code $ai_exit_code, falling back to Claude Opus" >&2
127
+ preferred_model="opus"
128
+ fi
129
+ elif [[ "$preferred_model" == "gemini" ]] && command -v gemini >/dev/null 2>&1; then
130
+ echo "[INFO] Using gemini 2.5 pro for ideation" >&2
131
+
132
+ # Call gemini with -y and -p flags
133
+ local ai_output
134
+ ai_output=$(gemini -y -p "$prompt" 2>&1)
135
+ local ai_exit_code=$?
136
+
137
+ if [[ $ai_exit_code -eq 0 ]]; then
138
+ # Check for authentication messages or other non-response content
139
+ if echo "$ai_output" | grep -q "Attempting to authenticate\|Authenticating\|Loading\|Initializing"; then
140
+ echo "[WARN] Gemini is still authenticating, falling back to Claude Opus" >&2
141
+ preferred_model="opus"
142
+ elif [[ -z "$ai_output" ]] || [[ $(echo "$ai_output" | wc -l) -lt 2 ]]; then
143
+ echo "[WARN] Gemini returned insufficient output, falling back to Claude Opus" >&2
144
+ preferred_model="opus"
145
+ else
146
+ echo "$ai_output"
147
+ return 0
148
+ fi
60
149
  else
61
- echo "[WARN] Codex o3 failed, falling back to Claude Opus" >&2
150
+ echo "[WARN] Gemini failed with exit code $ai_exit_code, falling back to Claude Opus" >&2
62
151
  preferred_model="opus"
63
152
  fi
64
153
  fi
@@ -92,6 +181,13 @@ call_ai_with_limit_check() {
92
181
  exit 1
93
182
  fi
94
183
 
184
+ # Validate output doesn't contain shell constructs that could corrupt CSV
185
+ if echo "$claude_output" | grep -E "EOF.*<.*null|<<.*EOF|<.*dev.*null" >/dev/null 2>&1; then
186
+ echo "[ERROR] AI output contains invalid shell constructs" >&2
187
+ echo "[DEBUG] Problematic output: $claude_output" | head -5 >&2
188
+ return 1
189
+ fi
190
+
95
191
  # Output Claude's response
96
192
  echo "$claude_output"
97
193
 
@@ -176,22 +272,117 @@ get_next_generation() {
176
272
  return
177
273
  fi
178
274
 
179
- # Find highest generation number
180
- local max_gen=0
181
- while IFS=, read -r id rest; do
182
- # Extract generation number from IDs like "gen01-001"
183
- if [[ $id =~ ^gen([0-9]+)- ]]; then
184
- local gen_num=$((10#${BASH_REMATCH[1]}))
185
- if (( gen_num > max_gen )); then
186
- max_gen=$gen_num
187
- fi
188
- fi
189
- done < <(tail -n +2 "$FULL_CSV_PATH")
275
+ # Use Python for proper CSV parsing
276
+ local max_gen
277
+ max_gen=$("$PYTHON_CMD" -c "
278
+ import csv
279
+ max_gen = 0
280
+ with open('$FULL_CSV_PATH', 'r') as f:
281
+ reader = csv.reader(f)
282
+ next(reader, None) # Skip header
283
+ for row in reader:
284
+ if row and len(row) > 0:
285
+ id_field = row[0].strip()
286
+ if id_field.startswith('gen') and '-' in id_field:
287
+ try:
288
+ gen_part = id_field.split('-')[0] # e.g., 'gen01'
289
+ gen_num = int(gen_part[3:]) # Extract number after 'gen'
290
+ max_gen = max(max_gen, gen_num)
291
+ except (ValueError, IndexError):
292
+ pass
293
+ print(max_gen)
294
+ ")
190
295
 
191
296
  # Increment and format with leading zero
192
297
  printf "%02d" $((max_gen + 1))
193
298
  }
194
299
 
300
+ # Get next available ID number for current generation
301
+ get_next_id_number() {
302
+ "$PYTHON_CMD" -c "
303
+ import csv
304
+ import re
305
+ max_id = 0
306
+ pattern = re.compile(r'^gen$CURRENT_GENERATION-(\d+)$')
307
+ with open('$FULL_CSV_PATH', 'r') as f:
308
+ reader = csv.reader(f)
309
+ next(reader, None) # Skip header
310
+ for row in reader:
311
+ if row and len(row) > 0:
312
+ match = pattern.match(row[0].strip())
313
+ if match:
314
+ max_id = max(max_id, int(match.group(1)))
315
+ print(max_id + 1)
316
+ "
317
+ }
318
+
319
+ # Process AI output and add ideas to CSV
320
+ process_ai_ideas() {
321
+ local ai_output="$1"
322
+ local count="$2"
323
+ local idea_type="$3" # novel, hill-climbing, structural, crossover
324
+ local top_performers="${4:-}" # Optional, for non-novel ideas
325
+
326
+ local next_id_num=$(get_next_id_number)
327
+ local ideas_added=0
328
+
329
+ while IFS= read -r line && [[ $ideas_added -lt $count ]]; do
330
+ # Skip empty lines
331
+ [[ -z "$line" || "$line" =~ ^[[:space:]]*$ ]] && continue
332
+
333
+ # Skip lines that look like headers or metadata
334
+ [[ "$line" =~ ^#|^\[|^==|^-- ]] && continue
335
+
336
+ # Clean the line
337
+ line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
338
+ line=$(echo "$line" | sed 's/^[0-9]\+\.\?[[:space:]]*//') # Remove numbering
339
+ line=$(echo "$line" | sed 's/^-[[:space:]]*//') # Remove bullet points
340
+
341
+ # Extract parent ID and description based on type
342
+ local parent_id=""
343
+ local description="$line"
344
+
345
+ if [[ "$idea_type" != "novel" ]]; then
346
+ # For non-novel ideas, extract parent ID from "From X:" format
347
+ if [[ "$line" =~ ^From[[:space:]]+([^:]+):[[:space:]]*(.+)$ ]]; then
348
+ parent_id="${BASH_REMATCH[1]}"
349
+ description="${BASH_REMATCH[2]}"
350
+ else
351
+ # If no parent specified, use the first from top_performers
352
+ parent_id=$(echo "$top_performers" | head -1 | cut -d',' -f1)
353
+ fi
354
+ fi
355
+
356
+ # Skip if description is too short or contains problematic content
357
+ [[ ${#description} -lt 20 ]] && continue
358
+ if echo "$description" | grep -qE 'EOF|/dev/null|<<<|>>>'; then
359
+ continue
360
+ fi
361
+
362
+ # Generate ID for this idea
363
+ local idea_id=$(printf "gen%s-%03d" "$CURRENT_GENERATION" $((next_id_num + ideas_added)))
364
+
365
+ # Escape quotes in description for CSV
366
+ description="${description//\"/\"\"}"
367
+
368
+ # Append to CSV
369
+ echo "$idea_id,$parent_id,\"$description\",,pending" >> "$FULL_CSV_PATH"
370
+
371
+ ((ideas_added++))
372
+ if [[ -n "$parent_id" ]]; then
373
+ echo "[INFO] Added $idea_type idea $idea_id (parent: $parent_id): ${description:0:50}..."
374
+ else
375
+ echo "[INFO] Added $idea_type idea $idea_id: ${description:0:70}..."
376
+ fi
377
+ done <<< "$ai_output"
378
+
379
+ if [[ $ideas_added -lt $count ]]; then
380
+ echo "[WARN] Only generated $ideas_added out of $count requested $idea_type ideas" >&2
381
+ fi
382
+
383
+ return 0
384
+ }
385
+
195
386
  # Get next available ID for current generation
196
387
  get_next_id() {
197
388
  local generation="$1"
@@ -200,24 +391,32 @@ get_next_id() {
200
391
  return
201
392
  fi
202
393
 
203
- # Find highest ID within this generation
204
- local max_id=0
205
- while IFS=, read -r id rest; do
206
- # Match IDs for this specific generation
207
- if [[ $id =~ ^gen${generation}-([0-9]+)$ ]]; then
208
- local id_num=$((10#${BASH_REMATCH[1]}))
209
- if (( id_num > max_id )); then
210
- max_id=$id_num
211
- fi
212
- fi
213
- done < <(tail -n +2 "$FULL_CSV_PATH")
394
+ # Use Python for proper CSV parsing
395
+ local max_id
396
+ max_id=$("$PYTHON_CMD" -c "
397
+ import csv
398
+ import re
399
+ max_id = 0
400
+ pattern = re.compile(r'^gen${generation}-(\d+)$')
401
+ with open('$FULL_CSV_PATH', 'r') as f:
402
+ reader = csv.reader(f)
403
+ next(reader, None) # Skip header
404
+ for row in reader:
405
+ if row and len(row) > 0:
406
+ id_field = row[0].strip()
407
+ match = pattern.match(id_field)
408
+ if match:
409
+ id_num = int(match.group(1))
410
+ max_id = max(max_id, id_num)
411
+ print(max_id)
412
+ ")
214
413
 
215
414
  # Format next ID with generation and 3-digit number
216
415
  printf "gen%s-%03d" "$generation" $((max_id + 1))
217
416
  }
218
417
 
219
418
 
220
- # Get top performers for parent selection
419
+ # Get top performers for parent selection (absolute + top novel candidates)
221
420
  get_top_performers() {
222
421
  local num_requested="$1"
223
422
  if [[ ! -f "$FULL_CSV_PATH" ]]; then
@@ -225,7 +424,7 @@ get_top_performers() {
225
424
  return
226
425
  fi
227
426
 
228
- # Use Python to properly parse CSV with quoted fields
427
+ # Use Python to properly parse CSV and find top performers + top novel candidates
229
428
  "$PYTHON_CMD" -c "
230
429
  import csv
231
430
  import sys
@@ -235,24 +434,57 @@ with open('$FULL_CSV_PATH', 'r') as f:
235
434
  next(reader) # Skip header
236
435
 
237
436
  completed = []
437
+ novel = []
438
+
439
+ # Collect all completed candidates
238
440
  for row in reader:
239
441
  if len(row) >= 5 and row[3] and row[4] == 'complete':
240
442
  try:
443
+ candidate_id = row[0]
444
+ parent_id = row[1] if len(row) > 1 else ''
445
+ description = row[2] if len(row) > 2 else ''
241
446
  score = float(row[3])
242
- completed.append((row[0], row[2], score))
447
+
448
+ completed.append((candidate_id, description, score))
449
+
450
+ # Track novel candidates separately
451
+ if not parent_id:
452
+ novel.append((candidate_id, description, score))
453
+
243
454
  except ValueError:
244
455
  pass
245
456
 
246
- # Sort by score descending
457
+ # Sort absolute leaders by score (descending)
247
458
  completed.sort(key=lambda x: x[2], reverse=True)
248
459
 
249
- # Output top N
250
- for i, (id, desc, score) in enumerate(completed[:$num_requested]):
251
- print(f'{id},{desc},{score}')
460
+ # Sort novel candidates by score (descending)
461
+ novel.sort(key=lambda x: x[2], reverse=True)
462
+
463
+ # Collect top performers
464
+ selected_ids = set()
465
+ results = []
466
+
467
+ # Add top absolute performers
468
+ for i, (candidate_id, description, score) in enumerate(completed[:$num_requested]):
469
+ results.append(f'{candidate_id},{description},{score}')
470
+ selected_ids.add(candidate_id)
471
+
472
+ # Add top novel candidates (if not already selected)
473
+ novel_count = 0
474
+ for candidate_id, description, score in novel:
475
+ if candidate_id not in selected_ids and novel_count < $NUM_REVOLUTION:
476
+ results.append(f'{candidate_id},{description},{score}')
477
+ selected_ids.add(candidate_id)
478
+ novel_count += 1
479
+
480
+ # Output all selected candidates
481
+ for result in results:
482
+ print(result)
252
483
  "
253
484
  }
254
485
 
255
486
 
487
+
256
488
  # Generate ideas using AI with multi-strategy approach
257
489
  ideate_ai_strategies() {
258
490
  if [[ ! -f "$FULL_BRIEF_PATH" ]]; then
@@ -260,7 +492,9 @@ ideate_ai_strategies() {
260
492
  exit 1
261
493
  fi
262
494
 
263
- # Get top performers
495
+ # Baseline should already be evaluated by run command
496
+
497
+ # Get top performers (now includes top novel candidates)
264
498
  local top_performers
265
499
  top_performers=$(get_top_performers "$NUM_ELITES")
266
500
 
@@ -284,305 +518,201 @@ ideate_ai_strategies() {
284
518
  [[ $CROSSOVER_HYBRID -gt 0 ]] && generate_crossover_direct "$CROSSOVER_HYBRID" "$top_performers"
285
519
  }
286
520
 
287
- # Generate novel exploration ideas by having Claude edit CSV directly
521
+ # Generate novel exploration ideas using structured output
288
522
  generate_novel_ideas_direct() {
289
523
  local count="$1"
290
524
 
291
- local prompt="Edit the file $FULL_CSV_PATH to add exactly $count new rows for novel algorithmic approaches.
292
-
293
- Current CSV content:
294
- $(cat "$FULL_CSV_PATH")
295
-
296
- Algorithm files you MUST examine for context:
297
- - Base algorithm: $FULL_ALGORITHM_PATH
298
- - Evolved algorithms: $FULL_OUTPUT_DIR/evolution_*.py (examine ALL to see what's been tried)
299
-
300
- IMPORTANT: Before generating ideas, you should:
301
- 1. Read the base algorithm to understand the codebase structure and possibilities
302
- 2. Read ALL existing evolution_*.py files to see what modifications have been attempted
303
- 3. Analyze the CSV to see which approaches worked (high scores) and which failed
304
- 4. Avoid repeating failed approaches unless trying them with significant modifications
305
-
306
- Project Brief:
307
- $(cat "$FULL_BRIEF_PATH")
308
-
309
- Requirements for new CSV rows:
310
- - IDs must use format: gen$CURRENT_GENERATION-XXX (e.g., gen$CURRENT_GENERATION-001, gen$CURRENT_GENERATION-002)
311
- - Continue numbering from the highest existing ID in generation $CURRENT_GENERATION
312
- - basedOnId should be empty (these are novel approaches)
313
- - Each description should be one clear sentence describing a specific algorithmic change
314
- - Descriptions should explore completely different approaches than existing ones
315
- - All new rows should have empty performance and status fields
316
-
317
- CRITICAL CSV FORMAT RULES:
318
- - DO NOT modify the CSV header row
319
- - DO NOT change the column order
320
- - DO NOT add extra columns or fields
321
- - DO NOT modify existing rows - only append new ones
322
- - DO NOT add extra blank lines or formatting
323
- - Maintain exact CSV format: id,basedOnId,description,performance,status
324
- - Leave performance and status fields completely empty (just commas)
325
- - Use proper CSV quoting only when descriptions contain commas
326
- - CRITICAL: You must read existing evolution files to avoid suggesting changes that:
327
- * Have already been tried and failed
328
- * Are impossible given the codebase structure
329
- * Would break the algorithm interface requirements
525
+ # Get next available ID for this generation
526
+ local next_id_num
527
+ next_id_num=$("$PYTHON_CMD" -c "
528
+ import csv
529
+ import re
530
+ max_id = 0
531
+ pattern = re.compile(r'^gen$CURRENT_GENERATION-(\d+)$')
532
+ with open('$FULL_CSV_PATH', 'r') as f:
533
+ reader = csv.reader(f)
534
+ next(reader, None) # Skip header
535
+ for row in reader:
536
+ if row and len(row) > 0:
537
+ match = pattern.match(row[0].strip())
538
+ if match:
539
+ max_id = max(max_id, int(match.group(1)))
540
+ print(max_id + 1)
541
+ ")
542
+
543
+ local prompt="Generate exactly $count novel algorithmic ideas for trading algorithm evolution.
330
544
 
331
- ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
545
+ Current evolution context:
546
+ - Generation: $CURRENT_GENERATION
547
+ - Algorithm: $FULL_ALGORITHM_PATH
548
+ - Brief: $(head -20 "$FULL_BRIEF_PATH")
332
549
 
333
- EXPLORE ANY CREATIVE IDEAS INCLUDING:
334
- - **Machine Learning**: Neural networks, decision trees, ensemble methods (use train() method properly)
335
- - **New Indicators**: Custom combinations, alternative calculations, multi-timeframe signals
336
- - **Market Regime Detection**: VIX patterns, correlation shifts, volume analysis, cross-asset signals
337
- - **Risk Management**: Dynamic stops, correlation-based position sizing, drawdown protection
338
- - **Timing**: Time-of-day effects, calendar patterns, volatility timing
339
- - **Alternative Strategies**: New sub-strategies, momentum scoring, mean reversion variants
340
- - **Cross-Asset Signals**: Bond yields, sector rotation, crypto correlations
341
- - **Multi-Timeframe**: Combining 30m/1h/daily signals for confirmation
342
- - **Advanced Exits**: Profit targets, time-based exits, volatility-based exits
550
+ You MUST output EXACTLY $count lines, where each line is a single sentence describing a specific algorithmic change.
551
+ NO PREAMBLE, NO EXPLANATION, NO NUMBERING - just $count lines of algorithm descriptions.
343
552
 
344
- Think outside the box! The codebase supports sophisticated approaches - be creative and ambitious.
553
+ Requirements:
554
+ - Each line should be one clear sentence describing a novel algorithmic approach
555
+ - Focus on creative, ambitious ideas that haven't been tried yet
556
+ - Consider machine learning, new indicators, regime detection, risk management, etc.
345
557
 
346
- Example descriptions:
347
- - Train LSTM network on 30-day OHLCV sequences to predict next-day direction probability
348
- - Add cross-correlation filter that reduces positions when TQQQ correlation with QQQ breaks down
349
- - Implement intraday momentum using 30-minute data to adjust daily position sizes
558
+ Example output format:
559
+ Train LSTM network on 30-day OHLCV sequences to predict next-day direction probability
560
+ Add cross-correlation filter that reduces positions when correlation with market breaks down
561
+ Implement intraday momentum using 30-minute data to adjust daily position sizes
350
562
 
351
- Add exactly $count rows to the CSV file now."
563
+ Output exactly $count lines now:"
352
564
 
353
565
  echo "[INFO] Generating $count novel exploration ideas..."
354
- if ! call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION"; then
566
+
567
+ # Get AI response
568
+ local ai_output
569
+ if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
355
570
  echo "[WARN] AI failed to generate novel ideas" >&2
356
571
  return 1
357
572
  fi
358
- echo "[INFO] Novel exploration ideas generated"
573
+
574
+ # Process the output using helper function
575
+ process_ai_ideas "$ai_output" "$count" "novel"
576
+
577
+ echo "[INFO] Novel exploration ideas generated successfully"
359
578
  }
360
579
 
361
- # Generate hill climbing ideas by having Claude edit CSV directly
580
+ # Generate hill climbing ideas by getting descriptions from AI
362
581
  generate_hill_climbing_direct() {
363
582
  local count="$1"
364
583
  local top_performers="$2"
365
584
 
366
- local prompt="Edit the file $FULL_CSV_PATH to add exactly $count new rows for parameter tuning based on successful algorithms.
367
-
368
- Current CSV content:
369
- $(cat "$FULL_CSV_PATH")
370
-
371
- Algorithm files you MUST examine for context:
372
- - Base algorithm: $FULL_ALGORITHM_PATH
373
- - Evolved algorithms: $FULL_OUTPUT_DIR/evolution_*.py (examine ALL to see what's been tried)
374
-
375
- IMPORTANT: Before generating ideas, you should:
376
- 1. Read the base algorithm to understand the codebase structure and possibilities
377
- 2. Read ALL existing evolution_*.py files to see what modifications have been attempted
378
- 3. Analyze the CSV to see which approaches worked (high scores) and which failed
379
- 4. Avoid repeating failed approaches unless trying them with significant modifications
585
+ # Get next available ID for this generation
586
+ local next_id_num
587
+ next_id_num=$("$PYTHON_CMD" -c "
588
+ import csv
589
+ import re
590
+ max_id = 0
591
+ pattern = re.compile(r'^gen$CURRENT_GENERATION-(\d+)$')
592
+ with open('$FULL_CSV_PATH', 'r') as f:
593
+ reader = csv.reader(f)
594
+ next(reader, None) # Skip header
595
+ for row in reader:
596
+ if row and len(row) > 0:
597
+ match = pattern.match(row[0].strip())
598
+ if match:
599
+ max_id = max(max_id, int(match.group(1)))
600
+ print(max_id + 1)
601
+ ")
602
+
603
+ local prompt="Generate exactly $count parameter tuning ideas for successful trading algorithms.
380
604
 
381
- Successful algorithms to build on:
605
+ Successful algorithms to tune (pick one as parent):
382
606
  $top_performers
383
607
 
384
- Project Brief:
385
- $(cat "$FULL_BRIEF_PATH")
386
-
387
- Requirements for new CSV rows:
388
- - IDs must use format: gen$CURRENT_GENERATION-XXX (e.g., gen$CURRENT_GENERATION-001, gen$CURRENT_GENERATION-002)
389
- - Continue numbering from the highest existing ID in generation $CURRENT_GENERATION
390
- - basedOnId should reference ONE of the successful algorithm IDs above (pick the best one)
391
- - Each description should be one clear sentence about parameter tuning
392
- - Focus on adjusting hyperparameters, thresholds, sizes, learning rates
393
- - All new rows should have empty performance and status fields
394
-
395
- CRITICAL CSV FORMAT RULES:
396
- - DO NOT modify the CSV header row
397
- - DO NOT change the column order
398
- - DO NOT add extra columns or fields
399
- - DO NOT modify existing rows - only append new ones
400
- - DO NOT add extra blank lines or formatting
401
- - Maintain exact CSV format: id,basedOnId,description,performance,status
402
- - Leave performance and status fields completely empty (just commas)
403
- - Use proper CSV quoting only when descriptions contain commas
404
- - CRITICAL: You must read the parent algorithm file to understand:
405
- * What parameters are actually tunable in the code
406
- * What changes made this algorithm successful vs its parent
407
- * What parameter ranges make sense given the implementation
608
+ You MUST output EXACTLY $count lines, where each line describes a parameter tuning idea.
609
+ NO PREAMBLE, NO EXPLANATION, NO NUMBERING - just $count lines of parameter tuning descriptions.
408
610
 
409
- ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
611
+ Each line should:
612
+ - Be one clear sentence about adjusting specific parameters
613
+ - Reference the parent algorithm ID at the beginning like \"From gen02-003:\"
614
+ - Focus on hyperparameters, thresholds, periods, weights, etc.
410
615
 
411
- EXPLORE PARAMETER TUNING INCLUDING:
412
- - **Entry/Exit Thresholds**: IBS_BUY_THRESHOLD, LARISSA_LOW_THRESHOLD, RSI levels, etc.
413
- - **Indicator Periods**: ATR_PERIOD, RSI_PERIOD, moving average lengths, etc.
414
- - **Strategy Weights**: Emphasize best performers or rebalance for diversification
415
- - **Risk Parameters**: Stop levels, timeout periods, correlation thresholds
416
- - **Regime Parameters**: Volatility thresholds, trend detection sensitivity
417
- - **ML Hyperparameters**: Learning rates, network sizes, ensemble weights (if using ML)
616
+ Example output format:
617
+ From gen02-003: Lower IBS_BUY_THRESHOLD from 0.15 to 0.12 to enter deeper oversold conditions
618
+ From gen02-003: Increase TRS_RSI_PERIOD from 2 to 3 for smoother RSI signals
619
+ From gen02-003: Raise WEIGHT_TDD from 0.38 to 0.42 to emphasize best performing strategy
418
620
 
419
- Be creative with parameter combinations and ranges - the system is sophisticated!
420
-
421
- Example descriptions:
422
- - Lower IBS_BUY_THRESHOLD from 0.15 to 0.12 to enter deeper oversold conditions
423
- - Increase TRS_RSI_PERIOD from 2 to 3 for smoother RSI signals
424
- - Raise WEIGHT_TDD from 0.38 to 0.42 to emphasize best performing strategy
425
-
426
- Add exactly $count parameter tuning rows to the CSV file now."
621
+ Output exactly $count lines now:"
427
622
 
428
623
  echo "[INFO] Generating $count hill climbing ideas..."
429
- if ! call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION"; then
624
+
625
+ # Get AI response
626
+ local ai_output
627
+ if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
430
628
  echo "[WARN] AI failed to generate hill climbing ideas" >&2
431
629
  return 1
432
630
  fi
433
- echo "[INFO] Hill climbing ideas generated"
631
+
632
+ # Process the output using helper function
633
+ process_ai_ideas "$ai_output" "$count" "hill-climbing" "$top_performers"
634
+
635
+ echo "[INFO] Hill climbing ideas generated successfully"
434
636
  }
435
637
 
436
- # Generate structural mutation ideas by having Claude edit CSV directly
638
+ # Generate structural mutation ideas by getting descriptions from AI
437
639
  generate_structural_mutation_direct() {
438
640
  local count="$1"
439
641
  local top_performers="$2"
440
642
 
441
- local prompt="Edit the file $FULL_CSV_PATH to add exactly $count new rows for structural modifications based on successful algorithms.
442
-
443
- Current CSV content:
444
- $(cat "$FULL_CSV_PATH")
643
+ local prompt="Generate exactly $count structural modification ideas for successful trading algorithms.
445
644
 
446
- Algorithm files you MUST examine for context:
447
- - Base algorithm: $FULL_ALGORITHM_PATH
448
- - Evolved algorithms: $FULL_OUTPUT_DIR/evolution_*.py (examine ALL to see what's been tried)
449
-
450
- IMPORTANT: Before generating ideas, you should:
451
- 1. Read the base algorithm to understand the codebase structure and possibilities
452
- 2. Read ALL existing evolution_*.py files to see what modifications have been attempted
453
- 3. Analyze the CSV to see which approaches worked (high scores) and which failed
454
- 4. Avoid repeating failed approaches unless trying them with significant modifications
455
-
456
- Successful algorithms to build on:
645
+ Successful algorithms to modify structurally:
457
646
  $top_performers
458
647
 
459
- Project Brief:
460
- $(cat "$FULL_BRIEF_PATH")
461
-
462
- Requirements for new CSV rows:
463
- - IDs must use format: gen$CURRENT_GENERATION-XXX (e.g., gen$CURRENT_GENERATION-001, gen$CURRENT_GENERATION-002)
464
- - Continue numbering from the highest existing ID in generation $CURRENT_GENERATION
465
- - basedOnId should reference ONE of the successful algorithm IDs above (pick the best one)
466
- - Each description should be one clear sentence about architectural changes
467
- - Keep core insights but change implementation approach
468
- - All new rows should have empty performance and status fields
469
-
470
- CRITICAL CSV FORMAT RULES:
471
- - DO NOT modify the CSV header row
472
- - DO NOT change the column order
473
- - DO NOT add extra columns or fields
474
- - DO NOT modify existing rows - only append new ones
475
- - DO NOT add extra blank lines or formatting
476
- - Maintain exact CSV format: id,basedOnId,description,performance,status
477
- - Leave performance and status fields completely empty (just commas)
478
- - Use proper CSV quoting only when descriptions contain commas
479
- - CRITICAL: You must read the parent algorithm file to understand:
480
- * What structural elements can be modified within the codebase constraints
481
- * What architectural decisions led to this algorithm's success
482
- * Which components are essential vs which can be replaced
483
-
484
- ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
485
-
486
- ✅ EXPLORE STRUCTURAL INNOVATIONS INCLUDING:
487
- - **Algorithm Architecture**: Replace sub-strategies, change combination logic, add new layers
488
- - **Indicator Swaps**: RSI → Stochastic, SMA → Hull MA, Bollinger → Keltner, etc.
489
- - **Machine Learning Integration**: Add neural networks, decision trees, reinforcement learning
490
- - **Market Regime Systems**: Multi-regime detection, regime-specific strategies
491
- - **Risk Management Overhauls**: Portfolio heat, correlation-based sizing, adaptive stops
492
- - **Multi-Asset Integration**: Cross-asset signals, sector rotation, bond/equity relationships
493
- - **Time-Based Innovations**: Intraday patterns, calendar effects, volatility timing
648
+ You MUST output EXACTLY $count lines, where each line describes a structural modification idea.
649
+ NO PREAMBLE, NO EXPLANATION, NO NUMBERING - just $count lines of structural change descriptions.
494
650
 
495
- The codebase is flexible - think architecturally about major improvements!
651
+ Each line should:
652
+ - Be one clear sentence about architectural/structural changes
653
+ - Reference the parent algorithm ID at the beginning like \"From gen02-003:\"
654
+ - Focus on replacing components, changing architecture, adding new systems
496
655
 
497
- Example descriptions:
498
- - Replace 2-period RSI with LSTM-predicted momentum scores for TRS strategy
499
- - Add ensemble voting system where sub-strategies vote on market regime
500
- - Implement hierarchical risk budgeting with correlation-adjusted position sizing
656
+ Example output format:
657
+ From gen02-003: Replace 2-period RSI with LSTM-predicted momentum scores for TRS strategy
658
+ From gen02-003: Add ensemble voting system where sub-strategies vote on market regime
659
+ From gen02-003: Implement hierarchical risk budgeting with correlation-adjusted position sizing
501
660
 
502
- Add exactly $count structural modification rows to the CSV file now."
661
+ Output exactly $count lines now:"
503
662
 
504
663
  echo "[INFO] Generating $count structural mutation ideas..."
505
- if ! call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION"; then
664
+
665
+ # Get AI response
666
+ local ai_output
667
+ if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
506
668
  echo "[WARN] AI failed to generate structural mutation ideas" >&2
507
669
  return 1
508
670
  fi
509
- echo "[INFO] Structural mutation ideas generated"
671
+
672
+ # Process the output using helper function
673
+ process_ai_ideas "$ai_output" "$count" "structural" "$top_performers"
674
+
675
+ echo "[INFO] Structural mutation ideas generated successfully"
510
676
  }
511
677
 
512
- # Generate crossover hybrid ideas by having Claude edit CSV directly
678
+ # Generate crossover hybrid ideas by getting descriptions from AI
513
679
  generate_crossover_direct() {
514
680
  local count="$1"
515
681
  local top_performers="$2"
516
682
 
517
- local prompt="Edit the file $FULL_CSV_PATH to add exactly $count new rows for hybrid combinations of successful algorithms.
518
-
519
- Current CSV content:
520
- $(cat "$FULL_CSV_PATH")
521
-
522
- Algorithm files you MUST examine for context:
523
- - Base algorithm: $FULL_ALGORITHM_PATH
524
- - Evolved algorithms: $FULL_OUTPUT_DIR/evolution_*.py (examine ALL to see what's been tried)
683
+ local prompt="Generate exactly $count hybrid combination ideas from successful trading algorithms.
525
684
 
526
- IMPORTANT: Before generating ideas, you should:
527
- 1. Read the base algorithm to understand the codebase structure and possibilities
528
- 2. Read ALL existing evolution_*.py files to see what modifications have been attempted
529
- 3. Analyze the CSV to see which approaches worked (high scores) and which failed
530
- 4. Avoid repeating failed approaches unless trying them with significant modifications
531
-
532
- Top performers to combine:
685
+ Top performers to combine (reference at least 2 in each idea):
533
686
  $top_performers
534
687
 
535
- Project Brief:
536
- $(cat "$FULL_BRIEF_PATH")
537
-
538
- Requirements for new CSV rows:
539
- - IDs must use format: gen$CURRENT_GENERATION-XXX (e.g., gen$CURRENT_GENERATION-001, gen$CURRENT_GENERATION-002)
540
- - Continue numbering from the highest existing ID in generation $CURRENT_GENERATION
541
- - basedOnId should reference ONE of the successful algorithm IDs above (pick the best one as base)
542
- - Each description should be one clear sentence combining elements from different algorithms
543
- - Be specific about what elements to merge
544
- - All new rows should have empty performance and status fields
545
-
546
- CRITICAL CSV FORMAT RULES:
547
- - DO NOT modify the CSV header row
548
- - DO NOT change the column order
549
- - DO NOT add extra columns or fields
550
- - DO NOT modify existing rows - only append new ones
551
- - DO NOT add extra blank lines or formatting
552
- - Maintain exact CSV format: id,basedOnId,description,performance,status
553
- - Leave performance and status fields completely empty (just commas)
554
- - Use proper CSV quoting only when descriptions contain commas
555
- - CRITICAL: You must read the relevant algorithm files to:
556
- * Identify the specific improvements that made each algorithm successful
557
- * Understand which components are compatible for merging
558
- * Ensure the combined approach is technically feasible in the codebase
688
+ You MUST output EXACTLY $count lines, where each line describes a hybrid combination idea.
689
+ NO PREAMBLE, NO EXPLANATION, NO NUMBERING - just $count lines of hybrid combination descriptions.
559
690
 
560
- ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
561
-
562
- EXPLORE CREATIVE COMBINATIONS INCLUDING:
563
- - **Strategy Fusion**: Merge successful sub-strategies, combine entry/exit logic
564
- - **Indicator Blending**: Mix different technical analysis approaches from successful algorithms
565
- - **Machine Learning Hybrids**: Combine ML predictions with rule-based systems
566
- - **Multi-Regime Integration**: Blend different regime detection methods
567
- - **Risk System Combinations**: Merge multiple risk management approaches
568
- - **Cross-Asset Blends**: Combine internal signals with external market data
569
- - **Multi-Timeframe Fusion**: Blend signals from different time horizons
691
+ Each line should:
692
+ - Be one clear sentence combining elements from 2+ successful algorithms
693
+ - Reference the base parent algorithm ID at the beginning like \"From gen02-003:\"
694
+ - Explicitly mention which elements to combine from which algorithms
570
695
 
571
- Think creatively about what worked in different algorithms and how to combine them!
696
+ Example output format:
697
+ From gen02-003: Combine VIX regime filter from gen02-003 with LSTM predictions from gen01-005
698
+ From gen02-003: Merge volatility regime detection from gen02-003 with ML momentum from gen01-007
699
+ From gen02-003: Integrate multi-timeframe signals from gen02-003 with correlation sizing from gen01-009
572
700
 
573
- Example descriptions:
574
- - Combine VIX regime filter from algorithm 3 with LSTM predictions from algorithm 5
575
- - Merge volatility regime detection with machine learning momentum scoring
576
- - Integrate multi-timeframe signals with correlation-based position adjustments
577
-
578
- Add exactly $count hybrid combination rows to the CSV file now."
701
+ Output exactly $count lines now:"
579
702
 
580
703
  echo "[INFO] Generating $count crossover hybrid ideas..."
581
- if ! call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION"; then
704
+
705
+ # Get AI response
706
+ local ai_output
707
+ if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
582
708
  echo "[WARN] AI failed to generate crossover ideas" >&2
583
709
  return 1
584
710
  fi
585
- echo "[INFO] Crossover hybrid ideas generated"
711
+
712
+ # Process the output using helper function
713
+ process_ai_ideas "$ai_output" "$count" "crossover" "$top_performers"
714
+
715
+ echo "[INFO] Crossover hybrid ideas generated successfully"
586
716
  }
587
717
 
588
718
  # Legacy AI generation mode (for backward compatibility)
@@ -592,28 +722,24 @@ ideate_ai_legacy() {
592
722
  exit 1
593
723
  fi
594
724
 
595
- # Get top performers (pure shell)
725
+ # Get top performers for context
596
726
  local top_performers=""
597
727
  if [[ -f "$FULL_CSV_PATH" ]]; then
598
728
  # Simple top performers extraction (lines with non-empty performance)
599
729
  top_performers=$(awk -F, 'NR > 1 && $4 != "" { print $1 ": " $3 " (score: " $4 ")" }' "$FULL_CSV_PATH" | head -5)
600
730
  fi
601
731
 
602
- # Build prompt
603
- local prompt="Edit the file $FULL_CSV_PATH to add exactly $TOTAL_IDEAS new algorithm variation rows.
732
+ # Build prompt for description-only output
733
+ local prompt="Generate exactly $TOTAL_IDEAS novel algorithmic ideas for trading algorithm evolution.
604
734
 
605
- Current CSV content:
606
- $(cat "$FULL_CSV_PATH")
607
-
608
- Algorithm files you MUST examine for context:
735
+ Algorithm files for context:
609
736
  - Base algorithm: $FULL_ALGORITHM_PATH
610
- - Evolved algorithms: $FULL_OUTPUT_DIR/evolution_*.py (examine ALL to see what's been tried)
737
+ - Evolved algorithms: $FULL_OUTPUT_DIR/evolution_*.py
611
738
 
612
739
  IMPORTANT: Before generating ideas, you should:
613
740
  1. Read the base algorithm to understand the codebase structure and possibilities
614
741
  2. Read ALL existing evolution_*.py files to see what modifications have been attempted
615
- 3. Analyze the CSV to see which approaches worked (high scores) and which failed
616
- 4. Avoid repeating failed approaches unless trying them with significant modifications
742
+ 3. Consider which approaches might work well
617
743
 
618
744
  Project Brief:
619
745
  $(cat "$FULL_BRIEF_PATH")"
@@ -627,44 +753,41 @@ $top_performers"
627
753
 
628
754
  prompt+="
629
755
 
630
- Requirements for new CSV rows:
631
- - IDs must use format: gen$CURRENT_GENERATION-XXX (e.g., gen$CURRENT_GENERATION-001, gen$CURRENT_GENERATION-002)
632
- - Continue numbering from the highest existing ID in generation $CURRENT_GENERATION
633
- - basedOnId should be empty or reference existing algorithm ID
634
- - Each description should be one clear sentence describing an algorithmic approach
635
- - All new rows should have empty performance and status fields
636
-
637
- CRITICAL CSV FORMAT RULES:
638
- - DO NOT modify the CSV header row
639
- - DO NOT change the column order
640
- - DO NOT add extra columns or fields
641
- - DO NOT modify existing rows - only append new ones
642
- - DO NOT add extra blank lines or formatting
643
- - Maintain exact CSV format: id,basedOnId,description,performance,status
644
- - Leave performance and status fields completely empty (just commas)
645
- - Use proper CSV quoting only when descriptions contain commas
756
+ You MUST output EXACTLY $TOTAL_IDEAS lines, where each line is a single sentence describing a specific algorithmic change.
757
+ NO PREAMBLE, NO EXPLANATION, NO NUMBERING - just $TOTAL_IDEAS lines of algorithm descriptions.
758
+
759
+ Requirements:
760
+ - Each line should be one clear sentence describing an algorithmic approach
761
+ - Mix both parameter tuning and structural changes
762
+ - If building on existing algorithms, start with 'From ALGORITHM_ID:'
646
763
 
647
764
  ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
648
765
 
649
766
  ✅ EXPLORE ALL CREATIVE POSSIBILITIES INCLUDING:
650
- - **Machine Learning**: Neural networks, ensemble methods, reinforcement learning (use train() method)
651
- - **Advanced Indicators**: Custom combinations, multi-timeframe signals, cross-asset indicators
652
- - **Market Regime Detection**: VIX patterns, correlation analysis, volatility clustering
653
- - **Risk Management**: Dynamic stops, portfolio heat, correlation-based position sizing
654
- - **Alternative Strategies**: New sub-strategies, momentum variants, mean reversion innovations
655
- - **Multi-Asset Signals**: Sector rotation, bond yields, commodity signals
656
- - **Time-Based Patterns**: Intraday effects, calendar anomalies, volatility timing
657
- - **Parameter Optimization**: Entry thresholds, indicator periods, strategy weights
767
+ - Machine Learning: Neural networks, ensemble methods, reinforcement learning (use train() method)
768
+ - Advanced Indicators: Custom combinations, multi-timeframe signals, cross-asset indicators
769
+ - Market Regime Detection: VIX patterns, correlation analysis, volatility clustering
770
+ - Risk Management: Dynamic stops, portfolio heat, correlation-based position sizing
771
+ - Alternative Strategies: New sub-strategies, momentum variants, mean reversion innovations
772
+ - Multi-Asset Signals: Sector rotation, bond yields, commodity signals
773
+ - Time-Based Patterns: Intraday effects, calendar anomalies, volatility timing
774
+ - Parameter Optimization: Entry thresholds, indicator periods, strategy weights
658
775
 
659
- Think outside the box - the system is sophisticated and can handle advanced approaches!
660
-
661
- Add exactly $TOTAL_IDEAS algorithm variation rows to the CSV file now."
776
+ Output exactly $TOTAL_IDEAS lines now:"
662
777
 
663
778
  echo "[INFO] Generating $TOTAL_IDEAS ideas (legacy mode)..."
664
- if ! call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION"; then
779
+
780
+ # Get AI response
781
+ local ai_output
782
+ if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
665
783
  echo "[WARN] AI failed to generate ideas" >&2
666
784
  return 1
667
785
  fi
786
+
787
+ # Process the output using helper function
788
+ # For legacy mode, we treat all as "novel" since we're not specifying a strategy
789
+ process_ai_ideas "$ai_output" "$TOTAL_IDEAS" "novel"
790
+
668
791
  echo "[INFO] Legacy ideas generated"
669
792
  }
670
793