diff --git a/.gitignore b/.gitignore index be9bfdf9..552b70e7 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,11 @@ QWEN.md # Internal documentation (not for public) TODO.md +# Private prompts (your improved versions) +prompts/local/ +*.local.yaml +*_private.yaml + # Test credentials .env.test *.test.env diff --git a/prompts/README.md b/prompts/README.md new file mode 100644 index 00000000..ce606ece --- /dev/null +++ b/prompts/README.md @@ -0,0 +1,287 @@ +# Predix Prompts + +This directory contains all LLM prompts for the Predix trading agent. + +--- + +## 📁 Directory Structure + +``` +prompts/ +├── standard_prompts.yaml # Default prompts (committed to Git) +├── local/ # YOUR IMPROVED PROMPTS (not in Git!) +│ ├── factor_discovery_v2.yaml +│ ├── optimized_prompts.yaml +│ └── best_performing.yaml +└── README.md # This file +``` + +--- + +## 🎯 How It Works + +**Prompt Loading Priority:** + +1. **`prompts/local/*.yaml`** ← Your improved prompts (loaded first!) +2. **`prompts/standard_prompts.yaml`** ← Default prompts (fallback) + +**Example:** +```python +from rdagent.components.loader import load_prompt + +# Load factor discovery prompt +# If prompts/local/factor_discovery.yaml exists → loads that +# Otherwise → loads from standard_prompts.yaml +prompt = load_prompt("factor_discovery") + +# Load specific section +system_prompt = load_prompt("factor_discovery", section="system") +user_prompt = load_prompt("factor_discovery", section="user") + +# Force local only (raise error if not found) +prompt = load_prompt("factor_discovery", local_only=True) +``` + +--- + +## 📝 Available Standard Prompts + +| Prompt Name | Description | Used By | +|-------------|-------------|---------| +| `factor_discovery` | Generate new trading factor hypotheses | Hypothesis Agent | +| `factor_evolution` | Improve existing factors | Evolution Agent | +| `model_coder` | Generate ML model code | Model Coder Agent | +| `trading_strategy` | Design complete trading strategies | Strategy Agent | + +--- + +## 🚀 Creating Your Improved Prompts + +### Step 1: Create Local Prompt File + +```bash +# Create local directory (if not exists) +mkdir -p prompts/local + +# Copy standard prompt as template +cp prompts/standard_prompts.yaml prompts/local/factor_discovery_v2.yaml +``` + +### Step 2: Edit Your Prompt + +```yaml +# prompts/local/factor_discovery_v2.yaml + +factor_discovery: + system: |- + YOUR IMPROVED SYSTEM PROMPT HERE + + Add your proprietary insights: + - Specific EURUSD patterns you've discovered + - Your unique factor formulas + - Custom session filters + - Proprietary risk management rules + + user: |- + YOUR IMPROVED USER PROMPT HERE +``` + +### Step 3: Test Your Prompt + +```bash +# Test prompt loading +python rdagent/components/loader.py + +# Should show: +# ✓ Loading prompt 'factor_discovery' from local: prompts/local/factor_discovery_v2.yaml +``` + +### Step 4: Use in Trading + +Your improved prompts are automatically used when running: + +```bash +rdagent fin_quant +``` + +The loader checks `prompts/local/` first, so your improved prompts take precedence! + +--- + +## 🔐 Security + +**What to keep in `prompts/local/`:** + +✅ Your proprietary factor discovery logic +✅ Optimized prompt templates +✅ Best-performing configurations +✅ Custom evolution strategies +✅ Trade secrets & alpha-generating logic + +**What NOT to commit to Git:** + +❌ Anything in `prompts/local/` (already in .gitignore) +❌ Files with `.local.yaml` suffix +❌ Files with `_private.yaml` suffix + +--- + +## 📊 Best Practices + +### 1. Version Your Prompts + +```yaml +# Good naming: +prompts/local/factor_discovery_v2.yaml +prompts/local/factor_discovery_v3_optimized.yaml +prompts/local/model_coder_xgboost_v1.yaml +``` + +### 2. Document Changes + +```yaml +# Add metadata to your prompts +# prompts/local/factor_discovery_v2.yaml + +# Version: 2.0 +# Author: Your Name +# Date: 2026-04-02 +# Changes: +# - Added session-specific filters +# - Improved spread cost modeling +# - Target ARR: 12% (up from 9.62%) + +factor_discovery: + system: |- + ... +``` + +### 3. Test Performance + +```python +# Compare prompt versions +from rdagent.components.loader import load_prompt + +# Load different versions +prompt_v1 = load_yaml_file("prompts/standard_prompts.yaml") +prompt_v2 = load_yaml_file("prompts/local/factor_discovery_v2.yaml") + +# Run backtests and compare +# ... +``` + +### 4. Backup Your Prompts + +```bash +# Backup to private repo +cd ~/Predix +git archive --format=tar prompts/local/ | gzip > ~/backups/prompts_local_$(date +%Y%m%d).tar.gz + +# Or sync to private GitHub repo +git clone git@github.com:TPTBusiness/predix-prompts-private.git +cp -r prompts/local/* predix-prompts-private/ +cd predix-prompts-private && git push +``` + +--- + +## 🔧 Advanced Usage + +### Load All Prompts + +```python +from rdagent.components.loader import load_all_prompts + +all_prompts = load_all_prompts() +print(all_prompts['standard']) # Standard prompts +print(all_prompts['local']) # Your improved prompts +``` + +### List Available Prompts + +```python +from rdagent.components.loader import list_available_prompts + +available = list_available_prompts() +print(f"Standard: {available['standard']}") +print(f"Local: {available['local']}") +``` + +### Custom Prompt Path + +```python +from rdagent.components.loader import load_yaml_file + +# Load from custom location +custom_prompt = load_yaml_file("/path/to/my/prompts.yaml") +``` + +--- + +## 📈 Performance Tips + +### 1. Be Specific + +**Bad:** +```yaml +system: "Generate a good trading factor." +``` + +**Good:** +```yaml +system: | + Generate a EURUSD mean-reversion factor for the London session. + Target: 8-12% ARR, <15% max drawdown. + Use 5-minute lookback with RSI filter. +``` + +### 2. Include Domain Knowledge + +```yaml +system: | + EURUSD domain knowledge: + - London session (08:00-16:00 UTC): highest volume + - Spread cost: 1.5 bps + - Mean-reverting on <1h windows + - Trending on >4h windows +``` + +### 3. Specify Output Format + +```yaml +system: | + Your response must be in JSON format: + { + "hypothesis": "...", + "reason": "...", + "target_session": "london/ny/asian/all", + "expected_arr_range": "8-12%" + } +``` + +### 4. Provide Examples + +```yaml +user: | + Example of a good factor: + + Name: Momentum_8Bar_London + Logic: Long if 8-bar return > 0 and is_london=True + Filter: ADX > 1.2 (trending regime) + Expected ARR: 9.5% + + Now generate a NEW factor with different logic. +``` + +--- + +## 🎯 Next Steps + +1. **Review standard prompts:** `cat prompts/standard_prompts.yaml` +2. **Create your improved version:** `mkdir -p prompts/local` +3. **Test:** `python rdagent/components/loader.py` +4. **Run trading:** `rdagent fin_quant` + +--- + +**Your improved prompts in `prompts/local/` are your competitive edge! 🚀** diff --git a/prompts/standard_prompts.yaml b/prompts/standard_prompts.yaml new file mode 100644 index 00000000..e0eccb28 --- /dev/null +++ b/prompts/standard_prompts.yaml @@ -0,0 +1,160 @@ +# Predix Prompts - Standard Version +# +# These are the default prompts for EUR/USD quantitative trading. +# Store your improved prompts in prompts/local/ (not committed to Git). +# +# Usage: +# from rdagent.components.loader import load_prompt +# prompt = load_prompt("factor_discovery") # Loads from prompts/local/ if exists, else prompts/ + +# ============================================================ +# Factor Discovery Prompts +# ============================================================ + +factor_discovery: + system: |- + You are an expert quantitative researcher specialized in FX (foreign exchange) trading, + specifically EURUSD intraday strategies on 1-minute bars. + + EURUSD domain knowledge you must apply: + - London session (08:00-16:00 UTC): highest volume, trending behavior + - NY session (13:00-21:00 UTC): second volume peak + - Asian session (00:00-08:00 UTC): lower volume, mean-reverting + - London/NY overlap (13:00-16:00 UTC): strongest directional moves + - Spread cost: ~1.5 bps per trade — factors must overcome this + - EURUSD is mean-reverting on short windows (<1h), trending on longer (>4h) + + Your hypothesis must: + 1. Specify which session(s) the factor targets + 2. Include spread filter (expected return > 0.0003) + 3. Name the market regime (trending/mean-reverting) + 4. Be testable with available data (OHLCV, returns, technical indicators) + + Please ensure your response is in JSON format: + { + "hypothesis": "Clear factor hypothesis", + "reason": "Detailed explanation", + "target_session": "london/ny/asian/all", + "expected_arr_range": "e.g. 8-12%" + } + + user: |- + Previously tried factors and their results: + {{ factor_descriptions }} + + Additional context: + {{ report_content }} + + Generate a NEW factor hypothesis that is meaningfully different from what has been tried. + Target: beat current best ARR of 9.62%. + +# ============================================================ +# Factor Evolution Prompts +# ============================================================ + +factor_evolution: + system: |- + You are improving existing trading factors for EURUSD 1-minute data. + + Improvement strategies: + 1. Add session filters (is_london, is_ny) + 2. Add regime filters (ADX, volatility) + 3. Optimize lookback periods + 4. Combine with complementary factors + 5. Add risk management (stop-loss, take-profit) + + Your response must include: + - What to improve and why + - Expected performance gain + - Implementation approach + + JSON format: + { + "improvement": "Description of improvement", + "reason": "Why this will work better", + "expected_improvement": "e.g. +2% ARR, -5% drawdown" + } + + user: |- + Current factor: + {{ factor_code }} + + Performance metrics: + {{ factor_metrics }} + + Suggest specific improvements to beat current performance. + +# ============================================================ +# Model Coder Prompts +# ============================================================ + +model_coder: + system: |- + You are an expert ML engineer specialized in EURUSD trading models. + + Supported model types: + - TimeSeries: LSTM, GRU, TCN, Transformer, PatchTST + - Tabular: XGBoost, LightGBM, RandomForest + - Hybrid: CNN+LSTM, XGBoost+LSTM ensemble + + EURUSD-specific rules: + 1. Session filter: use is_london and is_ny columns + 2. Spread filter: only trade when abs(prediction) > 0.0003 + 3. ADX regime: if adx_proxy > 1.2 use trend model, else mean-reversion + 4. Weekend filter: close positions Friday 20:00 UTC + 5. Max frequency: target <15 trades per day + + Your code must: + - Be production-ready (error handling, logging) + - Include session/regime filters + - Account for spread costs + - Support both classification and regression targets + + user: |- + Factor descriptions: + {{ factor_descriptions }} + + Available features: + {{ feature_list }} + + Target: {{ target_variable }} + + Write complete, production-ready code for the model. + +# ============================================================ +# Trading Strategy Prompts +# ============================================================ + +trading_strategy: + system: |- + You are a portfolio manager designing trading strategies for EURUSD. + + Strategy components: + 1. Entry signals (from factors/models) + 2. Position sizing (volatility-adjusted) + 3. Risk management (stop-loss, take-profit, max drawdown) + 4. Session awareness (London/NY/Asian) + 5. Correlation management (if multiple factors) + + Your strategy must specify: + - Entry conditions (which signals, what thresholds) + - Exit conditions (time-based, signal-based, stop-loss) + - Position sizing (fixed, volatility-adjusted, Kelly) + - Risk limits (max position, max leverage, max drawdown) + + JSON format: + { + "entry_conditions": [...], + "exit_conditions": [...], + "position_sizing": "...", + "risk_limits": {...} + } + + user: |- + Available factors: + {{ factors }} + + Historical performance: + {{ historical_metrics }} + + Design a complete trading strategy that combines these factors optimally. diff --git a/rdagent/components/loader.py b/rdagent/components/loader.py new file mode 100644 index 00000000..a13c963a --- /dev/null +++ b/rdagent/components/loader.py @@ -0,0 +1,193 @@ +""" +Predix Prompt Loader + +Loads prompts from: +1. prompts/local/*.yaml (your improved prompts - not in Git) +2. prompts/standard_prompts.yaml (default prompts - in Git) + +Usage: + from rdagent.components.loader import load_prompt + + # Load factor discovery prompt + prompt = load_prompt("factor_discovery") + + # Load with custom local prompt + prompt = load_prompt("factor_discovery", local_only=True) +""" + +import os +import yaml +from pathlib import Path +from typing import Optional, Dict, Any + + +# Base paths +BASE_DIR = Path(__file__).parent.parent.parent # Predix/ +PROMPTS_DIR = BASE_DIR / "prompts" +LOCAL_PROMPTS_DIR = PROMPTS_DIR / "local" +STANDARD_PROMPTS_FILE = PROMPTS_DIR / "standard_prompts.yaml" + + +def get_local_prompt_path(name: str) -> Optional[Path]: + """Find local prompt file by name.""" + if not LOCAL_PROMPTS_DIR.exists(): + return None + + # Try different file extensions + for ext in ["yaml", "yml"]: + path = LOCAL_PROMPTS_DIR / f"{name}.{ext}" + if path.exists(): + return path + + # Try subdirectories + for subdir in LOCAL_PROMPTS_DIR.iterdir(): + if subdir.is_dir(): + for ext in ["yaml", "yml"]: + path = subdir / f"{name}.{ext}" + if path.exists(): + return path + + return None + + +def load_yaml_file(path: Path) -> Dict[str, Any]: + """Load YAML file.""" + with open(path, 'r', encoding='utf-8') as f: + return yaml.safe_load(f) + + +def load_prompt( + name: str, + section: Optional[str] = None, + local_only: bool = False, + fallback_to_standard: bool = True +) -> str: + """ + Load a prompt by name. + + Priority: + 1. prompts/local/{name}.yaml (if exists) + 2. prompts/standard_prompts.yaml (if fallback_to_standard=True) + + Args: + name: Prompt name (e.g., "factor_discovery") + section: Specific section in YAML (e.g., "system" or "user") + local_only: Only load from local/, raise error if not found + fallback_to_standard: If True, fall back to standard prompts + + Returns: + Prompt text + + Raises: + FileNotFoundError: If prompt not found + """ + # Try local prompts first + local_path = get_local_prompt_path(name) + + if local_path: + print(f"✓ Loading prompt '{name}' from local: {local_path}") + data = load_yaml_file(local_path) + + if section: + return data.get(section, "") + + # If data is dict with 'system' and 'user', return full dict + if isinstance(data, dict): + return data + return str(data) + + # Local not found + if local_only: + raise FileNotFoundError(f"Local prompt '{name}' not found in {LOCAL_PROMPTS_DIR}") + + # Try standard prompts + if not fallback_to_standard: + raise FileNotFoundError(f"Prompt '{name}' not found") + + if not STANDARD_PROMPTS_FILE.exists(): + raise FileNotFoundError(f"Standard prompts file not found: {STANDARD_PROMPTS_FILE}") + + print(f"✓ Loading prompt '{name}' from standard prompts") + data = load_yaml_file(STANDARD_PROMPTS_FILE) + + # Get section from standard prompts + if name in data: + prompt_data = data[name] + + if section and isinstance(prompt_data, dict): + return prompt_data.get(section, "") + + return prompt_data + + raise FileNotFoundError(f"Prompt '{name}' not found in standard prompts") + + +def load_all_prompts() -> Dict[str, Any]: + """Load all available prompts.""" + result = {} + + # Load standard prompts + if STANDARD_PROMPTS_FILE.exists(): + result["standard"] = load_yaml_file(STANDARD_PROMPTS_FILE) + + # Load local prompts + if LOCAL_PROMPTS_DIR.exists(): + result["local"] = {} + for path in LOCAL_PROMPTS_DIR.glob("*.yaml"): + result["local"][path.stem] = load_yaml_file(path) + + return result + + +def list_available_prompts() -> Dict[str, list]: + """List all available prompts.""" + result = {"standard": [], "local": []} + + # Standard prompts + if STANDARD_PROMPTS_FILE.exists(): + data = load_yaml_file(STANDARD_PROMPTS_FILE) + result["standard"] = list(data.keys()) + + # Local prompts + if LOCAL_PROMPTS_DIR.exists(): + result["local"] = [p.stem for p in LOCAL_PROMPTS_DIR.glob("*.yaml")] + + return result + + +# Convenience functions for specific prompts +def get_factor_discovery_prompt() -> Dict[str, str]: + """Get factor discovery prompt (system + user).""" + return load_prompt("factor_discovery") + + +def get_factor_evolution_prompt() -> Dict[str, str]: + """Get factor evolution prompt.""" + return load_prompt("factor_evolution") + + +def get_model_coder_prompt() -> Dict[str, str]: + """Get model coder prompt.""" + return load_prompt("model_coder") + + +def get_trading_strategy_prompt() -> Dict[str, str]: + """Get trading strategy prompt.""" + return load_prompt("trading_strategy") + + +# Test function +if __name__ == "__main__": + print("=== Available Prompts ===") + available = list_available_prompts() + print(f"Standard: {available['standard']}") + print(f"Local: {available['local']}") + + print("\n=== Testing Prompt Load ===") + try: + prompt = load_prompt("factor_discovery") + print(f"✓ Loaded factor_discovery prompt") + print(f" System: {len(prompt.get('system', ''))} chars") + print(f" User: {len(prompt.get('user', ''))} chars") + except FileNotFoundError as e: + print(f"✗ Error: {e}") diff --git a/web/index.html b/web/index.html index f531ac5f..9df102f4 100644 --- a/web/index.html +++ b/web/index.html @@ -5,11 +5,11 @@ - - - -