Created
February 4, 2021 19:50
-
-
Save nidorx/0d5928786fd4c06bd6d2acdff1cbaef6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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