Documentação
Fluxo de Dados e Decisões de Projeto
Este documento apresenta o fluxo completo da solução: de onde os dados nascem, por quais camadas de código passam, como são persistidos, como o modelo é treinado e como as previsões são consumidas na interface.
1) Aquisição de dados (Binance → API Python)
- Ponto de entrada (FastAPI):
routers/ingest.py(POST/ingest)- Responsável por iniciar a cadeia de ingestão: chama os serviços de obtenção e persistência.
- Serviço de ingestão:
services/ingestion_service.pyfetch_binance_klines(...)→ Faz requisição REST à Binance (/api/v3/klines) usandorequestscomsymbol,intervalelimitvindos de variáveis de ambiente (vercore/config.py).normalize_klines_payload(...)→ Converte o payload para DataFrame com colunas padronizadas[time, open, high, low, close, volume], ordena por tempo e remove campos não utilizados.upsert_candles(df)→ Insere no PostgreSQL (tabelabtc_candles) comINSERT ... ON CONFLICT (time) DO NOTHING, garantindo idempotência.
2) Persistência (PostgreSQL)
- Tabela
btc_candles(time, open, high, low, close, volume)→ Série OHLCV “limpa” para consumo por treino e previsões. - Tabela
job_logs(...)→ Registro de execução, métricas e mensagens de auditoria. - Tabela
futures(time, pred_close, real_close, err_close)→ Série prospectiva: previsões feitas em t−1 comparadas com o real em t (sem retro-preencher passado).
3) Janela e features (engenharia de atributos)
- Arquivo:
ml/features.py- Deriva features a partir de OHLCV (ex.:
ret,acc,amp,vol_rel) e targets (open_next,high_next,low_next,close_next,amp_next, edir_next). - Retorna DataFrame alinhado (descarta
NaNdecorrente deshift) pronto para treino/previsão.
- Deriva features a partir de OHLCV (ex.:
- Decisão: features simples e interpretáveis para um horizonte curto (5 min).
vol_relnormaliza volume;ampcaptura volatilidade local.
4) Treinamento (modelo e avaliação)
- Ponto de entrada (FastAPI):
routers/train.py(POST/train) - Serviço:
services/training_service.py- Carrega janela temporal (configurável por
LOOKBACK_DAYS). build_features_targets(df)para obterX(features),Yreg(targets contínuos) eYcls(direção).- Monta sequências para alimentar o LSTM (
lstm_seq_len), preservando a ordem temporal. - Split temporal 80/20 (sem embaralhar), limitando validação mínima (até 500 amostras) para estabilidade.
- Treino: LSTM (TensorFlow/Keras) com duas saídas:
- Regressão multi-saída (open/high/low/close/amp do t+1)
- Classificação direcional (prob_up/prob_down em t+1)
- Usa EarlyStopping + checkpoint e exporta modelo + scalers/metadados para o volume.
- Métricas no conjunto de validação (out-of-sample): MAE, MAPE, SMAPE (em
close_next). - Persistência dos modelos (via
joblib) e log das métricas (job_logs).
- Carrega janela temporal (configurável por
- Decisão: split temporal para evitar “vazamento temporal”; LSTM multi-saída mantém consistência entre os alvos e simplifica o deploy.
4.1 Sequências (SEQ_LEN) — interpretação prática
- O LSTM não recebe “um candle”; ele recebe uma janela de tamanho
SEQ_LEN. - No projeto,
SEQ_LEN=48significa ~4 horas de histórico (48 candles × 5 min) para prever o próximo candle.
4.2 Normalização (scalers) — por que e como
- Redes neurais treinam melhor quando as variáveis estão em escalas semelhantes.
- No treino:
scaler_xé ajustado (fit) apenas no conjunto de treino e aplicado em treino/validação.scaler_yé ajustado (fit) apenas no treino para os alvos de regressão.
- Isso evita “vazamento” estatístico do futuro para o passado.
4.3 EarlyStopping e checkpoint (quantas épocas o treino roda)
- O treino usa EarlyStopping monitorando
val_loss: se não houver melhora porpatienceépocas, interrompe e restaura os melhores pesos. - Um ModelCheckpoint salva o “melhor modelo” (menor
val_loss) durante o treino.
4.4 Artefatos salvos (para inferência consistente)
Após treinar, a aplicação salva (em volume) artefatos para que inferência use a mesma preparação do treino:
api/models/lstm_model.keras: modelo treinadoapi/models/lstm_bundle.joblib: bundle comscaler_x,scaler_y, colunas de features/targets,seq_lene metadados necessários
5) Previsões em série (histórico + t→t+1)
- Ponto de entrada (FastAPI):
routers/series.py(GET/series) - Serviço:
services/prediction_service.py- Carrega
btc_candles(intervalo pedido ou janela padrão), monta features e carrega modelos salvos. - Para cada linha i, prevê o próximo candle (i+1) e calcula erro relativo ao
closereal (quando disponível). - Entrega uma lista de pontos contendo:
real(OHLCV),pred(targets i+1),cls(direção/probabilidades) eerr.
- Carrega
- Decisão: alinhar previsão i→(i+1) para refletir “uso real” e facilitar construção de gráficos consistentes.
6) Série prospectiva “Futuros” (avaliação contínua)
- Pontos de entrada (FastAPI):
routers/futures.py- POST
/futures/update→ Atualiza a linha prospectiva do último timestamp disponível (t). - GET
/futures→ Retorna a série prospectiva para análise (pred vs real vs erro).
- POST
- Serviço:
services/futures_service.py- Garante que a previsão armazenada para o tempo t foi de fato gerada em t−1 (mapeando
time_next → idx_prev). - Evita retro-preencher histórico: apenas timestamps prospectivos.
- Garante que a previsão armazenada para o tempo t foi de fato gerada em t−1 (mapeando
- Decisão: separar avaliação “on-line” de validação (split 80/20) para ter duas visões: robustez histórica e desempenho recente/operacional.
7) Métricas públicas (para UI)
- Ponto de entrada (FastAPI):
routers/metrics.py(GET/metrics)- Extrai do último
job_logsde treino as métricas e reconstruções auxiliares (início da validação) para sombreamento no front.
- Extrai do último
- Decisão: manter a UI independente da lógica de treino; a API expõe métrica consolidada, e a UI apenas consome.
8) Apresentação (Site ASP.NET Core 9.0)
- Camada de UI:
site/Views/Charts/Index.cshtml- Busca
/series,/metrics,/futurese constrói gráficos (ECharts) com OHLC, close, erro%, volume, futuros e direção. - Sombreamento da região de validação: ajuda leitura das métricas em contexto.
- Spinners de loading simples: exibidos até as séries serem carregadas.
- Busca
- Documentação:
DocsController+MarkdownServicerenderizando.md(Docs); Swagger da API Python embutido em view dedicada. - Jobs (Quartz.NET):
IngestJob,TrainDailyJob,TrainDriftJobeBackfillJobdisparam periodicamente os endpoints Python. - Decisão: separar visualização (site) de processamento (API) simplifica implantação e escalabilidade.
9) Orquestração e Configuração
- Docker Compose: sobe
db(Postgres),pyapi(FastAPI),site(ASP.NET Core) eadminer. - Variáveis de ambiente: senhas e endpoints são lidos de
.envna raiz (não versionado). O site injeta aConnectionStrings__DefaultConnectionpor env var. - Volumes:
./api/modelspara persistir artefatos do modelo entre reinícios. - Decisão: compose simplifica dev/ops;
.envevita segredos em repositório; healthchecks garantem dependências.
9.0.1 Diferença entre /series, /series/cached e a tabela series_cache
GET /series: calcula a série on-demand (útil para debugging e comparação).GET /series/cached: retorna a série pronta a partir da tabela materializadaseries_cache(mais rápido para a UI).POST /series/rebuild: (re)materializaseries_cacheapós um treino, garantindo que os gráficos carreguem rápido.
9.1 Política de retreino (produção) — Opção C (Quartz)
A policy de retreino fica no Quartz (.NET):
- Treino diário fixo (
TrainDailyJob): chamaPOST /trainePOST /series/rebuild. - Checagem de drift (
TrainDriftJob): roda periodicamente e treina somente se:- passou >=
TrainMinHoursdesde o último treino e MAPE(rolling)emfutures>=FuturesMapeThreshold(calculado sobre os últimosFuturesRollingNpontos).
- passou >=
Configuração (sem UI) em site/appsettings.json (seção PythonApi).
10) Considerações de Design
- Temporal split (80/20) ao invés de K-fold: evita vazamento de futuro e reflete uso em produção.
- Modelo único (LSTM multi-saída): prevê múltiplos alvos do próximo candle e também uma probabilidade direcional (head de classificação).
- WDA e avaliação prospectiva: métricas direcionais complementam MAPE/SMAPE (nível) e aproximam utilidade econômica.
- Postgres: SQL padrão, consultas simples, integrável a Adminer; bom equilibrio entre robustez e praticidade.
- ECharts: controle fino de séries temporais, performance aceitável, conectividade de zoom/pan.
11) Caminhos no Código (resumo)
- Aquisição e ingestão:
api/services/ingestion_service.py←api/routers/ingest.py - Features/targets:
api/ml/features.py - Treino:
api/services/training_service.py←api/routers/train.py - Previsões de série:
api/services/prediction_service.py←api/routers/series.py - Futuros (prospectivo):
api/services/futures_service.py←api/routers/futures.py - Métricas:
api/routers/metrics.py - UI (gráficos):
site/Views/Charts/Index.cshtml - Jobs:
site/Jobs/*.cs - Config/env:
api/core/config.py,.env(raiz),docker-compose.yml