Skip to main content
Glama
cesarscf

albion-market-ia

by cesarscf
README.md
# Albion Market IA — Detector de Lucro em Compra → Transporte → Refino

[![CI](https://github.com/cesarscf/albion-market-ia/actions/workflows/ci.yml/badge.svg)](https://github.com/cesarscf/albion-market-ia/actions/workflows/ci.yml)

**[Baixar](https://github.com/cesarscf/albion-market-ia/releases/latest)** — Windows, macOS e Linux.

> Documento de concepção. Pesquisa validada em 08/09/2026 com chamadas reais à API do AODP
> e extração direta do `items.json` do `ao-bin-dumps`.

---

## 1. Problema

Descobrir, **agora**, quais itens do Albion Online dão mais lucro no ciclo:

```
comprar raw (cidade A) → transportar (cidade B) → refinar → vender (cidade C)
```

O gargalo não é o cálculo — é ter **preço real e fresco** por cidade, e modelar corretamente
tudo que a API *não* entrega (return rate, taxas de estação, impostos, peso, risco de rota).

---

## Como rodar

Requer Node 22.5+ (usa o `node:sqlite` embutido, sem dependência nativa) e pnpm.

```bash
pnpm install
pnpm sync:catalog                      # baixa receitas e pesos do ao-bin-dumps
pnpm dev                               # API + app web em http://localhost:5183
```

O servidor mantém os preços atualizados sozinho: um poller REST a cada 5 minutos
e o feed NATS ao vivo do AODP. `ALBION_POLL=off` e `ALBION_NATS=off` desligam.

Também dá para usar só pelo terminal:

```bash
pnpm poll                              # uma coleta manual
pnpm opps "Fort Sterling" 2000000      # ranqueia rotas para essa cidade e capital
```

Estado fica em `~/.albion-market/market.sqlite` (mude com `ALBION_HOME`).
Servidor padrão é o `west`; troque com `ALBION_SERVER=east|europe`.

```bash
pnpm -r test         # 31 testes
pnpm -r typecheck
```

### App desktop

Pronto para instalar em [Releases](https://github.com/cesarscf/albion-market-ia/releases/latest),
ou para rodar do código:

```bash
pnpm dev:desktop     # abre a janela do Electron
pnpm dist:desktop    # gera o instalador da plataforma atual
```

Windows, macOS e Linux, sem dependência nativa. Detalhes em
[docs/user/desktop.md](./docs/user/desktop.md).

### Usar dentro da sua IA

```bash
pnpm mcp             # servidor MCP no stdio
```

Registre em Claude Code, Codex, Cursor ou OpenCode e pergunte
*"o que compensa refinar agora estando em Lymhurst com 2M?"* usando a assinatura
que você já tem. Passo a passo em [docs/user/mcp.md](./docs/user/mcp.md).

---

> **Arquitetura técnica:** ver [ARCHITECTURE.md](./ARCHITECTURE.md) — stack, estrutura de pastas,
> contrato, tema e o mecanismo de "use qualquer IA", inspirados no [t3code](https://github.com/pingdotgg/t3code).

---

## 2. De onde vêm os dados

**Não existe API oficial de mercado da Sandbox Interactive.** O `gameinfo.albiononline.com`
só expõe PvP/guildas/players. Todo app de preço (AlbionOnline2D, Albion Free Market,
AlbionCodex, calculadoras diversas) consome a **mesma fonte**: o
**Albion Online Data Project (AODP)**.

### Como o AODP funciona

1. O jogador roda um **data client** (`albiondata-client` oficial, ou o **AFM Data Client**,
   que tem versão Android).
2. O client escuta pacotes UDP do jogo via libpcap. **Não modifica o cliente do jogo** —
   por isso é tolerado pela SBI.
3. Quando o jogador abre a aba de Mercado / Casa de Leilões numa cidade, o client parseia
   as ordens e publica num servidor **NATS** central.
4. O NATS deduplica (janela de 10 min) e alimenta o banco que expõe a **API REST pública**.

> **Consequência crítica:** o preço só existe se algum jogador abriu aquela aba recentemente.
> Não é um feed do servidor do jogo. Frescor é função do tráfego de jogadores.

---

## 3. As três fontes obrigatórias

### 3.1. API REST do AODP — preço atual e histórico

| Servidor | Base URL |
|---|---|
| Americas (West) | `https://west.albion-online-data.com` |
| Asia (East) | `https://east.albion-online-data.com` |
| Europe | `https://europe.albion-online-data.com` |

```
/api/v2/stats/prices/{ids}.json?locations=Caerleon,Martlock&qualities=1
/api/v2/stats/history/{ids}.json?date=...&end_date=...&locations=...&time-scale=24
/api/v2/stats/charts/{ids}.json?...&time-scale=6
/api/v2/stats/gold.json?count=24
```

- `time-scale`: `1` horário · `6` 6h · `24` diário
- `qualities`: 1 Normal · 2 Bom · 3 Excepcional · 4 Excelente · 5 Obra-prima
- **Rate limit: 180 req/min e 300 req/5min**
- **URL máx 4096 chars** → empacote ~100 item IDs por chamada. Use gzip.

Resposta real (T4_PLANKS, servidor West, 08/09/2026):

```json
{"item_id":"T4_PLANKS","city":"Fort Sterling","quality":1,
 "sell_price_min":295,"sell_price_min_date":"2026-09-08T17:25:00",
 "sell_price_max":328,"sell_price_max_date":"2026-09-08T17:25:00",
 "buy_price_min":2,"buy_price_min_date":"2026-09-08T17:25:00",
 "buy_price_max":253,"buy_price_max_date":"2026-09-08T17:25:00"}
```

**O campo que separa app amador de app bom é o `*_date`.** Na mesma chamada:
- Martlock veio com timestamp de **ontem**
- Caerleon veio com `sell_price_min: 580` e `sell_price_max: 13292` — outlier puro
- `T6_PLANKS` na Black Market e em Brecilien voltou **tudo zero** (sem dado)

Semântica dos campos:
- `sell_price_min` → menor **sell order** = preço de **compra instantânea**
- `buy_price_max` → maior **buy order** = preço de **venda instantânea**

### 3.2. Stream NATS — tempo real (push, sem polling)

```
nats://public:thenewalbiondata@nats.albion-online-data.com:4222
```

Tópicos: `marketorders.deduped` · `markethistories.deduped` · `goldprices.deduped`

Mesmo dado da API REST, porém push: você recebe a ordem no instante em que qualquer
jogador do mundo abre aquele mercado.

### 3.3. `ao-bin-dumps` — metadados do jogo (fonte autoritativa)

Repo `ao-data/ao-bin-dumps`, arquivo `items.json` (~17 MB). Contém receitas, pesos,
`itemvalue` e custo de foco. Extraído diretamente:

```json
"T6_PLANKS": {
  "@itemvalue": "64", "@weight": "1.14", "@fasttravelfactor": "8",
  "craftingrequirements": [{
    "@craftingfocus": "164", "@amountcrafted": "1",
    "craftresource": [ {"T6_WOOD": 4}, {"T5_PLANKS": 1} ]
  }]
}
```

**Receitas de refino** (confirmadas no dump):

| Tier | Raw | Refinado (T-1) |
|---|---|---|
| T4 | 2 | 1 |
| T5 | 3 | 1 |
| T6 | 4 | 1 |
| T7 | 5 | 1 |
| T8 | 5 | 1 |

Detalhe que quase nenhum calculador considera: existe uma **receita alternativa com
Faction Token** que troca 1 raw por 1 token de facção.

---

## 4. O que a API NÃO dá — a matemática do lucro

### 4.1. Resource Return Rate (RRR)

```
RRR = b / (1 + b)      // b = soma ADITIVA dos bônus
```

| Situação | b | RRR |
|---|---|---|
| Cidade sem bônus | 0,18 | **15,3%** |
| Cidade com bônus de refino (+40%) | 0,58 | **36,7%** |
| Cidade com bônus + foco (+59%) | 1,17 | **53,9%** |
| Cidade com bônus + foco + dia de ouro (+20%) | 1,37 | **57,8%** |

Consumo real de material = `nominal × (1 − RRR)`.
Com 53,9% de RRR você consome só ~46% dos materiais nominais.

> **Especialização não aumenta RRR** — ela reduz o custo de foco (Focus Cost Efficiency).

### 4.2. Cidades de bônus de refino

| Raw | Refinado | Cidade |
|---|---|---|
| Minério (Ore) | Barra (Metal Bar) | **Thetford** |
| Couro cru (Hide) | Couro (Leather) | **Martlock** |
| Fibra (Fiber) | Tecido (Cloth) | **Lymhurst** |
| Madeira (Wood) | Tábua (Plank) | **Fort Sterling** |
| Pedra (Stone) | Bloco (Stone Block) | **Bridgewatch** |

### 4.3. Taxa da estação de refino

```
taxa_por_unidade = itemvalue × 0,1125 × (taxa_por_100_nutricao / 100)
```

Ex.: T6_PLANKS (`itemvalue` 64) numa estação a 300 → `64 × 0,1125 × 3 = 21,6` prata/unidade.

`itemvalue` dobra por tier: T4=16 · T5=32 · T6=64 · T7=128 · T8=256.

### 4.4. Taxas de mercado

| Ação | Custo |
|---|---|
| Criar/atualizar ordem (setup fee) | **2,5%** — perdido mesmo se não vender |
| Imposto na venda (sem Premium) | **8%** |
| Imposto na venda (com Premium) | **4%** |

Venda instantânea (bater na buy order) não paga setup fee, só o imposto.

### 4.5. Transporte

- `@weight` do dump × capacidade da montaria → quantos ciclos de viagem
- `@fasttravelfactor` → custo de fast travel
- Rota para Caerleon atravessa red zone → o modelo precisa de **fator de risco**

---

## 5. Arquitetura proposta

> **Regra de ouro: o LLM não calcula.** Ele erra aritmética e alucina preço.
> A IA é camada de *interface e interpretação*, nunca de cálculo.

```
┌─────────────────────────────────────────────────────────────┐
│  CAMADA 1 — INGESTÃO                                        │
│  • Data client próprio (AFM/oficial) rodando local          │
│  • Subscriber NATS (marketorders.deduped)                   │
│  • Poller REST em batch (~100 ids/req) p/ cidades não visit.│
│  • Sync periódico do ao-bin-dumps/items.json                │
│         ↓ Postgres + TimescaleDB                            │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│  CAMADA 2 — MOTOR DETERMINÍSTICO                            │
│  Input: cidade_atual, capital, capacidade_peso,             │
│         tem_premium, tem_foco, tolerancia_risco             │
│  Loop: família × tier × cidade_compra × cidade_refino ×     │
│        cidade_venda                                          │
│  Aplica: RRR · receita · taxa estação · impostos · peso     │
│  Output: ranking com margem abs, margem %, capital travado, │
│          idade_do_dado_min, liquidez estimada               │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│  CAMADA 3 — LLM (tool / function calling)                   │
│  Recebe o top-N já calculado. Faz o que ele faz bem:        │
│  • interpretar intenção em linguagem natural                │
│  • filtrar por contexto que não cabe em SQL                 │
│  • explicar trade-off risco × retorno                       │
│  • comparar com histórico e sinalizar dado suspeito         │
└─────────────────────────────────────────────────────────────┘
```

### Ganho de rodar data client próprio

1. Dado **mais fresco** que a API pública para as cidades onde você joga
2. Não fica refém do rate limit
3. Vantagem informacional real sobre quem só consome a API

### Assinatura da tool exposta ao LLM

```
buscar_oportunidades(
  cidade_atual: str,
  capital_disponivel: int,
  capacidade_peso: float,
  tem_premium: bool,
  tem_foco: bool,
  tolerancia_risco: "baixa" | "media" | "alta",
  max_idade_dado_min: int = 120
) -> list[Oportunidade]
```

---

## 6. Regras de sanidade obrigatórias

Sem isso o sistema gera "oportunidades" fantasma:

- [ ] Descartar preço com `*_date` mais velho que ~2h — **crítico para buy orders**, elas somem rápido
- [ ] Descartar `price == 0` e `date == "0001-01-01T00:00:00"`
- [ ] Cruzar com `/history` (média móvel 7d): spread > 3σ = outlier, não oportunidade
- [ ] Nunca assumir liquidez — usar `item_count` do `/history` para saber se o mercado absorve o volume
- [ ] `buy_price_max` é só o topo da fila — você vende *aquela* quantidade nesse preço, não o estoque todo
- [ ] Sempre exibir a **idade do dado** junto da margem, na UI e na resposta da IA

---

## 7. Roadmap sugerido

| Fase | Entrega |
|---|---|
| 1 | Poller REST + Postgres + sync do `items.json` |
| 2 | Motor determinístico (RRR + receitas + taxas + impostos) |
| 3 | Regras de sanidade e cruzamento com histórico |
| 4 | Data client próprio + subscriber NATS |
| 5 | Camada LLM com function calling |
| 6 | Sinais proativos (alertas quando margem > X e dado < Y min) |

---

## 8. Referências

- [The Albion Online Data Project](https://www.albion-online-data.com/)
- [AODP API reference](https://www.albion-online-data.com/api/)
- [albiondata-client (GitHub)](https://github.com/ao-data/albiondata-client)
- [ao-bin-dumps (GitHub)](https://github.com/ao-data/ao-bin-dumps)
- [AFM Data Client](https://albionfreemarket.com/data-client)
- [Return Rate Explained — Albion Codex](https://www.albioncodex.com/guides/albion-online-return-rate-explained)
- [Albion Online Refining Guide — Heaven Guardian](https://heaven-guardian.com/albion-online-refining-guide/)
- [Marketplace — Albion Online Wiki](https://wiki.albiononline.com/wiki/Marketplace)
- [Explaining Crafting Tax — Albion Online Forum](https://forum.albiononline.com/index.php/Thread/167434-Explaining-Crafting-Tax-and-more/)
- [How to Use Albion Market Data (AODP Guide) — Albion Codex](https://www.albioncodex.com/guides/how-to-use-albion-market-data)