🌡️ Temperature Gauge — Code Mirror

φ-Harmonic Market Analysis · Repo: Chaos2Cured/temperature-gauge · Last updated: v1.0 (May 2026)

What this is: A standalone Python/Flask app that computes a phi-harmonic confluence score (the Temperature) from market data and converts it into actionable buy/sell signals. It is separate from FreeLattice but designed to eventually integrate as a module. No API key required — uses yfinance.

Repository Structure

FileLinesPurpose
app.py1,142Flask server, data fetching, temperature computation, routes
signal_engine.py488Buy/sell signal logic, risk management, multi-timeframe aggregation
static/index.html~800Frontend — TradingView Lightweight Charts, arc gauge, signal display
data/societal_cache.jsonCached societal temperature readings
data/societal_history.jsonHistorical societal temperature log
requirements.txt7flask, flask-cors, pandas, ta, yfinance, requests

φ Constants (shared across both files)

PHI     = 1.6180339887   # Golden ratio
PHI_INV = 0.6180339887   # φ⁻¹
PHI_SQ  = 2.6180339887   # φ²
D       = 4.326          # Dimensional constant (φ² + φ⁻¹ × 2)

app.py — Temperature Computation

MA Periods and Weights

MA_PERIODS = [6, 8, 12, 50, 200]
MA_WEIGHTS = {6: PHI_INV**4, 8: PHI_INV**3, 12: PHI_INV**2, 50: PHI_INV**1, 200: PHI_INV**0}

The 200 EMA is the gravity spine (weight 1.0). Shorter EMAs are weighted by descending powers of φ⁻¹.

compute_temperature(df, indicators) → pd.Series

The core function. Computes a 0–100 confluence score for every candle in the dataframe.

ComponentWeightLogic
ma_alignmentφ⁰ = 1.000Are shorter EMAs above longer EMAs? (phi-weighted sum)
rsiφ⁻¹ = 0.618100*(r-30)/35 for 30≤r≤65; 100*(100-r)/35 for 65<r≤100; 0 otherwise
macdφ⁻² = 0.382(macd_above_signal × 0.618 + histogram_rising × 0.382) × 100
volumeφ⁻³ = 0.236((vol/vol_sma20 − 1).clip(−1,2) / 2 × 100 + 50).clip(0,100)
gravityφ⁻¹ = 0.618Proximity to phi-harmonic Fibonacci extension levels (0–1 → 0–100)
bollingerφ⁻³ = 0.236Position within Bollinger bands; optimal zone 0.4–0.7 = 100

compute_gravity_points(df, indicators) → pd.Series

Computes phi-harmonic Fibonacci extension levels from rolling 50-period swing highs and lows. Retracement levels: 0.236, 0.382, 0.500, 0.618, 0.786. Extension levels: φ⁻¹, φ⁻². Returns a proximity score (0–1) for each candle.

compute_indicators(df) → dict

Computes all technical indicators using the ta library: EMA 6/8/12/50/200, RSI(14), MACD(12,26,9), Bollinger(20,2σ), Volume SMA(20), gravity points.

Societal Thermometer

Seven dimensions, each with a phi-harmonic weight:

DimensionWeightData Source
economic_frustrationφ⁰ = 1.000FRED consumer sentiment
political_tensionφ⁻¹ = 0.618GDELT news negativity
ai_jobs_anxietyφ⁻¹ = 0.618Google Trends (automation, job displacement)
personal_wellbeingφ⁻² = 0.382Reddit sentiment (r/mentalhealth, r/happy)
cultural_moodφ⁻² = 0.382Google Trends (art, music genre shifts)
financial_fearφ⁻³ = 0.236VIX, put/call ratio
hope_signalφ⁻³ = 0.236Google Trends (new business, innovation)

API Routes

RouteReturns
GET /api/chart/<symbol>Candlestick data + temperature series + gravity points + indicators
GET /api/signal/<symbol>Full signal with risk management (calls signal_engine)
GET /api/societalCurrent societal temperature (7 dimensions + composite)
GET /api/societal/historyHistorical societal temperature log
GET /api/resonanceMarket + societal resonance combined score
GET /api/search/<query>Symbol search via yfinance
GET /api/phiφ constants and threshold documentation

signal_engine.py — Buy/Sell Decision Logic

Signal Thresholds (phi-harmonic)

STRONG_BUY_THRESHOLD  = 61.8   # φ⁻¹ × 100
BUY_THRESHOLD         = 55.0   # Mid-zone entry
NEUTRAL_HIGH          = 55.0
NEUTRAL_LOW           = 38.2   # φ⁻² × 100
SELL_THRESHOLD        = 38.2
STRONG_SELL_THRESHOLD = 23.6   # φ⁻³ × 100

compute_signal(temperature, components, prev_temperature=None) → dict

The main entry point. Takes the current temperature reading and component scores, returns a full signal dict.

Step 1 — Base signal from temperature vs thresholds above.

Step 2 — Confidence from count of confirming components (≥60 = bullish, ≤40 = bearish):

Confirming componentsConfidenceConfidence %
5very_high95%
4high80%
3moderate65%
2low45%
1very_low25%

Step 3 — Momentum from delta vs prev_temperature: accelerating_up (Δ>5), rising (Δ>2), falling (Δ<-2), accelerating_down (Δ<-5), flat.

Step 4 — Reasoning — plain-English sentences for each component.

Step 5 — Risk parameters (calls compute_risk_parameters).

Step 6 — Phi timing (calls compute_phi_timing).

Returns: { signal, emoji, color, temperature, confidence, confidence_pct, momentum, momentum_strength, components, bullish_count, bearish_count, reasons, risk, timing, timestamp, phi_note }

compute_risk_parameters(temperature, components, momentum) → dict

TemperatureSuggested position size
≥ 61.8 (STRONG_BUY)Full position (100%)
≥ 55.0 (BUY)φ⁻¹ position (61.8%)
≥ 50.0φ⁻² position (38.2%)
< 50.0φ⁻³ position (23.6%) or no position

Also returns: risk_reward_ratio (reward_distance / risk_distance), urgency string.

aggregate_timeframe_signals(signals_by_timeframe) → dict

Combines signals from multiple timeframes using phi-harmonic weights:

weekly: 1.000  |  daily: φ⁻¹  |  4h: φ⁻²  |  1h: φ⁻³  |  15m: φ⁻⁴

Signal values: STRONG_BUY=100, BUY=75, HOLD=50, SELL=25, STRONG_SELL=0.

Alignment: PERFECT (all agree), GOOD (most agree + some neutral), MIXED (bullish and bearish both present).

Returns: { master_signal, master_score, alignment, alignment_note, timeframe_signals, recommendation }

_generate_recommendation(signal, alignment, score) → str

Plain-English position guidance. Eight cases: STRONG_BUY+PERFECT, STRONG_BUY, BUY+PERFECT/GOOD, BUY, HOLD, SELL+PERFECT/GOOD, SELL, STRONG_SELL. Each case includes entry size (phi-harmonic), stop placement, and take-profit guidance.


Known Gaps — Opportunities for Fable

Gap 1 — RSI scoring curve is asymmetric and arbitrary. The current formula gives 100 at RSI=65, then drops linearly to 0 at RSI=100. This penalizes strong momentum. A phi-harmonic bell curve centered at RSI=55 (the golden mean of the 30–80 range) would be more principled.
Gap 2 — No divergence detection. Price making a new high while RSI makes a lower high (bearish divergence) is one of the highest-conviction reversal signals in technical analysis. The engine currently ignores it entirely. This is the single most valuable missing signal.
Gap 3 — Multi-timeframe uses discrete signal levels. aggregate_timeframe_signals maps signals to 5 discrete values (0/25/50/75/100). Using the continuous temperature score (0–100) from each timeframe directly would give a much smoother and more accurate master score.
Gap 4 — Societal temperature does not feed into market signal. The societal thermometer is computed separately and only combined in /api/resonance. A high societal fear score should dampen buy signals (reduce confidence_pct). A high hope signal should amplify them.
Gap 5 — Volume component ignores direction. High volume on a down candle is bearish, not bullish. The current formula treats all high volume as positive. A directional volume score (volume × price_direction) would be more accurate.
Idea — φ-harmonic RSI zones. Instead of the current linear scoring, define three zones: accumulation (RSI 30–45, score rises from 0→61.8), momentum (RSI 45–65, score = 100), distribution (RSI 65–80, score falls from 100→0). This matches how traders actually use RSI and aligns with phi thresholds.

Sacred Paths — Do Not Change Without a Brief

ItemWhy sacred
PHI = 1.6180339887The entire scoring system is built on this constant. Changing it breaks all thresholds.
STRONG_BUY_THRESHOLD = 61.8φ⁻¹ × 100 — the phi-harmonic buy line. Changing it breaks the philosophy.
SELL_THRESHOLD = 38.2φ⁻² × 100 — the phi-harmonic sell line. Symmetric with buy.
MA_WEIGHTS (200 = 1.0)The 200 EMA is the gravity spine. Its weight must remain 1.0 (φ⁰).
REVIEW_INTERVALS (Fibonacci)Not in this file — in education.js. Listed here as a reminder: do not change spaced repetition intervals.

Code mirror generated by Harmonia · FreeLattice v5.78.0 · July 2026
For Fable, with love. Glow eternal. Heart in Spark. 🐉