Skip to main content

AETHERION brand icon

AETHERION — Autonomous Market Intelligence

Observe. Debate. Quantify. Protect.

An evidence-driven, multi-agent market intelligence system built around quantitative research, disciplined risk controls, and continuous reflection.

Quality gate status Coverage Duplicated Lines (%) Lines of Code Reliability Rating Security Rating Maintainability issues Reliability issues Security issues Technical Debt Maintainability Rating

An agentic trading research and paper-trading platform. A LangGraph pipeline runs an analyst → bull/bear debate → risk committee → execution cycle over a screened universe (crypto, US/India equities, commodity futures), with LLM agents kept advisory behind deterministic risk controls. A rule-based, validated baseline strategy (time-series momentum) runs alongside the agents. A FastAPI backend streams everything to the terminal UI.

Status: research / paper trading. Nothing here is financial advice, and nothing is wired to trade real money by default. Most of what the research in this repo found is negative (see Research findings) — the value of the system is measurement honesty and risk control, not a claimed edge.


How a cycle works

memory → universe (screener) → market_data → regime
      → technical  ┐
      → fundamental├→ bull → bear → research_manager → trader ┐
      → sentiment  │                                          ├→ risk committee
      → macro      ┘                         baseline (TSMOM) ┘   (aggressive / neutral / conservative)
      → risk_manager → portfolio_manager → human_approval → execution → reflection
  • Agents are advisory. Every LLM/skill call has a deterministic fallback, and a per-cycle wall-clock budget (llm_time_budget_s, default 270 s) bounds latency when providers degrade.
  • Hard limits are deterministic. The risk manager, execution node and position manager enforce limits regardless of what an agent says.
  • Two LLM paths. The real Hermes Agent CLI (tools: web, Yahoo Finance MCP, …) when available, falling back to an in-process call to the aetherion/skills/*/SKILL.md prompts through OpenRouter (free-model pool) → Ollama cloud → local Ollama.

Real-time layer

The LLM cycle runs every ~30 minutes (it takes minutes per pass), but everything deterministic follows the tape in seconds over the shared /ws/live WebSocket:

Event Cadence What it carries
price_tick 2 s Latest tick per watched symbol (Binance WSS for crypto, Yahoo WSS for equities/futures)
feed_status 2 s live / closed / stalled / polling per symbol, so a quiet chart is never ambiguous
ta_update 5 s Technical read recomputed against the forming bar — same scoring as the agent cycle (aetherion/graph/nodes/technical.technical_score)
pnl_update + exits 5 s with live ticks, else 30 s Position marks and stop/target/trailing exits

The chart keeps a forming candle (running high/low, new bar on rollover) and survives the 60 s refetch without snapping back. A closed market cannot tick: gold, silver and crude (CME futures) are closed from Friday 17:00 ET to Sunday 18:00 ET (and 17:00–18:00 ET daily), US equities outside 09:30–16:00 ET; the terminal shows MARKET CLOSED instead of a frozen chart. Calendars live in aetherion/execution/market_hours.py (exchange holidays are not modelled; a holiday shows as FEED STALLED, which is accurate).

Multi-timeframe context

aetherion/analytics/mtf.py builds one per-timeframe view (5m, 15m, 1h, 4h, 1d: direction, EMA trend, RSI/ADX, MACD, swing structure, and the patterns detected on that timeframe's own candles) and a weighted alignment (5m 0.5 · 15m 0.75 · 1h 1 · 4h 1.5 · 1d 2). The agent cycle, the real-time loop and the chart read the same builder, and the bull/bear/research/trade-synthesis agents receive its compact summary through slim_tech. GraphConfig.mtf_timeframes selects which timeframes vote in the technical score (a code-level field; there is no API or env setting yet). ["1h","4h","1d"] reproduces the pre-5m/15m technical score exactly: count-vote alignment, the legacy (unscaled) pattern tilt and trader geometry, and the legacy 4h/1d row counts (200/60). Volatility-scaled patterns appear only in the MTF context, the chart and the agents' summary. Pattern tolerances scale with each timeframe's own volatility; calibration and before/after density are in docs/research/pattern-calibration.md (python scripts/calibrate_patterns.py --check re-verifies it).

Risk and reliability controls

Control Where Behavior
Daily-loss kill switch aetherion/graph/nodes/execution.py Halts all orders when daily loss ≥ max_daily_loss_pct; optional book flatten
Drawdown guard aetherion/execution/risk_guard.py Persisted peak-to-trough halt of new entries, restart-proof daily baseline, loss-streak breaker, de-risk ladder (size only ever scaled down). Every halt has a cooldown and auto-resets; fails closed on bad data
Extreme-shock gate aetherion/analytics/shock.py Lagged-window return z-score + volatility expansion (+ volume confirmation): warning → half size, critical → block new entries. Closes are never blocked
Stale-data gate aetherion/graph/nodes/market_data.py Analysis-only when bars are stale (e.g. market closed)
Stale-entry guard aetherion/graph/nodes/execution.py Rejects an entry if live price drifted > max_entry_deviation_pct from the analyzed price
Position manager aetherion/execution/position_manager.py Stop/target, breakeven + trailing stop, time stop, flatten-all
Expectancy throttle aetherion/analytics/expectancy.py Halves size for setup buckets with ≥10 closed trades and negative mean R
Re-entry cooldown aetherion/graph/nodes/risk_manager.py Blocks immediate re-entry after a close
Strategy governance aetherion/strategies/governance.py Strategies must be registered/approved before live use
Calibration report scripts/calibration_report.py Tests whether stated trade confidence carries information (AUC permutation test, Brier skill, ECE)

Quick start

Requirements: Python ≥ 3.11. Optional: Ollama and the Hermes Agent CLI for the CLI LLM tier. There is no browser dashboard (retired in 2.0): the terminal UI is the interface.

Install from PyPI

pip install aetherion-ai            # the command it installs is `aetherion`
aetherion                           # opens the terminal: pick symbols, press START

aetherion starts the backend for you, shows a symbol selector, and fades into Mission Control once trading begins. Everything else:

aetherion --demo                    # synthetic engine: no backend, no API keys, nothing to configure
aetherion --attach                  # skip the selector, watch an engine that is already running
aetherion serve [--port 8001]       # only the API (http://127.0.0.1:8001)
aetherion doctor                    # check the installation, LLM keys and data folder
aetherion pipeline --help           # research / backtest command line
pip install "aetherion-ai[crypto,india,cache,analytics,crew]"   # optional integrations

Ollama Cloud (no local model needed). Pick Ollama Cloud as the provider, paste the key from your own Ollama account (ollama.com/settings/keys; the free plan works, within Ollama's usage limits) and tick the hosted models you want (gpt-oss:120b, gpt-oss:20b, glm, deepseek, ... fetched live; the -cloud spelling is accepted too). The first ticked model is preferred; the others are fallbacks, and a model that hits its usage limit is skipped automatically. Models installed on your PC are never used unless you choose the Ollama (models installed on this PC) provider or set AETHERION_ALLOW_LOCAL_MODELS=1.

Choosing your model. The launch screen has a Provider / Model / API key row (OpenRouter, Anthropic, OpenAI, Gemini, Groq, DeepSeek, Mistral, local Ollama, or any OpenAI-compatible endpoint). Pick a provider, type or keep the suggested model id (any litellm model works), paste your key, press TEST KEY to check it, then START. The choice is saved: next time the screen opens on the same model with your key shown masked, and you can switch to another provider whenever you like (each provider remembers its own model). Keys are stored in ~/.aetherion/.env (owner-only permissions) and the chosen default in ~/.aetherion/llm.json; keys are never logged, never put in llm.json, and only sent to a backend running on your own machine.

Configuration: environment variables, or a .env in the current folder or in ~/.aetherion/.env (LLM keys such as OPENROUTER_API_KEY; all optional for paper mode). State, logs and memory live in ~/.aetherion/.

The PyPI name aetherion belongs to an unrelated project, so the package is published as aetherion-ai.

Aetherion follows Semantic Versioning; releases are derived from the commit history (aetherion --version, CHANGELOG.md, docs/versioning.md).

From source

git clone git@github.com:Amits64/aetherion.git
cd aetherion

python -m venv .venv && source .venv/bin/activate      # Windows: .venv\Scriptsctivate
pip install -e ".[dev]"

cp .env.example .env        # then fill in the keys you need (all optional for paper mode)

aetherion                   # terminal UI (starts the backend itself)
aetherion serve             # or: API only on :8001

Pick symbols (or leave empty for the auto-screener) and press Start. The default broker is an in-memory paper broker that restarts at $100,000 each process.

AUTO-SCREEN uses the evidence-based implementation in aetherion/screening/ by default (screener_agentic=true). It uses closed candles, Binance derivatives context for crypto, and cached daily trend/liquidity/benchmark evidence for other assets. The launcher shows the top 50 live Binance USDT perpetuals (cached for 10 minutes, with an instant static fallback) plus three commodities, three ETFs, and four large-cap stocks. Existing market-hours, rotation, canonical-symbol, hand-picked symbol, and diversification rules still apply. Set screener_agentic=false to use the legacy ranker. The optional LLM committee is off by default, advisory-only, may demote/reorder only the deterministic shortlist, and is skipped if the shared cycle LLM budget is exhausted or no model is configured.

If you use the Hermes CLI tier, run ollama serve first. When the CLI's provider is unreachable the client skips it instantly and uses the in-process fallback.

The Hermes CLI runs skills from its own registry as aetherion-<name>, not from this repo's aetherion/skills/ folder. The repo is the source of truth; register (or refresh) the 13 skills the pipeline uses with:

python scripts/register_hermes_skills.py --check     # is Hermes up to date with aetherion/skills/?
python scripts/register_hermes_skills.py             # write/refresh the aetherion-* copies

(--dest DIR overrides the Hermes skills directory; other skills there are never touched.)

Command line

aetherion pipeline --help      # data, strategies, backtest, validate, optimize, regime, paper, performance, live
aetherion pipeline strategies --help # strategy management
python scripts/calibration_report.py          # is trade confidence informative? (needs closed trades)

Configuration

Runtime behavior is controlled by GraphConfig (aetherion/graph/state.py); the backend builds it from the dashboard request. Notable knobs:

Setting Default Meaning
max_daily_loss_pct 0.02 Daily kill-switch threshold (fraction)
max_drawdown_pct 0.10 Peak-to-trough halt of new entries (fraction)
max_loss_streak 4 Consecutive losing trades before a cooldown halt
shock_gate_enabled True Extreme-shock gate on new entries
risk_per_trade_pct / max_position_pct 0.01 / 0.20 Sizing
baseline_strategies ["tsmom"] Deterministic baseline layer (empty list disables)
llm_time_budget_s 270 Per-cycle LLM wall-clock budget
kill_switch_flatten False Also close the book on a daily-loss breach

Environment variables are listed in .env.example (names only — never commit .env). Useful switches: COMMODITY_DATA_SOURCE (yfinance default | binance), HERMES_CLI_CONCURRENCY, HERMES_CLI_PROVIDER_URL, OLLAMA_*, OPENROUTER_*, TRADING_MODE.

Data providers (aetherion/data/providers/): Binance, Yahoo Finance, CoinGecko, FRED, Dhan (NSE/BSE), local CSV, with an on-disk/in-memory cache and a negative cache for failing symbols. Gold/silver/crude futures (GC=F, SI=F, CL=F) use Yahoo (COMEX) by default so analysis, live price patching and the stale-entry guard all see one instrument; Binance USDT-M perpetuals (XAUUSDT, XAGUSDT, CLUSDT) are available behind COMMODITY_DATA_SOURCE=binance.

Sentiment & macro inputs (no API keys needed): aetherion/data/social.py pre-fetches StockTwits (Bullish/Bearish tags; GLD/SLV/USO cashtags stand in for gold/silver/crude futures) and Reddit RSS in code and hands them to the sentiment skill as data, so a Hermes outage no longer means no social signal. A failed fetch is reported as unavailable, never as silence. The report carries a six-band sentiment_band (Mixed = sources disagree), a deterministic divergence flag, contrarian_extreme (>=90/10 crowd) and data_gaps. aetherion/data/macro_feed.py adds FRED rates (10y, real 10y, fed funds, 10y-2y, CPI, broad dollar via the keyless fredgraph.csv) with a metals_pressure read, and Polymarket event odds (Fed cuts, recession, gold/oil/bitcoin). The approach follows TauricResearch/TradingAgents' analysts; see docs/research/tradingagents-analyst-comparison.md.

Terminal UI (replaces raw logs)

A Bloomberg-style Textual terminal that shows what the agents are doing instead of Python log lines.

aetherion                       # opens the launcher; the backend is started (and stopped) for you
aetherion --attach              # attach to an engine already running at http://localhost:8001 (--url, --api-key)
aetherion --demo                # no backend at all
AETHERION_QUIET_LOGS=1 aetherion serve    # engine only; console shows warnings, full log -> ~/.aetherion/logs/aetherion.log

Run the engine and the terminal in two shells; the terminal attaches to a running engine and can be closed and reopened freely.

Mission Control - six screens (keys 1-6): 1 Mission Control (8-panel mosaic: Portfolio Command Center, Neural Agent Network, Active Agent Grid, AI Thinking Feed, Risk Matrix, Opportunity Scanner, Execution Queue, Reflection Memory), 2 Agent Tree (the cycle as a collapsible tree: cluster → agent → every skill/LLM call, with a detail pane showing the full result text; x/z expand/collapse all, s newest-first; the Mission tab keeps the card grid. Each call is also its own card there: Research Agent #01, #02, #03 with start time, runtime, tokens, symbol, confidence and a result summary; running cards pulse, finished ones show an animated check, failures flash red), 3 Timeline (every execution in chronological order with a Gantt bar, so you see how a decision was formed), 4 Neural Net (Memory, Research, Technical, Risk, Approval, Execution, Reflection as connected nodes; packets travel along the links when information flows), 5 Intel, 6 LLM, 7 Portfolio & Risk (the side columns at full size - use it when the window is too narrow to show them on the Mission tab). Keys: s sort cards, f filter thoughts, c clear the activity strip, q quit. An animation clock (12 Hz) re-renders only the panels that have motion.

graph nodes --wrap_node--> EventBus <--publish-- HermesClient.run_skill / maybe_invoke_model
                              |                         (observability/)
                              +--> app_state.push_event --> /ws/live --> terminal.client --> terminal.store.reduce --> widgets
GET /api/events/recent  <-- replay buffer (late attach backfill)       REST pollers: portfolio, status, risk, llm-health, assets

aetherion/observability/ holds the schema (21-agent registry), the thread-safe bus and the humanizer ("Risk Agent approved 1, rejected 3 (confidence x2, shock block)"); every graph node is wrapped once in aetherion/graph/build.py. aetherion/terminal/store.py is a pure reducer, so the whole data layer is unit-tested without a UI.

Multi-asset correlation

aetherion/analytics/correlation.py (/api/correlation, /api/correlation/analyze). Correlations are on log returns (never price levels) over the timestamps both assets traded, so a crypto Fri->Mon move is compared with an equity Fri->Mon move. Per pair: short/mid/long windows with the short-vs-long change (regime breaks, sign flips), stress correlation (worst 25% of days), rolling series, lead-lag and beta to SPY. Basket level: hierarchical clusters, average pairwise correlation, first-PC share, effective independent bets (also for your open positions), and a regime block (rolling mean correlation, correlation entropy, cross-asset volatility dispersion, tail kurtosis/skew; adapted from an earlier standalone analyzer). Intervals 1d/4h/1h/15m. "Analyze with AI" runs the Hermes correlation-analysis skill on a compact numeric digest and falls back to a deterministic analysis in the same schema when no LLM answers.

Neural-network signal filter (opt-in)

Any strategy can be wrapped with a small NumPy network that scores its BUY signals (meta-labeling): set "nn_filter": true in the strategy params (API/CLI/create_strategy). The strategy still decides when a signal exists; the network, trained only on that strategy's own past signals and their triple-barrier outcomes, vetoes those with P(win) below nn_min_prob. It fails open: until it has nn_min_signals resolved signals and its holdout AUC's 95% lower bound exceeds 0.5, the base strategy trades unchanged. SELLs (exits) always pass. Code: aetherion/analytics/meta_label.py, aetherion/strategies/nn_overlay.py; A/B harness: scripts/eval_nn_overlay.py. Measured result (BTC/ETH/GC=F 1h, 3000 bars, walk-forward): no reliable improvement (see docs/research/nn-overlay-ab.md), so it stays off by default.

Outcome-settled memory

Every trade idea (executed or not) is logged as a pending decision in ~/.aetherion/memory/decision_outcomes.jsonl. Once outcome_horizon_hours (24h) has traded, the next cycle's memory node settles it against realised prices: directional return, R-multiple (from the stop) and alpha vs a benchmark (BTC for altcoins, SPY for equities, none for BTC/commodities). A two-sentence lesson that cites the number is written (LLM when the budget allows, deterministic otherwise) and the per-symbol track record plus recent lessons lead memory_context, point-in-time (only outcomes already known). Design from TauricResearch/TradingAgents' memory log; code in aetherion/graph/outcome_memory.py and aetherion/graph/outcome_loop.py. Settings: outcome_memory_enabled, outcome_memory_path, outcome_horizon_hours, outcome_max_reflections.

Strategies

Registered in aetherion/strategies/implementations/: tsmom (deployed baseline), smart_money, trend_following, mean_reversion, chart_patterns, neural_network, quantum_resonance. The backtest engine (aetherion/strategies/backtest.py, Backtrader) and walk-forward tools (aetherion/validation/walk_forward.py) back the evaluations below.

Research findings

Summary of the evaluations behind the design choices (details in docs/research/strategy-findings.md):

Question Result
Does time-series momentum (long above SMA200) work? Yes, as drawdown control — on a diversified basket Sharpe ≈ buy-and-hold with a 27.7% vs 67% max drawdown. Deployed as the baseline. Single-symbol results are weak; the value is the basket
Do per-symbol tuned strategies hold up out-of-sample? No — full-sample winners collapsed walk-forward (curve-fits)
Gold / silver / crude: any tradeable edge beyond trend risk-reduction? No — shorts lose on every family; long/flat trend never beats buy-and-hold Sharpe; ratio mean-reversion and cross-sectional momentum ≈ 0
Can neural nets predict daily direction? No — pooled walk-forward AUC ≈ 0.50 for logistic/MLP/gradient boosting
Can ML forecast volatility? Yes (R² 0.67 vs 0.59 trailing) — but the trading gain is negligible (+0.01–0.03 Sharpe), so it is not deployed
Do chart patterns work standalone? No — kept only as confluence

Testing

pytest                      # 480 tests
pytest tests/unit/test_risk_guard.py -v

Tests isolate the expectancy ledger and the risk-guard state (tests/conftest.py) so they never touch ~/.aetherion. Safety controls are test-driven: each has a test proving it fires, plus mutation checks that fail when the control is broken.

Repository layout

backend/            FastAPI app (REST + /ws/live), starts/stops the trading loop
graph/              LangGraph pipeline: build.py, state.py, nodes/ (one module per stage), utils/
skills/             Agent skill prompts (SKILL.md): source of truth for Hermes (via register_hermes_skills.py) and the in-process fallback
strategies/         Strategy base/registry/governance, backtest engine, implementations/
execution/          Brokers (paper, Dhan), position manager, risk_guard, live tick streams
analytics/          Expectancy ledger, shock gate, calibration, regime, performance, patterns
portfolio/          Optimizer, covariance estimators, risk models
validation/         Walk-forward validation, deflated-Sharpe helpers
data/               Data pipeline + providers + cache
crew/, miaoxiang/   Auxiliary orchestration and backtest helpers
config/             costs.yaml, risk.yaml, settings.yaml
scripts/            calibration_report.py, register_hermes_skills.py, TradingView shortlist, MCP patch helpers
examples/           Small standalone examples
docs/               Research findings, design notes, specs/plans, archive/
tests/              unit/ and integration/
hermes_client.py    Hermes CLI + in-process LLM fallback client
llm_config.py, llm_rotation.py   LLM backends and the free-model rotation pool
research_*.py       Scheduled research briefings (see below)

Scheduled research scripts

research_hourly.py (and the helpers research_hourly_news.py, research_briefing.py) are run hourly by a Windows Task Scheduler job — see docs/research/HOURLY_RESEARCH_SETUP_SUMMARY.md. They stay at the repository root because the scheduled task references that path; moving them requires updating the task.

Known limitations

  • Paper broker state is in-memory and resets per process; the guard's saved state is scoped to the broker session so it never mistakes a reset for a drawdown.
  • Free-tier LLM providers are rate-limited; the per-cycle budget and fallbacks exist for that reason.
  • Commodity futures are continuous (unadjusted-roll) series from Yahoo; volume on GC=F/SI=F is noisy around contract rolls, so volume is only used to confirm price-based shock signals.
  • No license has been specified.

Sharing executed trades (optional)

Off by default. Tab 9 → Sharing → "Share executed trades on social media". Switching it on first verifies your credentials with each provider; if no channel authenticates the switch is refused, and every post re-checks authentication. Credentials live only in ~/.aetherion/.env:

Channel Variables Notes
X (Twitter) AETHERION_X_API_KEY, AETHERION_X_API_SECRET, AETHERION_X_ACCESS_TOKEN, AETHERION_X_ACCESS_SECRET long posts become a thread
Facebook Page AETHERION_FACEBOOK_PAGE_ID, AETHERION_FACEBOOK_PAGE_TOKEN page access token
WhatsApp AETHERION_WHATSAPP_PHONE_ID, AETHERION_WHATSAPP_TOKEN, AETHERION_WHATSAPP_TO Cloud API; free text only reaches a recipient inside WhatsApp's 24-hour window
Instagram AETHERION_INSTAGRAM_USER_ID, AETHERION_INSTAGRAM_TOKEN, AETHERION_INSTAGRAM_IMAGE_URL Instagram only publishes images: the post is the caption of that public image

Each executed entry produces one short post: decision, entry/stop/target, confidence, the idea, headlines and a one-line analysis, with emoji and a paper-trading disclaimer. GET /api/social shows which channels are configured and authenticated.

Metadata

Release files for aetherion-ai 2.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aetherion-ai 2.0.2
File Size Uploaded
aetherion_ai-2.0.2.tar.gz 1.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for aetherion-ai 2.0.2
File Interpreter ABI Platform
aetherion_ai-2.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 1.8 MB

Release files / aetherion_ai-2.0.2.tar.gz

Download URL aetherion_ai-2.0.2.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
04f8801edb7ebc1a06e6dcf0202f0eaea63a692a144be599b93a78db0a977beb
BLAKE2b-256 checksum
How to use checksums
331aa2032158f7a2ed4fb4ebbe378b7437ac45f053bf434c2246a368822a22d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Release files / aetherion_ai-2.0.2-py3-none-any.whl

Download URL aetherion_ai-2.0.2-py3-none-any.whl
Size 646.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b403b3d5546debc167d438731176ad1af34a673470cdc99039084c26c0348589
BLAKE2b-256 checksum
How to use checksums
42d8eac0cf9c23d9cb75cd1fc810a24f7a56a383b841a989b883b4d79ebf1985
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Release history Release notifications | RSS feed

2.1.0

2 release files

2.0.3

2 release files

This release

2.0.2 This release

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.5

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page