A Python asyncio market monitor and alert system focused on MA cluster density and 200MA touch detection. When conditions are met, it pushes instant Telegram notifications to support trading decisions.
Since v0.2, optional integration with TradingAgents: rule-based MAs decide when to alert; multi-agent LLM analysis helps interpret what it might mean after each alert.
Current version: v0.2 — hybrid data sources + Telegram alerts + optional TradingAgents AI analysis
Languages: English (this file) · 中文 readme
Disclaimer
The author does not trade live with this system or work in the finance industry. This is a paper-trading / portfolio project for learning only. Not financial advice.
Core Philosophy
- Value investing — watch meaningful assets only
- Buy the dip — no entry until price reaches a “bargain” zone; with enough symbols, something will eventually qualify
- Survival first — not losing is winning
- Trust the MAs, not headlines — moving averages reflect where real money has settled
Features
| Feature | Description | Status |
|---|---|---|
| MA cluster alerts | 20/60/120 MA & EMA (6 lines), 4H / 1D / 1W, spread ≤ 0.8% | ✅ |
| 200MA touch alerts | 1D / 1W only, 200MA only (not 200EMA), distance ≤ 1.2% | ✅ |
| Telegram commands | /status, /status BTC, /clear, etc. |
✅ |
| Binance futures | Crypto (BTC, ETH, …) via WebSocket | ✅ |
| Nasdaq / Yahoo | US equities & gold (GC=F) — historical bars + polled price | ✅ |
| Telegram push | Touch-triggered, cooldown + debounce | ✅ |
| Dynamic config | Watchlist in config.yaml |
✅ |
| AI deep-dive | Auto TradingAgents analysis after alerts (optional) | ✅ |
| Database | None (v1 in-memory; cooldown resets on restart) | — |
Monitoring Rules
Each symbol is monitored independently on 3 timeframes. Alerts cooldown per symbol + interval + type.
Example: BTC/USDT
| Check | 4H | 1D | 1W |
|---|---|---|---|
| MA cluster (6-line spread ≤ 0.8%) | ✅ | ✅ | ✅ |
| 200MA touch (≤ 1.2% from 200MA) | — | ✅ | ✅ |
No 200MA touch on 4H. 200EMA is not used for touch alerts.
13 symbols today (see config.yaml): 5 crypto + 8 US equities/ETFs/gold.
Each interval needs ≥200 closed bars at startup; otherwise that monitor is skipped (e.g. HYPE 1W, CRCL 1W). Typically ~37/39 monitors are active.
Tech Stack
| Layer | Technology |
|---|---|
| Language | Python 3.12+ |
| Package manager | uv |
| Market data | Binance USDT-M futures (crypto) + Yahoo Finance (equities/gold) |
| Indicators | Pandas |
| Alerts | Telegram Bot API |
| Runtime | Asyncio |
| Deploy | Docker + systemd |
Project Structure
invest-alert-bot/
├── app/
│ ├── main.py # Entry point
│ ├── core/ # Config, logging
│ ├── schemas/ # Pydantic models
│ ├── providers/ # Binance WS/REST, yfinance, TradingAgents
│ ├── services/ # Engine, alerts, coordinator, analysis worker
│ └── notifiers/ # Telegram push & commands
├── tests/
├── config.yaml # Watchlist & thresholds
├── .env.example # Telegram & AI keys template
├── Dockerfile
├── prd.md
├── plan.md
└── README.md
Architecture
Code layout
Single-process asyncio app: providers fetch data, services compute & orchestrate, notifiers talk to Telegram.
flowchart TB
subgraph Entry["Entry"]
MAIN["app/main.py"]
end
subgraph Core["core/ — infrastructure"]
CFG["config.py<br/>config.yaml + .env"]
LOG["logging.py"]
end
subgraph Schemas["schemas/ — models"]
MK["market.py<br/>Kline · Tick · Indicators"]
AL["alert.py<br/>AlertEvent · AlertType"]
SC["config.py<br/>AppConfig · SymbolConfig"]
end
subgraph Providers["providers/ — market data"]
BREST["binance_rest.py"]
BWS["binance_ws.py"]
YF["yfinance_poll.py"]
TA["tradingagents_client.py"]
end
subgraph Services["services/ — business logic"]
COORD["coordinator.py"]
SM["symbol_monitor.py"]
ENG["engine.py"]
AM["alert_manager.py"]
AW["analysis_worker.py"]
end
subgraph Notifiers["notifiers/"]
TG["telegram.py"]
TGCMD["telegram_commands.py"]
end
subgraph External["External (no API key)"]
BINREST["Binance REST"]
BINWS["Binance WebSocket"]
YAHOO["Yahoo Finance"]
end
subgraph ExternalAuth["External (requires .env)"]
TGAPI["Telegram Bot API"]
LLM["LLM API (DeepSeek/OpenAI)"]
end
MAIN --> CFG
MAIN --> COORD
MAIN --> TGCMD
COORD --> BREST & BWS & YF
COORD --> SM
SM --> ENG & AM
SM -->|AlertEvent| COORD
COORD --> TG
COORD --> AW
AW --> TA
AW --> TG
TGCMD -->|format_status| COORD
BREST --> BINREST
BWS --> BINWS
YF --> YAHOO
TA --> LLM
TG & TGCMD --> TGAPI
| Layer | Directory | Role |
|---|---|---|
| Entry | main.py |
Start coordinator + Telegram command bot; handle SIGINT/SIGTERM |
| Orchestration | coordinator.py |
Init monitors, wire data sources, route tick/kline updates |
| Monitor | symbol_monitor.py |
Per symbol × interval: bars, indicators, live price |
| Engine | engine.py |
Pandas MA/EMA; cluster & touch detection |
| Alerts | alert_manager.py |
4h cooldown + 60s debounce per (symbol, interval, type) |
| Market data | providers/ |
Binance REST/WS, Yahoo polling |
| Analysis | analysis_worker.py |
Async queue → TradingAgents → Telegram summary + HTML |
| Notify | notifiers/ |
Telegram alerts & commands |
Data flow
Bootstrap
flowchart LR
A["uv run python -m app.main"] --> B["load_config()"]
B --> C["Coordinator.start()"]
C --> D["Binance REST<br/>250 historical bars"]
C --> E["yfinance<br/>250 historical bars"]
D --> F["SymbolMonitor.initialize()"]
E --> F
F --> G["calculate_indicators()<br/>needs ≥200 bars"]
G --> H["Binance WS<br/>aggTrade + kline"]
H --> I["Telegram startup message"]
Runtime
flowchart TB
subgraph Binance["Binance live (source: binance)"]
WS1["aggTrade"] -->|live price| P["SymbolMonitor.on_price()"]
WS2["kline event"] -->|is_closed=true| K["SymbolMonitor.on_kline_closed()"]
K --> R["Recalc MA/EMA"]
R --> P
end
subgraph Yahoo["Yahoo Finance (source: nasdaq)"]
POLL["Poll every 300s"] --> U["update_klines()"]
U --> R2["Recalc MA/EMA"]
R2 --> P2["on_price(latest close)"]
end
P --> E["_evaluate()"]
P2 --> E
E --> C{"Cluster or touch?"}
C -->|No| X["Skip"]
C -->|Yes| D{"AlertManager<br/>cooldown & debounce?"}
D -->|No| X
D -->|Yes| T["TelegramNotifier.send_alert()"]
T --> Q["AnalysisWorker.enqueue()<br/>(if AI enabled)"]
Data sources
Config source |
History | Live price | Notes |
|---|---|---|---|
binance + market: futures |
Binance futures REST | Binance futures WS | Crypto, e.g. BTC/USDT |
nasdaq |
Yahoo Finance | Polled close | US tickers like MSFT; gold XAU + ticker: GC=F |
yfinance |
Same as nasdaq | Same as nasdaq | Alias for nasdaq |
Intervals with fewer than 200 bars are skipped at startup (see logs).
Algorithm
Indicators
Computed from closed bar closes (Pandas rolling/EWM). Requires at least 200 bars.
flowchart LR
KL["Kline[]<br/>max 250 bars"] --> DF["DataFrame(close)"]
DF --> MA20["MA 20"]
DF --> EMA20["EMA 20"]
DF --> MA60["MA 60"]
DF --> EMA60["EMA 60"]
DF --> MA120["MA 120"]
DF --> EMA120["EMA 120"]
DF --> MA200["MA 200"]
DF --> EMA200["EMA 200"]
MA20 & EMA20 & MA60 & EMA60 & MA120 & EMA120 --> IND["Indicators<br/>6 lines for cluster"]
MA200 --> IND
EMA200 -.->|not used for alerts| IND
Alert evaluation (on every price update)
Live price from Binance tick or Yahoo poll; MAs from closed bars — touch does not wait for bar close.
flowchart TB
START["on_price(current_price)"] --> CHECK{"indicators<br/>ready?"}
CHECK -->|No| END["Skip"]
CHECK -->|Yes| CLUSTER
subgraph Cluster["MA cluster (4H / 1D / 1W)"]
CLUSTER["6 MAs: 20/60/120 MA & EMA"]
CLUSTER --> SPREAD["spread = (max - min) / price"]
SPREAD --> COK{"spread ≤ 0.8%?"}
COK -->|Yes| CE["AlertType.CLUSTER"]
end
subgraph Touch["200MA touch (1D / 1W only)"]
TMA["touch = |price - 200MA| / price"]
TMA --> TOK1{"≤ 1.2%?"}
TOK1 -->|Yes| AE1["AlertType.TOUCH_200_MA"]
end
CE & AE1 --> AM["AlertManager.should_send()"]
AM --> COOL{"≥ 4h since last<br/>same-type alert?"}
COOL -->|No| END
COOL -->|Yes| DEDUP{"60s debounce?"}
DEDUP -->|Duplicate| END
DEDUP -->|Pass| SEND["Telegram push"]
SEND --> REC["record_sent()"]
REC --> END
Formulas
MA cluster (6 lines: 20/60/120 MA + EMA):
spread = (max(6 MAs) - min(6 MAs)) / current_price
Trigger: spread ≤ thresholds.cluster (default 0.8%)
200MA touch (1D / 1W only; not 4H; not 200EMA):
touch = abs(current_price - 200MA) / current_price
Trigger: touch ≤ thresholds.touch (default 1.2%)
| Design choice | Detail |
|---|---|
| Touch on live price | No need to wait for bar close |
| MAs from closed bars | Current incomplete bar excluded |
| Cooldown | Default 4 hours per (symbol, interval, alert_type) |
| Debounce | No duplicate send within 60s for same key |
| In-memory state | No DB; cooldown resets on restart |
See prd.md for full specs and acceptance criteria.
End-to-end: Install → Run → Verify
This is a single-process bot (not a web API): one command runs market monitoring + Telegram commands + (optional) AI analysis.
Overview
flowchart TB
subgraph Setup["One-time setup"]
A1["Install uv + clone repo"]
A2["cp .env.example → .env<br/>set TELEGRAM_*"]
A3["Optional: uv sync --extra analysis<br/>set DEEPSEEK_API_KEY"]
end
subgraph Start["Start app.main"]
B1["Load config.yaml + .env"]
B2["Fetch history → init monitors"]
B3["Binance WS + Yahoo poller"]
B4["Telegram command bot online"]
B5["Optional: analysis worker queue"]
end
subgraph Runtime["While running"]
C1["Price update → MAs → alert check"]
C2["Telegram alert push"]
C3["Each alert → enqueue AI job"]
C4["Done → summary + HTML attachment"]
end
A1 --> A2 --> A3 --> B1
B1 --> B2 --> B3 --> B4 --> B5
B5 --> C1 --> C2 --> C3 --> C4
Step 1: Install dependencies
cd invest-alert-bot
# Core (monitoring + alerts — required)
uv sync
# AI analysis (TradingAgents + DeepSeek) — optional
uv sync --extra analysis
uv syncalone is enough for monitoring and alerts. Without--extra analysis, AI is disabled and the startup message will say so.
Step 2: Configure environment
cp .env.example .env
Minimum (alerts only):
TELEGRAM_BOT_TOKEN=your_botfather_token
TELEGRAM_CHAT_ID=your_numeric_chat_id
For AI analysis, also set:
ANALYSIS_ENABLED=true
LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=your_deepseek_key
DeepSeek base URL is built into TradingAgents (https://api.deepseek.com). Watchlist and thresholds live in config.yaml.
Step 3: Run
uv run python -m app.main
Success indicators:
- No errors in terminal; logs like:
Coordinator started with XX monitorsBinance futures WS startedEquity poller started: MSFT ...Analysis worker started(if AI enabled)
- Telegram startup message with monitor count and
🧠 AI analysis: enabled (deepseek)(or disabled / not installed) /startor/statusreturns a reply
Press Ctrl+C to stop.
Step 4: Verification checklist
| # | Check | Command / action | Expected |
|---|---|---|---|
| 1 | Unit tests | uv run pytest tests/ -v |
All PASS |
| 2 | Lint | uv run ruff check app tests |
No errors |
| 3 | Telegram | uv run python -m app.scripts.test_telegram |
Test message received |
| 4 | Bot online | Send /status |
Full watchlist status |
| 5 | Single symbol | /status MSFT |
MSFT per-interval cluster / 200MA |
| 6 | AI package | uv run python -c "import tradingagents; print('ok')" |
Prints ok (skip if no AI) |
| 7 | Manual AI | /analyze MSFT |
“Queued…” → summary + HTML in ~5–20 min |
| 8 | Alert → AI | Wait for real alert or watch logs | Alert push → auto AI queue (if enabled) |
Logs: logs/app.log (configure in config.yaml → logging)
AI reports: reports/report_*.html (also sent as Telegram attachments)
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
TELEGRAM_* missing on start |
Empty .env |
Fill per .env.example |
| AI shows “not installed” | Missing --extra analysis |
Run uv sync --extra analysis, restart |
| AI shows “disabled” | ANALYSIS_ENABLED=false |
Set true + DEEPSEEK_API_KEY |
nan% in /status |
Incomplete Yahoo bars | Update code & restart (fixed in current version) |
| Some intervals skipped | <200 bars | Check startup log Skip monitor — expected for new listings |
Quick Start
Create a Telegram bot (one-time)
You need a Bot Token and Chat ID.
1. BotFather
- Open @BotFather in Telegram
- Send
/newbot - Choose a display name, e.g.
Invest Alert Bot - Choose a username ending in
bot, e.g.my_invest_alert_bot - Copy the token →
TELEGRAM_BOT_TOKEN
2. Chat ID
Option A (recommended):
uv run python -m app.scripts.get_chat_id
Send your bot a message when prompted; the script prints TELEGRAM_CHAT_ID.
Option B: @userinfobot → copy numeric Id
Option C: Browser getUpdates
- Message your bot (
/start) - Visit
https://api.telegram.org/bot<TOKEN>/getUpdates - Find
"chat":{"id":123456789}
Empty
"result":[]? Message the correct bot, or calldeleteWebhookfirst.
3. Write .env
cp .env.example .env
TELEGRAM_BOT_TOKEN=7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TELEGRAM_CHAT_ID=123456789
Install & configure
# Install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh
git clone https://github.com/Formyselfonly/invest-alert-bot.git
cd invest-alert-bot
uv sync
# uv sync --extra analysis # if you want AI
Edit config.yaml:
symbols:
# Crypto — Binance futures
- symbol: BTC/USDT
source: binance
market: futures
intervals: [4h, 1d, 1wk]
# US equity — Yahoo Finance
- symbol: MSFT
source: nasdaq
intervals: [4h, 1d, 1wk]
# Gold — COMEX futures
- symbol: XAU
source: nasdaq
ticker: GC=F
intervals: [4h, 1d, 1wk]
thresholds:
cluster: 0.008 # 0.8% cluster width
touch: 0.012 # 1.2% from 200MA
How to run (no FastAPI)
This project is not a web API. One command keeps the bot alive:
uv run python -m app.main
Process running = bot online. Close the terminal = bot offline.
Telegram-only smoke test (no full monitor): uv run python -m app.scripts.test_telegram
Telegram commands
| Command | Action |
|---|---|
/start |
Welcome & menu |
/status |
All symbols × intervals |
/status BTC |
Single symbol |
/analyze MSFT |
Manual AI analysis (requires AI enabled) |
/clear |
Clear chat (does not reset alerts) |
/help |
Help |
Alert titles: 📊 MA cluster — entry opportunity / 🎯 200MA touch — dip opportunity
After alerts (if AI enabled): auto 🧠 Analysis queued… → summary + HTML attachment.
Tests
uv run pytest tests/ -v
uv run ruff check app tests
Sample alert
📊 Invest Alert Bot
━━━━━━━━━━━━━━━
Alert: MA cluster
Asset: BTC/USDT
Interval: 4H
Price: $67,432.5000
Detail: Cluster width 0.62% (threshold 0.8%)
Time: 2026-06-16 14:32:08 UTC
Configuration reference
| Setting | File | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN |
.env |
From BotFather |
TELEGRAM_CHAT_ID |
.env |
Your Telegram user ID |
ANALYSIS_ENABLED |
.env |
Enable TradingAgents queue |
LLM_PROVIDER |
.env |
e.g. deepseek, openai |
symbols |
config.yaml |
Watchlist |
thresholds.cluster |
config.yaml |
Default 0.008 (0.8%) |
thresholds.touch |
config.yaml |
Default 0.012 (1.2%) |
alert.cooldown_seconds |
config.yaml |
Default 14400 (4 hours) |
Docker
docker build -t invest-alert-bot .
docker run -d \
--name invest-alert-bot \
--restart always \
--env-file .env \
-v $(pwd)/config.yaml:/app/config.yaml \
-v $(pwd)/logs:/app/logs \
invest-alert-bot
Best on an always-on VM (AWS EC2 / Lightsail). Not suited to serverless.
Relationship to TradingAgents
This repo is a downstream integration of TradingAgents — not a fork of the upstream project.
| TradingAgents (upstream) | Invest Alert Bot (this repo) | |
|---|---|---|
| Role | Multi-agent LLM financial research framework | 24/7 MA monitor + Telegram alert bot |
| Trigger | CLI / manual propagate(ticker, date) |
Auto-queue on every alert + /analyze |
| Latency | Minutes | Alerts in seconds; AI async 5–20 min |
| Core logic | Fundamentals, sentiment, news, debate | Rule-based MAs (cluster + 200MA) |
| Install | pip install tradingagents |
uv sync --extra analysis |
Where TradingAgents runs in this project
Division of labor: the bot answers “when to look” (second-level rule alerts); TradingAgents answers “how to read it / is it worth acting on” (multi-agent research over minutes). Moving averages remain the only automatic alert source — AI does not change thresholds or place orders.
End-to-end flow
flowchart TD
A["Alert push or /analyze MSFT"] --> B["Coordinator picks monitor\nprefers 1d interval"]
B --> C["build_snapshot()\nprice + MAs + alert context"]
C --> D["AnalysisWorker background queue\ndoes not block Binance WS"]
D --> E["TradingAgentsClient.run()\nsync in thread pool"]
E --> F["build_briefing()\ninject bot MA snapshot"]
F --> G["TradingAgentsGraph.propagate(ticker, date)"]
G --> H1["Market Analyst\nyfinance OHLCV + indicators + LLM"]
H1 --> H2["Sentiment Analyst\nnews + StockTwits + Reddit + LLM"]
H2 --> H3["News Analyst\nnews + macro + insider trades + LLM"]
H3 --> H4["Fundamentals Analyst\nfinancials + LLM"]
H4 --> I["Bull ↔ Bear debate\nANALYSIS_MAX_DEBATE_ROUNDS"]
I --> J["Research Manager + Trader + LLM"]
J --> K["Aggressive / Conservative / Neutral risk debate + LLM"]
K --> L["Portfolio Manager\nBUY / HOLD / SELL + LLM"]
L --> M["Merge bot snapshot + decision text"]
M --> N["write_html_report() → reports/"]
N --> O["Telegram summary + HTML attachment"]
What the result depends on
| Source | Content | Determinism |
|---|---|---|
| Invest Alert Bot | Price, MA20/60/120/200, cluster width, 200MA distance, alert type | High (live kline math) |
| TradingAgents / yfinance | OHLCV, MACD/RSI, fundamentals, news | Medium (external API) |
| TradingAgents / StockTwits | Retail Bullish/Bearish sentiment | Medium |
| TradingAgents / Reddit | r/wallstreetbets, r/stocks, r/investing posts | Low (often 403-blocked; degrades gracefully) |
| DeepSeek / OpenAI LLM | Debate, synthesis, final stance | Low (non-deterministic) |
Why it takes so long
TradingAgents runs 4 analysts + bull/bear debate + trader + three-way risk debate + portfolio manager in sequence. Each step waits on data fetches and LLM calls (often 10–60s each). A full run is typically 5–20 minutes. Default timeout: ANALYSIS_TIMEOUT_SECONDS=1800 (30 minutes).
Reddit 403 errors come from TradingAgents’ built-in sentiment data source being blocked — analysis continues with degraded social data and is unrelated to timeout failures.
- Wrapper:
app/providers/tradingagents_client.py - Design doc: tradingagents-iteration.md
- Default LLM:
LLM_PROVIDER=deepseek(OpenAI and other upstream providers also work)
Citing TradingAgents
@misc{xiao2025tradingagentsmultiagentsllmfinancial,
title={TradingAgents: Multi-Agents LLM Financial Trading Framework},
author={Yijia Xiao and Edward Sun and Di Luo and Wei Wang},
year={2025},
eprint={2412.20138},
archivePrefix={arXiv},
primaryClass={q-fin.TR},
url={https://arxiv.org/abs/2412.20138},
}
Getting visibility with the upstream project
| Approach | Action |
|---|---|
| README + Star | Keep this section; star TradingAgents |
| Showcase Issue | Open an issue on upstream with repo link & architecture — good for community discovery |
| Docs PR | Propose a “Community Projects” line or minimal examples/ snippet upstream |
| Discord | Share in upstream Discord showcase channel |
Enable AI analysis (TradingAgents)
Important: Monitoring and alerts work without AI dependencies. Only the deep-dive analysis is skipped.
1. Optional dependency
uv sync --extra analysis
2. .env
ANALYSIS_ENABLED=true
LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=your_key
DeepSeek uses OpenAI-compatible API (endpoint built into TradingAgents). For OpenAI: LLM_PROVIDER=openai + OPENAI_API_KEY.
Optional tuning:
ANALYSIS_ANALYSTS=market,news,fundamentals # comma-separated; default omits social
ANALYSIS_MAX_DEBATE_ROUNDS=1 # debate rounds; higher = slower
ANALYSIS_TIMEOUT_SECONDS=1800 # per-run timeout (seconds); default 30 min
3. Behavior
| Event | Behavior |
|---|---|
| After any alert | Auto-queue TradingAgents analysis (~5–20 min) |
| Analysis starts | Telegram: “Analysis queued…” |
| Analysis done | Summary message + HTML report attachment |
/analyze MSFT |
Manual trigger (no alert required) |
Reports are saved under reports/ and attached in Telegram.
Startup message shows: 🧠 AI analysis: enabled (deepseek) or disabled / not installed.
4. How to read the analysis output
What’s in the HTML report
After analysis completes, Telegram sends a summary message plus an HTML attachment. Typical sections:
| Section | Content |
|---|---|
| Bot snapshot | Price, MAs, cluster width, 200MA distance (ground truth — AI must not invent prices) |
| Overall rating | Final label, e.g. Hold |
| Portfolio Manager decision | Full write-up (Executive Summary, stop/add conditions, etc.) |
| Market analysis | TradingAgents technical view (MACD, RSI, MAs, …) |
| News & macro | Ticker news + Fed / macro headlines |
| Fundamentals | Financials, valuation, cash flow (stocks / ETFs) |
| Trader plan | Trading stance summary |
| Bull/Bear debate & risk review | Debate conclusions |
The Telegram summary prefers the Executive Summary; use the HTML attachment for the full report.
What the final rating means (Buy / Hold / Sell…)
After all analysts, debate, and risk review, the Portfolio Manager outputs a 5-tier rating (most bullish → most bearish):
| Rating | Meaning (research view — not a trade order) |
|---|---|
| Buy | Strong bullish — add / open position |
| Overweight | Bullish — above benchmark weight |
| Hold | Neutral — maintain status quo; no add, no cut; wait and watch |
| Underweight | Bearish — below benchmark weight |
| Sell | Strong bearish — reduce / exit |
Hold does not mean “no analysis” or “analysis failed”. It means the AI sees offsetting bull/bear factors: not worth buying actively, not worth selling actively — keep current exposure.
Example (MSFT far below 200MA): decent fundamentals + weak technicals → often Hold (stay at benchmark weight; consider adds only after a confirmed reclaim of key levels).
How this relates to Bot MA alerts
| Layer | Says what |
|---|---|
| Bot alert | “Price hit a rule level — time to look” — rule trigger (seconds) |
| AI rating | “After review, is it worth acting?” — research conclusion (minutes) |
Division of labor:
- Bot cluster / 200MA rules remain the only automatic alert source
- AI does not change alert thresholds and does not place orders
Holdmeans: the alert is worth attention, but AI does not support adding or cutting right now
Disclaimer: AI output is for research only, not investment advice. You may compare it with your MA strategy;
Holdis not a hard ban on trading.
Details: tradingagents-iteration.md.
Documentation
| Doc | Description |
|---|---|
| readme.zh-CN.md | Chinese README |
| prd.md | Product requirements & acceptance |
| plan.md | Development plan |
| tradingagents-iteration.md | TradingAgents integration design |
| TradingAgents upstream | Official multi-agent framework |
Comments