# Indicators Guide This guide explains how to configure and use the Indicators table on the live terminal dashboard. ## Overview The Indicators table displays computed financial indicators (e.g., WTI/BRENT ratio, live prices, moving averages, RSI) with their current value, 1-hour and 1-day percentage changes, and deviation from a long-term average. The system is **config-driven** — new indicators are added by editing `_data/indicators.json`. No code changes are required for standard indicator types. ## Dashboard Table The Indicators table is displayed below the Market table in the dashboard. It shows: | Column | Description | |--------|-------------| | `#` | Indicator number | | `Indicator` | Display name from config | | `Value` | Current indicator value | | `1h Change` | Percentage change over the last 1 hour | | `1D Change` | Percentage change over the last 1 day | | `Deviation` | Deviation from the long-term average | Changes are color-coded: **green** for positive, **red** for negative, **yellow** for neutral. ## Configuration ### Default Visibility The Indicators table is enabled by default. The visibility is set in `main_app.py` (`MainApp.__init__`): ```python self.renderer = DashboardRenderer(table_visibility={ "market": True, "strategies": False, "indicators": True, }) ``` ### Runtime Toggling Toggle the Indicators table at runtime: ```python app.toggle_table("indicators") # flip on/off app.toggle_table("indicators", enabled=True) # explicitly enable app.toggle_table("indicators", enabled=False) # explicitly disable ``` ## Indicator Types The following indicator types are supported in `_data/indicators.json`: ### `ratio` — A/B Ratio Computes `numerator / denominator`. ```json "wti_brent_ratio": { "display_name": "WTI/BRENT", "type": "ratio", "numerator": "xyz:CL", "denominator": "xyz:BRENTOIL", "changes": ["1h", "1d"], "show_deviation": true } ``` - **Value**: `live(numerator) / live(denominator)` from latest 1m candle closes - **1h Change**: compares to ratio from 1h candle close prices - **1D Change**: compares to ratio from 1d candle close prices - **Deviation**: `(current - long_avg) / long_avg * 100`, where `long_avg` is the mean of daily ratios over all available history ### `price` — Single Price ```json "wti_price": { "display_name": "WTI", "type": "price", "coin": "xyz:CL", "changes": ["1h", "1d"], "show_deviation": true } ``` - **Value**: latest close price from `{coin}_1m` table - **1h/1D Change**: compares to close from 1h/1d candle tables - **Deviation**: `(current - long_avg) / long_avg * 100`, where `long_avg` is the mean of daily closes ### `spread` — Price Difference Computes `numerator - denominator`. ```json "wti_brent_spread": { "display_name": "WTI-BRENT Spread", "type": "spread", "numerator": "xyz:CL", "denominator": "xyz:BRENTOIL", "changes": ["1h", "1d"], "show_deviation": true } ``` ### `diff_pct` — Percentage Difference Computes `(numerator - denominator) / denominator * 100`. ```json "wti_brent_diff": { "display_name": "WTI-BRENT Diff%", "type": "diff_pct", "numerator": "xyz:CL", "denominator": "xyz:BRENTOIL", "changes": ["1h", "1d"], "show_deviation": true } ``` ### `ma` — Moving Average ```json "wti_ma_20": { "display_name": "WTI MA(20)", "type": "ma", "coin": "xyz:CL", "timeframe": "1h", "period": 20, "changes": ["1h", "1d"], "show_deviation": true } ``` - **Value**: latest SMA value on the specified timeframe - **1h Change**: compares to MA value from 1h candle table - **1D Change**: compares to MA value from 1d candle table - **Deviation**: `(current_price - MA) / MA * 100` (how far the live price is from the MA) ### `rsi` — Relative Strength Index ```json "wti_rsi_14": { "display_name": "WTI RSI(14)", "type": "rsi", "coin": "xyz:CL", "timeframe": "1h", "period": 14, "changes": ["1h", "1d"], "show_deviation": true } ``` - **Value**: latest RSI value (0-100) on the specified timeframe - **1h/1D Change**: absolute change in RSI points - **Deviation**: `RSI - 50` (deviation from neutral) ### `custom` — Custom Function Calls a user-defined Python function. ```json "custom_indicator": { "display_name": "My Custom Indicator", "type": "custom", "module": "indicators.custom_indicators", "function": "my_custom_calc", "args": {"param1": "value1"}, "changes": ["1h", "1d"], "show_deviation": true } ``` The custom function must accept `db_path` as the first argument, plus any `args` from the config, and return a dict: ```python def my_custom_calc(db_path, **kwargs): return { "value": 0.96611, "reference": 0.96044, "changes": {"1h": 0.12, "1d": -0.45}, "deviation": 0.59 } } ``` ## Data Sources All indicator calculations read from the SQLite database `_data/market_data.db`: - **Live value**: latest close price from `{coin}_1m` candle table (updated in real-time by `live_candle_fetcher.py`) - **1h change**: close price from `{coin}_1h` candle table (second-to-last completed 1h candle) - **1D change**: close price from `{coin}_1d` candle table (second-to-last completed 1d candle) - **Reference value**: mean of daily values over all available historical data ## Process Architecture ``` indicators_fetcher.py (subprocess, runs every 30s) | +---> indicators.py (IndicatorCalculator) | | | +---> _data/market_data.db (SQLite candle data) | +---> _data/indicators.json (config) | +---> _logs/indicators_status.json (output) | +---> main_app.py (MainApp.read_indicators_status) | +---> dashboard.py (DashboardRenderer.build_indicators_table) ``` ## File Reference | File | Description | |------|-------------| | `_data/indicators.json` | Indicator definitions (config) | | `indicators.py` | `IndicatorCalculator` class — computation logic | | `indicators_fetcher.py` | Standalone script — runs in a loop, computes indicators, writes JSON | | `dashboard.py` | `DashboardRenderer.build_indicators_table()` — renders the table | | `main_app.py` | `run_indicators_fetcher()` — process target; `MainApp.read_indicators_status()` — reads JSON | | `_logs/indicators_status.json` | Output file with computed indicator values | ## Adding a New Indicator 1. Edit `_data/indicators.json` and add a new entry: ```json "my_new_indicator": { "display_name": "My Indicator", "type": "price", "coin": "BTC", "changes": ["1h", "1d"], "show_deviation": true } ``` 2. Restart the application (`python main_app.py`). The Indicators Fetcher will automatically pick up the new config on its next run. No code changes are needed for standard indicator types (`ratio`, `price`, `spread`, `diff_pct`, `ma`, `rsi`). For custom calculations, use the `custom` type.