From 009d71bca0a35bed5a37e09a1ad979bbf69dac7d Mon Sep 17 00:00:00 2001 From: shuim Date: Mon, 23 Feb 2026 08:55:11 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/endpoints/recommendations.py | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/backend/app/api/endpoints/recommendations.py b/backend/app/api/endpoints/recommendations.py index 88297d2..cdf6881 100644 --- a/backend/app/api/endpoints/recommendations.py +++ b/backend/app/api/endpoints/recommendations.py @@ -173,7 +173,7 @@ def analyze_custom_signals(chart_data): disparity = (close / ma20) * 100 # ๐Ÿšซ ๊ธ‰๋“ฑ ์ข…๋ชฉ ํ•„ํ„ฐ: ์ตœ๊ทผ 3์ผ ์ƒ์Šน๋ฅ  ์ฒดํฌ - if len(closes) >= 3: + if len(closes) >= 4: price_3days_ago = closes[-4] recent_gain = ((close - price_3days_ago) / price_3days_ago) * 100 if price_3days_ago > 0 else 0 if recent_gain > 10: # 3์ผ๊ฐ„ 10% ์ด์ƒ ๊ธ‰๋“ฑ ์‹œ ๋งค์ˆ˜ ์•ˆํ•จ @@ -1123,8 +1123,14 @@ async def get_rule_based_recommendations( result = await get_rule_based_recommendations_from_db(db) # ์ž๋™๋งค๋งค ์‹คํ–‰ (๋ฐฑ๊ทธ๋ผ์šด๋“œ) + # ์ฃผ์˜: ์—”๋“œํฌ์ธํŠธ ๋ฐ˜ํ™˜ ํ›„ FastAPI๊ฐ€ db ์„ธ์…˜์„ ๋‹ซ์œผ๋ฏ€๋กœ, + # ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํƒœ์Šคํฌ๋Š” ๋…๋ฆฝ์ ์ธ ์ƒˆ ์„ธ์…˜์„ ์—ด์–ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. if auto_trade and result.get("recommendations_by_rule"): - asyncio.create_task(execute_auto_trade_background(result, db)) + rec_snapshot = result + async def _bg_trade(): + async with AsyncSessionLocal() as bg_db: + await execute_auto_trade_background(rec_snapshot, bg_db) + asyncio.create_task(_bg_trade()) logger.info("๐Ÿค– Auto-trade task created in background") return result @@ -2033,16 +2039,16 @@ async def execute_auto_trade(stock: dict, db: AsyncSession): score_val = 0.0 buy_keywords = [ - "์ •๋ฐฐ์—ด ์ƒ์Šน ๋งค์ˆ˜ํƒ€์ ", - "๋ˆŒ๋ฆผ๋ชฉ", # ๋ˆŒ๋ฆผ๋ชฉ ์ง„์ž… ๋งค์ˆ˜ํƒ€์  - "RSI ๊ณผ๋งค๋„", - "RSI ์ค‘๋ฆฝ-์ƒ์Šน", - "์Šคํ† ์บ์Šคํ‹ฑ ๊ณผ๋งค๋„", + "์ •๋ฐฐ์—ด ๋ˆŒ๋ฆผ๋ชฉ ๋งค์ˆ˜", # "์ •๋ฐฐ์—ด ๋ˆŒ๋ฆผ๋ชฉ ๋งค์ˆ˜ (์ด๊ฒฉ๋„ ์•ˆ์ •)" + "๋ˆŒ๋ฆผ๋ชฉ ์ง„์ž… ๋งค์ˆ˜ํƒ€์ ", # "๋ˆŒ๋ฆผ๋ชฉ ์ง„์ž… ๋งค์ˆ˜ํƒ€์ " + "RSI ๋ฐ”๋‹ฅ ํƒˆ์ถœ ๋ฐ˜๋“ฑ", # "RSI ๋ฐ”๋‹ฅ ํƒˆ์ถœ ๋ฐ˜๋“ฑ (XX)" + "RSI ์•ˆ์ • ์ƒ์Šน", # "RSI ์•ˆ์ • ์ƒ์Šน (XX)" + "์Šคํ† ์บ์Šคํ‹ฑ ๊ณผ๋งค๋„", # "์Šคํ† ์บ์Šคํ‹ฑ ๊ณผ๋งค๋„ (%K: XX)" "5์ผ์„  > 20์ผ์„ ", "20์ผ์„  > 60์ผ์„ ", - "๊ณจ๋“ ํฌ๋กœ์Šค", + "๊ณจ๋“ ํฌ๋กœ์Šค", # "MACD ๊ณจ๋“ ํฌ๋กœ์Šค" "๋ณผ๋ฆฐ์ € ํ•˜ํ•œ์„  ํ„ฐ์น˜", - "ADX ๊ฐ•ํ•œ ์ถ”์„ธ", + "ํšก๋ณด์žฅ โ€” ํ‰๊ท ํšŒ๊ท€ ์œ ๋ฆฌ", # "ADX(XX<20) ํšก๋ณด์žฅ โ€” ํ‰๊ท ํšŒ๊ท€ ์œ ๋ฆฌ" "๊ฑฐ๋ž˜๋Ÿ‰ ์ฆ๊ฐ€์™€ ์ƒ์Šน", ] should_buy = any(k in text_signals for k in buy_keywords) @@ -2192,7 +2198,7 @@ async def execute_auto_trade(stock: dict, db: AsyncSession): last_buy_at = recent_buys[0].created_at if recent_buys else None # ์ฟจ๋‹ค์šด ์ฒดํฌ - if last_buy_at and (datetime.now() - last_buy_at).total_seconds() < cooldown_min * 60: + if last_buy_at and (_get_kst_now() - last_buy_at).total_seconds() < cooldown_min * 60: logger.info(f"โณ ์ถ”๊ฐ€๋งค์ˆ˜ ๋Œ€๊ธฐ: {stock_name} {cooldown_min}๋ถ„ ์ฟจ๋‹ค์šด ๋ฏธ๊ฒฝ๊ณผ") return {"action": "HOLD", "stock": stock_name, "reason": "cooldown"}