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.
- package/bin/claude-evolve-analyze +29 -13
- package/bin/claude-evolve-clean-invalid +117 -0
- package/bin/claude-evolve-cleanup-duplicates +131 -0
- package/bin/claude-evolve-ideate +433 -310
- package/bin/claude-evolve-run +79 -30
- package/bin/claude-evolve-status +23 -0
- package/bin/claude-evolve-worker +24 -24
- package/lib/__pycache__/evolution_csv.cpython-311.pyc +0 -0
- package/lib/__pycache__/evolution_csv.cpython-313.pyc +0 -0
- package/lib/config.sh +3 -0
- package/lib/csv_helper_robust.py +121 -0
- package/lib/evolution_csv.py +349 -0
- package/package.json +1 -1
package/bin/claude-evolve-ideate
CHANGED
|
@@ -26,11 +26,43 @@ get_model_for_generation() {
|
|
|
26
26
|
gen_num=1 # Default for malformed input
|
|
27
27
|
fi
|
|
28
28
|
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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]
|
|
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
|
-
#
|
|
180
|
-
local max_gen
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
#
|
|
204
|
-
local max_id
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
#
|
|
250
|
-
|
|
251
|
-
|
|
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
|
-
#
|
|
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
|
|
521
|
+
# Generate novel exploration ideas using structured output
|
|
288
522
|
generate_novel_ideas_direct() {
|
|
289
523
|
local count="$1"
|
|
290
524
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
545
|
+
Current evolution context:
|
|
546
|
+
- Generation: $CURRENT_GENERATION
|
|
547
|
+
- Algorithm: $FULL_ALGORITHM_PATH
|
|
548
|
+
- Brief: $(head -20 "$FULL_BRIEF_PATH")
|
|
332
549
|
|
|
333
|
-
|
|
334
|
-
|
|
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
|
-
|
|
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
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
-
|
|
563
|
+
Output exactly $count lines now:"
|
|
352
564
|
|
|
353
565
|
echo "[INFO] Generating $count novel exploration ideas..."
|
|
354
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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
|
|
605
|
+
Successful algorithms to tune (pick one as parent):
|
|
382
606
|
$top_performers
|
|
383
607
|
|
|
384
|
-
|
|
385
|
-
$
|
|
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
|
-
|
|
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
|
-
|
|
412
|
-
-
|
|
413
|
-
-
|
|
414
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
460
|
-
$
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
661
|
+
Output exactly $count lines now:"
|
|
503
662
|
|
|
504
663
|
echo "[INFO] Generating $count structural mutation ideas..."
|
|
505
|
-
|
|
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
|
-
|
|
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
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
536
|
-
$
|
|
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
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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="
|
|
732
|
+
# Build prompt for description-only output
|
|
733
|
+
local prompt="Generate exactly $TOTAL_IDEAS novel algorithmic ideas for trading algorithm evolution.
|
|
604
734
|
|
|
605
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
- Each
|
|
635
|
-
-
|
|
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
|
-
-
|
|
651
|
-
-
|
|
652
|
-
-
|
|
653
|
-
-
|
|
654
|
-
-
|
|
655
|
-
-
|
|
656
|
-
-
|
|
657
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|