Skip to content

Commit 32dc482

Browse files
authored
Merge pull request #266 from yroulin/main
Adding Fear and Greed Index Widget
2 parents 7208611 + f112138 commit 32dc482

3 files changed

Lines changed: 310 additions & 0 deletions

File tree

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# Crypto Fear & Greed Index
2+
3+
A [Glance](https://github.com/glanceapp/glance) widget that displays the current **Crypto Fear & Greed Index** — a widely followed market sentiment indicator that measures whether crypto investors are driven by fear or greed at any given moment. The widget shows a live score from 0 to 100, a color-coded gradient bar with a moving indicator, a sentiment label, an emoji, and a trend arrow comparing today's value against yesterday's.
4+
5+
No API key, no sign-up, no configuration beyond pasting the YAML.
6+
7+
---
8+
9+
## Preview
10+
11+
![Crypto Fear & Greed Index widget preview](preview.png)
12+
13+
---
14+
15+
## What is the Fear & Greed Index?
16+
17+
The Crypto Fear & Greed Index was originally inspired by CNN's Fear & Greed Index for traditional stock markets, adapted for the cryptocurrency ecosystem. It distills complex market signals into a single number between **0** (Extreme Fear) and **100** (Extreme Greed).
18+
19+
The idea is simple: when the market is driven by **fear**, prices tend to be suppressed and may represent buying opportunities. When the market is driven by **greed**, prices may be overextended and due for a correction.
20+
21+
22+
### Index scale
23+
24+
| Range | Classification | Color | Emoji | What it means |
25+
|---|---|---|---|---|
26+
| 0 – 25 | **Extreme Fear** | 🔴 Red | 😱 | Investors are very worried. Historically a potential buying opportunity. |
27+
| 26 – 45 | **Fear** | 🟠 Orange | 😨 | Market sentiment is cautious and uncertain. |
28+
| 46 – 54 | **Neutral** | 🟡 Yellow | 😐 | Market is balanced between buyers and sellers. |
29+
| 55 – 75 | **Greed** | 🟢 Green | 😏 | Investors are increasingly confident, FOMO may be building. |
30+
| 76 – 100 | **Extreme Greed** | 💚 Dark Green | 🤑 | Market may be overheated and due for a correction. |
31+
32+
---
33+
34+
## Features
35+
36+
- 📊 **Live sentiment score** — numeric value from 0 to 100 displayed prominently
37+
- 🎨 **Dynamic color coding** — the score and label change color automatically based on the current classification
38+
- 📍 **Gradient progress bar** — a full spectrum bar (red → orange → yellow → green) with a white indicator dot that moves to the exact position of the current score
39+
- 😱 → 🤑 **Emoji + sentiment label** — human-readable classification shown alongside the score
40+
- **▲ ▼ → Trend arrow** — compares today's score against yesterday's so you can see at a glance whether sentiment is improving or deteriorating
41+
- 🗓 **Yesterday's value** — displayed as secondary text beneath the classification
42+
- 🆓 **Completely free** — uses the public [alternative.me](https://alternative.me/crypto/fear-and-greed-index/) API with no authentication required
43+
44+
---
45+
46+
## API
47+
48+
This widget relies on the **alternative.me Crypto Fear & Greed Index API**, a free and widely used public API that has been running since 2018.
49+
50+
| Property | Value |
51+
|---|---|
52+
| **Endpoint** | `https://api.alternative.me/fng/?limit=2` |
53+
| **Authentication** | None — no API key required |
54+
| **Rate limit** | None enforced for normal usage |
55+
| **Update frequency** | Once per day (scores are published daily) |
56+
| **Response format** | JSON |
57+
58+
The `?limit=2` query parameter tells the API to return the **two most recent daily entries**: today's value (`data.0`) and yesterday's (`data.1`). This is what enables the trend arrow comparison.
59+
60+
### Example API response
61+
62+
```json
63+
{
64+
"name": "Fear and Greed Index",
65+
"data": [
66+
{
67+
"value": "13",
68+
"value_classification": "Extreme Fear",
69+
"timestamp": "1708905600",
70+
"time_until_update": "74093"
71+
},
72+
{
73+
"value": "18",
74+
"value_classification": "Extreme Fear",
75+
"timestamp": "1708819200",
76+
"time_until_update": null
77+
}
78+
],
79+
"metadata": {
80+
"error": null
81+
}
82+
}
83+
```
84+
85+
### Fields used by this widget
86+
87+
| JSON path | Type | Used for |
88+
|---|---|---|
89+
| `data.0.value` | `Int` | Current day's score (0–100) |
90+
| `data.1.value` | `Int` | Yesterday's score for trend comparison |
91+
| `data.0.value_classification` | `String` | Sentiment label (e.g. `"Extreme Fear"`) |
92+
93+
---
94+
95+
## Installation
96+
97+
### 1. Open your Glance config file
98+
99+
Typically located at `glance.yml` or wherever you have your Glance configuration set up (local install or Docker volume mount).
100+
101+
### 2. Add the widget
102+
103+
Paste the following block into the `widgets` list of any column on any page:
104+
105+
```yaml
106+
- type: custom-api
107+
title: Crypto Fear & Greed Index
108+
cache: 1h
109+
url: https://api.alternative.me/fng/?limit=2
110+
template: |
111+
{{ $value := .JSON.Int "data.0.value" }}
112+
{{ $prev := .JSON.Int "data.1.value" }}
113+
{{ $label := .JSON.String "data.0.value_classification" }}
114+
115+
{{ $color := "#e74c3c" }}
116+
{{ if ge $value 26 }}{{ $color = "#e67e22" }}{{ end }}
117+
{{ if ge $value 46 }}{{ $color = "#f1c40f" }}{{ end }}
118+
{{ if ge $value 55 }}{{ $color = "#2ecc71" }}{{ end }}
119+
{{ if ge $value 76 }}{{ $color = "#27ae60" }}{{ end }}
120+
121+
{{ $emoji := "😱" }}
122+
{{ if ge $value 26 }}{{ $emoji = "😨" }}{{ end }}
123+
{{ if ge $value 46 }}{{ $emoji = "😏" }}{{ end }}
124+
{{ if ge $value 76 }}{{ $emoji = "🤑" }}{{ end }}
125+
126+
{{ $arrow := "→" }}
127+
{{ if gt $value $prev }}{{ $arrow = "▲" }}{{ end }}
128+
{{ if lt $value $prev }}{{ $arrow = "▼" }}{{ end }}
129+
130+
<div style="display: flex; flex-direction: column; gap: 0.75em;">
131+
132+
<div style="display: flex; align-items: center; gap: 0.5em;">
133+
<span style="font-size: 3em; font-weight: bold; color: {{ $color }}; line-height: 1;">
134+
{{ $value }}
135+
</span>
136+
<div style="display: flex; flex-direction: column;">
137+
<span style="font-size: 1.1em; font-weight: bold; color: {{ $color }};">
138+
{{ $emoji }} {{ $label }}
139+
</span>
140+
<span style="font-size: 0.78em; color: var(--color-subdue);">
141+
Yesterday: {{ $prev }} {{ $arrow }}
142+
</span>
143+
</div>
144+
</div>
145+
146+
<div style="position: relative; height: 10px; border-radius: 5px;
147+
background: linear-gradient(to right, #e74c3c 0%, #e67e22 25%, #f1c40f 45%, #2ecc71 75%, #27ae60 100%);">
148+
<div style="
149+
position: absolute;
150+
left: calc({{ $value }}% - 6px);
151+
top: 50%;
152+
transform: translateY(-50%);
153+
width: 13px; height: 13px;
154+
background: white;
155+
border-radius: 50%;
156+
border: 2px solid {{ $color }};
157+
box-shadow: 0 0 4px rgba(0,0,0,0.5);
158+
"></div>
159+
</div>
160+
161+
<div style="display: flex; justify-content: space-between; font-size: 0.68em; color: var(--color-subdue);">
162+
<span>😱 Extreme Fear</span>
163+
<span>Fear</span>
164+
<span>Greed</span>
165+
<span>🤑 Extreme Greed</span>
166+
</div>
167+
168+
<div style="font-size: 0.8em; color: var(--color-subdue); border-top: 1px solid var(--color-border); padding-top: 0.4em;">
169+
Source: alternative.me · Updates daily
170+
</div>
171+
172+
</div>
173+
```
174+
175+
### 3. Restart or reload Glance
176+
177+
```bash
178+
# If running locally
179+
./glance
180+
181+
# If running with Docker
182+
docker compose restart glance
183+
```
184+
185+
The widget will appear immediately on your dashboard.
186+
187+
---
188+
189+
## Configuration
190+
191+
This widget has no required configuration — it works out of the box. The only optional field you may want to adjust is `cache`.
192+
193+
### Cache
194+
195+
```yaml
196+
cache: 1h
197+
```
198+
199+
Since the index only updates **once per day**, a cache of `1h` is more than sufficient. Setting it lower (e.g. `5m`) will not give you fresher data and only creates unnecessary HTTP requests to the free API. You could even set it as high as `12h` if you prefer.
200+
201+
---
202+
203+
## How the template works
204+
205+
The widget uses Glance's `custom-api` widget type with a Go template. Here is a breakdown of what each section does:
206+
207+
**Variable extraction**
208+
```
209+
{{ $value := .JSON.Int "data.0.value" }}
210+
{{ $prev := .JSON.Int "data.1.value" }}
211+
{{ $label := .JSON.String "data.0.value_classification" }}
212+
```
213+
Reads today's score, yesterday's score, and the text classification from the API JSON response. Note that the API returns `value` as a string in the JSON, but Glance's `.JSON.Int` helper automatically coerces it to an integer.
214+
215+
**Dynamic color**
216+
```
217+
{{ $color := "#e74c3c" }}
218+
{{ if ge $value 26 }}{{ $color = "#e67e22" }}{{ end }}
219+
{{ if ge $value 46 }}{{ $color = "#f1c40f" }}{{ end }}
220+
{{ if ge $value 55 }}{{ $color = "#2ecc71" }}{{ end }}
221+
{{ if ge $value 76 }}{{ $color = "#27ae60" }}{{ end }}
222+
```
223+
Uses `ge` (greater than or equal) comparisons to progressively override the color variable as the score crosses each threshold. The comparisons are chained so only the highest matching band wins — a value of `80` will pass all four checks, ending on dark green `#27ae60`.
224+
225+
**Trend arrow**
226+
```
227+
{{ $arrow := "→" }}
228+
{{ if gt $value $prev }}{{ $arrow = "▲" }}{{ end }}
229+
{{ if lt $value $prev }}{{ $arrow = "▼" }}{{ end }}
230+
```
231+
Compares today vs yesterday. Arrow points up if sentiment improved, down if it worsened, and stays sideways if the value is identical.
232+
233+
**Gradient bar indicator**
234+
```css
235+
left: calc({{ $value }}% - 6px);
236+
```
237+
The indicator dot is positioned using the raw score as a CSS percentage. A value of `72` places the dot at `72%` along the bar, which naturally lands in the green "Greed" zone. The `-6px` offset re-centers the 13px dot on that exact position.
238+
239+
---
240+
241+
## Credits
242+
- Index data provided by [alternative.me](https://alternative.me/crypto/fear-and-greed-index/)
243+
- Built for [Glance](https://github.com/glanceapp/glance) using the `custom-api` widget type with Go templates
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
- type: custom-api
2+
title: Crypto Fear & Greed Index
3+
cache: 12h
4+
url: https://api.alternative.me/fng/?limit=2
5+
template: |
6+
{{ $value := .JSON.Int "data.0.value" }}
7+
{{ $prev := .JSON.Int "data.1.value" }}
8+
{{ $label := .JSON.String "data.0.value_classification" }}
9+
10+
{{ $color := "#e74c3c" }}
11+
{{ if ge $value 26 }}{{ $color = "#e67e22" }}{{ end }}
12+
{{ if ge $value 46 }}{{ $color = "#f1c40f" }}{{ end }}
13+
{{ if ge $value 55 }}{{ $color = "#2ecc71" }}{{ end }}
14+
{{ if ge $value 76 }}{{ $color = "#27ae60" }}{{ end }}
15+
16+
{{ $emoji := "😱" }}
17+
{{ if ge $value 26 }}{{ $emoji = "😨" }}{{ end }}
18+
{{ if ge $value 46 }}{{ $emoji = "😏" }}{{ end }}
19+
{{ if ge $value 76 }}{{ $emoji = "🤑" }}{{ end }}
20+
21+
{{ $arrow := "→" }}
22+
{{ if gt $value $prev }}{{ $arrow = "▲" }}{{ end }}
23+
{{ if lt $value $prev }}{{ $arrow = "▼" }}{{ end }}
24+
25+
<div style="display: flex; flex-direction: column; gap: 0.75em;">
26+
27+
<div style="display: flex; align-items: center; gap: 0.5em;">
28+
<span style="font-size: 3em; font-weight: bold; color: {{ $color }}; line-height: 1;">
29+
{{ $value }}
30+
</span>
31+
<div style="display: flex; flex-direction: column;">
32+
<span style="font-size: 1.1em; font-weight: bold; color: {{ $color }};">
33+
{{ $emoji }} {{ $label }}
34+
</span>
35+
<span style="font-size: 0.78em; color: var(--color-subdue);">
36+
Yesterday: {{ $prev }} {{ $arrow }}
37+
</span>
38+
</div>
39+
</div>
40+
41+
<div style="position: relative; height: 10px; border-radius: 5px;
42+
background: linear-gradient(to right, #e74c3c 0%, #e67e22 25%, #f1c40f 45%, #2ecc71 75%, #27ae60 100%);">
43+
<div style="
44+
position: absolute;
45+
left: calc({{ $value }}% - 6px);
46+
top: 50%;
47+
transform: translateY(-50%);
48+
width: 13px; height: 13px;
49+
background: white;
50+
border-radius: 50%;
51+
border: 2px solid {{ $color }};
52+
box-shadow: 0 0 4px rgba(0,0,0,0.5);
53+
"></div>
54+
</div>
55+
56+
<div style="display: flex; justify-content: space-between; font-size: 0.68em; color: var(--color-subdue);">
57+
<span>😱 Extreme Fear</span>
58+
<span>Fear</span>
59+
<span>Greed</span>
60+
<span>🤑 Extreme Greed</span>
61+
</div>
62+
63+
<div style="font-size: 0.8em; color: var(--color-subdue); border-top: 1px solid var(--color-border); padding-top: 0.4em;">
64+
Source: alternative.me · Updates daily
65+
</div>
66+
67+
</div>
29.9 KB
Loading

0 commit comments

Comments
 (0)