niedziela, maja 21, 2023

Ile w tym i przyszłym miesiącu z odsetek za obligacje?

Moją główną formą oszczędzania jest kupowanie obligacji skarbu państwa.
Zawsze kupuję 4 letnie.

Przy obecnej inflacji zyski z tych obligacji są dość ładne ;-) OK, może bardziej kwoty z odsetek są ładne, bo trudno powiedzieć czy są większe czy mniejsze niż inflacja ;-)

I czasem chciałbym wiedzieć ile w danym miesiącu i następnym dostanę tych odsetek, albo czy może nastąpi wykup obligacji.

Oczywiście strona do zakupu obligacji i ogólnie zarządzania nimi wygląda jakby była zrobiona w latach 2000, a może i wcześniej ;-)

Przy tym wyglądzie próbuje być bardzo dynamiczna, więc nie ma co próbować wszystkiego czytać z HTMLa bo złośliwie wielu rzeczy tam nie ma, dopiero powstają jak się na coś najedzie ;-)

Walczyłem już z tym kiedyś i mam dzięki temu bookmarki, jeden mi liczy oprocentowanie ważone, drugi generuje CSV z danymi o moich obligacjach.

Dziś* postanowiłem napisać taki, który będzie wypisywał ile w tym i przyszłym miesiącu dostanę :-)

Efekt działania, nie jest może powalający, ale robi to co powinien ;-)
Pokazuje Alert z informacjami :-) [wartości tu podane mogą być prawdziwe, mogą być nieprawdziwe]

Samo monstrum wygląda tak:

var TAX = 0.81;
// sadly this part is only for hacky way of finding what are Ids
function findIdLambda(elem,list,func) {
var id = elem.id;
if (id && func(id)) {
list.push(id);
}
for (var i=0; i<elem.childNodes.length; i++) {
var child = elem.childNodes[i];
findIdLambda(child,list,func);
}
}

function findId(elem,idStart,list) {
findIdLambda(elem,list,x => x.startsWith(idStart));
}

var list = [];
findId(document,"stanRachunku",list);
var id = list.filter(x => x.endsWith("data")).filter(x => x.indexOf("idt")!=-1)[0];
var no = id.split("idt")[1].split("_")[0]*1;
var idxNo = no;

function findQtipId(pattern) {
var list = [];
findIdLambda(document,list,x => x.startsWith(pattern));
return list[0];
}
//end of hacky way for finding proper Ids

const mouseoverEvent = new Event('mouseover');
function amount2number(s) {
var nbrsp=String.fromCharCode(160);
return s.replace(nbrsp,"").replace(',',".").replace(nbrsp+"PLN","");
}
function getPercents(idx) {
var id = findQtipId("qtip-stanRachunku:j_idt"+idxNo+":"+idx+":j_idt");
console.log(id);
var element=document.getElementById(id);
var data=element.innerText.split("%");
var res = [];
for (var i=0; i<data.length; i++) {
var line=data[i];
line=line.trim();
if (line.length==0) continue;
var l=line.split(" ");
res.push(l[l.length-1]);
}
return res;
}
var table=document.getElementById("stanRachunku:j_idt"+idxNo+"_data");
var data=table.childNodes;
var content="id,number,value,actual value,cycle,%,redemption date\n";

function isJanOfNextYear(l) {
return (l[0]==new Date().getFullYear()+1) && (l[1]==1);
}

function toYearMonth(s) {
var l=s.split("-");
l=l.map(x => x*1);
if (isJanOfNextYear(l)) l[1]=13;
return l;
}

var currentYear = new Date().getFullYear();

// 13 month is January of next year
var interests = [0,0,0,0,0,0,0,0,0,0,0,0,0];
var redemptions = [0,0,0,0,0,0,0,0,0,0,0,0,0];

for (var i=0; i<data.length; i++) {
var line = data[i].childNodes;
// ugly hack... but without this it will not be visible, and we would not be able to get percents
line[0].firstChild.dispatchEvent(mouseoverEvent);
var emId=line[0].innerText;
var number=line[1].innerText;
var value=line[3].innerText;
var actual=line[4].innerText;
var redemption=line[5].innerText;
var yearAndMonth = toYearMonth(redemption);
// harcoded that I buy only 4 years bonds

var yearMod = yearAndMonth[1]==13 ? 1 : 0;

var percentYear = currentYear + yearMod-(yearAndMonth[0]-4) ;

var percents=getPercents(i);

var thisYearPercent = percents[percentYear-1];
if (thisYearPercent) {
// hardcoded price of bond
interests[yearAndMonth[1]-1]+=number*100.0*thisYearPercent/100;
}
if (percentYear==4) {
redemptions[yearAndMonth[1]-1]+=number*100.0;
}
var cycle = percents.length;
var percentage = percents[percents.length-1];
var l=[emId,number,amount2number(value),amount2number(actual),cycle,percentage,redemption];
var cl = "";
for (var j=0; j<l.length; j++) cl+=l[j]+",";
cl=cl.substring(0,cl.length-1);
content+=cl+"\n";
}

var interestsAfterTax = interests.map(x => x*TAX).map(x => x.toFixed(2));
interests = interests.map(x => x.toFixed(2));
redemptions = redemptions.map(x => x.toFixed(2));
totals = [];
for (var i=0; i<interests.length; i++) {
totals.push((interestsAfterTax[i]*1+redemptions[i]*1).toFixed(2));
}
var currentMonth = new Date().getMonth();
var nextMonth = currentMonth+1;

var months = ["styczeń","luty","marzec","kwiecień","maj","czerwiec","lipiec","sierpień","wrzesień","październik","listopad","grudzień"];

var cashContent = months[currentMonth%12]+" "+totals[currentMonth]+" PLN (odsetki "+interestsAfterTax[currentMonth]+", wykup "+redemptions[currentMonth]+")\n";
cashContent += months[nextMonth%12]+" "+totals[nextMonth]+" PLN (odsetki "+interestsAfterTax[nextMonth]+", wykup "+redemptions[nextMonth]+")\n";
alert(cashContent);

Jak ktoś zainteresowany to tutaj link wygenerowany przez Bookmarklet Maker'a.

Ile odsetek w tym i przyszłym miesiącu?

Ciekawa sprawa, że część kodu napisał mi Copilot od GitHuba :-)
Np. w przypadku tablic interests i redemptions sam wygenerował tablice z 12 elementami (ja później dodałem 13 na styczeń następnego roku), a zrozumiał do czego służą bo wcześniej były mapami, ale w kodzie pisałem tak jakby to była tablica (więc nie działało), skasowałem {}, wpisałem [ i wtedy zaproponował dokończenie z 12 zerami oddzielonymi przecinkiem, ] i średnik.
W liczeniu kwoty całkowitej też był sprytny, zrobiłem tabelę totals, zacząłem pisać for (var to... i już zaproponował kod do policzenia totali :-) ale fakt, zrobił błąd bo użył interests, a nie interestsAfterTax. 
Podobnie ciekawie robił z map na tablicach. A i tablica miesięcy (z nazwami) to też jego robota ;-)

Ograniczenia:

  • działa tylko dla 4 letnich obligacji, nie próbowałem znaleźć sposobu na ustalenie jaka to jest obligacja.
  • zakłada, że obligacja warta jest 100 PLN
  • żeby policzył dla wszystkich obligacji trzeba wybrać w selektorze by pokazywał 50 (czyli nie wszystkie, a 50 ;-), nie mam więcej więc nie wiem czy później pokazuje się w tabelce możliwość wybrania więcej niż 50 emisji ;-))

* - może technicznie nie dziś ;-) bo post piszę w sobotę 20 maja 2023, żeby mieć post na zapas bo nie wiem czy jutro będę miał czas pisać ;-)




Podobne postybeta
Bookmarklet do robienia CSV z obligacjami i ich oprocentowaniem ;-)
Czasem człowiek musi napisać dekodowanie Base64 w JavaScript ;-)
Ile z obligacji... odsłona 2 ;-)
[Updated] Czytanie Pocketa ;-)
2016 będzie rokiem "nietypowym"

Brak komentarzy:

Prześlij komentarz