87 lines
2.5 KiB
Markdown
87 lines
2.5 KiB
Markdown
|
|
# 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 실행" 메시지를 출력하고 종료한다.
|