xtbrep — Analizator portfela XTB

Spis treści
- Co robi program
- Pojęcia finansowe
- Algorytm XIRR
- Architektura
- Moduł A — Zestawienie po symbolu
- Moduł B — Silnik podatkowy PIT-38
- Moduł C — Dane inflacyjne CPI
- Format danych wejściowych
- Pipeline parsowania XLSX
- Mapa modułów
- Drzewo źródeł
- Budowanie
- Wymagania systemowe
- Eksport CSV i schowek
Co robi program
xtbrep wczytuje eksport XTB (menu xStation → Historia → Eksportuj jako XLSX) i w jednym oknie prezentuje:
| Zakładka | Zawartość |
|---|---|
| Podsumowanie | Wpłaty, wypłaty, net P&L zamknięty/otwarty, dywidendy, odsetki, XIRR, szacunek podatkowy |
| Symbole | Zestawienie zysku/straty i dywidend per ticker, sortowalne, z filtrem |
| Transakcje | Pełna lista zamkniętych pozycji z Gross P&L / prowizja / swap / Net P&L |
| Przepływy gotówki | Wszystkie operacje cashowe: wpłaty, wypłaty, dywidendy, podatki u źródła, odsetki |
| Podatek PL | Roczna tabela PIT-38: podstawa Belki, odliczenia strat, dopłata od dywidend |
| Wykres | Słupki roczne net P&L + linia kumulatywna + linia inflacyjna (benchmark CPI GUS) |
Filtr w pasku narzędzi działa na żywo na zakładkach Symbole, Transakcje i Przepływy. Dwuklik wiersza w Symbolach kopiuje ticker do filtra i przełącza na Transakcje — natychmiast widać całą historię danego waloru.
Pojęcia finansowe
P&L (Profit & Loss)
XTB rozróżnia:
- Gross P&L — wynik brutto transakcji bez kosztów transakcyjnych
- Prowizja — opłata brokera przy otwarciu/zamknięciu pozycji (wartość ujemna)
- Swap — koszt finansowania pozycji overnight (może być ujemny lub dodatni)
- Net P&L = Gross P&L + Prowizja + Swap
Program agreguje Net P&L na rok, po symbolu i łącznie.
Otwarte vs zamknięte pozycje
Eksport XTB zawiera wyłącznie zamknięte pozycje. Wartość otwartych pozycji jest szacowana ze wzoru:
openNetPl = portfolioValueNow − netDeposited − closedNetPl
gdzie portfolioValueNow to aktualna wartość konta wpisana ręcznie przez użytkownika. Bez tego parametru pole otwarte wynosi zero.
Dywidendy a podatek u źródła (Withholding Tax)
XTB w operacjach gotówkowych rejestruje dwa typy wierszy per dywidenda:
| Typ operacji | Znaczenie |
|---|---|
DIVIDENT |
Kwota brutto dywidendy uznana na rachunku |
Withholding Tax |
Podatek potrącony u źródła przez kraj emitenta (wartość ujemna) |
dividendsNet = suma(DIVIDENT) + suma(Withholding Tax) — wartość netto faktycznie wpływająca na konto.
XIRR a zwykłe stopy zwrotu
Prosta stopa zwrotu (wynik / zainwestowane) jest myląca przy nieregularnych wpłatach w czasie — kwota zainwestowana zmienia się wraz z każdą wpłatą i wypłatą. XIRR eliminuje ten błąd przez sprowadzenie wszystkich przepływów do jednej rocznej stopy dyskontowej. Patrz sekcja Algorytm XIRR.
Algorytm XIRR
Definicja
XIRR (Extended Internal Rate of Return) to annualizowana stopa zwrotu r, dla której wartość bieżąca netto (NPV) serii datowanych przepływów pieniężnych wynosi zero:
NPV(r) = Σ [ CF_i / (1 + r)^t_i ] = 0
gdzie:
CF_i— przepływ pieniężny nri(wpłata jako wartość ujemna, wypłata lub końcowa wartość portfela jako dodatnia)t_i— czas w latach od pierwszego przepływu do przepływui, liczony jako(JDN_i − JDN_0) / 365.25JDN— Juliański Numer Dnia (Julian Day Number) — algebraicznie poprawna reprezentacja dat bez problemu przestępnych lat
Przepływy gotówki używane w obliczeniu
Wpłaty są traktowane jak wydatek inwestora (przepływ ujemny), wypłaty i końcowa wartość portfela jak zwrot (przepływ dodatni) — konwencja zgodna z Excelem i Google Sheets.
Metoda bisekcji ze wstępnym bracketingiem
Implementacja używa bisekcji (nie Newton-Raphson) dla lepszej stabilności numerycznej przy dużych stopach:
1. Przedział [low=−0.999, high=1.0]
2. Rozszerzaj high×2, aż NPV(low)·NPV(high) < 0 (max high=100.0)
3. 120 iteracji bisekcji: mid = (low+high)/2
Implementacja (Report.cpp::ComputeXirr):
double low = -0.999, high = 1.0;
double fLow = npv(low), fHigh = npv(high);
while (fLow * fHigh > 0.0 && high < 100.0) {
high *= 2.0; fHigh = npv(high);
}
if (fLow * fHigh > 0.0) return 0.0;
double mid = 0.0;
for (int i = 0; i < 120; ++i) {
mid = (low + high) * 0.5;
const double fMid = npv(mid);
if (std::abs(fMid) < 1e-10) break;
if (fLow * fMid < 0.0) { high = mid; fHigh = fMid; }
else { low = mid; fLow = fMid; }
}
return mid;
Ograniczenie low ≥ −0.999 zapobiega singularności (1+r)^t przy ujemnych stawkach bliskich −1.
XIRR całościowy vs. roczny
| Tryb | Przepływy | Wartość terminalna |
|---|---|---|
| Cała historia | wszystkie wpłaty/wypłaty od początku | bieżąca wartość portfela |
| Rok X (filtr roku) | saldo na 1 sty roku X + wpłaty w roku X | szacunkowa wartość na 31 gru roku X |
Dla filtra rocznego przepływy w ComputeAnnualXirr():
t = 0,0 : −EstimatePortfolio(rok−1) ← kapitał na początku roku
t = x : −wpłata lub +wypłata
t = 1,0 : +EstimatePortfolio(rok) ← wartość na końcu roku
Dlaczego XIRR jest dokładniejszy niż IRR
| Właściwość | IRR | XIRR |
|---|---|---|
| Uwzględnia konkretne daty przepływów | nie (zakłada równe okresy) | tak |
| Poprawny dla nieregularnych wpłat | nie | tak |
| Annualizuje wynik | wynik per okres | zawsze roczny |
| Zgodny z Excelem/Google Sheets | tylko IRR | XIRR |
| Czas obliczeń na 500 przepływach | O(n·iter) | O(n·iter), ident. |
Dla portfela z wpłatami co kilka miesięcy przez kilka lat różnica między IRR a XIRR może wynosić kilka punktów procentowych — IRR zawyża stopę zwrotu przy częstych wpłatach na początku.
Juliański Numer Dnia (JDN)
Daty transakcji z seriali Excela przeliczane są do JDN — liczby całkowitej liczącej dni od 1 stycznia 4713 p.n.e. (południe). Algorytm Meeus'a (StringUtil.cpp::JulianDay) jest algebraicznie dokładny dla dowolnej daty po roku 1582:
int JulianDay(int y, int m, int d) noexcept {
return d - 32075
+ 1461 * (y + 4800 + (m - 14) / 12) / 4
+ 367 * (m - 2 - (m - 14) / 12 * 12) / 12
- 3 * ((y + 4900 + (m - 14) / 12) / 100) / 4;
}
Czas w latach: t = (JDN_i − JDN_0) / 365.25. Dzielnik 365.25 odpowiada średniej długości roku gregoriańskiego.
Architektura
Warstwy
Przepływ danych od pliku do ekranu
Moduł A — Zestawienie po symbolu
Cel
Zakładka Symbole agreguje wynik per ticker przez cały okres historii. Kolumny:
| Symbol | Transakcje | Gross P/L | Prowizje | Swap | Net P/L | Dywidendy | Razem |
|---|
Razem = Net P/L + Dywidendy — faktyczny wkład instrumentu do portfela.
Agregacja
Podczas Aggregate() w Report.cpp jednoczesny forward pass po trades i cash:
Klucz mapy to std::wstring (ticker). Dywidendy i podatki u źródła dodają się algebraicznie: dividends += amount gdzie Withholding Tax ma wartość ujemną — wynik to automatycznie kwota netto bez osobnego odejmowania.
Filtr live
Pole IDC_FILTER obsługuje zdarzenie EN_CHANGE. Przy każdej zmianie tekstu wywołanie ContainsInsensitive() filtruje wektor przed odświeżeniem ListView — bez ponownego parsowania danych. Filtr działa równolegle na zakładkach Symbole, Transakcje i Przepływy (wspólne pole tekstowe, stan zachowany przy przełączaniu zakładek).
Dwuklik na symbolu w tabeli Symbole → kopiuje ticker do filtra → TabCtrl_SetCurSel(tab_, 2) → OnTabChange() → widać przefiltrowane transakcje dla wybranego waloru.
Moduł B — Silnik podatkowy PIT-38
Podstawy prawne
- Art. 30b ustawy o PIT — 19% podatek od dochodów z odpłatnego zbycia papierów wartościowych (tzw. podatek Belki od giełdy)
- Art. 9 ust. 3 — straty można odliczać przez 5 kolejnych lat podatkowych, przy czym w jednym roku można odliczyć nie więcej niż 50% straty z danego roku stratnego
- Dywidendy zagraniczne (§30a + UPO) — Polska wymaga łącznie 19% od kwoty brutto. Podatek potrącony u źródła (np. 15% USA via W-8BEN) zalicza się na poczet polskiego — dopłata =
max(0, 19% × gross − |withheld|). Nadwyżka podatku zagranicznego ponad 19% nie jest zwracana.
Algorytm rozliczenia strat — kolejka przeniesionych strat
Slot LossSlot przechowuje zarówno original (do wyznaczenia cap 50%) jak i remaining (saldo do odliczenia). Po wyczerpaniu slotu jest usuwany z deque. Sloty starsze niż 5 lat wygasają na początku każdej iteracji przed zastosowaniem.
Dopłata dywidendowa
Dla każdego roku:
divWithheld = Σ |Withholding Tax| (wartości ujemne → bierzemy wartość bezwzględną)
divSupplement = max(0.0, 0.19 × divGross − divWithheld)
Logika bierze pod uwagę lata, w których wpłynęły dywidendy, nawet jeśli w tym roku nie było zamkniętych pozycji (brak wiersza w YearSummary).
Widok tabeli Podatek PL
| Rok | P/L pozycji | Straty odlicz. | Podstawa | Belka 19% | Dyw. brutto | Potrącono | Dopłata dyw. | Łącznie |
|---|---|---|---|---|---|---|---|---|
| 2021 | 4 200,00 zł | — | 4 200,00 zł | 798,00 zł | 320,00 zł | 48,00 zł | 12,80 zł | 810,80 zł |
| 2022 | −1 800,00 zł | — | — | — | — | — | — | — |
| 2023 | 3 500,00 zł | 900,00 zł | 2 600,00 zł | 494,00 zł | — | — | — | 494,00 zł |
Wiersz SUMA i sekcja strat do przeniesienia widoczne na końcu tabeli.
Moduł C — Dane inflacyjne CPI
Skąd są dane o inflacji (dla użytkownika)
Program zaciąga inflację online i ma kilka fallbacków, żeby wykres zawsze działał nawet bez internetu:
- Cache w
%APPDATA%\xtbrep\cpi_cache.txt(jeśli cache ma ≤ 30 dni, używa cache; źródło w UI:cache GUS <rok>). - Fetch online (GUS BDL API) (pobiera z
bdl.stat.gov.pl, zmienna 59; po sukcesie zapisuje do cache i używa online; źródło w UI:GUS BDL <rok> (online)). - Stary cache (gdy online nie działa, a cache istnieje; źródło w UI:
cache GUS <rok> (przestarzały)). - Fallback wbudowany (gdy wszystko zawiedzie; tablica wbudowana w
InflationData.h; źródło w UI:wbudowana <rok>; najnowszy rok wbudowany: 2025).
Łańcuch działania: cache świeży → online → cache stary → fallback.
Strategia trójetapowa
Tablica wbudowana kCpiFallback[] i stała kCpiFallbackLastYear żyją wyłącznie w InflationData.h — są inline constexpr, dostępne w każdej jednostce kompilacji bez ODR, bez pliku .cpp.
Format cache
Plik tekstowy %APPDATA%\xtbrep\cpi_cache.txt:
FETCHED=2025-11-15
2005=0.021000
2006=0.010000
...
2025=0.050000
Data FETCHED wyznacza świeżość. Przy odczycie: difftime(now, cachedT) / 86400.0 ≤ 30. Zapis: atomowy — najpierw do pliku tymczasowego, potem MoveFileEx (nie zaimplementowane w tej wersji — zapis bezpośredni; NTFS jest wystarczająco odporny dla danych statystycznych).
GUS BDL API
Endpoint: https://bdl.stat.gov.pl/api/v1/data/by-variable/59?format=json&unit-level=0&page-size=40&lang=pl
Zmienna 59 = "Wskaźnik cen towarów i usług konsumpcyjnych ogółem, rok poprzedni = 100". Wartość 102.1 oznacza inflację 2.1% → rate = val/100 − 1.
Timeouty WinHTTP ustawione na 8 sekund per fazę (connect / send / receive) — wątek tła nie blokuje UI.
Aktualizacja wykresu przy przybyciu danych
ChartView::UpdateCpiData() → RebuildBars() przelicza inflacyjny benchmark od zera korzystając z nowej tablicy CPI:
inflRefAbs_{i} = inflRefAbs_{i-1} × (1 + CPI_i) + newDep_i × (1 + CPI_i / 2)
inflGain_i = inflRefAbs_i − cumDeposited_i
Konwencja połowy roku (CPI/2 dla nowych depozytów) modeluje depozyty rozłożone równomiernie w ciągu roku. barInputs_ (dane niezależne od CPI) są zachowane między SetData() a UpdateCpiData() — brak ponownego parsowania pliku.
Footer wykresu (dwuliniowy pasek) wyświetla:
Linia 1 — stopy procentowe:
| Metryka | Wzór | Interpretacja |
|---|---|---|
| XIRR | bisekcja NPV=0 | annualizowana stopa zwrotu |
| Realna stopa | (1+XIRR)/(1+CPI)−1 |
zysk w sile nabywczej |
| Alfa vs CPI | XIRR − CPI [pp] |
o ile pp bijesz inflację |
Linia 2 — wartości PLN: zysk łączny / wkład netto / powyżej inflacji (PLN).
Źródło: GUS BDL 2025 (online) / cache GUS 2024 / wbudowana 2025.
Format danych wejściowych
Plik XLSX z xStation zawiera dwa arkusze:
CLOSED POSITION HISTORY
| Position | Symbol | Type | Volume | Open time | Open price | Market price | Purchase value | SL | TP | Margin | Commission | Swap | Rollover | Gross P/L | Comment |
|---|
Kluczowe kolumny używane przez parser:
| Kolumna | Typ | Użycie |
|---|---|---|
Symbol |
tekst | ticker, klucz w zestawieniu po symbolu |
Type |
tekst | BUY / SELL |
Close time |
serial Excel | data zamknięcia — P/L przypisywane do roku zamknięcia |
Open time |
serial Excel | fallback gdy Close time brak |
Gross P/L |
liczba | wynik brutto |
Commission |
liczba | prowizja (ujemna) |
Swap |
liczba | swap nocny |
CASH OPERATION HISTORY
| ID | Type | Time | Comment | Symbol | Amount |
|---|
Typy operacji rozpoznawane przez parser (dopasowanie case-insensitive, toleruje sufiksy):
| Typ (przykłady z eksportu XTB) | Znaczenie |
|---|---|
deposit / Deposit |
wpłata środków |
withdrawal / Withdrawal from 1844768 |
wypłata środków — toleruje suffix z numerem konta |
DIVIDENT |
dywidenda brutto (literówka w eksporcie XTB) |
Withholding Tax |
podatek u źródła potrącony od dywidendy (ujemny) |
Free-funds Interest / Free-funds Interest 2024-01 |
odsetki od wolnych środków |
Free-funds Interest Tax / Free-funds Interest Tax 2024-01 |
podatek od odsetek (ujemny) |
Pipeline parsowania XLSX
XLSX to ZIP z plikami XML. Cały stos I/O napisany od zera — zero zewnętrznych bibliotek.
Serial Excela → data
Excel przechowuje daty jako liczbę dni od 30.12.1899 (z historycznym błędem: Feb 29 1900 nie istnieje, Excel go ma). Korekcja:
void ExcelSerialToDate(double serial, int& y, int& m, int& d) noexcept {
int n = static_cast<int>(serial);
if (n >= 60) n--; // cofnięcie błędu Lotus 1-2-3 skopiowanego przez Excel
const int jdn = n + 2415020; // JDN dla 31.12.1899
// algorytm Meeus JDN → Gregorian
...
}
Skanowanie nagłówków
Parser nie zakłada stałej pozycji kolumn — skanuje pierwszy wiersz z daną nazwą metodą FindHeaderRow() + MapColumns(), budując mapę wstring → int. Odporne na różne wersje eksportu XTB (różne liczby metadanych powyżej tabeli).
Mapa modułów
| Moduł | Plik | Odpowiedzialność |
|---|---|---|
| App | App.cpp |
bootstrap: dark mode, COM, InitCommonControls, MainDialog::Show() |
| Cli | Cli.cpp |
tryb CLI: xtbrep.exe plik.xlsx [portfel] → CSV na stdout |
| StringUtil | StringUtil.cpp/.h |
Utf8ToWide, FormatPln, FormatPct, FormatDate, JulianDay, ExcelSerialToDate |
| Inflate | Inflate.cpp/.h |
DEFLATE dekompresja RFC 1951, własna implementacja |
| ZipReader | ZipReader.cpp/.h |
czytanie ZIP: centralny katalog, lokalne nagłówki, wyodrębnianie pliku po nazwie |
| XlsxReader | XlsxReader.cpp/.h |
parsowanie XLSX XML: shared strings, worksheet, typy komórek, seriale dat |
| Report | Report.cpp/.h |
BuildReport(): parsowanie obu arkuszy + Aggregate() + wywołanie BuildTaxReport() |
| TaxEngine | TaxEngine.cpp |
BuildTaxReport(): Belka 19%, deque strat 5-letni, dopłata dywidendowa |
| InflationData | InflationData.h |
constexpr kCpiFallback[], CpiFallbackForYear(), kCpiFallbackLastYear |
| InflationFetcher | InflationFetcher.cpp/.h |
wątek tła WinHTTP, cache plik, GUS BDL API, PostMessage(WM_INFLATION_UPDATED) |
| ChartView | ChartView.cpp/.h |
okno GDI dziecka: słupki roczne, linia kumulatywna, linia inflacyjna, double-buffer |
| MainDialog | MainDialog.cpp/.h |
główne okno: 6 zakładek, 5 ListView, filtr live, MICA/dark mode, CSV eksport |
| DarkMode | DarkMode.h |
uxtheme undocumented API: SetPreferredAppMode, AllowDarkModeForWindow |
| LinkerDeps | LinkerDeps.cpp |
#pragma comment(lib, ...) zamiast ręcznego linkowania w projekcie |
Drzewo źródeł
xtbrep/
├── src/
│ ├── xtbrep.cpp wWinMainCRTStartup → App::Run()
│ ├── xtbrep.rc zasoby: dialog, version info (UTF-8, #pragma code_page)
│ ├── xtbrep.manifest DPI-aware, Common Controls v6, Win10+ compatibility
│ ├── Resource.h IDC_ / IDM_ / WM_USER stałe
│ ├── WinCommon.h _WIN32_WINNT=0x0A00, WIN32_LEAN_AND_MEAN, NOMINMAX
│ ├── LinkerDeps.cpp pragma comment lib
│ ├── app/
│ │ ├── App.cpp/.h bootstrap aplikacji
│ ├── cli/
│ │ ├── Cli.cpp/.h interfejs wiersza poleceń
│ ├── core/
│ │ ├── Report.h struktury danych: TradeRow, CashRow, YearSummary,
│ │ │ SymbolSummary, TaxYear, LossSlot, TaxReport, Report
│ │ ├── Report.cpp BuildReport() + Aggregate()
│ │ ├── TaxEngine.cpp BuildTaxReport(): PIT-38, carryforward, dywidendy
│ │ ├── InflationData.h constexpr kCpiFallback[], CpiFallbackForYear()
│ │ ├── InflationFetcher.h/.cpp async WinHTTP, cache, GUS BDL API
│ │ ├── StringUtil.h/.cpp formatowanie, kodowanie, daty
│ │ ├── XlsxReader.h/.cpp parser XLSX XML
│ │ ├── ZipReader.h/.cpp parser ZIP
│ │ └── Inflate.h/.cpp dekompresja DEFLATE
│ └── ui/
│ ├── MainDialog.h/.cpp główne okno dialogowe
│ ├── ChartView.h/.cpp wykres GDI
│ └── DarkMode.h ciemny motyw WinAPI
├── test/
│ └── test.xlsx przykładowy eksport XTB do testów
├── xtbrep.vcxproj projekt MSVC v145, C++23, x64/x86
├── xtbrep.vcxproj.filters filtry Solution Explorer
├── xtbrep.slnx plik solution
└── build.ps1 skrypt MSBuild PowerShell
Budowanie
Wymagania
- Visual Studio 2022 lub 2026 z toolsetem MSVC v145
- Windows SDK 10.0
- PowerShell 5.1+
Kompilacja
.\build.ps1
Lub bezpośrednio przez MSBuild:
msbuild xtbrep.vcxproj /p:Configuration=Release /p:Platform=x64
Konfiguracje projektu
| Konfiguracja | Optymalizacja | CRT |
|---|---|---|
| Debug | x64 | wyłączona | dynamiczny /MDd |
| Release | x64 | MaxSpeed /O2 |
statyczny /MT |
| Debug | Win32 | wyłączona | dynamiczny /MDd |
| Release | Win32 | MaxSpeed /O2 |
statyczny /MT |
Flagi kompilatora stosowane we wszystkich konfiguracjach:
/utf-8 kodowanie źródła i wykonania = UTF-8
/W4 wysoki poziom ostrzeżeń
/permissive- ścisła zgodność ISO C++
/sdl dodatkowe kontrole bezpieczeństwa
/std:c++latest C++23 (std::format, std::ranges, std::expected)
/Zc:__cplusplus __cplusplus odzwierciedla faktyczny standard
/Zc:preprocessor nowy preprocestor zgodny z normą
Release /MT zapewnia brak zależności od redistribuowalnych pakietów VC++.
Wymagania systemowe
| Składnik | Wymaganie |
|---|---|
| System operacyjny | Windows 10 lub nowszy (MICA wymaga Win11 22000+) |
| Architektura | x64 (projekt domyślny) lub Win32 |
| Zależności zewnętrzne | brak — wyłącznie WinAPI (comctl32, dwmapi, uxtheme, ole32, shell32, shlwapi, winhttp) |
| Plik wejściowy | eksport .xlsx z xStation XTB (Historia → Eksportuj) |
| Połączenie sieciowe | opcjonalne — wyłącznie do aktualizacji danych CPI z GUS BDL |
Eksport CSV i schowek
Przycisk Eksport CSV eksportuje aktywną zakładkę (z uwzględnieniem aktywnego filtra) do pliku CSV:
- Separator:
;(zgodny z polskim Excel) - Kodowanie: UTF-8 z BOM (
\xFEFF) — Excel otwiera bez konfiguracji - Pola z
;lub"są cytowane zgodnie z RFC 4180
Schowek Windows: prawy przycisk myszy na dowolnej liście → Kopiuj zaznaczone (tabulator jako separator) lub Kopiuj wszystkie. Podwójne kliknięcie wiersza = Kopiuj zaznaczone — z wyjątkiem zakładki Symbole, gdzie podwójne kliknięcie ustawia filtr.
C++23 — wybrane zastosowania
| Cecha | Gdzie użyta |
|---|---|
std::format / std::wformat |
formatowanie dat, kwot, procentów w całym UI |
std::ranges::sort / min_element / max_element |
sortowanie transakcji, szukanie dat granicznych |
std::ranges::stable_sort |
sortowanie ListView z zachowaniem kolejności równych elementów |
std::fma |
obliczenie inflRefAbs w RebuildBars() bez utraty precyzji |
| Designated initializers | inicjalizacja struktur konfiguracyjnych |
[[nodiscard]] |
BuildReport(), ComputeXirr(), wszystkie helpery zwracające wynik |
constexpr / inline constexpr |
tablica CPI w InflationData.h, stałe zasobów |
std::atomic<bool> |
guard jednoinstancyjny wątku InflationFetcher |
std::thread::detach |
wątek tła InflationFetcher bez zarządzania cyklem życia |
std::deque<LossSlot> |
kolejka carryforward strat podatkowych |
xtbrep v1.1.0 — C++23, WinAPI, zero zewnętrznych zależności.
kvc.pl | [email protected]