HERMES // TRADING FLOOR

{{ 'MONITOR ACTIVE' if status else 'DASHBOARD ONLY' }} Updated: --:--:--
{% set mode = status.get('mode', 'paper') %} {{ mode }} {% if status.get('live_trading') %} 💰 REAL {% endif %}
{% if not status %}
Agents are not analyzing yet The dashboard does not silently start the monitor because agent cycles may consume paid LLM and market-data usage. From the extracted bot folder, initialize paper cash once and then start the monitor: source venv/bin/activate && python run_paper.py --reset --initial-cash 1000
./launch_monitor.sh
Keep this terminal open. Mira, Nova, and Vesper will appear in Agent Chat after an LLM analysis cycle. Paper mode places no real orders.
{% endif %}
Cash
${{ "%.2f"|format(portfolio.get('cash', 0)) }}
Equity
{% set ps = status.get('portfolio_summary', {}) if status else {} %} {% set init_eq = ps.get('current_equity') if ps.get('current_equity') is not none else ( (portfolio.get('equity_history') or [{}])[-1].get('total_equity', portfolio.get('cash', 0)) ) %}
${{ "%.2f"|format( init_eq ) }}
P&L
{% set ps = status.get('portfolio_summary', {}) if status else {} %} {% set init = ps.get('initial_cash') if ps.get('initial_cash') is not none else portfolio.get('initial_cash', 0) %} {% set live_eq = ps.get('current_equity') if ps.get('current_equity') is not none else ( (portfolio.get('equity_history') or [{}])[-1].get('total_equity', portfolio.get('cash', 50)) ) %} {% set overall_val = live_eq - init %} {% set overall_pct = ps.get('total_return_pct', (overall_val / init * 100 if init else 0)) %}
${{ "%.2f"|format(overall_val) }}
{{ "%.1f"|format(overall_pct) }}% all-time
Realized (closed)
{% set rpnl = portfolio.get('total_realized_pnl', 0) %}
${{ "%.2f"|format(rpnl) }}
Trades
{{ portfolio.get('total_trades', 0) }}
Risk & Stats
{% set equity_hist = portfolio.get('equity_history') or [] %} {% set eq_val = (equity_hist[-1] if equity_hist else {}).get('total_equity', portfolio.get('cash', 0)) or 1 %}
Exposure
{{ "%.0f"|format(((portfolio.get('positions') or [])|length * 25) / eq_val * 100 if eq_val and eq_val > 0 else 0) }}%
Positions
{{ (portfolio.get('positions') or [])|length }}
Buffer
{{ "%.0f"|format((portfolio.get('cash',0)/eq_val*100) if eq_val>0 else 0) }}%
{% set ps = status.get('portfolio_summary', {}) if status else {} %} {% if ps.get('win_rate') is not none %}
Win rate {{ "%.1f"|format(ps.get('win_rate',0)) }}% • Avg W/L ${{ "%.2f"|format(ps.get('avg_win',0)) }} / ${{ "%.2f"|format(ps.get('avg_loss',0)) }} • Expectancy ${{ "%.2f"|format(ps.get('expectancy_per_trade',0)) }}
{% endif %}
Positions
{% set positions = portfolio.get('positions') or {} %} {% if positions %}
{% for symbol, pos in positions.items() %}
{{ symbol }} {{ "%.4f"|format( (pos.get('shares',0) or 0)|float ) }} sh
${{ "%.2f"|format( (pos.get('cost_basis',0) or 0)|float ) }}
@ ${{ "%.2f"|format( (pos.get('avg_cost',0) or 0)|float ) }}
{% endfor %}
{% else %}
— no open positions —
{% endif %}
Decisions
{% if decisions %}
{% for d in decisions[:6] %} {% set raw = (d.get('action','') or '')|string|lower %}
{{ (d.get('action','')|string).upper() }} {{ d.get('symbol','') or '' }} {% set rpnl = d.get('realized_pnl') %} {% if rpnl is not none and rpnl != 0 %} {{ '+' if rpnl >= 0 else '' }}${{ "%.2f"|format(rpnl) }} {% endif %}
${{ "%.0f"|format( (d.get('usd_amount',0) or 0)|float ) }}
{{ d.get('reasoning','') or '' }}
{% endfor %}
{% else %}
— awaiting first trade —
{% endif %}
Agent Feed
◆ Nova ◆ Vesper ◆ Mira
NOVA • VESPER • MIRA // multi-agent floor
Session Memorybuys · sells · cooldowns · discoveries