[2026-05-18] 슬래시 커맨드 프로젝트로 이동 (git 관리)

This commit is contained in:
2026-05-18 12:57:46 +09:00
parent d7190cb1be
commit 4697286c8e
4 changed files with 299 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
# claude_evening — 장 후 분석 및 피드백
오늘 매매 결과를 분석하고 `reports/daily/날짜.md`를 생성한다.
## 실행 순서
### 1. 데이터 수집
```bash
python app/ai/evening.py --print
```
### 2. 분석 항목
수집된 데이터를 바탕으로 다음을 판단한다:
**오늘 매매 평가**
- 승률·손익 수준이 적절했는가
- 손절이 제대로 작동했는가
- AI 부스트 종목 성과 vs 일반 종목 비교
- 이상 패턴 (연속 손절, 특정 시간대 집중 손실 등)
**파라미터 조정** (문제가 명확할 때만)
- 연속 손절 3회 이상 → `SL_PCT` 축소 검토
- 목표가 도달 후 즉시 반락 패턴 → `TP1_PCT` 상향 검토
- 승률 < 40% 지속 → `STRATEGY_K` 조정 검토
- 조정이 필요하면 `app/config.py`를 직접 수정
### 3. 실전 전환 조건 체크
`live_ready` 섹션의 5가지 조건을 확인한다:
- 누적 운영 30거래일 이상
- 최근 30일 승률 > 48%
- 최근 30일 MDD < -10%
- 최근 30일 샤프지수 > 1.0
- 이번 달 L3 발동 2회 이하
**5가지 모두 충족 시:**
```bash
mkdir -p reports/live_ready
```
`reports/live_ready/날짜_READY.md`를 생성하고 Discord에 🚀 알림을 보낸다.
### 4. 일일 리포트 저장
`reports/daily/날짜.md` 형식으로 저장한다:
```markdown
# [날짜] 일일 리포트
## 매매 결과
- 총 매매: N회 / 승 N 패 N (승률 N%)
- 순손익: +N원
## 매매 상세
| 종목 | 진입 | 청산 | 사유 | 손익 |
|------|------|------|------|------|
## 분석 및 피드백
(Claude 분석 내용)
## 파라미터 변경
(변경했으면 내용, 없으면 "없음")
## 실전 전환 조건
| 조건 | 기준 | 현재 | 통과 |
|------|------|------|------|
```
### 5. Discord 알림 전송
```bash
python -c "
import asyncio, json, sys
sys.path.insert(0, '.')
from app.main import load_env; load_env()
from app.monitor.notifier import send
# 분석 결과 요약을 msg에 담아 전송
asyncio.run(send(msg))
"
```
### 6. 완료
리포트 경로와 한 줄 요약을 출력하고 종료한다.
+64
View File
@@ -0,0 +1,64 @@
# claude_morning — 장 전 분석
오늘 날짜 기준으로 장 전 분석을 수행하고 `data/daily_context.json`을 생성한다.
## 실행 순서
### 1. 데이터 수집
```bash
python app/ai/morning.py --print
```
위 명령을 실행해 뉴스 헤드라인과 KIS 시장 데이터를 수집한다.
### 2. 분석
수집된 데이터를 바탕으로 다음 항목을 판단한다:
- **시장 분위기**: 강세 / 중립 / 약세
- **감성 점수**: 0~100 (50=중립, 70이상=강세, 30이하=약세)
- **리스크 레벨**: 낮음 / 보통 / 높음
- **주목 섹터**: 수급·뉴스 모두 긍정적인 섹터
- **회피 섹터**: 악재·수급 부진 섹터
- **boosted_tickers**: 거래량 상위 + 외국인 순매수 겹치는 종목코드
- **blacklist_tickers**: 악재(횡령·소송·거래정지 등) 종목코드
- **position_size_multiplier**: 0.5(약세) ~ 1.0(중립) ~ 1.5(강세)
- **trade_allowed**: sentiment_score < 40이면 false
### 3. daily_context.json 저장
분석 결과를 `data/daily_context.json`에 저장한다. 형식:
```json
{
"date": "YYYY-MM-DD",
"generated_at": "HH:MM:SS",
"trade_allowed": true,
"market_sentiment": "중립",
"sentiment_score": 62,
"risk_level": "보통",
"hot_sectors": ["반도체", "2차전지"],
"avoid_sectors": ["금융", "건설"],
"boosted_tickers": ["005930", "000660"],
"blacklist_tickers": [],
"position_size_multiplier": 1.0,
"reason": "50자 이내 시장 요약"
}
```
### 4. Discord 알림 전송
아래 Python 코드를 실행해 분석 결과를 Discord로 전송한다:
```bash
python -c "
import asyncio, json, os, sys
sys.path.insert(0, '.')
from app.main import load_env; load_env()
from app.monitor.notifier import send
ctx = json.load(open('data/daily_context.json', encoding='utf-8'))
hot = ', '.join(ctx.get('hot_sectors', [])) or '없음'
avoid = ', '.join(ctx.get('avoid_sectors', [])) or '없음'
boosted = ', '.join(ctx.get('boosted_tickers', [])) or '없음'
flag = '✅ 거래허용' if ctx.get('trade_allowed', True) else '🚫 거래중단'
msg = f'[장전분석] {ctx[\"date\"]} {ctx.get(\"generated_at\",\"\")}\n시장: {ctx[\"market_sentiment\"]}({ctx[\"sentiment_score\"]}점) | 리스크: {ctx[\"risk_level\"]} | {flag}\n주목 섹터: {hot}\n회피 섹터: {avoid}\n관심 종목: {boosted}\n비중 배율: x{ctx.get(\"position_size_multiplier\",1.0)}\n📝 {ctx.get(\"reason\",\"\")}'
asyncio.run(send(msg))
print('Discord 전송 완료')
"
```
### 5. 완료
분석 요약을 한 줄로 출력하고 종료한다.
+71
View File
@@ -0,0 +1,71 @@
# start-bot — 매매 봇 백그라운드 시작
`app/main.py`를 독립 백그라운드 프로세스로 실행한다.
Claude Code가 종료된 뒤에도 봇은 계속 실행된다.
## 실행 순서
### 1. 기존 봇 전부 종료 (PID 파일 + 프로세스 스캔 병행)
```python
import subprocess, os
pid_file = r'C:\Users\whdwo\OneDrive\바탕 화면\stockbot_v3\logs\bot.pid'
# 1-a) PID 파일로 종료
if os.path.exists(pid_file):
try:
pid = int(open(pid_file).read().strip())
subprocess.run(['taskkill', '/PID', str(pid), '/F'], capture_output=True)
print(f'PID 파일 종료: {pid}')
except Exception as e:
print(f'PID 파일 종료 실패: {e}')
os.remove(pid_file)
# 1-b) Get-CimInstance로 잔존 프로세스 스캔해서 모두 종료
r = subprocess.run(
['powershell', '-Command',
'Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like "*app/main.py*" -or $_.CommandLine -like "*app\\main.py*" } | Select-Object -ExpandProperty ProcessId'],
capture_output=True, text=True
)
pids = [p.strip() for p in r.stdout.strip().splitlines() if p.strip().isdigit()]
for pid in pids:
subprocess.run(['taskkill', '/PID', pid, '/F'], capture_output=True)
print(f'잔존 프로세스 종료: {pid}')
if not pids:
print('실행 중인 봇 없음 — 새로 시작합니다')
```
### 2. 봇 시작 + PID 저장
```python
import subprocess, sys, os
os.chdir(r'C:\Users\whdwo\OneDrive\바탕 화면\stockbot_v3')
proc = subprocess.Popen(
[sys.executable, 'app/main.py'],
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
stdout=open('logs/bot_stderr.log', 'a', encoding='utf-8'),
stderr=subprocess.STDOUT,
close_fds=True,
)
# PID 파일 저장 (다음 재시작 때 확실히 종료하기 위해)
with open('logs/bot.pid', 'w') as f:
f.write(str(proc.pid))
print(f'봇 시작 완료 PID={proc.pid}')
```
### 3. Discord 시작 알림
```python
import asyncio, sys, os
sys.path.insert(0, '.')
from app.main import load_env; load_env()
from app.monitor.notifier import send
mode = os.getenv('KIS_MOCK', 'true')
dry = os.getenv('DRY_RUN', 'true')
label = '[모의투자]' if mode == 'true' else '[실거래]'
asyncio.run(send(f'{label} 자동매매 봇 시작 (DRY_RUN={dry})'))
print('Discord 알림 전송 완료')
```
### 4. 완료
"봇 시작 완료" 메시지를 출력하고 종료한다.
+86
View File
@@ -0,0 +1,86 @@
# stop-bot — 봇 정산 후 종료
보유 포지션 현황 확인 → 오늘 결산 Discord 전송 → 봇 프로세스 종료.
장 중 수동 종료 시 사용. 다음 `/start-bot`으로 깨끗하게 재시작 가능.
## 실행 순서
### 1. 현재 수익 현황 출력
```bash
python app/ai/status.py
```
### 2. 오늘 결산 Discord 전송
```python
import asyncio, sys, os
sys.path.insert(0, '.')
from app.main import load_env; load_env()
from app.db.models import get_conn
from app.monitor.notifier import send
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
now_str = datetime.now().strftime("%H:%M")
with get_conn() as conn:
rows = conn.execute("""
SELECT pnl FROM trades
WHERE date=? AND exit_time IS NOT NULL
""", (today,)).fetchall()
open_cnt = conn.execute("SELECT COUNT(*) FROM positions").fetchone()[0]
pnls = [r[0] for r in rows if r[0] is not None]
total = len(pnls)
wins = sum(1 for p in pnls if p > 0)
losses = total - wins
net = sum(pnls)
sign = "+" if net >= 0 else ""
msg = (
f"[수동종료] {today} {now_str} 결산\n"
f"체결: {total}회 (승{wins}{losses}) | 실현손익: {sign}{net:,.0f}\n"
f"미청산 포지션: {open_cnt}개 (청산 없이 종료됨)"
)
asyncio.run(send(msg))
print('Discord 결산 전송 완료')
```
### 3. 봇 프로세스 종료
```python
import subprocess, os
pid_file = r'C:\Users\whdwo\OneDrive\바탕 화면\stockbot_v3\logs\bot.pid'
killed = []
# PID 파일로 종료
if os.path.exists(pid_file):
try:
pid = int(open(pid_file).read().strip())
r = subprocess.run(['taskkill', '/PID', str(pid), '/F'], capture_output=True)
if r.returncode == 0:
killed.append(pid)
except Exception:
pass
os.remove(pid_file)
# 잔존 프로세스 스캔
r = subprocess.run(
['powershell', '-Command',
'Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like "*app/main.py*" -or $_.CommandLine -like "*app\\main.py*" } | Select-Object -ExpandProperty ProcessId'],
capture_output=True, text=True
)
for pid_str in r.stdout.strip().splitlines():
if pid_str.strip().isdigit():
pid = int(pid_str.strip())
subprocess.run(['taskkill', '/PID', str(pid), '/F'], capture_output=True)
killed.append(pid)
if killed:
print(f'봇 종료 완료 (PID: {", ".join(str(p) for p in set(killed))})')
else:
print('실행 중인 봇 없음')
```
### 4. 완료
"봇 종료 완료. 재시작하려면 /start-bot 실행" 메시지를 출력하고 종료한다.