Skip to content
Back to skills

Parallax Credit Lens

ASecurity

Credit risk assessment for publicly traded companies: leverage, coverage, liquidity, solvency (Palepu), Altman Z-score, and credit health signals vs. peer medians. Symbol in RIC format (AAPL.O, JPM.N). NOT for portfolio credit risk (use /parallax-scenario-analysis), not for private companies (requires document ingestion; not covered), not for forensic earnings-quality screening (use /parallax-earnings-quality), not for single-stock fundamental analysis (use /parallax-deep-dive).

  • 5 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 11, 2026
toolspythongoshellapi

Works with

  • claude code
  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 12 files and shows the line behind each finding

Scanned October 5, 2026

npx -y skills add bencharoenwong/parallax-workflows --skill parallax-credit-lens --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Parallax Credit Lens?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Parallax Credit Lens
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bencharoenwong-parallax-credit-lens/badge)](https://www.skillsdirectory.com/skills/bencharoenwong-parallax-credit-lens)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: parallax-credit-lens
description: "Credit risk assessment for publicly traded companies: leverage, coverage, liquidity, solvency (Palepu), Altman Z-score, and credit health signals vs. peer medians. Symbol in RIC format (AAPL.O, JPM.N). NOT for portfolio credit risk (use /parallax-scenario-analysis), not for private companies (requires document ingestion; not covered), not for forensic earnings-quality screening (use /parallax-earnings-quality), not for single-stock fundamental analysis (use /parallax-deep-dive)."
---

<!-- white-label: integration-pattern.md -->

# Credit Lens

## When not to use

- Private company credit analysis (requires document ingestion) → not covered; this skill needs a publicly traded issuer
- Portfolio credit concentration → use /parallax-scenario-analysis
- Single stock fundamental analysis → use /parallax-deep-dive
- Forensic earnings-quality screen → use /parallax-earnings-quality

## Gotchas

- Expected Parallax spend: ~10 tokens: Batch A 4 (three statements + peer snapshot), Batch B 6 (Palepu 5, score analysis 1; telemetry is free).
- JIT-load `_parallax/parallax-conventions.md` for §0.0 pre-flight, §1 RIC resolution, §3 parallel execution, §4 / §4.0 fallbacks, §11 verdict sensitivity, §14 host primitives.
- `credit_lens_logic.py` is the pure arithmetic layer: every flag, the Altman Z-score and zone, the Quality-change flag and the overall traffic-light are computed there, never in prose. No MCP calls or file writes go in it. `assemble_report()` is a test-only reference renderer: it omits §9.1 and §9.2 and must not produce client-facing output.
- The published cutoffs in Step 4 mirror the module's constants (`ABSOLUTE_THRESHOLDS`, the Altman zone function, `flag_quality_change`); `tests/test_credit_lens.py` pins the two in agreement. Edit the module first, then the table.
- `get_financial_analysis` is async (2–5 min) and supplies BOTH the solvency (§3) and liquidity (§3a) narratives — one call, two sections; if it fails, both are marked unavailable while the quantitative Liquidity row (from `ratios`) stands.
- Quality factor is a credit-health proxy: a deteriorating Quality score is an early warning of credit stress.
- Apply `_parallax/white-label/integration-pattern.md` §2 (load), §5 (Branding Header), §7 (About This Report).
- Not a house-view consumer: no loader step, no audit row.

Credit risk assessment for publicly traded companies using Parallax MCP tools.

## Usage

```
/parallax-credit-lens AAPL.O
/parallax-credit-lens JPM.N
/parallax-credit-lens 0001.HK "Hong Kong banking"
```

## Workflow

Every host interaction below is a host primitive from `parallax-conventions.md` §14 (bindings §14.2, fail-open §14.3). Parallax callables are whatever `discover-tools` returns this session (§0.1).

### Step 0 — Pre-flight

1. Resolve every `_parallax/...` path named in this file to the canonical copy (conventions §0.0 item 1).
2. `discover-tools`: bind every logical tool named anywhere in this workflow (Steps 1–2) to the exact callable and schema exposed now.
   <!-- host-note -->
   Claude Code: `ToolSearch` with query `"+Parallax"` before the first Parallax call.
   <!-- /host-note -->
3. Parse args: symbol; optional context text.
4. `load-reference` `_parallax/white-label/integration-pattern.md`; run §2 and record `white_label_active` + `client_name` (seven-key loader; `branding["voice"]` raises `KeyError` by design).

### Step 1 — Resolve inputs

`run-shell` `validate_ric()` in `credit_lens_logic.py` on the symbol. A plain ticker (AAPL) is resolved to RIC form per conventions §1 (→ AAPL.O) and re-validated. Then `call-tool` `get_company_info` for the identity oracle and market cap.

### Step 2 — Fetch (parallel batches)

**Batch A — core financials (4 tokens).** `call-tool` all four together:

```
get_financials(symbol=<RIC>, statement="balance_sheet")   # Total debt, equity, total assets, working capital, retained earnings
get_financials(symbol=<RIC>, statement="cash_flow")       # Operating CF, Capex, FCF
get_financials(symbol=<RIC>, statement="ratios")          # D/E, D/EBITDA, Interest Cov, margins, peer_median / peer_p75
get_peer_snapshot(symbol=<RIC>)                           # peer medians, factor scores
```

**Batch B — solvency, trend, macro (6 tokens, async).** `call-tool` all three together; `get_financial_analysis` never blocks the rest:

```
get_financial_analysis(symbol=<RIC>)   # Palepu solvency AND liquidity read (async)
get_score_analysis(symbol=<RIC>)       # Quality score 52-week trajectory
get_telemetry()                        # Market regime tag (no symbol parameter)
```

### Step 3 — Verify

- Identity per conventions §2: `get_peer_snapshot.target_company` vs `get_company_info.name`; `get_score_analysis` `data[0].symbol` vs the RIC.
- Input completeness for the helper: zero `total_assets` or `total_liabilities`, or a non-finite value, makes the Altman leg UNAVAILABLE (the module raises; do not substitute zero). A missing `peer_median`/`peer_p75` pair on a peer-relative-only metric makes that row UNAVAILABLE, never GREEN.
- The traffic-light is gate-shaped for its legs (conventions §4.0): an unjudgeable leg is UNAVAILABLE and excluded from the vote; the coverage clause in the header states it.

### Step 4 — Compute

Zero tool calls. `run-shell` `credit_lens_logic.py` for every number: `flag_metric(value, peer_median, peer_p75, metric_key)` per dashboard row (peer-relative and absolute, more conservative wins); `compute_altman_z(AltmanInputs(...))` → score, variant (`Z`, or `Z'` on book equity when market cap is absent) and zone; `quality_change_pts(current, prior)` → `flag_quality_change(...)`; `dashboard_rows(report)`; `build_header(report)` (and `finalize_verdict(report)` when `report.overall_flag` is needed downstream). → Load `references/flagging-rules.md` before building the report: it carries the `metric_key` registry, the peer-p75 direction rule, the Altman fallbacks, and the double-counting traps.

**Published cutoffs** (mirrors of the module constants; the module applies them, this table only documents them for §11 sensitivity lines):

| Leg | Amber | Red |
|---|---|---|
| Debt/EBITDA | > 3.5x | > 5.0x |
| Interest Coverage | < 3.0x | < 1.5x |
| Current Ratio | < 1.2x | < 1.0x |
| Altman Z (public-company variant, Altman 1968) | Grey zone 1.81–2.99 | Distress zone < 1.81 (Safe > 2.99) |
| Quality score change, 52 weeks, 0–10 scale | ≤ −0.5 pts | ≤ −1.5 pts |

Peer-relative rule for every metric: better than `peer_median` → GREEN; between median and the adverse `peer_p75` → AMBER; worse than `peer_p75` → RED. Overall: majority color wins; ties go to the more conservative color; UNAVAILABLE legs do not vote.

### Step 5 — Compose

Fill **Output Format** below in order: header via `build_header`, dashboard via `dashboard_rows`, §11 verdict-sensitivity line for the Altman leg only, Palepu narratives, Key Flags naming every unjudged leg; Branding Header per integration-pattern.md §5; About This Report per §7 with the currency line; `parallax-conventions.md §9.2` disclosure; standard disclaimer `parallax-conventions.md §9.1`.

### Step 6 — Render (deterministic gate, mandatory)

`run-shell` the shared gate per conventions §10.3 with this skill's key:

```
DRAFT="$(mktemp "${TMPDIR:-/tmp}/creditlens.XXXXXX")"
cat > "$DRAFT" <<'REPORT'
<your complete drafted report goes here>
REPORT
python3 "<skill-dir>/../_parallax/render_gate.py" --skill credit-lens < "$DRAFT"; rm -f "$DRAFT"
```

The entire final message is that command's stdout. The stderr `[render-gate] WARN:` line is diagnostics: never include it. If `run-shell` is absent, apply conventions §14.3: the render-gate row for the gate, and the gate-shaped-helper row for the flags — every leg is UNVERIFIED and the skill says so up front; never compute a flag in prose.

## Output Format

**Begin the response immediately with the rendered report — no preamble.** The first expected line is the `## Credit Risk Assessment: …` header, or the Branding Header when active. Structure output in markdown with the following sections:

### 1. **Header** (1 line)
```
## Credit Risk Assessment: [Company] ([RIC]) | Traffic-Light: 🟢/🟡/🔴 | Judged: N of M metrics
```

Emit this with `build_header(report)` rather than by copying the template. The `| Judged: N of M metrics` clause is appended only when a leg is unjudged, and on a routine run several are — so a hand-copied header without it understates the gap on exactly the runs that need it stated.
Overall traffic-light determined by: count of RED flags (→ Red), count of AMBER flags (→ Amber), count of GREEN (→ Green). Majority color wins. If two or more colors tie for the highest count, render the most conservative tied color (Red > Amber > Green) — e.g., a 2-2-2 split renders Red. Compute via `overall_traffic_light(flags)`, which also drops UNAVAILABLE legs from the count and returns UNAVAILABLE when every leg is missing.

**State the coverage whenever any leg is UNAVAILABLE.** Dropping those legs is right for the vote but silent in the header, so a 🟢 can rest on two judged metrics out of six and still read as a full clean bill.

**Call `finalize_verdict(report)` rather than assigning `overall_flag` yourself.** It sets the verdict from `report_flags(report)` — every `metric_rows` flag plus `altman_flag` plus `quality_flag` — and `build_header()` counts that same list, so the verdict and the `| Judged: N of M metrics` count cannot describe different metric sets. Assigning the flag by hand reintroduces exactly that divergence. Populate `quality_flag` and `altman_flag` on the report; they vote, and a leg you leave at its default counts as unjudged.

List which metrics went unjudged, and why, in Key Flags.

This is the normal case, not an edge case: seven of the ten registered keys carry no absolute band, and the `ratios` response supplies peer percentiles for only five metrics, so the five with neither are unjudged on a routine run. Never present a majority verdict drawn from a minority of the metrics without saying so.

### 2. **Metrics Dashboard** (table)
```
| Category      | Signal | Metric Value | Peer Median | Interpretation |
|---------------|--------|--------------|-------------|-----------------|
| Leverage      | 🔴 RED  | D/E 2.1x     | Peer 1.2x   | 75% above peer |
| Leverage      | 🟡 AMBER| D/EBITDA 3.9x | Peer 2.8x  | Above peer |
| Leverage      | ➖ UNAVAILABLE | —     | —           | No peer data and no absolute band |
| Coverage      | 🟢 GREEN| Int Cov 5.2x | Peer 3.1x   | Top quartile |
| Coverage      | ➖ UNAVAILABLE | —     | —           | No peer data and no absolute band |
| Liquidity     | 🟡 AMBER| Curr Ratio 1.3x | Peer 1.8x | Below median |
| Liquidity     | ➖ UNAVAILABLE | —     | —           | No peer data and no absolute band |
| Profitability | 🟢 GREEN| EBITDA Margin 28% | Peer 22% | Above peer |
| Profitability | ➖ UNAVAILABLE | —     | —           | No peer data and no absolute band |
| Profitability | ➖ UNAVAILABLE | —     | —           | No peer data and no absolute band |
| Altman Z      | 🟡 AMBER| Z = 2.1      | —           | Grey Zone |
| Quality Trend | 🔴 RED  | –1.8 pts (52w) | —         | Deteriorating |
```

Twelve rows: ten registered metrics plus the two module-owned legs. **Category repeats** — it is a grouping label, not the row identity. Five rows read `➖ UNAVAILABLE` on a routine run because those metrics carry no absolute band and `ratios` returns no peer pair for them; that is the normal shape, not a failure.

**Build the table with `dashboard_rows(report)`, not from `metric_rows` directly.** It returns your metric rows plus the Altman and Quality rows, which it renders from `altman_flag` / `quality_flag`. Those two are legs in their own right: supplying them as rows as well makes each vote twice, and doubling two legs flips real verdicts — three RED metrics against two GREEN is RED, but with both GREEN legs doubled it becomes 3 RED against 4 GREEN and renders GREEN.

Every `MetricRow` you build needs `metric_key` set to the registry key it was flagged with. `report_flags()` identifies a leg by that key, not by its display label, and raises on a missing key, an unregistered key, a reserved key, or the same key twice. Labels are free text; the key is the identity.

### 2a. **Verdict sensitivity** (one line)
State the Altman Z-score's nearest band boundary (2.99 Safe/Grey or 1.81 Grey/Distress) and the arithmetic flip condition, per `parallax-conventions.md` §11. Example: "Altman Z = 2.85 is within the Grey Zone, 0.14 below the 2.99 Safe threshold; a Z rise above 2.99 would move this leg to Safe." Applies only to the Altman Z band — the overall traffic-light header is a multi-metric majority vote, not a single published numeric cutoff, and is out of scope for this line.

### 3. **Solvency Assessment** (narrative)
Output the Palepu solvency section from `get_financial_analysis`. If unavailable, note: `[Solvency assessment unavailable — tool error]`.

### 3a. **Liquidity Assessment** (narrative)
Output the Palepu liquidity section from the same `get_financial_analysis` response. This explains *why* the Liquidity row in the Metrics Dashboard reads as it does — working-capital cycle, cash conversion, near-term obligations — and is not a restatement of the current/quick ratio. Do not omit it because the ratio already appears above. If unavailable, note: `[Liquidity assessment unavailable — tool error]`.

### 4. **Key Flags** (bulleted list)
List every RED and AMBER flag with one-line explanation:
- 🔴 RED: Debt/EBITDA 5.2x exceeds peer 75th percentile (3.8x) and absolute threshold (5.0x)
- 🟡 AMBER: Quality score down 1.4 pts over 52 weeks — monitor for further deterioration
- 🔴 RED: Interest Coverage 2.1x below absolute threshold (3.0x); limited debt service cushion

### 5. **Quality Trend** (one sentence)
[Quality score 52-week trajectory + interpretation from `get_score_analysis`]
Example: "Quality score deteriorated 1.4 points over the past 52 weeks, signaling a potential credit health decline."

### 6. **Macro Context** (one sentence)
[Market regime from `get_telemetry` + one sentence on credit implication]
Example: "Current market regime is recessionary — a challenging environment for credit quality; elevated default risk across all sectors."

### 7. **Branding Header** (only if `white_label_active` AND `client_name != ""`)
Single line at the very top of the rendered output: `**<client_name>** credit lens`. Logo handling per integration-pattern.md §5.

### 8. **About This Report** (always present)
One line stating branding state per integration-pattern.md §7, plus the unconditional §7 currency line: `Currency: figures as reported by source data; no base-currency conversion applied.` If a logo was skipped, append `Logo on file: <basename>` as a further About This Report line.

### 9. **Footer**

**AI-interaction disclosure (required regardless of view state):** Render `parallax-conventions.md §9.2` immediately above the disclaimer below.

Render the standard disclaimer verbatim from `parallax-conventions.md` §9.1.


## Failure modes

- Symbol not found or not RIC-resolvable: stop with the conventions §1 message; suggest checking the exchange suffix.
- `get_financial_analysis` fails or times out: continue; mark **both** §3 `[Solvency assessment unavailable — tool error]` and §3a `[Liquidity assessment unavailable — tool error]`; the Liquidity dashboard row (from `ratios`) is unaffected.
- `report_flags()` raises (missing, unregistered, reserved or duplicate `metric_key`): a construction error in the row list — fix the rows and re-render; never catch and continue.
- Peer pair missing or inverted for a metric: absolute rule only where one exists, else UNAVAILABLE; say so in Key Flags.
- Market cap absent: Z' on book equity with the substitution stated; no book equity either → Altman leg UNAVAILABLE and no §2a line.
- Host lacks `run-shell`: every flag leg UNVERIFIED (conventions §14.3); the skill states this before any table.

## Done when

- Header emitted by `build_header` with the `Judged: N of M` clause whenever any leg is unjudged; dashboard has twelve rows from `dashboard_rows`; first line is the header or the Branding Header.
- Every RED/AMBER flag and every UNAVAILABLE leg is named in Key Flags with its reason.
- §2a sensitivity line present for the Altman leg (or explicitly skipped when the leg is unavailable).
- The render gate ran and the reply is its stdout (or the §14.3 note is present in About This Report).
- `parallax-conventions.md §9.2` disclosure, the §9.1 disclaimer, and the About This Report currency line are present.
- Expected spend stated (Gotchas).

## Callouts (interpretation caveats)

- **Quality score is a credit proxy**: A deteriorating Quality score (a 52-week change of -1.5 pts or worse on the 0-10 scale) is an early warning of credit stress and should be flagged as RED even if other metrics are healthy.
- **Altman Z thresholds shift by industry**: Manufacturing thresholds may differ from retail/financial. The fixed thresholds are generic — note industry caveats in output if appropriate.
- **Peer comparisons assume comparable size/structure**: A mega-cap's peer medians may not be relevant to an analyst evaluating a small-cap. Call this out if significant size mismatch is detected.
- **Palepu solvency assessment includes accruals quality**: High accruals (earnings not backed by cash) is a red flag independent of traditional credit metrics.

Files in this skill

  • SKILL.md17.3 KB
  • credit_lens_logic.py34.1 KB
  • pytest.ini517 B
  • references/flagging-rules.md5.6 KB
  • tests/fixtures/get_financial_analysis.json1.8 KB
  • tests/fixtures/get_financials_balance_sheet.json1.2 KB
  • tests/fixtures/get_financials_cash_flow.json656 B
  • tests/fixtures/get_financials_ratios.json1 KB
  • tests/fixtures/get_financials_ratios_distressed.json1 KB
  • tests/fixtures/get_peer_snapshot.json532 B
  • tests/fixtures/get_score_analysis.json2.5 KB
  • tests/fixtures/get_telemetry.json598 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…