feat: rewrite strategy to 10m vol-lead with undying signal + watch alert
- core/strategy.py: full rewrite to Volume Lead strategy - 10m candle direct detection (no 40m resampling) - F&G 3-tier vol threshold: <=40->6x, 41-50->5x, >50->blocked - Undying signal: price drop does not cancel signal (sig_p fixed) - Vol refresh: stronger vol_r updates signal price and timer - Watch alert: 4x-6x approaching threshold notifies via Telegram - WATCH_VOL_THRESH=4.0, WATCH_COOLDOWN_MIN=30, WATCH_VOL_JUMP=0.5 - daemon/runner.py: remove FNG_MIN_ENTRY block and Bear regime block - Only FNG_MAX_ENTRY(>50) blocks scan (greed/extreme greed) - Fast-poll loop cleaned of regime check - core/notify.py: add notify_watch() for near-signal Telegram alerts - Shows vol_r, distance to threshold, price, quiet pct - tests/: add 1y data collection and simulation scripts - collect_1y_data.py, refresh_cache.py - sim_10m_vol.py, sim_current.py, sim_regime_1y.py - sim_regime_sweep.py, sim_vol_override.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,10 +6,9 @@ import threading
|
||||
import time
|
||||
|
||||
from core import trader
|
||||
from core.fng import FNG_MIN_ENTRY, get_fng
|
||||
from core.fng import get_fng
|
||||
from core.market import get_top_tickers
|
||||
from core.market_regime import get_regime
|
||||
from core.strategy import get_active_signals, should_buy
|
||||
from core.strategy import FNG_MAX_ENTRY, get_active_signals, should_buy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -28,21 +27,19 @@ def _fast_poll_loop() -> None:
|
||||
try:
|
||||
signals = get_active_signals()
|
||||
if signals:
|
||||
regime = get_regime()
|
||||
if regime["name"] != "bear":
|
||||
positions = trader.get_positions()
|
||||
for ticker in list(signals):
|
||||
if ticker in positions:
|
||||
continue
|
||||
if len(positions) >= trader.MAX_POSITIONS:
|
||||
break
|
||||
try:
|
||||
if should_buy(ticker):
|
||||
logger.info(f"[빠른감시] 매수 신호: {ticker}")
|
||||
trader.buy(ticker)
|
||||
time.sleep(0.1)
|
||||
except Exception as e:
|
||||
logger.error(f"[빠른감시] 오류 {ticker}: {e}")
|
||||
positions = trader.get_positions()
|
||||
for ticker in list(signals):
|
||||
if ticker in positions:
|
||||
continue
|
||||
if len(positions) >= trader.MAX_POSITIONS:
|
||||
break
|
||||
try:
|
||||
if should_buy(ticker):
|
||||
logger.info(f"[빠른감시] 매수 신호: {ticker}")
|
||||
trader.buy(ticker)
|
||||
time.sleep(0.1)
|
||||
except Exception as e:
|
||||
logger.error(f"[빠른감시] 오류 {ticker}: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"신호 감시 루프 오류: {e}")
|
||||
|
||||
@@ -64,26 +61,16 @@ def run_scanner() -> None:
|
||||
time.sleep(SCAN_INTERVAL)
|
||||
continue
|
||||
|
||||
# Bear 레짐 시 신규 매수 완전 차단
|
||||
regime = get_regime()
|
||||
if regime["name"] == "bear":
|
||||
logger.info(
|
||||
f"[Bear차단] 레짐={regime['emoji']} BEAR "
|
||||
f"(score={regime['score']:+.2f}%) — 신규 매수 스킵"
|
||||
)
|
||||
time.sleep(SCAN_INTERVAL)
|
||||
continue
|
||||
|
||||
# F&G 진입 필터 — 차단 구간이면 전체 스캔 스킵
|
||||
# F&G 탐욕/극탐욕 구간 → 전체 스캔 스킵 (strategy.py와 동일 기준)
|
||||
fv = get_fng()
|
||||
fng_label = (
|
||||
"극탐욕" if fv >= 76 else "탐욕" if fv >= 56 else
|
||||
"중립" if fv >= 46 else "약공포" if fv >= 41 else
|
||||
"공포" if fv >= 26 else "극공포"
|
||||
)
|
||||
if fv < FNG_MIN_ENTRY:
|
||||
if fv > FNG_MAX_ENTRY:
|
||||
logger.info(
|
||||
f"[F&G차단] F&G={fv} ({fng_label}) < {FNG_MIN_ENTRY} — 신규 매수 스킵"
|
||||
f"[F&G차단] F&G={fv} ({fng_label}) > {FNG_MAX_ENTRY} — 탐욕 구간 스캔 스킵"
|
||||
)
|
||||
time.sleep(SCAN_INTERVAL)
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user