Motor de classificação inteligente de linhas de extrato bancário com suporte a PyOdide.
fin-classifier é uma biblioteca Python que fornece um sistema flexível e extensível para classificar transações bancárias, encontradas usualmente em extratos bancários e demonstrativos de caixa, baseado em regras customizáveis. Pode ser usado para categorizar linhas de extratos de forma automática e inteligente.
- Baseado em Regras: Defina regras de classificação usando uma DSL intuitiva
- Operadores Lógicos: Combine condições com AND (&), OR (|) e NOT (~)
- Condições Flexíveis: Suporte para condições de texto e valor
- Sem Dependências: Compatível com PyOdide, sem dependências externas
- Type-safe: Desenvolvido com type hints completos
- Well-tested: Cobertura de testes abrangente
pip install fin-classifierpip install git+https://github.com/tpougy/fin-classifier.gitpip install fin-classifier[dev]from extrato_classifier import BaseClassifier, Rule, Text, Amount, Transaction
class MinhaClassificacao(BaseClassifier):
"""Defina um classificador herdando de BaseClassifier"""
# Regra 1: Rendimentos
__salario = Rule(
Text.contains("salario") & Amount.positive()
)
# Regra 2: Despesas
__despesa = Rule(
Text.contains("despesa", "custo") & Amount.negative()
)
# Regra fallback (deve ser a última)
__outros = Rule()
# Classifique uma transação
trans = Transaction("Salário Mensal", 5000.00)
resultado = MinhaClassificacao.classify(trans)
print(resultado) # Output: salario (prioridade: 0, regra: salario)Verifica se o texto contém TODOS os termos (AND lógico).
condition = Text.contains("banco", "brasil")
# Matches: "Banco do Brasil"
# Not matches: "Banco Itau"Verifica se o texto contém QUALQUER um dos termos (OR lógico).
condition = Text.any_of("cri", "deb", "lci")
# Matches: "Rendimento CRI"
# Matches: "DEB ABC"Verifica se o texto começa com algum dos termos.
condition = Text.starts_with("pix", "ted")
# Matches: "PIX para João"
# Not matches: "Transferência PIX"Verifica se o texto termina com algum dos termos.
condition = Text.ends_with("mensais", "anuais")
# Matches: "Juros Mensais"Verifica se o texto é exatamente igual a algum dos termos.
condition = Text.equals("pix")
# Matches: "PIX"
# Not matches: "PIX para João"condition = Amount.gt(100)condition = Amount.lt(100)condition = Amount.gte(100)condition = Amount.lte(100)condition = Amount.eq(100, tolerance=0.01)condition = Amount.between(100, 1000)condition = Amount.positive() # > 0condition = Amount.negative() # < 0# AND (&)
condition = Text.contains("banco") & Amount.positive()
# OR (|)
condition = Text.contains("banco") | Text.contains("caixa")
# NOT (~)
condition = ~Text.contains("custodia")
# Composição complexa
condition = (
(Text.any_of("cri", "deb") | Text.contains("tesouro"))
& Amount.positive()
& ~Text.contains("provisao")
)transactions = [
Transaction("Salário", 5000.00),
Transaction("Despesa", -100.00),
Transaction("Outro", 50.00),
]
resultados = MinhaClassificacao.classify_batch(transactions)
for resultado in resultados:
print(resultado)# Obter todas as regras
regras = MinhaClassificacao.get_rules()
# Obter descrição detalhada das regras
print(MinhaClassificacao.describe_rules())fin-classifier/
├── src/
│ └── classifier/
│ ├── __init__.py
│ ├── classifier.py # BaseClassifier e Rule
│ ├── models.py # Transaction e ClassificationResult
│ └── conditions.py # Condições de texto e valor
├── tests/
│ ├── conftest.py # Fixtures compartilhadas
│ ├── unit/ # Testes unitários
│ ├── integration/ # Testes de integração
│ └── __init__.py
├── pyproject.toml
├── pytest.ini
└── README.md
uv add --group dev pytest-xdist pytest-cov pytest-mock pytest-benchmark ruff mypy blackpytest # Todos os testes
pytest -m unit # Apenas unitários
pytest -m integration # Apenas integração
pytest -v # Verbose
pytest --cov=src # Com cobertura
pytest -n auto # Paralelo (xdist)pytest --cov=src --cov-report=html
# Abrir htmlcov/index.htmlruff format src tests
ruff check --fix src teststy srcEsta biblioteca é totalmente compatível com PyOdide, permitindo usar classificação financeira diretamente no excel com xlwings lite.
<script
defer
src="https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js"
></script>
<script>
async function main() {
let pyodide = await loadPyodide();
await pyodide.loadPackage("fin-classifier");
pyodide.runPython(`
from extrato_classifier import BaseClassifier, Rule, Text, Amount, Transaction
# ... seu código aqui
`);
}
main();
</script>from extrato_classifier import BaseClassifier, Rule, Text, Amount, Transaction
class ClassificadorExtrato(BaseClassifier):
"""Classificador para extratos de investimentos"""
# Ativos de Renda Fixa - Juros
__ativo_juros = Rule(
Text.any_of("cri", "deb", "lci", "lca")
& Text.contains("juros")
& Amount.positive()
)
# Ativos de Renda Fixa - Amortização
__ativo_amort = Rule(
Text.any_of("cri", "deb", "lci", "lca")
& Text.contains("amort")
& Amount.positive()
)
# Tesouro Direto
__tesouro_direto = Rule(
Text.contains("tesouro", "direto")
& Amount.positive()
)
# Dividendos
__dividendos = Rule(
Text.any_of("dividendo", "jcp", "jscp")
& Amount.positive()
)
# Despesas Operacionais
__despesas = Rule(
Text.contains("custo")
& ~Text.any_of("custodia", "oferta")
& Amount.negative()
)
# Taxas e Impostos
__taxas_impostos = Rule(
Text.any_of("taxa", "imposto", "ir", "iof")
& Amount.negative()
)
# Fallback
__outros = Rule()
# Uso
trans = Transaction("Rendimento CRI XPTO Juros Mensais", 150.50)
resultado = ClassificadorExtrato.classify(trans)
print(resultado)MIT
- Autor: Thomaz Pougy
- Email: thomazpougy@gmail.com