Skip to content

Nimblestorm/Precoggers

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Precoggers — Precognition Test App

Can you guess a symbol before it's generated? Precoggers runs a daily experiment: pick one of 20 icons for two independent targets (market and random), each with two guess windows (primary before midnight, secondary before 9:30 AM). After 4 PM the results are revealed and your hit rate is tracked against the 5% baseline you'd expect from pure chance.

"I built an app where I guess tomorrow's symbol before it's generated, and the actual symbol gets determined later either by the stock market or a random generator. Over time it tracks whether I'm beating the odds or just guessing like a normal human with an overconfident brain."


The 20 icons

Icon preview

circle · triangle · square · star · wave · spiral · heart · skull · tree · lightning · eye · key · sun · moon · mountain · feather · arrow · hourglass · crown · flame


How it works

Two modes

Mode How the target is picked
Market SHA-256 hash of {date}_{SPY closing price} → deterministic, verifiable
Random secrets.token_hex(16) seed → SHA-256 → icon index, seed published for verification

Two guess windows per mode

Guess type Deadline What it tests
Primary Midnight Pure precognition — result not yet determined
Secondary 9:30 AM Last chance before market opens

Four slots per day total: market-primary, market-secondary, random-primary, random-secondary.

Daily schedule (automated)

Time Event
00:00 Primary guesses lock
09:00 Reminder logged
09:30 Secondary guesses lock
16:05 SPY price fetched via yfinance; both results revealed

Quickstart

# 1. Install dependencies
cd backend
pip install -r requirements.txt

# 2. Initialize the database (safe to re-run — migrates existing data)
python init_db.py

# 3. Start the server
uvicorn main:app --host 0.0.0.0 --port 8000

# 4. Open the frontend
# Open frontend/index.html in a browser, or:
cd ../frontend && python -m http.server 8080

The backend runs on http://localhost:8000. The frontend expects it there and calls it directly.


File structure

Precoggers/
├── backend/
│   ├── main.py              # FastAPI app factory — mounts routers, starts scheduler
│   ├── db.py                # Database class + BinomialStats
│   ├── scheduler.py         # APScheduler — 4 daily jobs
│   ├── init_db.py           # DB init + migration (adds guess_type/locked to old DBs)
│   ├── requirements.txt
│   └── routes/
│       ├── guesses.py       # POST /guess/{mode}/{guess_type}, GET /today/guesses
│       ├── results.py       # POST /result/{market|random}, GET /today/results, GET /yesterday
│       ├── stats.py         # GET /stats/*, GET /stats/by-guess-type
│       └── history.py       # GET /history
│   └── tests/
│       ├── conftest.py      # Fixtures: test_db, client
│       ├── test_db.py
│       ├── test_guesses.py
│       ├── test_results.py
│       └── test_scheduler.py
├── frontend/
│   ├── index.html           # Structure only — no inline CSS or JS
│   ├── styles.css
│   ├── app.js               # SPA — dashboard, guess grids, results, stats, history
│   └── icons/               # 20 SVG files (circle, triangle, square, ...)
└── precoggers.db            # SQLite — created on first run

API reference

Guesses

POST /guess/{mode}/{guess_type}     mode: market|random  guess_type: primary|secondary
Body: { "image_id": 7 }

Response:
{
  "already_locked": false,
  "guess": { "id": 1, "target_date": "2026-06-13", "mode": "market",
             "guess_type": "primary", "image_id": 7, "image_name": "heart", "locked": 0 },
  "target_date": "2026-06-13"
}
GET /today/guesses
Response: { "target_date": "2026-06-13", "slots": {
    "market_primary": {...},  "market_secondary": null,
    "random_primary": {...},  "random_secondary": null } }

Results

POST /result/random                 Reveals today's random result (idempotent)
POST /result/market
Body: { "spy_close": 527.43 }       Manual override — scheduler handles this automatically

GET /today/results                  Results annotated with primary_guess + secondary_guess per result
GET /yesterday

Stats

GET /stats/binomial                 Overall z-score, p-value, confidence interval
GET /stats/by-guess-type            Accuracy breakdown: market_primary, market_secondary, ...
GET /stats/rolling?window_days=14   Per-day accuracy over recent window
GET /stats/expected-vs-actual?days=30
GET /history?days=60

Database schema

CREATE TABLE guesses (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    target_date DATE    NOT NULL,
    mode        TEXT    NOT NULL CHECK(mode IN ('market', 'random')),
    guess_type  TEXT    NOT NULL CHECK(guess_type IN ('primary', 'secondary')),
    image_id    INTEGER NOT NULL REFERENCES images(id),
    timestamp   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    locked      BOOLEAN NOT NULL DEFAULT 0,
    UNIQUE(target_date, mode, guess_type)
);

CREATE TABLE results (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    date        DATE    NOT NULL,
    mode        TEXT    NOT NULL CHECK(mode IN ('market', 'random')),
    seed_source TEXT    NOT NULL,   -- "SPY=527.43" or "secure_rng"
    hash        TEXT    NOT NULL UNIQUE,
    image_id    INTEGER NOT NULL REFERENCES images(id),
    timestamp   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(date, mode)
);

Existing databases with the old single-guess schema are automatically migrated by init_db.py (existing rows get guess_type = 'primary', locked = 0).


Statistics

The null hypothesis is 5% accuracy (1 in 20 icons). The app tracks:

  • Z-score — standard deviations above/below chance
  • P-value — probability of results this good occurring by luck
  • Wilson 95% CI — confidence interval on true hit rate
  • By-guess-type breakdown — primary vs secondary, market vs random independently

Rough significance thresholds:

Z-score Interpretation
< 1.645 Within random variation
~2σ Marginal (p ≈ 0.05)
~2.5σ Significant (p ≈ 0.01)
3σ+ Strong evidence

You need roughly 100–300 days of data for meaningful conclusions at 5% base rate.


Result verification

Both result types publish a seed and hash so the outcome can be independently verified:

Market: seed = "{date}_{spy_close:.2f}" → SHA-256 → byte[0] % 20 → icon index

Random: seed = secrets.token_hex(16) (published in seed_source) → SHA-256 → byte[0] % 20 → icon index. The hash column stores sha256(seed).hexdigest()[:16] so you can confirm the stored hash matches the published seed.


Running tests

cd backend
pytest tests/ -v

35 tests covering DB methods, all four routes, scheduler jobs, and SPY fetch behavior (closed market detection).

About

Daily precognition test — guess a symbol before it's generated, track your hit rate vs. chance

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors