{# ── Idle state ── #} {% if scan_status == 'idle' %}
🚀
No scan has been run yet

Configure your Finviz filters in the Controls tab, then click ▶ Run Scan.

{# ── Running state ── #} {% elif scan_status == 'running' %}
Scan in progress…

Fetching data from Finviz · Yahoo Finance.
This can take a few minutes.

Elapsed: 0s

{# ── Error state ── #} {% elif scan_status == 'error' %}
Scan failed
{{ scan_error }}
{# ── Done state ── #} {% elif scan_status == 'done' %} {% if stocks %} {# Stat cards #} {% set ns = namespace(sb=0, sells=0, top=0) %} {% for s in stocks %} {% if s.TD_Signal == 'STRONG BUY' %}{% set ns.sb = ns.sb + 1 %}{% endif %} {% if s.TD_Signal == 'SELL' %}{% set ns.sells = ns.sells + 1 %}{% endif %} {% if s.Score is not none and s.Score|int > ns.top %} {% set ns.top = s.Score|int %}{% endif %} {% endfor %}
{{ stocks|length }}
Stocks Matched
{{ ns.sb }}
Strong Buy Signals
{{ ns.sells }}
Sell Signals
{{ ns.top }}
Top Score
{# ── Sort-weight macros ── #} {# Emit a numeric key used by data-order so DataTables sorts signals semantically #} {% macro sig_w(v) -%} {%- if v == 'STRONG BUY' -%}5 {%- elif v == 'BUY' -%}4 {%- elif v == 'NEUTRAL' -%}3 {%- elif v == 'WEAK - WAIT' -%}2 {%- elif v == 'SELL' -%}1 {%- else -%}0{%- endif -%} {%- endmacro %} {% macro trend_w(v) -%} {%- if v == 'UPTREND' -%}3 {%- elif v == 'SIDEWAYS' -%}2 {%- elif v == 'DOWNTREND' -%}1 {%- else -%}0{%- endif -%} {%- endmacro %} {% macro cross_w(v) -%} {%- if v == 'CROSS UP' -%}3 {%- elif v == 'NO CROSS' -%}2 {%- elif v == 'CROSS DOWN' -%}1 {%- else -%}0{%- endif -%} {%- endmacro %} {# Table #}
📊 Stock Signals & Scores
{{ timestamp }}
{% for s in stocks %} {# Source — sort alphabetically #} {# Ticker — sort alphabetically on raw ticker symbol #} {# Price — sort on raw float #} {# Change % — sort on raw float (preserves negative) #} {# Volume — sort on raw float (comma-formatted display) #} {# RSI — sort on raw float #} {# ATR — sort on raw float #} {# TD Signal — sort on semantic weight (STRONG BUY=5 … SELL=1) #} {% set sig = s.TD_Signal|string if s.TD_Signal is not none else '—' %} {# TD Trend — sort on semantic weight (UPTREND=3 … DOWNTREND=1) #} {% set tr = s.TD_Trend|string if s.TD_Trend is not none else '—' %} {# YF Signal — sort on semantic weight #} {% set ys = s.YF_Signal|string if s.YF_Signal is not none else '—' %} {# EMA Cross — sort on semantic weight (CROSS UP=3, NO CROSS=2, CROSS DOWN=1) #} {% set xc = s.EMA_Cross|string if s.EMA_Cross is not none else '—' %} {# Score — sort on raw int #} {# Latest News — plain text, no sort weirdness #} {# Insider Action — coerce to string first to avoid float-NaN 'in' crash #} {% endfor %}
Source Ticker Price Change % Volume RSI ATR TD Signal TD Trend YF Signal EMA Cross Score Latest News Insider Action
{{ s.Source }}{{ s.Ticker }} {{ '$' ~ "%.2f"|format(s.Price|float) if s.Price is not none else '—' }} {% if s.Change is not none %} {% set chg = s.Change|float %} {{ '+' if chg >= 0 else '' }}{{ "%.2f"|format(chg) }}% {% else %}—{% endif %} {{ "{:,.0f}".format(s.Volume|float) if s.Volume is not none else '—' }} {% if s.RSI is not none %} {% set rsi = s.RSI|float %} {{ "%.1f"|format(rsi) }} {% else %}—{% endif %} {{ "%.2f"|format(s.ATR|float) if s.ATR is not none else '—' }} {% if sig == 'STRONG BUY' %} {{ sig }} {% elif sig == 'BUY' %}{{ sig }} {% elif sig == 'SELL' %}{{ sig }} {% elif sig == 'WEAK - WAIT' %} {{ sig }} {% elif sig == 'NEUTRAL' %} {{ sig }} {% else %}{{ sig }} {% endif %} {% if tr == 'UPTREND' %}▲ {{ tr }} {% elif tr == 'DOWNTREND' %} ▼ {{ tr }} {% elif tr == 'SIDEWAYS' %} — {{ tr }} {% else %}{{ tr }} {% endif %} {% if ys == 'STRONG BUY' %} {{ ys }} {% elif ys == 'BUY' %}{{ ys }} {% elif ys == 'SELL' %}{{ ys }} {% elif ys == 'WEAK - WAIT' %} {{ ys }} {% elif ys == 'NEUTRAL' %} {{ ys }} {% else %}{{ ys }} {% endif %} {% if xc == 'CROSS UP' %}↑ {{ xc }} {% elif xc == 'CROSS DOWN' %} ↓ {{ xc }} {% else %}{{ xc }} {% endif %} {% if s.Score is not none %} {% set sc = s.Score|int %} {{ sc }} {% else %}—{% endif %} {{ s.Latest_News|string if s.Latest_News is not none else '—' }} {% set ia = s.Insider_Action|string if s.Insider_Action is not none else '—' %} {% if 'Buy' in ia %}🔼 {{ ia }} {% elif 'Sale' in ia or 'Sell' in ia %} 🔽 {{ ia }} {% else %} {{ ia }} {% endif %}
{% else %} {# Done but zero results #}
🔍
No stocks matched your filters

Try loosening the filter criteria in Controls.

{% endif %} {% endif %}
{# /dashboardContent #}
{# /tab-dashboard #}
🔧 Scan Filters

These map directly to Finviz screener filter keys and values. Browse available filters ↗

{% for key, value in filters.items() %}
{% endfor %}
{# /tab-controls #}
Background Scan Schedule (EST)

Scheduler checks every minute bucket and runs scans in the background based on this schedule. If an end time is earlier than its start time, that session continues past midnight into the next day.

Session
Start
End
Interval (min)
Enabled

After Hours
Run once daily
Valid only when run time is before close.
{# /tab-schedule #}
📨 Ticker Subscriptions
    {# /tab-tickers #}
    Log file:
    Click ↺ Refresh to load logs.
    {# /tab-logs #}
    {# /tab-content #}
    {# /container-fluid #}