Motor de classificação inteligente de linhas de extrato bancário com suporte a PyOdide
Project description
Fin Classifier
Motor de classificação inteligente de linhas de extrato bancário com suporte a PyOdide.
Descrição
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.
Características
- 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
Instalação
Do PyPI
pip install fin-classifier
Do repositório
pip install git+https://github.com/tpougy/fin-classifier.git
Com dependências de desenvolvimento
pip install fin-classifier[dev]
Uso Rápido
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)
Condições de Texto
Text.contains(*terms, case_sensitive=False)
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"
Text.any_of(*terms, case_sensitive=False)
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"
Text.starts_with(*terms, case_sensitive=False)
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"
Text.ends_with(*terms, case_sensitive=False)
Verifica se o texto termina com algum dos termos.
condition = Text.ends_with("mensais", "anuais")
# Matches: "Juros Mensais"
Text.equals(*terms, case_sensitive=False)
Verifica se o texto é exatamente igual a algum dos termos.
condition = Text.equals("pix")
# Matches: "PIX"
# Not matches: "PIX para João"
Condições de Valor
Amount.gt(value) - Maior que
condition = Amount.gt(100)
Amount.lt(value) - Menor que
condition = Amount.lt(100)
Amount.gte(value) - Maior ou igual
condition = Amount.gte(100)
Amount.lte(value) - Menor ou igual
condition = Amount.lte(100)
Amount.eq(value, tolerance=0.01) - Igual
condition = Amount.eq(100, tolerance=0.01)
Amount.between(min_value, max_value) - Entre
condition = Amount.between(100, 1000)
Amount.positive() - Positivo
condition = Amount.positive() # > 0
Amount.negative() - Negativo
condition = Amount.negative() # < 0
Operadores Lógicos
# 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")
)
Classificação em Lote
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)
Inspecionando Regras
# Obter todas as regras
regras = MinhaClassificacao.get_rules()
# Obter descrição detalhada das regras
print(MinhaClassificacao.describe_rules())
Estrutura do Projeto
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
Desenvolvimento
Instalar dependências de desenvolvimento
uv add --group dev pytest-xdist pytest-cov pytest-mock pytest-benchmark ruff mypy black
Executar testes
pytest # 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)
Verificar cobertura de testes
pytest --cov=src --cov-report=html
# Abrir htmlcov/index.html
Formatar código
ruff format src tests
ruff check --fix src tests
Type checking
ty src
Compatibilidade com PyOdide
Esta 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>
Exemplos Avançados
Classificador de Extratos Bancários
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)
Licença
MIT
Contato
- Autor: Thomaz Pougy
- Email: thomazpougy@gmail.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fin_classifier-0.1.2.tar.gz.
File metadata
- Download URL: fin_classifier-0.1.2.tar.gz
- Upload date:
- Size: 54.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
278416d06d74fb1fde4ed2240e105158229e78262159715190ef4f08b9245237
|
|
| MD5 |
3af16dcba1a4cbd520030bcb37b0dc47
|
|
| BLAKE2b-256 |
888070899c8e281ef7e1b4822f38900e5b494b36a24cf74a48e8c9fe3e19534f
|
File details
Details for the file fin_classifier-0.1.2-py3-none-any.whl.
File metadata
- Download URL: fin_classifier-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0971add1284a53b9c570659699f44eeafe973407a27573c69d5ab7fec518d36a
|
|
| MD5 |
cc927413ae83a9bf31def3fe0d533bf2
|
|
| BLAKE2b-256 |
7e9f79a72e5a907933a812550a66463dbb6a2f442ee6f36e3e58182497d880c5
|