В предыдущей статье мы использовали LLM для анализа логов и поиска технических ошибок. Теперь применим LLM для более high-level задачи: анализа качества торговых решений.

Каждый профессиональный трейдер ведёт торговый журнал (trading journal): записывает каждую сделку, анализирует ошибки, отслеживает соблюдение риск-менеджмента. Для робота это можно автоматизировать полностью.


Проблема: знать цифры недостаточно

Типичный дневной отчёт (без LLM)

Daily Report - 2025-03-20
=========================

Trades: 15
Winners: 9 (60%)
Losers: 6 (40%)

Total PnL: +$234.50
Avg Win: +$42.30
Avg Loss: -$28.70
Largest Win: +$87.50
Largest Loss: -$65.20

Sharpe Ratio: 1.23
Max Drawdown: -$98.40 (occurred at 14:32)

Что мы знаем: цифры.

Что мы НЕ знаем:

  • Почему просадка произошла в 14:32?
  • Были ли нарушения риск-менеджмента?
  • Есть ли паттерн в убыточных сделках?
  • Что нужно изменить завтра?

Решение: LLM-анализ торгового дня

Архитектура

Trading Bot → Trade Log → LLM Analyzer → Daily Report
              (JSON/CSV)   (ChatGPT/Claude)  (Markdown + Actions)

Шаг 1: Сбор данных о сделках

# trading_journal.py
import json
from datetime import datetime
from dataclasses import dataclass, asdict

@dataclass
class Trade:
    """Single trade record"""
    id: str
    timestamp: datetime
    symbol: str
    side: str  # 'BUY' or 'SELL'
    entry_price: float
    exit_price: float
    size: float
    pnl: float
    pnl_pct: float
    duration_minutes: int

    # Risk management fields
    planned_stop_loss: float
    actual_stop_loss: float  # None if not hit
    planned_take_profit: float
    planned_risk_amount: float
    actual_risk_amount: float

    # Context
    entry_reason: str  # Why did we enter?
    exit_reason: str   # Why did we exit?
    market_condition: str  # 'trending_up', 'ranging', 'volatile', etc.

    # Metadata
    strategy_name: str
    was_manual_override: bool  # Did human intervene?

class TradingJournal:
    def __init__(self, filepath='trading_journal.json'):
        self.filepath = filepath
        self.trades = []

    def record_trade(self, trade: Trade):
        """Add trade to journal"""
        self.trades.append(trade)
        self._save()

    def _save(self):
        """Save to JSON"""
        with open(self.filepath, 'w') as f:
            json.dump([asdict(t) for t in self.trades], f, indent=2, default=str)

    def get_trades_for_date(self, date):
        """Get all trades for specific date"""
        return [t for t in self.trades if t.timestamp.date() == date]

    def get_daily_stats(self, date):
        """Calculate daily statistics"""
        trades = self.get_trades_for_date(date)

        if not trades:
            return None

        winners = [t for t in trades if t.pnl > 0]
        losers = [t for t in trades if t.pnl < 0]

        return {
            'date': date.isoformat(),
            'total_trades': len(trades),
            'winners': len(winners),
            'losers': len(losers),
            'win_rate': len(winners) / len(trades) if trades else 0,
            'total_pnl': sum(t.pnl for t in trades),
            'avg_win': sum(t.pnl for t in winners) / len(winners) if winners else 0,
            'avg_loss': sum(t.pnl for t in losers) / len(losers) if losers else 0,
            'largest_win': max((t.pnl for t in winners), default=0),
            'largest_loss': min((t.pnl for t in losers), default=0),
            'avg_duration': sum(t.duration_minutes for t in trades) / len(trades),
            'manual_overrides': sum(1 for t in trades if t.was_manual_override),
        }

# Usage in trading bot
journal = TradingJournal()

def on_position_closed(position):
    """Called when position is closed"""
    trade = Trade(
        id=position.order_id,
        timestamp=datetime.now(),
        symbol=position.symbol,
        side='LONG',  # or 'SHORT'
        entry_price=position.entry_price,
        exit_price=position.exit_price,
        size=position.size,
        pnl=position.calculate_pnl(),
        pnl_pct=position.calculate_pnl_pct(),
        duration_minutes=position.get_duration_minutes(),
        planned_stop_loss=position.stop_loss,
        actual_stop_loss=position.exit_price if position.exit_reason == 'STOP' else None,
        planned_take_profit=position.take_profit,
        planned_risk_amount=position.planned_risk,
        actual_risk_amount=abs(position.pnl) if position.pnl < 0 else 0,
        entry_reason=position.entry_signal,
        exit_reason=position.exit_reason,
        market_condition=position.market_regime,
        strategy_name=position.strategy.__class__.__name__,
        was_manual_override=position.manual_override
    )

    journal.record_trade(trade)

Шаг 2: Генерация ежедневного отчёта с LLM

# scripts/generate_daily_report.py
from openai import OpenAI
from datetime import date, datetime

client = OpenAI()
import json

def generate_daily_report_with_llm(journal, target_date):
    """Generate comprehensive daily report using LLM"""

    # Get trades and stats
    trades = journal.get_trades_for_date(target_date)
    stats = journal.get_daily_stats(target_date)

    if not trades:
        return "No trades today."

    # Format trades for LLM
    trades_text = "\n".join([
        f"""
Trade #{t.id}:
- Symbol: {t.symbol}
- Entry: ${t.entry_price:.2f} @ {t.timestamp.strftime('%H:%M:%S')}
- Exit: ${t.exit_price:.2f}
- PnL: ${t.pnl:+.2f} ({t.pnl_pct:+.2f}%)
- Duration: {t.duration_minutes} minutes
- Entry reason: {t.entry_reason}
- Exit reason: {t.exit_reason}
- Market condition: {t.market_condition}
- Planned stop-loss: ${t.planned_stop_loss:.2f}
- Actual stop: ${t.actual_stop_loss:.2f if t.actual_stop_loss else 'N/A (TP or manual)'}
- Planned risk: ${t.planned_risk_amount:.2f}
- Actual risk: ${t.actual_risk_amount:.2f}
- Manual override: {t.was_manual_override}
        """
        for t in trades
    ])

    prompt = f"""
You are an expert trading coach and risk management analyst.

Analyze this trader's performance for {target_date.strftime('%B %d, %Y')}:

STATISTICS:
- Total trades: {stats['total_trades']}
- Win rate: {stats['win_rate']*100:.1f}%
- Total PnL: ${stats['total_pnl']:+.2f}
- Average win: ${stats['avg_win']:+.2f}
- Average loss: ${stats['avg_loss']:+.2f}
- Largest win: ${stats['largest_win']:+.2f}
- Largest loss: ${stats['largest_loss']:+.2f}
- Average trade duration: {stats['avg_duration']:.0f} minutes
- Manual overrides: {stats['manual_overrides']}

DETAILED TRADES:
{trades_text}

Provide comprehensive analysis with these sections:

1. **Executive Summary** (2-3 sentences: overall performance)

2. **Risk Management Review**
   - Were stop-losses respected?
   - Any position sizing violations?
   - Risk-reward ratios analysis
   - Flag ANY deviation from plan

3. **Pattern Analysis**
   - Common factors in winning trades
   - Common factors in losing trades
   - Time-of-day patterns
   - Symbol-specific patterns

4. **Behavioral Analysis**
   - Any emotional trading? (breaking rules, revenge trading)
   - Manual overrides: were they justified?
   - Discipline score (1-10)

5. **What Went Well** (specific examples)

6. **What Went Wrong** (specific examples with trade IDs)

7. **Action Items for Tomorrow** (concrete, actionable improvements)

8. **Grade** (A+ to F with justification)

Be brutally honest. Focus on rule violations and emotional mistakes.
Use specific trade IDs and timestamps in your analysis.
"""

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "You are a professional trading coach."},
            {"role": "user", "content": prompt}
        ],
        temperature=0.4
    )

    return response.choices[0].message.content

# Usage
journal = TradingJournal()
report = generate_daily_report_with_llm(journal, date.today())

# Save report
with open(f'reports/daily_{date.today().isoformat()}.md', 'w') as f:
    f.write(report)

print(report)

Пример сгенерированного отчёта

# Trading Performance Review - March 20, 2025

## Executive Summary

**Overall: GOOD but with concerning risk violations**

You had a profitable day (+$234.50, 60% win rate) with solid execution on most trades. However, **3 trades violated stop-loss discipline**, and there were 2 questionable manual overrides that need review. The afternoon session (14:00-17:00) showed significantly worse performance than morning, suggesting fatigue or changing market conditions.

**Grade: B-** (would be A- without the risk violations)

---

## 🛡️ Risk Management Review

### ✅ Respected Stop-Losses (12/15 trades)

**Good examples:**
- Trade #12347 (ETH/USDT): Stopped out exactly at planned -3.0% ($-28.50)
- Trade #12351 (BTC/USDT): Stopped at -2.9% (within acceptable slippage)

### ❌ Stop-Loss Violations (3/15 trades) 🚨

**Trade #12349 - SOL/USDT (14:23)**
- **Planned stop:** -3.0% ($-45.00)
- **Actual loss:** -4.7% ($-70.50)
- **Violation:** 57% worse than planned!
- **Reason:** "Manual override" logged
- **Analysis:** You moved the stop-loss from $148.50 to $145.00 AFTER price was approaching original stop. This is **classic mistake #1**: moving stops to avoid loss.
- **Impact:** Lost extra $25.50 that should have been saved
- **CRITICAL:** This behavior must stop immediately.

**Trade #12353 - AVAX/USDT (15:45)**
- **Planned stop:** -3.0% ($-30.00)
- **Actual loss:** -3.8% ($-38.00)
- **Violation:** 27% worse than planned
- **Reason:** High volatility caused slippage
- **Analysis:** Stop-loss was market order during volatile period. Consider using stop-limit orders OR widen planned stop to -2.7% to achieve actual -3.0% with slippage.

**Trade #12355 - BTC/USDT (16:58)**
- **Planned stop:** -3.0% ($-90.00)
- **Actual loss:** -3.4% ($-102.00)
- **Violation:** 13% worse
- **Analysis:** Similar to #12353 - slippage issue

**Total extra loss from violations:** $37.50 (16% of gross profit eroded by poor execution)

---

### Position Sizing Analysis

**ALL CORRECT** ✅

Every trade risked exactly 1.0% of capital as planned:
- Average planned risk: $30.00 (1.0% of $3,000 capital)
- Average actual risk on losers: $31.50 (within tolerance)

Good discipline here!

---

### Risk-Reward Ratios

**Winners:**
- Average R:R: 1:1.8 (target was 1:2, close enough)
- Best: Trade #12346 (3.2:1) - let winner run, excellent!

**Losers:**
- Average R:R: N/A (stopped out correctly)

**Issue:** 3 trades exited at only 1:1.2 reward (vs planned 1:2)
- Trades #12348, #12350, #12354
- **Pattern:** All exited with "Manual override - took profit early"
- **Why?** Fear of giving back profits?
- **Impact:** Left $45 on table (trades continued +15% more after you exited)

**Recommendation:** Set take-profit orders automatically, don't watch trades tick-by-tick.

---

## 📊 Pattern Analysis

### Common Factors in Winning Trades (9 trades)

**Time of day:**
- 7 of 9 winners occurred 09:00-12:00
- Only 2 winners after 14:00

**Entry reason:**
- "RSI oversold + price at lower Bollinger Band": 6/9 (67%)
- "Breakout with volume": 3/9 (33%)

**Market condition:**
- "Ranging": 8/9 (89%) ← Your strategy LOVES range-bound markets
- "Trending": 1/9 (11%)

**Duration:**
- Average: 32 minutes
- Sweet spot: 25-40 minutes

**Symbol:**
- BTC/USDT: 4 winners
- ETH/USDT: 3 winners
- SOL/USDT: 1 winner
- AVAX/USDT: 1 winner

---

### Common Factors in Losing Trades (6 trades)

**Time of day:**
- 5 of 6 losers occurred 14:00-17:00 🚨
- **This is a HUGE red flag!**

**Entry reason:**
- "RSI oversold": 5/6 (but market kept dropping)
- "Breakout false signal": 1/6

**Market condition:**
- "Trending down": 4/6 (67%)
- "High volatility": 2/6 (33%)

**Pattern identified:** Your mean-reversion strategy fails in trending markets!

**Specific example:**
Between 14:00-17:00, BTC dropped from $51,200 to $49,800 (-2.7%). Your strategy kept trying to "catch the falling knife" with RSI oversold signals. All 4 entries got stopped out as trend continued.

**Critical insight:** Need market regime filter! Don't take mean-reversion trades during strong trends.

---

### Time-of-Day Pattern (CRITICAL)

| Time Block | Trades | Winners | PnL |
|------------|--------|---------|-----|
| 09:00-12:00 | 6 | 5 (83%) | +$187 |
| 12:00-14:00 | 3 | 2 (67%) | +$42 |
| 14:00-17:00 | 5 | 1 (20%) | -$95 |
| 17:00-20:00 | 1 | 1 (100%) | +$101 |

**Analysis:**
Morning session: Excellent (83% win rate, $187 profit)
Afternoon session: TERRIBLE (20% win rate, -$95 loss)

**Why?**
- Morning: Crypto markets ranging after Asian session
- Afternoon: US markets open → increased volatility → trending moves → your strategy fails

**Recommendation:** Consider pausing strategy 14:00-17:00 OR switch to trend-following during this period.

---

## 🧠 Behavioral Analysis

### Emotional Trading Indicators

**Manual Override Trades: 2** (Trade #12349, #12354)

**Trade #12349 Analysis:**
You manually moved stop-loss as price approached it. Classic fear response: "I don't want to take this loss, let me give it more room."

**Result:** Lost MORE money (-$70.50 instead of -$45.00)

**This is textbook emotional trading.** Stop-loss exists for a reason. Moving it = breaking your own rules.

---

**Trade #12354 Analysis:**
Closed position at +1.8% profit (planned target was +3.0%) with manual override.

**Log note:** "Taking profit before reversal"

**Actual outcome:** Price continued to +4.2% before reversing.

**Left on table:** $36.00

**Analysis:** Fear of giving back profits. You didn't trust your system. Price was clearly trending up (higher highs/lows), no reversal signal present.

---

### Discipline Score: 6/10

**Positives (+):**
- Position sizing perfect (all 1% risk)
- Most stop-losses respected (12/15)
- Good trade selection in morning

**Negatives (-):**
- Moved stop-loss on 1 trade (major violation)
- Early profit-taking on 2 trades (broke plan)
- Continued trading during afternoon when clearly not working
- Ignored regime change (kept mean-rev in trend)

**Overall:** You have a good system but **emotional interference** is costing you money.

---

## ✅ What Went Well

### 1. Trade #12346 - BTC/USDT (09:15) ⭐ PERFECT EXECUTION

**Entry:** RSI 28.4 (oversold), price at lower BB, ranging market
**Stop:** -3.0% at $48,621
**Target:** +6.0% at $51,729

**Outcome:** Closed at +5.8% ($+87.50) after 45 minutes

**Why perfect:**
- Clear signal (all criteria met)
- No manual interference
- Let winner run close to target
- Respected time-based exit (45 min = your average)

**Lesson:** When you follow the system, it works!

---

### 2. Morning Session (09:00-12:00) - 83% Win Rate

You recognized ranging market conditions and executed strategy flawlessly. 5 out of 6 winners.

**What you did right:**
- Waited for clear RSI + BB alignment
- Didn't overtrade (6 trades in 3 hours = selective)
- Took profits at targets
- Let #12346 run (biggest winner)

---

### 3. Position Sizing Discipline

Every single trade: exactly 1% risk. Not 0.8%, not 1.2%. Exactly 1.0%.

This level of discipline is rare and commendable. Keep it up!

---

## ❌ What Went Wrong

### 1. Trade #12349 - SOL/USDT (14:23) - DISASTER

**What happened:**
- Entered SOL long at $150.00 (RSI oversold)
- SOL continued dropping (downtrend, not ranging)
- Price approached your stop at $148.50
- **YOU MOVED THE STOP TO $145.00** 🚨
- Price continued to $145.00, stopped out
- Lost $70.50 instead of $45.00

**Why this is terrible:**
1. Moving stop = admitting you don't trust your risk management
2. If original stop was wrong, EXIT THE TRADE, don't move stop
3. You violated your #1 rule: never risk more than 1%

**Root cause:** Emotional attachment to being "right". You didn't want to admit the trade was wrong.

**Fix:** Set stop-losses on exchange (not in your head). Can't manually move them if they're automated.

---

### 2. Afternoon Trading (14:00-17:00) - Kept Fighting the Trend

You entered **5 mean-reversion trades** during a clear downtrend:
- 14:23 - SOL (lost)
- 14:45 - ETH (lost)
- 15:15 - BTC (lost)
- 15:45 - AVAX (lost)
- 16:30 - ETH (lost)

**All 5 had same pattern:**
- "RSI oversold, buy signal"
- Price kept dropping (trend)
- Stopped out

**What you should have done:**
After 2 consecutive losses with same pattern, STOP trading that setup!

**Alternative:**
- Recognize regime change (ranging → trending)
- Pause mean-reversion strategy
- Switch to trend-following OR stay flat

**Lost:** -$95 from fighting the trend

---

### 3. Early Profit-Taking (Trades #12348, #12350, #12354)

**Pattern:** All exited at ~60% of profit target due to "fear of reversal"

**Reality:** All 3 continued to full target (+3.0%) or beyond

**Money left on table:** ~$45

**Psychological issue:** You're watching the trades too closely. Every small pullback makes you nervous.

**Solution:**
- Set take-profit orders at target (automatic)
- Close the charts after entry
- Check only every 30 minutes

---

## 📋 Action Items for Tomorrow

### Priority 1: Fix Risk Management Violations 🚨

- [ ] **NEVER move stop-loss away from entry** (moving it closer to lock profit is OK)
- [ ] Place stop-loss orders on EXCHANGE immediately after entry (can't manually move)
- [ ] If you feel urge to move stop, close the position entirely instead
- [ ] Set take-profit orders automatically at target (don't manual)

---

### Priority 2: Add Market Regime Filter

- [ ] Before each trade, check: is market ranging or trending?
- [ ] Simple filter: if ADX > 25, skip mean-reversion setups
- [ ] Backtest this filter on today's trades:
  - Morning (ADX 18-22): 5/6 winners ✓
  - Afternoon (ADX 28-35): 1/5 winners ✗ (would have skipped 4 losers!)

---

### Priority 3: Time-Based Trading Rules

- [ ] Limit mean-reversion trades to 09:00-14:00 only
- [ ] Pause strategy 14:00-17:00 (US market volatility)
- [ ] If must trade afternoon, use different strategy (trend-following?)

---

### Priority 4: Behavioral Improvements

- [ ] After entry: close charts, set timer for 30 minutes
- [ ] Don't watch tick-by-tick price movement
- [ ] If feeling emotional (fear/greed), STOP trading for 1 hour
- [ ] Max 2 consecutive losses before mandatory break

---

## 📊 Grade: B-

**Breakdown:**
- Strategy execution (morning): A
- Risk management: C (violations hurt)
- Emotional discipline: D+ (moved stop, early exits)
- Adaptation: F (didn't stop when pattern failing)
- Position sizing: A+ (perfect)

**Overall:** Strong foundation, but emotional interference preventing A-level performance.

**Path to A:** Implement Priority 1 & 2 action items. If you had followed them today, PnL would have been +$312 instead of +$235 (+33% improvement).

---

**Remember:** The system works when you follow it. Your edge comes from discipline, not from "outsmarting" your own rules.

Good luck tomorrow! 📈

Оценка результата

LLM превосходно:

  • Выявил конкретные нарушения риск-менеджмента (Trade #12349)
  • Обнаружил паттерн времени дня (morning good, afternoon bad)
  • Идентифицировал эмоциональное trading (moving stop, early exits)
  • Дал actionable рекомендации (не общие, а конкретные)
  • Присвоил честную оценку (B-, не завышает)

Решение #2: Трекинг прогресса по неделям

Задача

Один день - это snapshot. Нужно видеть динамику улучшения/ухудшения.

Реализация

def generate_weekly_review(journal, week_start_date):
    """Generate weekly performance review"""

    # Get all days in week
    days = [week_start_date + timedelta(days=i) for i in range(7)]

    # Collect daily stats
    daily_stats = [journal.get_daily_stats(day) for day in days]
    daily_stats = [s for s in daily_stats if s]  # Remove days with no trades

    # Aggregate
    total_trades = sum(s['total_trades'] for s in daily_stats)
    total_pnl = sum(s['total_pnl'] for s in daily_stats)
    avg_win_rate = sum(s['win_rate'] for s in daily_stats) / len(daily_stats) if daily_stats else 0

    # Count violations
    all_trades = []
    for day in days:
        all_trades.extend(journal.get_trades_for_date(day))

    violations = {
        'moved_stops': 0,
        'oversized_positions': 0,
        'revenge_trades': 0,
        'ignored_signals': 0
    }

    for trade in all_trades:
        if trade.was_manual_override and "moved stop" in trade.exit_reason.lower():
            violations['moved_stops'] += 1

        actual_risk_pct = (trade.actual_risk_amount / 3000) * 100  # assume $3000 capital
        if actual_risk_pct > 1.2:  # >20% over planned 1%
            violations['oversized_positions'] += 1

    # Generate weekly report with LLM
    prompt = f"""
    Generate a WEEKLY REVIEW for week {week_start_date.isoformat()}

    WEEKLY STATISTICS:
    - Trading days: {len(daily_stats)}
    - Total trades: {total_trades}
    - Average win rate: {avg_win_rate*100:.1f}%
    - Total PnL: ${total_pnl:+.2f}
    - Best day: {max(daily_stats, key=lambda x: x['total_pnl'])['date']} (${max(daily_stats, key=lambda x: x['total_pnl'])['total_pnl']:+.2f})
    - Worst day: {min(daily_stats, key=lambda x: x['total_pnl'])['date']} (${min(daily_stats, key=lambda x: x['total_pnl'])['total_pnl']:+.2f})

    DISCIPLINE TRACKING:
    - Stop-loss moves: {violations['moved_stops']}
    - Oversized positions: {violations['oversized_positions']}

    DAILY BREAKDOWN:
    {chr(10).join([f"- {s['date']}: {s['total_trades']} trades, {s['win_rate']*100:.0f}% WR, ${s['total_pnl']:+.2f}" for s in daily_stats])}

    Provide:
    1. Week summary (how did we do overall?)
    2. Improvement vs last week (if available)
    3. Consistency analysis (are results stable or erratic?)
    4. Discipline grade (A-F based on violations)
    5. Focus areas for next week
    """

    # ... call LLM ...

Решение #3: Автоматический pre-trade checklist

Задача

Предотвратить ошибки до совершения сделки.

Реализация

class PreTradeChecklist:
    """Validate trade before execution"""

    def __init__(self, journal, llm_enabled=True):
        self.journal = journal
        self.llm_enabled = llm_enabled

    def validate_trade(self, planned_trade):
        """Check if trade passes all criteria"""

        issues = []

        # 1. Check recent performance in same symbol
        recent_trades = self._get_recent_trades_same_symbol(planned_trade.symbol, hours=24)

        if recent_trades:
            win_rate = sum(1 for t in recent_trades if t.pnl > 0) / len(recent_trades)
            if win_rate < 0.3 and len(recent_trades) >= 3:
                issues.append(f"⚠️  Recent performance on {planned_trade.symbol}: {win_rate*100:.0f}% win rate (last 24h). Consider skipping.")

        # 2. Check current drawdown
        today_pnl = sum(t.pnl for t in self.journal.get_trades_for_date(date.today()))
        if today_pnl < -100:
            issues.append(f"⚠️  Current daily drawdown: ${today_pnl:.2f}. Maybe stop trading for today?")

        # 3. Check consecutive losses
        recent_all = self._get_recent_trades(hours=4)
        if len(recent_all) >= 2:
            if all(t.pnl < 0 for t in recent_all[-2:]):
                issues.append(f"⚠️  2 consecutive losses. Take a break before next trade.")

        # 4. Check market regime
        if planned_trade.entry_reason == "RSI oversold" and planned_trade.market_condition == "trending_down":
            issues.append(f"🚨 Mean-reversion signal in downtrend! High probability of failure.")

        # 5. LLM validation
        if self.llm_enabled and issues:
            decision = self._ask_llm_should_trade(planned_trade, issues)
            return decision

        return {
            'approved': len(issues) == 0,
            'issues': issues,
            'recommendation': 'SKIP' if len(issues) >= 2 else 'PROCEED WITH CAUTION'
        }

    def _ask_llm_should_trade(self, planned_trade, issues):
        """Final validation with LLM"""

        prompt = f"""
        Trader wants to enter this trade:

        Symbol: {planned_trade.symbol}
        Entry: ${planned_trade.entry_price}
        Stop: ${planned_trade.stop_loss}
        Size: {planned_trade.size}
        Risk: ${planned_trade.risk_amount} ({planned_trade.risk_pct}% of capital)
        Reason: {planned_trade.entry_reason}
        Market: {planned_trade.market_condition}

        ISSUES DETECTED:
        {chr(10).join(f"- {issue}" for issue in issues)}

        Should we take this trade? Respond in format:

        DECISION: [TAKE / SKIP / REDUCE SIZE]
        REASON: [1-2 sentences why]
        """

        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.3,
            max_tokens=150
        )

        answer = response.choices[0].message.content

        return {
            'approved': 'TAKE' in answer,
            'issues': issues,
            'llm_decision': answer
        }

# Usage in trading bot
checklist = PreTradeChecklist(journal, llm_enabled=True)

def on_signal(signal):
    """Before entering trade"""
    planned_trade = create_planned_trade(signal)

    # Validate
    validation = checklist.validate_trade(planned_trade)

    if not validation['approved']:
        print(f"Trade REJECTED: {validation['llm_decision']}")
        log_rejected_trade(planned_trade, validation)
        return  # Skip trade

    # Proceed
    execute_trade(planned_trade)

Пример LLM ответа

DECISION: SKIP

REASON: You have 2 consecutive losses in last 4 hours AND trying mean-reversion in downtrend. This is exactly the pattern that cost you $95 yesterday afternoon. High probability of 3rd consecutive loss. Take a break, wait for market regime change.

Результат: LLM предотвращает эмоциональную сделку, которая скорее всего привела бы к убытку.


Решение #4: Генерация Trading Insights

Задача

Найти неочевидные паттерны, которые человек не заметит.

Реализация

def discover_insights_with_llm(journal, days=30):
    """Use LLM to discover non-obvious patterns"""

    # Get all trades for last N days
    all_trades = []
    for i in range(days):
        day = date.today() - timedelta(days=i)
        all_trades.extend(journal.get_trades_for_date(day))

    # Create comprehensive dataset
    dataset_summary = f"""
    Dataset: {len(all_trades)} trades over {days} days

    Symbols: {', '.join(set(t.symbol for t in all_trades))}

    By day of week:
    {get_stats_by_day_of_week(all_trades)}

    By hour:
    {get_stats_by_hour(all_trades)}

    By entry reason:
    {get_stats_by_entry_reason(all_trades)}

    By exit reason:
    {get_stats_by_exit_reason(all_trades)}

    By market condition:
    {get_stats_by_market_condition(all_trades)}

    By duration:
    {get_stats_by_duration(all_trades)}
    """

    prompt = f"""
    You are a quantitative trading analyst.

    Analyze this trading dataset and discover NON-OBVIOUS INSIGHTS:

    {dataset_summary}

    Look for:
    1. Hidden patterns (correlations not immediately obvious)
    2. Optimal conditions (when does strategy work best?)
    3. Red flags (when to avoid trading?)
    4. Actionable improvements

    Examples of insights:
    - "Trades opened on Mondays have 20% lower win rate"
    - "Exits due to 'manual override' are 50% more likely to be early (left profit on table)"
    - "ETH trades held >45 minutes have negative expected value"

    Provide 5-7 specific, data-backed insights.
    """

    # ... call LLM ...

Пример результата

# Trading Insights - Last 30 Days

## Insight #1: Friday Afternoon Curse 📉
**Finding:** Trades opened on Fridays after 14:00 have **18% win rate** vs 62% average

**Data:**
- Friday 14:00+ trades: 11 total, 2 winners (18%)
- Other times: 234 trades, 145 winners (62%)

**Hypothesis:** Weekend uncertainty → lower conviction → poorer execution

**Recommendation:** Avoid opening new positions on Friday afternoons. Close existing positions before weekend if in profit.

**Estimated impact:** +$120/month by skipping Friday afternoon trades

---

## Insight #2: The 45-Minute Rule ⏰
**Finding:** Trades held >45 minutes have **negative** expected value for ETH/USDT

**Data:**
- ETH trades <45 min: 28 trades, 18 winners (64%), avg PnL +$12
- ETH trades >45 min: 15 trades, 5 winners (33%), avg PnL -$8

**Why:** ETH mean-reverts quickly. After 45 minutes, if target not hit, market regime likely changed.

**Recommendation:** Add time-based exit for ETH: if not at target after 45 minutes, close position.

---

## Insight #3: Manual Override Paradox 🤔
**Finding:** Manual overrides have **opposite** effect than intended

**Data:**
- Overrides to "protect profit" (early exit): 12 trades, left avg $23 on table
- Overrides to "give more room" (move stop): 5 trades, lost avg $18 extra

**Impact:** Manual overrides cost you $391 over 30 days!

**Recommendation:** Disable manual trading. Automate everything.

---

## Insight #4: BTC/USDT Sweet Spot 🎯
**Finding:** BTC trades work best in specific volatility range

**Data:**
- Low volatility (ATR <$500): 58% win rate
- Medium volatility (ATR $500-$1000): **72% win rate**- High volatility (ATR >$1000): 41% win rate

**Recommendation:** Add volatility filter:
```python
if 500 < atr < 1000:
    # Good conditions for BTC mean-reversion
    enter_trade()

Estimated impact: +15% improvement in BTC win rate


Insight #5: Correlation Between Entry Reason and Duration ⏱️

Finding: “Breakout” entries need more time than “RSI oversold”

Data:

  • RSI oversold entries: avg duration 28 min, 65% win rate
  • Breakout entries: avg duration 52 min, 59% win rate

Analysis: You’re exiting breakout trades too early (using same 30-min target for both)

Recommendation: Separate targets:

  • RSI oversold: 30-min or +2% target
  • Breakout: 60-min or +4% target

Insight #6: The Lunch Dip 🍔

Finding: 12:00-13:00 entries underperform, but 13:00-14:00 entries excel

Data:

  • 12:00-13:00: 15 trades, 47% win rate
  • 13:00-14:00: 18 trades, 72% win rate

Hypothesis: Lunch hour = low liquidity → chop. Post-lunch = directional moves resume.

Recommendation: Skip 12:00-13:00, resume at 13:00.


Insight #7: Symbol Rotation Pattern 🔄

Finding: After 2 consecutive losses on one symbol, next trade on DIFFERENT symbol has 78% win rate

Data:

  • Same symbol after 2 losses: 8 trades, 25% win rate (revenge trading?)
  • Different symbol after 2 losses: 9 trades, 78% win rate

Psychology: Switching symbols = emotional reset, better decision-making

Recommendation: After 2 losses on BTC, trade ETH next (and vice versa) ```

Оценка

LLM нашёл паттерны, которые человек пропустил бы:

  • Friday afternoon (специфичный день недели + время)
  • 45-minute rule для ETH (symbol-specific timing)
  • Manual override paradox (behavioral pattern)
  • Symbol rotation (psychological insight)

Заключение

Автоматический разбор торговых дней с LLM даёт: ✅ Честный ежедневный feedback (без самообмана) ✅ Выявление нарушений риск-менеджмента ✅ Обнаружение эмоциональных ошибок ✅ Actionable рекомендации (конкретные, не общие) ✅ Предотвращение ошибок через pre-trade checklist ✅ Открытие неочевидных паттернов через insights

Экономия времени: 30-60 минут ежедневного анализа журнала → 2 минуты автоматически

Улучшение производительности: По данным пользователей, внедрение автоматического разбора дней улучшает дисциплину на 30-40%, что напрямую влияет на P&L.

В следующей статье: ИИ как помощник по данным: формирование фичей для ML-стратегии на естественном языке.