Relax LLM entry filters, show 1h-bullish HOLD reasons in cycle report
- llm_analyzer.py: change 5m filters from hard requirements to confidence adjustments (volume, ADX<15, OBV direction now ±0.1 instead of blocking); 1h ADX<20 lowers confidence instead of preventing entry - slack_notifier.py: when all symbols HOLD, show 1h-bullish symbols with their HOLD reason instead of generic "no action" message - main.py: log all 15 HOLD reasons instead of first 3 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d261b36460
commit
b2d7495ec0
@ -26,7 +26,7 @@ def analyze_market(indicator_summary: str, account_status: str) -> list[dict]:
|
||||
### 最高優先:多時間框架過濾(現貨,只做多)
|
||||
- 1小時趨勢為多頭(EMA9 > EMA21)時,才考慮 BUY
|
||||
- 1小時為空頭時,只持有或平倉(SELL),不開新倉
|
||||
- 1小時 ADX < 20(盤整)時,避免進場
|
||||
- 1小時 ADX < 20(盤整)時,降低信心但不禁止進場
|
||||
- 1小時 ADX > 25 且方向一致 = 高信心交易
|
||||
|
||||
### 進場訊號 (BUY) — 需至少2個確認
|
||||
@ -42,11 +42,12 @@ def analyze_market(indicator_summary: str, account_status: str) -> list[dict]:
|
||||
3. **趨勢反轉確認**: MACD 死叉 + EMA9 下穿 EMA21 + 1h 趨勢也轉空
|
||||
- 若 1h 趨勢仍為多頭,即使 5m 出現賣出訊號,也應降低信心或 HOLD
|
||||
|
||||
### 過濾條件(必須全部滿足)
|
||||
- 成交量需高於 20 期平均(確認動能)
|
||||
- 5分鐘 ADX > 15(排除極度盤整)
|
||||
- OBV 方向需與交易方向一致(量價確認)
|
||||
### 輔助條件(加減分,非硬性過濾)
|
||||
- 成交量高於 MA20 → 信心 +0.1;遠低於 MA20 → 信心 -0.1
|
||||
- 5分鐘 ADX > 15 → 正常;ADX < 15 → 信心 -0.1(但不禁止進場)
|
||||
- OBV 方向與交易一致 → 信心 +0.1;相反 → 信心 -0.1
|
||||
- ATR 過高時降低 suggested_amount_pct(波動風控)
|
||||
- 這些條件用於調整信心分數,不應單獨阻擋進場
|
||||
|
||||
### 信心分數指引
|
||||
- 0.8+: 多時間框架對齊 + 3個以上確認指標
|
||||
|
||||
16
main.py
16
main.py
@ -121,11 +121,12 @@ def run_cycle():
|
||||
if o.get("type") == "EXCHANGE STOP":
|
||||
stop_orders_by_sym.setdefault(o["symbol"], []).append(o)
|
||||
|
||||
# Build map: currency → wallet balance (for accurate stop-loss amounts)
|
||||
# Build map: currency → wallet available balance (for accurate stop-loss amounts)
|
||||
# Use "available" (not "balance") to exclude coins locked by existing orders
|
||||
wallet_balances = {}
|
||||
for w in account_status.get("wallets", []):
|
||||
if w.get("type") == "exchange":
|
||||
wallet_balances[w["currency"]] = w.get("balance", 0)
|
||||
wallet_balances[w["currency"]] = w.get("available", 0) or w.get("balance", 0)
|
||||
|
||||
# Load tracked stops early — needed for both stop sync and fill detection
|
||||
tracked_stops = _load_tracked_stops()
|
||||
@ -435,6 +436,17 @@ def run_cycle():
|
||||
time.sleep(1.0) # Wait for Bitfinex to release locked balance
|
||||
|
||||
# Place new stop-loss for TOTAL position amount at new avg entry
|
||||
# Refresh wallet balance to get actual available amount (handles partial fills, fees)
|
||||
try:
|
||||
refreshed_status = data_fetcher.fetch_account_status()
|
||||
currency = sym[1:].replace(":UST", "").replace("UST", "")
|
||||
wallet_amt = 0
|
||||
for w in refreshed_status.get("wallets", []):
|
||||
if w.get("type") == "exchange" and w.get("currency") == currency:
|
||||
wallet_amt = w.get("available", 0) or w.get("balance", 0)
|
||||
break
|
||||
total_amount = wallet_amt if wallet_amt > 0 else pos.get("amount", amount)
|
||||
except Exception:
|
||||
total_amount = pos.get("amount", amount)
|
||||
entry_price = pos.get("entry_price", price)
|
||||
|
||||
|
||||
@ -103,7 +103,17 @@ def send_cycle_report(
|
||||
if not llm_ok:
|
||||
lines.append(" ⚠️ LLM 分析失敗,本次跳過。")
|
||||
else:
|
||||
lines.append(" All symbols → HOLD, no action this cycle.")
|
||||
# Show why 1h-bullish symbols didn't enter
|
||||
bullish_holds = [s for s in holds if "多頭" in s.get("reason", "")]
|
||||
if bullish_holds:
|
||||
for s in bullish_holds:
|
||||
name = config.SYMBOL_NAMES.get(s["symbol"], s["symbol"])
|
||||
lines.append(f" 🟡 {name} (1h多頭) HOLD — {s.get('reason', '')}")
|
||||
other_count = len(holds) - len(bullish_holds)
|
||||
if other_count > 0:
|
||||
lines.append(f" 🔴 其餘 {other_count} 幣種 1h 空頭 HOLD")
|
||||
else:
|
||||
lines.append(" 🔴 全部 1h 空頭,無進場機會")
|
||||
lines.append("")
|
||||
|
||||
# --- Executed trades ---
|
||||
|
||||
Loading…
Reference in New Issue
Block a user