price-alerts

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Price Alerts (US markets)

价格提醒(美国市场)

Evaluates alert rules from the watchlist (see
watchlist-manager
) against fresh quotes and reports only new alerts. Not financial advice. Never place, modify or cancel orders - even if an alert fires, even if a broker tool is connected, unless the user explicitly confirms that specific order in this conversation.
scripts/
ships next to this SKILL.md (copied by
npx skills add
). Run from this skill folder, or from a git clone of the repo (root
scripts/
is the same files).
根据自选股列表(参见
watchlist-manager
)中的提醒规则对照最新行情进行评估,并且仅报告新增提醒。 不构成投资建议。绝不下单、修改或取消订单——即使提醒触发,即使连接了券商工具,除非用户在本次对话中明确确认该具体订单。
scripts/
位于本
SKILL.md
同级目录(由
npx skills add
复制)。请在该 skill 目录中运行,或从该仓库的 git clone 中运行(根目录下的
scripts/
包含相同的文件)。

Run it

运行方式

bash
python3 scripts/watchlist.py init                                                         # copy examples/watchlist.json if missing
python3 scripts/quickstart.py                                                             # offline fixture demo (labeled, not live)
python3 scripts/alerts.py --watchlist watchlist.json --state .alert_state.json           # text output
python3 scripts/alerts.py --format json                                                    # machine-readable
python3 scripts/alerts.py --force-session                                                  # evaluate on weekends / holidays too
python3 scripts/alerts.py --dry-run                                                        # don't update cooldown state
python3 scripts/alerts.py --notify                                                         # also deliver via WATCHLIST_NOTIFY sinks
python3 scripts/market_calendar.py                                                         # current ET session
Output:
ALERT <message>
lines, or
no new alerts
, or
market closed, showing last regular close
after the bell (last regular print; no
--force-session
needed). Weekends and full-day holidays stay silent (
market closed (weekend|holiday). Next session YYYY-MM-DD
) unless
--force-session
. Data errors go to stderr as
WARN
(including
earnings_error
/
iv_error
).
NOTIFY <sink>
confirms delivery; sink failures are
WARN notify …
and must not abort the check. Never treat a notify sink as a broker.
bash
python3 scripts/watchlist.py init                                                         # 如果缺失,则复制 examples/watchlist.json
python3 scripts/quickstart.py                                                             # 离线 fixture 演示(已标记,非实时行情)
python3 scripts/alerts.py --watchlist watchlist.json --state .alert_state.json           # 文本输出
python3 scripts/alerts.py --format json                                                    # 机器可读格式
python3 scripts/alerts.py --force-session                                                  # 在周末/节假日也进行评估
python3 scripts/alerts.py --dry-run                                                        # 不更新冷却状态
python3 scripts/alerts.py --notify                                                         # 同时通过 WATCHLIST_NOTIFY 接收端投递
python3 scripts/market_calendar.py                                                         # 当前 ET 交易时段
输出为
ALERT <message>
行,或
no new alerts
,收盘后则为
market closed, showing last regular close
(使用最近一次常规时段收盘价;无需
--force-session
)。周末和全日节假日会保持静默(
market closed (weekend|holiday). Next session YYYY-MM-DD
),除非使用
--force-session
。数据错误通过 stderr 输出为
WARN
(包括
earnings_error
/
iv_error
)。
NOTIFY <sink>
表示投递成功;接收端失败会显示为
WARN notify …
,且不得中止检查。绝不能将通知接收端视为券商。

Alert types

提醒类型

typevaluefires whenkind
price_above
/
price_below
pricelast >= / <= valuelevel
stop_hit
price (default: ticker
stop
)
long: last <= stop; short: last >= stoplevel (implicit if
stop
set)
target_hit
-last crosses any
targets
entry
level (implicit if
targets
set)
pct_change_up
/
pct_change_down
/
pct_move
%last vs prior close (after hours: last regular close). A recovered session low does not firedaily
gap_up
/
gap_down
% (default 2)open vs prior closedaily
new_52w_high
/
new_52w_low
-last beyond prior 252-session rangedaily
near_52w_high
/
near_52w_low
% (default settings.near_52w_pct)within value% of 52w extremedaily-ish (level latch)
golden_cross
/
death_cross
fast
,
slow
(50/200)
SMA fast crosses slow on latest bardaily
cross_above_ma
/
cross_below_ma
MA length (default 50)last close crosses its SMAdaily
rsi_above
/
rsi_below
RSI level; optional
period
(14)
Wilder RSI on daily closeslevel
iv_above
/
iv_below
IV percentunofficial Yahoo ATM IV (nearest expiry); skip if missing/0level
volume_spike
multiple (default 2.0)today's volume >= value x 20-day avgdaily
earnings_within
days (default 3)next earnings date within N daysdaily
intraday_range_pct
%
(day_high-day_low)/prev_close
; skip if high/low missing
daily
intraday_low_pct
/
intraday_high_pct
%opt-in session low/high vs prior close. Catches a −3% low that recovered into the closedaily
intraday_extreme_pct
%alias: expands to both
intraday_low_pct
and
intraday_high_pct
daily
Any rule may set
cooldown_minutes
to override
settings.cooldown_minutes
.
Default % checks use last print vs prior close (
pct_change_*
/
pct_move
). They do not look at the session high/low. If the user says “alert me if it drops 3% today” and they mean the print that traded through 3% even if it bounced, add
intraday_low_pct
(or
intraday_extreme_pct
). Do not add those unless they ask — they are opt-in.
类型值触发条件类别
price_above
/
price_below
价格最新价 >= / <= 设定值阈值类
stop_hit
价格(默认取 ticker 的
stop
)
多头:最新价 <= 止损价;空头:最新价 >= 止损价阈值类(设置
stop
后隐式生效)
target_hit
—最新价穿越任一
targets
条目
阈值类(设置
targets
后隐式生效)
pct_change_up
/
pct_change_down
/
pct_move
%最新成交价与前收盘价相比(盘后:最近一次常规时段收盘价)。即使当日低点已经回升,也不会触发每日类
gap_up
/
gap_down
%(默认 2)开盘价与前收盘价相比每日类
new_52w_high
/
new_52w_low
—最新价突破此前 252 个交易时段的价格区间每日类
near_52w_high
/
near_52w_low
%(默认
settings.near_52w_pct
)
距离 52 周极值在设定值%以内近似每日(阈值锁存)
golden_cross
/
death_cross
fast
、
slow
(50/200)
快速 SMA 在最新 K 线上穿/下穿慢速 SMA每日类
cross_above_ma
/
cross_below_ma
MA 长度(默认 50)最新收盘价上穿/下穿其 SMA每日类
rsi_above
/
rsi_below
RSI 水平;可选
period
(14)
基于每日收盘价计算 Wilder RSI阈值类
iv_above
/
iv_below
IV 百分比非官方 Yahoo ATM IV(最近到期日);缺失或为 0 时跳过阈值类
volume_spike
倍数(默认 2.0)当日成交量 >= 设定值 x 20 日均量每日类
earnings_within
天数(默认 3)下一次财报日期在 N 天内每日类
intraday_range_pct
%
(day_high-day_low)/prev_close
;最高价/最低价缺失时跳过
每日类
intraday_low_pct
/
intraday_high_pct
%需显式启用的当日低点/高点与前收盘价比较。可捕捉盘中一度触及 −3% 后回升至收盘的情况每日类
intraday_extreme_pct
%别名:展开为
intraday_low_pct
和
intraday_high_pct
每日类
任何规则都可设置
cooldown_minutes
,以覆盖
settings.cooldown_minutes
。
默认百分比检查使用最新成交价与前收盘价比较(
pct_change_*
/
pct_move
),不会查看当日最高价/最低价。如果用户说“今天跌 3% 时提醒我”,其意思是即使价格曾穿过 −3% 后又反弹,也要基于当时的成交价触发,请添加
intraday_low_pct
(或
intraday_extreme_pct
)。除非用户明确要求,否则不要添加;这些检查必须显式启用。

Anti-spam rules (implemented in
scripts/alerts.py
, state in
.alert_state.json
)

防垃圾提醒规则(已在
scripts/alerts.py
中实现,状态保存在
.alert_state.json
)

  • Level alerts latch: once fired they stay silent until price moves back through the level by
    rearm_pct
    (default 0.5%). A stock hovering at $240 never pings repeatedly.
    iv_*
    rearms when ATM IV no longer breaches the threshold.
  • Daily-event alerts fire at most once per trading day per ticker/type.
  • Cooldown (
    cooldown_minutes
    , default 240) applies to every re-fire.
  • Cap of
    max_alerts_per_run
    (default 20). Alerts past the cap are not written to state, so they can fire on the next run. If many fire, summarize ("7 alerts, 4 on TSLA") rather than dumping walls of text.
  • If the state file is missing or corrupt, start fresh but warn the user that duplicates are possible on this run.
  • Each
    targets[]
    level is its own latched
    target_hit
    (T1 firing does not hide T2).
  • 阈值类提醒会锁存:触发后会保持静默,直到价格回穿该价位并达到
    rearm_pct
    (默认 0.5%)才会重新触发。一直在 $240 附近波动的股票不会反复提醒。
    iv_*
    在 ATM IV 不再突破阈值时重新武装。
  • 每日事件类提醒每个交易日、每个 ticker/类型最多触发一次。
  • 冷却时间(
    cooldown_minutes
    ,默认 240)适用于每次重新触发。
  • 每次运行最多触发
    max_alerts_per_run
    (默认 20)条提醒。超过上限的提醒不会写入状态,因此可以在下次运行时触发。如果大量提醒同时触发,应进行汇总(例如“7 条提醒,其中 4 条与 TSLA 有关”),而不是输出大量文本。
  • 如果状态文件缺失或损坏,则重新开始,但应警告用户本次运行可能出现重复提醒。
  • 每个
    targets[]
    价位都是独立的锁存式
    target_hit
    (T1 触发不会掩盖 T2)。

Market hours (America/New_York, handled by
scripts/market_calendar.py
)

交易时段(America/New_York,由
scripts/market_calendar.py
处理)

  • Pre-market 04:00-09:30, regular 09:30-16:00, after-hours 16:00-20:00 ET; early-close days (day after Thanksgiving, Christmas Eve, July 3 when a weekday) close 13:00 with after-hours to 17:00.
  • NYSE holidays: New Year's (not observed when Saturday), MLK, Presidents', Good Friday, Memorial, Juneteenth, Independence, Labor, Thanksgiving, Christmas (Sat -> Fri, Sun -> Mon). Unscheduled closures: bundled
    data/holidays_overrides.json
    ,
    NYSE_EXTRA_CLOSURES
    /
    settings.extra_closures
    , and (with Alpaca keys) weekdays missing from the official calendar. Mention it if quotes look stale on a weekday the calendar thinks is open.
  • settings.sessions
    controls when extended-hours quotes are treated as live. Default
    ["regular"]
    . After the bell (or pre-open / overnight) on a trading day, the script still evaluates the last regular close and labels
    last_close
    — you do not need
    --force-session
    . Add
    "pre"
    /
    "after"
    only if you want to treat extended-hours prints as the live session. Those quotes are thinner and free sources may lag.
  • Always state times in ET (add the user's local time if known, e.g. "10:05 ET / 9:05 CT").
  • 盘前交易 04:00-09:30,常规交易 09:30-16:00,盘后交易 16:00-20:00 ET;提前收盘日(感恩节次日、平安夜、7 月 3 日且为工作日时)在 13:00 收盘,盘后交易持续到 17:00。
  • NYSE 节假日:元旦(逢周六不观察)、MLK、总统日、耶稣受难日、阵亡将士纪念日、六月节、独立日、劳工节、感恩节、圣诞节(周六 -> 周五,周日 -> 周一)。非计划休市:内置
    data/holidays_overrides.json
    、
    NYSE_EXTRA_CLOSURES
    /
    settings.extra_closures
    ,以及配置 Alpaca 密钥后对官方日历中缺失交易日的补充。如果日历认定某工作日开市,但行情看起来已过期,应说明这一点。
  • settings.sessions
    控制何时将延长交易时段行情视为实时行情。默认为
    ["regular"]
    。在交易日收盘后(或开盘前/隔夜期间),脚本仍会使用最近一次常规时段收盘价进行评估,并将其标记为
    last_close
    ——无需
    --force-session
    。仅当希望将盘前/盘后成交视为当前交易时段时,才添加
    "pre"
    /
    "after"
    。这类行情流动性较低,免费数据源可能存在延迟。
  • 始终使用 ET 标注时间(如果已知用户所在时区,也应添加本地时间,例如“10:05 ET / 9:05 CT”)。

Data sources (
scripts/quotes.py
, auto-fallback in this order)

数据源(
scripts/quotes.py
,按以下顺序自动回退)

  1. --fixture
    path, if given (tests/demos only).
  2. Alpaca snapshot + daily bars, if
    ALPACA_API_KEY_ID
    and
    ALPACA_API_SECRET_KEY
    are set (official US feed).
  3. yfinance
    if installed (
    pip install yfinance
    ).
  4. Yahoo public chart API (stdlib, unofficial, best-effort):
    query1.finance.yahoo.com
    , then
    query2
    .
    prev_close
    is
    previousClose
    or the prior aligned daily bar — after ~20:00 ET a today-row with
    close: None
    is dropped, not treated as yesterday.
  5. Finnhub quote + candles, if
    FINNHUB_API_KEY
    is set.
  6. Alpha Vantage daily, if
    ALPHAVANTAGE_API_KEY
    is set.
Force one with
--provider
or
WATCHLIST_PROVIDER
. HTTP 429/5xx are retried; failures are tagged
QuoteError
s (provider, HTTP status, hint). Free data can be delayed ~15 min; say so when precision matters.
Earnings dates are filled after the quote, first hit: existing field (yfinance/fixture) → Yahoo
calendarEvents
(cookie + crumb) → Yahoo quote HTML → Nasdaq analyst
earnings-date
(free, no key) → Finnhub / Alpha Vantage if keyed.
earnings_source
says which layer won; if none do,
earnings_error
prints a WARN.
Stale quotes:
--stale-after
/
WATCHLIST_STALE_AFTER
/
settings.stale_after_seconds
(default 900). During the regular session, warn if
as_of
is older than that.
0
disables.
ATM IV: only fetched for tickers with
iv_above
/
iv_below
. Unofficial Yahoo options chain (same crumb), then yfinance if installed. Nearest expiration, ATM call/put average as percent. Not IV rank. Failures set
iv_error
and print a WARN.
python3 scripts/quotes.py AAPL --iv
to inspect.
Notify (optional):
WATCHLIST_NOTIFY=ntfy,slack,webhook,desktop,file
and/or
--notify
. See README for env vars. Do not notify on empty/skipped/dry-run. Delivery errors stay warnings.
Known limits: unscheduled closures live in
data/holidays_overrides.json
(incomplete) plus env/settings plus an optional Alpaca official calendar overlay (day-cached). Yahoo endpoints are unofficial. See
docs/LIMITATIONS.md
.
MCP option: if an
alpaca
MCP server (alpacahq/alpaca-mcp-server) or
tradingview
MCP (atilaahmettaner/tradingview-mcp) is connected, you may use it for quotes/indicators instead of the scripts, then apply the exact same rules and anti-spam logic (read/write
.alert_state.json
in the same format). Use broker MCPs for read-only calls only.
  1. 如果提供了
    --fixture
    路径,则使用该路径(仅用于测试/演示)。
  2. 如果同时设置
    ALPACA_API_KEY_ID
    和
    ALPACA_API_SECRET_KEY
    ,则使用 Alpaca snapshot 和日线数据(美国官方行情源)。
  3. 如果已安装
    yfinance
    ,则使用
    yfinance
    (
    pip install yfinance
    )。
  4. Yahoo 公共图表 API(仅使用标准库,非官方,尽力而为):先访问
    query1.finance.yahoo.com
    ,然后访问
    query2
    。
    prev_close
    取
    previousClose
    或按日期对齐的上一根日线;在 ET 时间约 20:00 之后,如果今日行包含
    close: None
    ,则将其丢弃,而不是视为昨日数据。
  5. 如果设置了
    FINNHUB_API_KEY
    ,则使用 Finnhub 报价和 K 线数据。
  6. 如果设置了
    ALPHAVANTAGE_API_KEY
    ,则使用 Alpha Vantage 日线数据。
使用
--provider
或
WATCHLIST_PROVIDER
可强制指定某个数据源。HTTP 429/5xx 会重试;失败会标记为
QuoteError
(数据源、HTTP 状态、提示)。免费数据可能延迟约 15 分钟;对精度有要求时应说明这一点。
财报日期在获取行情后填充,按以下顺序采用第一个可用来源:现有字段(yfinance/fixture)→ Yahoo
calendarEvents
(cookie + crumb)→ Yahoo 报价 HTML → Nasdaq 分析师
earnings-date
(免费、无需密钥)→ 已配置密钥时使用 Finnhub / Alpha Vantage。
earnings_source
表明最终采用的数据层;如果全部失败,
earnings_error
会输出 WARN。
**过期行情:**可通过
--stale-after
/
WATCHLIST_STALE_AFTER
/
settings.stale_after_seconds
配置(默认 900)。常规交易时段内,如果
as_of
早于该时间,则发出警告。
0
表示禁用。
**ATM IV:**仅为配置了
iv_above
/
iv_below
的 ticker 获取。使用非官方 Yahoo 期权链(同一 crumb),然后回退到已安装的 yfinance。选择最近到期日,以 ATM call/put 的平均值表示百分比。不是 IV rank。失败时设置
iv_error
并输出 WARN。可通过
python3 scripts/quotes.py AAPL --iv
检查。
**通知(可选):**可通过
WATCHLIST_NOTIFY=ntfy,slack,webhook,desktop,file
和/或
--notify
启用。环境变量参见 README。没有提醒、提醒被跳过或处于 dry-run 状态时不得发送通知。投递错误仅作为警告处理。
**已知限制:**非计划休市信息来自
data/holidays_overrides.json
(并不完整)、环境变量/设置以及可选的 Alpaca 官方日历叠加层(按日缓存)。Yahoo 端点均为非官方接口。参见
docs/LIMITATIONS.md
。
MCP 选项:如果连接了
alpaca
MCP 服务器(alpacahq/alpaca-mcp-server)或
tradingview
MCP(atilaahmettaner/tradingview-mcp),可以使用它们获取行情/指标来代替脚本,然后应用完全相同的规则和防垃圾提醒逻辑(以相同格式读写
.alert_state.json
)。broker MCP 仅可用于
只读
调用。

Reporting format

报告格式

🔔 3 new alerts (10:05 ET, regular session, data: yahoo, ~15m delayed)
- AAPL $241.50 is above $240.00  (thesis: services margin; stop $210, T1 $250)
- TSLA down -6.0% today, gapped down -5.0%, volume 3.0x avg
- TSLA reports earnings in 1 day (2026-10-16)
Group by ticker, include the stored thesis/stop/target for context, no recommendations. If no alerts: one short line, or stay silent when running on a heartbeat (see
HEARTBEAT.md
).
🔔 3 条新提醒(10:05 ET,常规交易时段,数据源:yahoo,约延迟 15 分钟)
- AAPL $241.50 已高于 $240.00(投资逻辑:服务业务利润率;止损 $210,T1 $250)
- TSLA 今天下跌 -6.0%,向下跳空 -5.0%,成交量为均值的 3.0 倍
- TSLA 将在 1 天后发布财报(2026-10-16)
按 ticker 分组,附上已存储的投资逻辑、止损和目标价以便理解上下文,不要给出建议。如果没有提醒:输出一行简短信息;在运行心跳检查时则保持静默(参见
HEARTBEAT.md
)。

Creating alerts from chat

从对话中创建提醒

"Alert me if AAPL drops below 200" ->
python scripts/watchlist.py update AAPL --alert price_below:200 --append
(add the ticker first if missing). Confirm the rule back in plain English.
“如果 AAPL 跌到 200 美元以下就提醒我” ->
python scripts/watchlist.py update AAPL --alert price_below:200 --append
(如果列表中还没有该 ticker,请先添加)。用简单直白的话向用户复述规则并确认。