A floating, always-on-top macOS stock ticker with a plugin architecture for custom indicators — in a single Swift file, no Xcode required.
- Real-time data: Alpaca WebSocket streaming with REST polling and Yahoo Finance fallback
- Plugin indicators: Add your own technical analysis via a simple
Indicatorprotocol - Built-in indicators: RSI (14-period), MACD (12/26/9), Volume ratio — functional out of the box
- Composite signal: Weighted aggregation of all indicator scores → BUY / SELL / NEUTRAL
- News headlines: Alpaca-sourced headlines displayed in the INTEL section
- Market context: SPY benchmark, short interest data, session phase detection
- Web dashboard: Lightweight Bun-based web UI on port 3099
- macOS 13+
- Swift (included with Xcode Command Line Tools:
xcode-select --install) - Alpaca Markets API key (optional — falls back to Yahoo Finance)
# 1. Compile
make build
# 2. Run (defaults to SPY)
./run.sh
# Track a different symbol
TICKER_SYMBOL=AAPL ./run.sh
# Run tests
make testYou can also click the ticker symbol in the UI to switch symbols at runtime.
All configuration is via environment variables:
| Variable | Required | Description |
|---|---|---|
TICKER_SYMBOL |
No | Stock symbol to track (default: SPY) |
ALPACA_KEY |
No | Alpaca API key ID. Without it, data comes from Yahoo Finance only. |
ALPACA_SECRET |
No | Alpaca API secret key |
Copy .env.example to .env and fill in your values, or export the env vars before running.
HoverStock uses a plugin architecture. Implement the Indicator protocol to add your own analysis:
struct BollingerIndicator: Indicator {
let id = "bollinger"
let name = "Bollinger Bands"
func evaluate(snapshot: MarketSnapshot) -> [IndicatorResult] {
let points = snapshot.points
guard points.count >= 20 else { return [] }
let window = Array(points.suffix(20))
let mean = window.reduce(0, +) / 20.0
let stdDev = sqrt(window.map { ($0 - mean) * ($0 - mean) }.reduce(0, +) / 20.0)
let upper = mean + 2 * stdDev
let lower = mean - 2 * stdDev
let position = (upper - lower) > 0
? (snapshot.price - lower) / (upper - lower) : 0.5
let score = position > 0.9 ? -0.5 : position < 0.1 ? 0.5 : 0
return [IndicatorResult(
name: "BB Position", section: .tech,
value: "\(Int(position * 100))%",
color: position > 0.9 ? .red : position < 0.1 ? .green : .gray,
score: score, weight: 1.0,
tooltip: "Position within Bollinger Bands. 0% = lower band, 100% = upper band."
)]
}
}Register it in AppDelegate.applicationDidFinishLaunching:
fetcher.indicators = [
RSIIndicator(),
MACDIndicator(),
VolumeIndicator(),
BollingerIndicator(), // your custom indicator
]| Field | Type | Description |
|---|---|---|
price |
Double |
Current price |
prevClose |
Double |
Previous day's close |
points |
[Double] |
Intraday 5-min close prices |
volumes |
[Double] |
Corresponding volumes |
highs / lows |
[Double] |
Bar highs and lows |
sessionPhase |
SessionPhase |
Current market session phase |
benchmark |
BenchmarkData |
SPY price and change |
news |
[NewsItem] |
Recent headlines |
shortInterest |
ShortInterestData |
Short interest metrics |
bidPrice / askPrice |
Double |
Current bid/ask |
| Field | Description |
|---|---|
name |
Display label |
section |
.tech, .risk, .intel, or .market |
value |
Formatted display string |
color |
Display color |
score |
-1.0 to +1.0, feeds into composite signal |
weight |
Importance multiplier (default 1.0) |
tooltip |
Hover help text |
bun --hot ./index.ts # http://localhost:3099A separate, simpler ticker view using Yahoo Finance data.
This software is for informational and educational purposes only. It is NOT investment advice.
The signals and indicators generated by this software are algorithmic outputs based on market data and heuristics. They do not constitute recommendations to buy, sell, or hold any security.
- Past performance does not guarantee future results
- Real-time data may be delayed, incomplete, or incorrect
- No warranty is made regarding the accuracy or reliability of any output
You are solely responsible for your own investment decisions. The authors and contributors accept no liability for financial losses incurred through use of this software.