albion-market-ia
Albion Market IA — Detector de Lucro em Compra → Transporte → Refino
Baixar — 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.jsondoao-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.
pnpm install
pnpm sync:catalog # baixa receitas e pesos do ao-bin-dumps
pnpm dev # API + app web em http://localhost:5183O 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:
pnpm poll # uma coleta manual
pnpm opps "Fort Sterling" 2000000 # ranqueia rotas para essa cidade e capitalEstado fica em ~/.albion-market/market.sqlite (mude com ALBION_HOME).
Servidor padrão é o west; troque com ALBION_SERVER=east|europe.
pnpm -r test # 31 testes
pnpm -r typecheckApp desktop
Pronto para instalar em Releases, ou para rodar do código:
pnpm dev:desktop # abre a janela do Electron
pnpm dist:desktop # gera o instalador da plataforma atualWindows, macOS e Linux, sem dependência nativa. Detalhes em docs/user/desktop.md.
Usar dentro da sua IA
pnpm mcp # servidor MCP no stdioRegistre 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.
Arquitetura técnica: ver ARCHITECTURE.md — stack, estrutura de pastas, contrato, tema e o mecanismo de "use qualquer IA", inspirados no 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
O jogador roda um data client (
albiondata-clientoficial, ou o AFM Data Client, que tem versão Android).O client escuta pacotes UDP do jogo via libpcap. Não modifica o cliente do jogo — por isso é tolerado pela SBI.
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.
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) |
|
Asia (East) |
|
Europe |
|
/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=24time-scale:1horário ·66h ·24diárioqualities: 1 Normal · 2 Bom · 3 Excepcional · 4 Excelente · 5 Obra-primaRate 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):
{"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: 580esell_price_max: 13292— outlier puroT6_PLANKSna 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âneabuy_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:4222Tó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:
"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ônusSituaçã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
@weightdo dump × capacidade da montaria → quantos ciclos de viagem@fasttravelfactor→ custo de fast travelRota 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
Dado mais fresco que a API pública para as cidades onde você joga
Não fica refém do rate limit
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
*_datemais velho que ~2h — crítico para buy orders, elas somem rápidoDescartar
price == 0edate == "0001-01-01T00:00:00"Cruzar com
/history(média móvel 7d): spread > 3σ = outlier, não oportunidadeNunca assumir liquidez — usar
item_countdo/historypara saber se o mercado absorve o volumebuy_price_maxé só o topo da fila — você vende aquela quantidade nesse preço, não o estoque todoSempre 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 |
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) |