Skip to content

ajfonthemove/hoverstock

Repository files navigation

HoverStock

A floating, always-on-top macOS stock ticker with a plugin architecture for custom indicators — in a single Swift file, no Xcode required.

What it does

  • Real-time data: Alpaca WebSocket streaming with REST polling and Yahoo Finance fallback
  • Plugin indicators: Add your own technical analysis via a simple Indicator protocol
  • 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

Requirements

  • macOS 13+
  • Swift (included with Xcode Command Line Tools: xcode-select --install)
  • Alpaca Markets API key (optional — falls back to Yahoo Finance)

Quick start

# 1. Compile
make build

# 2. Run (defaults to SPY)
./run.sh

# Track a different symbol
TICKER_SYMBOL=AAPL ./run.sh

# Run tests
make test

You can also click the ticker symbol in the UI to switch symbols at runtime.

Configuration

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.

Writing custom indicators

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
]

What's available in MarketSnapshot

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

IndicatorResult fields

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

Web dashboard

bun --hot ./index.ts    # http://localhost:3099

A separate, simpler ticker view using Yahoo Finance data.

Disclaimer

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.

License

MIT

About

A floating, always-on-top macOS stock ticker with ML-backed trading signals, technical analysis, and real-time streaming

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors