Sztuczna inteligencja w sprawozdawczości GAMAM

Narracja a rzeczywistość
Szkoła Główna Handlowa w Warszawie | 2026

AiDisclosures.pl

Środowisko badawcze AiDisclosures.pl umożliwia zdalne uruchomienie kodu źródłowego wykorzystanego w pracy magisterskiej „Sztuczna inteligencja w sprawozdawczości GAMAM. Narracja a rzeczywistość”.

W rozdziałach 1 i 2 pracy zidentyfikowano następujący problem: system rachunkowości US GAAP nie jest w stanie w pełni ująć wartości aktywów związanych ze sztuczną inteligencją. Inwestycje w R&D są natychmiastowo ujmowane w kosztach, a wiele kluczowych zasobów AI pozostaje księgowo niewidocznych. Powstaje więc luka informacyjna między tym, co pokazują dane finansowe, a tym, co inwestorzy chcieliby wiedzieć o potencjale technologicznym spółek. Odpowiedzią na tę lukę mają być ujawnienia narracyjne, czyli jakościowe opisy w raportach i telekonferencjach, przypuuszczalnie kompensujące ograniczenia rachunkowości. Rozdział 3 stanowi empiryczną weryfikację tej tezy. Skrypt realizuje tę weryfikację poprzez automatyczną analizę dokumentacji źródłowej spółek GAMAM.

Panel działa na serwerze z zainstalowanym środowiskiem R. Użytkownik może uruchomić skrypt za pomocą przycisku URUCHOM BADANIE, a wyniki są generowane automatycznie i wyświetlane w konsoli. Ponieważ dane źródłowe i kod są stałe, każde uruchomienie daje identyczne rezultaty. Istnieje możliwość pobrania kompletnego pakietu replikacyjnego (skrypt, dane, wyniki) oraz wglądu do dokumentacji źródłowej. Aby poznać szczegóły i etapy analizy, rozwiń panele poniżej.

Celem pracy jest empiryczna weryfikacja, czy ujawnienia narracyjne dotyczące AI w raportach 10-K, 10-Q i telekonferencjach wynikowych wpływają na reakcje rynku kapitałowego oraz czy ich obecność jest powiązana z rzeczywistymi decyzjami inwestycyjnymi spółek na przykładzie grupy GAMAM. Sformułowano następujące pytania badawcze:

  1. W których częściach raportów 10-K koncentrują się ujawnienia dotyczące sztucznej inteligencji?
  2. Czy intensywność ujawnień dotyczących sztucznej inteligencji różni się między kanałami komunikacji spółek?
  3. Czy istnieje związek między intensywnością ujawnień dotyczących sztucznej inteligencji a nakładami inwestycyjnymi (CAPEX) oraz wydatkami na badania i rozwój (R&D)?
  4. Czy publikacja dokumentów o wysokiej intensywności ujawnień dotyczących sztucznej inteligencji wywołuje istotne reakcje rynku mierzone nadmiarowymi stopami zwrotu?

Hipotezy badawcze:

  • H1: W raportach 10-K odniesienia do sztucznej inteligencji częściej pojawiają się w sekcjach narracyjnych niż w częściach zawierających dane finansowe.
  • H2: Liczba odniesień do sztucznej inteligencji jest wyższa w komunikacji zarządów z inwestorami niż w formalnych raportach rocznych 10-K.
  • H3: Spółki o wyższej skali inwestycji technologicznych, mierzonej relacją nakładów na badania i rozwój oraz nakładów inwestycyjnych do przychodów, wykazują większą liczbę odniesień do sztucznej inteligencji w ujawnieniach korporacyjnych.
  • H4: Publikacje wyników finansowych oraz telekonferencje wynikowe o relatywnie wysokiej liczbie odniesień do sztucznej inteligencji są związane z wyższymi nadmiarowymi stopami zwrotu akcji w krótkim okresie wokół daty publikacji.

Zmienne badawcze:

  • Ujawnienia AI:
    • AI_density – gęstość wystąpień terminów AI na 1000 słów dokumentu.
    • AI_general – udział terminów ogólnych.
    • AI_specific – udział terminów specjalistycznych.
    • AI_future – udział zdań o AI z orientacją przyszłościową.
    • AI_risk – udział zdań o AI zawierających odniesienia do ryzyka.
  • Skala inwestycji technologicznych:
    • R&D Intensity – wydatki na badania i rozwój / przychody.
    • CAPEX Intensity – nakłady inwestycyjne / przychody.
  • Reakcja rynku na ujawnienia AI:
    • CAR – skumulowana nadmiarowa stopa zwrotu w oknach [–1,+1], [–3,+3], [–5,+5].
  • Zmienne kontrolne:
    • SUE – standaryzowane zaskoczenie wynikami (EPS surprise).
    • Firma FE, Rok FE – efekty stałe.

Próba badawcza:

  • Spółki: Alphabet (GOOGL), Amazon (AMZN), Meta (META), Apple (AAPL), Microsoft (MSFT) – grupa GAMAM.
  • Okres: lata fiskalne 2022–2025. Dla badania zdarzeń – rzeczywiste daty publikacji w latach kalendarzowych 2022–2025.
  • Liczba dokumentów: 23 raporty 10-K, 62 raporty 10-Q, 85 transkrypcji earnings calls.
  • Dodatkowo: sekcje narracyjne (Business, MD&A, Risk Factors) wyodrębnione z 10-K oraz dane rynkowe dla badania zdarzeń.

Źródła danych:

Narzędzia badawcze:

  • Środowisko: R (wersja 4.3+).
  • Pakiety: tidyverse (dplyr, tidyr, stringr), pdftools, plm, lmtest, sandwich, clubSandwich, BayesFactor, quantreg, car, lubridate, readxl, shiny.

Procedura badawcza:

  1. Ekstrakcja tekstu z dokumentów źródłowych (PDF/TXT) z katalogów: 10K, 10-Q, earnings_calls, Business - Risk Factors - MD&A.
  2. Czyszczenie tekstu, normalizacja i tokenizacja (podział na słowa oraz zdania).
  3. Identyfikacja terminów związanych ze sztuczną inteligencją na podstawie autorskiego słownika (terminy ogólne, specyficzne, przyszłościowe i odniesienia do ryzyka). Słownik znajduje się w skrypcie badania (wiersze 129–205).
  4. Obliczenie gęstości wystąpień AI na 1 000 słów dla każdego dokumentu.
  5. Analiza zdań zawierających terminy AI pod kątem ich orientacji (przyszłościowa vs. ryzyko) oraz klasyfikacja terminów na ogólne i specjalistyczne.
  6. Synchronizacja lat fiskalnych na kalendarzowe dla spółek Microsoft i Apple.
  7. Podział transkrypcji earnings calls na część prezentacyjną i sesję Q&A.
  8. Agregacja wyników dla raportów 10-K, 10-Q i Earnings Calls z podziałem na firmy, lata i typ dokumentu.
  9. Badanie związku między ujawnieniami AI a nakładami inwestycyjnymi (CAPEX) i wydatkami na R&D: korelacje Spearmana oraz modele panelowe z efektami stałymi (FE).
  10. Obliczenie skumulowanych nadmiarowych stóp zwrotu (CAR), testy t i U Manna–Whitneya dla grup HIGH/LOW, test BMP, test Corrado, test placebo, analiza wolumenu, specyfikacje T+0 i bez 2022 oraz modele regresyjne M1–M3.
  11. Przeprowadzenie testów dodatkowych dla hipotezy H4: test permutacyjny, czynnik Bayesa, regresja kwantylowa, bootstrapowy przedział ufności oraz analiza zmiany intensywności ujawnień AI (delta_density)
  12. Generowanie tabel i zestawień opisanych w strukturze wyników.

Zastosowane metody statystyczne:

  • Współczynnik korelacji Spearmana: związek CAPEX/R&D z gęstością ujawnień AI.
  • Modele panelowe: estymacja z efektami stałymi (FE) z estymatorem HC3 dla CAPEX/R&D (eksploracyjnie; ograniczona liczba obserwacji).
  • Event study: model rynkowy Sharpe'a (120-dniowe okno estymacyjne), CAR dla okien [–1,+1], [–2,+2], [–3,+3], [–5,+5], testy t Welcha oraz U Manna-Whitneya (porównanie grup HIGH/LOW), test BMP, test Corrado, analiza placebo (jako walidacja metody).
  • Modele regresyjne (M1–M3): M1: CAR ~ AI (HC3), M2: CAR ~ AI + SUE (HC3), M3: CAR ~ AI + SUE + efekty stałe (firma, rok) z estymatorem CR2.
  • Testy dodatkowe dla event study: test permutacyjny, czynnik Bayesa, regresja kwantylowa, bootstrapowy przedział ufności, modele regresyjne z delta_density.

I. Raporty 10-K

  • Dla każdego raportu rocznego skrypt wyświetla:
    • nazwę spółki i rok,
    • łączną liczbę wystąpień terminów AI,
    • gęstość wystąpień AI na 1000 słów,
    • procent zdań z AI zawierających wskaźniki przyszłościowe,
    • procent zdań z AI zawierających wskaźniki ryzyka.
  • Tabela 5: Łączna liczba wystąpień terminów AI w każdym raporcie rocznym, w podziale na spółki i lata, wraz ze średnią w okresie 2022–2025.
  • Tabela 6: Gęstość wystąpień AI na 1000 słów w każdym raporcie rocznym, w podziale na spółki i lata, wraz ze średnią 2022–2025.
  • Tabela 6.1: Średnia gęstość dla całej grupy GAMAM w każdym roku.

II. Sekcje narracyjne 10-K

  • Dla każdej sekcji (Business, MD&A, Risk Factors) skrypt wyświetla:
    • nazwę spółki, rok i nazwę sekcji,
    • liczbę wystąpień terminów AI,
    • gęstość wystąpień AI na 1000 słów.
  • Tabela 7: Średnia gęstość AI w każdej z trzech sekcji narracyjnych w poszczególnych latach, wraz z testem Kruskala-Wallisa sprawdzającym, czy różnice między sekcjami są istotne statystycznie.
  • Tabela 8: Porównanie zagregowanej gęstości w sekcjach narracyjnych vs. części finansowej raportu, wraz z weryfikacją hipotezy H1.

III. Raporty 10-Q

  • Dla każdego raportu kwartalnego skrypt wyświetla:
    • nazwę spółki, rok kalendarzowy i kwartał (po synchronizacji),
    • liczbę wystąpień terminów AI,
    • gęstość wystąpień AI na 1000 słów.
  • Tabela 10: Gęstość AI w raportach kwartalnych – zsumowana z Q1, Q2, Q3 dla każdego roku (agregacja roczna), wraz ze średnią 2022–2025, zmianą w sztukach i zmianą procentową pomiędzy latami 2022 i 2025.
  • Tabela 10.1: Średnia gęstość dla całej grupy GAMAM w poszczególnych latach.

IV. Earnings Calls

  • Dla każdej transkrypcji skrypt wyświetla:
    • nazwę spółki, rok fiskalny, kwartał i rok kalendarzowy (po synchronizacji),
    • liczbę wystąpień terminów AI,
    • gęstość wystąpień AI na 1000 słów,
    • procent zdań z AI zawierających wskaźniki przyszłościowe,
    • procent zdań z AI zawierających wskaźniki ryzyka.
  • Tabela 13: Średnia roczna gęstość AI w telekonferencjach dla każdej spółki.
  • Tabela 13.1: Średnia gęstość dla całej grupy GAMAM w poszczególnych latach.
  • Tabela 13.2: Podział na część prezentacyjną i sesję Q&A – gęstość AI w każdej z nich oraz udział procentowy prezentacji.
  • Tabela 13.3: Podział prezentacja/Q&A dla każdej spółki w 2025 roku.
  • Korelacja Spearmana: Współczynnik korelacji między gęstością AI w prezentacji a w sesji Q&A.
  • Tabela 14: Porównanie EC vs. 10-K – średnie gęstości i iloraz (EC / 10-K).
  • Weryfikacja H2: Porównanie średniej gęstości EC, 10-K i 10-Q wraz z wnioskiem.

V. Korelacje z R&D i CAPEX

  • Tabela 16.1: Korelacje Spearmana (globalne) – związek R&D i CAPEX z gęstością AI w 10-K, wraz z poziomami istotności.
  • Tabela 16.2: Korelacje wewnątrz poszczególnych spółek (eksploracyjne, n = 4).
  • Tabela 17: Modele panelowe z efektami stałymi (FE) dla 10-K:
    • model CAPEX (surowy) – współczynnik, błąd, wartości t i p,
    • miary dopasowania: within R², between R², liczba obserwacji, liczba firm,
    • model R&D (surowy),
    • model łączny CAPEX + R&D,
    • model CAPEX (log-log),
    • model R&D (log-log),
    • model CAPEX + efekty czasowe (rok).
  • Test Hausmana: Porównanie FE vs. RE z uzasadnieniem wyboru FE.
  • Test F: Porównanie FE vs. Pooled OLS.
  • Diagnostyka modelu panelowego (10-K):
    • VIF (współliniowość) – wartości GVIF dla każdej zmiennej,
    • test Breuscha-Pagana (heteroskedastyczność),
    • test Wooldridge'a (autokorelacja).
  • Tabela 16.3: Korelacje Spearmana dla Earnings Calls (globalne i wewnątrz spółek).
  • Tabela 16.4: Modele regresji panelowej FE dla Earnings Calls – R&D, log-log CAPEX, log-log R&D, CAPEX + czas.
  • Weryfikacja H3: Podsumowanie wpływu CAPEX i R&D na gęstość ujawnień AI.

VI. Analiza jakościowa

  • Dla całej grupy GAMAM – udział terminów ogólnych vs. specyficznych oraz udział zdań o AI zawierających wskaźniki przyszłościowe vs. ryzyka (osobno dla 10-K i EC).
  • Tabela 22.1: Powyższe w podziale na spółki.

VII. Event Study

  • Obliczanie CAR: Dla każdego zdarzenia skrypt oblicza skumulowane nadmiarowe stopy zwrotu (CAR) w czterech przedziałach czasowych: [-1,+1], [-2,+2], [-3,+3], [-5,+5] dni wokół daty zdarzenia. Wykorzystuje model jednoczynnikowy Sharpe’a estymowany na 120-dniowym oknie estymacyjnym.
  • Mediany gęstości AI: Wyświetla mediany dla 10-K, 10-Q i Earnings Calls, służące do podziału na grupy HIGH i LOW.
  • Tabela 23 (CAAR): Średnie skumulowane nadmiarowe stopy zwrotu dla każdego typu dokumentu w czterech oknach czasowych, wraz z testem t sprawdzającym, czy CAAR jest istotnie różne od zera.
  • Tabela 24: Porównanie CAR między grupami HIGH i LOW – średnie, odchylenia standardowe, mediany, test t i test U Manna-Whitneya dla każdego typu dokumentu i okna.
  • Tabela 26 (BMP): Standaryzowane CAR (SCAR) z testem BMP – dla całej próby i dla grup HIGH/LOW, wraz z wartościami Z i p.
  • Analiza wolumenu: Średnia procentowa zmiana wolumenu obrotu w oknie zdarzenia względem średniej z 50 dni poprzedzających, porównanie między grupami HIGH i LOW z testem t.
  • Specyfikacja T+0: Analiza tylko dla dnia publikacji – różnica HIGH vs LOW, wartości p z testu t i U Manna-Whitneya.
  • Specyfikacja bez 2022: Analiza z wyłączeniem roku 2022.
  • Test placebo: Losowe przesunięcie dat zdarzeń o ±30-60 dni – średni CAR placebo, wartości t i p. Wielokrotny test placebo (100 powtórzeń) – średnie p i odsetek istotnych wyników.
  • Diagnostyka modelu regresyjnego (Earnings Calls):
    • test Shapiro-Wilka (normalność CAR),
    • test Levene'a (równość wariancji HIGH vs LOW),
    • VIF (współliniowość AI i SUE),
    • test Breuscha-Pagana (heteroskedastyczność).
  • Modele regresyjne H4:
    • M1: CAR ~ AI (HC3) – zmienna ciągła i binarna,
    • M2: CAR ~ AI + SUE (HC3) – zmienna ciągła i binarna,
    • M3: CAR ~ AI + SUE + efekty stałe (firma, rok) z estymatorem CR2.
  • Podsumowanie modeli: Współczynniki dla AI we wszystkich modelach z poziomami istotności.
  • Miary dopasowania: R², Adj. R², F, p, N dla każdego modelu.
  • Test łącznej istotności efektów stałych (M3): Testy dla efektów firmy, roku oraz łącznie.
  • Test Corrado: Nieparametryczny test nadmiarowych stóp zwrotu z wykorzystaniem rang – wyniki dla poszczególnych dni oraz test łączny dla całego okna, dla każdego typu dokumentu.

VIII. Testy dodatkowe dla H4

  • Test permutacyjny: Obserwowana różnica średnich CAR między grupami HIGH i LOW oraz p z 10 000 permutacji.
  • Bayes Factor: siła dowodu na rzecz braku różnicy (BF < 1/3 = dowód za brakiem różnicy).
  • Regresja kwantylowa: Różnica median CAR między grupami HIGH i LOW.
  • Bootstrapowy przedział ufności: 95% CI dla różnicy średnich CAR.
  • Analiza delta_density: Modele FE sprawdzające reakcję rynku na zmianę intensywności ujawnień AI (wzrost vs spadek względem poprzedniego okresu) – rozkład kierunków zmian w poszczególnych latach, modele CAR ~ delta_density + rok oraz CAR ~ delta_density + EPS + rok.
  • Podsumowanie testów dodatkowych: Zestawienie wyników z wnioskami.

W podglądzie dokumentów fragmenty tekstu oznaczone są kolorami: żółte podświetlenie oznacza słowa dotyczące sztucznej inteligencji, a różowe podświetlenie oznacza słowa z orientacją przyszłościową lub odniesieniem do ryzyk. Dla danych rynkowych poniżej przedstawiono objaśnienie kolumn w poszczególnych dokumentach.

Notowania spółek i S&P 500:

  • Data – data notowania,
  • Otwarcie – cena otwarcia,
  • Najwyzszy – cena najwyższa,
  • Najnizszy – cena najniższa,
  • Zamkniecie – cena zamknięcia,
  • Wolumen – wolumen obrotu.

Daty zdarzeń i EPS surprise:

  • event_id – identyfikator zdarzenia,
  • firm_symbol – symbol spółki,
  • group – typ dokumentu (10-K, 10-Q, EC),
  • event_date – data publikacji,
  • year – rok fiskalny,
  • quarter – kwartał fiskalny,
  • eps_surprise – zaskoczenie zyskami (EPS).

Pozostałe kolumny (event_window_start, event_window_end, estimation_window_start i estimation_window_end) określają liczbę dni przed i po dacie zdarzenia: event_window to maksymalne okno zdarzeń, a estimation_window to okno estymacji modelu rynkowego.

Autor: Patryk Sęk, Szkoła Główna Handlowa w Warszawie

Kontakt: ps141537@student.sgh.waw.pl

Wyniki badania

Poniżej przedstawiono najważniejsze ustalenia analizy empirycznej przeprowadzonej na podstawie dokumentacji spółek GAMAM w latach 2022–2025. Wyniki zaprezentowano w kolejności odpowiadającej strukturze rozdziału III pracy magisterskiej.

I. Skala inwestycji technologicznych

Analiza wykazała znaczne zróżnicowanie intensywności inwestycji technologicznych w grupie GAMAM. Meta Platforms, Inc. charakteryzuje się najwyższą intensywnością wydatków na badania i rozwój (R&D Intensity) średnio na poziomie 28,51% przychodów, podczas gdy Apple Inc. osiąga najniższy wynik (7,70%). W przypadku nakładów inwestycyjnych (CAPEX Intensity) Meta ponownie przewodzi z średnią 26,08%, przy czym w 2025 r. wskaźnik ten sięgnął rekordowego poziomu 34,68%. Szczególnie istotny wzrost CAPEX nastąpił w latach 2024–2025, kiedy to Alphabet (wzrost o 11,57 p.p.) oraz Microsoft (wzrost o 10,86 p.p.) znacznie zwiększyli skalę inwestycji infrastrukturalnych. Na tym tle wyraźnie odstaje Apple, u którego CAPEX Intensity utrzymuje się na stabilnie niskim poziomie (2,76% średnio, zmiana o 0,34 p.p. w badanym okresie), co wskazuje na ograniczoną skalę inwestycji w fizyczne zaplecze dla sztucznej inteligencji.

II. Gęstość ujawnień AI w raportach 10-K

W analizowanym okresie nastąpił wielokrotny wzrost liczby odniesień do AI we wszystkich spółkach grupy. Łączna liczba wystąpień terminów AI w raportach rocznych wzrosła średnio o 341% w skali grupy, przy czym największy wzrost odnotowała Meta Platforms, Inc. (z 30 do 166 wystąpień, +453%). Jeszcze bardziej wymownym wskaźnikiem jest gęstość wystąpień na 1000 słów – średnia dla grupy GAMAM wzrosła z 0,42 w 2022 r. do 1,63 w 2025 r. (wzrost o 288%). Szczególnie dynamiczny wzrost nastąpił na przełomie 2022 i 2023 r., co koresponduje z premierą ChatGPT. Alphabet osiągnął najwyższą średnią gęstość (2,23), podczas gdy Apple pozostaje na najniższym poziomie (0,13).

III. Lokalizacja ujawnień AI w strukturze raportu 10-K – weryfikacja H1

Analiza struktury raportów 10-K ujawnia wyraźną koncentrację ujawnień dotyczących AI w sekcjach narracyjnych. Gęstość odniesień w sekcjach Business, MD&A i Risk Factors jest od 7 do 12 razy wyższa niż w części finansowej raportu. W 2022 r. dominującą sekcją był Business (51,4% wszystkich ujawnień), jednak w 2025 r. nastąpiło wyraźne przesunięcie w kierunku sekcji Risk Factors, która zgromadziła 50,8% wszystkich odniesień do AI. Świadczy to o ewolucji postrzegania AI – od technologii stanowiącej źródło przewagi konkurencyjnej, w kierunku istotnego źródła ryzyka operacyjnego, regulacyjnego i systemowego.

Hipoteza H1 została potwierdzona – odniesienia do AI w raportach 10-K częściej pojawiają się w sekcjach narracyjnych niż w częściach zawierających dane finansowe.

IV. Raporty 10-Q – porównanie z 10-K

W przypadku raportów kwartalnych 10-Q również zaobserwowano wyraźny trend wzrostowy. Średnia gęstość dla grupy GAMAM wzrosła z 0,19 w 2022 r. do 1,07 w 2025 r. (wzrost o 463%). Najwyższy wzrost odnotował Microsoft (z 0,56 do 3,17), a następnie Meta (z 0,21 do 1,34). W przeciwieństwie do raportów 10-K, w przypadku 10-Q nie nastąpił gwałtowny skok już w 2023 r. – wzrost był bardziej stopniowy, co sugeruje, że spółki szybciej reagowały na przełom technologiczny w komunikatach rocznych niż kwartalnych. Raporty 10-K charakteryzują się systematycznie wyższą gęstością ujawnień AI niż 10-Q, przy czym dystans między nimi zmniejszył się w latach 2024–2025, co wskazuje na stabilizację komunikacji.

V. Ujawnienia AI w telekonferencjach wynikowych – weryfikacja H2

Telekonferencje wynikowe okazały się kanałem komunikacji o AI o zdecydowanie największej intensywności. Łącznie 80 transkrypcji zawierało 5477 odniesień do AI, podczas gdy 20 raportów 10-K – 1446, a 60 raportów 10-Q – 1333. Średnia gęstość dla grupy GAMAM w earnings calls wzrosła z 2,08 w 2022 r. do 10,32 w 2025 r. (wzrost o 396%). Gęstość ujawnień w telekonferencjach była od 5 do ponad 7 razy wyższa niż w raportach 10-K. Szczególnie istotny wzrost nastąpił w I kwartale 2023 r. (wzrost o 74% w skali grupy), bezpośrednio po premierze ChatGPT. Microsoft odnotował wzrost z 5,56 w Q4 2022 do 10,95 w Q1 2023 (o 97%), podczas gdy Alphabet utrzymywał wysoki poziom ujawnień już przed przełomem (10,24 w Q4 2022). Analiza podziału na część prezentacyjną i sesję Q&A wykazała, że gęstość ujawnień jest wyższa w części prezentacyjnej (12,9 w 2025 r.) niż w Q&A (8,14), przy czym udział prezentacji w całkowitej liczbie słów wynosi około 47%. Korelacja Spearmana między gęstością AI w prezentacji a w Q&A wyniosła 0,847 (p < 0,001), co wskazuje na silny związek między komunikacją w obu częściach.

Hipoteza H2 została potwierdzona – liczba odniesień do AI jest wyższa w komunikacji zarządów z inwestorami (earnings calls) niż w raportach rocznych 10-K.

Rysunek 1 przedstawia ewolucję gęstości odniesień do AI w grupie GAMAM w podziale na kolejne kwartały badanego przedziału czasowego.

VI. Ranking spółek według intensywności ujawnień AI

Analiza porównawcza ujawniła trzy grupy spółek o zróżnicowanej strategii komunikacyjnej. Microsoft Corp. (2467 łącznych odniesień) oraz Alphabet Inc. (2105) stanowią liderów, konsekwentnie komunikując AI zarówno w dokumentach formalnych, jak i w telekonferencjach. Meta Platforms (2310 łącznie, przy czym najwięcej w 10-Q – 672) zajmuje trzecią pozycję, osiągając najwyższą pojedyńczą kwartalną gęstość w earnings calls (13,96 w Q2 2024). Amazon.com (998 łącznie) wykazał najdynamiczniejszy wzrost względny – z 0,08 w 2022 r. do 7,83 w 2025 r. w earnings calls (ponad 9688%). Apple Inc. (376 łącznie) pozostaje zdecydowanym ostatnim, ze średnią gęstością 0,13 w 10-K, 0,05 w 10-Q i 2,70 w earnings calls, co odzwierciedla marginalne znaczenie tematyki AI w jej komunikacji. Rysunek 2 przedstawia łączne liczby ujawnień i gęstości dla każdej ze spółek

VII. Zależność między inwestycjami a ujawnieniami AI – weryfikacja H3

Korelacje Spearmana dla całej próby wykazały, że nakłady inwestycyjne (CAPEX) są umiarkowanie dodatnio skorelowane z ujawnieniami AI: ρ = 0,60 dla 10-K (p = 0,005) oraz ρ = 0,51 dla earnings calls (p = 0,023). Oznacza to, że wyższym nakładom inwestycyjnym towarzyszy przeciętnie wyższa intensywność komunikacji o AI. Wydatki na badania i rozwój (R&D) wykazują słabszy związek: ρ = 0,41 dla 10-K (p = 0,074) oraz ρ = 0,24 dla earnings calls (p = 0,301) – żaden z wyników nie osiągnął przyjętego poziomu istotności. Eksploracyjne modele panelowe z efektami stałymi (FE) dla 10-K wykazały istotny wpływ CAPEX na gęstość ujawnień AI w modelu surowym (β = 0,077; p = 0,014) oraz w modelu log-log (β = 1,102; p = 0,003), co oznacza, że wzrostowi CAPEX o 1% towarzyszy wzrost gęstości ujawnień AI o około 1,1%. Po kontroli trendu czasowego efekt ten traci istotność (p = 0,094), co sugeruje, że obserwowana zależność może wynikać z ogólnego trendu wzrostowego, a nie indywidualnych decyzji inwestycyjnych spółek. Dla earnings calls CAPEX okazał się nieistotny we wszystkich specyfikacjach. R&D pozostawało nieistotne we wszystkich modelach.

Hipoteza H3 nie została potwierdzona – R&D nie wykazuje istotnego związku z gęstością ujawnień AI w żadnym kanale komunikacji, pomimo umiarkowanej zależności w przypadku CAPEX.

Rysunek 3 przedstawia wykresy rozrzutu z liniami regresji Pearsona, obrazujące wziualny związek między nakładami na CAPEX oraz R&D a gęstością ujawnień AI w raportach 10-K i telekonferencjach wynikowych (EC).

VIII. Analiza jakościowa ujawnień

Analiza jakościowa ujawniła kształtowanie się pięciu głównych kategorii tematycznych w raportach 10-K: regulacyjna, kosztowa, operacyjna, inwestycyjna oraz konkurencyjna. W 2022 r. dominowały komunikaty operacyjne o zastosowaniach AI w istniejących produktach. W 2023 r. narracja przesunęła się w kierunku wątków inwestycyjnych (rozwój własnych modeli, partnerstwa strategiczne). W latach 2024–2025 nastąpiło dalsze przesunięcie w stronę ujawnień o charakterze kosztowym (rosnące CAPEX na centra danych) i regulacyjnym (AI Act, odpowiedzialność za treści generowane przez modele).

Sekcja Risk Factors raportów 10-K pokazuje ewolucję postrzegania ryzyka: od problemów technicznych i operacyjnych w latach 2022–2023, przez ryzyka regulacyjne i odpowiedzialności prawnej w 2024 r., po ryzyka systemowe i infrastrukturalne w 2025 r. (zależność od łańcuchów dostaw GPU/TPU, bezpieczeństwo modeli, dezinformacja). Co istotne, mimo rosnącej szczegółowości, sekcje ryzyk nie odnoszą się do egzystencjalnych zagrożeń związanych z AI.

Analiza konkretyzacji zamierzeń wykazała przejście od ogólnych deklaracji strategicznych w latach 2022–2023 do coraz bardziej szczegółowych opisów modeli, partnerstw i wdrożeń w latach 2024–2025. Microsoft i Alphabet jako pierwsi wprowadzili nazwy własnych produktów (Copilot, Gemini), Meta przeszła do otwartego mówienia o superinteligencji, a Apple po okresie bardzo ogólnej komunikacji w 2024 r. ogłosił debiut Apple Intelligence.

Struktura terminologiczna różni się między kanałami. W raportach 10-K dominują terminy ogólne (77,2% wobec 52,6% w EC), podczas gdy w earnings calls częściej pojawiają się terminy specyficzne (47,4% wobec 22,8% w 10-K). Udział zdań o AI z odniesieniami do ryzyka jest prawie sześciokrotnie wyższy w 10-K (35,1%) niż w EC (6,0%). Natomiast udział zdań o AI z orientacją przyszłościową jest wyższy w 10-K (29,8%) niż w EC (21,7%) – co wynika z obligatoryjnego charakteru sekcji MD&A i Risk Factors, które wymuszają wybieganie w przyszłość.

IX. Reakcja rynku na ujawnienia AI – badanie zdarzeń (H4)

Badanie zdarzeń przeprowadzono na próbie 160 zdarzeń (20 raportów 10-K, 60 raportów 10-Q oraz 80 telekonferencji wynikowych).

Średnie skumulowane nadmiarowe stopy zwrotu (CAAR) dla wszystkich typów dokumentów we wszystkich oknach czasowych są bliskie zeru i nieistotne statystycznie (najniższe p = 0,713 dla 10-K w oknie [-5,+5]). Oznacza to, że przeciętnie publikacje wyników finansowych ani telekonferencje nie wywołują systematycznej reakcji rynku.

Podział zdarzeń na grupy HIGH (wysoka gęstość ujawnień AI) i LOW (niska gęstość) nie wykazał istotnych różnic w CAR. Dla okna [-1,+1] różnica średnich CAR wyniosła: 0,00992 dla 10-K (p = 0,768), 0,01482 dla 10-Q (p = 0,521) oraz 0,00583 dla earnings calls (p = 0,842). Żaden z wyników nie był istotny statystycznie, a w przypadku 10-K i EC mediany CAR dla grup LOW były wyższe niż dla HIGH, co jest kierunkiem przeciwnym do zakładanego.

Rysunek 4 przedstawia zestawienie średnich skumulowanych nadmiarowych stóp zwrotu (CAAR) dla całej próby oraz porównanie średnich i median CAR dla grup o wysokim (HIGH) i niskim (LOW) nasyceniu ujawnieniami AI. Naniesione na wykresy średnich 95-procentowe przedziały ufności, silnie przecinające poziom zera, wraz z niespójnością kierunkową median, wizualizują całkowity brak statystycznej istotności (p > 0,05) i losowy charakter reakcji rynku na te informacje.

Modele regresyjne M1–M3 (odpowiednio: CAR ~ AI, CAR ~ AI + SUE, CAR ~ AI + SUE + FE) wykazały, że współczynnik dla zmiennej AI pozostaje nieistotny we wszystkich sześciu specyfikacjach (p między 0,598 a 0,916). Modele cechują się bardzo niskimi wartościami (0,0027–0,0938), co oznacza, że wyjaśniają jedynie minimalną część zmienności CAR.

Test BMP (kontrola zmienności indukowanej zdarzeniem) wykazał, że w dniach publikacji dokumentów dochodzi do wyraźnego wzrostu zmienności (SD SCAR = 4,47–8,93 vs oczekiwane 1,0), ale nie przekłada się to na systematyczne, kierunkowe nadmiarowe stopy zwrotu. Wszystkie wartości p dla testu BMP były nieistotne (najniższe p = 0,499).

Analiza wolumenu obrotu wykazała znaczny wzrost w dniach zdarzeń (od 53,4% do 85,4% w zależności od grupy), co potwierdza, że dni publikacji wyników są okresami podwyższonej aktywności inwestorów. Różnice między grupami HIGH i LOW nie były istotne statystycznie (p = 0,172 dla 10-K, p = 0,968 dla 10-Q, p = 0,199 dla EC).

Testy alternatywne dla earnings calls: test permutacyjny (p = 0,743), Bayes Factor (BF = 0,244, co stanowi pozytywny dowód na rzecz braku różnicy), regresja kwantylowa (p = 0,742), bootstrapowy 95% przedział ufności (obejmuje zero). Test placebo z losowym przesunięciem dat zdarzeń o ±30-60 dni dał średnią p-value 0,5446 przy odsetku istotnych wyników 2% (mniej niż oczekiwane 5%), co potwierdza poprawność metody.

Hipoteza H4 nie została potwierdzona – publikacja wyników finansowych oraz telekonferencje wynikowe o relatywnie wysokiej liczbie odniesień do AI nie są związane z wyższymi nadmiarowymi stopami zwrotu akcji w krótkim okresie wokół publikacji dokumentu. Wynik ten jest spójny niezależnie od typu dokumentu, okna zdarzenia, zastosowanego testu czy specyfikacji modelu.

X. Podsumowanie weryfikacji hipotez

  • H1 – POTWIERDZONA: W raportach 10-K odniesienia do AI częściej pojawiają się w sekcjach narracyjnych (Business, MD&A, Risk Factors) niż w częściach zawierających dane finansowe. Gęstość ujawnień w sekcjach narracyjnych jest od 7 do 12 razy wyższa.
  • H2 – POTWIERDZONA: Liczba odniesień do AI jest wyższa w komunikacji zarządów z inwestorami (earnings calls) niż w formalnych raportach rocznych 10-K. Gęstość ujawnień w telekonferencjach jest od 5 do ponad 7 razy wyższa.
  • H3 – NIE POTWIERDZONA: R&D nie wykazuje istotnego związku z gęstością ujawnień AI. CAPEX wykazuje umiarkowaną zależność.
  • H4 – NIE POTWIERDZONA: Wyższa intensywność ujawnień AI nie przekłada się na wyższe nadmiarowe stopy zwrotu w krótkim okresie wokół publikacji. Wynik jest spójny we wszystkich testach i specyfikacjach.

XI. Główne wnioski z badania

  • AI stała się trwałym i intensywnym elementem komunikacji korporacyjnej – liczba odniesień do AI we wszystkich analizowanych kanałach komunikacji wzrosła wielokrotnie, a największą dynamikę zaobserwowano w telekonferencjach wynikowych.
  • Nastąpiło przesunięcie akcentów w ujawnieniach – od ogólnych deklaracji strategicznych, przez konkretyzację produktów i modeli, po ujawnienia finansowe i długoterminowe zobowiązania inwestycyjne, a także identyfikację ryzyk systemowych.
  • CAPEX, a nie R&D, wykazuje związek z intensywnością komunikacji o AI – inwestycje infrastrukturalne są silniej komunikowane niż wydatki badawcze, co sugeruje, że spółki postrzegają fizyczną skalę inwestycji jako bardziej wiarygodny sygnał dla rynku.
  • Rynek nie wycenia ujawnień AI w krótkim okresie – inwestorzy nie traktują ujawnień dotyczących AI w komunikacji wynikowej jako nowej, wartościowej informacji wpływającej na decyzje inwestycyjne w krótkim horyzoncie. Narracja o AI pełni funkcję informacyjną i strategiczną, ale nie ma charakteru bezpośrednio cenotwórczego.
  • Możliwe funkcje długookresowe narracji o AI – brak krótkookresowej reakcji rynku nie przesądza o braku wartości informacyjnej ujawnień. Narracja może pełnić funkcję stopniowego budowania przekonania oraz redukcji asymetrii informacyjnej w dłuższym horyzoncie.

XII. Ograniczenia i kierunki przyszłych badań

Ograniczenia badania:

  • Ograniczona liczebność próby: 5 spółek, 23 raporty 10-K, 62 raporty 10-Q i 85 transkrypcji ogranicza możliwość uogólnienia wyników na cały sektor technologiczny, a tym bardziej na dowolne przedsiębiorstwa inwestujące w sztuczną inteligencję.
  • Autorski słownik AI: subiektywny dobór terminów może wpływać na wyniki.
  • Interpretacja narracji: analiza ilościowa oparta na zliczaniu słów kluczowych, choć obiektywna i powtarzalna, nie oddaje w pełni kontekstu semantycznego. Możliwe jest występowanie klasyfikacji fałszywie pozytywnych oraz fałszywie negatywnych.
  • Ekstrakcja tekstu z PDF: ryzyko błędów w odczycie (np. podźial wyrazów na końcu wiersza, formatowanie).
  • Ograniczenia zapisu transkrypcji: transkrypcje telekonferencji wynikowych podlegają zautomatyzowanej konwersji mowy na tekst, co może wprowadzać błędy w rozpoznawaniu terminów technicznych.
  • Problem przyczynowości: analiza zdarzeń pozwala na identyfikację współwystępowania ujawnień i reakcji rynku, ale nie rozstrzyga o związku przyczynowym. Nakładające się okna zdarzeń oraz czynniki zewnętrzne (np. rynkowe, makroekonomiczne) mogą zakłócać wyniki.
  • Selektywność okresu badawczego: lata 2022–2025 to okres wyjątkowo intensywnego rozwoju technologii AI, co może skutkować zawyżeniem obserwowanej intensywności ujawnień w stosunku do długookresowych trendów.
  • Brak istotnych zmiennych: analiza nie obejmuje kontekstu strategicznego ani kultury organizacyjnej spółek.

Kierunki przyszłych badań:

  • Rozszerzenie próby: objęcie bardziej zróżnicowanych spółek – o mniejszej skali działalności, z sektorów tradycyjnych (np. finanse, opieka zdrowotna, produkcja) lub działających w innych jurysdykcjach regulacyjnych.
  • Zaawansowane techniki NLP: wykorzystanie analizy sentymentu czy klasyfikacji intencji wypowiedzi, co pozwoliłoby na bardziej subtelną ocenę jakości i charakteru ujawnień.
  • Długookresowe efekty: zbadanie wpływu narracji o AI na wyceny w dłuższym horyzoncie, np. poprzez modele długookresowych nadmiarowych stóp zwrotu lub analizę zmian kosztu kapitału.
  • Porównanie z innymi narracjami technologicznymi: reakcje rynku na narrację o AI vs. wcześniejsze narracje (np. big data, cloud computing).
  • Przedłużenie okresu badawczego: objęcie okresu 2026–2032, w celu oceny, czy po wygaśnięciu początkowej euforii związek między ujawnieniami a reakcjami rynku ulegnie zmianie.
Skrypt badania
# =====================================================================
# MASTER SCRIPT  
# =====================================================================
#
# SPIS TREŚCI 
# 0. Instalacja i wczytanie bibliotek – wiersz 107
#    (ładowanie wszystkich niezbędnych pakietów)
# 00. Uniwersalny słownik – w. 125
#    (terminy ogólne, specyficzne, future, risk)
# 000. Funkcje pomocnicze – w. 208
#    (zliczanie terminów, słów, segmentacja zdań, synchronizacja kalendarzowa)
# I. Analiza raportów 10-K (całe raporty) – w. 376
#    - Analiza całych raportów 10-K (gęstość AI na 1000 słów)
#    - Tabela 5: Liczba odniesień do AI
#    - Tabela 6: Gęstość na 1000 słów
#    - Tabela 6.1: Średnia dla grupy GAMAM
# II. Analiza sekcji narracyjnych (Business, MD&A, Risk Factors) – w. 456
#    - Analiza gęstości AI w poszczególnych sekcjach
#    - Test Kruskala-Wallisa różnic między sekcjami
#    - Tabela H1: Porównanie sekcji narracyjnych vs finansowa
#    - Weryfikacja hipotezy H1
# III. Analiza raportów 10-Q – w. 549
#    - Synchronizacja kalendarzowa (rok fiskalny → kalendarzowy)
#    - Agregacja roczna (Q1-Q3)
#    - Tabela 10: Gęstość 10-Q
#    - Tabela 10.1: Średnia GAMAM (10-Q)
# IV. Analiza Earnings Calls – w. 697
#    - Synchronizacja kalendarzowa (rok fiskalny → kalendarzowy)
#    - Podział na presentation i Q&A
#    - Tabela 13: Gęstość EC (średnia roczna)
#    - Tabela 13.1: Średnia GAMAM (EC)
#    - Tabela 13.2: Podział presentation/Q&A
#    - Korelacja Spearmana: presentation vs Q&A
#    - Porównanie EC vs 10-K - weryfikacja H2
# V. Korelacje ujawnień z R&D i CAPEX (H3) – w. 913
#    - Korelacje Spearmana (globalne i wewnątrz spółek)
#    - Regresja panelowa Fixed Effects (10-K)
#      * Model CAPEX (surowy)
#      * Model R&D (surowy)
#      * Model łączny CAPEX + R&D
#      * Modele log-log
#      * Model z efektami czasowymi
#    - Test Hausmana (FE vs RE)
#    - Test F (FE vs Pooled OLS)
#    - Tabela 16: Korelacje Spearmana dla EC
#    - Tabela 17: Modele panelowe dla EC
#    - Weryfikacja hipotezy H3
# VI. Analiza jakościowa (Future/Risk, General/Specific) – w. 1290
#    - Analiza kontekstu: Future i Risk w zdaniach z AI
#    - Podział na terminy ogólne i specyficzne
#    - Tabela 22: Średnia dla grupy GAMAM
#    - Tabela 23: Podział na spółki
# VII. Event Study – w. 1328
#    - Obliczanie CAR dla okien [-1,+1], [-3,+3], [-5,+5]
#    - Podział na HIGH/LOW według mediany gęstości AI
#    - Tabele 26 i 25: Test hipotezy H4 (regresja + Mann-Whitney)
#    - CAAR (średnie CAR) z testem t
#    - Regresja CAR (M1, M2, M3)
# VIII.- Tabela 27: Test BMP
#    - Analiza wolumenu obrotu (zmiana procentowa)
#    - Specyfikacja T+0 (dzień publikacji)
#    - Specyfikacja bez roku 2022
#    - Test Placebo
#    - Test Corrado
#    - Alternatywne testy statystyczne dla H4:
#      * Test permutacyjny 
#      * Bayes Factor 
#      * Regresja kwantylowa (mediana)
#      * Bootstrapowy przedział ufności (95%)
#      * Analiza zmiany intensywności (delta_density)
# IX. Funkcja główna main() – w. 2601
# 
#    Format plików w poszczególnych załącznikach:
#    - pkt 3 (10-K, całe raporty) → .txt
#    - pkt 4 (10-K, sekcje narracyjne) → .txt
#    - pkt 5 (10-Q) → .pdf
#    - pkt 6 (Earnings calls) → .txt
#    - pkt 7 (Korelacje z R&D/CAPEX) → dane z pkt 3 i 6 
#    - pkt 8 (Analiza jakościowa) → dane z pkt 3 i 6
#    - pkt 9 (Event Study) → .pdf (10-K i 10-Q) + .txt (Earnings calls) + .csv + .xlsx
#    Wymagane nazwy plików (przykłady):
#    - pkt 3 (10-K, cały raport):     `10-K 2024 Microsoft.txt`
#    - pkt 4 (sekcje narracyjne):     
#      * Business:   `Microsoft 2025 10-K Business.txt`
#      * MD&A:       `Microsoft 2025 10-K MD&A.txt`
#      * Risk:       `Microsoft 2025 10-K Risk Factors.txt`
#    - pkt 5 (10-Q):                  `10-Q3 2023 Alphabet.pdf`
#    - pkt 6 (Earnings calls):        `Amazon_2023_Q2_earnings.txt`
#    - pkt 9 (Event Study):
#      * 10-K (.pdf):                 `10-K 2024 Apple.pdf`
#      * 10-Q (.pdf):                 `10-Q2 2022 Meta.pdf`
#      * Earnings calls (.txt):       `Alphabet_2023_Q2_earnings.txt`
#      * Dane cenowe (.csv):          `AAPL_US.csv`, `MSFT_US.csv`, `GOOGL_US.csv`, 
#                                      `AMZN_US.csv`, `META_US.csv`, `SPX_US.csv`
#      * Daty zdarzeń i EPS_suprise (.xlsx):        `mag_tabele_i_wykresy.xlsx`
# =====================================================================



# ŚCIEŻKI
folder_10k       <- "10K"
folder_narrative <- "Business - Risk Factors - MD&A"
folder_10q       <- "10-Q"
folder_ec        <- "earnings_calls"
folder_prices    <- "event_study"

# =====================================================================
# 0. INSTALACJA I WCZYTANIE BIBLIOTEK
# =====================================================================

required_packages <- c(
  "stringr", "tidyr", "dplyr", "lubridate",
  "plm", "lmtest", "sandwich", "pdftools", 
  "readxl", "quantreg", "car", "clubSandwich", 
  "BayesFactor"
)

# Bezpieczne ładowanie pakietów bez prób ich reinstalacji
suppressPackageStartupMessages({ for (pkg in required_packages) {
  if (!require(pkg, character.only = TRUE)) {
    stop(paste("Błąd krytyczny: Brak pakietu", pkg, "na serwerze!"))
  }
} })

# =====================================================================
# 1. SŁOWNIK
# =====================================================================

# --- Terminy ogólne ---
AI_TERMS_GENERAL <- c(
  # --- Terminy ogólne i strategiczne ---
  "artificial intelligence", "\\bai\\b", "\\bai-", "machine intelligence", 
  "cognitive computing", "sovereign ai", "ai strategy", "ai investment", 
  "ai initiative", "ai research",
  
  # --- Uczenie maszynowe i Architektura ---
  "machine learning", "\\bml\\b", "supervised learning", "unsupervised learning",
  "reinforcement learning", "deep learning", "neural network", "neural networks",
  "\\bcnn\\b", "\\brnn\\b", "transformer model", "attention mechanism",
  "neural engine", "\\bnpu\\b"
)


# --- Terminy specyficzne (Specific) ---
AI_TERMS_SPECIFIC <- c(
  # --- Generatywna AI i Agenci ---
  "generative ai", "\\bgenai\\b", "generative model", "diffusion model",
  "large language model", "large language models", "\\bllm\\b", "\\bllms\\b",
  "foundation model", "multimodal model", "\\bgpt\\b", "\\bchatgpt\\b", "\\bai agent\\b", 
  "agentic ai", "context window", "parameter count",
  
  # --- Procesy modelowe i Interakcja ---
  "model training", "inference engine", "fine-tuning", "pre-training", 
  "model deployment", "\\bprompting\\b", "\\btokenization\\b", "cost per token",
  
  # --- Infrastruktura AI ---
  "ai compute", "\\bgpu\\b", "\\bgpus\\b", "\\btpu\\b", "compute cluster",
  "data pipeline", "data labeling", "ai workloads", "ai platform", 
  "on-device ai", "edge ai",
  
  # --- Zastosowania ---
  "autonomous systems", "recommendation engine", "algorithmic recommendation",
  "anomaly detection", "predictive analytics",
  
  # --- Ryzyka, etyka i bezpieczeństwo ---
  "model risk", "model bias", "\\bexplainability\\b", "\\bhallucination\\b",
  "responsible ai", "ethical ai", "ai governance", "ai compliance",
  "adversarial attack", "data poisoning",
  
  # --- Brand Terms - Alphabet ---
  "google ai", "\\bgemini\\b", "\\bbard\\b", "\\bdeepmind\\b", "vertex ai", "\\bpaalm\\b", "tpu v5",
  
  # --- Brand Terms - Microsoft ---
  "microsoft ai", "\\bcopilot\\b", "azure ai", "\\bopenai\\b", "\\bphi–3\\b", "copilot\\+",
  
  # --- Brand Terms - Meta ---
  "meta ai", "\\bllama\\b", "\\bpytorch\\b", "segment anything", "superintelligence",
  
  # --- Brand Terms - Amazon ---
  "amazon ai", "\\balexa\\b", "amazon q", "aws ai", "\\bbedrock\\b", "\\btitan\\b",
  
  # --- Brand Terms - Apple ---
  "apple intelligence", "\\bsiri\\b", "\\bajax\\b"
)

ALL_AI_TERMS <- c(AI_TERMS_GENERAL, AI_TERMS_SPECIFIC)
ALL_AI_TERMS_SORTED <- ALL_AI_TERMS[order(nchar(ALL_AI_TERMS), decreasing = TRUE)]

FUTURE_INDICATORS <- c(
  "will", "expect", "anticipate", "plan", "intend", "goal", "target",
  "outlook", "guidance", "pipeline", "roadmap", "future", "upcoming",
  "next year", "next quarter", "long-term", "strategic", "opportunity",
  "potential", "going forward", "looking ahead", "we believe",
  "we project", "we forecast", "we aim", "committed to", "investing in",
  "expanding", "scaling", "ramp up"
)

RISK_INDICATORS <- c(
  "risk", "risks", "uncertainty", "uncertainties", "challenge", "challenges",
  "concern", "concerns", "threat", "threats", "exposure", "vulnerability",
  "vulnerabilities", "caution", "cautionary", "subject to", "potential adverse", "adverse", "difficult", "difficulties",
  "complex", "complexity", "regulatory", "regulation", "compliance",
  "ethical", "bias", "hallucination", "misuse", "abuse", "safeguard",
  "mitigate", "mitigation", "unforeseen", "unexpected", "volatile",
  "disruption", "liability", "litigation", "may", "could", "might"
)

# =====================================================================
# 2. FUNKCJE POMOCNICZE
# =====================================================================

count_terms <- function(text, terms_list) {
  if (is.na(text) || nchar(text) == 0) return(0)
  text_clean <- clean_text(text)
  total_count <- 0
  for (term in terms_list) {
    if (grepl("\\\\b", term)) {
      pattern <- term
    } else if (grepl(" ", term)) {
      term_regex <- str_replace_all(term, " ", "\\\\s+")
      pattern <- paste0("\\b", term_regex, "\\b")
    } else {
      pattern <- paste0("\\b", term, "\\b")
    }
    count <- str_count(text_clean, pattern)
    total_count <- total_count + count
    text_clean <- str_remove_all(text_clean, pattern)
  }
  return(total_count)
}

count_words <- function(text) {
  if (is.na(text) || nchar(text) == 0) return(0)
  return(length(str_split(tolower(text), "\\s+")[[1]]))
}

calculate_density <- function(mentions, words) {
  result <- ifelse(words > 0, (mentions / words) * 1000, 0)
  return(round(result, 2))
}

count_terms_with_details <- function(text, terms_list) {
  text_lower <- tolower(text)
  total_count <- 0
  term_counts <- list()
  
  clean_length <- function(t) {
    nchar(str_replace_all(t, "\\\\b", ""))
  }
  sorted_terms <- terms_list[order(sapply(terms_list, clean_length), decreasing = TRUE)]
  
  for (term in sorted_terms) {
    if (str_detect(term, "^\\\\b")) {
      pattern <- term
    } else {
      pattern <- paste0("\\b", str_replace_all(term, "([.\\\\+*?\\[\\^\\]$()])", "\\\\\\1"), "\\b")
    }
    
    matches <- str_extract_all(text_lower, regex(pattern, ignore_case = TRUE))[[1]]
    count <- length(matches)
    
    if (count > 0) {
      total_count <- total_count + count
      term_counts[[term]] <- count
      text_lower <- str_replace_all(text_lower, regex(pattern, ignore_case = TRUE), "")
    }
  }
  return(list(total = total_count, counts = term_counts))
}

ABBREVIATIONS <- c("Mr", "Mrs", "Ms", "Dr", "Prof", "Inc", "Corp", "Co", "Ltd",
                   "Jan", "Feb", "Mar", "Apr", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
                   "e.g", "i.e", "vs", "etc")

split_into_sentences <- function(text) {
  text <- str_replace_all(text, "\\.{3,}", "___ELLIPSIS___")
  for (abbr in ABBREVIATIONS) {
    text <- str_replace_all(text, paste0("\\b", abbr, "\\."), paste0(abbr, "___DOT___"))
  }
  text <- str_replace_all(text, "(\\d)\\.(\\d)", "\\1___DECIMAL___\\2")
  sentences <- str_split(text, "(?<=[.!?])\\s+")[[1]]
  sentences <- str_replace_all(sentences, "___DOT___", ".")
  sentences <- str_replace_all(sentences, "___DECIMAL___", ".")
  sentences <- str_replace_all(sentences, "___ELLIPSIS___", "...")
  sentences <- sentences[str_trim(sentences) != ""]
  return(sentences)
}

sentence_has_ai <- function(sentence, terms_list) {
  sentence_lower <- tolower(sentence)
  for (term in terms_list) {
    if (grepl("\\\\b", term)) {
      if (str_detect(sentence_lower, regex(term, ignore_case = TRUE))) return(TRUE)
    } else {
      if (str_detect(sentence_lower, regex(paste0("\\b", term, "\\b"), ignore_case = TRUE))) return(TRUE)
    }
  }
  return(FALSE)
}

analyze_qualitative <- function(text, company, year, doc_type) {
  total_words <- count_words(text)
  result <- count_terms_with_details(text, ALL_AI_TERMS_SORTED)
  total_ai_count <- result$total
  term_counts <- result$counts
  
  general_count <- 0
  specific_count <- 0
  for (term in names(term_counts)) {
    if (term %in% AI_TERMS_GENERAL) {
      general_count <- general_count + term_counts[[term]]
    } else if (term %in% AI_TERMS_SPECIFIC) {
      specific_count <- specific_count + term_counts[[term]]
    }
  }
  
  ai_per_1000 <- if (total_words > 0) (total_ai_count / total_words) * 1000 else 0
  if (total_ai_count > 0) {
    pct_general <- (general_count / total_ai_count) * 100
    pct_specific <- (specific_count / total_ai_count) * 100
  } else {
    pct_general <- 0
    pct_specific <- 0
  }
  
  sentences <- split_into_sentences(text)
  future_count <- 0
  risk_count <- 0
  ai_sentences <- 0
  for (sentence in sentences) {
    if (sentence_has_ai(sentence, ALL_AI_TERMS_SORTED)) {
      ai_sentences <- ai_sentences + 1
      sent_lower <- tolower(sentence)
      if (any(sapply(FUTURE_INDICATORS, function(x) grepl(x, sent_lower, fixed = TRUE)))) future_count <- future_count + 1
      if (any(sapply(RISK_INDICATORS, function(x) grepl(x, sent_lower, fixed = TRUE)))) risk_count <- risk_count + 1
    }
  }
  
  pct_future <- if (ai_sentences > 0) round(future_count / ai_sentences * 100, 1) else 0
  pct_risk <- if (ai_sentences > 0) round(risk_count / ai_sentences * 100, 1) else 0
  
  return(data.frame(
    company = company, year = year, doc_type = doc_type,
    total_words = total_words, total_ai = total_ai_count,
    AI_Total = total_ai_count,                    
    AI_Specific_Count = specific_count,           
    AI_General_Count = general_count,             
    AI_Sentences_Count = ai_sentences,            
    Future_Count = future_count,                  
    Risk_Count = risk_count,                      
    mentions = total_ai_count, words = total_words, density = round(ai_per_1000, 2),
    pct_general = round(pct_general, 1), pct_specific = round(pct_specific, 1),
    pct_future = pct_future, pct_risk = pct_risk,
    stringsAsFactors = FALSE
  ))
}

sync_calendar <- function(fiscal_year, fiscal_quarter, company) {
  cal_year <- as.numeric(fiscal_year)
  cal_quarter <- fiscal_quarter
  
  if (company == "MSFT") {
    if (fiscal_quarter == "Q1") { cal_quarter <- "Q3"; cal_year <- cal_year - 1 }
    else if (fiscal_quarter == "Q2") { cal_quarter <- "Q4"; cal_year <- cal_year - 1 }
    else if (fiscal_quarter == "Q3") { cal_quarter <- "Q1" }
    else if (fiscal_quarter == "Q4") { cal_quarter <- "Q2" }
  } else if (company == "AAPL") {
    if (fiscal_quarter == "Q1") { cal_quarter <- "Q4"; cal_year <- cal_year - 1 }
    else if (fiscal_quarter == "Q2") { cal_quarter <- "Q1" }
    else if (fiscal_quarter == "Q3") { cal_quarter <- "Q2" }
    else if (fiscal_quarter == "Q4") { cal_quarter <- "Q3" }
  }
  return(list(year = as.character(cal_year), quarter = cal_quarter))
}

# =====================================================================
# 3. ANALIZA RAPORTÓW 10-K
# =====================================================================

clean_text <- function(text) {
  if (is.na(text) || nchar(text) == 0) return("")
  text %>%
    tolower() %>%
    str_replace_all("[\r\n\t]", " ") %>%
    str_replace_all("\\s+", " ") %>%
    str_trim()
}

read_document_text <- function(file_path) {
  if (grepl("\\.pdf$", file_path, ignore.case = TRUE)) {
    pages <- pdftools::pdf_text(file_path)
    pages <- pages[nchar(pages) > 20]
    text <- paste(pages, collapse = " ")
    text <- gsub("([a-zA-Z])-\\s+([a-zA-Z])", "\\1\\2", text)
    text <- gsub("([a-zA-Z])-\\n+([a-zA-Z])", "\\1\\2", text)
    text <- gsub("[\r\n\t]", " ", text)
    text <- gsub("\\s+", " ", text)
    text <- iconv(text, from = "UTF-8", to = "ASCII", sub = " ")
    return(clean_text(text))
  } else {
    text <- paste(readLines(file_path, warn = FALSE), collapse = " ")
    return(clean_text(text))
  }
}

analyze_10k_full <- function(folder_path) {
  cat("\n", strrep("=", 70), "\n")
  cat("I. ANALIZA RAPORTÓW 10-K (CAŁE RAPORTY)\n")
  cat(strrep("=", 70), "\n")
  
  files <- list.files(folder_path, pattern = "\\.txt$", full.names = TRUE, ignore.case = TRUE)
  results <- list()
  
  for (file in files) {
    name <- basename(file)
    company <- case_when(
      grepl("Alphabet", name) ~ "GOOGL",
      grepl("Amazon", name) ~ "AMZN",
      grepl("Apple", name) ~ "AAPL",
      grepl("Meta", name) ~ "META",
      grepl("Microsoft", name) ~ "MSFT",
      TRUE ~ NA_character_
    )
    year <- str_extract(name, "202[2-5]")
    if (is.na(company) || is.na(year)) next
    
    cat("Przetwarzam:", company, year, "-", name, "\n")
    text <- read_document_text(file)
    if (nchar(text) == 0) next
    
    result <- analyze_qualitative(text, company, year, "10-K")
    results[[length(results) + 1]] <- result
    cat("  → AI:", result$total_ai, "| gęstość:", result$density, "| Future:", result$pct_future, "% | Risk:", result$pct_risk, "%\n")
  }
  
  if (length(results) == 0) return(NULL)
  df <- bind_rows(results)
  
  cat("\n--- TABELA 5: Liczba odniesień (10-K) ---\n")
  table_5 <- df %>% select(company, year, total_ai) %>%
    pivot_wider(names_from = year, values_from = total_ai, values_fill = 0) %>%
    mutate(avg_2022_2025 = round((`2022`+`2023`+`2024`+`2025`)/4, 0))
  print(table_5)
  
  cat("\n--- TABELA 6: Gęstość na 1000 słów (10-K) ---\n")
  table_6 <- df %>% select(company, year, density) %>%
    pivot_wider(names_from = year, values_from = density, values_fill = 0) %>%
    mutate(avg_2022_2025 = round((`2022`+`2023`+`2024`+`2025`)/4, 2))
  print(table_6)
  
  cat("\n--- TABELA 6.1: Średnia GAMAM (10-K) ---\n")
  table_7 <- df %>% group_by(year) %>% summarise(gamam_avg_density = round(mean(density), 2))
  print(table_7)
  
  return(df)
}

# =====================================================================
# 4. ANALIZA RAPORTÓW 10-K - SEKCJE NARRACYJNE
# =====================================================================

analyze_narrative_sections <- function(folder_path, results_full_10k) {
  cat("\n", strrep("=", 70), "\n")
  cat("II. SEKCJE NARRACYJNE (Business, MD&A, Risk Factors)\n")
  cat(strrep("=", 70), "\n")
  
  files <- list.files(folder_path, pattern = "\\.txt$", full.names = TRUE)
  results <- list()
  
  for (file in files) {
    name <- basename(file)
    parts <- str_split(str_replace(name, "\\.txt$", ""), " ")[[1]]
    
    company <- case_when(
      grepl("MICROSOFT", parts[1], ignore.case = TRUE) ~ "MSFT",
      grepl("ALPHABET|GOOGLE", parts[1], ignore.case = TRUE) ~ "GOOGL",
      grepl("AMAZON", parts[1], ignore.case = TRUE) ~ "AMZN",
      grepl("APPLE", parts[1], ignore.case = TRUE) ~ "AAPL",
      grepl("META|FACEBOOK", parts[1], ignore.case = TRUE) ~ "META",
      TRUE ~ NA_character_
    )
    year <- parts[2]
    section <- parts[4]
    if (is.na(company)) next
    
    cat("Przetwarzam:", company, year, "- sekcja:", section, "\n")
    text <- paste(readLines(file, warn = FALSE), collapse = " ")
    if (nchar(text) == 0) next
    
    ai_count <- count_terms(text, ALL_AI_TERMS_SORTED)
    word_count <- count_words(text)
    density <- calculate_density(ai_count, word_count)
    
    results[[length(results) + 1]] <- data.frame(
      company = company, year = year, section = section,
      ai_count = ai_count, word_count = word_count, density = density,
      stringsAsFactors = FALSE
    )
    cat("  → AI:", ai_count, "| gęstość:", density, "\n")
  }
  
  if (length(results) == 0) return(NULL)
  df <- bind_rows(results)
  
  cat("\n--- TABELA 7: Średnia gęstość w poszczególnych sekcjach ---\n")
  table_sections <- df %>% group_by(section, year) %>%
    summarise(srednia_gestosc = round(mean(density), 2), .groups = "drop") %>%
    pivot_wider(names_from = year, values_from = srednia_gestosc, values_fill = 0)
  print(table_sections)
  
  for (rok in c("2022", "2023", "2024", "2025")) {
    dane_rok <- df %>% filter(year == rok)
    if (nrow(dane_rok) >= 3 && length(unique(dane_rok$section)) >= 3) {
      kw_test <- kruskal.test(density ~ section, data = dane_rok)
      cat(paste("Rok", rok, "- p-value =", round(kw_test$p.value, 4)))
      if (kw_test$p.value < 0.05) cat(" ✅ Istotne różnice\n") else cat(" ❌ Brak istotnych różnic\n")
    }
  }
  
  narrative_sum <- df %>% group_by(company, year) %>%
    summarise(narrative_ai = sum(ai_count), narrative_words = sum(word_count),
              narrative_density = calculate_density(narrative_ai, narrative_words), .groups = "drop")
  
  h1_data <- results_full_10k %>% select(company, year, total_ai, total_words, density) %>%
    left_join(narrative_sum, by = c("company", "year")) %>%
    mutate(
      other_ai = total_ai - narrative_ai,
      other_words = total_words - narrative_words,
      other_density = calculate_density(other_ai, other_words)
    )
  
  cat("\n--- TABELA 8: Porównanie sekcji narracyjnych vs finansowa ---\n")
  h1_summary <- h1_data %>% group_by(year) %>%
    summarise(
      narrative_avg = round(mean(narrative_density, na.rm = TRUE), 2),
      other_avg = round(mean(other_density, na.rm = TRUE), 2),
      total_avg = round(mean(density, na.rm = TRUE), 2)
    )
  print(h1_summary)
  
  narrative_2025 <- h1_summary %>% filter(year == 2025) %>% pull(narrative_avg)
  other_2025 <- h1_summary %>% filter(year == 2025) %>% pull(other_avg)
  cat("\n✅ Hipoteza H1: Gęstość w sekcjach narracyjnych (", narrative_2025, 
      ") > finansowa (", other_2025, ") → POTWIERDZONA\n", sep="")
  
  return(list(sections = df, h1 = h1_summary))
}

# =====================================================================
# 5. ANALIZA RAPORTÓW 10-Q
# =====================================================================

analyze_10q_full <- function(folder_path) {
  cat("\n", strrep("=", 70), "\n")
  cat("III. ANALIZA RAPORTÓW 10-Q\n")
  cat(strrep("=", 70), "\n")
  
  clean_text <- function(text) {
    text %>%
      tolower() %>%
      str_replace_all("[\r\n]", " ") %>%
      str_replace_all("\\s+", " ") %>%
      str_trim()
  }
  
  read_pdf_text_improved <- function(pdf_path) {
    pages <- pdftools::pdf_text(pdf_path)
    pages <- pages[nchar(pages) > 20]
    text <- paste(pages, collapse = " ")
    text <- gsub("([a-zA-Z])-\\s+([a-zA-Z])", "\\1\\2", text)
    text <- gsub("([a-zA-Z])-\\n+([a-zA-Z])", "\\1\\2", text)
    text <- gsub("[\r\n\t]", " ", text)
    text <- gsub("\\s+", " ", text)
    text <- iconv(text, from = "UTF-8", to = "ASCII", sub = " ")
    text <- clean_text(text)
    return(text)
  }
  
  count_terms_10q <- function(text, terms_list) {
    text_clean <- clean_text(text)
    total_count <- 0
    for (term in terms_list) {
      if (grepl("\\\\b", term)) {
        pattern <- term
      } else {
        term_regex <- str_replace_all(term, " ", "\\\\s+")
        pattern <- paste0("\\b", term_regex, "\\b")
      }
      count <- str_count(text_clean, regex(pattern, ignore_case = TRUE))
      total_count <- total_count + count
      text_clean <- str_remove_all(text_clean, regex(pattern, ignore_case = TRUE))
    }
    return(total_count)
  }
  
  count_words_10q <- function(text) {
    text_clean <- clean_text(text)
    words <- str_split(text_clean, "\\s+")[[1]]
    words <- words[words != ""]
    return(length(words))
  }
  
  extract_calendar_period <- function(filename, company) {
    name <- basename(filename)
    fy <- as.numeric(str_extract(name, "202[2-6]"))
    fq <- str_extract(name, "Q[1-4]")
    if (is.na(fq)) fq <- "Q1" 
    
    cal_year <- fy
    cal_quarter <- fq
    
    if (company == "MSFT") {
      if (fq == "Q1") { cal_quarter <- "Q3"; cal_year <- fy - 1 }
      else if (fq == "Q2") { cal_quarter <- "Q4"; cal_year <- fy - 1 }
      else if (fq == "Q3") { cal_quarter <- "Q1" }
      else if (fq == "Q4") { cal_quarter <- "Q2" }
    } else if (company == "AAPL") {
      if (fq == "Q1") { cal_quarter <- "Q4"; cal_year <- fy - 1 }
      else if (fq == "Q2") { cal_quarter <- "Q1" }
      else if (fq == "Q3") { cal_quarter <- "Q2" }
      else if (fq == "Q4") { cal_quarter <- "Q3" }
    }
    return(list(year = as.character(cal_year), quarter = cal_quarter))
  }
  
  extract_company_10q <- function(filename) {
    name <- toupper(basename(filename))
    if (grepl("META", name)) return("META")
    if (grepl("GOOGL|GOOG|ALPHABET", name)) return("GOOGL")
    if (grepl("MSFT|MICROSOFT", name)) return("MSFT")
    if (grepl("AMZN|AMAZON", name)) return("AMZN")
    if (grepl("AAPL|APPLE", name)) return("AAPL")
    return("UNKNOWN")
  }
  
  files <- list.files(folder_path, pattern = "\\.pdf$", full.names = TRUE, ignore.case = TRUE)
  results <- list()
  
  for (file in files) {
    company <- extract_company_10q(file)
    if (company == "UNKNOWN") next
    
    period <- extract_calendar_period(file, company)
    year <- period$year
    quarter <- period$quarter
    
    if (is.na(year) || !year %in% c("2022", "2023", "2024", "2025")) next
    
    cat("Przetwarzam:", company, "→ CY", year, quarter, "-", basename(file), "\n")
    
    text <- read_pdf_text_improved(file)
    if (nchar(text) < 100) next
    
    mentions <- count_terms_10q(text, ALL_AI_TERMS_SORTED)
    words <- count_words_10q(text)
    density <- ifelse(words > 0, round((mentions / words) * 1000, 2), 0)
    
    results[[length(results) + 1]] <- data.frame(
      company = company, year = year, quarter = quarter,
      total_mentions = mentions, word_count = words, density = density,
      stringsAsFactors = FALSE
    )
    cat("  → AI:", mentions, "| gęstość:", density, "\n")
  }
  
  if (length(results) == 0) return(NULL)
  df <- bind_rows(results)
  cat("\n=== 10-Q: Wczytano", nrow(df), "plików ===\n")
  
  annual <- df %>%
    filter(quarter %in% c("Q1", "Q2", "Q3")) %>%
    group_by(company, year) %>%
    summarise(
      total_mentions = sum(total_mentions),
      word_count = sum(word_count),
      density = round((sum(total_mentions) / sum(word_count)) * 1000, 2),
      .groups = "drop"
    )
  
  cat("\n--- TABELA 10: Gęstość 10-Q (agregacja roczna Q1-Q3) ---\n")
  table_9 <- annual %>% select(company, year, density) %>%
    pivot_wider(names_from = year, values_from = density, values_fill = 0) %>%
    mutate(
      avg = round((`2022` + `2023` + `2024` + `2025`) / 4, 2),
      change_pp = round(`2025` - `2022`, 2),
      change_pct = round(((`2025` - `2022`) / `2022`) * 100, 1)
    )
  print(table_9)
  
  cat("\n--- TABELA 10.1: Średnia GAMAM (10-Q) ---\n")
  table_10 <- annual %>% group_by(year) %>% summarise(gamam_avg_density = round(mean(density), 2))
  print(table_10)
  
  return(list(raw = df, annual = annual))
}

# =====================================================================
# 6. ANALIZA EARNINGS CALLS
# =====================================================================

analyze_earnings_calls_full <- function(folder_path, results_10k, results_10q_annual) {
  cat("\n", strrep("=", 70), "\n")
  cat("IV. ANALIZA EARNINGS CALLS (+ presentation/Q&A)\n")
  cat(strrep("=", 70), "\n")
  
  files <- list.files(folder_path, pattern = "\\.txt$", full.names = TRUE)
  results <- list()
  
  for (file in files) {
    name <- basename(file)
    name_clean <- str_replace(name, "\\.txt$", "")
    parts <- str_split(name_clean, "_")[[1]]
    
    company_raw <- parts[1]
    company <- case_when(
      toupper(company_raw) == "ALPHABET" ~ "GOOGL",
      toupper(company_raw) == "AMAZON" ~ "AMZN",
      toupper(company_raw) == "APPLE" ~ "AAPL",
      toupper(company_raw) == "META" ~ "META",
      toupper(company_raw) == "MICROSOFT" ~ "MSFT",
      TRUE ~ NA_character_
    )
    if (is.na(company)) next
    
    fiscal_year <- parts[2]
    fiscal_quarter <- if (length(parts) > 2) parts[3] else NA
    if (is.na(fiscal_quarter)) next
    
    cal <- sync_calendar(fiscal_year, fiscal_quarter, company)
    if (is.na(cal$year) || !cal$year %in% c("2022", "2023", "2024", "2025")) next
    
    cat("Przetwarzam:", company, "FY", fiscal_year, fiscal_quarter, "→ CY", cal$year, cal$quarter, "-", name, "\n")
    
    tekst <- paste(readLines(file, warn = FALSE), collapse = " ")
    if (nchar(tekst) == 0) next
    
    qa_start <- str_locate(tekst, "Questions & Answers:")[1, "start"]
    
    if (!is.na(qa_start)) {
      presentation <- str_sub(tekst, 1, qa_start - 1)
      qa <- str_sub(tekst, qa_start, nchar(tekst))
    } else {
      presentation <- tekst
      qa <- ""
    }
    
    result_caly <- analyze_qualitative(tekst, company, cal$year, "Earnings Call")
    result_caly$quarter <- cal$quarter
    result_caly$part <- "caly"
    result_caly$total_words <- result_caly$words
    
    result_prez <- analyze_qualitative(presentation, company, cal$year, "Earnings Call")
    result_prez$quarter <- cal$quarter
    result_prez$part <- "presentation"
    
    result_qa <- analyze_qualitative(qa, company, cal$year, "Earnings Call")
    result_qa$quarter <- cal$quarter
    result_qa$part <- "qa"
    
    results[[length(results) + 1]] <- result_caly
    results[[length(results) + 1]] <- result_prez
    results[[length(results) + 1]] <- result_qa
    
    cat("  → AI całość:", result_caly$total_ai, "| gęstość:", result_caly$density,
        "| Future:", result_caly$pct_future, "% | Risk:", result_caly$pct_risk, "%\n")
  }
  
  if (length(results) == 0) return(NULL)
  df <- bind_rows(results)
  
  cat("\n--- TABELA 13: Gęstość Earnings Calls (średnia roczna) ---\n")
  table_13 <- df %>% 
    filter(part == "caly") %>%
    group_by(company, year) %>%
    summarise(
      total_ai = sum(AI_Total),
      total_words = sum(total_words),
      srednia_gestosc = round((total_ai / total_words) * 1000, 2),
      .groups = "drop"
    ) %>%
    pivot_wider(
      id_cols = company,
      names_from = year,
      values_from = srednia_gestosc,
      values_fill = 0
    )
  
  print(table_13)
  
  cat("\n--- TABELA 13.1: Średnia GAMAM (Earnings Calls) ---\n")
  table_14 <- df %>% 
    filter(part == "caly") %>%
    group_by(year) %>%
    summarise(
      total_ai = sum(AI_Total),
      total_words = sum(total_words),
      srednia_gestosc_EC = round((total_ai / total_words) * 1000, 2),
      .groups = "drop"
    )
  print(table_14)
  
  cat("\n--- TABELA 13.2: Podział earnings calls na presentation i Q&A ---\n")
  table_15_raw <- df %>% 
    filter(part != "caly") %>%
    group_by(year, part) %>%
    summarise(
      total_words = sum(total_words, na.rm = TRUE),
      total_ai = sum(AI_Total, na.rm = TRUE),
      gestosc = round((total_ai / total_words) * 1000, 2),
      .groups = "drop"
    )
  
  udzial_prez <- table_15_raw %>%
    group_by(year) %>%
    summarise(
      udzial_prezentacji = round(
        total_words[part == "presentation"] / 
          (total_words[part == "presentation"] + total_words[part == "qa"]) * 100, 
        1
      ),
      .groups = "drop"
    )
  
  table_15_wide <- table_15_raw %>%
    select(year, part, gestosc) %>%
    pivot_wider(
      id_cols = year,
      names_from = part,
      values_from = gestosc,
      values_fill = 0
    )
  
  table_15 <- table_15_wide %>%
    left_join(udzial_prez, by = "year") %>%
    select(year, presentation, qa, udzial_prezentacji)
  
  print(table_15)
  
  cat("\n--- TABELA 13.3 PREZENTACJA vs Q&A DLA KAŻDEJ SPÓŁKI W 2025 ROKU ---\n")
  table_15_by_company <- df %>% 
    filter(year == "2025", part != "caly") %>%
    group_by(company, part) %>%
    summarise(
      total_ai = sum(AI_Total),
      total_words = sum(total_words),
      gestosc = round((total_ai / total_words) * 1000, 2),
      .groups = "drop"
    ) %>%
    pivot_wider(
      id_cols = company,
      names_from = part,
      values_from = gestosc,
      values_fill = 0
    )
  print(table_15_by_company)
  
  # === KORELACJA SPEARMANA PRESENTATION vs Q&A ===
  cat("\n--- KORELACJA SPEARMANA: PRESENTATION vs Q&A ---\n")
  
  df_wide_qa <- df %>%
    filter(part %in% c("presentation", "qa")) %>%
    select(company, year, quarter, part, density) %>%
    pivot_wider(names_from = part, values_from = density)
  
  valid_rows <- df_wide_qa %>% filter(!is.na(presentation) & !is.na(qa))
  
  if (nrow(valid_rows) >= 3) {
    cor_test_qa <- cor.test(valid_rows$presentation, valid_rows$qa, method = "spearman", exact = FALSE)
    
    cat(paste("Współczynnik korelacji (rho):", round(cor_test_qa$estimate, 3), "\n"))
    cat(paste("p-value:", round(cor_test_qa$p.value, 4), "\n"))
    
    if (cor_test_qa$p.value < 0.05) {
      cat("✅ Istnieje statystycznie istotny związek między gęstością AI w Prezentacji a w Q&A.\n")
    } else {
      cat("❌ Brak statystycznie istotnego związku między Prezentacją a Q&A.\n")
    }
  } else {
    cat("⚠️ Zbyt mało kompletnych par (Prezentacja + Q&A) do obliczenia korelacji.\n")
  }
  
  # === PORÓWNANIE EC VS 10-K ===
  gest_10k <- results_10k %>% 
    filter(year %in% c("2022", "2023", "2024", "2025")) %>% 
    group_by(year) %>% 
    summarise(gest_10K = round(mean(density), 2), .groups = "drop")
  
  comparison <- table_14 %>% 
    rename(rok = year) %>%
    left_join(gest_10k, by = c("rok" = "year")) %>% 
    mutate(iloraz = round(srednia_gestosc_EC / gest_10K, 1))
  
  cat("\n--- Tabela 14: PORÓWNANIE EARNINGS CALLS VS 10-K ---\n")
  print(comparison)
  
  # === WERYFIKACJA H2 ===
  if (!is.null(results_10q_annual)) {
    h2_ec <- mean(comparison$srednia_gestosc_EC, na.rm = TRUE)
    h2_10k <- mean(comparison$gest_10K, na.rm = TRUE)
    h2_10q <- mean(results_10q_annual$density, na.rm = TRUE)
    cat("\n--- WERYFIKACJA HIPOTEZY H2 ---\n")
    cat(paste("Średnia gęstość EC: ", round(h2_ec, 2), "| 10-K:", round(h2_10k, 2), "| 10-Q:", round(h2_10q, 2), "\n"))
    if(h2_ec > h2_10k && h2_10k > h2_10q) {
      cat("✅ Hipoteza H2 POTWIERDZONA: Earnings Calls > 10-K\n")
    } else {
      cat("❌ Hipoteza H2 NIE POTWIERDZONA\n")
    }
  }
  
  return(list(raw = df, annual = table_13, gamam = table_14, split = table_15))
}

# =====================================================================
# 7. KORELACJE Z R&D I CAPEX
# =====================================================================

analyze_rd_capex_full <- function(results_10k, results_ec = NULL) {
  cat("\n", strrep("=", 70), "\n")
  cat("V. KORELACJE Z R&D I CAPEX (H3)\n")
  cat(strrep("=", 70), "\n")

  fe_capex_time     <- NULL
  ct_capex_time     <- NULL
  fe_capex_time_ec  <- NULL
  ct_capex_time_ec  <- NULL
  ct_log_capex_ec   <- NULL
  fe_log_capex_ec   <- NULL
  p_ec_raw          <- NULL
  p_ec_time         <- NULL
  
  df_rd_capex <- data.frame(
    spolka = c(rep("Alphabet",4), rep("Amazon",4), rep("Apple",4), rep("Meta",4), rep("Microsoft",4)),
    rok = rep(2022:2025, 5),
    rd = c(13.97,14.78,14.09,15.16, 14.24,14.90,13.83,15.14,
           6.66,7.80,8.02,8.30, 30.30,28.53,26.67,28.55, 12.36,12.83,12.04,11.53),
    capex = c(11.13,10.49,15.01,22.70, 12.38,9.17,12.96,18.39,
              2.72,2.86,2.42,3.06, 26.95,20.05,22.65,34.68, 12.05,13.26,18.14,22.91)
  )
  
  df_10k_mapped <- results_10k %>%
    mutate(spolka = case_when(
      company == "GOOGL" ~ "Alphabet",
      company == "AMZN" ~ "Amazon",
      company == "AAPL" ~ "Apple",
      company == "META" ~ "Meta",
      company == "MSFT" ~ "Microsoft"
    ), rok = as.numeric(year))
  
  df <- df_10k_mapped %>%
    left_join(df_rd_capex, by = c("spolka", "rok")) %>%
    mutate(
      log_ai = log(density + 0.01),
      log_rd = log(rd + 0.01),
      log_capex = log(capex + 0.01)
    )
  
  cat("\n--- TABELA 16.1: KORELACJE SPEARMANA (globalne) ---\n")
  cor_test_rd <- cor.test(df$rd, df$density, method = "spearman", exact = FALSE)
  cor_test_capex <- cor.test(df$capex, df$density, method = "spearman", exact = FALSE)
  cat(paste("R&D vs AI density:   ρ =", round(cor_test_rd$estimate, 2),
            "p-value =", round(cor_test_rd$p.value, 4), "\n"))
  cat(paste("CAPEX vs AI density: ρ =", round(cor_test_capex$estimate, 2),
            "p-value =", round(cor_test_capex$p.value, 4), "\n"))
  
  cat("\n--- TABELA 16.2: KORELACJE WEWNĄTRZ SPÓŁEK ---\n")
  for (comp in unique(df$spolka)) {
    dane_comp <- df[df$spolka == comp, ]
    if (nrow(dane_comp) >= 3) {
      cor_rd_comp <- cor(dane_comp$rd, dane_comp$density, method = "spearman", use = "complete.obs")
      cor_capex_comp <- cor(dane_comp$capex, dane_comp$density, method = "spearman", use = "complete.obs")
      cat(paste(comp, ": R&D =", round(cor_rd_comp, 2), "| CAPEX =", round(cor_capex_comp, 2), "\n"))
    }
  }
  cat("\n⚠️ Uwaga: korelacje wewnątrz spółek liczone na n=4 obserwacjach - wyłącznie eksploracyjne.\n")
  
  cat("\n--- TABELA 17: REGRESJA PANELOWA 10-K (Fixed Effects + CR2) ---\n")
  p_df <- pdata.frame(df, index = c("spolka", "rok"))
  
  fe_capex <- plm(density ~ capex, data = p_df, model = "within")
  fe_rd    <- plm(density ~ rd,    data = p_df, model = "within")
  fe_full  <- plm(density ~ capex + rd, data = p_df, model = "within")
  
  cat("\nModel CAPEX (surowy):\n")
  print(clubSandwich::coef_test(fe_capex, vcov = "CR2", cluster = "individual"))
  cat("\n--- MIARY DOPASOWANIA MODELU CAPEX (10-K) ---\n")
  cat("Within R²:", round(summary(fe_capex)$r.squared[1], 4), "\n")
  cat("Between R²:", round(summary(fe_capex)$r.squared[2], 4), "\n")
  cat("Liczba obserwacji:", nrow(p_df), "\n")
  cat("Liczba firm:", length(unique(df$spolka)), "\n\n")
  
  cat("\nModel R&D (surowy):\n")
  print(clubSandwich::coef_test(fe_rd, vcov = "CR2", cluster = "individual"))
  cat("Within R²:", round(summary(fe_rd)$r.squared[1], 4), "\n\n")
  
  cat("\nModel łączny CAPEX + R&D:\n")
  print(clubSandwich::coef_test(fe_full, vcov = "CR2", cluster = "individual"))
  cat("Within R²:", round(summary(fe_full)$r.squared[1], 4), "\n")
  cat("⚠️ Uwaga: VIF dla capex i rd w tym modelu jest bardzo wysoki (patrz sekcja diagnostyczna) -\n")
  cat("   współczynniki modelu łącznego są niewiarygodne i nie powinny być interpretowane osobno.\n\n")
  
  fe_log_capex <- plm(log_ai ~ log_capex, data = p_df, model = "within")
  fe_log_rd    <- plm(log_ai ~ log_rd,    data = p_df, model = "within")
  
  cat("\n--- MODEL CAPEX (log-log, CR2) ---\n")
  print(clubSandwich::coef_test(fe_log_capex, vcov = "CR2", cluster = "individual"))
  
  cat("\n--- MODEL R&D (log-log, CR2) ---\n")
  print(clubSandwich::coef_test(fe_log_rd, vcov = "CR2", cluster = "individual"))
  
  cat("\n--- MODEL CAPEX + EFEKTY CZASOWE (robustness check, CR2) ---\n")
  fe_capex_time <- tryCatch({
    m <- plm(density ~ capex + factor(rok), data = p_df, model = "within")
    ct_result <- clubSandwich::coef_test(m, vcov = "CR2", cluster = "individual")
    
    if (is.null(ct_result)) {
      cat("⚠️ coef_test zwrócił NULL - CR2 nie mogło zostać obliczone.\n")
      ct_capex_time <- NULL
      NULL
    } else {
      ct_capex_time <- ct_result
      print(ct_result)
      m
    }
  }, error = function(e) {
    cat("⚠️ Algorytm CR2 nie mógł obliczyć macierzy dla modelu z efektami czasu.\n")
    cat("Powód: Zbyt mała liczba klastrów (N=5) w stosunku do liczby estymowanych parametrów.\n")
    cat("   Treść błędu:", conditionMessage(e), "\n")
    NULL
  })
  
  # Test Hausmana (FE vs RE)
  re_model <- plm(density ~ capex, data = p_df, model = "random")
  hausman_test <- phtest(fe_capex, re_model)
  
  cat("\n--- TEST HAUSMANA ---\n")
  print(hausman_test)
  cat("Uwaga: Zastosowano model FE niezależnie od wyniku testu Hausmana.\n")
  cat("Uzasadnienie: próba nielosowa (celowy dobór Big Tech) wyklucza\n")
  cat("założenie losowości efektów indywidualnych wymagane przez RE.\n")
  
  # Test F (FE vs Pooled OLS)
  pooled_model <- plm(density ~ capex, data = p_df, model = "pooling")
  f_test <- pFtest(fe_capex, pooled_model)
  
  cat("\n--- TEST F (FE vs POOLED OLS) ---\n")
  print(f_test)
  
  # ===== DIAGNOSTYKA MODELU PANELOWEGO =====
  cat("\n", strrep("=", 70), "\n")
  cat("DIAGNOSTYKA MODELU PANELOWEGO (10-K)\n")
  cat(strrep("=", 70), "\n")
  
  if (requireNamespace("car", quietly = TRUE)) {
    lm_full <- lm(density ~ capex + rd + factor(spolka) + factor(rok), data = df)
    vif_vals <- car::vif(lm_full)
    cat("\n--- VIF (współliniowość) ---\n")
    print(vif_vals)
    if (any(vif_vals > 5)) cat("⚠️ Uwaga: VIF > 5 – współliniowość (dotyczy zwłaszcza modelu łącznego CAPEX+R&D)\n") else cat("✅ Brak istotnej współliniowości\n")
  }
  
  # Test Breuscha-Pagana 
  bp_lm_equiv <- lm(density ~ capex + rd + factor(spolka), data = df)
  bp_test <- lmtest::bptest(bp_lm_equiv)
  cat("\n--- Test Breuscha-Pagana (heteroskedastyczność, model FE jako lm z dummy) ---\n")
  print(bp_test)
  if (bp_test$p.value < 0.05) cat("⚠️ Heteroskedastyczność – uzasadnienie dla CR2\n") else cat("✅ Brak istotnej heteroskedastyczności\n")
  
  # Test Wooldridge'a (autokorelacja w panelu)
  if (requireNamespace("plm", quietly = TRUE)) {
    w_test <- plm::pwartest(fe_full)
    cat("\n--- Test Wooldridge'a (autokorelacja) ---\n")
    print(w_test)
    if (w_test$p.value < 0.05) cat("⚠️ Autokorelacja w panelu - zaadresowana przez klastrowanie CR2 na poziomie spółki\n") else cat("✅ Brak autokorelacji\n")
  }
  
  # ===== Analiza Earnings Calls =====
  if (!is.null(results_ec) && !is.null(results_ec$raw)) {
    df_ec_mapped <- results_ec$raw %>%
      filter(part == "caly") %>%
      mutate(spolka = case_when(
        company == "GOOGL" ~ "Alphabet",
        company == "AMZN" ~ "Amazon",
        company == "AAPL" ~ "Apple",
        company == "META" ~ "Meta",
        company == "MSFT" ~ "Microsoft"
      ), rok = as.numeric(year)) %>%
      group_by(spolka, rok) %>%
      summarise(ec_density = mean(density, na.rm = TRUE), .groups = "drop")
    
    df_ec_merged <- df_ec_mapped %>%
      inner_join(df_rd_capex, by = c("spolka", "rok")) %>%
      mutate(
        log_ec = log(ec_density + 0.01),
        log_capex = log(capex + 0.01),
        log_rd = log(rd + 0.01)
      )
    
    cat("\n--- TABELA 16.3: KORELACJE SPEARMANA DLA EARNINGS CALLS ---\n")
    cat("⚠️ Uwaga: korelacje per-spółka liczone na n=4 - traktować wyłącznie eksploracyjnie.\n\n")
    
    get_p <- function(d, col1, col2) {
      d_sub <- d[!is.na(d[[col1]]) & !is.na(d[[col2]]), ]
      if (nrow(d_sub) < 3) return(NA)
      round(cor.test(d_sub[[col1]], d_sub[[col2]], method = "spearman", exact = FALSE)$p.value, 4)
    }
    
    zakresy <- c("Globalna", unique(df_ec_merged$spolka))
    tab18 <- data.frame(
      Zakres = zakresy,
      R_vs_EC_rho = sapply(zakresy, function(x) {
        d <- if (x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
        if (nrow(d[!is.na(d$rd) & !is.na(d$ec_density), ]) < 3) return(NA)
        round(cor(d$rd, d$ec_density, method = "spearman", use = "complete.obs"), 2)
      }),
      R_vs_EC_p = sapply(zakresy, function(x) {
        d <- if (x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
        get_p(d, "rd", "ec_density")
      }),
      CAPEX_vs_EC_rho = sapply(zakresy, function(x) {
        d <- if (x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
        if (nrow(d[!is.na(d$capex) & !is.na(d$ec_density), ]) < 3) return(NA)
        round(cor(d$capex, d$ec_density, method = "spearman", use = "complete.obs"), 2)
      }),
      CAPEX_vs_EC_p = sapply(zakresy, function(x) {
        d <- if (x == "Globalna") df_ec_merged else df_ec_merged[df_ec_merged$spolka == x, ]
        get_p(d, "capex", "ec_density")
      })
    )
    print(tab18)
    
    cat("\n--- TABELA 16.4: MODELE REGRESJI PANELOWEJ FE DLA EARNINGS CALLS (CR2) ---\n")
    
    p_df_ec <- pdata.frame(df_ec_merged, index = c("spolka", "rok"))
    
    fe_c_ec  <- plm(ec_density ~ capex, data = p_df_ec, model = "within")
    fe_f_ec  <- plm(ec_density ~ capex + rd, data = p_df_ec, model = "within")
    fe_rd_ec <- plm(ec_density ~ rd, data = p_df_ec, model = "within")
    
    cat("\n--- MODEL R&D (EC) ---\n")
    print(clubSandwich::coef_test(fe_rd_ec, vcov = "CR2", cluster = "individual"))
    cat("Within R²:", round(summary(fe_rd_ec)$r.squared[1], 4), "\n\n")
    
    fe_log_capex_ec <- plm(log_ec ~ log_capex, data = p_df_ec, model = "within")
    cat("\n--- MODEL LOG-LOG CAPEX (EC) ---\n")
    ct_log_capex_ec <- clubSandwich::coef_test(fe_log_capex_ec, vcov = "CR2", cluster = "individual")
    print(ct_log_capex_ec)
    
    fe_log_rd_ec <- plm(log_ec ~ log_rd, data = p_df_ec, model = "within")
    cat("\n--- MODEL LOG-LOG R&D (EC) ---\n")
    print(clubSandwich::coef_test(fe_log_rd_ec, vcov = "CR2", cluster = "individual"))
    
    cat("\n--- MODEL CAPEX + CZAS (EC) ---\n")
    fe_capex_time_ec <- tryCatch({
      m <- plm(ec_density ~ capex + factor(rok), data = p_df_ec, model = "within")
      ct_result <- clubSandwich::coef_test(m, vcov = "CR2", cluster = "individual")
      
      if (is.null(ct_result)) {
        cat("⚠️ coef_test zwrócił NULL - CR2 nie mogło zostać obliczone\n")
        cat("   (zbyt mała liczba obserwacji na klaster po dodaniu efektów czasowych).\n")
        ct_capex_time_ec <- NULL
        NULL   
      } else {
        ct_capex_time_ec <- ct_result
        print(ct_result)
        m
      }
    }, error = function(e) {
      cat("⚠️ Ominięto CR2 dla modelu z czasem ze względu na brak stopni swobody.\n")
      cat("   Treść błędu:", conditionMessage(e), "\n")
      NULL
    })
    
    ct_c_ec <- clubSandwich::coef_test(fe_c_ec, vcov = "CR2", cluster = "individual")
    ct_f_ec <- clubSandwich::coef_test(fe_f_ec, vcov = "CR2", cluster = "individual")
    
    tab19 <- data.frame(
      Model = c("CAPEX (EC)", "CAPEX + R&D (EC)"),
      Wsp_CAPEX = c(round(coef(fe_c_ec)["capex"], 4), round(coef(fe_f_ec)["capex"], 4)),
      P_val_CR2 = c(round(ct_c_ec["capex", "p_Satt"], 4), round(ct_f_ec["capex", "p_Satt"], 4)),
      R2_Within = c(round(summary(fe_c_ec)$r.squared[1], 3), round(summary(fe_f_ec)$r.squared[1], 3))
    )
    print(tab19)
    
    p_ec_raw  <- round(ct_log_capex_ec["log_capex", "p_Satt"], 4)
    if (!is.null(fe_capex_time_ec) && !is.null(ct_capex_time_ec)) {
      p_ec_time <- round(ct_capex_time_ec["capex", "p_Satt"], 4)
      }
    }
    # ===== WERYFIKACJA WYNIKÓW  =====
    ct_capex_raw <- clubSandwich::coef_test(fe_capex, vcov = "CR2", cluster = "individual")
    ct_rd_raw    <- clubSandwich::coef_test(fe_rd,    vcov = "CR2", cluster = "individual")
    
    cat("\n", strrep("=", 70), "\n")
    cat("WERYFIKACJA WYNIKÓW DLA NAKŁADÓW NA INNOWACJE (estymator CR2)\n")
    cat(strrep("=", 70), "\n")
    
    # --- CAPEX (10-K): surowy vs + czas ---
    cat("--- Wpływ CAPEX na gęstość AI (10-K) ---\n")
    beta_raw <- round(coef(fe_capex)["capex"], 4)
    p_raw    <- round(ct_capex_raw["capex", "p_Satt"], 4)
    cat(sprintf("Model surowy (bez kontroli czasu): beta = %.4f | p = %.4f  %s\n",
                beta_raw, p_raw, ifelse(p_raw < 0.05, "✅ istotny", "❌ nieistotny")))
    
    if (!is.null(fe_capex_time) && !is.null(ct_capex_time)) {
      beta_time <- round(coef(fe_capex_time)["capex"], 4)
      p_time    <- round(ct_capex_time["capex", "p_Satt"], 4)
      cat(sprintf("Model + efekty czasowe (rok):      beta = %.4f | p = %.4f  %s\n",
                  beta_time, p_time, ifelse(p_time < 0.05, "✅ istotny", "❌ nieistotny")))
      if (p_raw < 0.05 && p_time >= 0.05) {
        cat("⚠️ Efekt CAPEX traci istotność po kontroli trendu czasowego.\n\n")
      } else {
        cat("\n")
      }
    } else {
      cat("⚠️ Model + czas nie został policzony (brak stopni swobody) - wynik surowy\n")
      cat("   nie został zweryfikowany tym robustness checkiem.\n\n")
    }
    
    # --- CAPEX (EC): log-log vs + czas ---
    if (!is.null(fe_log_capex_ec) && !is.null(p_ec_raw)) {
      cat("--- Wpływ CAPEX na gęstość AI (Earnings Calls) ---\n")
      beta_ec_raw <- round(coef(fe_log_capex_ec)["log_capex"], 4)
      cat(sprintf("Model log-log (bez kontroli czasu): beta = %.4f | p = %.4f  %s\n",
                  beta_ec_raw, p_ec_raw, ifelse(p_ec_raw < 0.05, "✅ istotny", "❌ nieistotny/marginalny")))
      
      if (!is.null(fe_capex_time_ec) && !is.null(p_ec_time)) {
        beta_ec_time <- round(coef(fe_capex_time_ec)["capex"], 4)
        cat(sprintf("Model + efekty czasowe (rok):        beta = %.4f | p = %.4f  %s\n",
                    beta_ec_time, p_ec_time, ifelse(p_ec_time < 0.05, "✅ istotny", "❌ nieistotny")))
        cat("\n")
      } else {
        cat("⚠️ Model + czas dla EC nie został policzony (brak stopni swobody).\n\n")
      }
    }
    
    # --- R&D ---
    cat("--- Wpływ R&D na gęstość AI (10-K) ---\n")
    beta_rd <- round(coef(fe_rd)["rd"], 5)
    p_rd    <- round(ct_rd_raw["rd", "p_Satt"], 4)
    cat(sprintf("beta = %.5f | p = %.4f  %s\n\n", beta_rd, p_rd,
                ifelse(p_rd < 0.05, "✅ istotny", "❌ brak istotnego wpływu")))
    
    # --- PODSUMOWANIE H3 ---
  cat(strrep("-", 70), "\n")
  cat("PODSUMOWANIE H3\n")
  

  model_czas_10k_policzony <- !is.null(fe_capex_time) && !is.null(ct_capex_time)
  model_czas_ec_policzony  <- !is.null(fe_capex_time_ec) && !is.null(ct_capex_time_ec)
  
  # CAPEX
  if (model_czas_10k_policzony || model_czas_ec_policzony) {
    
    capex_traci_10k <- model_czas_10k_policzony && 
      p_raw < 0.05 && round(ct_capex_time["capex", "p_Satt"], 4) >= 0.05
    
    capex_traci_ec <- model_czas_ec_policzony && 
      !is.null(p_ec_time) && p_ec_time >= 0.05
    
    if (capex_traci_10k || capex_traci_ec) {
      cat("Efekt CAPEX traci istotność po kontroli trendu czasowego - niepotwierdzony.\n")
    } else {
      cat("Efekt CAPEX pozostaje istotny po kontroli trendu czasowego.\n")
    }
    
  } else {
    cat("Brak modelu z kontrolą trendu czasowego (brak stopni swobody) - wynik surowy niezweryfikowany.\n")
  }
  
  # R&D
  if (p_rd >= 0.05) {
    cat("R&D: brak istotnego wpływu (p =", round(p_rd, 4), ").\n")
  } else {
    cat("R&D: istotny wpływ (p =", round(p_rd, 4), ").\n")
  }
  
  cat("Uwaga: N = 20 (10-K), przy 5 firmach - wyniki eksploracyjne.\n\n")
    
    fe_capex <<- fe_capex
    fe_rd <<- fe_rd
    fe_full <<- fe_full
    fe_capex_time <<- fe_capex_time
    fe_capex_time_ec <<- fe_capex_time_ec
    
    return(df)
  }


# =====================================================================
# 8. ANALIZA JAKOŚCIOWA
# =====================================================================

qualitative_summary_full <- function(results_10k, results_ec) {
  cat("\n", strrep("=", 70), "\n")
  cat("VI. ANALIZA JAKOŚCIOWA (Future/Risk, General/Specific)\n")
  cat(strrep("=", 70), "\n")
  
  all_results <- bind_rows(
    results_10k,
    results_ec$raw %>% filter(part == "caly")
  )
  
  cat("\n--- TABELA 22: ŚREDNIA DLA GRUPY GAMAM ---\n")
  summary_weighted <- all_results %>% group_by(doc_type) %>%
    summarise(
      Pct_General = round(sum(AI_General_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
      Pct_Specific = round(sum(AI_Specific_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
      Pct_Future = round(sum(Future_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1),
      Pct_Risk = round(sum(Risk_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1)
    )
  print(summary_weighted)
  
  cat("\n--- TABELA 22.1: DLA KAŻDEJ SPÓŁKI ---\n")
  by_company_weighted <- all_results %>% group_by(company, doc_type) %>%
    summarise(
      Pct_General = round(sum(AI_General_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
      Pct_Specific = round(sum(AI_Specific_Count, na.rm = TRUE) / sum(AI_Total, na.rm = TRUE) * 100, 1),
      Pct_Future = round(sum(Future_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1),
      Pct_Risk = round(sum(Risk_Count, na.rm = TRUE) / sum(AI_Sentences_Count, na.rm = TRUE) * 100, 1),
      .groups = "drop"
    ) %>% arrange(company, doc_type)
  
  print(by_company_weighted, n = Inf)
  
  return(all_results)
}

# =====================================================================
# 9. EVENT STUDY
# =====================================================================

calculate_car <- function(event_date, firm, prices_wide, start_shift = -1, end_shift = 1) {
  if (!firm %in% colnames(prices_wide)) return(NA)
  
  idx_pub <- which(prices_wide$data >= event_date)
  if (length(idx_pub) == 0) return(NA)
  idx_pub <- min(idx_pub)
  
  if (abs(prices_wide$data[idx_pub] - event_date) > 3) return(NA)
  
  event_idx <- idx_pub + 1
  if (event_idx < 2 || event_idx > nrow(prices_wide)) return(NA)
  
  est_start <- max(1, idx_pub - 130)
  est_end <- idx_pub - 11
  if (est_end <= est_start || est_end > nrow(prices_wide)) return(NA)
  
  est_data <- prices_wide[est_start:est_end, ]
  firm_returns <- diff(log(est_data[[firm]]))
  market_returns <- diff(log(est_data$SPX))
  valid <- !is.na(firm_returns) & !is.na(market_returns)
  if (sum(valid) < 10) return(NA)
  
  model <- lm(firm_returns[valid] ~ market_returns[valid])
  alpha <- coef(model)[1]
  beta <- coef(model)[2]
  
  ev_start_idx <- max(2, event_idx + start_shift)
  ev_end_idx <- min(nrow(prices_wide), event_idx + end_shift)
  if (ev_start_idx >= ev_end_idx) return(NA)
  
  ev_data <- prices_wide[(ev_start_idx - 1):ev_end_idx, ]
  ar <- c()
  for (i in 2:nrow(ev_data)) {
    firm_ret <- log(ev_data[[firm]][i] / ev_data[[firm]][i-1])
    market_ret <- log(ev_data$SPX[i] / ev_data$SPX[i-1])
    if (!is.na(firm_ret) && !is.na(market_ret)) {
      ar <- c(ar, firm_ret - (alpha + beta * market_ret))
    }
  }
  return(sum(ar, na.rm = TRUE))
}


calculate_car_t0 <- function(event_date, firm, prices_wide) {
  if (!firm %in% colnames(prices_wide)) return(NA)
  
  idx_pub <- which(prices_wide$data >= event_date)
  if (length(idx_pub) == 0) return(NA)
  idx_pub <- min(idx_pub)
  
  if (abs(prices_wide$data[idx_pub] - event_date) > 3) return(NA)
  
  event_idx <- idx_pub + 1
  if (event_idx < 2 || event_idx > nrow(prices_wide)) return(NA)
  
  est_start <- max(1, idx_pub - 130)
  est_end <- idx_pub - 11
  if (est_end <= est_start || est_end > nrow(prices_wide)) return(NA)
  
  est_data <- prices_wide[est_start:est_end, ]
  firm_returns <- diff(log(est_data[[firm]]))
  market_returns <- diff(log(est_data$SPX))
  valid <- !is.na(firm_returns) & !is.na(market_returns)
  if (sum(valid) < 10) return(NA)
  
  model <- lm(firm_returns[valid] ~ market_returns[valid])
  alpha <- coef(model)[1]
  beta <- coef(model)[2]
  
  firm_ret <- log(prices_wide[[firm]][event_idx] / prices_wide[[firm]][event_idx - 1])
  market_ret <- log(prices_wide$SPX[event_idx] / prices_wide$SPX[event_idx - 1])
  if (!is.na(firm_ret) && !is.na(market_ret)) {
    return(firm_ret - (alpha + beta * market_ret))
  }
  return(NA)
}

calculate_sar <- function(event_date, firm, prices_wide, start_shift = -1, end_shift = 1) {
  if (!firm %in% colnames(prices_wide)) return(NA)
  
  idx_pub <- which(prices_wide$data >= event_date)
  if (length(idx_pub) == 0) return(NA)
  idx_pub <- min(idx_pub)
  
  if (abs(prices_wide$data[idx_pub] - event_date) > 3) return(NA)
  
  event_idx <- idx_pub + 1
  if (event_idx < 2 || event_idx > nrow(prices_wide)) return(NA)
  
  est_start <- max(1, idx_pub - 130)
  est_end <- idx_pub - 11
  if (est_end <= est_start || est_end > nrow(prices_wide)) return(NA)
  
  est_data <- prices_wide[est_start:est_end, ]
  firm_returns <- diff(log(est_data[[firm]]))
  market_returns <- diff(log(est_data$SPX))
  valid <- !is.na(firm_returns) & !is.na(market_returns)
  if (sum(valid) < 10) return(NA)
  
  model <- lm(firm_returns[valid] ~ market_returns[valid])
  alpha <- coef(model)[1]
  beta <- coef(model)[2]
  sigma_est <- summary(model)$sigma
  T_est <- length(firm_returns[valid])
  m_avg <- mean(market_returns[valid])
  m_sum_sq <- sum((market_returns[valid] - m_avg)^2)
  
  ev_start_idx <- max(2, event_idx + start_shift)
  ev_end_idx <- min(nrow(prices_wide), event_idx + end_shift)
  if (ev_start_idx >= ev_end_idx) return(NA)
  
  ev_data <- prices_wide[(ev_start_idx - 1):ev_end_idx, ]
  sar_vec <- c()
  for (i in 2:nrow(ev_data)) {
    firm_ret <- log(ev_data[[firm]][i] / ev_data[[firm]][i-1])
    market_ret <- log(ev_data$SPX[i] / ev_data$SPX[i-1])
    if (!is.na(firm_ret) && !is.na(market_ret)) {
      ar_it <- firm_ret - (alpha + beta * market_ret)
      C_it <- sqrt(1 + 1/T_est + ((market_ret - m_avg)^2 / m_sum_sq))
      sar_it <- ar_it / (sigma_est * C_it)
      sar_vec <- c(sar_vec, sar_it)
    }
  }
  return(sum(sar_vec, na.rm = TRUE))
}

calculate_volume_change <- function(event_row, volumes_wide, ev_start = -1, ev_end = 1, shift = 1) {
  event_date <- as.Date(event_row$event_date)
  firm <- event_row$spolka
  vol_col <- firm
  
  if (!vol_col %in% colnames(volumes_wide)) return(NA)
  idx_pub <- which(volumes_wide$data >= event_date)
  if (length(idx_pub) == 0) return(NA)
  idx_pub <- min(idx_pub)
  
  if (abs(volumes_wide$data[idx_pub] - event_date) > 3) return(NA)
  
  event_idx <- idx_pub + shift
  if (event_idx < 1 || event_idx > nrow(volumes_wide)) return(NA)
  
  base_start <- max(1, idx_pub - 60)
  base_end <- idx_pub - 11
  if (base_end <= base_start || base_end > nrow(volumes_wide)) return(NA)
  
  base_vol <- mean(volumes_wide[[vol_col]][base_start:base_end], na.rm = TRUE)
  if (base_vol == 0 || is.na(base_vol)) return(NA)
  
  ev_start_idx <- max(1, event_idx + ev_start)
  ev_end_idx <- min(nrow(volumes_wide), event_idx + ev_end)
  if (ev_start_idx > ev_end_idx) return(NA)
  
  ev_vol <- mean(volumes_wide[[vol_col]][ev_start_idx:ev_end_idx], na.rm = TRUE)
  
  return((ev_vol - base_vol) / base_vol * 100)
}

load_price_data <- function(folder_prices) {
  spolki <- c("AAPL", "MSFT", "GOOGL", "AMZN", "META", "SPX")
  ceny <- list()
  for (s in spolki) {
    csv_file <- file.path(folder_prices, paste0(s, "_US.csv"))
    if (file.exists(csv_file)) {
      d <- read.csv(csv_file)
      colnames(d) <- c("data", "open", "high", "low", "close", "volume")
      d$data <- as.Date(d$data)
      ceny[[s]] <- d[, c("data", "close", "volume")]
    }
  }
  prices_wide <- ceny[["SPX"]] %>% select(data, close) %>% rename(SPX = close)
  for (s in spolki[spolki != "SPX"]) {
    if (!is.null(ceny[[s]])) {
      prices_wide <- prices_wide %>% left_join(ceny[[s]] %>% select(data, close) %>% rename(!!s := close), by = "data")
    }
  }
  volumes_wide <- data.frame(data = prices_wide$data)
  for (s in spolki[spolki != "SPX"]) {
    if (!is.null(ceny[[s]])) {
      volumes_wide <- volumes_wide %>% left_join(ceny[[s]] %>% select(data, volume) %>% rename(!!s := volume), by = "data")
    }
  }
  return(list(prices = prices_wide, volumes = volumes_wide))
}

# === Testy alternatywne dla H4 ===
run_alternative_tests <- function(df_all) {
  cat("\n", strrep("=", 70), "\n")
  cat("VIII. ALTERNATYWNE TESTY STATYSTYCZNE DLA HIPOTEZY H4\n")
  cat(strrep("=", 70), "\n")
  
  # Sprawdź czy df_all istnieje
  if (!exists("df_all")) {
    cat("❌ Brak df_all - najpierw uruchom event study\n")
    return(NULL)
  }
  
  # ===== 1. PRZYGOTOWANIE DANYCH =====
  ec_data <- df_all %>% filter(typ == "Earnings Call",
                               year_calendar %in% c("2022","2023","2024","2025"),
                               !is.na(CAR_m1_1))
  
  cat("\n=== LICZBA OBSERWACJI ===\n")
  cat("EC:", nrow(ec_data), "\n")
  cat("HIGH:", sum(ec_data$ai_intensity == "HIGH"), "\n")
  cat("LOW:", sum(ec_data$ai_intensity == "LOW"), "\n\n")
  
  # ===== 2. TEST PERMUTACYJNY (bez założeń) =====
  cat("=== TEST PERMUTACYJNY ===\n")
  
  obs_diff <- mean(ec_data$CAR_m1_1[ec_data$ai_intensity == "HIGH"]) - 
    mean(ec_data$CAR_m1_1[ec_data$ai_intensity == "LOW"])
  
  set.seed(123)
  n_perm <- 10000
  perm_diffs <- replicate(n_perm, {
    perm_intensity <- sample(ec_data$ai_intensity)
    mean(ec_data$CAR_m1_1[perm_intensity == "HIGH"]) - 
      mean(ec_data$CAR_m1_1[perm_intensity == "LOW"])
  })
  
  p_perm <- mean(abs(perm_diffs) >= abs(obs_diff))
  cat("Obserwowana różnica:", round(obs_diff, 6), "\n")
  cat("p-value (permutacyjny):", p_perm, "\n")
  if(p_perm < 0.05) cat("✅ Istotne\n") else cat("❌ Nieistotne\n\n")
  
  # ===== 3. TEST BAYESA (Bayes Factor) =====
  cat("=== Bayes Factor ===\n")
  
  if (requireNamespace("BayesFactor", quietly = TRUE)) {
    library(BayesFactor)
    bf_result <- ttestBF(formula = CAR_m1_1 ~ ai_intensity, data = ec_data)
    bf <- extractBF(bf_result)$bf
    cat("Bayes Factor:", round(bf, 3), "\n")
    if(bf > 3) {
      cat("✅ Dowód za różnicą (istotne)\n")
    } else if(bf < 1/3) {
      cat("✅ Dowód za BRAKIEM różnicy\n")
    } else {
      cat("❌ Dowód niejednoznaczny\n")
    }
    cat("Interpretacja: BF > 3 = dowód za H1, BF < 1/3 = dowód za brakiem H1\n\n")
  } else {
    cat("⚠️ Pakiet BayesFactor nie jest zainstalowany\n")
    cat("Pomijam ten test\n\n")
  }
  
  # ===== 4. REGRESJA KWANTYLOWA (odporna na outliery) =====
  cat("=== REGRESJA KWANTYLOWA (mediana) ===\n")
  
  if (requireNamespace("quantreg", quietly = TRUE)) {
    library(quantreg)
    
    qr_data <- ec_data
    qr_data$ai_binary <- ifelse(qr_data$ai_intensity == "HIGH", 1, 0)
    qr_data$year_num <- as.numeric(qr_data$year_calendar)
    
    qr_model <- suppressWarnings(rq(CAR_m1_1 ~ ai_binary + year_num, data = qr_data, tau = 0.5))
    qr_sum <- summary(qr_model, se = "boot", R = 1000)
    
    if ("ai_binary" %in% rownames(qr_sum$coefficients)) {
      qr_coef <- qr_sum$coefficients["ai_binary", 1]
      qr_p <- qr_sum$coefficients["ai_binary", 4]
      cat("Różnica median (HIGH vs LOW):", round(qr_coef, 6), "\n")
      cat("p-value:", round(qr_p, 4), "\n")
      if(qr_p < 0.05) cat("✅ Istotne\n") else cat("❌ Nieistotne\n\n")
    } else {
      cat("Brak współczynnika w modelu\n")
      cat("Dostępne współczynniki:", paste(rownames(qr_sum$coefficients), collapse=", "), "\n\n")
    }
  } else {
    cat("⚠️ Pakiet quantreg nie jest zainstalowany\n")
    cat("Pomijam ten test\n\n")
  }
  
  # ===== 5. BOOTSTRAPOWY PRZEDZIAŁ UFNOŚCI =====
  cat("=== BOOTSTRAPOWY PRZEDZIAŁ UFNOŚCI ===\n")
  
  set.seed(123)
  n_boot <- 5000
  boot_diffs <- replicate(n_boot, {
    boot_idx <- sample(1:nrow(ec_data), replace = TRUE)
    boot_df <- ec_data[boot_idx, ]
    mean(boot_df$CAR_m1_1[boot_df$ai_intensity == "HIGH"]) - 
      mean(boot_df$CAR_m1_1[boot_df$ai_intensity == "LOW"])
  })
  
  ci_boot <- quantile(boot_diffs, c(0.025, 0.975))
  cat("95% przedział ufności (bootstrap): [", round(ci_boot[1], 6), ", ", round(ci_boot[2], 6), "]\n")
  if(ci_boot[1] > 0 || ci_boot[2] < 0) {
    cat("✅ Przedział nie zawiera 0 – istotne\n\n")
  } else {
    cat("❌ Przedział zawiera 0 – nieistotne\n\n")
  }
  
  # ===== 6. ANALIZA ZMIANY INTENSYWNOŚCI AI (delta_density) =====
  cat("=== ANALIZA ZMIANY INTENSYWNOŚCI AI (delta_density) ===\n")
  cat("Hipoteza: rynek reaguje na WZROST ujawnień AI, nie na ich poziom\n\n")
  
  p_matched <- NA
  t_test_matched_result <- NULL
  
delta_data <- df_all %>%
  filter(typ == "Earnings Call",
         year_calendar %in% c("2022", "2023", "2024", "2025"),
         !is.na(CAR_m1_1), !is.na(density)) %>%
  distinct(spolka, event_date, .keep_all = TRUE) %>%
  arrange(spolka, event_date) %>%
  group_by(spolka) %>%
  mutate(
    density_lag   = dplyr::lag(density),
    delta_density = density - density_lag
  ) %>%
  ungroup() %>%
  filter(!is.na(delta_density)) %>%
  mutate(
    period_id = as.numeric(factor(event_date)),
    year_id   = as.factor(year_calendar)          
  )

cat("Obserwacji po usunięciu pierwszego okresu:", nrow(delta_data), "\n")
cat("Firm:", length(unique(delta_data$spolka)), "\n")
cat("⚠️ Uwaga: liczba klastrów (firm) =", length(unique(delta_data$spolka)), "\n",
    "- poniżej progu rekomendowanego dla stabilnej inferencji CR2\n\n")

delta_data <- delta_data %>%
  mutate(delta_direction = ifelse(delta_density > 0, "WZROST", "SPADEK"))

cat("--- Rozkład kierunku zmian ---\n")
print(table(delta_data$delta_direction, delta_data$year_calendar))
cat("\n")

# --- MODEL 1: FE(firma) + rok + CR2, delta_density ciągła ---
cat("--- MODEL 1: CAR ~ delta_density + year_id (FE firma, CR2) ---\n")
p_delta <- pdata.frame(delta_data, index = c("spolka", "period_id"))

fe_delta_1 <- plm(CAR_m1_1 ~ delta_density + year_id,
                  data  = p_delta,
                  model = "within")

cat("N:", nobs(fe_delta_1), "\n")
print(summary(fe_delta_1))

cr2_delta_1 <- clubSandwich::coef_test(fe_delta_1, vcov = "CR2", cluster = "individual")
cat("\nWspółczynnik delta_density:", round(cr2_delta_1["delta_density", "beta"], 6), "\n")
cat("p-value (Satterthwaite):",    round(cr2_delta_1["delta_density", "p_Satt"], 4), "\n")
if (cr2_delta_1["delta_density", "p_Satt"] < 0.05) {
  cat("✅ Istotne – rynek reaguje na zmianę intensywności AI\n\n")
} else {
  cat("❌ Nieistotne\n\n")
}

# --- MODEL 2: FE(firma) + rok + CR2, delta_density + eps_surprise ---
cat("--- MODEL 2: CAR ~ delta_density + eps_surprise + year_id (FE firma, CR2) ---\n")
fe_delta_2 <- plm(CAR_m1_1 ~ delta_density + eps_surprise + year_id,
                  data  = p_delta,
                  model = "within")

cat("N:", nobs(fe_delta_2), "\n")
print(summary(fe_delta_2))

cr2_delta_2 <- clubSandwich::coef_test(fe_delta_2, vcov = "CR2", cluster = "individual")
cat("\nWspółczynnik delta_density:", round(cr2_delta_2["delta_density", "beta"], 6), "\n")
cat("p-value (Satterthwaite):",    round(cr2_delta_2["delta_density", "p_Satt"], 4), "\n")
cat("Współczynnik eps_surprise:",  round(cr2_delta_2["eps_surprise", "beta"], 6), "\n")
cat("p-value eps_surprise:",       round(cr2_delta_2["eps_surprise", "p_Satt"], 4), "\n")
if (cr2_delta_2["delta_density", "p_Satt"] < 0.05) {
  cat("✅ Istotne po kontroli EPS surprise\n\n")
} else {
  cat("❌ Nieistotne po kontroli EPS surprise\n\n")
}

cat("--- Podsumowanie modeli FE (delta_density) ---\n")
summary_delta <- data.frame(
  Model      = c("M1: CAR ~ delta_density + rok",
                 "M2: CAR ~ delta_density + EPS + rok"),
  Beta_delta = round(c(cr2_delta_1["delta_density", "beta"],
                        cr2_delta_2["delta_density", "beta"]), 6),
  SE         = round(c(cr2_delta_1["delta_density", "SE"],
                        cr2_delta_2["delta_density", "SE"]), 6),
  p_Satt     = round(c(cr2_delta_1["delta_density", "p_Satt"],
                        cr2_delta_2["delta_density", "p_Satt"]), 4),
  Istotne    = ifelse(c(cr2_delta_1["delta_density", "p_Satt"],
                        cr2_delta_2["delta_density", "p_Satt"]) < 0.05, "✅", "❌")
)
print(summary_delta)

cat("\n--- Średni CAR według kierunku zmiany i roku ---\n")
delta_summary <- delta_data %>%
  group_by(year_calendar, delta_direction) %>%
  summarise(
    mean_CAR = round(mean(CAR_m1_1, na.rm = TRUE), 5),
    n        = n(),
    .groups  = "drop"
  ) %>%
  pivot_wider(names_from  = delta_direction,
              values_from = c(mean_CAR, n),
              values_fill = list(mean_CAR = NA, n = 0))
print(delta_summary)

p_matched <- cr2_delta_2["delta_density", "p_Satt"]
  
  # ===== PODSUMOWANIE =====
  cat("\n", strrep("=", 70), "\n")
  cat("PODSUMOWANIE ALTERNATYWNYCH TESTÓW\n")
  cat(strrep("=", 70), "\n")
  
  cat("Test permutacyjny: p =", round(p_perm, 4), if(p_perm < 0.05) " ✅" else " ❌", "\n")
  
  if (exists("bf")) {
    cat("Bayes Factor: BF =", round(bf, 3),
        if(bf > 3) " ✅ (za H1)" else if(bf < 1/3) " ✅ (za brakiem H1)" else " ❌ (niejednoznaczny)", "\n")
  }
  
  if (exists("qr_p")) {
    cat("Regresja kwantylowa: p =", round(qr_p, 4), if(qr_p < 0.05) " ✅" else " ❌", "\n")
  }
  
  cat("Bootstrap CI: ", if(ci_boot[1] > 0 || ci_boot[2] < 0) "✅ (nie zawiera 0)" else "❌ (zawiera 0)", "\n")
  
  cat("Analiza delta_density:",
      if (!is.na(p_matched)) {
        paste0("p = ", round(p_matched, 4), if (p_matched < 0.05) " ✅" else " ❌")
      } else "❌ brak wyników", "\n")
  
  # Zwróć wyniki
  return(list(
    obs_diff = obs_diff,
    p_perm = p_perm,
    bf = if(exists("bf")) bf else NA,
    qr_p = if(exists("qr_p")) qr_p else NA,
    ci_boot = ci_boot
  ))
}

analyze_event_study <- function(folder_7, ai_terms_sorted) {
  cat("\n", strrep("=", 70), "\n")
  cat("VII. EVENT STUDY (CAR, BMP, wolumen, H4, T+0, bez 2022)\n")
  cat("UWAGA: Czytanie plików bezpośrednio z folderu:", folder_7, "\n")
  cat(strrep("=", 70), "\n")
  
  pliki <- list.files(folder_7, pattern = "\\.pdf$|\\.txt$", full.names = TRUE, recursive = FALSE)
  cat("Znaleziono plików:", length(pliki), "\n")
  wyniki <- list()
  
  # LICZNIK POSTĘPU
  total_files <- length(pliki)
  processed_files <- 0
  
  for (plik in pliki) {
    processed_files <- processed_files + 1
    nazwa <- basename(plik)
    
    if (grepl("10-K", nazwa, ignore.case = TRUE)) { typ <- "10-K"
    } else if (grepl("10-Q", nazwa, ignore.case = TRUE)) { typ <- "10-Q"
    } else if (grepl("earnings", nazwa, ignore.case = TRUE) || grepl("Earnings", nazwa)) { typ <- "Earnings Call"
    } else { next }
    
    if (grepl("Alphabet|GOOGL", nazwa, ignore.case = TRUE)) { spolka <- "GOOGL"
    } else if (grepl("Amazon|AMZN", nazwa, ignore.case = TRUE)) { spolka <- "AMZN"
    } else if (grepl("Apple|AAPL", nazwa, ignore.case = TRUE)) { spolka <- "AAPL"
    } else if (grepl("Meta|META|Facebook", nazwa, ignore.case = TRUE)) { spolka <- "META"
    } else if (grepl("Microsoft|MSFT", nazwa, ignore.case = TRUE)) { spolka <- "MSFT"
    } else { next }
    
    rok <- str_extract(nazwa, "202[0-6]")
    if (is.na(rok)) next
    
    kwartal <- str_extract(nazwa, "Q[1-4]")
    if (is.na(kwartal)) {
      kwartal <- str_extract(nazwa, "(?<=10-Q)[1-4]")
      if (!is.na(kwartal)) kwartal <- paste0("Q", kwartal)
    }
    if (is.na(kwartal)) kwartal <- "unknown"
    
    if (grepl("\\.pdf$", nazwa, ignore.case = TRUE)) {
      text <- tryCatch({
        pages <- pdftools::pdf_text(plik)
        pages <- pages[nchar(pages) > 20]
        text <- paste(pages, collapse = " ")
        text <- gsub("([a-zA-Z])-\\s+([a-zA-Z])", "\\1\\2", text)
        text <- gsub("([a-zA-Z])-\\n+([a-zA-Z])", "\\1\\2", text)
        text <- gsub("[\r\n\t]", " ", text)
        text <- gsub("\\s+", " ", text)
        text <- iconv(text, from = "UTF-8", to = "ASCII", sub = " ")
        clean_text(text)
      }, error = function(e) { "" })
    } else {
      text <- tryCatch({
        text <- paste(readLines(plik, warn = FALSE), collapse = " ")
        clean_text(text)
      }, error = function(e) { "" })
    }
    
    if (nchar(text) < 50) next
    
    mentions <- count_terms(text, ai_terms_sorted)
    words <- count_words(text)
    density <- ifelse(words > 0, round((mentions / words) * 1000, 2), 0)
    
    cat(sprintf("\r[%d/%d] %s | %s %s %s | AI: %d (%.2f)", 
                processed_files, total_files, spolka, typ, rok, kwartal, mentions, density), flush = TRUE)
    flush.console()
    
    wyniki[[length(wyniki) + 1]] <- data.frame(
      plik = nazwa, spolka = spolka, typ = typ,
      rok = rok, kwartal = kwartal, density = density,
      stringsAsFactors = FALSE
    )
  }
  cat("\n")
  
  df_documents <- bind_rows(wyniki)
  cat("\n=== Wczytano dokumentów:", nrow(df_documents), "===\n")
  
  df_documents <- df_documents %>%
    mutate(
      kwartal = ifelse(typ == "10-K", "Q4", kwartal),
      kwartal = ifelse(kwartal == "unknown", NA, kwartal),
      rok = as.character(rok)
    ) %>%
    filter(!is.na(kwartal))
  
  excel_file <- file.path(folder_7, "mag_tabele_i_wykresy.xlsx")
  if (!file.exists(excel_file)) {
    cat("⚠️ Brak pliku Excel z datami zdarzeń – pomijam event study\n")
    return(NULL)
  }
  
  events <- read_excel(excel_file) %>%
    mutate(event_date = as.Date(event_date, format = "%d.%m.%Y"),
           firm_symbol = str_remove(firm_symbol, "\\.US$"),
           group = case_when(
             grepl("Earnings", group, ignore.case = TRUE) ~ "Earnings Call",
             TRUE ~ group
           ),
           year_fiscal = as.character(year),
           quarter_fiscal = as.character(quarter),
           eps_surprise = as.numeric(eps_surprise))
  assign("df_documents", df_documents, envir = .GlobalEnv)
  assign("events", events, envir = .GlobalEnv)
  df_all <- df_documents %>%
    inner_join(events, by = c("spolka" = "firm_symbol", "typ" = "group", 
                              "rok" = "year_fiscal", "kwartal" = "quarter_fiscal")) %>%
    mutate(year_calendar = as.character(year(ymd(event_date))))
  
  cat("Połączono zdarzeń:", nrow(df_all), "\n")
  if (nrow(df_all) == 0) return(NULL)
  
  price_vol <- load_price_data(folder_7)
  prices_wide <- price_vol$prices
  volumes_wide <- price_vol$volumes
  
  windows <- list(
    list(name = "m1_1", start = -1, end = 1, label = "[-1,+1]"),
    list(name = "m2_2", start = -2, end = 2, label = "[-2,+2]"),
    list(name = "m3_3", start = -3, end = 3, label = "[-3,+3]"),
    list(name = "m5_5", start = -5, end = 5, label = "[-5,+5]")
  )
  
  cat("\n", strrep("-", 70), "\n")
  cat("OBLICZAM CAR DLA RÓŻNYCH OKIEN\n")
  cat(strrep("-", 70), "\n")
  
  total_events <- nrow(df_all)
  bar_width <- 40 
  
  for (w in windows) {
    col_name <- paste0("CAR_", w$name)
    cat(sprintf("\n→ Okno %s (%d zdarzeń)\n", w$label, total_events), flush = TRUE)
    
    cat("  [", paste(rep(" ", bar_width), collapse = ""), "] 0%", sep = "", flush = TRUE)
    
    df_all[[col_name]] <- sapply(1:nrow(df_all), function(i) {
      if (i %% max(1, round(total_events/20)) == 0 || i == total_events) {
        pct <- round(i/total_events * 100)
        filled <- round(pct/100 * bar_width)
        
        cat(sprintf("\r  [%s%s] %3d%%", 
                    paste(rep("=", filled), collapse = ""),
                    paste(rep(" ", bar_width - filled), collapse = ""),
                    pct), flush = TRUE)
        flush.console()
      }
      
      calculate_car(df_all$event_date[i], df_all$spolka[i], prices_wide, w$start, w$end)
    })
    
    cat("\n", flush = TRUE)
    completed <- sum(!is.na(df_all[[col_name]]))
    cat(sprintf("  ✅ %d/%d obliczeń CAR\n", completed, total_events), flush = TRUE)
  }
  
  df_all$CAR <- df_all$CAR_m1_1
  
  # === PODZIAŁ NA GRUPY HIGH/LOW ===
  medians <- df_all %>% group_by(typ) %>% summarise(med = median(density, na.rm = TRUE))
  df_all <- df_all %>% left_join(medians, by = "typ") %>%
    mutate(ai_intensity = ifelse(density > med, "HIGH", "LOW")) %>%
    select(-med)
  
  cat("\n--- MEDIANY GĘSTOŚCI AI (podział HIGH/LOW) ---\n")
  for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
    med_val <- medians %>% filter(typ == doc_type) %>% pull(med)
    cat(paste0(doc_type, ": ", round(med_val, 4), "\n"))
  }
  cat("\n")
  

  cat("\n--- TABELA 23: CAAR (Średnie CAR) ---")
  for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
    df_type <- df_all %>% filter(typ == doc_type)
    if(nrow(df_type) == 0) next
    cat(paste0("\n", doc_type, ":\n"))
    for (w in windows) {
      col_name <- paste0("CAR_", w$name)
      mean_car <- mean(df_type[[col_name]], na.rm = TRUE)
      sd_car <- sd(df_type[[col_name]], na.rm = TRUE)
      n_car <- sum(!is.na(df_type[[col_name]]))
      t_stat <- mean_car / (sd_car / sqrt(n_car))
      p_value <- 2 * pt(-abs(t_stat), df = n_car - 1)
      cat(paste(w$label, "- Średni CAR:", round(mean_car, 5), 
                "(t =", round(t_stat, 3), ", p =", round(p_value, 4), ")\n"))
    }
  }
  

  cat("\n--- TABELA 24: TEST HIPOTEZY H4 – Porównanie CAR między HIGH a LOW  ---\n")
  ev_summary <- list()
  for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
    df_type <- df_all %>% filter(typ == doc_type)
    if(nrow(df_type) == 0) next
    
    for (w in windows) {
      col_name <- paste0("CAR_", w$name)
      df_clean <- df_type %>% filter(!is.na(.data[[col_name]]))
      
      if (nrow(df_clean) >= 10 && length(unique(df_clean$ai_intensity)) == 2) {
        df_clean$ai_intensity <- relevel(factor(df_clean$ai_intensity), ref = "LOW")
        model <- lm(as.formula(paste(col_name, "~ ai_intensity + factor(year_calendar)")), data = df_clean)
        wilcox_t <- wilcox.test(as.formula(paste(col_name, "~ ai_intensity")), data = df_clean)
        
        if ("ai_intensityHIGH" %in% rownames(summary(model)$coefficients)) {
          
          # Zastosowanie estymatora CR2
          res_cr2 <- clubSandwich::coef_test(model, vcov = "CR2", cluster = df_clean$spolka)
          
          ev_summary[[length(ev_summary)+1]] <- data.frame(
            Typ = doc_type, Okno = w$label,
            Mean_HIGH = round(mean(df_clean[[col_name]][df_clean$ai_intensity == "HIGH"]), 5),
            Mean_LOW = round(mean(df_clean[[col_name]][df_clean$ai_intensity == "LOW"]), 5),
            SD_HIGH = round(sd(df_clean[[col_name]][df_clean$ai_intensity == "HIGH"]), 5),
            SD_LOW = round(sd(df_clean[[col_name]][df_clean$ai_intensity == "LOW"]), 5),
            Median_HIGH = round(median(df_clean[[col_name]][df_clean$ai_intensity == "HIGH"]), 5),
            Median_LOW = round(median(df_clean[[col_name]][df_clean$ai_intensity == "LOW"]), 5),
            T_stat = round(res_cr2["ai_intensityHIGH", "tstat"], 3),
            P_val_T_test = round(res_cr2["ai_intensityHIGH", "p_Satt"], 4), # Pobiera p-value Satterthwaite'a
            P_val_Wilcoxon = round(wilcox_t$p.value, 4),
            N_HIGH = sum(df_clean$ai_intensity == "HIGH"),
            N_LOW = sum(df_clean$ai_intensity == "LOW")
          )
        }
      }
    }
  }
  if(length(ev_summary) > 0) {
    final_table <- bind_rows(ev_summary)
    rownames(final_table) <- NULL  
    print(final_table)
  }
  
  cat("\n--- TABELA 26: TEST BMP ---")
  for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
    df_type <- df_all %>% filter(typ == doc_type, !is.na(CAR_m1_1))
    if(nrow(df_type) < 10) next
    
    # ===== BMP dla całej próby (przed podziałem) =====
    scars_all <- sapply(1:nrow(df_type), function(i) {
      calculate_sar(df_type$event_date[i], df_type$spolka[i], prices_wide, -1, 1)
    })
    scars_all <- scars_all[!is.na(scars_all)]
    n_all <- length(scars_all)
    z_all <- mean(scars_all) / (sd(scars_all) / sqrt(n_all))
    p_all <- 2 * pt(-abs(z_all), df = n_all - 1)
    
    cat(paste0("\n--- BMP: ", doc_type, " (cała próba) ---\n"))
    cat(paste("Mean_SCAR =", round(mean(scars_all), 4), 
              "| Z =", round(z_all, 3), 
              "| p =", round(p_all, 4), 
              "| n =", n_all, "\n"))
    
    # ===== BMP dla grup HIGH/LOW =====
    df_type$SCAR <- scars_all
    df_type <- df_type[!is.na(df_type$SCAR), ]
    
    if(nrow(df_type) > 0 && length(unique(df_type$ai_intensity)) == 2) {
      bmp_results <- df_type %>% group_by(ai_intensity) %>%
        summarise(
          Mean_SCAR = round(mean(SCAR), 4), 
          SD_SCAR = round(sd(SCAR), 3),
          n = n(), 
          BMP_Z = round(mean(SCAR) / (sd(SCAR) / sqrt(n())), 3),
          p_value = round(2 * pt(-abs(mean(SCAR) / (sd(SCAR) / sqrt(n()))), df = n() - 1), 4), 
          .groups = "drop"
        )
      cat(paste0("\n--- BMP: ", doc_type, " (podział HIGH/LOW) ---\n"))
      print(bmp_results)
    }
  }
  
  cat("\n--- ANALIZA WOLUMENU ---")
  for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
    df_type <- df_all %>% filter(typ == doc_type, !is.na(ai_intensity))
    if(nrow(df_type) == 0) next
    df_type$Volume_Change <- sapply(1:nrow(df_type), function(i) {
      calculate_volume_change(df_type[i, ], volumes_wide, -1, 1, 1)
    })
    df_clean <- df_type %>% filter(abs(Volume_Change) <= 200, !is.na(Volume_Change))
    if(nrow(df_clean) > 0 && length(unique(df_clean$ai_intensity)) == 2) {
      vol_high <- mean(df_clean$Volume_Change[df_clean$ai_intensity == "HIGH"], na.rm = TRUE)
      vol_low <- mean(df_clean$Volume_Change[df_clean$ai_intensity == "LOW"], na.rm = TRUE)
      vol_test <- t.test(Volume_Change ~ ai_intensity, data = df_clean)
      cat(paste0("\n--- WOLUMEN: ", doc_type, " ---\n"))
      cat(paste("Średnia zmiana HIGH:", round(vol_high, 1), "% | LOW:", round(vol_low, 1), "%\n"))
      cat(paste("p-value:", round(vol_test$p.value, 4)))
      if(vol_test$p.value < 0.05) cat(" ✅ Istotna różnica\n") else cat(" ❌ Brak istotnej różnicy\n")
    }
  }
  
  
  df_all$CAR_t0 <- sapply(1:nrow(df_all), function(i) {
    calculate_car_t0(df_all$event_date[i], df_all$spolka[i], prices_wide)
  })
  cat("\n--- SPECYFIKACJA T+0 (dzień publikacji) dla 10-K ---\n")
  k10_t0 <- df_all %>% filter(typ == "10-K", year_calendar %in% c("2022","2023","2024","2025"),
                              !is.na(CAR_t0), !is.na(ai_intensity))
  k10_t0_clean <- k10_t0 
  if (nrow(k10_t0_clean) >= 10 && length(unique(k10_t0_clean$ai_intensity)) == 2) {
    k10_t0_clean$ai_intensity <- relevel(factor(k10_t0_clean$ai_intensity), ref = "LOW")
    model_k10_t0 <- lm(CAR_t0 ~ ai_intensity + factor(year_calendar), data = k10_t0_clean)
    coef_high_k10 <- summary(model_k10_t0)$coefficients["ai_intensityHIGH", ]
    wilcox_k10_t0 <- wilcox.test(CAR_t0 ~ ai_intensity, data = k10_t0_clean)
    cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10[1], 5), "\n"))
    cat(paste("p-value (t):", round(coef_high_k10[4], 4), "\n"))
    cat(paste("p-value (Mann-Whitney):", round(wilcox_k10_t0$p.value, 4), "\n"))
  } else {
    cat("Za mało obserwacji (n =", nrow(k10_t0_clean), ")\n")
  }
  
  cat("\n--- SPECYFIKACJA T+0 (dzień publikacji) dla Earnings Calls ---\n")
  ec_t0 <- df_all %>% filter(typ == "Earnings Call", year_calendar %in% c("2022","2023","2024","2025"),
                             !is.na(CAR_t0), !is.na(ai_intensity))
  ec_t0_clean <- ec_t0 
  if (nrow(ec_t0_clean) >= 10 && length(unique(ec_t0_clean$ai_intensity)) == 2) {
    ec_t0_clean$ai_intensity <- relevel(factor(ec_t0_clean$ai_intensity), ref = "LOW")
    model_t0 <- lm(CAR_t0 ~ ai_intensity + factor(year_calendar), data = ec_t0_clean)
    coef_high_t0 <- summary(model_t0)$coefficients["ai_intensityHIGH", ]
    wilcox_t0 <- wilcox.test(CAR_t0 ~ ai_intensity, data = ec_t0_clean)
    cat(paste("Różnica HIGH vs LOW:", round(coef_high_t0[1], 5), "\n"))
    cat(paste("p-value (t):", round(coef_high_t0[4], 4), "\n"))
    cat(paste("p-value (Mann-Whitney):", round(wilcox_t0$p.value, 4), "\n"))
  }
  
  cat("\n--- SPECYFIKACJA T+0 (dzień publikacji) dla 10-Q ---\n")
  k10q_t0 <- df_all %>% filter(typ == "10-Q", year_calendar %in% c("2022","2023","2024","2025"),
                               !is.na(CAR_t0), !is.na(ai_intensity))
  k10q_t0_clean <- k10q_t0 
  if (nrow(k10q_t0_clean) >= 10 && length(unique(k10q_t0_clean$ai_intensity)) == 2) {
    k10q_t0_clean$ai_intensity <- relevel(factor(k10q_t0_clean$ai_intensity), ref = "LOW")
    model_k10q_t0 <- lm(CAR_t0 ~ ai_intensity + factor(year_calendar), data = k10q_t0_clean)
    coef_high_k10q <- summary(model_k10q_t0)$coefficients["ai_intensityHIGH", ]
    wilcox_k10q_t0 <- wilcox.test(CAR_t0 ~ ai_intensity, data = k10q_t0_clean)
    cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10q[1], 5), "\n"))
    cat(paste("p-value (t):", round(coef_high_k10q[4], 4), "\n"))
    cat(paste("p-value (Mann-Whitney):", round(wilcox_k10q_t0$p.value, 4), "\n"))
  } else {
    cat("Za mało obserwacji (n =", nrow(k10q_t0_clean), ")\n")
  }
  
  cat("\n--- 10-K BEZ ROKU 2022 ---\n")
  k10_no2022 <- df_all %>% filter(typ == "10-K", year_calendar %in% c("2023","2024","2025"),
                                  !is.na(CAR_m1_1), !is.na(ai_intensity))
  if (nrow(k10_no2022) >= 10 && length(unique(k10_no2022$ai_intensity)) == 2) {
    k10_no2022$ai_intensity <- relevel(factor(k10_no2022$ai_intensity), ref = "LOW")
    model_k10_no2022 <- lm(CAR_m1_1 ~ ai_intensity + factor(year_calendar), data = k10_no2022)
    coef_high_k10_no2022 <- summary(model_k10_no2022)$coefficients["ai_intensityHIGH", ]
    wilcox_k10_no2022 <- wilcox.test(CAR_m1_1 ~ ai_intensity, data = k10_no2022)
    cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10_no2022[1], 5), "\n"))
    cat(paste("p-value (t):", round(coef_high_k10_no2022[4], 4), "\n"))
    cat(paste("p-value (Mann-Whitney):", round(wilcox_k10_no2022$p.value, 4), "\n"))
  } else {
    cat("Za mało obserwacji (n =", nrow(k10_no2022), ")\n")
  }
  
  cat("\n--- EARNINGS CALLS BEZ ROKU 2022 ---\n")
  ec_no2022 <- df_all %>% filter(typ == "Earnings Call", year_calendar %in% c("2023","2024","2025"),
                                 !is.na(CAR_m1_1), !is.na(ai_intensity))
  if (nrow(ec_no2022) >= 10 && length(unique(ec_no2022$ai_intensity)) == 2) {
    ec_no2022$ai_intensity <- relevel(factor(ec_no2022$ai_intensity), ref = "LOW")
    model_no2022 <- lm(CAR_m1_1 ~ ai_intensity + factor(year_calendar), data = ec_no2022)
    coef_high_no2022 <- summary(model_no2022)$coefficients["ai_intensityHIGH", ]
    wilcox_no2022 <- wilcox.test(CAR_m1_1 ~ ai_intensity, data = ec_no2022)
    cat(paste("Różnica HIGH vs LOW:", round(coef_high_no2022[1], 5), "\n"))
    cat(paste("p-value (t):", round(coef_high_no2022[4], 4), "\n"))
    cat(paste("p-value (Mann-Whitney):", round(wilcox_no2022$p.value, 4), "\n"))
  }
  
  cat("\n--- 10-Q BEZ ROKU 2022 ---\n")
  k10q_no2022 <- df_all %>% filter(typ == "10-Q", year_calendar %in% c("2023","2024","2025"),
                                   !is.na(CAR_m1_1), !is.na(ai_intensity))
  if (nrow(k10q_no2022) >= 10 && length(unique(k10q_no2022$ai_intensity)) == 2) {
    k10q_no2022$ai_intensity <- relevel(factor(k10q_no2022$ai_intensity), ref = "LOW")
    model_k10q_no2022 <- lm(CAR_m1_1 ~ ai_intensity + factor(year_calendar), data = k10q_no2022)
    coef_high_k10q_no2022 <- summary(model_k10q_no2022)$coefficients["ai_intensityHIGH", ]
    wilcox_k10q_no2022 <- wilcox.test(CAR_m1_1 ~ ai_intensity, data = k10q_no2022)
    cat(paste("Różnica HIGH vs LOW:", round(coef_high_k10q_no2022[1], 5), "\n"))
    cat(paste("p-value (t):", round(coef_high_k10q_no2022[4], 4), "\n"))
    cat(paste("p-value (Mann-Whitney):", round(wilcox_k10q_no2022$p.value, 4), "\n"))
  } else {
    cat("Za mało obserwacji (n =", nrow(k10q_no2022), ")\n")
  }
  
  # ============================================================
  # PLACEBO TEST
  # ============================================================
  cat("\n", strrep("=", 70), "\n")
  cat("PLACEBO TEST – LOSOWE PRZESUNIĘCIE DAT ZDARZEŃ\n")
  cat(strrep("=", 70), "\n")
  
  set.seed(123)
  
  # Dla Earnings Calls (najwięcej obserwacji)
  df_placebo <- df_all %>% filter(typ == "Earnings Call")
  
  # Losowe przesunięcie dat o -60, -30, +30, +60 dni
  shifts <- sample(c(-60, -30, 30, 60), nrow(df_placebo), replace = TRUE)
  df_placebo$placebo_date <- df_placebo$event_date + shifts
  
  df_placebo$CAR_placebo <- sapply(1:nrow(df_placebo), function(i) {
    calculate_car(df_placebo$placebo_date[i], df_placebo$spolka[i], prices_wide, -1, 1)
  })
  
  mean_placebo <- mean(df_placebo$CAR_placebo, na.rm = TRUE)
  sd_placebo <- sd(df_placebo$CAR_placebo, na.rm = TRUE)
  n_placebo <- sum(!is.na(df_placebo$CAR_placebo))
  t_placebo <- mean_placebo / (sd_placebo / sqrt(n_placebo))
  p_placebo <- 2 * pt(-abs(t_placebo), df = n_placebo - 1)
  
  cat("\n--- Placebo test (losowe przesunięcie dat o ±30-60 dni) ---\n")
  cat(paste("Średni CAR placebo:", round(mean_placebo, 6), "\n"))
  cat(paste("t-stat:", round(t_placebo, 3), "\n"))
  cat(paste("p-value:", round(p_placebo, 4), "\n"))
  
  if(p_placebo < 0.05) {
    cat("⚠️ UWAGA: Placebo CAR jest istotne – metoda może być błędna!\n")
  } else {
    cat("✅ Placebo CAR nieistotne – metoda event study działa poprawnie.\n")
  }
  
  cat("\n--- Placebo test – wielokrotny (100 powtórzeń) ---\n")
  set.seed(123)
  p_values_placebo <- replicate(100, {
    shifts_rep <- sample(c(-60, -30, 30, 60), nrow(df_placebo), replace = TRUE)
    placebo_date_rep <- df_placebo$event_date + shifts_rep
    car_placebo_rep <- sapply(1:nrow(df_placebo), function(i) {
      calculate_car(placebo_date_rep[i], df_placebo$spolka[i], prices_wide, -1, 1)
    })
    t_test_rep <- t.test(car_placebo_rep[!is.na(car_placebo_rep)])
    t_test_rep$p.value
  })
  
  cat(paste("Średnia p-value z 100 placebo testów:", round(mean(p_values_placebo), 4), "\n"))
  cat(paste("Odsetek istotnych (p < 0.05):", round(mean(p_values_placebo < 0.05) * 100, 1), "%\n"))
  
  if(mean(p_values_placebo < 0.05) < 0.05) {
    cat("✅ Mniej niż 5% placebo testów istotnych – metoda działa poprawnie.\n")
  } else {
    cat("⚠️ Ponad 5% placebo testów istotnych – potencjalny problem.\n")
  }
  
  # ============================================================
  # ROZSZERZONE MODELE REGRESYJNE H4 
  # ============================================================
  
  # Przygotowanie danych dla EC
  dane_reg <- df_all %>%
    filter(typ == "Earnings Call",
           year_calendar %in% c("2022","2023","2024","2025"),
           !is.na(CAR_m1_1)) %>%
    mutate(
      AI_Intensity = density,
      AI_HIGH = ifelse(ai_intensity == "HIGH", 1, 0),
      SUE = eps_surprise,
      firm_id = as.factor(spolka),
      year_id = as.factor(year_calendar)
    )
  
  # ===== DIAGNOSTYKA MODELU REGRESYJNEGO (EC) =====
  cat("\n", strrep("=", 70), "\n")
  cat("DIAGNOSTYKA MODELU REGRESYJNEGO (Earnings Calls)\n")
  cat(strrep("=", 70), "\n")
  
  # 1. Test normalności (Shapiro-Wilk) dla CAR
  car_values <- dane_reg$CAR_m1_1[!is.na(dane_reg$CAR_m1_1)]
  if (length(car_values) >= 3 && length(car_values) <= 5000) {
    sw_test <- shapiro.test(car_values)
    cat("\n--- Test Shapiro-Wilka (normalność CAR) ---\n")
    print(sw_test)
    if (sw_test$p.value < 0.05) cat("⚠️ Rozkład CAR nie jest normalny – uzasadnienie dla testu Manna-Whitneya\n")
  }
  
  # 2. Test Levene'a 
  if (requireNamespace("car", quietly = TRUE)) {
    lev_test <- suppressWarnings(car::leveneTest(CAR_m1_1 ~ ai_intensity, data = dane_reg))
    cat("\n--- Test Levene'a (równość wariancji HIGH vs LOW) ---\n")
    print(lev_test)
    if (!is.na(lev_test$`Pr(>F)`[1]) && lev_test$`Pr(>F)`[1] < 0.05) {
      cat("⚠️ Wariancje różne – test t może być nieodpowiedni\n")
    } else {
      cat("✅ Wariancje równe – test t odpowiedni\n")
    }
  }
  
  # 3. VIF (współliniowość AI i SUE)
  m2_vif <- lm(CAR_m1_1 ~ AI_Intensity + SUE, data = dane_reg)
  if (requireNamespace("car", quietly = TRUE)) {
    vif_vals <- car::vif(m2_vif)
    cat("\n--- VIF (współliniowość AI i SUE) ---\n")
    print(vif_vals)
    if (any(vif_vals > 5)) cat("⚠️ Współliniowość między zmiennymi\n") else cat("✅ Brak istotnej współliniowości\n")
  }
  
  # 4. Test Breuscha-Pagana 
  bp_test <- lmtest::bptest(m2_vif)
  cat("\n--- Test Breuscha-Pagana (heteroskedastyczność) ---\n")
  print(bp_test)
  if (bp_test$p.value < 0.05) cat("✅ Heteroskedastyczność – uzasadnienie dla HC3\n")
  
  
  cat("\n", strrep("=", 70), "\n")
  cat("ROZSZERZONE MODELE REGRESYJNE H4 (z kontrolami i FE)\n")
  cat(strrep("=", 70), "\n")
  
  # ===== MODEL 1: samo AI =====
  cat("\n--- MODEL 1: CAR ~ AI (HC3) ---\n")
  m1_lin <- lm(CAR_m1_1 ~ AI_Intensity, data = dane_reg)
  m1_bin <- lm(CAR_m1_1 ~ AI_HIGH, data = dane_reg)
  
  cr2_m1_lin <- lmtest::coeftest(m1_lin, vcov = sandwich::vcovHC(m1_lin, type = "HC3"))
  cr2_m1_bin <- lmtest::coeftest(m1_bin, vcov = sandwich::vcovHC(m1_bin, type = "HC3"))
  
  cat("Zmienna ciągła (HC3):\n")
  print(cr2_m1_lin["AI_Intensity", , drop = FALSE])
  
  cat("Zmienna binarna (HIGH vs LOW) (HC3):\n")
  print(cr2_m1_bin["AI_HIGH", , drop = FALSE])
  
  # ===== MODEL 2: AI + SUE =====
  cat("\n--- MODEL 2: CAR ~ AI + SUE (HC3) ---\n")
  m2_lin <- lm(CAR_m1_1 ~ AI_Intensity + SUE, data = dane_reg)
  m2_bin <- lm(CAR_m1_1 ~ AI_HIGH + SUE, data = dane_reg)
  
  cr2_m2_lin <- lmtest::coeftest(m2_lin, vcov = sandwich::vcovHC(m2_lin, type = "HC3"))
  cr2_m2_bin <- lmtest::coeftest(m2_bin, vcov = sandwich::vcovHC(m2_bin, type = "HC3"))
  
  cat("Zmienna ciągła + SUE (HC3):\n")
  print(cr2_m2_lin[c("AI_Intensity", "SUE"), ])
  
  cat("Zmienna binarna + SUE (HC3):\n")
  print(cr2_m2_bin[c("AI_HIGH", "SUE"), ])
  
  # ===== MODEL 3: AI + SUE + FE (firma + rok) z CR2 =====
  cat("\n--- MODEL 3: CAR ~ AI + SUE + FE(firma, rok) + CR2 ---\n")
  
  m3_lin <- lm(CAR_m1_1 ~ AI_Intensity + SUE + firm_id + year_id, data = dane_reg)
  m3_bin <- lm(CAR_m1_1 ~ AI_HIGH      + SUE + firm_id + year_id, data = dane_reg)
  
  if (requireNamespace("clubSandwich", quietly = TRUE)) {
  
    cr2_m3_lin <- clubSandwich::coef_test(m3_lin, vcov = "CR2", cluster = dane_reg$firm_id)
    cr2_m3_bin <- clubSandwich::coef_test(m3_bin, vcov = "CR2", cluster = dane_reg$firm_id)
  
    cat("Zmienna ciągła + FE (CR2):\n")
    df_cr2_lin <- as.data.frame(cr2_m3_lin)
    print(df_cr2_lin[rownames(df_cr2_lin) %in% c("AI_Intensity", "SUE"), c("beta", "SE", "p_Satt")])
  
    cat("Zmienna binarna + FE (CR2):\n")
    df_cr2_bin <- as.data.frame(cr2_m3_bin)
    print(df_cr2_bin[rownames(df_cr2_bin) %in% c("AI_HIGH", "SUE"), c("beta", "SE", "p_Satt")])
  
    # ===== PODSUMOWANIE MODELI – WSPÓŁCZYNNIK DLA AI =====
    cat("\n", strrep("=", 70), "\n")
    cat("PODSUMOWANIE MODELI – WSPÓŁCZYNNIK DLA AI\n")
    cat(strrep("=", 70), "\n")
  
    get_coef_hc3 <- function(obj, var_name) {
      if (var_name %in% rownames(obj)) {
        list(beta = round(obj[var_name, "Estimate"], 5),
             p    = round(obj[var_name, "Pr(>|t|)"], 4))
      } else list(beta = NA, p = NA)
    }
  
    get_coef_cr2 <- function(obj, var_name) {
      if (var_name %in% rownames(obj)) {
        list(beta = round(obj[var_name, "beta"], 5),
             p    = round(obj[var_name, "p_Satt"], 4))
      } else list(beta = NA, p = NA)
    }
  
    c1_lin <- get_coef_hc3(cr2_m1_lin, "AI_Intensity")
    c1_bin <- get_coef_hc3(cr2_m1_bin, "AI_HIGH")
    c2_lin <- get_coef_hc3(cr2_m2_lin, "AI_Intensity")
    c2_bin <- get_coef_hc3(cr2_m2_bin, "AI_HIGH")
    c3_lin <- get_coef_cr2(cr2_m3_lin, "AI_Intensity")
    c3_bin <- get_coef_cr2(cr2_m3_bin, "AI_HIGH")
  
    summary_h4 <- data.frame(
      Model = c("M1: Samo AI (ciągłe)", "M1: Samo AI (binarne)",
                "M2: + SUE (ciągłe)", "M2: + SUE (binarne)",
                "M3: + FE (ciągłe, CR2)", "M3: + FE (binarne, CR2)"),
      Wspolczynnik = round(c(c1_lin$beta, c1_bin$beta, c2_lin$beta, c2_bin$beta, c3_lin$beta, c3_bin$beta), 5),
      P_value      = round(c(c1_lin$p, c1_bin$p, c2_lin$p, c2_bin$p, c3_lin$p, c3_bin$p), 4)
    )
  
    summary_h4$Istotne <- ifelse(summary_h4$P_value < 0.05, "✅", "❌")
    print(summary_h4)
  
    if (any(summary_h4$P_value < 0.05, na.rm = TRUE)) {
      cat("\n✅ β1 JEST ISTOTNE w co najmniej jednym modelu – rynek reaguje na AI\n")
    } else {
      cat("\n❌ β1 NIE JEST ISTOTNE w żadnym modelu – brak dowodu na reakcję rynku na AI\n")
    }
  }
  
  
  # ============================================================
  # MIARY DOPASOWANIA MODELI H4
  # ============================================================
  
  cat("\n", strrep("=", 70), "\n")
  cat("MIARY DOPASOWANIA MODELI H4\n")
  cat(strrep("=", 70), "\n")
  
  get_fit_stats <- function(model, label) {
  s <- summary(model)
  f <- s$fstatistic

  data.frame(
    Model   = label,
    R2      = round(s$r.squared, 4),
    Adj_R2  = round(s$adj.r.squared, 4),
    F_stat  = if (!is.null(f)) round(unname(f[1]), 2) else NA,
    p_value = if (!is.null(f)) round(unname(pf(f[1], f[2], f[3], lower.tail = FALSE)), 4) else NA,
    N       = nobs(model)
  )
}

  fit_summary <- rbind(
  get_fit_stats(m1_lin, "M1: CAR ~ AI (HC3)"),
  get_fit_stats(m2_lin, "M2: CAR ~ AI + SUE (HC3)"),
  get_fit_stats(m3_lin, "M3: CAR ~ AI + SUE + FE (CR2)")
)

  print(fit_summary, row.names = FALSE)

  cat("\nLiczba klastrów (spółek) w M3:", length(unique(dane_reg$firm_id)), "\n")
  
  
  # ============================================================
  # TEST ŁĄCZNEJ ISTOTNOŚCI EFEKTÓW STAŁYCH (M3)
  # ============================================================
  
  cat("\n--- Test łącznej istotności efektów stałych (M3) ---\n")
  
  if (requireNamespace("car", quietly = TRUE)) {
  
    coef_names <- names(coef(m3_lin))
    firm_coefs <- coef_names[grepl("^firm_id", coef_names)]
    year_coefs <- coef_names[grepl("^year_id", coef_names)]
  
    if (length(firm_coefs) > 0) {
      cat("\nEfekty firmy:\n")
      print(car::linearHypothesis(m3_lin, paste0(firm_coefs, " = 0")))
    }
  
    if (length(year_coefs) > 0) {
      cat("\nEfekty roku:\n")
      print(car::linearHypothesis(m3_lin, paste0(year_coefs, " = 0")))
    }
  
    if (length(firm_coefs) > 0 && length(year_coefs) > 0) {
      cat("\nEfekty firmy + roku łącznie:\n")
      print(car::linearHypothesis(m3_lin, paste0(c(firm_coefs, year_coefs), " = 0")))
    }
  }
    
    # ============================================================
    # TEST CORRADO
    # ============================================================
    cat("\n", strrep("=", 70), "\n")
    cat("TEST CORRADO\n")
    cat(strrep("=", 70), "\n")
    
    corrado_test_proper <- function(event_dates, firms, 
                                    est_window = 120,
                                    ev_start = -1, ev_end = 1,
                                    buffer = 10) {
      
      n <- length(event_dates)
      Z_avg <- NA
      p_avg <- NA
      
      if (n < 5) return(list(day_results = NA, Z_sum = NA, p_sum = NA, n = n))
      
      ev_days <- ev_start:ev_end
      n_ev <- length(ev_days)
      
      all_ar <- matrix(NA, nrow = n, ncol = est_window + n_ev)
      colnames(all_ar) <- c(paste0("est_", 1:est_window), paste0("ev_", ev_days))
      
      for (i in 1:n) {
        event_date <- event_dates[i]
        firm <- firms[i]
        
        idx_pub <- which(prices_wide$data >= event_date)
        if (length(idx_pub) == 0) next
        idx_pub <- min(idx_pub)
        if (abs(prices_wide$data[idx_pub] - event_date) > 3) next
        
        event_idx <- idx_pub + 1
        if (event_idx < 2 || event_idx > nrow(prices_wide)) next
        
          est_start <- event_idx - est_window - buffer 
          est_end <- event_idx - 1 - buffer  
        if (est_start < 2) next
        
        est_returns <- data.frame(
          firm = diff(log(prices_wide[[firm]][(est_start-1):est_end])),
          market = diff(log(prices_wide$SPX[(est_start-1):est_end]))
        )
        est_returns <- est_returns[!is.na(est_returns$firm) & !is.na(est_returns$market), ]
        if (nrow(est_returns) < 10) next
        
        model <- lm(firm ~ market, data = est_returns)
        alpha <- coef(model)[1]
        beta <- coef(model)[2]
        
        for (d in 1:est_window) {
          day_idx <- est_start + d - 1
          if (day_idx < 2 || day_idx > nrow(prices_wide)) next
          firm_ret <- log(prices_wide[[firm]][day_idx] / prices_wide[[firm]][day_idx - 1])
          market_ret <- log(prices_wide$SPX[day_idx] / prices_wide$SPX[day_idx - 1])
          if (!is.na(firm_ret) && !is.na(market_ret)) {
            all_ar[i, paste0("est_", d)] <- firm_ret - (alpha + beta * market_ret)
          }
        }
        
        for (j in 1:n_ev) {
          d <- ev_days[j]
          day_idx <- event_idx + d
          if (day_idx < 2 || day_idx > nrow(prices_wide)) next
          firm_ret <- log(prices_wide[[firm]][day_idx] / prices_wide[[firm]][day_idx - 1])
          market_ret <- log(prices_wide$SPX[day_idx] / prices_wide$SPX[day_idx - 1])
          if (!is.na(firm_ret) && !is.na(market_ret)) {
            all_ar[i, paste0("ev_", d)] <- firm_ret - (alpha + beta * market_ret)
          }
        }
      }
      
      results <- data.frame(Dzien = ev_days, Z = NA, p = NA, N = NA)
      K_matrix <- matrix(NA, nrow = n, ncol = n_ev)
      
      for (j in 1:n_ev) {
        day_col <- paste0("ev_", ev_days[j])
        valid_rows <- which(!is.na(all_ar[, day_col]))
        
        if (length(valid_rows) < 5) next
        
        K_vals <- numeric(length(valid_rows))
        
        for (k in 1:length(valid_rows)) {
          i <- valid_rows[k]
          est_cols <- grep("^est_", colnames(all_ar), value = TRUE)
          est_ars <- all_ar[i, est_cols]
          est_ars <- est_ars[!is.na(est_ars)]
          
          if (length(est_ars) < 10) {
            K_vals[k] <- NA
            next
          }
          
          ar_t <- all_ar[i, day_col]
          all_ars <- c(est_ars, ar_t)
          T_total <- length(all_ars)
          rank_t <- rank(all_ars, na.last = "keep")[T_total]
          K_vals[k] <- (rank_t - (T_total + 1) / 2) / sqrt(((T_total - 1) * (T_total + 1)) / 12)
          K_matrix[i, j] <- K_vals[k]
        }
        
        K_vals <- K_vals[!is.na(K_vals)]
        if (length(K_vals) >= 5) {
          L_t <- mean(K_vals)
          Z_t <- L_t * sqrt(length(K_vals))
          p_t <- 2 * (1 - pnorm(abs(Z_t)))
          results[j, "Z"] <- round(Z_t, 4)
          results[j, "p"] <- round(p_t, 4)
          results[j, "N"] <- length(K_vals)
        }
      }
      
      cat("\n--- Wyniki dla poszczególnych dni ---\n")
      print(results)
      
      cat("\n--- Test łączny dla całego okna ---\n")
      K_sum <- apply(K_matrix, 1, function(row) {
        if (all(is.na(row))) return(NA)
        row_clean <- row[!is.na(row)]
        if (length(row_clean) == 0) return(NA)
        return(mean(row_clean))
      })
      
      K_sum <- K_sum[!is.na(K_sum)]
      
      if (length(K_sum) >= 5) {
        L_avg <- mean(K_sum)
        Z_avg <- L_avg * sqrt(length(K_sum))
        p_avg <- 2 * (1 - pnorm(abs(Z_avg)))
        cat(sprintf("Z = %.4f, p = %.4f, n = %d\n", Z_avg, p_avg, length(K_sum)))
        if (p_avg < 0.05) cat("✅ Istotne\n") else cat("❌ Nieistotne\n")
      } else {
        cat("Za mało obserwacji do testu łącznego\n")
      }
      
      return(list(day_results = results, Z_sum = Z_avg, p_sum = p_avg))
    }
    
    for(doc_type in c("10-K", "10-Q", "Earnings Call")) {
      cat(sprintf("\n=== %s ===\n", doc_type))
      
      df_doc <- df_all %>% 
        filter(typ == doc_type,
               year_calendar %in% c("2022", "2023", "2024", "2025"),
               !is.na(event_date), !is.na(spolka))
      
      if (nrow(df_doc) >= 10) {
        corrado_test_proper(
          event_dates = df_doc$event_date,
          firms = df_doc$spolka,
          est_window = 120,
          ev_start = -1,
          ev_end = 1
        )
      } else {
        cat(sprintf("Za mało obserwacji: n = %d\n", nrow(df_doc)))
      }
    }
  
  # ===== URUCHOMIENIE ALTERNATYWNYCH TESTÓW =====
  alt_test_results <- run_alternative_tests(df_all)
  assign("df_all", df_all, envir = .GlobalEnv)
  summary_h4 <<- summary_h4
  alt_test_results <<- alt_test_results
  prices_wide <<- prices_wide
  return(list(events_all = df_all, alt_tests = alt_test_results))
}

# =====================================================================
# 10. FUNKCJA GŁÓWNA
# =====================================================================

main <- function() {
  cat("\n")
  cat("████████████████████████████████████████████████████████████████████\n")
  cat("██     Analiza ujawnień AI w raportach 10-K, 10-Q, EC        ██\n")
  cat("████████████████████████████████████████████████████████████████████\n")
  
  
  # ===== I. =====
  results_10k <- analyze_10k_full(folder_10k)
  
  # ===== II. =====
  if (!is.null(results_10k)) {
    narrative_results <- analyze_narrative_sections(folder_narrative, results_10k)
  }
  
  # ===== III. =====
  results_10q_obj <- analyze_10q_full(folder_10q)
  if (!is.null(results_10q_obj)) {
    results_10q_raw <- results_10q_obj$raw
    results_10q_annual <- results_10q_obj$annual
  } else {
    results_10q_raw <- NULL
    results_10q_annual <- NULL
  }
  
  # ===== IV. =====
  results_ec <- analyze_earnings_calls_full(folder_ec, results_10k, results_10q_annual)
  
  # ===== V. =====
  if (!is.null(results_10k)) {
    rd_capex_results <- analyze_rd_capex_full(results_10k, results_ec)
  }
  
  # ===== VI. =====
  if (!is.null(results_10k) && !is.null(results_ec)) {
    qualitative_results <- qualitative_summary_full(results_10k, results_ec)
  }
  
  # ===== VII. =====
  if (!is.null(results_10k) && !is.null(results_10q_raw) && !is.null(results_ec)) {
    event_results <- analyze_event_study(folder_prices, ALL_AI_TERMS_SORTED)
  }
  
  # ===== PODSUMOWANIE KOŃCOWE =====
  cat("\n", strrep("=", 70), "\n")
  cat("WSZYSTKIE ANALIZY ZAKOŃCZONE POMYŚLNIE!\n")
  cat(strrep("=", 70), "\n")
  
  assign("results_10k", results_10k, envir = .GlobalEnv)
  if (exists("results_10q_annual")) assign("results_10q_annual", results_10q_annual, envir = .GlobalEnv)
  if (exists("results_10q_raw")) assign("results_10q_raw", results_10q_raw, envir = .GlobalEnv)
  assign("results_ec", results_ec, envir = .GlobalEnv)
  if (exists("narrative_results")) assign("narrative_results", narrative_results, envir = .GlobalEnv)
  if (exists("rd_capex_results")) assign("rd_capex_results", rd_capex_results, envir = .GlobalEnv)
  if (exists("qualitative_results")) assign("qualitative_results", qualitative_results, envir = .GlobalEnv)
  if (exists("event_results")) assign("event_results", event_results, envir = .GlobalEnv)
  

  save(
    results_10k,
    results_10q_raw,
    results_10q_annual,
    results_ec,
    narrative_results,
    rd_capex_results,
    qualitative_results,
    event_results,
    fe_capex, fe_rd, fe_full,          
    summary_h4, alt_test_results,      
    file = "wyniki_analizy.RData"
  )

}

# URUCHOMIENIE CAŁOŚCI
main()
Konsola serwera
Konsola gotowa.

Czym jest ten panel?

Środowisko badawcze AiDisclosures.pl to interfejs umożliwiający zdalne uruchomienie analizy ujawnień dotyczącej sztucznej inteligencji w raportach spółek z grupy GAMAM (Alphabet, Amazon, Meta, Apple, Microsoft) bezpośrednio z poziomu przeglądarki.

Jak uruchomić badanie?

Cała analiza wykonywana jest na serwerze wyposażonym w środowisko R. Nie jest wymagana instalacja żadnego oprogramowania na komputerze użytkownika – wystarczy przeglądarka internetowa. Po kliknięciu przycisku URUCHOM BADANIE skrypt zaczyna działać na serwerze, a wyniki na bieżąco pojawiają się w konsoli.

Co dokładnie analizuje skrypt?

Skrypt przetwarza dokumentację źródłową (raporty 10-K, 10-Q, transkrypcje telekonferencji wynikowych (EC) oraz sekcje Business/Risk Factors/MD&A z raportów 10-K), wyszukuje w niej fragmenty dotyczące sztucznej inteligencji, a następnie wykonuje obliczenia wykorzystane w pracy magisterskiej.

Ile trwa badanie i na co zwrócić uwagę?

Pełne wykonanie skryptu może trwać do kilkudziesięciu minut. Proces działa na serwerze niezależnie od sesji użytkownika, zamknięcie karty uniemożliwia wyłącznie obserwację postępu. Kolejne uruchomienie jest możliwe dopiero po zakończeniu poprzedniego.

Co oznaczają kolory w dokumentacji źródłowej?

W podglądzie dokumentacji źródłowej fragmenty tekstu oznaczone są kolorami: żółte podświetlenie oznacza słowa dotyczące sztucznej inteligencji, a różowe podświetlenie oznacza słowa z orientacją przyszłościową lub odniesieniem do ryzyk w zdaniach wzmiankujących o sztucznej inteligencji.

Wer. 1.27 | Ost. akt.: 03-09-2026