xtbrep — Analizator portfela XTB


xtbrep — Analizator portfela XTB

**Version 1.1.0** — Desktopowy analizator portfela XTB w WinAPI + C++23 *Wczytuje eksport XLSX z xStation i liczy P/L, XIRR, PIT-38, dywidendy, odsetki oraz porównanie z inflacją GUS.* *Zero zależności, czysty WinAPI, statyczne `/MT`, brak VC++ Redistributable.*

Spis treści


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 nr i (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ływu i, liczony jako (JDN_i − JDN_0) / 365.25
  • JDN — Juliański Numer Dnia (Julian Day Number) — algebraicznie poprawna reprezentacja dat bez problemu przestępnych lat

Przepływy gotówki używane w obliczeniu

flowchart LR A[Operacje gotowkowe XTB] --> B[Wektor CashFlow] C[Wartosc portfela teraz] --> B B --> D[XIRR Newton Raphson] D --> E[Stopa roczna]

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

flowchart TD UI[UI] --> Core[Core] Core --> IO[IO] Core --> Utils[Utils] UI --> CLI[CLI] App[App] --> UI App --> CLI UI -.->|WM_INFLATION_UPDATED| Core

Przepływ danych od pliku do ekranu

sequenceDiagram participant U as Uzytkownik participant D as MainDialog participant B as BuildReport participant X as XlsxReader participant T as TaxEngine participant F as InflationFetcher U->>D: otworz XLSX D->>B: BuildReport B->>X: Open X-->>B: Closed positions X-->>B: Cash operations B->>B: Parse i agreguj B->>T: BuildTaxReport T-->>B: TaxReport B-->>D: Report ok D->>D: Populate taby par Tlo F->>F: Fetch CPI F-->>D: WM_INFLATION_UPDATED D->>D: UpdateCpiData end

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:

flowchart LR TR[Trades] --> SM[SymbolSummary mapa] CA[Cash] --> SM SM --> SV[Symbols wektor]

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

flowchart TD YS[YearSummary] --> CHECK{Zysk?} CHECK -->|Nie| ADD[Dodaj strata] ADD --> EXPIRE[Usun po 5 latach] CHECK -->|Tak| APPLY[Zastosuj straty] APPLY --> TAX[Belka 19 procent] TAX --> NEXT[Nastepny rok] EXPIRE --> NEXT

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:

  1. Cache w %APPDATA%\xtbrep\cpi_cache.txt (jeśli cache ma ≤ 30 dni, używa cache; źródło w UI: cache GUS <rok>).
  2. 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)).
  3. Stary cache (gdy online nie działa, a cache istnieje; źródło w UI: cache GUS <rok> (przestarzały)).
  4. 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

flowchart LR START[Start] --> CT[Wbudowana CPI] START --> TH[Fetcher] TH --> CACHE{Cache swiezy} CACHE -->|Tak| POST[Update UI] CACHE -->|Nie| NET[Online GUS] NET -->|OK| WRITE[Zapis cache] WRITE --> POST NET -->|Fail| STALE{Stary cache} STALE -->|Tak| POST STALE -->|Nie| FAIL[Fallback wbudowany]

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.

flowchart LR XLSX[Plik XLSX] --> ZR[ZipReader] ZR --> INF[Inflate] INF --> XML[XlsxReader] XML --> ROWS[XlsxSheet] ROWS --> RP[Report]

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]