Tehnički članak

Obveznice i trezorske formule u Delphiju s HotXLS-om

HotXLS izvorno u Delphiju i C++Builderu izračunava financijske funkcije za obveznice i trezorske zapise iz Excela: PRICE, YIELD, DURATION, MDURATION, šest primitiva za datume kupona, trojku funkcija za trezorske zapise, obitelj diskontnih funkcija i francuske funkcije amortizacije. Izračunavaju se unutar vlastitog mehanizma formula knjižnice, pa se radna knjiga koja vrednuje portfelj obveznica ponovno izračunava na poslužitelju bez Excela i bez ikakvog dodatka Analysis ToolPak na vidiku

Ove su funkcije nekoć živjele u dodatku Analysis ToolPak, zbog čega i dalje nose reputaciju nezgrapnih. Od Excela 2007 dio su standardnog skupa funkcija i zapisuju se u formatu datoteke bez oznake, bez prefiksa _xlfn. koji nose stvarno novije funkcije. Radna knjiga koja ih koristi obična je radna knjiga; jedino je pitanje zna li ono što je ponovno izračunava te funkcije

Što mehanizam datuma kupona mora ispravno napraviti

Svaki izračun obveznice počiva na istim primitivima: koliko dana od posljednjeg kupona, koliko dana u trenutačnom razdoblju kupona, koliko dana do sljedećeg kupona, kada ti kuponi padaju, i koliko ih preostaje. To su COUPDAYBS, COUPDAYS, COUPDAYSNC, COUPPCD, COUPNCD i COUPNUM, a svaka funkcija cijene i prinosa poziva ih

Ono što ih čini netrivijalnima jest argument baze. U igri je pet konvencija brojanja dana — 30/360 US, actual/actual, actual/360, actual/365 i 30/360 European — a one se ne slažu oko pitanja poput toga što se događa kada datum namire padne na 31. dan u mjesecu, ili kako se datum veljačkog kupona ponaša u prijestupnoj godini. Ispravno provođenje jedne konvencije uz aproksimiranje ostalih proizvodi rezultate koji izgledaju vjerodostojno, a pogrešni su za nekoliko baznih bodova, što je na velikoj poziciji stvaran novac

HotXLS implementira svih pet u samodostatnom ugniježđenom mehanizmu datuma kupona koji dijele sve funkcije kojima je potreban, pa se PRICE i DURATION ne mogu međusobno ne slagati oko toga gdje se nalaze datumi kupona

HotXLS-ov mehanizam datuma kupona za Delphi: ulazi obveznice i odabrana baza brojanja dana napajaju šest primitiva COUP koje dijele PRICE, YIELD, DURATION i MDURATION
Svih pet baza brojanja dana napaja jedan ugniježđeni mehanizam datuma kupona koji dijeli svaka financijska funkcija u HotXLS-u, pa se PRICE i DURATION nikada ne mogu ne slagati oko toga gdje padaju datumi kupona

Cijena i prinos u radnoj knjizi

Ništa u pozivajućem kodu nije posebno: napišite formule, ponovno izračunajte, pročitajte vrijednosti. Upravo je to poanta — radna knjiga je model, a vaša Delphi aplikacija kalkulator:

uses
  lxHandleX;

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
begin
  Book := TXLSXWorkbook.Create;
  try
    Sheet := Book.Sheets.Add('Bond');
    Sheet.Cells[1, 1].Value := EncodeDate(2026, 3, 15);   // namira
    Sheet.Cells[2, 1].Value := EncodeDate(2034, 11, 15);  // dospijeće
    Sheet.Cells[3, 1].Value := 0.0425;                    // kuponska stopa
    Sheet.Cells[4, 1].Value := 0.0391;                    // tražen prinos
    Sheet.Cells[5, 1].Value := 100;                       // otkup
    Sheet.Cells[6, 1].Value := 2;                         // učestalost
    Sheet.Cells[7, 1].Value := 1;                         // baza: actual/actual

    Sheet.Cells[9, 1].Formula  := '=PRICE(A1,A2,A3,A4,A5,A6,A7)';
    Sheet.Cells[10, 1].Formula := '=DURATION(A1,A2,A3,A4,A6,A7)';
    Sheet.Cells[11, 1].Formula := '=MDURATION(A1,A2,A3,A4,A6,A7)';
    Sheet.Cells[12, 1].Formula := '=COUPNUM(A1,A2,A6,A7)';

    Book.Recalculate;

    Writeln(Format('price %.6f  Macaulay %.6f  modified %.6f  coupons %d',
      [Double(Sheet.Cells[9, 1].Value), Double(Sheet.Cells[10, 1].Value),
       Double(Sheet.Cells[11, 1].Value),
       Integer(Sheet.Cells[12, 1].Value)]));
  finally
    Book.Free;
  end;
end;

Datumi ulaze kao stvarne vrijednosti datuma, a ne kao nizovi znakova. Tekstualni datum radi u Excelu jer ga Excel prisilno pretvara, a ta pretvorba ovisi o lokalizaciji (locale), što je upravo vrsta ovisnosti koju izračun na strani poslužitelja ne bi trebao imati. Pravila sustava datuma koja stoje ispod obrađena su u članku serijski brojevi datuma i sustav 1904

Prinos nema zatvoreni oblik, i to ima posljedice

PRICE je izravan izračun: diskontirajte novčane tokove, zbrojite ih. YIELD je njegov obrat i nema rješenje u zatvorenom obliku za obveznicu s više od jednog preostalog kupona, pa se mora rješavati numerički. HotXLS koristi rješavač bisekcijom, koji pouzdano konvergira, a ne brzo

Slijede dvije praktične posljedice. Prinos je mjerljivo skuplji od cijene, pa revalorizacija portfelja koja izračunava prinose za deset tisuća pozicija stoji primjetno više od one koja izračunava cijene, i vrijedi znati koje od to dvoje vaš model doista treba. A prinos koji se ne može uokviriti (bracket) — jer ulazi opisuju obveznicu koju nijedan prinos ne može vrednovati na zadanu vrijednost — vraća pogrešku umjesto pogrešnog broja, što je ispravno ponašanje i ono koje treba testirati

U HotXLS-u na Delphiju, PRICE je jedan izravan prolaz diskontiranih novčanih tokova, dok YIELD nema zatvoreni oblik i rješava se petljom bisekcije koja vraća pogrešku kada ne postoji okvir
PRICE je jedan izravan prolaz kroz diskontirane novčane tokove, dok YIELD nema zatvoreni oblik i uokviruje se te bisecira, vraćajući pogrešku umjesto pogrešnog broja kada se ulazi ne mogu vrednovati

Trezorski zapisi zasebna su obitelj

Zapisi su diskontni instrumenti bez kupona, pa koriste TBILLPRICE, TBILLYIELD i TBILLEQ umjesto funkcija za obveznice. TBILLEQ pretvara diskontnu stopu u prinos ekvivalentan obveznici, a ima dokumentiranu osobitost vrijednu poznavanja: za dospijeća dulja od 182 dana pretvorba je kvadratna, a ne linearna, jer vrijednosnica obuhvaća više od jednog polugodišnjeg razdoblja

Uvođenje zapisa umjesto toga u PRICE, s nultim kuponom i učestalošću, ne proizvodi isti broj. Obitelj diskontnih instrumenata — DISC, INTRATE, RECEIVED, PRICEDISC i YIELDDISC — postoji upravo zato što se ti instrumenti kotiraju i namiruju drugačije

Ostatak skupa, na jednom mjestu

Osim obveznica i zapisa, ista skupina obuhvaća funkcije koje ih okružuju u stvarnim modelima. PRICEMAT i YIELDMAT obrađuju vrijednosnice koje plaćaju kamatu pri dospijeću. ACCRINTM izračunava obračunatu kamatu za njih. EFFECT i NOMINAL pretvaraju između efektivnih i nominalnih godišnjih stopa, što je pretvorba koju se najčešće pogrešno radi ručno. CUMIPMT i CUMPRINC daju kumulativnu kamatu i glavnicu preko raspona razdoblja. FVSCHEDULE primjenjuje niz različitih stopa redoslijedom, uzimajući raspon ili skalar

DOLLARDE i DOLLARFR pretvaraju između decimalnih i razlomljenih dolarskih kotacija, što je bitno za svaki instrument koji se još uvijek kotira u tridesetdvojinama. A AMORDEGRC i AMORLINC implementiraju francuske metode amortizacije, koje zahtijevaju francuska računovodstvena pravila, a nisu izborna pogodnost

// Pretvorba stope koju ljudi rutinski pogrešno rade ručno
Sheet.Cells[1, 3].Formula := '=EFFECT(0.0425,12)';   // nominalna u efektivnu
Sheet.Cells[2, 3].Formula := '=NOMINAL(0.043338,12)'; // i natrag

// Kumulativna kamata tijekom prve dvije godine 25-godišnjeg zajma
Sheet.Cells[4, 3].Formula :=
  '=CUMIPMT(0.0389/12,300,340000,1,24,0)';

// Projekcija promjenjive stope: 3 posto, zatim 3,5, zatim 4
Sheet.Cells[6, 3].Formula := '=FVSCHEDULE(10000,{0.03;0.035;0.04})';

Provjera implementacije koju niste vi napisali

Financijske su funkcije jedino područje gdje "vraća broj" nije dokaz ničega. Broj je po konstrukciji vjerodostojan, a pogreška u konvenciji brojanja dana pomiče rezultate za iznos premalen da bi se primijetio, a prevelik da bi se prihvatio

Test koji doista radi diferencijalan je. Izgradite proračunsku tablicu reprezentativnih instrumenata — jednu obveznicu po bazi brojanja dana, jednu koja se namiruje na kraju mjeseca, jednu koja obuhvaća veljaču u prijestupnoj godini, jedan zapis ispod 182 dana i jedan iznad — izračunajte vrijednosti u Excelu jednom, pohranite ih kao očekivane rezultate, i provjeravajte prema njima nakon svake nadogradnje knjižnice. Pozicije koje premošćuju datum kupona i namire na 31. dan mjesto su gdje se implementacije razilaze, pa oboje namjerno uključite

Diferencijalni skup provjere za HotXLS funkcije obveznica i trezorskih zapisa u Delphiju: reprezentativni instrumenti uključujući slučajeve prijestupne godine i kraja mjeseca izračunavaju se jednom u Excelu i provjeravaju nakon svake nadogradnje knjižnice
Diferencijalni paket testova vrednuje reprezentativne instrumente jednom u Excelu, pohranjuje vrijednosti kao očekivanja i provjerava ih nakon svake nadogradnje HotXLS-a, pa se odstupanje od baznih bodova ne može sakriti iza vjerodostojnog izlaza

Za same radne knjige, dva pratioca ove značajke jesu mehanizam izračuna koji odlučuje što ponovno izračunati, opisan u članku prirasni ponovni izračun i graf ovisnosti, i statistička obitelj obrađena u članku statističke funkcije distribucije. Zajedno su to ono što financijskom modelu omogućuje neovisno pokretanje na poslužitelju, što je bio cijeli razlog njihove izvorne implementacije

Financije obveznica, statistika, inženjerske funkcije i mehanizam ponovnog izračuna isporučuju se u jednoj knjižnici za Delphi i C++Builder; potpuni popis značajki nalazi se na stranici HotXLS Delphi komponente za proračunske tablice