Skip to content

Instantly share code, notes, and snippets.

@nidorx
Created February 4, 2021 19:50
Show Gist options
  • Save nidorx/0d5928786fd4c06bd6d2acdff1cbaef6 to your computer and use it in GitHub Desktop.
Save nidorx/0d5928786fd4c06bd6d2acdff1cbaef6 to your computer and use it in GitHub Desktop.
/**
* Baseado na Fórmula Mágica de Joel Greenblatt, adiciona (opcionalmente) rank de DIVIDENDOS
*
* 1 - Abrir o navegador (Chrome) no link https://fundamentus.com.br/resultado.php
* 2 - Pressionar F12 para abrir o Console
* 3 - Colar esse script completo e pressionar Enter
*
* Referências:
* Clube do Valor: https://youtu.be/4Shv3OMaLVA
* Diogo Investe: https://youtu.be/PEWfCORYGyA
*
* @author Alex Rodin <https://github.com/nidorx>
*/
(function(){
/*
PARA A FORMULA ORIGINAL USE OS PARAMETROS ABAIXO, IGNORANDO O DIVY:
FATOR_PRECO = 1;
FATOR_LUCRO = 1;
FATOR_DIVY = 0;
*/
let FATOR_PRECO = 1.1;
let FATOR_LUCRO = 1;
let FATOR_DIVY = 0.5;
let papeis = [];
let empresas = {};
document.querySelectorAll('#resultado tr').forEach((tr)=>{
let ticker = tr.querySelector('td:nth-child(1) > span > a')
let ev_ebit = tr.querySelector('td:nth-child(11)')
let roic = tr.querySelector('td:nth-child(16)')
let liq = tr.querySelector('td:nth-child(18)')
let pl = tr.querySelector('td:nth-child(3)')
let div = tr.querySelector('td:nth-child(20)')
let dy = tr.querySelector('td:nth-child(6)')
if(!ticker || !ev_ebit || !roic || !liq || !pl || !div || !dy){ return }
ticker = ticker.innerText
// ignora UNITS?
if(ticker.endsWith('11')) { return }
ev_ebit = Number.parseFloat(ev_ebit.innerText.replace('.','').replace(',','.'))
roic = Number.parseFloat(roic.innerText.replace('.','').replace(',','.'))
liq = Number.parseFloat(liq.innerText.replace('.','').replace(',','.'))
pl = Number.parseFloat(pl.innerText.replace('.','').replace(',','.'))
div = Number.parseFloat(div.innerText.replace('.','').replace(',','.'))
dy = Number.parseFloat(dy.innerText.replace('.','').replace(',','.'))
// ignora ebit e roic negativo
if(ev_ebit < 0 || roic < 0 ) { return }
// ignora empresas que não possuem lucro, P/L deve ser positivo
if(pl <= 0) { return }
// ignora se o volume médio de negociação é menor que 50.000, portanto não possui liquidez
if(liq < 50.000) { return }
// só permite empresas com dívidas equilibradas (Dívida Bruta/Patrimonio > 3)
if(div > 3) { return }
let papel = {ticker, ev_ebit, roic, dy}
// agrupa por empresa para pegar o papel com maior liquidez apenas
let empresa = ticker.replace(/\d+$/,'')
if(!empresas[empresa]){
empresas[empresa] = []
}
empresas[empresa].push(papel)
papeis.push(papel)
})
let rank = 0;
let last_value = 0;
// ordenar ev_ebit do menor para maior e aplicar rank (mais baratos no início)
papeis.sort((a, b)=>{ return a.ev_ebit - b.ev_ebit })
papeis.forEach((a)=>{
if(a.ev_ebit > last_value){
rank++
last_value = a.ev_ebit
}
a.rank1 = rank*(1/FATOR_PRECO)
})
rank = 0;
last_value = 999999999;
// ordenar roic do maior para menor e aplicar rank (maior lucro no inicio)
papeis.sort((a, b)=>{ return b.roic - a.roic })
papeis.forEach((a)=>{
if(a.roic < last_value){
rank++
last_value = a.roic
}
a.rank2 = a.rank1 + rank*FATOR_LUCRO
})
rank = 0;
last_value = 999999999;
// ordenar por DIVIDEND YIELD do maior para menor e aplicar rank (maior DY no inicio)
papeis.sort((a, b)=>{ return b.dy - a.dy })
papeis.forEach((a)=>{
if(a.dy < last_value){
rank++
last_value = a.dy
}
a.rank = a.rank2 + rank*FATOR_DIVY
})
// Obtém os papeis mais bem colocados por empresa (Ordinárias vs Preferenciais)
papeis = Object.keys(empresas)
.map((empresa)=>{
empresas[empresa].sort((a, b)=>{ return a.rank - b.rank })
return empresas[empresa][0]
})
// Finalmente gera a ordenação final
papeis.sort((a, b)=>{ return a.rank - b.rank })
let saida = papeis
//.slice(0, 50)
.map((a, i)=>{
return (i+1)+'\t'+a.ticker
})
.join('\n')
console.log(saida)
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment