Skip to content
Back to skills

Conviction Scoring

ASecurity

'"Multi-factor conviction scoring engine combining technical, momentum"

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 4, 2026
developmentpythonrustgotestingdocumentation

Security analysis

A100/100

Scanned September 4, 2026

npx -y skills add paulpas/agent-skill-router --skill conviction-scoring --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Conviction Scoring?

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

Security grade badge for Conviction Scoring
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-conviction-scoring/badge)](https://www.skillsdirectory.com/skills/paulpas-conviction-scoring)

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: conviction-scoring
compatibility: opencode
completeness: 95
content-types:
- code
- guidance
- do-dont
- examples
description: '"Multi-factor conviction scoring engine combining technical, momentum"
  trend, volatility, and volume signals with configurable weights'
license: MIT
maturity: stable
metadata:
  domain: coding
  output-format: code
  related-skills: null
  role: implementation
  scope: implementation
  triggers: combining, conviction scoring, conviction-scoring, engine, multi-factor
  archetypes:
  - tactical
  - generation
  anti_triggers:
  - brainstorming
  - vague ideation
  - code golf
  - over-engineering
  response_profile:
    verbosity: low
    directive_strength: high
    abstraction_level: operational
version: "1.0.0"




---




# Skill: coding-conviction-scoring

# Multi-factor conviction scoring engine combining technical, momentum, trend, volatility, and volume signals with configurable weights

## Role / Purpose

This skill covers the pattern for turning raw indicator scores into a single, actionable conviction score for trading decisions. The `ConvictionEngine` is initialized with configurable factor weights, validates those weights at construction, and exposes pure functions for scoring individual signals or batches of signal events.

---

## Key Patterns

### 1. Weight Validation at Construction — Fail Fast

All four weights must be non-negative and must sum to 1.0 (within 0.01 tolerance). These checks run in `__init__` before any weights are stored. A `ConvictionEngine` with bad weights cannot be created.

```python
class ConvictionEngine:
    def __init__(
        self,
        minimum_entry: float = 0.7,
        minimum_exit: float = 0.5,
        momentum_weight: float = 0.3,
        trend_weight: float = 0.3,
        volatility_weight: float = 0.2,
        volume_weight: float = 0.2,
    ):
        """Initialize conviction engine - fail fast on invalid params."""
        # Guard clause - early exit for invalid inputs
        if minimum_entry <= 0 or minimum_entry > 1:
            raise ValueError("Minimum entry conviction must be in (0, 1]")
        if minimum_exit <= 0 or minimum_exit > 1:
            raise ValueError("Minimum exit conviction must be in (0, 1]")
        if (
            momentum_weight < 0
            or trend_weight < 0
            or volatility_weight < 0
            or volume_weight < 0
        ):
            raise ValueError("Factor weights cannot be negative")
        total = momentum_weight + trend_weight + volatility_weight + volume_weight
        if abs(total - 1.0) > 0.01:
            raise ValueError("Factor weights must sum to 1.0")

        self.minimum_entry = minimum_entry
        self.minimum_exit = minimum_exit
        self.momentum_weight = momentum_weight
        self.trend_weight = trend_weight
        self.volatility_weight = volatility_weight
        self.volume_weight = volume_weight
```

---

### 2. `calculate_conviction()` — Pure Function

All five input scores are validated to be in `[0, 1]` before any calculation. The technical score is the weighted average of the four factor scores. The function returns an immutable `ConvictionScore` model.

```python
    def calculate_conviction(
        self,
        technical_score: float,
        momentum_score: float,
        trend_score: float,
        volatility_score: float,
        volume_score: float,
    ) -> ConvictionScore:
        """Calculate conviction score from component scores - pure function."""
        # Guard clause - early exit for invalid inputs
        for score in [technical_score, momentum_score, trend_score, volatility_score, volume_score]:
            if score < 0 or score > 1:
                raise ValueError(f"All scores must be in [0, 1], got {score}")

        # Weighted average formula for technical score
        technical = (
            self.momentum_weight * momentum_score
            + self.trend_weight * trend_score
            + self.volatility_weight * volatility_score
            + self.volume_weight * volume_score
        )

        overall = technical

        return ConvictionScore(
            overall=overall,
            technical=technical,
            momentum=momentum_score,
            trend=trend_score,
            volatility=volatility_score,
            volume=volume_score,
        )
```

---

### 3. `should_enter()` / `should_exit()` — Threshold Checks

Pure boolean functions. No side effects, no mutations. Callers get a clear decision without knowing the threshold values.

```python
    def should_enter(self, conviction_score: ConvictionScore) -> bool:
        """Determine if position should be entered - pure function."""
        return conviction_score.overall >= self.minimum_entry

    def should_exit(self, conviction_score: ConvictionScore) -> bool:
        """Determine if position should be exited - pure function."""
        return conviction_score.overall <= self.minimum_exit
```

---

### 4. Scoring from Signal Events — Batch and Single

`score_signal_event()` scores a single `SignalEvent` using `signal.confidence` as the technical score and extracting factor scores from the signal's metadata. `calculate_conviction_from_signals()` aggregates a list of signals by averaging each factor across all signals.

```python
    def score_signal_event(self, signal: SignalEvent) -> ConvictionScore:
        """Score a single signal event - pure function."""
        if not signal:
            raise ValueError("Signal cannot be None")

        metadata = signal.metadata or {}

        return self.calculate_conviction(
            technical_score=signal.confidence,
            momentum_score=metadata.get("momentum_score", 0.5),
            trend_score=metadata.get("trend_score", 0.5),
            volatility_score=metadata.get("volatility_score", 0.5),
            volume_score=metadata.get("volume_score", 0.5),
        )

    def calculate_conviction_from_signals(
        self,
        signal_events: list[SignalEvent],
    ) -> ConvictionScore:
        """Calculate conviction from list of signal events - pure function."""
        if not signal_events:
            raise ValueError("Signal events list cannot be empty")

        momentum_scores = []
        trend_scores = []
        volatility_scores = []
        volume_scores = []

        for signal in signal_events:
            metadata = signal.metadata or {}
            momentum_scores.append(metadata.get("momentum_score", 0.5))
            trend_scores.append(metadata.get("trend_score", 0.5))
            volatility_scores.append(metadata.get("volatility_score", 0.5))
            volume_scores.append(metadata.get("volume_score", 0.5))

        import numpy as np
        momentum_score = np.mean(momentum_scores)
        trend_score = np.mean(trend_scores)
        volatility_score = np.mean(volatility_scores)
        volume_score = np.mean(volume_scores)
        technical_score = np.mean([s.confidence for s in signal_events])

        return self.calculate_conviction(
            technical_score=technical_score,
            momentum_score=momentum_score,
            trend_score=trend_score,
            volatility_score=volatility_score,
            volume_score=volume_score,
        )
```

---

### 5. Module-Level Pure Function

A standalone function wraps the engine for callers who have a pre-built engine instance.

```python
def calculate_conviction_score(
    technical: float,
    momentum: float,
    trend: float,
    volatility: float,
    volume: float,
    engine: ConvictionEngine,
) -> ConvictionScore:
    """Calculate conviction score using provided engine - pure function."""
    return engine.calculate_conviction(
        technical_score=technical,
        momentum_score=momentum,
        trend_score=trend,
        volatility_score=volatility,
        volume_score=volume,
    )
```

---

## Code Examples

### Engine Setup and Single Signal Scoring

```python
from apex.signals.conviction import ConvictionEngine
from apex.core.models import SignalEvent, SignalType

# Create engine - raises immediately if weights don't sum to 1.0
engine = ConvictionEngine(
    minimum_entry=0.7,
    minimum_exit=0.5,
    momentum_weight=0.3,
    trend_weight=0.3,
    volatility_weight=0.2,
    volume_weight=0.2,
)

# Signal with metadata scores
signal = SignalEvent(
    symbol="BTC/USDT",
    signal_type=SignalType.LONG,
    confidence=0.82,
    price=65_000.0,
    timeframe="1h",
    metadata={
        "momentum_score": 0.75,
        "trend_score": 0.80,
        "volatility_score": 0.60,
        "volume_score": 0.70,
    },
)

score = engine.score_signal_event(signal)

# Decision gate
if engine.should_enter(score):
    print(f"Enter long — conviction: {score.overall:.2f}")
else:
    print(f"Skip — conviction too low: {score.overall:.2f}")
```

### Direct Score Calculation

```python
score = engine.calculate_conviction(
    technical_score=0.80,
    momentum_score=0.75,
    trend_score=0.80,
    volatility_score=0.60,
    volume_score=0.70,
)

# technical = 0.3*0.75 + 0.3*0.80 + 0.2*0.60 + 0.2*0.70
#           = 0.225 + 0.24 + 0.12 + 0.14 = 0.725
print(score.overall)    # 0.725
print(score.technical)  # 0.725
```

### Batch Scoring from Multiple Signals

```python
signals = [signal_1, signal_2, signal_3]  # Each with metadata scores
combined_score = engine.calculate_conviction_from_signals(signals)
print(f"Aggregate conviction: {combined_score.overall:.3f}")
```

---

## When to Use Conviction vs Raw Signals

| Use case | Recommendation |
|---|---|
| Single indicator trigger | Raw signal confidence |
| Multi-indicator confluence | Conviction scoring |
| Entry/exit threshold decisions | `should_enter()` / `should_exit()` |
| Comparing signals across strategies | Normalized conviction score |
| Backtesting entry quality | Record conviction at entry |

---

## Philosophy Checklist

- **Early Exit**: Weight validation and score range validation run at the top of their respective methods
- **Parse Don't Validate**: Scores in `[0, 1]` are checked once at `calculate_conviction()`; `ConvictionScore` model then trusts them
- **Atomic Predictability**: All scoring functions are pure — same inputs always produce the same `ConvictionScore`
- **Fail Fast**: Invalid weights halt engine construction; out-of-range scores halt calculation; empty signal list raises
- **Intentional Naming**: `should_enter`, `should_exit`, `score_signal_event`, `calculate_conviction_from_signals` — reads like a decision flow

---

## Constraints

### MUST DO
- Include at least one BAD/GOOD code example pair
- Reference a relevant standard (OWASP, SOLID, DRY, KISS, etc.)
- Use type hints on all function signatures

### MUST NOT DO
- Use magic numbers or hardcoded configuration values
- Bypass error handling for assumed-valid inputs
- Write functions longer than 50 lines without decomposition

## Live References

> Authoritative documentation links for this domain. The model follows markdown links at load time to resolve external references and inline content.

- [Technical Analysis Indicators Reference (Investopedia)](https://www.investopedia.com/terms/t/technical-indicators.asp) — Investopedia's comprehensive reference on technical indicators used in conviction scoring
- [Machine Learning for Financial Forecasting (Goodfellow et al.)](https://www.deeplearningbook.org/) — Goodfellow's Deep Learning textbook with chapters on time series prediction and feature engineering
- [Weighted Scoring Models (Project Management Institute)](https://www.pmi.org/) — PMI standards for multi-factor decision scoring applicable to conviction system design
- [Signal Processing for Trading Systems (Ernest Chan)](https://epchan.blogspot.com/) — Ernest Chan's blog on quantitative trading signals and signal processing techniques
- [Ensemble Learning Methods (scikit-learn)](https://scikit-learn.org/stable/modules/ensemble.html) — scikit-learn's ensemble methods for combining multiple prediction signals

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…