Skip to content

Commit dde035c

Browse files
aaron-jangclaude
andcommitted
feat: /ticker_use 명령어 추가 — 프로필 기반 운용 종목 선택
기존 /ticker 메뉴는 SOXL/TQQQ 버튼만 하드코딩되어 있어서 신규 등록 티커를 활성화할 수 없었음. upstream commands.py/views.py 수정 없이 독립 명령어로 해결: - /ticker_use TICKER1 [TICKER2 ...] → 프로필에 등록된 티커만 활성화 가능 → 미등록 티커 사용 시 에러 + /ticker_add 안내 - /ticker_list에 활성 종목 ✅ 마커 추가 - 빈 인자 시 현재 활성 종목 + 사용법 표시 예: /ticker_use SOXL TQQQ UPRO Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 420e06b commit dde035c

3 files changed

Lines changed: 55 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ docs/ # 문서
235235
|--------|------|------|
236236
| `/ticker_add` | 신규 티커 등록 | - 양식: `/ticker_add TICKER BASE REVERSE_EXIT TRAILING_STOP`<br>- 예시: `/ticker_add UPRO SPY -18 1.2`<br>- yfinance로 티커/기초자산 실존 검증<br>- 기초자산 매핑, 리버스 탈출 수익률(%), 트레일링 스탑(%) 설정<br>- 시드/분할/목표는 `/seed`, `/settlement`로 별도 설정 |
237237
| `/ticker_remove` | 티커 프로필 삭제 | - 양식: `/ticker_remove TICKER`<br>- 예시: `/ticker_remove UPRO` |
238-
| `/ticker_list` | 등록된 티커 목록 | - 현재 프로필에 등록된 모든 티커 표시<br>- 기초자산, 리버스 탈출, 트레일링 스탑 정보 포함 |
238+
| `/ticker_list` | 등록된 티커 목록 | - 현재 프로필에 등록된 모든 티커 표시<br>- 활성 종목은 ✅로 표시<br>- 기초자산, 리버스 탈출, 트레일링 스탑 정보 포함 |
239+
| `/ticker_use` | 운용 종목 변경 | - 양식: `/ticker_use TICKER1 TICKER2 ...`<br>- 예시: `/ticker_use SOXL TQQQ UPRO`<br>- 프로필에 등록된 티커만 선택 가능<br>- 기본 `/ticker` 메뉴(SOXL/TQQQ 버튼)를 대체 |
239240

240241
---
241242

trading_bot/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ async def post_init(application):
214214
BotCommand("ticker_add", "신규 티커 프로필 등록"),
215215
BotCommand("ticker_remove", "티커 프로필 삭제"),
216216
BotCommand("ticker_list", "등록된 티커 프로필 목록"),
217+
BotCommand("ticker_use", "운용 종목 변경 (프로필 기반)"),
217218
])
218219
app.post_init = post_init
219220

trading_bot/telegram/ticker_commands.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def register(app, bot):
2626
app.add_handler(CommandHandler("ticker_add", _make_ticker_add(bot)))
2727
app.add_handler(CommandHandler("ticker_remove", _make_ticker_remove(bot)))
2828
app.add_handler(CommandHandler("ticker_list", _make_ticker_list(bot)))
29+
app.add_handler(CommandHandler("ticker_use", _make_ticker_use(bot)))
2930

3031

3132
def _make_ticker_add(bot):
@@ -129,15 +130,65 @@ async def cmd_ticker_list(update: Update, context: ContextTypes.DEFAULT_TYPE):
129130
await update.message.reply_text("📋 등록된 티커가 없습니다.")
130131
return
131132

133+
active = bot.cfg.get_active_tickers()
134+
132135
lines = ["📋 <b>[ 등록된 티커 프로필 ]</b>\n"]
133136
for t in sorted(tickers):
134137
profile = tp.get_profile(t)
138+
marker = "✅" if t in active else "⬜"
135139
lines.append(
136-
f"🔹 <b>{t}</b> → {profile['base_ticker']}\n"
140+
f"{marker} <b>{t}</b> → {profile['base_ticker']}\n"
137141
f" 리버스 탈출: {profile['reverse_exit']}% / "
138142
f"트레일링 스탑: {profile['trailing_stop']}%"
139143
)
140144

145+
lines.append("\n💡 운용 종목 변경: <code>/ticker_use TICKER1 TICKER2 ...</code>")
146+
lines.append(" 예: <code>/ticker_use SOXL TQQQ UPRO</code>")
147+
141148
await update.message.reply_text("\n".join(lines), parse_mode='HTML')
142149

143150
return cmd_ticker_list
151+
152+
153+
def _make_ticker_use(bot):
154+
async def cmd_ticker_use(update: Update, context: ContextTypes.DEFAULT_TYPE):
155+
if not bot._is_admin(update):
156+
return
157+
158+
args = context.args
159+
if not args:
160+
active = bot.cfg.get_active_tickers()
161+
await update.message.reply_text(
162+
f"📌 <b>현재 운용 종목:</b> {', '.join(active) if active else '(없음)'}\n\n"
163+
f"사용법:\n"
164+
f"<code>/ticker_use TICKER1 [TICKER2 ...]</code>\n\n"
165+
f"예시:\n"
166+
f"<code>/ticker_use SOXL</code>\n"
167+
f"<code>/ticker_use SOXL TQQQ</code>\n"
168+
f"<code>/ticker_use UPRO</code>",
169+
parse_mode='HTML'
170+
)
171+
return
172+
173+
new_tickers = [t.upper() for t in args]
174+
175+
# 모든 티커가 프로필에 등록되어 있는지 확인
176+
registered = set(tp.list_tickers())
177+
unknown = [t for t in new_tickers if t not in registered]
178+
if unknown:
179+
await update.message.reply_text(
180+
f"❌ 다음 티커는 프로필에 등록되지 않았습니다: <b>{', '.join(unknown)}</b>\n\n"
181+
f"먼저 <code>/ticker_add</code>로 등록하세요.",
182+
parse_mode='HTML'
183+
)
184+
return
185+
186+
bot.cfg.set_active_tickers(new_tickers)
187+
await update.message.reply_text(
188+
f"✅ <b>운용 종목 변경 완료</b>\n\n"
189+
f"▫️ 활성 종목: <b>{', '.join(new_tickers)}</b>\n\n"
190+
f"💡 <code>/sync</code>로 확인하세요.",
191+
parse_mode='HTML'
192+
)
193+
194+
return cmd_ticker_use

0 commit comments

Comments
 (0)