claude-evolve 1.4.11 → 1.4.13

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.
@@ -199,6 +199,98 @@ call_claude_with_limit_check() {
199
199
  call_ai_with_limit_check "$@"
200
200
  }
201
201
 
202
+ # Robust AI calling with fallbacks across all available models
203
+ call_ai_with_fallbacks() {
204
+ local prompt="$1"
205
+ local generation="${2:-01}"
206
+
207
+ # List of models to try in order
208
+ local models=()
209
+
210
+ # Check which AI tools are available
211
+ if command -v codex >/dev/null 2>&1; then
212
+ models+=("o3")
213
+ fi
214
+ if command -v gemini >/dev/null 2>&1; then
215
+ models+=("gemini")
216
+ fi
217
+ # Claude is always available (fallback)
218
+ models+=("opus" "sonnet" "haiku")
219
+
220
+ # Try each model in sequence
221
+ for model in "${models[@]}"; do
222
+ echo "[INFO] Trying $model for ideation (fallback attempt)" >&2
223
+
224
+ local ai_output
225
+ local ai_exit_code
226
+
227
+ if [[ "$model" == "o3" ]] && command -v codex >/dev/null 2>&1; then
228
+ ai_output=$(codex -m o3 --full-auto -q "$prompt" 2>&1)
229
+ ai_exit_code=$?
230
+
231
+ if [[ $ai_exit_code -eq 0 ]]; then
232
+ # Clean o3 output like in the original function
233
+ if echo "$ai_output" | grep -q '"content"'; then
234
+ ai_output=$(echo "$ai_output" | python3 -c "
235
+ import sys
236
+ import json
237
+ try:
238
+ data = json.load(sys.stdin)
239
+ if 'content' in data:
240
+ print(data['content'])
241
+ elif 'response' in data:
242
+ print(data['response'])
243
+ elif 'text' in data:
244
+ print(data['text'])
245
+ else:
246
+ print(json.dumps(data))
247
+ except:
248
+ print(sys.stdin.read())
249
+ " 2>/dev/null || echo "$ai_output")
250
+ fi
251
+
252
+ if [[ -n "$ai_output" ]] && ! echo "$ai_output" | grep -q "error\|failed\|exception"; then
253
+ echo "$ai_output"
254
+ return 0
255
+ fi
256
+ fi
257
+
258
+ elif [[ "$model" == "gemini" ]] && command -v gemini >/dev/null 2>&1; then
259
+ ai_output=$(gemini -y -p "$prompt" 2>&1)
260
+ ai_exit_code=$?
261
+
262
+ if [[ $ai_exit_code -eq 0 ]]; then
263
+ if ! echo "$ai_output" | grep -q "Attempting to authenticate\|Authenticating\|Loading\|Initializing"; then
264
+ if [[ -n "$ai_output" ]] && [[ $(echo "$ai_output" | wc -l) -ge 2 ]]; then
265
+ echo "$ai_output"
266
+ return 0
267
+ fi
268
+ fi
269
+ fi
270
+
271
+ else
272
+ # Use Claude with the specified model
273
+ ai_output=$(echo "$prompt" | claude --dangerously-skip-permissions --model "$model" -p 2>&1)
274
+ ai_exit_code=$?
275
+
276
+ if [[ $ai_exit_code -eq 0 ]]; then
277
+ # Check for usage limits
278
+ if ! echo "$ai_output" | grep -q "Claude AI usage limit reached"; then
279
+ if ! echo "$ai_output" | grep -E "EOF.*<.*null|<<.*EOF|<.*dev.*null" >/dev/null 2>&1; then
280
+ echo "$ai_output"
281
+ return 0
282
+ fi
283
+ fi
284
+ fi
285
+ fi
286
+
287
+ echo "[WARN] $model failed or returned unusable output, trying next model..." >&2
288
+ done
289
+
290
+ echo "[ERROR] All AI models failed to generate usable output" >&2
291
+ return 1
292
+ }
293
+
202
294
  # Parse arguments
203
295
  use_strategies=true
204
296
 
@@ -297,7 +389,8 @@ print(max_gen)
297
389
  printf "%02d" $((max_gen + 1))
298
390
  }
299
391
 
300
- # Get next available ID number for current generation
392
+ # This function is no longer used with direct CSV modification approach
393
+ # Keeping for backward compatibility but it's not called anywhere
301
394
  get_next_id_number() {
302
395
  "$PYTHON_CMD" -c "
303
396
  import csv
@@ -316,70 +409,242 @@ print(max_id + 1)
316
409
  "
317
410
  }
318
411
 
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
412
+ # Validate that AI directly modified the CSV file
413
+ validate_direct_csv_modification() {
414
+ local temp_csv="$1"
415
+ local expected_count="$2"
416
+ local idea_type="$3"
325
417
 
326
- local next_id_num=$(get_next_id_number)
327
- local ideas_added=0
418
+ # Check if the file was actually modified
419
+ if [[ ! -f "$temp_csv" ]]; then
420
+ echo "[ERROR] CSV file was not found after AI modification" >&2
421
+ return 1
422
+ fi
328
423
 
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"
424
+ # Validate the modified CSV has more entries than original
425
+ local original_count
426
+ original_count=$(wc -l < "$FULL_CSV_PATH")
427
+ local new_count
428
+ new_count=$(wc -l < "$temp_csv")
429
+
430
+ echo "[DEBUG] Original CSV line count: $original_count" >&2
431
+ echo "[DEBUG] Modified CSV line count: $new_count" >&2
432
+ echo "[DEBUG] Expected to add: $expected_count ideas" >&2
433
+
434
+ if [[ $new_count -le $original_count ]]; then
435
+ echo "[ERROR] CSV file wasn't modified - same number of lines ($new_count <= $original_count)" >&2
436
+ echo "[DEBUG] First 10 lines of CSV after AI attempt:" >&2
437
+ head -10 "$temp_csv" >&2
438
+ return 1
439
+ fi
440
+
441
+ local added_count=$((new_count - original_count))
442
+ if [[ $added_count -ne $expected_count ]]; then
443
+ echo "[WARN] Expected to add $expected_count ideas but added $added_count" >&2
444
+ fi
445
+
446
+ # Replace original CSV with modified version
447
+ mv "$temp_csv" "$FULL_CSV_PATH"
448
+
449
+ echo "[INFO] Successfully added $added_count $idea_type ideas to CSV"
450
+ return 0
451
+ }
452
+
453
+ # DEPRECATED: Old validation function for CSV output approach
454
+ validate_and_apply_csv_modification_old() {
455
+ local modified_csv="$1"
456
+ local temp_csv="$2"
457
+ local expected_count="$3"
458
+ local idea_type="$4"
459
+
460
+ # Check if the response looks like an error message (but not if it's just CSV data containing these words)
461
+ if echo "$modified_csv" | head -1 | grep -q "id,basedOnId,description,performance,status"; then
462
+ # This looks like a CSV file, not an error message
463
+ echo "[DEBUG] AI returned what appears to be a CSV file" >&2
464
+ elif echo "$modified_csv" | grep -qi "error\|failed\|limit\|exceeded\|sorry\|cannot\|unable"; then
465
+ echo "[ERROR] AI failed to modify CSV and returned an error message:" >&2
466
+ echo "$modified_csv" | head -200 >&2
467
+ return 1
468
+ fi
469
+
470
+ # Check if response is too short to be a valid CSV
471
+ if [[ ${#modified_csv} -lt 50 ]]; then
472
+ echo "[ERROR] AI response is too short to be a valid CSV (${#modified_csv} chars):" >&2
473
+ echo "$modified_csv" >&2
474
+ return 1
475
+ fi
476
+
477
+ # Extract CSV from AI output (in case there's extra text before it)
478
+ local csv_start_line
479
+ csv_start_line=$(echo "$modified_csv" | grep -n "id,basedOnId,description,performance,status" | head -1 | cut -d: -f1)
480
+
481
+ if [[ -n "$csv_start_line" ]]; then
482
+ # Extract CSV starting from the header line
483
+ modified_csv=$(echo "$modified_csv" | tail -n +$csv_start_line)
484
+ echo "[DEBUG] Found CSV header at line $csv_start_line, extracting from there" >&2
485
+ elif ! echo "$modified_csv" | head -1 | grep -q "id,basedOnId,description,performance,status"; then
486
+ echo "[ERROR] AI failed to return a valid CSV file. Expected CSV with header, but got:" >&2
487
+ echo "$modified_csv" | head -c 500 >&2
488
+ echo "" >&2
489
+ echo "[DEBUG] The AI was asked to output the complete modified CSV but didn't" >&2
490
+ return 1
491
+ fi
492
+
493
+ # Write the modified CSV to temp file
494
+ echo "$modified_csv" > "$temp_csv"
495
+
496
+ # Validate the modified CSV has more entries than original
497
+ local original_count
498
+ original_count=$(wc -l < "$FULL_CSV_PATH")
499
+ local new_count
500
+ new_count=$(wc -l < "$temp_csv")
501
+
502
+ echo "[DEBUG] Original CSV line count: $original_count" >&2
503
+ echo "[DEBUG] Modified CSV line count: $new_count" >&2
504
+ echo "[DEBUG] Expected to add: $expected_count ideas" >&2
505
+
506
+ if [[ $new_count -le $original_count ]]; then
507
+ echo "[ERROR] Modified CSV doesn't have more entries ($new_count <= $original_count)" >&2
508
+ echo "[DEBUG] First 10 lines of modified CSV:" >&2
509
+ head -10 "$temp_csv" >&2
510
+ return 1
511
+ fi
512
+
513
+ local added_count=$((new_count - original_count))
514
+ if [[ $added_count -ne $expected_count ]]; then
515
+ echo "[WARN] Expected to add $expected_count ideas but added $added_count" >&2
516
+ fi
517
+
518
+ # Replace original CSV with modified version
519
+ mv "$temp_csv" "$FULL_CSV_PATH"
520
+
521
+ echo "[INFO] Successfully added $added_count $idea_type ideas to CSV"
522
+ return 0
523
+ }
524
+
525
+ # DEPRECATED: Old two-step process function - kept for reference
526
+ process_ai_ideas_direct_old() {
527
+ local count="$1"
528
+ local idea_type="$2" # novel, hill-climbing, structural, crossover
529
+ local top_performers="${3:-}" # Optional, for non-novel ideas
530
+ local ai_output="$4" # The AI's response with ideas
531
+
532
+ # Create temporary CSV copy
533
+ local temp_csv="/tmp/claude-evolve-temp-csv-$$.csv"
534
+ cp "$FULL_CSV_PATH" "$temp_csv"
535
+
536
+ echo "[DEBUG] Starting CSV modification for $count $idea_type ideas" >&2
537
+ echo "[DEBUG] Original CSV path: $FULL_CSV_PATH" >&2
538
+ echo "[DEBUG] Temp CSV path: $temp_csv" >&2
539
+ echo "[DEBUG] Original CSV size: $(wc -l < "$FULL_CSV_PATH") lines" >&2
540
+
541
+ # Build prompt for AI to directly modify the CSV
542
+ local csv_prompt="I need you to add exactly $count new $idea_type ideas to this CSV file.
543
+
544
+ Here are the $count $idea_type ideas to add:
545
+ $ai_output
546
+
547
+ Current CSV contents:
548
+ $(cat "$temp_csv")
549
+
550
+ Instructions:
551
+ 1. Add exactly $count new rows to the CSV
552
+ 2. Use the next available generation numbers (gen$CURRENT_GENERATION-XXX format)
553
+ 3. For each idea, create a row with: id,parent_id,description,,pending
554
+ 4. For novel ideas: leave parent_id empty
555
+ 5. For other idea types: use appropriate parent IDs from these top performers:
556
+ $top_performers
557
+
558
+ IMPORTANT: Output the complete modified CSV file. Do not add any explanation or other text - just output the CSV."
559
+
560
+ echo "[INFO] Having AI directly modify CSV with $count $idea_type ideas..."
561
+
562
+ # Get AI to modify the CSV with fallbacks
563
+ local modified_csv
564
+ local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
565
+ if ! modified_csv=$(call_ai_with_fallbacks "$csv_prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
566
+ echo "[ERROR] All AI models failed to modify CSV" >&2
567
+ cat "$stderr_file" >&2
568
+ rm -f "$temp_csv" "$stderr_file"
569
+ return 1
570
+ fi
571
+ rm -f "$stderr_file"
572
+
573
+ # Check if the response looks like an error message
574
+ if echo "$modified_csv" | grep -qi "error\|failed\|limit\|exceeded\|sorry\|cannot\|unable"; then
575
+ echo "[ERROR] AI failed to modify CSV and returned an error message:" >&2
576
+ echo "$modified_csv" | head -200 >&2
577
+ rm -f "$temp_csv"
578
+ return 1
579
+ fi
580
+
581
+ # Check if response is too short to be a valid CSV
582
+ if [[ ${#modified_csv} -lt 50 ]]; then
583
+ echo "[ERROR] AI response is too short to be a valid CSV (${#modified_csv} chars):" >&2
584
+ echo "$modified_csv" >&2
585
+ rm -f "$temp_csv"
586
+ return 1
587
+ fi
588
+
589
+ # Extract CSV from AI output (in case there's extra text before it)
590
+ local csv_start_line
591
+ csv_start_line=$(echo "$modified_csv" | grep -n "id,basedOnId,description,performance,status" | head -1 | cut -d: -f1)
592
+
593
+ if [[ -n "$csv_start_line" ]]; then
594
+ # Extract CSV starting from the header line
595
+ modified_csv=$(echo "$modified_csv" | tail -n +$csv_start_line)
596
+ echo "[DEBUG] Found CSV header at line $csv_start_line, extracting from there" >&2
597
+ elif ! echo "$modified_csv" | head -1 | grep -q "id,basedOnId,description,performance,status"; then
598
+ echo "[ERROR] AI failed to return a valid CSV file. Expected CSV with header, but got:" >&2
599
+ echo "$modified_csv" | head -c 500 >&2
600
+ echo "" >&2
601
+ echo "[DEBUG] The AI was asked to output the complete modified CSV but didn't" >&2
602
+ rm -f "$temp_csv"
603
+ return 1
604
+ fi
605
+
606
+ # Write the modified CSV to temp file
607
+ echo "$modified_csv" > "$temp_csv"
378
608
 
379
- if [[ $ideas_added -lt $count ]]; then
380
- echo "[WARN] Only generated $ideas_added out of $count requested $idea_type ideas" >&2
609
+ # Debug: Show the AI's CSV modification attempt
610
+ echo "[DEBUG] AI response length: ${#modified_csv} characters" >&2
611
+ echo "[DEBUG] First 300 chars of AI response:" >&2
612
+ echo "$modified_csv" | head -c 300 >&2
613
+ echo "" >&2
614
+ echo "[DEBUG] Last 300 chars of AI response:" >&2
615
+ echo "$modified_csv" | tail -c 300 >&2
616
+ echo "" >&2
617
+
618
+ # Validate the modified CSV has more entries than original
619
+ local original_count
620
+ original_count=$(wc -l < "$FULL_CSV_PATH")
621
+ local new_count
622
+ new_count=$(wc -l < "$temp_csv")
623
+
624
+ echo "[DEBUG] Original CSV line count: $original_count" >&2
625
+ echo "[DEBUG] Modified CSV line count: $new_count" >&2
626
+ echo "[DEBUG] Expected to add: $count ideas" >&2
627
+
628
+ if [[ $new_count -le $original_count ]]; then
629
+ echo "[ERROR] Modified CSV doesn't have more entries ($new_count <= $original_count)" >&2
630
+ echo "[DEBUG] Temp CSV contents:" >&2
631
+ cat "$temp_csv" | head -10 >&2
632
+ echo "[DEBUG] Original CSV contents:" >&2
633
+ cat "$FULL_CSV_PATH" | head -10 >&2
634
+ rm -f "$temp_csv"
635
+ return 1
381
636
  fi
382
637
 
638
+ local added_count=$((new_count - original_count))
639
+ if [[ $added_count -ne $count ]]; then
640
+ echo "[WARN] Expected to add $count ideas but added $added_count" >&2
641
+ fi
642
+
643
+ # Replace original CSV with modified version
644
+ mv "$temp_csv" "$FULL_CSV_PATH"
645
+
646
+ echo "[INFO] Successfully added $added_count $idea_type ideas to CSV"
647
+
383
648
  return 0
384
649
  }
385
650
 
@@ -499,10 +764,10 @@ ideate_ai_strategies() {
499
764
  top_performers=$(get_top_performers "$NUM_ELITES")
500
765
 
501
766
  if [[ -z $top_performers ]]; then
502
- echo "[INFO] No completed algorithms found, using pure novel exploration"
503
- # Generate all ideas as novel exploration
504
- generate_novel_ideas_direct "$TOTAL_IDEAS"
505
- return 0
767
+ echo "[INFO] No completed algorithms found, will use baseline algorithm for hill climbing"
768
+ # For hill climbing and mutations, use the baseline algorithm
769
+ # Use a special ID that validation script will recognize
770
+ top_performers="000,Baseline Algorithm (algorithm.py),0.0"
506
771
  fi
507
772
 
508
773
  echo "[INFO] Generating $TOTAL_IDEAS ideas using multi-strategy approach:"
@@ -518,201 +783,239 @@ ideate_ai_strategies() {
518
783
  [[ $CROSSOVER_HYBRID -gt 0 ]] && generate_crossover_direct "$CROSSOVER_HYBRID" "$top_performers"
519
784
  }
520
785
 
521
- # Generate novel exploration ideas using structured output
786
+ # Generate novel exploration ideas using direct CSV modification
522
787
  generate_novel_ideas_direct() {
523
788
  local count="$1"
524
789
 
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
- ")
790
+ # Create temporary CSV copy
791
+ local temp_csv="/tmp/claude-evolve-temp-csv-$$.csv"
792
+ cp "$FULL_CSV_PATH" "$temp_csv"
793
+
794
+ echo "[INFO] Generating $count novel exploration ideas..."
795
+ echo "[DEBUG] Original CSV has $(wc -l < "$FULL_CSV_PATH") lines" >&2
542
796
 
543
- local prompt="Generate exactly $count novel algorithmic ideas for trading algorithm evolution.
797
+ local prompt="Please add exactly $count novel algorithmic ideas directly to the CSV file $temp_csv.
544
798
 
545
799
  Current evolution context:
546
800
  - Generation: $CURRENT_GENERATION
547
801
  - Algorithm: $FULL_ALGORITHM_PATH
548
802
  - Brief: $(head -20 "$FULL_BRIEF_PATH")
549
803
 
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.
552
-
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.
557
-
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
562
-
563
- Output exactly $count lines now:"
564
-
565
- echo "[INFO] Generating $count novel exploration ideas..."
566
-
567
- # Get AI response
568
- local ai_output
569
- if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
570
- echo "[WARN] AI failed to generate novel ideas" >&2
804
+ Instructions:
805
+ 1. Read the current CSV file to see existing entries
806
+ 2. Add exactly $count new rows to the CSV file
807
+ 3. Use the next available generation numbers (gen$CURRENT_GENERATION-XXX format)
808
+ 4. For each idea, create a row with: id,,description,,pending (empty parent_id for novel ideas)
809
+ 5. Each description should be one clear sentence describing a novel algorithmic approach
810
+ 6. Focus on creative, ambitious ideas that haven't been tried yet
811
+ 7. Consider machine learning, new indicators, regime detection, risk management, etc.
812
+
813
+ IMPORTANT: Edit the CSV file directly. Do not return or print CSV data - just modify the file in place."
814
+
815
+ # Get AI to directly edit the CSV file
816
+ local ai_response
817
+ local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
818
+ if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
819
+ echo "[ERROR] All AI models failed to generate novel ideas" >&2
820
+ cat "$stderr_file" >&2
821
+ rm -f "$temp_csv" "$stderr_file"
571
822
  return 1
572
823
  fi
824
+ rm -f "$stderr_file"
573
825
 
574
- # Process the output using helper function
575
- process_ai_ideas "$ai_output" "$count" "novel"
826
+ echo "[DEBUG] AI response: $ai_response" >&2
827
+
828
+ # Validate that the CSV file was actually modified
829
+ if ! validate_direct_csv_modification "$temp_csv" "$count" "novel"; then
830
+ rm -f "$temp_csv"
831
+ return 1
832
+ fi
576
833
 
577
834
  echo "[INFO] Novel exploration ideas generated successfully"
835
+ return 0
578
836
  }
579
837
 
580
- # Generate hill climbing ideas by getting descriptions from AI
838
+ # Generate hill climbing ideas using direct CSV modification
581
839
  generate_hill_climbing_direct() {
582
840
  local count="$1"
583
841
  local top_performers="$2"
584
842
 
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
- ")
843
+ # Create temporary CSV copy
844
+ local temp_csv="/tmp/claude-evolve-temp-csv-$$.csv"
845
+ cp "$FULL_CSV_PATH" "$temp_csv"
602
846
 
603
- local prompt="Generate exactly $count parameter tuning ideas for successful trading algorithms.
604
-
605
- Successful algorithms to tune (pick one as parent):
606
- $top_performers
607
-
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.
610
-
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.
847
+ echo "[INFO] Generating $count hill climbing ideas..."
848
+ echo "[DEBUG] Original CSV has $(wc -l < "$FULL_CSV_PATH") lines" >&2
849
+
850
+ # Extract just the IDs from top performers for clarity
851
+ local valid_parent_ids
852
+ valid_parent_ids=$(echo "$top_performers" | cut -d',' -f1 | paste -sd ',' -)
853
+
854
+ local prompt="Please add exactly $count parameter tuning ideas directly to the CSV file $temp_csv.
615
855
 
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
856
+ IMPORTANT: You MUST use one of these exact parent IDs: $valid_parent_ids
620
857
 
621
- Output exactly $count lines now:"
858
+ Successful algorithms to tune:
859
+ $top_performers
622
860
 
623
- echo "[INFO] Generating $count hill climbing ideas..."
624
-
625
- # Get AI response
626
- local ai_output
627
- if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
628
- echo "[WARN] AI failed to generate hill climbing ideas" >&2
861
+ CRITICAL INSTRUCTION: Before generating parameter tuning ideas, you MUST read the source code of the parent algorithms.
862
+ Algorithm source files are located at: $FULL_OUTPUT_DIR/evolution_<PARENT_ID>.py
863
+ For example: $FULL_OUTPUT_DIR/evolution_gen01-251.py
864
+
865
+ Instructions:
866
+ 1. Read the current CSV file to see existing entries
867
+ 2. Add exactly $count new rows to the CSV file
868
+ 3. Use the next available generation numbers (gen$CURRENT_GENERATION-XXX format)
869
+ 4. For each idea, create a row with: id,parent_id,description,,pending
870
+ 5. Each parent_id MUST be one of: $valid_parent_ids
871
+ 6. Each description should focus on adjusting specific parameters that exist in the parent's source code
872
+ 7. Include current and new parameter values (e.g., \"Lower rsi_entry from 21 to 18\")
873
+
874
+ IMPORTANT: Edit the CSV file directly. Do not return or print CSV data - just modify the file in place."
875
+
876
+ # Get AI to directly edit the CSV file
877
+ local ai_response
878
+ local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
879
+ if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
880
+ echo "[ERROR] All AI models failed to generate hill climbing ideas" >&2
881
+ cat "$stderr_file" >&2
882
+ rm -f "$temp_csv" "$stderr_file"
629
883
  return 1
630
884
  fi
885
+ rm -f "$stderr_file"
631
886
 
632
- # Process the output using helper function
633
- process_ai_ideas "$ai_output" "$count" "hill-climbing" "$top_performers"
887
+ echo "[DEBUG] AI response: $ai_response" >&2
888
+
889
+ # Validate that the CSV file was actually modified
890
+ if ! validate_direct_csv_modification "$temp_csv" "$count" "hill-climbing"; then
891
+ rm -f "$temp_csv"
892
+ return 1
893
+ fi
634
894
 
635
895
  echo "[INFO] Hill climbing ideas generated successfully"
896
+ return 0
636
897
  }
637
898
 
638
- # Generate structural mutation ideas by getting descriptions from AI
899
+ # Generate structural mutation ideas using direct CSV modification
639
900
  generate_structural_mutation_direct() {
640
901
  local count="$1"
641
902
  local top_performers="$2"
642
903
 
643
- local prompt="Generate exactly $count structural modification ideas for successful trading algorithms.
904
+ # Create temporary CSV copy
905
+ local temp_csv="/tmp/claude-evolve-temp-csv-$$.csv"
906
+ cp "$FULL_CSV_PATH" "$temp_csv"
907
+
908
+ echo "[INFO] Generating $count structural mutation ideas..."
909
+ echo "[DEBUG] Original CSV has $(wc -l < "$FULL_CSV_PATH") lines" >&2
910
+
911
+ # Extract just the IDs from top performers for clarity
912
+ local valid_parent_ids
913
+ valid_parent_ids=$(echo "$top_performers" | cut -d',' -f1 | paste -sd ',' -)
914
+
915
+ local prompt="Please add exactly $count structural modification ideas directly to the CSV file $temp_csv.
916
+
917
+ IMPORTANT: You MUST use one of these exact parent IDs: $valid_parent_ids
644
918
 
645
919
  Successful algorithms to modify structurally:
646
920
  $top_performers
647
921
 
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.
650
-
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
655
-
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
660
-
661
- Output exactly $count lines now:"
662
-
663
- echo "[INFO] Generating $count structural mutation ideas..."
664
-
665
- # Get AI response
666
- local ai_output
667
- if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
668
- echo "[WARN] AI failed to generate structural mutation ideas" >&2
922
+ CRITICAL INSTRUCTION: Before generating structural modification ideas, you MUST read the source code of the parent algorithms.
923
+ Algorithm source files are located at: $FULL_OUTPUT_DIR/evolution_<PARENT_ID>.py
924
+ For example: $FULL_OUTPUT_DIR/evolution_gen01-251.py
925
+
926
+ Instructions:
927
+ 1. Read the current CSV file to see existing entries
928
+ 2. Add exactly $count new rows to the CSV file
929
+ 3. Use the next available generation numbers (gen$CURRENT_GENERATION-XXX format)
930
+ 4. For each idea, create a row with: id,parent_id,description,,pending
931
+ 5. Each parent_id MUST be one of: $valid_parent_ids
932
+ 6. Each description should focus on architectural/structural changes based on the parent's actual code
933
+ 7. Reference actual components/methods found in the source code
934
+
935
+ IMPORTANT: Edit the CSV file directly. Do not return or print CSV data - just modify the file in place."
936
+
937
+ # Get AI to directly edit the CSV file
938
+ local ai_response
939
+ local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
940
+ if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
941
+ echo "[ERROR] All AI models failed to generate structural mutation ideas" >&2
942
+ cat "$stderr_file" >&2
943
+ rm -f "$temp_csv" "$stderr_file"
669
944
  return 1
670
945
  fi
946
+ rm -f "$stderr_file"
947
+
948
+ echo "[DEBUG] AI response: $ai_response" >&2
671
949
 
672
- # Process the output using helper function
673
- process_ai_ideas "$ai_output" "$count" "structural" "$top_performers"
950
+ # Validate that the CSV file was actually modified
951
+ if ! validate_direct_csv_modification "$temp_csv" "$count" "structural"; then
952
+ rm -f "$temp_csv"
953
+ return 1
954
+ fi
674
955
 
675
956
  echo "[INFO] Structural mutation ideas generated successfully"
957
+ return 0
676
958
  }
677
959
 
678
- # Generate crossover hybrid ideas by getting descriptions from AI
960
+ # Generate crossover hybrid ideas using direct CSV modification
679
961
  generate_crossover_direct() {
680
962
  local count="$1"
681
963
  local top_performers="$2"
682
964
 
683
- local prompt="Generate exactly $count hybrid combination ideas from successful trading algorithms.
965
+ # Create temporary CSV copy
966
+ local temp_csv="/tmp/claude-evolve-temp-csv-$$.csv"
967
+ cp "$FULL_CSV_PATH" "$temp_csv"
968
+
969
+ echo "[INFO] Generating $count crossover hybrid ideas..."
970
+ echo "[DEBUG] Original CSV has $(wc -l < "$FULL_CSV_PATH") lines" >&2
971
+
972
+ # Extract just the IDs from top performers for clarity
973
+ local valid_parent_ids
974
+ valid_parent_ids=$(echo "$top_performers" | cut -d',' -f1 | paste -sd ',' -)
975
+
976
+ local prompt="Please add exactly $count hybrid combination ideas directly to the CSV file $temp_csv.
977
+
978
+ IMPORTANT: You MUST use ONLY these exact parent IDs: $valid_parent_ids
684
979
 
685
980
  Top performers to combine (reference at least 2 in each idea):
686
981
  $top_performers
687
982
 
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.
690
-
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
695
-
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
700
-
701
- Output exactly $count lines now:"
702
-
703
- echo "[INFO] Generating $count crossover hybrid ideas..."
704
-
705
- # Get AI response
706
- local ai_output
707
- if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
708
- echo "[WARN] AI failed to generate crossover ideas" >&2
983
+ CRITICAL INSTRUCTION: Before generating hybrid combination ideas, you MUST read the source code of the parent algorithms.
984
+ Algorithm source files are located at: $FULL_OUTPUT_DIR/evolution_<PARENT_ID>.py
985
+ For example: $FULL_OUTPUT_DIR/evolution_gen01-251.py
986
+
987
+ Instructions:
988
+ 1. Read the current CSV file to see existing entries
989
+ 2. Add exactly $count new rows to the CSV file
990
+ 3. Use the next available generation numbers (gen$CURRENT_GENERATION-XXX format)
991
+ 4. For each idea, create a row with: id,parent_id,description,,pending
992
+ 5. Each parent_id MUST be one of: $valid_parent_ids (choose the primary parent)
993
+ 6. Each description should combine actual elements from 2+ algorithms based on their source code
994
+ 7. Reference specific components/features found in the actual source code
995
+
996
+ IMPORTANT: Edit the CSV file directly. Do not return or print CSV data - just modify the file in place."
997
+
998
+ # Get AI to directly edit the CSV file
999
+ local ai_response
1000
+ local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
1001
+ if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
1002
+ echo "[ERROR] All AI models failed to generate crossover hybrid ideas" >&2
1003
+ cat "$stderr_file" >&2
1004
+ rm -f "$temp_csv" "$stderr_file"
709
1005
  return 1
710
1006
  fi
1007
+ rm -f "$stderr_file"
711
1008
 
712
- # Process the output using helper function
713
- process_ai_ideas "$ai_output" "$count" "crossover" "$top_performers"
1009
+ echo "[DEBUG] AI response: $ai_response" >&2
1010
+
1011
+ # Validate that the CSV file was actually modified
1012
+ if ! validate_direct_csv_modification "$temp_csv" "$count" "crossover"; then
1013
+ rm -f "$temp_csv"
1014
+ return 1
1015
+ fi
714
1016
 
715
1017
  echo "[INFO] Crossover hybrid ideas generated successfully"
1018
+ return 0
716
1019
  }
717
1020
 
718
1021
  # Legacy AI generation mode (for backward compatibility)
@@ -722,6 +1025,13 @@ ideate_ai_legacy() {
722
1025
  exit 1
723
1026
  fi
724
1027
 
1028
+ # Create temporary CSV copy
1029
+ local temp_csv="/tmp/claude-evolve-temp-csv-$$.csv"
1030
+ cp "$FULL_CSV_PATH" "$temp_csv"
1031
+
1032
+ echo "[INFO] Generating $TOTAL_IDEAS ideas (legacy mode)..."
1033
+ echo "[DEBUG] Original CSV has $(wc -l < "$FULL_CSV_PATH") lines" >&2
1034
+
725
1035
  # Get top performers for context
726
1036
  local top_performers=""
727
1037
  if [[ -f "$FULL_CSV_PATH" ]]; then
@@ -729,8 +1039,8 @@ ideate_ai_legacy() {
729
1039
  top_performers=$(awk -F, 'NR > 1 && $4 != "" { print $1 ": " $3 " (score: " $4 ")" }' "$FULL_CSV_PATH" | head -5)
730
1040
  fi
731
1041
 
732
- # Build prompt for description-only output
733
- local prompt="Generate exactly $TOTAL_IDEAS novel algorithmic ideas for trading algorithm evolution.
1042
+ # Build prompt for direct CSV modification
1043
+ local prompt="Please add exactly $TOTAL_IDEAS algorithmic ideas directly to the CSV file $temp_csv.
734
1044
 
735
1045
  Algorithm files for context:
736
1046
  - Base algorithm: $FULL_ALGORITHM_PATH
@@ -753,13 +1063,13 @@ $top_performers"
753
1063
 
754
1064
  prompt+="
755
1065
 
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:'
1066
+ Instructions:
1067
+ 1. Read the current CSV file to see existing entries
1068
+ 2. Add exactly $TOTAL_IDEAS new rows to the CSV file
1069
+ 3. Use the next available generation numbers (gen$CURRENT_GENERATION-XXX format)
1070
+ 4. For each idea, create a row with: id,parent_id,description,,pending
1071
+ 5. Mix both parameter tuning and structural changes
1072
+ 6. If building on existing algorithms, use their ID as parent_id, otherwise leave parent_id empty
763
1073
 
764
1074
  ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
765
1075
 
@@ -773,22 +1083,29 @@ Requirements:
773
1083
  - Time-Based Patterns: Intraday effects, calendar anomalies, volatility timing
774
1084
  - Parameter Optimization: Entry thresholds, indicator periods, strategy weights
775
1085
 
776
- Output exactly $TOTAL_IDEAS lines now:"
1086
+ IMPORTANT: Edit the CSV file directly. Do not return or print CSV data - just modify the file in place."
777
1087
 
778
- echo "[INFO] Generating $TOTAL_IDEAS ideas (legacy mode)..."
779
-
780
- # Get AI response
781
- local ai_output
782
- if ! ai_output=$(call_ai_with_limit_check "$prompt" "$CURRENT_GENERATION" 2>&1); then
783
- echo "[WARN] AI failed to generate ideas" >&2
1088
+ # Get AI to directly edit the CSV file
1089
+ local ai_response
1090
+ local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
1091
+ if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
1092
+ echo "[ERROR] All AI models failed to generate ideas" >&2
1093
+ cat "$stderr_file" >&2
1094
+ rm -f "$temp_csv" "$stderr_file"
784
1095
  return 1
785
1096
  fi
1097
+ rm -f "$stderr_file"
1098
+
1099
+ echo "[DEBUG] AI response: $ai_response" >&2
786
1100
 
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"
1101
+ # Validate that the CSV file was actually modified
1102
+ if ! validate_direct_csv_modification "$temp_csv" "$TOTAL_IDEAS" "mixed"; then
1103
+ rm -f "$temp_csv"
1104
+ return 1
1105
+ fi
790
1106
 
791
1107
  echo "[INFO] Legacy ideas generated"
1108
+ return 0
792
1109
  }
793
1110
 
794
1111
  # Determine generation number for this ideation run