---
title: "FFT spectral anomaly detection in Brazilian federal contracts"
description: "Brazil's transparency portal exposes millions of federal contracts. Classical outlier detection drowns in multi-modal distributions. FFT decomposes the time series into frequencies — and serial fraud leaves periodic signatures. How Cidadão.AI uses spectral entropy to reduce an ocean to hundreds of candidates."
author: "Anderson Henrique"
date: "2026-05-03T16:45:00Z"
updated: "2026-05-12T16:16:39.244294Z"
category: "technical"
tags: ["anomaly-detection","fft","spectral-analysis","government-transparency","cidadao-ai","python","signal-processing"]
canonical: "https://www.ntlabs.dev/en/blog/fft-spectral-anomaly-government-contracts"
locale: "en"
---

# FFT spectral anomaly detection in Brazilian federal contracts

Brazil's federal transparency portal (Portal da Transparência) exposes millions of public contracts. Finding overpricing, vendor steering, or fictitious contracts in that ocean is not a visualization problem — it is a search problem. And classical outlier detection methods fail for a specific reason: the distribution is multi-modal.

## Why z-score and IQR fall short

Take IT contracts per agency. The distribution has three obvious modes: emergency purchases (high value, short term), full bidding (medium value, long term), and low-value waiver (low value, high frequency). An R$ 500K emergency contract registers as an outlier in a global z-score, but it is completely legitimate in the context of "environmental emergency". Conversely, ten R$ 50K contracts spread across five agencies over three months trigger no alarm in point statistics — but if they go to the same company on an exact monthly cycle, they have a scheme signature.

The right question is not "is this value high?". It is "does this temporal pattern occur naturally?".

## The FFT intuition

Any time series can be decomposed into frequencies. The FFT (Fast Fourier Transform) does this in O(n log n). The result is a spectrum: amplitude per frequency.

Applied to public contracts, this answers an operational question: is there periodicity not explained by the nature of the service?

Payroll has periodicity — monthly, obvious, expected. Office supplies have periodicity — quarterly, aligned with budget. But a "strategic consulting" contract that pulses every 28 days to the same vendor, across three different agencies? That is a signature.

## Spectral entropy as a score

The FFT returns an amplitude vector. To turn this into an actionable score, we compute Shannon entropy over the normalized spectrum:

```python
import numpy as np
from scipy.fft import fft

def spectral_entropy(series: np.ndarray) -> float:
    spectrum = np.abs(fft(series - series.mean()))[: len(series) // 2]
    if spectrum.sum() == 0:
        return 0.0
    psd = spectrum / spectrum.sum()  # normalize to probability distribution
    psd = psd[psd > 0]  # avoid log(0)
    return float(-np.sum(psd * np.log2(psd)))
```

High entropy = energy distributed across many frequencies = natural noise, legitimate contracts with real variation. Low entropy = energy concentrated in few frequencies = strong periodic pattern = anomaly candidate.

The threshold is not universal. For payroll, low entropy is expected. For consulting contracts, it is a red flag. The agent carries a baseline table per expense nature/category and compares against it.

## In production, in Cidadão.AI

The Zumbi agent (named after Zumbi dos Palmares, a key figure in Brazilian abolitionist history) consumes time series per (agency, vendor, category) extracted from federal APIs. For each series with at least 12 points, it computes spectral entropy, normalizes against the category baseline, and assigns a score from 0 to 1.

Top-K results (typically top 100 per day) enter a review queue. This is not autonomous detection — it is search reduction. An auditor who previously had to scan 50K contracts per month now looks at 100 prioritized by spectral signature.

## The false positives that matter

Two adjustments dramatically reduced initial noise:

1. **Whitelist of seasonal natures.** Payroll (always periodic), rent (always periodic), electricity (always periodic). The baseline for these expense categories already expects low entropy. Not a signal.

2. **Minimum window.** Series with fewer than 12 contracts have unstable FFT. The agent ignores short history and waits for more data. This cut alerts for new vendors, which had 80% of false positives.

## What this does not solve

Spectral analysis finds periodic patterns, not causality. A contract can have a fraud signature and be legitimate — the client is a university restaurant buying ingredients on a fixed menu cycle. The final decision is human, with context. The system is a filter, not a judge.

And there are entire classes of fraud this approach does not catch: single high-value contracts (needs other heuristics), splitting across distinct agencies without periodicity (needs graph analysis), horizontal collusion between vendors (needs network analysis). Spectral FFT is a specific blade for a specific cut.

## Why it is worth it

Fraud detection at scale is not a single-model problem. It is a pipeline of successive filters, each discarding a different class of "this is normal". Spectral entropy is the filter that reduces temporal pattern to a number. The number is not the answer — it is the doorway to the next question.
