Skip to content

Latest commit

 

History

628 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Serenity (@aleabitoreddit)

Install via skills.sh skills.sh installs

SerenityAlphaTrader Pro

📈 Live Performance

Since 2026-07-16 (current live system): Account +3.32% vs SPY +1.90% (outperforming SPY by 1.42pp) All-time, net of all deposits/withdrawals: +1.67%

Last updated: 2026-08-19 20:30 UTC — percentage returns only, position size/equity not disclosed.

SerenityAlphaTrader Pro (short name: AlphaTrader) — an autonomous AI trading platform whose stock-selection brain reasons through the Serenity supply-chain chokepoint lens.

SerenityAlphaTrader Pro is a fully automated AI quantitative trading system powered by a Python/FastAPI backend and a pure HTML/JS frontend. It runs a hybrid LLM stack (local Qwen3.5 35B MoE + optional DeepSeek-Cloud API) with the Kronos K-line prediction model, and executes real trades across US (Alpaca) and Hong Kong (Moomoo OpenD) markets.

🧭 Powered by the Serenity supply-chain lens

The trade-selection brain applies the analytical methodology of Serenity (@aleabitoreddit) — a public X trader and AI/semiconductor supply-chain analyst who traces hyperscaler capex into the overlooked upstream bottlenecks (optical/CPO, InP substrates, memory/HBM, AI power/grid). His lens is packaged as two installable agent skills under .claude/skills/: serenity-aleabitoreddit (per-ticker theses + track record, distilled from 5,857 tweets) and serenity-chokepoint-analysis (the six-step chokepoint framework). Both are also published standalone at 14H034160212/serenity-skills — install with npx skills add 14H034160212/serenity-skills.

Attribution. The serenity-aleabitoreddit skill is redistributed from the upstream research artifact yan-labs/serenity-aleabitoreddit (skills.sh), which independently distilled the public work of Serenity (@aleabitoreddit). All credit for the underlying research and tweet corpus belongs to them; this project is an independent, unaffiliated redistribution. serenity-chokepoint-analysis is original work by @14H034160212.

⚠️ Decision-support only — not financial advice. The Serenity lens shapes which questions the brain asks; it never auto-trades on copied signals. Serenity's self-reported returns are unverified and carry survivorship/selection bias; his names are volatile micro/small-caps. See the skill's risk framing.

🔴🔴 What's new (2026-07-03) — Plan D management mandate + hybrid 4-master/Serenity cross-validation + rogue-engine kill-switch

Plan D ratified as the standing management mandate. The user formally delegated full ongoing stewardship ("以后你就是我的管家"). Target allocation: 70% SPY / 15% QQQ / 12% BRK.B / 3% cash as the core (95%+ of the portfolio), plus a Serenity satellite for opportunistic active picks, capped at 20% of total portfolio value ($12,333) with a 20%-of-satellite per-name guardrail ($2,467). This cap is non-negotiable by design — see ~/serenity-trader-stack/PLAN_D.md for the full escalating-authorization history and the backtest evidence (0/15 strategies tested achieve simultaneous up-capture>100%/down-capture<100%) behind why the cap exists.

New: crossvalidate_satellite.py — automated hybrid cross-validation, every 4 hours. Runs entirely on-demand-free local compute + a small paid tail:

  1. For each live satellite position (pulled fresh from Alpaca, core SPY/QQQ/BRK.B excluded), runs two independent local Ollama (gemma4:31b) lenses at zero marginal cost: a condensed 4-master value check (Buffett/Munger/段永平/李录 — approximates ai-berkshire's /investment-team, which needs a live Claude Code session and can't itself be cron-triggered) and a Serenity chokepoint re-check (is the original thesis still intact, not a fresh screen).
  2. Escalates to a paid claude -p deep-dive (~$0.05–0.15/call) only when the two lenses disagree, either flags a break, price has moved >15% from cost basis, or 7+ days have passed since the last paid check-in.
  3. Logs every cycle to ~/serenity-trader-stack/reports/<TICKER>/updates.md (git-committed); emails only on escalation — routine "still fine" cycles stay silent.
  4. Installed via cron: 0 */4 * * * ... crossvalidate_satellite.py.

This is the "hybrid" approach because the full ai-berkshire 4-master framework and Serenity's own six-step chokepoint analysis are each too expensive/interactive to run unattended every 4 hours — this script approximates both cheaply and only pays for a real Claude read when the local checks actually disagree or something looks wrong.

🔴 Rogue legacy-engine incident — recurred twice, root-caused and structurally fixed. The old always-on auto_trade_enabled=true engine sold live satellite positions twice without authorization (CRDO on 2026-07-01, VST on 2026-07-03), each time believed already stopped. Root causes, all now fixed:

  • stop.sh grepped for the uvicorn process on port 8000, but the server has always run on port 8888 — the pattern never matched anything, so stop.sh printed "successfully stopped" while the engine kept running the whole time. This is the most likely reason the same incident happened twice. (Fixed: pattern corrected to 8888; the health-check curl example above had the same stale port and is also fixed.)
  • backend/main.py has its own standalone if __name__ == "__main__" entrypoint that never checked the kill-switch — only start.sh did. (Fixed: same kill-switch check added there.)
  • A structural kill-switch file (/data/qbao775/AlphaTrader/.DISABLE_AUTOSTART) was added at the top of both entrypoints: while it exists, the engine refuses to start no matter how it's invoked (bash start.sh, python main.py, or systemd). It exits 0, not 1 — alphatrader.service runs with Restart=on-failure, so a non-zero exit would have made systemd tight-loop-restart start.sh every 5 seconds for as long as the switch was active.
  • Lesson recorded in the standing mandate: killing a process is not sufficient for a self-healing supervisor (start.sh's own while true loop, plus systemd, plus a shared server where anyone could re-run bash start.sh) — the fix has to be structural (a checked flag file), not just operational (killing PIDs).

news_watch.py fixes — a silent bug had it firing zero alerts for months: mcporter/node live in the base miniconda /bin, not on PATH inside the alphatrader conda env, so every Exa search silently failed with rc=127. Fixed by explicitly prepending the base conda bin/ to the subprocess PATH. Also added: keyword coverage for layoffs/tariffs/export-controls/M&A/model-releases (per the user's "track official announcements, not just headline sentiment" preference), and a local Ollama pre-screen (quick_chokepoint_take()) that scores each fresh headline as a real bottleneck / noise / too-early before it reaches an email alert.


🛑 What's new (2026-06-30) — Strategy pivot to passive-index core + on-demand AI research

After 6 months of live autonomous operation, the daily-driver model has been retired in favor of a passive-index core (70–80% SPY/VOO + HK 2800) + on-demand AI research via Claude Code skills.

Why the pivot:

  1. A live single-name SMIC bet (~$1,300 unrealized loss at the worst point) showed conviction-based satellite picks need stronger pre-trade discipline than the 24/7 auto-trade loop provided.
  2. For a personal portfolio of this size (~US$60k after a fresh NZ$100k deposit), keeping a fleet of background processes (Ollama GPU runner, IB Gateway, Moomoo OpenD, 21-task asyncio loop, cron jobs) running on a shared lab server is not a sustainable footprint. All AlphaTrader daemons have been shut down; the SQLite DB and code remain.
  3. Net of the SMIC drag, the existing Alpaca SPY/VOO core has tracked S&P 500 cleanly. The conclusion: index it, then be selective about the satellite ~20-30% rather than running a continuous decision engine.

The new path — serenity-trader-stack: a lightweight, on-demand stack that runs entirely inside Claude Code (Opus 4.8), with one install script and zero background processes.

~/.claude/{commands,skills}/         ← 18 ai-berkshire slash commands + 3 anthropic equity-research skills
~/serenity-trader-stack/
├── scripts/refresh-today.sh         # Anchor today's date (UTC/NZT/EDT/HKT) + market hours
├── scripts/snapshot-portfolio.sh    # Pull Alpaca + IBKR + Moomoo holdings → markdown snapshot
├── scripts/quote.sh <TICKER>        # Current price (US + HK) via market_data.get_stock_quote()
├── scripts/check-allocation.sh      # Actual vs target 70/20/8/2 allocation; warn if >5pp off
├── scripts/place-order.sh           # One-shot order placement (US auto via Alpaca, HK manual via App)
├── reports/                         # Git-versioned per-ticker thesis state (init'd by installer)
└── CLAUDE.md                        # 8 operating rules — sizing buckets, sourcing, falsifiable thesis

One-command install (idempotent, safe to re-run):

bash install-trader-stack.sh

This clones three external repos — xbtlin/ai-berkshire (Buffett/Munger/段永平/李录 multi-master value framework), muxuuu/serenity-skill (chokepoint scorecard JSON; the existing serenity-chokepoint-analysis Chinese skill is preserved), and anthropics/financial-services (idea-generation + thesis-tracker + market-researcher skills) — installs the markdown skills into ~/.claude/, writes the 5 helper scripts, sets up the git-versioned reports/ folder, and writes a project CLAUDE.md with the operating rules.

Daily use (no background daemons; everything is on-demand):

# Before any session — refresh date + portfolio snapshot
~/serenity-trader-stack/scripts/refresh-today.sh
~/serenity-trader-stack/scripts/snapshot-portfolio.sh   # IB Gateway / OpenD start on demand

# In Claude Code (Opus 4.8)
/portfolio-review                         # Re-evaluate current holdings against stored theses
/investment-team <ticker>                 # 4-master adversarial value research (Buffett/Munger/段/李)
/dyp-ask "<question>"                     # 段永平 persona
"用 Serenity 卡点分析 <theme>"            # Supply-chain chokepoint analysis (existing CN skill)
"Run an idea-generation screen for ..."   # Anthropic equity-research skill

What carries forward from the old system:

  • All broker integration in backend/futu_broker.py, backend/trading_engine.py, etc., is intact — scripts/place-order.sh wraps it for one-shot execution.
  • The bug-fix session that preceded the pivot landed: price_refresh 20-symbol starvation cap → 250; silent auto_trade failure logging at the call-site; dust-position filter for held-symbol scan front-loading; DCF poison-data gate tightened for non-US tickers (0.5×–2× sanity band); priority_symbols initialized before the try block so the gap-filter bypass never NameErrors.
  • The autonomous trading loop, dynamic watchlist, online RL pipeline, LLM shootout, regime-aware exposure engine, and cron-driven monitoring described below remain operational if re-started, but are not the recommended daily path.

The full Serenity supply-chain skill (serenity-chokepoint-analysis), the live tweet pipeline (fetch_serenity_tweets.sh), and the daily email reporting still work standalone if invoked manually.


What's new (June 2026)

  • 🛡️ No-margin lockdown (living-money safety): a critical bug had get_cash_balance() return Alpaca buying_power (4× margin) instead of real cash, letting the engine silently buy on margin. Fixed: real-cash only + a hard cash-reserve-floor guard at the single execute_buy() chokepoint (so deposit/rebalance paths can't bypass it) + the broker account is locked to max_margin_multiplier=1 + no_shorting=true — borrowing is now impossible at both the software and broker layer.
  • 📈 Adaptive exposure engine (market_regime.py): scores SPY trend / momentum / volatility / drawdown into RISK_ON / NEUTRAL / RISK_OFF and writes a dynamic cash_reserve_pct (20 / 40 / 65 %). "Earn more in good markets, lose less in bad" — the engine deploys more when healthy, defends when stressed. Daily pre-open cron, no restart needed.
  • 🐦 LIVE Serenity tweets via Agent Reach: the yan-labs archive froze at 2026-06-08; fetch_serenity_tweets.sh now pulls @aleabitoreddit's live timeline (burner account, never the main one) and merges it into the lens recency scoring, so his freshest picks (SIVE/AAOI/COHR …) drive the watchlist.
  • 🐳 Smart-money + influencer tracking (fetch_smart_money.sh): Buffett/Berkshire & Ackman 13F, Congressional/STOCK-Act trades (Pelosi, Trump), and Musk/Trump market-relevant X posts — a LAGGED cross-check only (never overrides Serenity, never auto-buys), surfaced in the daily email.
  • 📰 Proactive news alerts (news_watch.py): Exa-searches holdings + sectors (memory/HBM, CPO/optics) for material-risk headlines (plunge/downgrade/glut/halt …) and emails an alert — closes the "breaking-news blind spot".
  • 💰 Deposit auto-detect (deposit_watch.py): detects new cash deposits and lets the engine deploy them into Serenity names within the guardrails; emails on arrival.
  • 📧 Daily email upgrade: status banner shows leverage state, market regime + cash floor, and real cumulative return NET OF DEPOSITS broken down into unrealized + realized + today (deposits are never miscounted as gains).
  • 🔌 Real-time internet access (Agent Reach): Exa semantic search, RSS, web, GitHub, X — installed in an isolated agentreach conda env; powers the catalyst/news pipeline above.
  • 🧱 Cron-robustness: absolute SQLite DB path (was a relative ./ path that broke cron-run scripts) + rsync --delete excludes for locally-generated data files.

What's new (May 2026)

  • Hong Kong live trading via Moomoo NZ OpenD (FUTUAU entity). HK + US in one platform; separate daily emails.
  • P0 fix — Qwen3.5 reasoning-model JSON parser: previous extractor failed on Qwen3's free-text reasoning prefix, causing 73.9% of signals to come back as zero-conf HOLDs. Now < 1% parse-error rate via a robust extractor that handles <think> tags, "Thinking Process:" prefixes, multi-block JSON output, reasoning loops, and partial truncation.
  • Cross-stock catalyst engine: macro events (e.g. Trump's 2026 China visit with CEO delegation) automatically light up every materially-exposed ticker without hand-curating keyword lists per stock. Geopolitical RSS feeds (cached) feed directly into per-symbol catalyst detection.
  • backend/.env secret loading: SECRET_KEY no longer has a hardcoded fallback — must be supplied via gitignored .env file.
  • Scenario mute (DB column): user-flagged themes (e.g. Middle East/Iran in this account) are blocked from showing in reports AND from being regenerated by the AI Layer 4 scenario auto-generator.

Core Features

  • Real-time Market Data: Global market data via Yahoo Finance, auto-refreshing every 2 minutes with staggered requests to avoid rate limits.
  • K-Line Prediction: The Kronos foundation model (trained on data from 45+ exchanges) predicts the next 5 candles based on historical data.
  • AI Decision Making: Hybrid LLM (Qwen3.5-35B-A3B MoE for local, optional DeepSeek-Cloud API) synthesizes K-line predictions, technical indicators, news, catalysts, and social sentiment. Reasoning-model output is parsed via a robust extractor that handles <think> tags, free-text reasoning prefixes, and partial truncation.
  • Multi-Broker Automated Trading:
    • US equities via Alpaca Live API (notional/dollar orders, fractional shares).
    • Hong Kong equities via Moomoo OpenD (Moomoo NZ / FUTUAU entity, REAL or SIMULATE mode; supports odd-lot HK trading).
    • A-shares / Futu HK also supported via the same OpenD layer.
  • Cross-Stock Catalyst Engine: TRUMP_CHINA_BENEFICIARIES-style macro events automatically propagate to all materially-exposed tickers without per-symbol keyword duplication. Geopolitical RSS feeds (cached for 5 min) feed directly into per-symbol catalyst detection.
  • Linked Symbols: BABA → 9988.HK, BIDU → 9888.HK etc — earnings news on one listing surfaces as a catalyst alert on the cross-listed sibling.
  • Geopolitical Monitoring: Real-time tracking of 27 RSS feeds (White House, Reuters, BBC, Al Jazeera, CN financial, etc.) to auto-detect CRITICAL events.
  • Macro Scenario Lifecycle: DB-backed scenarios with ACTIVE/DECLINING/RESOLVED/EXPIRED states. AI Layer 4 auto-generates new scenarios from news. Per-scenario muted_by_user flag respects user preferences across restarts.
  • Two-Path RL Feedback Loop:
    • Path 1 (XGBoost) — short, fast: every 6 hours, train a candidate from rl_training_data.jsonl, A/B against current production by directional accuracy + RMSE, promote/shadow/reject.
    • Path 2 (Online LoRA fine-tune) — daily incremental: every day, rebuild training/rl_sft_dataset from the latest labeled signals and warm-start continue-training a QLoRA adapter on google/gemma-4-31B-it (the live brain — see "Model selection & online RL" below), validate vs holdout, and auto-promote into vLLM serving when it beats production.
  • Daily Email Reports: Separate emails for US (Alpaca, kitchen-sink) and HK (Moomoo, glance-friendly). Each summarizes account, positions, today's trades, top BUY/SELL signals.
  • Reply-to-Email AI: User can reply to the daily report; LLM parses and applies setting changes (auto-trade toggle, watchlist add/remove, confidence threshold).
  • JWT Multi-User: Secure authentication with isolated positions, settings, and trade records per user. SECRET_KEY MUST be supplied via backend/.env — no hardcoded fallback.

🧠 Model selection & online RL

How the live decision model is chosen (the shootout)

The live trading brain is not hand-picked — it wins an automated, backtested competition. backend/rl_llm_shootout.py:

  1. Discovers candidate local models across both Ollama daemons (system :11434 and the user-space :11435), e.g. gemma4:31b, deepseek-r1:32b, llama3:70b.
  2. Runs the exact production analyze_stock prompt for each candidate over a rolling 7-day holdout of already-reward-labeled signals.
  3. Scores each on directional accuracy + mean realised reward.
  4. If the winner beats the incumbent ollama_model by ≥ 5 percentage points, it auto-promotes (updates the ollama_model setting). A shootout report is written to rl_models/llm_shootout/.

Why gemma-4-31B-it (gemma4:31b) is live (promoted 2026-05-27): it won the shootout on rolling-holdout directional accuracy, beating deepseek-r1:32b (now the fallback) — while returning clean JSON on the production prompt and making sound calls (e.g. correctly holding parabolic names instead of chasing). It runs locally on Ollama :11435 (Q4 for fast inference) with full-precision HF weights available for fine-tuning.

Online RL — trains and serves the SAME model that trades

Earlier the LoRA pipeline fine-tuned Qwen3.5-35B while the live brain was gemma-4-31B — so RL never improved the model that actually traded. That mismatch is now closed: online RL targets google/gemma-4-31B-it, the live brain.

brain logs a signal on every watchlist name  ──►  reward_1d/3d/7d labeled after the fact
        (independent of whether a trade filled — paper forward-return reward)
                                   │
            daily cron rebuilds training/rl_sft_dataset from the latest labeled records
                                   │
        warm-start continue-train gemma-4-31B QLoRA adapter (attention-targeted, reward-weighted SFT)
                                   │
              validate vs holdout  ──►  decide_lora_promotion (≥5pp dir-acc AND reward↑)
                                   │ pass
        serve gemma-4-31B + adapter via vLLM (--enable-lora)  ──►  set `lora_inference_url`
                                   │
   deepseek_ai._call_ollama auto-routes live decisions to the vLLM adapter (no code change)
  • Daily incremental, not per-step. True per-step online RL on a 31B LLM is unstable; the practical form here is a daily warm-start continue-train on the newest labeled batch, mixed with historical replay (full rl_sft_dataset).
  • Validation gate prevents catastrophic forgetting. A new adapter only goes live if it beats the current production model on the holdout (rl_lora_validator.pydecide_lora_promotion). Otherwise it is shadowed/rejected.
  • Reward is forward price-return on signals, not realised account P&L (the account is small and trades rarely), so RL learns "which calls predicted good moves," not direct P&L. It is a drift-tracking refinement, not a profit switch.

📡 Data Sources and Acquisition Channels

SerenityAlphaTrader Pro utilizes multi-modal data inputs, continuously fetched in the background by automated daemon tasks:

  1. Market Data & Historical K-Lines
    • Channel: Yahoo Finance (yfinance Python library).
    • Content: Real-time global stock prices, historical OHLCV data (for Kronos model input), and dozens of auto-calculated technical indicators (MACD, RSI, etc.).
    • Mechanism: Auto-polled every 2 minutes with staggered requests to prevent API rate limiting.
  2. Stock-Specific News & Company Updates
    • Channel: Yahoo Finance News API and official AI company blog RSS feeds.
    • Content: Selected watchlist news summaries, major earnings releases, and industry trends.
    • Mechanism: Scanned automatically every 15 minutes.
  3. Retail Social Sentiment
    • Channel: StockTwits and Reddit (e.g., r/wallstreetbets, r/stocks).
    • Content: Extraction of retail discussion volume and bullish/bearish emotion tags.
    • Mechanism: Polled via API or specific web scraping every 30 minutes.
  4. Geopolitical & Macroeconomic Events (Core Feature)
    • Channel: 15 integrated top-tier global RSS feeds (White House, Reuters, BBC, Financial Times, etc.).
    • Content: Real-time capture of "CRITICAL" global macro events such as sudden wars, major sanctions, tariffs, or rate cuts.
    • Mechanism: High-frequency concurrent scanning every 10 minutes to trigger specific scenario playbooks and auto-execute trades on beneficiary assets.
  5. Real-World Trading Execution
    • Channel: Alpaca Live API.
    • Content: A commission-free, API-native broker acting as the system's "execution arm".
    • Mechanism: Executes millisecond-level live/paper trades, strictly using Notional (dollar-amount) orders for maximum reliability.
  6. Daily Trading Experience & Feedback Loop
    • Channel: Internal System Logs & Reinforcement Learning (RL) Data Collector.
    • Content: Extracted insights from daily profitable and losing trades, assessing why signals succeeded or failed.
    • Mechanism: Systematically archives execution records into rl_training_data.jsonl to form an ongoing feedback loop, fine-tuning future LLM trading logic.

System Architecture

Overview

graph TB
    subgraph DATA["📡 Information Layer"]
        YF["Yahoo Finance<br/>Quotes / K-lines / News"]
        RSS["15 RSS Feeds<br/>Reuters / BBC / White House"]
        SS["StockTwits / Reddit<br/>Retail Sentiment"]
        KRONOS["Kronos GPU Model<br/>K-line Prediction (next 5)"]
        QUANT["DCF / DDM Valuation<br/>Intrinsic Value"]
        GC["Global Context<br/>VIX / Indices / FX"]
        COT["CFTC COT<br/>Futures Positioning"]
    end

    subgraph SCENARIO["🌍 Macro Scenario Engine"]
        SCAN["Keyword Scanner<br/>Every 10 min"]
        AIREV["AI Review<br/>Every 6 hours"]
        DB_S[("scenario_states<br/>SQLite")]
        LIFE["ACTIVE → DECLINING → RESOLVED"]
    end

    subgraph AI["🧠 AI Brain Layer"]
        PROMPT["Super-Prompt Builder<br/>Quote + Technicals + Valuation + News<br/>+ Scenarios + Sentiment + Predictions + Lessons"]
        LLM["Ollama DRL70B<br/>/ DeepSeek-R1 API"]
        SIGNAL["JSON Signal Output<br/>BUY / SELL / HOLD<br/>confidence + target + stop_loss"]
    end

    subgraph FILTER["🛡️ Risk Control Layer"]
        F1["Gap Filter<br/>Skip BUY if +3% today"]
        F2["Bear Filter<br/>Skip BUY if SPY < MA20"]
        F3["Cooldown Filter<br/>No re-buy within 3d of stop-loss"]
        F4["Market Hours<br/>Skip if market closed"]
        F5["Kelly Sizing<br/>Half-Kelly × VIX scaling"]
    end

    subgraph EXEC["⚡ Execution Layer"]
        ENGINE["TradingEngine<br/>Auto broker routing"]
        ALP["Alpaca<br/>US Stocks"]
        FUTU["Futu<br/>CN / HK"]
        IBKR["IBKR<br/>Global"]
        PAPER["Paper<br/>Simulated"]
    end

    subgraph FB["🔄 Feedback Loop"]
        RL["RL Training Data<br/>232MB+ JSONL"]
        EMAIL["Daily Email Report<br/>P&L / Win Rate"]
        ARCHIVE["Signal Archive<br/>90-day compression"]
    end

    YF --> PROMPT
    RSS --> PROMPT
    RSS --> SCAN
    SS --> PROMPT
    KRONOS --> PROMPT
    QUANT --> PROMPT
    GC --> PROMPT
    COT --> PROMPT

    SCAN --> DB_S
    AIREV --> DB_S
    DB_S --> LIFE
    DB_S --> PROMPT

    PROMPT --> LLM
    LLM --> SIGNAL

    SIGNAL --> F1 --> F2 --> F3 --> F4 --> F5

    F5 --> ENGINE
    ENGINE --> ALP
    ENGINE --> FUTU
    ENGINE --> IBKR
    ENGINE --> PAPER

    ENGINE --> RL
    ENGINE --> EMAIL
    ENGINE --> ARCHIVE
    RL -.->|"Historical lessons<br/>fed back into prompt"| PROMPT
Loading

Trading Loop (Sequence)

sequenceDiagram
    participant Trader as ⏱️ auto_trade_loop
    participant MD as market_data.py
    participant NI as news_intelligence.py
    participant KR as Kronos (A100 GPU)
    participant AI as LLM (Qwen3.5 35B)
    participant FLT as Risk Filters
    participant ENG as TradingEngine
    participant DB as SQLite

    Trader->>Trader: Triggered every ~15-30 min
    loop For each symbol in watchlist
        par Gather data in parallel
            Trader->>MD: get_stock_quote + history + indicators + news
            Trader->>NI: scan_all_threats + detect_catalysts
            Trader->>KR: predict_next_candles (5 candles)
        end
        Trader->>Trader: Build super-prompt (all data merged)
        Trader->>AI: analyze_stock(prompt) with /no_think
        AI-->>Trader: signal / confidence / target / stop
        Trader->>DB: Store AI signal
        Trader->>FLT: Apply 5 filters
        alt All filters passed & confidence ≥ 75%
            FLT->>ENG: Execute trade
            ENG->>DB: Record trade + update position
            ENG-->>Trader: Broadcast via WebSocket
        else Filtered out
            FLT-->>Trader: Skip (log reason)
        end
    end
Loading

Macro Scenario Lifecycle

stateDiagram-v2
    [*] --> ACTIVE: Trigger keywords matched / AI creates new scenario
    ACTIVE --> ACTIVE: Evidence found (evidence_count + 1)
    ACTIVE --> DECLINING: 3h with no evidence OR resolution keywords ≥ 2
    DECLINING --> ACTIVE: New evidence appears (after 20 min cooldown)
    DECLINING --> RESOLVED: Resolution keywords ≥ 4 OR AI review confirms resolved
    DECLINING --> EXPIRED: 12h with zero evidence
    ACTIVE --> RESOLVED: Resolution keywords ≥ 4 OR AI review (every 6h)
    RESOLVED --> [*]
    EXPIRED --> [*]
Loading

Background Daemon Loops

graph LR
    subgraph CORE["Core trading & risk"]
        L1["🔴 auto_trade_loop<br/>⏱ ~15-30 min<br/>watchlist scan → AI → trade"]
        L2["🔴 stop_loss_monitor<br/>⏱ 15 sec<br/>Protect positions"]
        L3["🌍 global_market_scan<br/>⏱ 5 min<br/>VIX / cross-asset"]
    end
    subgraph INTEL["News & intelligence"]
        N1["📰 news_scan<br/>⏱ 10 min<br/>Breaking + scenarios"]
        N2["📅 event_scan<br/>⏱ 10 min<br/>Earnings / M&A"]
        N3["💬 social_sentiment<br/>⏱ 30 min<br/>StockTwits / Reddit"]
        N4["📝 blog_monitor<br/>⏱ 30 min<br/>AI lab blogs"]
        N5["🇭🇰 hk_ipo_scan<br/>⏱ 12 h<br/>New HK IPO watchlist add"]
    end
    subgraph EXEC["Execution & ops"]
        E1["⏳ pending_executor<br/>⏱ 5 min<br/>Deferred orders"]
        E2["🔁 dca_core_etf<br/>⏱ 1 h<br/>Re-buy SPY/QQQ to target"]
        E3["⚖ one_shot_rebalance<br/>⏱ Daily<br/>Drift control"]
        E4["💵 deposit_handler<br/>⏱ 5 min<br/>Detect & re-deploy fresh cash"]
    end
    subgraph RL["RL pipeline"]
        R1["🧠 rl_policy_trainer<br/>⏱ 6 h<br/>XGBoost retrain → A/B → promote"]
        R2["📊 kronos_gpu<br/>⏱ On-demand<br/>K-line prediction (A100)"]
    end
    subgraph COMM["Communication"]
        C1["📧 email_reporter<br/>⏱ 21:10 UTC<br/>2 emails: US + HK"]
        C2["📨 email_reply_checker<br/>⏱ IMAP IDLE<br/>Apply user commands via LLM"]
        C3["💼 annual_tax_report<br/>⏱ 31 Mar yearly<br/>NZ tax-year P&L"]
    end
Loading

Tech Stack

graph LR
    subgraph Backend
        FastAPI --> SQLAlchemy --> SQLite
    end
    subgraph AI_Models["AI Models"]
        Ollama["Ollama (DRL70B 70B)"]
        DeepSeek["DeepSeek-R1 API"]
        Kronos["Kronos (A100 GPU)"]
    end
    subgraph Brokers
        Alpaca
        Futu
        IBKR
    end
    subgraph Frontend
        direction TB
        SPA["HTML / JS / CSS"] --> WS["WebSocket"]
        WS --> TV["TradingView Charts"]
    end
    subgraph Infra["Infrastructure"]
        systemd --> HPC["University HPC Server"]
    end
Loading

Environment Requirements

Component Version Description
Python 3.10 (conda) alphatrader conda environment
CUDA 12.4+ A100 GPU for running Kronos
Ollama Any To run the DRL70B model
GPU A100 80GB × 1 Recommend GPU-7 (most idle)
SQLite Built-in No separate installation required

One-Time Installation (Initial Deployment)

1. Clone the Repository

git clone https://github.com/14H034160212/AlphaTrader.git
cd /data/qbao775/AlphaTrader

2. Create Conda Environment and Install Dependencies

conda create -n alphatrader python=3.10 -y

# Install PyTorch (CUDA 12.4)
/data/qbao775/miniconda3/envs/alphatrader/bin/pip install \
    torch==2.6.0 --index-url https://download.pytorch.org/whl/cu124

# Install all project dependencies
/data/qbao775/miniconda3/envs/alphatrader/bin/pip install \
    numpy pandas \
    fastapi "uvicorn[standard]" \
    sqlalchemy \
    pydantic \
    "python-jose[cryptography]" \
    bcrypt \
    python-multipart \
    requests \
    yfinance \
    ta \
    feedparser \
    "alpaca-trade-api" \
    "alpha_vantage==2.3.1" \
    transformers \
    huggingface_hub \
    accelerate \
    sentencepiece \
    einops \
    safetensors \
    tqdm

2b. (Optional) Real-time Intelligence via Agent Reach

Powers live Serenity tweets, Exa news search, and the smart-money / news / deposit watchers. Installed in its OWN isolated conda env (needs Python ≥ 3.10) so it never touches the trading env:

conda create -n agentreach python=3.11 -y
/data/qbao775/miniconda3/envs/agentreach/bin/pip install \
    "https://github.com/Panniantong/agent-reach/archive/main.zip"
/data/qbao775/miniconda3/envs/agentreach/bin/agent-reach install --env=auto          # zero-config channels
/data/qbao775/miniconda3/envs/agentreach/bin/agent-reach install --channels=twitter  # X channel tooling

# Exa global semantic search (needs node + mcporter, npm-global into miniconda)
npm install -g mcporter
mcporter config add exa https://mcp.exa.ai/mcp        # writes ./config/mcporter.json

# X / Twitter auth — use a BURNER account, never your main one (datacenter-IP
# scraping can get an account rate-limited/locked). Export cookies with the
# Cookie-Editor extension on x.com (Export → Header String), then:
#   agent-reach configure twitter-cookies "PASTED_STRING"
# and store the auth for cron (chmod 600), read by fetch_serenity_tweets.sh:
cat > ~/.agent-reach/twitter.env <<'EOF'
export TWITTER_AUTH_TOKEN="..."   # from the burner account's cookies
export TWITTER_CT0="..."
EOF
chmod 600 ~/.agent-reach/twitter.env

Cron jobs that drive the intelligence pipeline (all use absolute paths so they survive cron's minimal env):

*/30 * * * *        refresh_serenity_data.sh                 # yan-labs archive sync
23 */6 * * *        fetch_serenity_tweets.sh 25               # LIVE Serenity tweets
17 6 * * *          backend/refresh_serenity_intel.py         # semiconstocks focus
0 13 * * 1-5        backend/market_regime.py                  # adaptive cash floor (pre-open)
13 7 * * 1,4        fetch_smart_money.sh                      # 13F + congress + Musk/Trump
47 13,15,17,19 * * 1-5  backend/news_watch.py                 # breaking-news alerts (market hours)
*/30 * * * *        backend/deposit_watch.py                  # deposit auto-detect
33 21 * * 1-5       send_market_reports.sh                    # daily email (after US close)

3. Download Kronos Model Code

cd /data/qbao775/AlphaTrader/kronos_lib
git clone https://github.com/shiyu-coder/Kronos.git .

4. Download Kronos Model Weights (HuggingFace)

/data/qbao775/miniconda3/envs/alphatrader/bin/python3 -c "
from huggingface_hub import snapshot_download
snapshot_download(
    repo_id='NeoQuasar/Kronos-base',
    local_dir='/data/qbao775/AlphaTrader/kronos_lib/weights/Kronos-base',
    ignore_patterns=['*.bin']
)
snapshot_download(
    repo_id='NeoQuasar/Kronos-Tokenizer-base',
    local_dir='/data/qbao775/AlphaTrader/kronos_lib/weights/Kronos-Tokenizer-base'
)
print('Done')
"

5. Install Ollama and Pull DeepSeek-R1 70B

# Install Ollama (if not installed)
curl -fsSL https://ollama.com/install.sh | sh

# Pull DeepSeek-R1 70B (~42GB)
ollama pull DRL70B:latest

# Verify
ollama list
# Should display: DRL70B:latest   42.5GB

6. Create backend/.env for Secrets ⚠️ REQUIRED

The backend now refuses to start without SECRET_KEY. Generate a fresh 64-char hex and store it in backend/.env (gitignored). start.sh loads it automatically.

# Generate a random key (run on your local machine, NOT in chat):
python3 -c "import secrets; print(f'SECRET_KEY={secrets.token_hex(32)}')" > backend/.env
chmod 600 backend/.env   # important — file contains a credential

start.sh sources this file via set -a / set +a before launching uvicorn. If the file is missing or unreadable, the supervisor exits immediately with a fatal log line (don't run a JWT system with no signing key).

Other secrets (Alpaca API key/secret, DeepSeek API key, Gmail app password, Moomoo password MD5) live in the DB settings table, not in .env.

7. Configure systemd for Auto-Start

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/alphatrader.service << 'EOF'
[Unit]
Description=SerenityAlphaTrader Backend Service
After=network.target

[Service]
Type=simple
WorkingDirectory=/data/qbao775/AlphaTrader
ExecStart=/bin/bash /data/qbao775/AlphaTrader/start.sh
Restart=on-failure
RestartSec=5
StandardOutput=append:/tmp/alphatrader.log
StandardError=append:/tmp/alphatrader.log

[Install]
WantedBy=default.target
EOF

chmod 600 ~/.config/systemd/user/alphatrader.service
systemctl --user daemon-reload
systemctl --user enable alphatrader

Note: On shared servers where user@.service is in failed state (some NeSI-style HPC nodes), systemctl --user won't work. In that case run start.sh via setsid nohup bash start.sh </dev/null >>/tmp/alphatrader.log 2>&1 & from a login shell — start.sh's while true loop auto-restarts uvicorn on crash.

8. (Optional) Hong Kong Trading via Moomoo OpenD

For HK / A-share / multi-region trading, install Moomoo OpenD on the same host as the backend (or on any host SerenityAlphaTrader can reach on port 11111).

# Download OpenD Linux tarball from Moomoo's official site
# (region-gated, must use a logged-in Moomoo account)
mkdir -p ~/moomoo-opend && cd ~/moomoo-opend
# extract the tarball: tar -xzf moomoo_OpenD_*.tar.gz --strip-components=2

# Edit OpenD.xml — fill in your Moomoo UserID + 32-char MD5 of password
#   (generate MD5 locally: printf '你的密码' | md5sum | cut -d' ' -f1)
# Enable telnet (line ~40 of OpenD.xml) for first-time 2FA setup:
#   <telnet_ip>127.0.0.1</telnet_ip>
#   <telnet_port>22222</telnet_port>
chmod 600 OpenD.xml

# First launch will trigger SMS 2FA. Pipe code in via telnet:
nohup ./OpenD > opend.console.log 2>&1 &
# Then in another shell (or via Python socket), send to 127.0.0.1:22222:
#   input_phone_verify_code -code=NNNNNN

# Wire SerenityAlphaTrader to OpenD via the DB settings table:
#   futu_enabled=true
#   futu_host=127.0.0.1
#   futu_port=11111
#   futu_security_firm=FUTUAU       # for Moomoo NZ/AU. Use FUTUSECURITIES for Futu HK
#   futu_trade_env=REAL             # or SIMULATE for paper
#   futu_hk_acc_id=<your HK acc_id>  # required when futu_trade_env=REAL

OpenD must complete a one-time "API Questionnaire" inside the Moomoo phone app before it accepts any login. Without this, OpenD logs in successfully then exits with "regulatory requirements" error.

The Hong Kong daily P&L is sent as a separate email from the main US report (triggered at the same 21:10 UTC cadence).


Daily Start / Stop

Start Service

systemctl --user start alphatrader

Stop Service

systemctl --user stop alphatrader

Restart Service

systemctl --user restart alphatrader

Check Service Status

systemctl --user status alphatrader

View Real-Time Logs

tail -f /tmp/alphatrader.log

Verify Service Health

curl http://localhost:8888/api/health
# Returns: {"status":"ok","timestamp":"..."}

🔒 Kill-switch (safety standby)

If /data/qbao775/AlphaTrader/.DISABLE_AUTOSTART exists, both start.sh and backend/main.py's standalone entrypoint refuse to start (see "What's new (2026-07-03)" further down for why this exists). Delete it to restore normal operation:

rm /data/qbao775/AlphaTrader/.DISABLE_AUTOSTART
systemctl --user restart alphatrader

Initial Setup (Web UI)

Visit http://<Server IP>:8000 and go to the settings page:

Setting Recommended Value Description
AI Provider Local Ollama Use DRL70B (DeepSeek-R1 70B)
Alpaca API Key Your Key Live for real trades, Paper for testing
Alpaca Secret Key Your Secret Same as above
Alpaca Mode live / paper paper = simulated, live = real
Auto-Trading Enabled Auto-order when confidence ≥ 70%
Min Confidence 0.70 Minimum confidence threshold
Risk Per Trade 2.0% Max risk exposure per trade

Quick Configuration via API (CLI)

# Get token
TOKEN=$(curl -s http://localhost:8000/api/auth/auto-login | \
    python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

# Configure Alpaca for Live trading
curl -s -X POST http://localhost:8000/api/settings \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"key":"alpaca_api_key","value":"YOUR_KEY"}'

curl -s -X POST http://localhost:8000/api/settings \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"key":"alpaca_secret_key","value":"YOUR_SECRET"}'

curl -s -X POST http://localhost:8000/api/settings \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"key":"alpaca_paper_mode","value":"false"}'

# Enable auto-trading
curl -s -X POST http://localhost:8000/api/settings \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"key":"auto_trade_enabled","value":"true"}'

curl -s -X POST http://localhost:8000/api/settings \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"key":"ai_provider","value":"ollama"}'

Project Structure

SerenityAlphaTrader/
├── start.sh                    # Startup script (includes auto-restart daemon)
├── stop.sh                     # Stop script
├── rl_training_data.jsonl      # RL training data (appended per trade)
├── intelligence_attribution_report.json  # Signal attribution analysis report
│
├── backend/
│   ├── main.py                 # FastAPI app + background tasks
│   ├── auth.py                 # JWT authentication (bcrypt)
│   ├── database.py             # SQLAlchemy models + SQLite (incl. SignalArchive)
│   ├── trading_engine.py       # Trading engine (Alpaca Notional orders + short protection)
│   ├── market_data.py          # Market data + technical indicators
│   ├── deepseek_ai.py          # DeepSeek-R1 / Ollama AI analysis
│   ├── kronos_analysis.py      # Kronos K-line prediction (A100 GPU)
│   ├── news_intelligence.py    # News + macro scenario detection + geopolitical RSS
│   ├── social_sentiment.py     # StockTwits + Reddit sentiment scanning
│   ├── blog_monitor.py         # AI company blog RSS monitoring
│   ├── event_monitor.py        # Earnings / macro event calendar
│   ├── intelligence_feedback.py # RL signal feedback & reward calculation
│   ├── rl_data_collector.py    # RL training data collector
│   ├── quant_models.py         # Quantitative models (DCF/DDM/VPA)
│   ├── notifier.py             # Notifications
│   ├── trading_platform.db     # SQLite runtime database
│   └── requirements.txt        # Python dependencies (for reference, use conda env)
│
├── frontend/
│   ├── index.html              # SPA main page
│   ├── app.js                  # Frontend logic (market/trading/AI analysis)
│   └── styles.css              # Dark theme styles
│
└── kronos_lib/                 # Kronos model (cloned from git)
    ├── model/                  # Kronos code
    │   ├── __init__.py
    │   └── kronos.py           # KronosTokenizer, Kronos, KronosPredictor
    ├── prediction_results/     # Kronos prediction results (JSON, auto-gzipped >90 days)
    └── weights/
        ├── Kronos-base/        # Model weights (HuggingFace)
        └── Kronos-Tokenizer-base/  # Tokenizer weights

Data Storage

Data Location Description
Users/Positions/Trades/Signals backend/trading_platform.db SQLite, auto-created
Weekly Signal Archives signal_archives (Same DB) >90 days signals compressed into weekly summaries
Price Cache Memory Rebuilt ~2 mins after restart
Kronos Predictions kronos_lib/prediction_results/ JSON; compressed to gzip if >90 days old
RL Training Data rl_training_data.jsonl JSONL format, appended continuously
Signal Attribution Report intelligence_attribution_report.json Periodically updated
Service Logs /tmp/alphatrader.log Auto-rotated/gzipped if >200MB

Data Retention Policy (90 Days): Automated maintenance task runs daily at UTC 00:00:

  • AI Signals > 90 days → Aggregated into signal_archives by (user, stock, week) and deleted from original table.
  • Kronos JSON > 90 days → Gzipped, and JSON deleted.
  • Logs > 200MB → Keep last 500 lines as summary, gzip old logs, and truncate current file.

Background Tasks Overview

The following background loops run automatically once the service starts:

Task Frequency Description
background_price_refresh Every 2 mins Refreshes price cache; staggers requests to prevent rate limiting
background_auto_trade_loop Continuous Scans watchlist, triggers AI analysis, and auto-trades
background_news_scan Every 15 mins yfinance news + macro scenario detection
background_news_scan (Geopolitical Sub-task) Every 10 mins 15-feed RSS geopolitical scanning; auto-triggers AI for beneficiary stocks on CRITICAL events
background_event_scan Every 15 mins Competitive threats + catalyst identification
background_social_sentiment_scan Every 30 mins StockTwits/Reddit sentiment
background_blog_scan Every 15 mins AI company blog RSS
background_daily_summary Daily Generates daily summary reports
background_pending_trade_executor Every 1 min Executes pending limit/stop orders
_run_daily_maintenance Daily at UTC 00:00 Signal archival + Kronos gzip + log rotation

Geopolitical RSS Monitoring

The system monitors these 15 sources to detect CRITICAL macro events such as wars, sanctions, or tariffs in real-time:

Source Description
US White House whitehouse.gov official RSS
US Dept of State state.gov press releases
US Treasury treasury.gov announcements
Reuters Top news + World news
BBC BBC World news
Al Jazeera English RSS
The Guardian World edition
NPR International news
Financial Times World news
Associated Press Top headlines
Times of Israel Israel news
Jerusalem Post Israel news
OilPrice.com Oil market news

Built-in Macro Scenarios

Scenario Severity Level Beneficiary Assets Assets to Avoid
middle_east_war_2026 CRITICAL GLD, IAU, SLV, XOM, LMT, RTX, NOC TSLA, AMZN, AAPL, QQQ, TQQQ, SOXL
fed_rate_cut HIGH QQQ, ARKK, TSLA, NVDA, AMZN GLD (Partially)
tariff_war HIGH Domestic mfg, Agriculture Import/Export dependent stocks
recession_fears HIGH GLD, TLT Cyclical stocks

When a CRITICAL/HIGH scenario is detected, the system automatically triggers an AI analysis for the beneficiary stocks, and issues a buy order if the confidence is ≥ 70%.


Alpaca Order Mechanism

The system uses Notional (Dollar-Amount) Orders instead of quantity (qty) orders for the following reasons:

  • Alpaca limits the minimum fraction for qty orders, often causing small orders to be canceled.
  • Notional orders (e.g., notional=18.00) specify exact dollar amounts spent, providing much higher reliability.
  • Minimum order amount: $1.00

Short Protection Mechanism: Before selling, the system automatically verifies your position via the Alpaca API. If Alpaca shows no holding, the sell action is skipped, preventing accidental naked shorting leading to order rejections.


Troubleshooting

Service Fails to Start

# View detailed error logs
tail -50 /tmp/alphatrader.log

# Check port usage
ss -tlnp | grep 8000

# Manual startup test
cd /data/qbao775/AlphaTrader/backend
/data/qbao775/miniconda3/envs/alphatrader/bin/python3 -c "
import uvicorn
uvicorn.run('main:app', host='0.0.0.0', port=8000)
"

Kronos Fails to Load (CUDA OOM)

# Check GPU memory usage
nvidia-smi --query-gpu=index,memory.used,memory.free --format=csv

# Modify start.sh to select a more idle GPU
# E.g., Change CUDA_VISIBLE_DEVICES=7 to another free GPU index

Yahoo Finance Throttle (Too Many Requests)

The price refresh already operates with a 1.5s delay and 2-minute loop interval, usually avoiding throttling. If you still hit limits, temporarily increase the refresh interval in start.sh.

Alpaca Sell Rejected (not allowed to short)

The system includes short protection that auto-verifies your Alpaca holding before selling. If the error persists:

# Check if local portfolio syncs with Alpaca actual holding
curl -s http://localhost:8000/api/positions -H "Authorization: Bearer $TOKEN"

# Query actual position using Alpaca API
curl -s https://api.alpaca.markets/v2/positions \
    -H "APCA-API-KEY-ID: YOUR_KEY" \
    -H "APCA-API-SECRET-KEY: YOUR_SECRET"

Alpaca Buy Order Cancelled

The system uses notional orders, so normal purchases shouldn't be cancelled. If they are:

  • Ensure the account balance has enough cash (minimum $1).
  • Ensure the stock supports fractional trading (some OTC stocks might not).

Ollama Unresponsive

# Check Ollama processes
ps aux | grep ollama

# Verify model availability
curl http://localhost:11434/api/tags

# Restart Ollama
pkill ollama && ollama serve &

Disclaimer

This project is for educational and experimental purposes only. AI trading signals do NOT constitute investment advice, and the developers hold no liability for any trading losses. Please ensure you fully understand the associated risks and validate strategies in Paper Mode before performing live trading.

About

SerenityTrader Pro is an automated AI trading system with a Python/FastAPI backend, HTML/JS frontend, hybrid LLM stack, Kronos predictions, and live trading support for US and Hong Kong markets.

Resources

Stars

11 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages