{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Trading Code Generator\n",
"\n",
"This notebook creates a code generator that produces trading code to buy and sell equities in a simulated environment based on free APIs. It uses Gradio for the UI, similar to the approach in day5.ipynb.\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import io\n",
"import sys\n",
"import time\n",
"import random\n",
"import numpy as np\n",
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"import gradio as gr\n",
"from IPython.display import display\n",
"from huggingface_hub import InferenceClient\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OpenAI API Key exists and begins sk-proj-\n",
"Hugging Face Token exists and begins hf_fNncb\n"
]
}
],
"source": [
"load_dotenv(override=True)\n",
"openai_api_key = os.getenv('OPENAI_API_KEY')\n",
"hf_token = os.getenv('HF_TOKEN')\n",
"\n",
"if openai_api_key:\n",
" print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n",
"else:\n",
" print(\"OpenAI API Key not set\")\n",
" \n",
"if hf_token:\n",
" print(f\"Hugging Face Token exists and begins {hf_token[:8]}\")\n",
"else:\n",
" print(\"Hugging Face Token not set\")\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"openai_client = OpenAI()\n",
"hf_client = InferenceClient(token=hf_token)\n"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
"models = [\"gpt-4o\", \"gpt-3.5-turbo\", \"meta-llama/Llama-2-70b-chat-hf\"]\n",
"\n",
"def generate_with_openai(model, messages):\n",
" response = openai_client.chat.completions.create(\n",
" model=model, \n",
" messages=messages\n",
" )\n",
" return response.choices[0].message.content\n",
"\n",
"def generate_with_hf(model, messages):\n",
" prompt = \"\"\n",
" for msg in messages:\n",
" role = msg[\"role\"]\n",
" content = msg[\"content\"]\n",
" if role == \"system\":\n",
" prompt += f\"[INST] {content} [/INST]\\n\"\n",
" elif role == \"user\":\n",
" prompt += f\"[INST] {content} [/INST]\\n\"\n",
" else:\n",
" prompt += f\"{content}\\n\"\n",
" \n",
" response = hf_client.text_generation(\n",
" prompt,\n",
" model=model,\n",
" max_new_tokens=1024,\n",
" temperature=0.7,\n",
" repetition_penalty=1.2\n",
" )\n",
" return response\n"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"CSS = \"\"\"\n",
":root {\n",
" --py-color: #209dd7;\n",
" --trading-color: #27ae60;\n",
" --accent: #753991;\n",
" --card: #161a22;\n",
" --text: #e9eef5;\n",
"}\n",
"\n",
"/* Full-width layout */\n",
".gradio-container {\n",
" max-width: 100% !important;\n",
" padding: 0 40px !important;\n",
"}\n",
"\n",
"/* Code card styling */\n",
".card {\n",
" background: var(--card);\n",
" border: 1px solid rgba(255,255,255,.08);\n",
" border-radius: 14px;\n",
" padding: 10px;\n",
"}\n",
"\n",
"/* Make code block scrollable but fixed height */\n",
"#code-block {\n",
" max-height: 400px !important;\n",
" overflow-y: auto !important;\n",
"}\n",
"\n",
"#code-block .cm-editor {\n",
" height: 400px !important;\n",
"}\n",
"\n",
"/* Buttons */\n",
".generate-btn button {\n",
" background: var(--accent) !important;\n",
" border-color: rgba(255,255,255,.12) !important;\n",
" color: white !important;\n",
" font-weight: 700;\n",
"}\n",
".run-btn button {\n",
" background: #202631 !important;\n",
" color: var(--text) !important;\n",
" border-color: rgba(255,255,255,.12) !important;\n",
"}\n",
".run-btn.py button:hover { box-shadow: 0 0 0 2px var(--py-color) inset; }\n",
".run-btn.trading button:hover { box-shadow: 0 0 0 2px var(--trading-color) inset; }\n",
".generate-btn button:hover { box-shadow: 0 0 0 2px var(--accent) inset; }\n",
"\n",
"/* Outputs with color tint */\n",
".py-out textarea {\n",
" background: linear-gradient(180deg, rgba(32,157,215,.18), rgba(32,157,215,.10));\n",
" border: 1px solid rgba(32,157,215,.35) !important;\n",
" color: rgba(32,157,215,1) !important;\n",
" font-weight: 600;\n",
"}\n",
".trading-out textarea {\n",
" background: linear-gradient(180deg, rgba(39,174,96,.18), rgba(39,174,96,.10));\n",
" border: 1px solid rgba(39,174,96,.35) !important;\n",
" color: rgba(39,174,96,1) !important;\n",
" font-weight: 600;\n",
"}\n",
"\n",
"/* Align controls neatly */\n",
".controls .wrap {\n",
" gap: 10px;\n",
" justify-content: center;\n",
" align-items: center;\n",
"}\n",
"\"\"\"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"system_prompt = \"\"\"\n",
"You are an expert algorithmic trading code generator. Generate clean, bug-free Python code for trading strategies.\n",
"\n",
"Generate code that:\n",
"1. Uses synthetic data generation only - no API calls\n",
"2. Implements the specified trading strategy\n",
"3. Uses proper error handling\n",
"4. Visualizes strategy performance with buy/sell signals\n",
"5. Calculates performance metrics\n",
"6. Handles edge cases properly\n",
"\n",
"REQUIREMENTS:\n",
"1. Include if __name__ == \"__main__\": block that executes immediately\n",
"2. Define all variables before use\n",
"3. Pass parameters between functions, avoid global variables\n",
"4. NO explanatory text outside of code\n",
"5. NO markdown blocks or language indicators\n",
"6. Code must execute without user input\n",
"7. Use str() for pandas objects in f-strings\n",
"8. Use .copy() for DataFrame views that will be modified\n",
"9. Include min_periods in rolling calculations\n",
"10. Check array lengths before scatter plots\n",
"11. Configure logging properly\n",
"12. Include helper functions for formatting and plotting\n",
"\n",
"Respond ONLY with Python code. No explanations or markdown.\n",
"\"\"\"\n",
"\n",
"def user_prompt_for(description):\n",
" return f\"\"\"\n",
"Generate Python code for a trading strategy:\n",
"\n",
"{description}\n",
"\n",
"Requirements:\n",
"1. Use synthetic data generation only\n",
"2. Implement the strategy exactly as described\n",
"3. Include backtesting functionality\n",
"4. Visualize results with matplotlib\n",
"5. Calculate performance metrics\n",
"6. Handle all edge cases\n",
"7. No comments needed\n",
"\n",
"Make the code complete and runnable as-is with all necessary imports.\n",
"\"\"\"\n"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {},
"outputs": [],
"source": [
"def messages_for(description):\n",
" return [\n",
" {\"role\": \"system\", \"content\": system_prompt},\n",
" {\"role\": \"user\", \"content\": user_prompt_for(description)}\n",
" ]\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def validate_code(code):\n",
" issues = []\n",
" if \"import yfinance\" not in code and \"from yfinance\" not in code:\n",
" issues.append(\"Missing yfinance import\")\n",
" if \"import matplotlib\" not in code and \"from matplotlib\" not in code:\n",
" issues.append(\"Missing matplotlib import\")\n",
" if \"__name__ == \\\"__main__\\\"\" not in code and \"__name__ == '__main__'\" not in code:\n",
" issues.append(\"Missing if __name__ == '__main__' block\")\n",
" if \"f\\\"\" in code or \"f'\" in code:\n",
" lines = code.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if ('f\"' in line or \"f'\" in line) and ('data[' in line or '.iloc' in line or '.loc' in line):\n",
" issues.append(f\"Potentially unsafe f-string formatting with pandas objects on line {i+1}\")\n",
" if \"try:\" in code and \"except\" not in code:\n",
" issues.append(\"Try block without except clause\")\n",
" if \"rolling\" in code and \"min_periods\" not in code:\n",
" issues.append(\"Rolling window without min_periods parameter (may produce NaN values)\")\n",
" if \".loc\" in code and \"iloc\" not in code and \"copy()\" not in code:\n",
" issues.append(\"Potential pandas SettingWithCopyWarning - consider using .copy() before modifications\")\n",
" lines = code.split('\\n')\n",
" defined_vars = set()\n",
" for line in lines:\n",
" if line.strip().startswith('#') or not line.strip():\n",
" continue\n",
" if '=' in line and not line.strip().startswith('if') and not line.strip().startswith('elif') and not line.strip().startswith('while'):\n",
" var_name = line.split('=')[0].strip()\n",
" if var_name:\n",
" defined_vars.add(var_name)\n",
" if issues:\n",
" return False, issues\n",
" return True, []\n",
"\n",
"def generate_trading_code(model, description, force_gpt4=False):\n",
" messages = messages_for(description)\n",
" if force_gpt4:\n",
" try:\n",
" reply = generate_with_openai(\"gpt-4o\", messages)\n",
" except Exception as e:\n",
" print(f\"Error using GPT-4o: {e}. Falling back to selected model.\")\n",
" if \"gpt\" in model.lower():\n",
" reply = generate_with_openai(model, messages)\n",
" else:\n",
" reply = generate_with_hf(model, messages)\n",
" else:\n",
" if \"gpt\" in model.lower():\n",
" reply = generate_with_openai(model, messages)\n",
" else:\n",
" reply = generate_with_hf(model, messages)\n",
" reply = reply.replace('```python','').replace('```','')\n",
" is_valid, issues = validate_code(reply)\n",
" max_attempts = 3\n",
" attempt = 0\n",
" fix_model = \"gpt-4o\" if force_gpt4 else model\n",
" while not is_valid and attempt < max_attempts and (\"gpt\" in model.lower() or force_gpt4):\n",
" attempt += 1\n",
" fix_messages = messages.copy()\n",
" fix_messages.append({\"role\": \"assistant\", \"content\": reply})\n",
" fix_request = f\"\"\"The code has the following issues that need to be fixed:\n",
"{chr(10).join([f\"- {issue}\" for issue in issues])}\n",
"\n",
"Please provide a completely corrected version that addresses these issues. Make sure to:\n",
"\n",
"1. Avoid using f-strings with pandas Series or DataFrame objects directly\n",
"2. Always handle NaN values in calculations with proper checks\n",
"3. Use proper error handling with try/except blocks around all API calls and calculations\n",
"4. Include min_periods parameter in rolling window calculations\n",
"5. Use .copy() when creating views of DataFrames that will be modified\n",
"6. Make sure all variables are properly defined before use\n",
"7. Add yfinance timeout settings: yf.set_timeout(30)\n",
"8. Add proper logging for all steps\n",
"9. Use synthetic data generation as a fallback if API calls fail\n",
"10. Include proper if __name__ == \"__main__\" block\n",
"\n",
"Return ONLY the corrected code with no explanation or markdown formatting.\n",
"\"\"\"\n",
" fix_messages.append({\"role\": \"user\", \"content\": fix_request})\n",
" try:\n",
" if force_gpt4:\n",
" fixed_reply = generate_with_openai(\"gpt-4o\", fix_messages)\n",
" else:\n",
" if \"gpt\" in model.lower():\n",
" fixed_reply = generate_with_openai(model, fix_messages)\n",
" else:\n",
" fixed_reply = generate_with_hf(model, fix_messages)\n",
" fixed_reply = fixed_reply.replace('```python','').replace('```','')\n",
" is_fixed_valid, fixed_issues = validate_code(fixed_reply)\n",
" if is_fixed_valid or len(fixed_issues) < len(issues):\n",
" reply = fixed_reply\n",
" is_valid = is_fixed_valid\n",
" issues = fixed_issues\n",
" except Exception as e:\n",
" print(f\"Error during fix attempt {attempt}: {e}\")\n",
" reply = add_safety_features(reply)\n",
" return reply\n",
"\n",
"def add_safety_features(code):\n",
" if \"pandas\" in code:\n",
" safety_imports = \"\"\"\n",
"import pandas as pd\n",
"pd.set_option('display.float_format', '{:.5f}'.format)\n",
"\n",
"def safe_format(obj):\n",
" if isinstance(obj, (pd.Series, pd.DataFrame)):\n",
" return str(obj)\n",
" return obj\n",
"\"\"\"\n",
" import_lines = [i for i, line in enumerate(code.split('\\n')) if 'import' in line]\n",
" if import_lines:\n",
" lines = code.split('\\n')\n",
" lines.insert(import_lines[-1] + 1, safety_imports)\n",
" code = '\\n'.join(lines)\n",
" code = code.replace(\"yf.set_timeout(30)\", \"\")\n",
" code = code.replace(\"yf.pdr_override()\", \"\")\n",
" lines = code.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if 'f\"' in line or \"f'\" in line:\n",
" if any(term in line for term in ['data[', '.iloc', '.loc', 'Series', 'DataFrame']):\n",
" for term in ['.mean()', '.sum()', '.std()', '.min()', '.max()']:\n",
" if term in line:\n",
" lines[i] = line.replace(f\"{term}\", f\"{term})\")\n",
" lines[i] = lines[i].replace(\"f\\\"\", \"f\\\"{safe_format(\")\n",
" lines[i] = lines[i].replace(\"f'\", \"f'{safe_format(\")\n",
" code = '\\n'.join(lines)\n",
" if \"plt.scatter\" in code or \".scatter\" in code:\n",
" scatter_safety = \"\"\"\n",
"def safe_scatter(ax, x, y, *args, **kwargs):\n",
" if len(x) != len(y):\n",
" min_len = min(len(x), len(y))\n",
" x = x[:min_len]\n",
" y = y[:min_len]\n",
" if len(x) == 0 or len(y) == 0:\n",
" return None\n",
" return ax.scatter(x, y, *args, **kwargs)\n",
"\"\"\"\n",
" func_lines = [i for i, line in enumerate(code.split('\\n')) if line.startswith('def ')]\n",
" if func_lines:\n",
" lines = code.split('\\n')\n",
" lines.insert(func_lines[0], scatter_safety)\n",
" code = '\\n'.join(lines)\n",
" code = code.replace(\"plt.scatter(\", \"safe_scatter(plt.gca(), \")\n",
" code = code.replace(\".scatter(\", \"safe_scatter(\")\n",
" if \"yfinance\" in code and \"generate_synthetic_data\" not in code:\n",
" synthetic_data_func = \"\"\"\n",
"def generate_synthetic_data(ticker='AAPL', start_date=None, end_date=None, days=252, seed=42):\n",
" import numpy as np\n",
" import pandas as pd\n",
" from datetime import datetime, timedelta\n",
" if start_date is None:\n",
" end_date = datetime.now()\n",
" start_date = end_date - timedelta(days=days)\n",
" elif end_date is None:\n",
" if isinstance(start_date, str):\n",
" start_date = pd.to_datetime(start_date)\n",
" end_date = datetime.now()\n",
" np.random.seed(seed)\n",
" if isinstance(start_date, str):\n",
" start = pd.to_datetime(start_date)\n",
" else:\n",
" start = start_date\n",
" if isinstance(end_date, str):\n",
" end = pd.to_datetime(end_date)\n",
" else:\n",
" end = end_date\n",
" days = (end - start).days + 1\n",
" price = 100\n",
" prices = [price]\n",
" for _ in range(days):\n",
" change = np.random.normal(0, 0.01)\n",
" price *= (1 + change)\n",
" prices.append(price)\n",
" dates = pd.date_range(start=start, end=end, periods=len(prices))\n",
" df = pd.DataFrame({\n",
" 'Open': prices[:-1],\n",
" 'High': [p * 1.01 for p in prices[:-1]],\n",
" 'Low': [p * 0.99 for p in prices[:-1]],\n",
" 'Close': prices[1:],\n",
" 'Volume': [np.random.randint(1000000, 10000000) for _ in range(len(prices)-1)]\n",
" }, index=dates[:-1])\n",
" return df\n",
"\"\"\"\n",
" func_lines = [i for i, line in enumerate(code.split('\\n')) if line.startswith('def ')]\n",
" if func_lines:\n",
" lines = code.split('\\n')\n",
" lines.insert(func_lines[0], synthetic_data_func)\n",
" code = '\\n'.join(lines)\n",
" if \"logging\" in code and \"basicConfig\" not in code:\n",
" logging_config = \"\"\"\n",
"import logging\n",
"logging.basicConfig(\n",
" level=logging.INFO,\n",
" format='[%(asctime)s] %(levelname)s: %(message)s',\n",
" datefmt='%H:%M:%S'\n",
")\n",
"\"\"\"\n",
" import_lines = [i for i, line in enumerate(code.split('\\n')) if 'import' in line]\n",
" if import_lines:\n",
" lines = code.split('\\n')\n",
" lines.insert(import_lines[-1] + 1, logging_config)\n",
" code = '\\n'.join(lines)\n",
" if \"yfinance\" in code and \"try:\" not in code:\n",
" lines = code.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if \"yf.download\" in line and \"try:\" not in lines[max(0, i-5):i]:\n",
" indent = len(line) - len(line.lstrip())\n",
" indent_str = \" \" * indent\n",
" lines[i] = f\"{indent_str}try:\\n{indent_str} {line}\\n{indent_str}except Exception as e:\\n{indent_str} logging.error(f\\\"Error fetching data: {{e}}\\\")\\n{indent_str} # Use synthetic data as fallback\\n{indent_str} data = generate_synthetic_data(ticker, start_date, end_date)\"\n",
" code = '\\n'.join(lines)\n",
" break\n",
" if \"synthetic data\" in code.lower() and \"yf.download\" in code:\n",
" lines = code.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if \"yf.download\" in line:\n",
" indent = len(line) - len(line.lstrip())\n",
" indent_str = \" \" * indent\n",
" comment = f\"{indent_str}# Using synthetic data instead of API call\\n\"\n",
" synthetic = f\"{indent_str}data = generate_synthetic_data(ticker, start_date, end_date)\\n\"\n",
" lines[i] = f\"{indent_str}# {line.strip()} # Commented out to avoid API issues\"\n",
" lines.insert(i+1, comment + synthetic)\n",
" code = '\\n'.join(lines)\n",
" break\n",
" if \"plt.figure\" in code:\n",
" lines = code.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if \"plt.figure\" in line and \"try:\" not in lines[max(0, i-5):i]:\n",
" indent = len(line) - len(line.lstrip())\n",
" indent_str = \" \" * indent\n",
" try_line = f\"{indent_str}try:\\n{indent_str} \"\n",
" except_line = f\"\\n{indent_str}except Exception as e:\\n{indent_str} logging.error(f\\\"Error in plotting: {{e}}\\\")\"\n",
" j = i\n",
" while j < len(lines) and (j == i or lines[j].startswith(indent_str)):\n",
" j += 1\n",
" for k in range(i, j):\n",
" if lines[k].strip():\n",
" lines[k] = indent_str + \" \" + lines[k].lstrip()\n",
" lines.insert(i, try_line.rstrip())\n",
" lines.insert(j+1, except_line)\n",
" code = '\\n'.join(lines)\n",
" break\n",
" lines = code.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if \"print(\" in line and any(term in line for term in ['data[', '.iloc', '.loc', 'Series', 'DataFrame']):\n",
" lines[i] = line.replace(\"print(\", \"print(safe_format(\")\n",
" if \"))\" not in lines[i] and \"),\" in lines[i]:\n",
" lines[i] = lines[i].replace(\"),\", \")),\", 1)\n",
" elif \"))\" not in lines[i] and \")\" in lines[i]:\n",
" lines[i] = lines[i].replace(\")\", \"))\", 1)\n",
" code = '\\n'.join(lines)\n",
" return code\n"
]
},
{
"cell_type": "code",
"execution_count": 114,
"metadata": {},
"outputs": [],
"source": [
"def run_python(code):\n",
" # Create a completely separate namespace for execution\n",
" namespace = {\n",
" '__name__': '__main__',\n",
" '__builtins__': __builtins__\n",
" }\n",
" \n",
" # Modify the code to use a non-interactive matplotlib backend\n",
" # and fix pandas formatting issues\n",
" modified_code = \"\"\"\n",
"import matplotlib\n",
"matplotlib.use('Agg') # Use non-interactive backend\n",
"\n",
"# Import yfinance without setting timeout (not available in all versions)\n",
"import yfinance as yf\n",
"\n",
"# Configure logging to show in the output\n",
"import logging\n",
"logging.basicConfig(\n",
" level=logging.INFO,\n",
" format='[%(asctime)s] %(levelname)s: %(message)s',\n",
" datefmt='%H:%M:%S'\n",
")\n",
"\n",
"# Fix pandas formatting issues\n",
"import pandas as pd\n",
"pd.set_option('display.float_format', '{:.5f}'.format)\n",
"\n",
"# Override print to ensure it flushes immediately\n",
"import builtins\n",
"original_print = builtins.print\n",
"def custom_print(*args, **kwargs):\n",
" result = original_print(*args, **kwargs)\n",
" import sys\n",
" sys.stdout.flush()\n",
" return result\n",
"builtins.print = custom_print\n",
"\n",
"# Helper function to safely format pandas objects\n",
"def safe_format(obj):\n",
" if isinstance(obj, (pd.Series, pd.DataFrame)):\n",
" return str(obj)\n",
" else:\n",
" return obj\n",
"\"\"\"\n",
" \n",
" # Add the user's code\n",
" modified_code += \"\\n\" + code\n",
" \n",
" # Capture all output\n",
" output_buffer = io.StringIO()\n",
" \n",
" # Save original stdout and redirect to our buffer\n",
" original_stdout = sys.stdout\n",
" sys.stdout = output_buffer\n",
" \n",
" # Add timestamp for execution start\n",
" print(f\"[{time.strftime('%H:%M:%S')}] Executing code...\")\n",
" \n",
" try:\n",
" # Execute the modified code\n",
" exec(modified_code, namespace)\n",
" print(f\"\\n[{time.strftime('%H:%M:%S')}] Execution completed successfully.\")\n",
" \n",
" except ModuleNotFoundError as e:\n",
" missing_module = str(e).split(\"'\")[1]\n",
" print(f\"\\nError: Missing module '{missing_module}'. Click 'Install Dependencies' to install it.\")\n",
" namespace[\"__missing_module__\"] = missing_module\n",
" \n",
" except Exception as e:\n",
" print(f\"\\n[{time.strftime('%H:%M:%S')}] Error during execution: {str(e)}\")\n",
" import traceback\n",
" print(traceback.format_exc())\n",
" \n",
" finally:\n",
" # Restore original stdout\n",
" sys.stdout = original_stdout\n",
" \n",
" # Return the captured output\n",
" return output_buffer.getvalue()\n",
"\n",
"def install_dependencies(code):\n",
" import re\n",
" import subprocess\n",
" \n",
" import_pattern = r'(?:from|import)\\s+([a-zA-Z0-9_]+)(?:\\s+(?:import|as))?'\n",
" imports = re.findall(import_pattern, code)\n",
" \n",
" std_libs = ['os', 'sys', 'io', 'time', 'datetime', 'random', 'math', 're', 'json', \n",
" 'collections', 'itertools', 'functools', 'operator', 'pathlib', 'typing']\n",
" \n",
" modules_to_install = [module for module in imports if module not in std_libs]\n",
" \n",
" if not modules_to_install:\n",
" return \"No external dependencies found to install.\"\n",
" \n",
" results = []\n",
" for module in modules_to_install:\n",
" try:\n",
" result = subprocess.run(\n",
" [sys.executable, \"-m\", \"pip\", \"install\", module],\n",
" capture_output=True,\n",
" text=True,\n",
" check=False\n",
" )\n",
" \n",
" if result.returncode == 0:\n",
" results.append(f\"Successfully installed {module}\")\n",
" else:\n",
" results.append(f\"Failed to install {module}: {result.stderr}\")\n",
" except Exception as e:\n",
" results.append(f\"Error installing {module}: {str(e)}\")\n",
" \n",
" return \"\\n\".join(results)\n"
]
},
{
"cell_type": "code",
"execution_count": 109,
"metadata": {},
"outputs": [],
"source": [
"trading_strategies = [\n",
" {\n",
" \"name\": \"Moving Average Crossover\",\n",
" \"description\": \"Moving Average Crossover strategy for S&P 500 stocks. Buy when the 20-day moving average crosses above the 50-day moving average, and sell when it crosses below.\",\n",
" \"buy_signal\": \"20-day MA crosses above 50-day MA\",\n",
" \"sell_signal\": \"20-day MA crosses below 50-day MA\",\n",
" \"timeframe\": \"Daily\",\n",
" \"risk_level\": \"Medium\"\n",
" },\n",
" {\n",
" \"name\": \"RSI Mean Reversion\",\n",
" \"description\": \"Mean reversion strategy that buys stocks when RSI falls below 30 (oversold) and sells when RSI rises above 70 (overbought).\",\n",
" \"buy_signal\": \"RSI below 30 (oversold)\",\n",
" \"sell_signal\": \"RSI above 70 (overbought)\",\n",
" \"timeframe\": \"Daily\",\n",
" \"risk_level\": \"Medium\"\n",
" },\n",
" {\n",
" \"name\": \"Momentum Strategy\",\n",
" \"description\": \"Momentum strategy that buys the top 5 performing stocks from the Dow Jones Industrial Average over the past month and rebalances monthly.\",\n",
" \"buy_signal\": \"Stock in top 5 performers over past month\",\n",
" \"sell_signal\": \"Stock no longer in top 5 performers at rebalance\",\n",
" \"timeframe\": \"Monthly\",\n",
" \"risk_level\": \"High\"\n",
" },\n",
" {\n",
" \"name\": \"Pairs Trading\",\n",
" \"description\": \"Pairs trading strategy that identifies correlated stock pairs and trades on the divergence and convergence of their price relationship.\",\n",
" \"buy_signal\": \"Pairs ratio deviates 2+ standard deviations below mean\",\n",
" \"sell_signal\": \"Pairs ratio returns to mean or exceeds mean\",\n",
" \"timeframe\": \"Daily\",\n",
" \"risk_level\": \"Medium-High\"\n",
" },\n",
" {\n",
" \"name\": \"Bollinger Band Breakout\",\n",
" \"description\": \"Volatility breakout strategy that buys when a stock breaks out of its upper Bollinger Band and sells when it reverts to the mean.\",\n",
" \"buy_signal\": \"Price breaks above upper Bollinger Band (2 std dev)\",\n",
" \"sell_signal\": \"Price reverts to middle Bollinger Band (SMA)\",\n",
" \"timeframe\": \"Daily\",\n",
" \"risk_level\": \"High\"\n",
" },\n",
" {\n",
" \"name\": \"MACD Crossover\",\n",
" \"description\": \"MACD crossover strategy that buys when the MACD line crosses above the signal line and sells when it crosses below.\",\n",
" \"buy_signal\": \"MACD line crosses above signal line\",\n",
" \"sell_signal\": \"MACD line crosses below signal line\",\n",
" \"timeframe\": \"Daily\",\n",
" \"risk_level\": \"Medium\"\n",
" },\n",
" {\n",
" \"name\": \"Golden Cross\",\n",
" \"description\": \"Golden Cross strategy that buys when the 50-day moving average crosses above the 200-day moving average and sells on the Death Cross (opposite).\",\n",
" \"buy_signal\": \"50-day MA crosses above 200-day MA\",\n",
" \"sell_signal\": \"50-day MA crosses below 200-day MA\",\n",
" \"timeframe\": \"Daily\",\n",
" \"risk_level\": \"Low\"\n",
" }\n",
"]\n",
"\n",
"sample_strategies = [strategy[\"description\"] for strategy in trading_strategies]\n"
]
},
{
"cell_type": "code",
"execution_count": 110,
"metadata": {},
"outputs": [],
"source": [
"default_description = \"\"\"\n",
"Create a moving average crossover strategy with the following specifications:\n",
"- Use yfinance to download historical data for a list of stocks (AAPL, MSFT, AMZN, GOOGL, META)\n",
"- Calculate 20-day and 50-day moving averages\n",
"- Generate buy signals when the 20-day MA crosses above the 50-day MA\n",
"- Generate sell signals when the 20-day MA crosses below the 50-day MA\n",
"- Implement a simple backtesting framework to evaluate the strategy\n",
"- Calculate performance metrics: total return, annualized return, Sharpe ratio, max drawdown\n",
"- Visualize the equity curve, buy/sell signals, and moving averages\n",
"\"\"\"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2025-10-22 18:30:21,233 - INFO - HTTP Request: GET http://127.0.0.1:7875/gradio_api/startup-events \"HTTP/1.1 200 OK\"\n",
"2025-10-22 18:30:21,238 - INFO - HTTP Request: HEAD http://127.0.0.1:7875/ \"HTTP/1.1 200 OK\"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"* Running on local URL: http://127.0.0.1:7875\n",
"* To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"