# analyze_optimization.py # 24.69% 수익률 개선을 위한 심층 분석 import re from typing import Dict, List, Tuple from collections import defaultdict def parse_all_trades(log_path: str) -> Tuple[List[Dict], List[Dict]]: """BUY와 SELL 거래 모두 파싱""" buys = [] sells = [] with open(log_path, 'r', encoding='utf-16', errors='ignore') as f: for line in f: # BUY 패턴 buy_match = re.search( r'\[(\d{4}-\d{2}-\d{2})\]\s+BUY:\s+(.+?)\s+@\s+([\d,]+)\s+/\s+([\d,]+)주\s+\(SL:\s+([\d,]+)\)', line ) if buy_match: date, ticker, price, shares, sl = buy_match.groups() buys.append({ 'date': date, 'ticker': ticker.strip(), 'price': int(price.replace(',', '')), 'shares': int(shares.replace(',', '')), 'stop_loss': int(sl.replace(',', '')) }) # SELL 패턴 sell_match = re.search( r'\[(\d{4}-\d{2}-\d{2})\]\s+SELL\s+\(([^)]+)\):\s+(.+?)\s+@\s+[\d,]+\s+/\s+[\d,]+주\s+\(([+-]?\d+\.\d+)%\)', line ) if sell_match: date, exit_reason, ticker, return_pct = sell_match.groups() sells.append({ 'date': date, 'exit_reason': exit_reason, 'ticker': ticker.strip(), 'return_pct': float(return_pct) }) return buys, sells def analyze_trailing_stop_lt10pct(sells: List[Dict]) -> None: """TRAILING_STOP_LT10PCT 상세 분석""" ts_lt10 = [s for s in sells if s['exit_reason'] == 'TRAILING_STOP_LT10PCT'] print("\n" + "="*80) print("📉 TRAILING_STOP_LT10PCT 상세 분석 (104회, 평균 -1.53%)") print("="*80) # 손익 분포 profits = [s['return_pct'] for s in ts_lt10] wins = [p for p in profits if p > 0] losses = [p for p in profits if p < 0] print(f"\n1️⃣ 손익 분포:") print(f" - 수익 거래: {len(wins)}회 (승률 {len(wins)/len(ts_lt10)*100:.1f}%)") print(f" - 손실 거래: {len(losses)}회 (패율 {len(losses)/len(ts_lt10)*100:.1f}%)") print(f" - 평균 수익: {sum(wins)/len(wins) if wins else 0:.2f}%") print(f" - 평균 손실: {sum(losses)/len(losses) if losses else 0:.2f}%") # 손실 구간 분포 loss_ranges = { '0~-3%': [p for p in losses if -3 <= p < 0], '-3~-5%': [p for p in losses if -5 <= p < -3], '-5~-7%': [p for p in losses if -7 <= p < -5], '-7% 이하': [p for p in losses if p < -7] } print(f"\n2️⃣ 손실 구간 분포:") for range_name, range_data in loss_ranges.items(): if range_data: print(f" - {range_name}: {len(range_data)}회 ({len(range_data)/len(losses)*100:.1f}%)") # 수익 구간 분포 profit_ranges = { '0~3%': [p for p in wins if 0 < p <= 3], '3~5%': [p for p in wins if 3 < p <= 5], '5~7%': [p for p in wins if 5 < p <= 7], '7% 이상': [p for p in wins if p > 7] } print(f"\n3️⃣ 수익 구간 분포:") for range_name, range_data in profit_ranges.items(): if range_data: print(f" - {range_name}: {len(range_data)}회 ({len(range_data)/len(wins)*100 if wins else 0:.1f}%)") def analyze_profit_flow(sells: List[Dict]) -> None: """익절 후 추가 수익 흐름 분석""" print("\n" + "="*80) print("💰 익절 전략 효율성 분석") print("="*80) profit_takes = [s for s in sells if 'PROFIT_TAKE' in s['exit_reason']] trailing_stops = [s for s in sells if 'TRAILING_STOP' in s['exit_reason']] print(f"\n1️⃣ 익절(PROFIT_TAKE) 현황:") print(f" - 거래 횟수: {len(profit_takes)}회") print(f" - 평균 수익: {sum(s['return_pct'] for s in profit_takes)/len(profit_takes):.2f}%") print(f"\n2️⃣ 트레일링 스탑 현황:") print(f" - LT10PCT: {len([s for s in sells if s['exit_reason'] == 'TRAILING_STOP_LT10PCT'])}회 (평균 -1.53%)") print(f" - 10-30PCT: {len([s for s in sells if s['exit_reason'] == 'TRAILING_STOP_10_30PCT'])}회 (평균 9.49%)") print(f" - GT30PCT: {len([s for s in sells if s['exit_reason'] == 'TRAILING_STOP_GT30PCT'])}회 (평균 9.12%)") print(f"\n3️⃣ 문제점:") print(f" - PROFIT_TAKE 이후 남은 절반이 TRAILING_STOP_LT10PCT로 손실 청산") print(f" - 104회 × -1.53% = 약 -159% 누적 손실") print(f" - 이 손실만 0%로 만들어도 총 수익률 +6~8% 증가 가능") def suggest_improvements() -> None: """개선 방안 제시""" print("\n" + "="*80) print("🎯 총 수익률 개선 방안 (24.69% → 30~35% 목표)") print("="*80) print("\n" + "="*70) print("방안 1: TRAILING_STOP_LT10PCT 비율 완화 (즉시 적용 가능)") print("="*70) print(""" 현재: SELL_TRAILING_STOP_LOW_PCT = 0.07 (7% 하락) 문제: 104회 거래 중 대부분이 이 설정으로 -1.53% 손실 개선안: SELL_TRAILING_STOP_LOW_PCT = 0.10 # 7% → 10% 완화 예상 효과: - 104회 중 40~50%가 손실 → 소폭 수익으로 전환 - 평균 -1.53% → +0.5~1.0%로 개선 - 총 수익률 +5~7% 증가 (24.69% → 30~31%) """) print("\n" + "="*70) print("방안 2: 익절 비율 축소 (더 많이 남겨서 큰 수익 노리기)") print("="*70) print(""" 현재: SELL_PROFIT_TAKE_RATIO = 0.5 (50% 매도) 문제: 절반 매도 후 남은 절반이 손실로 청산되면 전체 수익 감소 개선안 A (공격적): SELL_PROFIT_TAKE_RATIO = 0.33 # 1/3만 매도 개선안 B (중도): SELL_PROFIT_TAKE_RATIO = 0.4 # 40% 매도 예상 효과: - 큰 수익(20~30%) 구간 진입 빈도 증가 - TRAILING_STOP_10_30PCT/GT30PCT 비중 증가 - 총 수익률 +3~5% 증가 (24.69% → 28~30%) 리스크: - 하락 시 손실폭 증가 가능 (단, MDD 모니터링 필요) """) print("\n" + "="*70) print("방안 3: 2단계 익절 전략 (안정성 + 수익성)") print("="*70) print(""" 현재: 15% 수익 시 50% 매도 → 나머지는 트레일링 문제: 단일 익절 후 바로 트레일링으로 넘어가 손실 가능성 개선안: 1차 익절: 12% 도달 시 30% 매도 2차 익절: 20% 도달 시 추가 30% 매도 3차: 나머지 40%는 트레일링 (10~15% 여유) 구현: SELL_PROFIT_TAKE_FIRST_PCT = 0.12 SELL_PROFIT_TAKE_FIRST_RATIO = 0.3 SELL_PROFIT_TAKE_SECOND_PCT = 0.20 SELL_PROFIT_TAKE_SECOND_RATIO = 0.3 # 나머지 40%는 트레일링 예상 효과: - 익절 구간 분산으로 리스크 감소 - TRAILING_STOP_LT10PCT 비중 감소 - 총 수익률 +4~6% 증가 (24.69% → 29~31%) """) print("\n" + "="*70) print("방안 4: 조건부 트레일링 (수익률별 차등 적용)") print("="*70) print(""" 현재: 모든 거래에 동일한 트레일링 적용 문제: 소폭 수익(5~10%) 구간에서 7% 하락은 너무 타이트 개선안: # 수익률 10% 미만: 트레일링 비활성화 (HOLD or 고정 익절) # 수익률 10~20%: 10% 트레일링 # 수익률 20% 이상: 7% 트레일링 (현재 유지) 의사코드: if profit_pct < 0.10: # 트레일링 없음, 손절선(-7%)만 적용 pass elif profit_pct < 0.20: trailing_pct = 0.10 else: trailing_pct = 0.07 예상 효과: - TRAILING_STOP_LT10PCT 거래 104회 중 60~70% 감소 - 평균 손실 -1.53% → 제거 - 총 수익률 +6~8% 증가 (24.69% → 31~33%) """) print("\n" + "="*70) print("방안 5: STOP_LOSS 추가 완화 (손실 -8.46% 개선)") print("="*70) print(""" 현재: SELL_STOP_LOSS_PCT = 0.07 (7% 손절) 문제: 22회 거래에서 평균 -8.46% 손실 (총 -186% 손실) 개선안: SELL_STOP_LOSS_PCT = 0.10 # 7% → 10% 완화 예상 효과: - 22회 중 30~40%가 손절 회피 - 평균 -8.46% → -6~7%로 개선 - 총 수익률 +2~3% 증가 (24.69% → 27%) 리스크: - 급락 종목 손실폭 증가 가능 - MDD 5~7% 증가 가능 (허용 범위 확인 필요) """) print("\n" + "="*70) print("🏆 종합 추천: 복합 전략 (방안 1+2+4)") print("="*70) print(""" 1단계 (즉시 적용): SELL_TRAILING_STOP_LOW_PCT = 0.10 # 7% → 10% SELL_PROFIT_TAKE_RATIO = 0.4 # 50% → 40% 2단계 (strategy.py 수정 필요): 수익률 10% 미만: 트레일링 비활성화 수익률 10~20%: 10% 트레일링 수익률 20% 이상: 7% 트레일링 예상 최종 성과: 현재: 24.69% 개선 후: 32~37% (+30~50% 증가) 승률: 현재 대비 +5~8% MDD: 현재 대비 +2~3% (허용 범위) """) print("\n" + "="*70) print("⚡ 우선순위:") print("="*70) print(""" Priority 1: SELL_TRAILING_STOP_LOW_PCT = 0.10 (즉시 적용) → 예상 효과: +5~7% 수익률 증가 Priority 2: SELL_PROFIT_TAKE_RATIO = 0.4 (즉시 적용) → 예상 효과: +3~5% 수익률 증가 Priority 3: 조건부 트레일링 (strategy.py 수정) → 예상 효과: +6~8% 수익률 증가 총 예상 개선: +14~20% → 최종 38~45% 목표 (매우 공격적) 현실적 목표: +10~15% → 최종 35~40% """) def main() -> None: log_path = 'clean_backtest.log' print("="*80) print("📊 24.69% 수익률 개선을 위한 심층 분석") print("="*80) buys, sells = parse_all_trades(log_path) print(f"\n총 {len(buys)}회 매수, {len(sells)}회 매도 분석") analyze_trailing_stop_lt10pct(sells) analyze_profit_flow(sells) suggest_improvements() if __name__ == '__main__': main()