Finance

CurrencyStrength

The relative strength of the major currencies as bars, strongest first, given or worked out from pairs' changes.

#finance#forex#chart#dashboard#no-js

Demo

Preview

Currency strength

Today
  1. AUDAustralian dollar+0.38%, the strongest
  2. EUREuro+0.16%
  3. CADCanadian dollar+0.12%
  4. CHFSwiss franc0.00%
  5. JPYJapanese yen-0.03%
  6. GBPBritish pound-0.11%
  7. USDUS dollar-0.15%, the weakest

Strength score, 0 to 10

Past week
  1. CHFSwiss franc7.2, the strongest
  2. USDUS dollar6.8
  3. GBPBritish pound5.6
  4. EUREuro5.1
  5. JPYJapanese yen3.4, the weakest

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/currency_strength.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/currency_strength.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/currency_strength.qwe
view CurrencyStrengthDemo() =    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; align-items: start">        <CurrencyStrength id="currency-strength-demo" period="Today" pairs={[            { pair: "EUR/USD", change: 0.22m }, { pair: "GBP/USD", change: -0.21m }, { pair: "USD/JPY", change: -0.42m },            { pair: "USD/CHF", change: 0m }, { pair: "AUD/USD", change: 0.35m }, { pair: "USD/CAD", change: -0.12m },            { pair: "EUR/GBP", change: 0.08m }, { pair: "EUR/JPY", change: 0.18m }, { pair: "GBP/JPY", change: -0.05m },            { pair: "AUD/JPY", change: 0.40m },        ]}/>        <CurrencyStrength id="currency-strength-demo-score" label="Strength score, 0 to 10" period="Past week" decimals={1}                          values={{ USD: 6.8m, EUR: 5.1m, GBP: 5.6m, JPY: 3.4m, CHF: 7.2m }}/>    </div>

Source

ui/currency_strength.qwe
// CurrencyStrength: how strong the major currencies are against each other, as a// bar each, strongest first. The strengths are given, or worked out from pairs'// changes: a currency's strength is the average of how it moved in every pair it is// in (a pair's change counts for its base and against its quote). When some are// negative the bars grow left and right of a middle line, green and red.////   <CurrencyStrength pairs={[{ pair: "EUR/USD", change: 0.22m }, { pair: "USD/JPY", change: -0.42m }, ...]} period="Today"/>//   <CurrencyStrength values={{ USD: 6.8m, EUR: 5.1m, JPY: 3.4m }} suffix="" decimals={1} label="Strength score, 0 to 10"/>//// pairs: a list of { pair, change }: "EUR/USD" and its change over the period, in// percent (decimals best; numbers are read as decimals). values: instead, a map of// code to its strength, on any scale. currencies: which to show (all that appear).// label: the heading ("Currency strength"). period: what the change is over, beside it// ("Today", "Past week"). suffix: after each number ("%" from pairs, "" from values).// decimals: digits shown (2). names: the currencies' names ({ CHF: "Swiss franc" };// the majors are known). locale: how numbers are written ("en-US"). id: the element's id.//// currency_strength_from_pairs(pairs) gives the map of code to strength, for other code.import ui/theme.qwe use ui_clslet currency_strength_css = css`.ui-fxstr { box-sizing: border-box; display: grid; gap: 10px; width: 100%; min-width: 0; max-width: 520px; padding: 16px 18px; border: 1px solid var(--ui-border);  border-radius: var(--ui-radius); background: var(--ui-surface); font: 13px/1.35 var(--ui-font); color: var(--ui-fg); }.ui-fxstr-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }.ui-fxstr .ui-fxstr-title { margin: 0; font-size: 15px; font-weight: 650; }.ui-fxstr-period { color: var(--ui-muted); font-size: 12px; }.ui-fxstr-list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }.ui-fxstr-item { display: grid; grid-template-columns: 22px 96px minmax(60px, 1fr) 64px; align-items: center; gap: 10px; }.ui-fxstr-rank { color: var(--ui-muted); font-size: 12px; text-align: right; font-variant-numeric: tabular-nums; }.ui-fxstr-code b { font-weight: 650; }.ui-fxstr-code small { display: block; overflow: hidden; color: var(--ui-muted); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }.ui-fxstr-track { position: relative; height: 12px; border-radius: 3px; background: var(--ui-subtle); }.ui-fxstr-split .ui-fxstr-track::after { content: ""; position: absolute; top: -3px; bottom: -3px; left: 50%; width: 1px; background: var(--ui-strong); }.ui-fxstr-bar { position: absolute; top: 0; bottom: 0; border-radius: 3px; background: var(--k); }.ui-fxstr-up { --k: var(--ui-success); } .ui-fxstr-down { --k: var(--ui-danger); } .ui-fxstr-level { --k: var(--ui-accent); }.ui-fxstr-value { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--k); }.ui-fxstr-level .ui-fxstr-value { color: var(--ui-fg); }.ui-fxstr-empty { margin: 0; color: var(--ui-muted); }@media (max-width: 420px) { .ui-fxstr-item { grid-template-columns: 18px 48px minmax(40px, 1fr) 56px; } .ui-fxstr-code small { display: none; } }`let currency_strength_names = { USD: "US dollar", EUR: "Euro", GBP: "British pound", JPY: "Japanese yen", CHF: "Swiss franc",                                CAD: "Canadian dollar", AUD: "Australian dollar", NZD: "New Zealand dollar", CNY: "Chinese yuan",                                SEK: "Swedish krona", NOK: "Norwegian krone", MXN: "Mexican peso" }// Each currency's strength from pairs' changes: the average of + the change where it is// the base and − the change where it is the quote. A map of code to a decimal.fn currency_strength_from_pairs(pairs: list) {    let moves = flatten(pairs | map((p) => {        let parts = split(upper(p.pair), "/")        let c = dec(p.change)        len(parts) > 1 ? [[parts[0], c], [parts[1], -c]] : []    }))    let groups = group_by(moves, (m) => m[0])    reduce(keys(groups), {}, (acc, k) => {        let xs = groups[k] | map((m) => m[1])        set(acc, k, sum(xs) / len(xs))    })}// A width or a place in percent, to two decimals.fn currency_strength_pct(n: num) -> str {    let r = round(n * 100) / 100    r == floor(r) ? str(floor(r)) : str(r)}view CurrencyStrength(pairs: list? = null, values: map? = null, currencies: list? = null, label: str = "Currency strength",                      period: str? = null, suffix: str? = null, decimals: int = 2, names: map? = null, locale: str = "en-US", id: str? = null,                      class: str? = null) {    style global currency_strength_css    let scores = values != null ? values : currency_strength_from_pairs(pairs ?? [])    let codes = currencies ?? keys(scores)    let items = codes | filter((c) => scores[c] != null) | map((c) => { code: c, v: round(dec(scores[c]), decimals, "half_up") })        | sort_by((it) => -it.v)    let top = len(items) > 0 ? max(items | map((it) => abs(it.v))) : 0    let split_bars = any(items, (it) => it.v < 0)    let unit = suffix ?? (values != null ? "" : "%")    let title = (c: str) => (names != null ? names[c] : null) ?? currency_strength_names[c]    <div class={ui_cls(["ui-fxstr", split_bars && "ui-fxstr-split", class])} id={id}>        <div.ui-fxstr-head>            <h3.ui-fxstr-title>{label}</h3>            {period != null && <span.ui-fxstr-period>{period}</span>}        </div>        {len(items) == 0            ? <p.ui-fxstr-empty>No currencies to compare.</p>            : <ol.ui-fxstr-list>                  {for [i, it] in enumerate(items) {                      let share = top == 0 ? 0 : float(abs(it.v)) / float(top)                      let width = split_bars ? share * 50 : share * 100                      let left = split_bars ? (it.v >= 0 ? 50 : 50 - width) : 0                      let tone = !split_bars ? "ui-fxstr-level" : (it.v > 0 ? "ui-fxstr-up" : (it.v < 0 ? "ui-fxstr-down" : "ui-fxstr-level"))                      let shown = `${split_bars && it.v > 0 ? "+" : ""}${format_number(it.v, locale, decimals)}${unit}`                      <li key={it.code} class={`ui-fxstr-item ${tone}`} data-code={it.code}>                          <span.ui-fxstr-rank aria-hidden="true">{i + 1}</span>                          <span.ui-fxstr-code><b>{it.code}</b>{title(it.code) != null && <small>{title(it.code)}</small>}</span>                          <span.ui-fxstr-track aria-hidden="true">                              <span.ui-fxstr-bar style={`left: ${currency_strength_pct(left)}%; width: ${currency_strength_pct(width)}%`}></span>                          </span>                          <span.ui-fxstr-value>{shown}{i == 0 && <span.ui-sr>, the strongest</span>}{i == len(items) - 1 && len(items) > 1 && <span.ui-sr>, the weakest</span>}</span>                      </li>                  }}              </ol>}    </div>}
Thread
77Useful? Like it, or add to its thread below.

Thread 0 posts

On CurrencyStrength: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.