240 lines
6.8 KiB
Markdown
240 lines
6.8 KiB
Markdown
# 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.
|